@rel-packages/osu-beatmap-parser 1.0.6 → 1.1.2

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 CHANGED
@@ -1,21 +1,11 @@
1
1
  ## osu-beatmap-parser
2
-
3
- .osu parser for nodejs used by [osu-stuff](https://github.com/mezleca/osu-stuff)
2
+ native .osu beatmap parser used on [osu-stuff](https://github.com/mezleca/osu-stuff)
4
3
 
5
4
  ## installation
6
5
 
7
6
  ```bash
8
- npm install osu-beatmap-parser
9
- ```
10
-
11
- ## development
12
-
13
- ```bash
14
- npm install
15
- npm run compile
7
+ npm install @rel-packages/osu-beatmap-parser
16
8
  ```
17
9
 
18
- ## TODO
19
- - [ ] native: handle "Storyboard" key
20
- - [ ] native: handle beatmap file version
21
- - [ ] native: handle lazer files (like, if we're trying to get AudioLocation from a lazer file, we will need to follow the hashed lazer path)
10
+ ## usage
11
+ check [examples](https://github.com/mezleca/osu-beatmap-parser/tree/main/examples) for wasm / nodejs usage examples.
package/dist/index.d.ts CHANGED
@@ -1,4 +1,7 @@
1
- import { OsuKey, OsuInput } from "./types";
1
+ import { OsuKey, OsuInput, OsuFileFormat } from "./types/types";
2
2
  export declare const get_property: (data: Uint8Array, key: OsuKey) => string;
3
3
  export declare const get_properties: (input: Uint8Array | OsuInput, keys: OsuKey[]) => Record<string, string>;
4
- export { OsuKey, OsuInput };
4
+ export declare const get_section: (data: Uint8Array, section: string) => string[];
5
+ export declare const parse: (input: Uint8Array | OsuInput) => OsuFileFormat;
6
+ export type { OsuKey, OsuInput, OsuFileFormat };
7
+ export * from "./types/types";
package/dist/index.js CHANGED
@@ -1,6 +1,20 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
2
16
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.get_properties = exports.get_property = void 0;
17
+ exports.parse = exports.get_section = exports.get_properties = exports.get_property = void 0;
4
18
  const bindings_1 = require("./lib/bindings");
5
19
  const get_property = (data, key) => {
6
20
  return bindings_1.native.get_property(data, key);
@@ -15,3 +29,13 @@ const get_properties = (input, keys) => {
15
29
  return result;
16
30
  };
17
31
  exports.get_properties = get_properties;
32
+ const get_section = (data, section) => {
33
+ return bindings_1.native.get_section(data, section);
34
+ };
35
+ exports.get_section = get_section;
36
+ const parse = (input) => {
37
+ const data = input instanceof Uint8Array ? input : input.data;
38
+ return bindings_1.native.parse(data);
39
+ };
40
+ exports.parse = parse;
41
+ __exportStar(require("./types/types"), exports);
@@ -1 +1,3 @@
1
- export declare const native: any;
1
+ import { INativeExporter } from "../types/types";
2
+ declare const native: INativeExporter;
3
+ export { native };
@@ -1,45 +1,10 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.native = void 0;
4
- const DEBUG = typeof process != "undefined" && process.env?.OSU_PARSER_DEBUG == "1";
5
- const log_debug = (...args) => {
6
- if (DEBUG) {
7
- console.log("[osu-beatmap-parser]", ...args);
8
- }
9
- };
10
- const load_native_module = () => {
11
- const fs = require("fs");
12
- const path = require("path");
13
- const platform = process.platform;
14
- const arch = process.arch;
15
- log_debug(`loading native module for ${platform}-${arch}`);
16
- log_debug(`__dirname: ${__dirname}`);
17
- const paths = [
18
- // prebuilt binaries
19
- path.join(__dirname, "..", "..", "prebuilds", `${platform}-${arch}`, "osu-beatmap-parser.node"),
20
- path.join(__dirname, "..", "prebuilds", `${platform}-${arch}`, "osu-beatmap-parser.node"),
21
- // local dev builds
22
- path.join(__dirname, "..", "..", "build", "osu-beatmap-parser.node"),
23
- path.join(__dirname, "..", "..", "build", "Release", "osu-beatmap-parser.node"),
24
- path.join(__dirname, "..", "build", "osu-beatmap-parser.node"),
25
- path.join(__dirname, "build", "osu-beatmap-parser.node"),
26
- ];
27
- for (const p of paths) {
28
- const resolved = path.resolve(p);
29
- const exists = fs.existsSync(resolved);
30
- log_debug(`checking: ${resolved} -> ${exists ? "found" : "not found"}`);
31
- if (exists) {
32
- log_debug(`loading native module from: ${resolved}`);
33
- return require(resolved);
34
- }
35
- }
36
- log_debug("no native module found in any path");
37
- return null;
38
- };
39
- exports.native = load_native_module();
40
- if (exports.native == null) {
41
- const platform = process.platform;
42
- const arch = process.arch;
43
- throw new Error(`failed to load native module for ${platform}-${arch}. ` +
44
- `Set OSU_PARSER_DEBUG=1 for more info.`);
45
- }
7
+ const node_gyp_build_1 = __importDefault(require("node-gyp-build"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const native = (0, node_gyp_build_1.default)(path_1.default.join(__dirname, "..", ".."));
10
+ exports.native = native;
@@ -1,3 +1,6 @@
1
+ import type { OsuFileFormat } from "../types/types";
1
2
  export declare const init_wasm: () => Promise<void>;
2
3
  export declare const get_property: (data: Uint8Array, key: string) => string;
3
4
  export declare const get_properties: (data: Uint8Array, keys: string[]) => Record<string, string>;
5
+ export declare const get_section: (data: Uint8Array, section: string) => string[];
6
+ export declare const parse: (data: Uint8Array) => OsuFileFormat;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.get_properties = exports.get_property = exports.init_wasm = void 0;
3
+ exports.parse = exports.get_section = exports.get_properties = exports.get_property = exports.init_wasm = void 0;
4
4
  console.log("[parser] wrapper loaded");
5
5
  let wasm_instance = null;
6
6
  let init_promise = null;
@@ -54,11 +54,39 @@ const get_properties = (data, keys) => {
54
54
  }
55
55
  };
56
56
  exports.get_properties = get_properties;
57
+ const get_section = (data, section) => {
58
+ if (wasm_instance == null)
59
+ throw new Error("wasm not initialized");
60
+ const buffer_ptr = wasm_instance._malloc(data.length);
61
+ wasm_instance.HEAPU8.set(data, buffer_ptr);
62
+ try {
63
+ return wasm_instance.get_section(buffer_ptr, data.length, section);
64
+ }
65
+ finally {
66
+ wasm_instance._free(buffer_ptr);
67
+ }
68
+ };
69
+ exports.get_section = get_section;
70
+ const parse = (data) => {
71
+ if (wasm_instance == null)
72
+ throw new Error("wasm not initialized");
73
+ const buffer_ptr = wasm_instance._malloc(data.length);
74
+ wasm_instance.HEAPU8.set(data, buffer_ptr);
75
+ try {
76
+ return wasm_instance.parse(buffer_ptr, data.length);
77
+ }
78
+ finally {
79
+ wasm_instance._free(buffer_ptr);
80
+ }
81
+ };
82
+ exports.parse = parse;
57
83
  if (typeof window != "undefined") {
58
84
  window.beatmap_parser = {
59
85
  init_wasm: exports.init_wasm,
60
86
  get_property: exports.get_property,
61
87
  get_properties: exports.get_properties,
88
+ get_section: exports.get_section,
89
+ parse: exports.parse,
62
90
  };
63
91
  console.log(window.beatmap_parser);
64
92
  console.log("[parser] attached to window");
@@ -0,0 +1,135 @@
1
+ export type OsuKey = "AudioFilename" | "AudioLeadIn" | "AudioHash" | "PreviewTime" | "Countdown" | "SampleSet" | "StackLeniency" | "Mode" | "LetterboxInBreaks" | "StoryFireInFront" | "UseSkinSprites" | "AlwaysShowPlayfield" | "OverlayPosition" | "SkinPreference" | "EpilepsyWarning" | "CountdownOffset" | "SpecialStyle" | "WidescreenStoryboard" | "SamplesMatchPlaybackRate" | "Bookmarks" | "DistanceSpacing" | "BeatDivisor" | "GridSize" | "TimelineZoom" | "Title" | "TitleUnicode" | "Artist" | "ArtistUnicode" | "Creator" | "Version" | "Source" | "Tags" | "BeatmapID" | "BeatmapSetID" | "HPDrainRate" | "CircleSize" | "OverallDifficulty" | "ApproachRate" | "SliderMultiplier" | "SliderTickRate" | "Background" | "Video" | "Storyboard";
2
+ export interface OsuInput {
3
+ data: Uint8Array;
4
+ id?: string;
5
+ }
6
+ export interface GeneralSection {
7
+ AudioFilename: string;
8
+ AudioLeadIn: number;
9
+ AudioHash: string;
10
+ PreviewTime: number;
11
+ Countdown: number;
12
+ SampleSet: string;
13
+ StackLeniency: number;
14
+ Mode: number;
15
+ LetterboxInBreaks: number;
16
+ StoryFireInFront: number;
17
+ UseSkinSprites: number;
18
+ AlwaysShowPlayfield: number;
19
+ OverlayPosition: string;
20
+ SkinPreference: string;
21
+ EpilepsyWarning: number;
22
+ CountdownOffset: number;
23
+ SpecialStyle: number;
24
+ WidescreenStoryboard: number;
25
+ SamplesMatchPlaybackRate: number;
26
+ }
27
+ export interface EditorSection {
28
+ Bookmarks: number[];
29
+ DistanceSpacing: number;
30
+ BeatDivisor: number;
31
+ GridSize: number;
32
+ TimelineZoom: number;
33
+ }
34
+ export interface MetadataSection {
35
+ Title: string;
36
+ TitleUnicode: string;
37
+ Artist: string;
38
+ ArtistUnicode: string;
39
+ Creator: string;
40
+ Version: string;
41
+ Source: string;
42
+ Tags: string;
43
+ BeatmapID: number;
44
+ BeatmapSetID: number;
45
+ }
46
+ export interface DifficultySection {
47
+ HPDrainRate: number;
48
+ CircleSize: number;
49
+ OverallDifficulty: number;
50
+ ApproachRate: number;
51
+ SliderMultiplier: number;
52
+ SliderTickRate: number;
53
+ }
54
+ export interface EventBackground {
55
+ filename: string;
56
+ xOffset: number;
57
+ yOffset: number;
58
+ }
59
+ export interface EventVideo {
60
+ filename: string;
61
+ startTime: number;
62
+ xOffset: number;
63
+ yOffset: number;
64
+ }
65
+ export interface EventBreak {
66
+ startTime: number;
67
+ endTime: number;
68
+ }
69
+ export interface EventsSection {
70
+ background: EventBackground | null;
71
+ video: EventVideo | null;
72
+ breaks: EventBreak[];
73
+ }
74
+ export interface TimingPoint {
75
+ time: number;
76
+ beatLength: number;
77
+ meter: number;
78
+ sampleSet: number;
79
+ sampleIndex: number;
80
+ volume: number;
81
+ uninherited: number;
82
+ effects: number;
83
+ }
84
+ export interface ColourSection {
85
+ Combos: [number, number, number][];
86
+ SliderTrackOverride: [number, number, number] | null;
87
+ SliderBorder: [number, number, number] | null;
88
+ }
89
+ export interface HitSample {
90
+ normalSet: number;
91
+ additionSet: number;
92
+ index: number;
93
+ volume: number;
94
+ filename: string;
95
+ }
96
+ export interface CurvePoint {
97
+ x: number;
98
+ y: number;
99
+ }
100
+ export interface EdgeSet {
101
+ normalSet: number;
102
+ additionSet: number;
103
+ }
104
+ export interface HitObject {
105
+ x: number;
106
+ y: number;
107
+ time: number;
108
+ type: number;
109
+ hitSound: number;
110
+ hitSample: HitSample;
111
+ curveType: string;
112
+ curvePoints: CurvePoint[];
113
+ slides: number;
114
+ length: number;
115
+ edgeSounds: number[];
116
+ edgeSets: EdgeSet[];
117
+ endTime: number;
118
+ }
119
+ export interface OsuFileFormat {
120
+ version: number;
121
+ General: GeneralSection;
122
+ Editor: EditorSection;
123
+ Metadata: MetadataSection;
124
+ Difficulty: DifficultySection;
125
+ Events: EventsSection;
126
+ TimingPoints: TimingPoint[];
127
+ Colours: ColourSection;
128
+ HitObjects: HitObject[];
129
+ }
130
+ export interface INativeExporter {
131
+ get_property(data: Uint8Array, key: string): string;
132
+ get_properties(data: Uint8Array, keys: string[]): Record<string, string>;
133
+ get_section(data: Uint8Array, section: string): string[];
134
+ parse(data: Uint8Array): OsuFileFormat;
135
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rel-packages/osu-beatmap-parser",
3
- "version": "1.0.6",
3
+ "version": "1.1.2",
4
4
  "description": ".osu parser for nodejs",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -15,7 +15,7 @@
15
15
  "compile:tsc": "tsc",
16
16
  "build": "tsx scripts/build.ts all && npm run compile:tsc",
17
17
  "example:wasm": "bun run compile:wasm && bun x http-server . -p 8080 -c-1 -o /examples/wasm/",
18
- "example:node": "bun run compile:node && bun run examples/node/index.ts"
18
+ "example:node": "bun run compile:native && bun run examples/node/index.ts"
19
19
  },
20
20
  "keywords": [
21
21
  "osu",
@@ -42,6 +42,8 @@
42
42
  "tsx": "^4.21.0",
43
43
  "typescript": "^5.9.3"
44
44
  },
45
- "dependencies": {},
45
+ "dependencies": {
46
+ "node-gyp-build": "^4.8.4"
47
+ },
46
48
  "optionalDependencies": {}
47
49
  }
package/dist/types.d.ts DELETED
@@ -1,9 +0,0 @@
1
- export type OsuKey = "AudioFilename" | "AudioLeadIn" | "PreviewTime" | "Countdown" | "SampleSet" | "StackLeniency" | "Mode" | "LetterboxInBreaks" | "WidescreenStoryboard" | "Bookmarks" | "DistanceSpacing" | "BeatDivisor" | "GridSize" | "TimelineZoom" | "Title" | "TitleUnicode" | "Artist" | "ArtistUnicode" | "Creator" | "Version" | "Source" | "Tags" | "BeatmapID" | "BeatmapSetID" | "HPDrainRate" | "CircleSize" | "OverallDifficulty" | "ApproachRate" | "SliderMultiplier" | "SliderTickRate" | "Background" | "Video" | "Storyboard" | "Duration";
2
- export interface OsuInput {
3
- data: Uint8Array;
4
- id?: string;
5
- }
6
- export interface INativeExporter {
7
- get_property(data: Uint8Array, key: string): string;
8
- get_properties(data: Uint8Array, keys: string[]): Record<string, string>;
9
- }
File without changes