xiv-strat-board 0.1.2 → 0.2.0
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 +5 -5
- package/dist/index.cjs +89 -65
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +89 -65
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -75,7 +75,7 @@ Decodes a share code to a strategy board.
|
|
|
75
75
|
|
|
76
76
|
```typescript
|
|
77
77
|
interface StrategyBoard {
|
|
78
|
-
name?: string; // Max
|
|
78
|
+
name?: string; // Max 20 characters
|
|
79
79
|
boardBackground?: BackgroundType;
|
|
80
80
|
objects: StrategyObject[];
|
|
81
81
|
}
|
|
@@ -89,7 +89,7 @@ interface StrategyObject {
|
|
|
89
89
|
typeId?: number; // Optional numeric ID (overrides type)
|
|
90
90
|
x: number; // 0-512, center at 256
|
|
91
91
|
y: number; // 0-384, center at 192
|
|
92
|
-
size?: number; //
|
|
92
|
+
size?: number; // 10-200, default 100 (text always 100)
|
|
93
93
|
background?: BackgroundType;
|
|
94
94
|
|
|
95
95
|
// Color (only for line_aoe, line, text)
|
|
@@ -97,8 +97,8 @@ interface StrategyObject {
|
|
|
97
97
|
transparency?: number; // 0-255
|
|
98
98
|
|
|
99
99
|
// AoE properties
|
|
100
|
-
arcAngle?: number; //
|
|
101
|
-
donutRadius?: number; // 0-255
|
|
100
|
+
arcAngle?: number; // 0-360, intervals of 10
|
|
101
|
+
donutRadius?: number; // 0-255 (0 = full circle/no hole)
|
|
102
102
|
|
|
103
103
|
// Line AoE properties
|
|
104
104
|
width?: number; // Width for line_aoe
|
|
@@ -117,7 +117,7 @@ interface StrategyObject {
|
|
|
117
117
|
verticalCount?: number; // Vertical count for linear_knockback
|
|
118
118
|
|
|
119
119
|
// Text objects
|
|
120
|
-
text?: string; // Text content
|
|
120
|
+
text?: string; // Text content (max 30 chars)
|
|
121
121
|
|
|
122
122
|
// Flip states
|
|
123
123
|
horizontalFlip?: boolean;
|
package/dist/index.cjs
CHANGED
|
@@ -371,24 +371,6 @@ var BOARD_BACKGROUND_IDS = {
|
|
|
371
371
|
grey_circle: 6,
|
|
372
372
|
grey_square: 7
|
|
373
373
|
};
|
|
374
|
-
var OBJECT_BACKGROUND_TYPES = {
|
|
375
|
-
0: "none",
|
|
376
|
-
1: "checkered",
|
|
377
|
-
2: "checkered_circle",
|
|
378
|
-
3: "checkered_square",
|
|
379
|
-
4: "grey",
|
|
380
|
-
5: "grey_circle",
|
|
381
|
-
6: "grey_square"
|
|
382
|
-
};
|
|
383
|
-
var OBJECT_BACKGROUND_IDS = {
|
|
384
|
-
none: 0,
|
|
385
|
-
checkered: 1,
|
|
386
|
-
checkered_circle: 2,
|
|
387
|
-
checkered_square: 3,
|
|
388
|
-
grey: 4,
|
|
389
|
-
grey_circle: 5,
|
|
390
|
-
grey_square: 6
|
|
391
|
-
};
|
|
392
374
|
|
|
393
375
|
// src/validation.ts
|
|
394
376
|
var BOUNDS = {
|
|
@@ -401,9 +383,9 @@ var BOUNDS = {
|
|
|
401
383
|
/** Maximum Y coordinate */
|
|
402
384
|
maxY: 484,
|
|
403
385
|
/** Minimum size percentage */
|
|
404
|
-
minSize:
|
|
386
|
+
minSize: 10,
|
|
405
387
|
/** Maximum size percentage */
|
|
406
|
-
maxSize:
|
|
388
|
+
maxSize: 200,
|
|
407
389
|
/** Minimum arc angle */
|
|
408
390
|
minArc: 0,
|
|
409
391
|
/** Maximum arc angle */
|
|
@@ -414,8 +396,10 @@ var BOUNDS = {
|
|
|
414
396
|
maxDonut: 255,
|
|
415
397
|
/** Maximum number of objects per board */
|
|
416
398
|
maxObjects: 50,
|
|
399
|
+
/** Maximum number of text objects per board */
|
|
400
|
+
maxTextObjects: 8,
|
|
417
401
|
/** Maximum name length (bytes) */
|
|
418
|
-
maxNameLength:
|
|
402
|
+
maxNameLength: 20
|
|
419
403
|
};
|
|
420
404
|
var VALID_CIPHER_CHARS = new Set(
|
|
421
405
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-_".split("")
|
|
@@ -490,19 +474,6 @@ function parseHexColor(color) {
|
|
|
490
474
|
b: parseInt(hex.slice(4, 6), 16)
|
|
491
475
|
};
|
|
492
476
|
}
|
|
493
|
-
function validateBackground(value) {
|
|
494
|
-
if (typeof value === "number") {
|
|
495
|
-
if (value >= 0 && value <= 6) {
|
|
496
|
-
return value;
|
|
497
|
-
}
|
|
498
|
-
return 0;
|
|
499
|
-
}
|
|
500
|
-
if (typeof value === "string") {
|
|
501
|
-
const id = OBJECT_BACKGROUND_IDS[value.toLowerCase()];
|
|
502
|
-
return id ?? 0;
|
|
503
|
-
}
|
|
504
|
-
return 0;
|
|
505
|
-
}
|
|
506
477
|
function validateBoardBackground(value) {
|
|
507
478
|
if (typeof value === "string") {
|
|
508
479
|
const id = BOARD_BACKGROUND_IDS[value.toLowerCase()];
|
|
@@ -553,16 +524,26 @@ function sanitizeObject(obj, index) {
|
|
|
553
524
|
typeId,
|
|
554
525
|
x: sanitizeCoordinate(obj.x, true),
|
|
555
526
|
y: sanitizeCoordinate(obj.y, false),
|
|
556
|
-
size: sanitizeSize(obj.size),
|
|
557
|
-
|
|
527
|
+
size: typeId === 100 ? 100 : sanitizeSize(obj.size),
|
|
528
|
+
angle: Math.round(obj.angle ?? 0),
|
|
558
529
|
colorR: sanitizeColorComponent(colorR),
|
|
559
530
|
colorG: sanitizeColorComponent(colorG),
|
|
560
531
|
colorB: sanitizeColorComponent(colorB),
|
|
561
532
|
transparency: sanitizeColorComponent(obj.transparency ?? 0),
|
|
562
|
-
arcAngle: clamp(Math.round(obj.arcAngle ?? 0), BOUNDS.minArc, BOUNDS.maxArc),
|
|
533
|
+
arcAngle: clamp(Math.round((obj.arcAngle ?? 0) / 10) * 10, BOUNDS.minArc, BOUNDS.maxArc),
|
|
563
534
|
donutRadius: clamp(Math.round(obj.donutRadius ?? 0), BOUNDS.minDonut, BOUNDS.maxDonut),
|
|
535
|
+
width: Math.round(obj.width ?? 0),
|
|
536
|
+
height: Math.round(obj.height ?? 0),
|
|
537
|
+
endX: sanitizeCoordinate(obj.endX ?? 0, true),
|
|
538
|
+
endY: sanitizeCoordinate(obj.endY ?? 0, false),
|
|
539
|
+
displayCount: Math.round(obj.displayCount ?? 0),
|
|
540
|
+
horizontalCount: Math.round(obj.horizontalCount ?? 0),
|
|
541
|
+
verticalCount: Math.round(obj.verticalCount ?? 0),
|
|
542
|
+
text: typeof obj.text === "string" ? obj.text.slice(0, 30) : "",
|
|
564
543
|
hidden: Boolean(obj.hidden),
|
|
565
|
-
locked: Boolean(obj.locked)
|
|
544
|
+
locked: Boolean(obj.locked),
|
|
545
|
+
horizontalFlip: Boolean(obj.horizontalFlip),
|
|
546
|
+
verticalFlip: Boolean(obj.verticalFlip)
|
|
566
547
|
};
|
|
567
548
|
}
|
|
568
549
|
function sanitizeBoard(board) {
|
|
@@ -575,6 +556,10 @@ function sanitizeBoard(board) {
|
|
|
575
556
|
if (board.objects.length > BOUNDS.maxObjects) {
|
|
576
557
|
throw new Error(`Board has too many objects (max ${BOUNDS.maxObjects})`);
|
|
577
558
|
}
|
|
559
|
+
const textCount = board.objects.filter((obj) => obj.type === "text" || obj.typeId === 100).length;
|
|
560
|
+
if (textCount > BOUNDS.maxTextObjects) {
|
|
561
|
+
throw new Error(`Board has too many text objects (max ${BOUNDS.maxTextObjects})`);
|
|
562
|
+
}
|
|
578
563
|
return {
|
|
579
564
|
name: sanitizeName(board.name),
|
|
580
565
|
boardBackground: validateBoardBackground(board.boardBackground),
|
|
@@ -798,15 +783,9 @@ function parseBinary(data) {
|
|
|
798
783
|
x: positions[i]?.x ?? 0,
|
|
799
784
|
y: positions[i]?.y ?? 0
|
|
800
785
|
};
|
|
801
|
-
obj.size = sizes[i] && sizes[i] > 0 ? sizes[i] : 100;
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
if (backgrounds[i] !== void 0 && backgrounds[i] !== 0) {
|
|
805
|
-
obj.angle = backgrounds[i];
|
|
806
|
-
}
|
|
807
|
-
} else if (backgrounds[i] !== void 0 && backgrounds[i] > 0) {
|
|
808
|
-
const bgName = OBJECT_BACKGROUND_TYPES[backgrounds[i]];
|
|
809
|
-
obj.background = bgName ?? backgrounds[i];
|
|
786
|
+
obj.size = iconId === 100 ? 100 : sizes[i] && sizes[i] > 0 ? sizes[i] : 100;
|
|
787
|
+
if (iconId !== 100 && backgrounds[i] !== void 0 && backgrounds[i] !== 0) {
|
|
788
|
+
obj.angle = backgrounds[i];
|
|
810
789
|
}
|
|
811
790
|
const colorableTypes = /* @__PURE__ */ new Set([11, 12, 100]);
|
|
812
791
|
if (colors[i]) {
|
|
@@ -852,10 +831,10 @@ function parseBinary(data) {
|
|
|
852
831
|
obj.verticalCount = tag11[i];
|
|
853
832
|
}
|
|
854
833
|
} else if (iconId === 17) {
|
|
855
|
-
if (tag10[i] && tag10[i] > 0) {
|
|
834
|
+
if (tag10[i] !== void 0 && tag10[i] > 0) {
|
|
856
835
|
obj.arcAngle = tag10[i];
|
|
857
836
|
}
|
|
858
|
-
if (tag11[i]
|
|
837
|
+
if (tag11[i] !== void 0) {
|
|
859
838
|
obj.donutRadius = tag11[i];
|
|
860
839
|
}
|
|
861
840
|
} else {
|
|
@@ -894,9 +873,20 @@ function parseBinary(data) {
|
|
|
894
873
|
function buildBinary(data) {
|
|
895
874
|
const { name, boardBackground, objects } = data;
|
|
896
875
|
const n = objects.length;
|
|
876
|
+
const nameBytes = new TextEncoder().encode(name.slice(0, 20));
|
|
877
|
+
const namePaddedLen = Math.max(8, nameBytes.length + 1 + 3 & -4);
|
|
878
|
+
const headerSize = 28 + namePaddedLen;
|
|
897
879
|
const tag4Size = n <= 1 ? 8 : 6 + n * 2;
|
|
898
880
|
const tag7Size = 6 + n + (n % 2 === 1 ? 1 : 0);
|
|
899
|
-
|
|
881
|
+
let textContentSize = 0;
|
|
882
|
+
for (const obj of objects) {
|
|
883
|
+
if (obj.typeId === 100 && obj.text) {
|
|
884
|
+
const textLen = new TextEncoder().encode(obj.text).length;
|
|
885
|
+
const paddedLen = Math.max(8, textLen + 1 + 3 & -4);
|
|
886
|
+
textContentSize += 4 + paddedLen;
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
const bufferSize = n === 0 ? headerSize + 8 : headerSize + n * 4 + textContentSize + tag4Size + (6 + n * 4) + (6 + n * 2) + tag7Size + (6 + n * 4) + (6 + n * 2) + (6 + n * 2) + (6 + n * 2) + 8;
|
|
900
890
|
const buffer = new ArrayBuffer(bufferSize);
|
|
901
891
|
const view = new DataView(buffer);
|
|
902
892
|
let pos = 0;
|
|
@@ -922,33 +912,45 @@ function buildBinary(data) {
|
|
|
922
912
|
writeUint32(0);
|
|
923
913
|
writeUint16(0);
|
|
924
914
|
writeUint16(1);
|
|
925
|
-
writeUint16(
|
|
926
|
-
|
|
927
|
-
for (let i = 0; i < 8; i++) {
|
|
915
|
+
writeUint16(namePaddedLen);
|
|
916
|
+
for (let i = 0; i < namePaddedLen; i++) {
|
|
928
917
|
writeUint8(nameBytes[i] ?? 0);
|
|
929
918
|
}
|
|
930
919
|
for (const obj of objects) {
|
|
931
920
|
writeUint16(2);
|
|
932
921
|
writeUint16(obj.typeId);
|
|
922
|
+
if (obj.typeId === 100 && obj.text) {
|
|
923
|
+
const textBytes = new TextEncoder().encode(obj.text);
|
|
924
|
+
const paddedLen = Math.max(8, textBytes.length + 1 + 3 & -4);
|
|
925
|
+
writeUint16(3);
|
|
926
|
+
writeUint16(paddedLen);
|
|
927
|
+
for (let i = 0; i < paddedLen; i++) {
|
|
928
|
+
writeUint8(textBytes[i] ?? 0);
|
|
929
|
+
}
|
|
930
|
+
}
|
|
933
931
|
}
|
|
934
932
|
if (n === 0) ; else if (n === 1) {
|
|
935
933
|
writeUint16(4);
|
|
936
934
|
writeUint16(1);
|
|
937
935
|
const obj = objects[0];
|
|
938
936
|
let flagsVal = 1;
|
|
939
|
-
if (obj.hidden)
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
}
|
|
937
|
+
if (obj.hidden) flagsVal &= -2;
|
|
938
|
+
if (obj.horizontalFlip) flagsVal |= 2;
|
|
939
|
+
if (obj.verticalFlip) flagsVal |= 4;
|
|
940
|
+
if (obj.locked) flagsVal |= 8;
|
|
944
941
|
writeUint16(1);
|
|
945
942
|
writeUint16(flagsVal);
|
|
946
943
|
} else {
|
|
947
944
|
writeUint16(4);
|
|
948
945
|
writeUint16(1);
|
|
949
946
|
writeUint16(n);
|
|
950
|
-
for (
|
|
951
|
-
|
|
947
|
+
for (const obj of objects) {
|
|
948
|
+
let flagsVal = 1;
|
|
949
|
+
if (obj.hidden) flagsVal &= -2;
|
|
950
|
+
if (obj.horizontalFlip) flagsVal |= 2;
|
|
951
|
+
if (obj.verticalFlip) flagsVal |= 4;
|
|
952
|
+
if (obj.locked) flagsVal |= 8;
|
|
953
|
+
writeUint16(flagsVal);
|
|
952
954
|
}
|
|
953
955
|
}
|
|
954
956
|
if (n > 0) {
|
|
@@ -963,7 +965,7 @@ function buildBinary(data) {
|
|
|
963
965
|
writeUint16(1);
|
|
964
966
|
writeUint16(n);
|
|
965
967
|
for (const obj of objects) {
|
|
966
|
-
|
|
968
|
+
writeInt16(obj.angle);
|
|
967
969
|
}
|
|
968
970
|
writeUint16(7);
|
|
969
971
|
writeUint16(0);
|
|
@@ -987,19 +989,41 @@ function buildBinary(data) {
|
|
|
987
989
|
writeUint16(1);
|
|
988
990
|
writeUint16(n);
|
|
989
991
|
for (const obj of objects) {
|
|
990
|
-
|
|
992
|
+
if (obj.typeId === 11) {
|
|
993
|
+
writeUint16(obj.width);
|
|
994
|
+
} else if (obj.typeId === 12) {
|
|
995
|
+
writeUint16(Math.round(obj.endX * 10));
|
|
996
|
+
} else if (obj.typeId === 110) {
|
|
997
|
+
writeUint16(obj.horizontalCount);
|
|
998
|
+
} else {
|
|
999
|
+
writeUint16(obj.arcAngle);
|
|
1000
|
+
}
|
|
991
1001
|
}
|
|
992
1002
|
writeUint16(11);
|
|
993
1003
|
writeUint16(1);
|
|
994
1004
|
writeUint16(n);
|
|
995
1005
|
for (const obj of objects) {
|
|
996
|
-
|
|
1006
|
+
if (obj.typeId === 11) {
|
|
1007
|
+
writeUint16(obj.height);
|
|
1008
|
+
} else if (obj.typeId === 12) {
|
|
1009
|
+
writeUint16(Math.round(obj.endY * 10));
|
|
1010
|
+
} else if (obj.typeId === 15) {
|
|
1011
|
+
writeUint16(obj.displayCount);
|
|
1012
|
+
} else if (obj.typeId === 110) {
|
|
1013
|
+
writeUint16(obj.verticalCount);
|
|
1014
|
+
} else {
|
|
1015
|
+
writeUint16(obj.donutRadius);
|
|
1016
|
+
}
|
|
997
1017
|
}
|
|
998
1018
|
writeUint16(12);
|
|
999
1019
|
writeUint16(1);
|
|
1000
1020
|
writeUint16(n);
|
|
1001
|
-
for (
|
|
1002
|
-
|
|
1021
|
+
for (const obj of objects) {
|
|
1022
|
+
if (obj.typeId === 12) {
|
|
1023
|
+
writeUint16(obj.height);
|
|
1024
|
+
} else {
|
|
1025
|
+
writeUint16(0);
|
|
1026
|
+
}
|
|
1003
1027
|
}
|
|
1004
1028
|
}
|
|
1005
1029
|
writeUint16(3);
|