adofai 2.9.7

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/.babelrc ADDED
@@ -0,0 +1,5 @@
1
+ {
2
+ "presets": [
3
+ "@babel/preset-env"
4
+ ]
5
+ }
package/index.ts ADDED
@@ -0,0 +1,12 @@
1
+ import pathData from './src/pathdata'
2
+ import * as Parsers from './src/parser'
3
+ import Level,* as Structure from './src/structure'
4
+ import * as Presets from './src/presets'
5
+
6
+ export {
7
+ pathData,
8
+ Parsers,
9
+ Level,
10
+ Structure,
11
+ Presets
12
+ }
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "adofai",
3
+ "version": "2.9.7",
4
+ "main": "index.js",
5
+ "scripts": {
6
+ "build": "webpack",
7
+ "tsc": "tsc",
8
+ "dev": "webpack --mode=development"
9
+ },
10
+ "keywords": ["adofai", "adofai-js", "adofai-ts", "adofai-ts-lib"],
11
+ "author": "Xbodwf",
12
+ "license": "BSD-3-Clause",
13
+ "homepage": "https://xbodwf.github.io/packages/adofai-js/",
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "https://github.com/Xbodwf/ADOFAI-JS.git"
17
+ },
18
+ "bugs": "https://github.com/Xbodwf/ADOFAI-JS/issues",
19
+ "description": "A Javascript library for ADOFAI levels.",
20
+ "devDependencies": {
21
+ "@babel/core": "^7.27.1",
22
+ "@babel/preset-env": "^7.27.2",
23
+ "@types/node": "^20.11.0",
24
+ "babel-loader": "^10.0.0",
25
+ "install": "^0.13.0",
26
+ "ts-loader": "^9.5.1",
27
+ "typescript": "^5.3.3",
28
+ "webpack": "^5.99.9",
29
+ "webpack-cli": "^6.0.1"
30
+ }
31
+ }
@@ -0,0 +1,82 @@
1
+ import * as presets from './presets'
2
+
3
+ interface Tile {
4
+ addDecorations?: any[];
5
+ actions?: Action[];
6
+ [key: string]: any;
7
+ }
8
+
9
+ interface Action {
10
+ eventType: string;
11
+ [key: string]: any;
12
+ }
13
+
14
+ /**
15
+ * @param {Array} tiles ADOFAI Tiles from ADOFAI.Level
16
+ * @returns {Array} new Tiles
17
+ */
18
+ function clearDecorations(tiles: Tile[]): Tile[] {
19
+ if (!Array.isArray(tiles)) {
20
+ throw new Error('Arguments are not supported.');
21
+ }
22
+
23
+ return tiles.map(tile => {
24
+ const newTile = { ...tile };
25
+
26
+ if (newTile.hasOwnProperty('addDecorations')) {
27
+ newTile.addDecorations = [];
28
+ }
29
+
30
+ if (Array.isArray(newTile.actions)) {
31
+ newTile.actions = newTile.actions.filter(action =>
32
+ !presets.preset_inner_no_deco.events.includes(action.eventType)
33
+ );
34
+ }
35
+
36
+ return newTile;
37
+ });
38
+ }
39
+
40
+ /**
41
+ * @param {Array} eventTypes Eventlist to remove
42
+ * @param {Array} tiles ADOFAI Tiles from ADOFAI.Level
43
+ * @returns {Array} new Tiles
44
+ */
45
+ function clearEvents(eventTypes: string[], tiles: Tile[]): Tile[] {
46
+ return tiles.map(tile => {
47
+ const newTile = { ...tile };
48
+ if (Array.isArray(newTile.actions)) {
49
+ newTile.actions = newTile.actions.filter(action =>
50
+ !eventTypes.includes(action.eventType)
51
+ );
52
+ }
53
+
54
+ return newTile;
55
+ });
56
+ }
57
+
58
+ /**
59
+ * @param {Array} eventTypes Eventlist to keep
60
+ * @param {Array} tiles ADOFAI Tiles from ADOFAI.Level
61
+ * @returns {Array} new Tiles
62
+ */
63
+ function keepEvents(eventTypes: string[], tiles: Tile[]): Tile[] {
64
+ return tiles.map(tile => {
65
+ const newTile = { ...tile };
66
+ if (Array.isArray(newTile.actions)) {
67
+ newTile.actions = newTile.actions.filter(action =>
68
+ eventTypes.includes(action.eventType)
69
+ );
70
+ }
71
+
72
+ return newTile;
73
+ });
74
+ }
75
+
76
+
77
+ const effectProcessor = {
78
+ clearDecorations,
79
+ clearEvents,
80
+ keepEvents
81
+ }
82
+ export default effectProcessor;
package/src/format.ts ADDED
@@ -0,0 +1,69 @@
1
+ /**
2
+ * @param {object} obj - JSON Object
3
+ * @param {number} indent - No usage
4
+ * @param {boolean} isRoot - Is JSON the Root?
5
+ * @returns ADOFAI File Content or Object
6
+ */
7
+ function exportAsADOFAI(obj: any, indent: number = 0, isRoot: boolean = false): string {
8
+
9
+ if (typeof obj !== 'object' || obj === null) {
10
+ return JSON.stringify(obj);
11
+ }
12
+
13
+ if (Array.isArray(obj)) {
14
+ const allPrimitives = obj.every(item =>
15
+ typeof item !== 'object' || item === null
16
+ );
17
+
18
+ if (allPrimitives) {
19
+ return '[' + obj.map(item => exportAsADOFAI(item)).join(',') + ']';
20
+ }
21
+
22
+ const spaces = ' '.repeat(indent);
23
+ const arrayItems = obj.map(item =>
24
+ spaces + ' ' + formatAsSingleLine(item)
25
+ ).join(',\n');
26
+
27
+ return '[\n' + arrayItems + '\n' + spaces + ']';
28
+ }
29
+
30
+ const spaces = ' '.repeat(indent);
31
+ const keys = Object.keys(obj);
32
+
33
+ if (isRoot) {
34
+ const objectItems = keys.map(key =>
35
+ ' ' + JSON.stringify(key) + ': ' + exportAsADOFAI((obj as Record<string, any>)[key], 2)
36
+ ).join(',\n');
37
+
38
+ return '{\n' + objectItems + '\n}';
39
+ }
40
+
41
+ const objectItems = keys.map(key =>
42
+ spaces + ' ' + JSON.stringify(key) + ': ' + exportAsADOFAI((obj as Record<string, any>)[key], indent + 2)
43
+ ).join(',\n');
44
+
45
+ return '{\n' + objectItems + '\n' + spaces + '}';
46
+ }
47
+
48
+ /**
49
+ * @param {Array} obj Eventlist to keep
50
+ * @returns {string} JSON formated as singleline
51
+ */
52
+ function formatAsSingleLine(obj: any): string {
53
+ if (typeof obj !== 'object' || obj === null) {
54
+ return exportAsADOFAI(obj);
55
+ }
56
+
57
+ if (Array.isArray(obj)) {
58
+ return '[' + obj.map(formatAsSingleLine).join(',') + ']';
59
+ }
60
+
61
+ const keys = Object.keys(obj);
62
+ const entries = keys.map(key =>
63
+ JSON.stringify(key) + ': ' + formatAsSingleLine((obj as Record<string, any>)[key])
64
+ ).join(', ');
65
+
66
+ return '{' + entries + '}';
67
+ }
68
+
69
+ export default exportAsADOFAI;
@@ -0,0 +1,102 @@
1
+ const BOM = Buffer.of(0xef, 0xbb, 0xbf)
2
+ const COMMA = Buffer.from(",")
3
+
4
+ export function stripBOM(buffer: Buffer): Buffer {
5
+ if (buffer.length >= 3 && BOM.equals(buffer.subarray(0, 3))) {
6
+ return buffer.subarray(3)
7
+ }
8
+ return buffer
9
+ }
10
+
11
+ export function normalizeJsonBuffer(text: Buffer): Buffer {
12
+ let builder: Buffer[] = []
13
+ let last: "other" | "string" | "escape" | "comma" = "other"
14
+ let from = 0
15
+ text.forEach((charCode, i) => {
16
+ if (last == "escape") {
17
+ last = "string"
18
+ } else {
19
+ switch (charCode) {
20
+ case 34:
21
+ switch (last) {
22
+ case "string":
23
+ last = "other"
24
+ break
25
+ case "comma":
26
+ builder.push(COMMA)
27
+ default:
28
+ last = "string"
29
+ break
30
+ }
31
+ break
32
+ case 92:
33
+ if (last === "string") last = "escape"
34
+ break
35
+ case 44:
36
+ builder.push(text.subarray(from, i))
37
+ from = i + 1
38
+ if (last === "other") last = "comma"
39
+ break
40
+ case 93:
41
+ case 125:
42
+ if (last === "comma") last = "other"
43
+ break
44
+ case 9:
45
+ case 10:
46
+ case 11:
47
+ case 12:
48
+ case 13:
49
+ case 32:
50
+ break
51
+ default:
52
+ if (last === "comma") {
53
+ builder.push(COMMA)
54
+ last = "other"
55
+ }
56
+ break
57
+ }
58
+ }
59
+ })
60
+ builder.push(text.subarray(from))
61
+ return Buffer.concat(builder)
62
+ }
63
+
64
+ export function normalizeJsonString(text: string): string {
65
+ return normalizeJsonBuffer(Buffer.from(text, "utf-8")).toString("utf-8")
66
+ }
67
+
68
+ export function decodeStringFromUTF8BOM(buffer: Buffer): string {
69
+ return stripBOM(buffer).toString("utf-8")
70
+ }
71
+
72
+ export function encodeStringAsUTF8BOM(text: string): Buffer {
73
+ return Buffer.concat([BOM, stripBOM(Buffer.from(text, "utf-8"))])
74
+ }
75
+
76
+ export function decodeJsonFromString(text: string): any {
77
+ return JSON.parse(normalizeJsonString(text))
78
+ }
79
+
80
+ export function decodeJsonFromBuffer(buffer: Buffer): any {
81
+ return JSON.parse(
82
+ decodeStringFromUTF8BOM(normalizeJsonBuffer(stripBOM(buffer))),
83
+ )
84
+ }
85
+
86
+ export function encodeJsonAsString(obj: any): string {
87
+ return JSON.stringify(obj)
88
+ }
89
+
90
+ export function encodeJsonAsBufferUTF8BOM(obj: any): Buffer {
91
+ return encodeStringAsUTF8BOM(encodeJsonAsString(obj))
92
+ }
93
+
94
+ export function parse(text: string): any {
95
+ return decodeJsonFromString(text)
96
+ }
97
+
98
+ export function stringify(obj: any): string {
99
+ return encodeJsonAsString(obj)
100
+ }
101
+
102
+ export default {parse,stringify}
@@ -0,0 +1,168 @@
1
+ class ADOFAIX {
2
+ static parse(text: string | null, reviver?: (key: string, value: any) => any): any {
3
+ if (text == null) return null
4
+
5
+ const result = new ParserX(text).parseValue()
6
+
7
+ // Apply reviver function if provided (similar to JSON.parse)
8
+ if (typeof reviver === "function") {
9
+ return this._applyReviver("", result, reviver)
10
+ }
11
+
12
+ return result
13
+ }
14
+
15
+ static parsePartially(text: string | null, upToSection: string | null, reviver?: (key: string, value: any) => any): any {
16
+ if (text == null) return null
17
+
18
+ const result = new ParserX(text, upToSection).parseValue()
19
+
20
+ if (typeof reviver === "function") {
21
+ return this._applyReviver("", result, reviver)
22
+ }
23
+
24
+ return result
25
+ }
26
+
27
+ static stringify(value: any, replacer?: (key: string, value: any) => any, space?: string | number): string {
28
+ const serializer = new Serializer(replacer, space)
29
+ return serializer.serialize(value)
30
+ }
31
+
32
+ // Helper method for reviver function
33
+ static _applyReviver(key: string, value: any, reviver: (key: string, value: any) => any): any {
34
+ if (value && typeof value === "object") {
35
+ if (Array.isArray(value)) {
36
+ const arrValue = value as any[];
37
+ for (let i = 0; i < arrValue.length; i++) {
38
+ arrValue[i] = this._applyReviver(i.toString(), arrValue[i], reviver)
39
+ }
40
+ } else {
41
+ const objValue = value as Record<string, any>;
42
+ for (const prop in objValue) {
43
+ if (Object.prototype.hasOwnProperty.call(objValue, prop)) {
44
+ objValue[prop] = this._applyReviver(prop, objValue[prop], reviver)
45
+ }
46
+ }
47
+ }
48
+ }
49
+ return reviver(key, value)
50
+ }
51
+ }
52
+
53
+ class ParserX {
54
+ static WHITE_SPACE = " \t\n\r\uFEFF"
55
+ static WORD_BREAK = ' \t\n\r{}[],:\"'
56
+
57
+ static TOKEN = {
58
+ NONE: 0,
59
+ CURLY_OPEN: 1,
60
+ CURLY_CLOSE: 2,
61
+ SQUARED_OPEN: 3,
62
+ SQUARED_CLOSE: 4,
63
+ COLON: 5,
64
+ COMMA: 6,
65
+ STRING: 7,
66
+ NUMBER: 8,
67
+ TRUE: 9,
68
+ FALSE: 10,
69
+ NULL: 11,
70
+ }
71
+
72
+ private json: string;
73
+ private position: number;
74
+ private endSection: string | null;
75
+
76
+ constructor(jsonString: string, endSection: string | null = null) {
77
+ this.json = jsonString
78
+ this.position = 0
79
+ this.endSection = endSection
80
+
81
+ // Skip BOM if present
82
+ if (this.peek() === 0xfeff) {
83
+ this.read()
84
+ }
85
+ }
86
+
87
+ parseValue(): any {
88
+ return this.parseByToken(this.nextToken)
89
+ }
90
+
91
+ parseObject(): Record<string, any> | null {
92
+ const obj: Record<string, any> = {}
93
+ this.read() // consume '{'
94
+
95
+ while (true) {
96
+ let nextToken
97
+ do {
98
+ nextToken = this.nextToken
99
+ if (nextToken === ParserX.TOKEN.NONE) {
100
+ return null
101
+ }
102
+ if (nextToken === ParserX.TOKEN.CURLY_CLOSE) {
103
+ return obj
104
+ }
105
+ } while (nextToken === ParserX.TOKEN.COMMA)
106
+
107
+ // Rest of the parser implementation would go here
108
+ // This is a placeholder for the remaining parser code
109
+ }
110
+ }
111
+
112
+ // Placeholder for other methods that would be in the Parser class
113
+ private get nextToken(): number {
114
+ // Implementation would go here
115
+ return 0;
116
+ }
117
+
118
+ private read(): number {
119
+ // Implementation would go here
120
+ return 0;
121
+ }
122
+
123
+ private peek(): number {
124
+ // Implementation would go here
125
+ return 0;
126
+ }
127
+
128
+ private parseByToken(token: number): any {
129
+ // Implementation would go here
130
+ return null;
131
+ }
132
+ }
133
+
134
+ class Serializer {
135
+ constructor(replacer?: (key: string, value: any) => any, space?: string | number) {
136
+ // Implementation would go here
137
+ }
138
+
139
+ serialize(value: any): string {
140
+ // Implementation would go here
141
+ return "";
142
+ }
143
+ }
144
+
145
+ class StringParser {
146
+ static parseError(f: string) {
147
+ return f;
148
+ }
149
+
150
+ /**
151
+ * @param {string} t - Input Content
152
+ * @param {object} provider - Third-party JSON Parser
153
+ * @returns {object} ADOFAI File Object
154
+ */
155
+ static parseAsObject(t: string, provider?: any) {
156
+ return (typeof provider == 'undefined' ? ADOFAIX : provider).parse(StringParser.parseAsText(t));
157
+ }
158
+
159
+ /**
160
+ * @param {string} t - Input Content
161
+ * @returns {string} ADOFAI File Content
162
+ */
163
+ static parseAsText(t: string) {
164
+ return this.parseError(t);
165
+ }
166
+ }
167
+
168
+ export default StringParser
package/src/parser.ts ADDED
@@ -0,0 +1,4 @@
1
+ import StringParser from "./parser/StringParser";
2
+ import BufferParser from './parser/BufferParser';
3
+
4
+ export {StringParser, BufferParser}
@@ -0,0 +1,20 @@
1
+ interface PathDataTable {
2
+ [key: string]: number;
3
+ }
4
+
5
+ const pathDataTable: PathDataTable = { "R": 0, "p": 15, "J": 30, "E": 45, "T": 60, "o": 75, "U": 90, "q": 105, "G": 120, "Q": 135, "H": 150, "W": 165, "L": 180, "x": 195, "N": 210, "Z": 225, "F": 240, "V": 255, "D": 270, "Y": 285, "B": 300, "C": 315, "M": 330, "A": 345, "5": 555, "6": 666, "7": 777, "8": 888, "!": 999 };
6
+
7
+ /**
8
+ * @param {string} pathdata - PathData from ADOFAI
9
+ * @returns {Array<number>} Converted AngleData
10
+ */
11
+ function parseToangleData(pathdata: string): number[] {
12
+ let pt = Array.from(String(pathdata));
13
+ let result: number[] = pt.map(t => (pathDataTable as Record<string, number>)[t]);
14
+ return result;
15
+ }
16
+
17
+ export default {
18
+ pathDataTable,
19
+ parseToangleData
20
+ }
package/src/presets.ts ADDED
@@ -0,0 +1,85 @@
1
+ export interface Preset {
2
+ type: 'include'|'exclude'|"special";
3
+ events: string[];
4
+ [key: string]: any;
5
+ }
6
+
7
+ export const preset_noeffect: Preset = {
8
+ type: 'exclude', events: [
9
+ 'Flash',
10
+ 'SetFilter',
11
+ 'SetFilterAdvanced',
12
+ 'HallOfMirrors',
13
+ 'Bloom',
14
+ 'ScalePlanets',
15
+ 'ScreenTile',
16
+ 'ScreenScroll',
17
+ 'ShakeScreen'
18
+ ]
19
+ };
20
+
21
+ export const preset_noholds: Preset = {
22
+ type: 'exclude', events: [
23
+ 'Hold',
24
+ ]
25
+ }
26
+
27
+ export const preset_nomovecamera: Preset = {
28
+ type: 'exclude', events: [
29
+ 'MoveCamera',
30
+ ]
31
+ }
32
+
33
+ export const preset_noeffect_completely: Preset = {
34
+ type: 'exclude', events: [
35
+ "AddDecoration",
36
+ "AddText",
37
+ "AddObject",
38
+ "Checkpoint",
39
+ "SetHitsound",
40
+ "PlaySound",
41
+ "SetPlanetRotation",
42
+ "ScalePlanets",
43
+ "ColorTrack",
44
+ "AnimateTrack",
45
+ "RecolorTrack",
46
+ "MoveTrack",
47
+ "PositionTrack",
48
+ "MoveDecorations",
49
+ "SetText",
50
+ "SetObject",
51
+ "SetDefaultText",
52
+ "CustomBackground",
53
+ "Flash",
54
+ "MoveCamera",
55
+ "SetFilter",
56
+ "HallOfMirrors",
57
+ "ShakeScreen",
58
+ "Bloom",
59
+ "ScreenTile",
60
+ "ScreenScroll",
61
+ "SetFrameRate",
62
+ "RepeatEvents",
63
+ "SetConditionalEvents",
64
+ "EditorComment",
65
+ "Bookmark",
66
+ "Hold",
67
+ "SetHoldSound",
68
+ //"MultiPlanet",
69
+ //"FreeRoam",
70
+ //"FreeRoamTwirl",
71
+ //"FreeRoamRemove",
72
+ "Hide",
73
+ "ScaleMargin",
74
+ "ScaleRadius"
75
+ ]
76
+ }
77
+
78
+ export const preset_inner_no_deco: Preset = {
79
+ type: "special", events: [
80
+ "MoveDecorations",
81
+ "SetText",
82
+ "SetObject",
83
+ "SetDefaultText"
84
+ ]
85
+ }