d2r-saver 0.1.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/LICENSE +21 -0
- package/README.md +126 -0
- package/data/data.json +1 -0
- package/data/strings.json +1 -0
- package/dist/core/binary-reader.d.ts +43 -0
- package/dist/core/binary-reader.d.ts.map +1 -0
- package/dist/core/binary-reader.js +130 -0
- package/dist/core/binary-reader.js.map +1 -0
- package/dist/core/binary-writer.d.ts +49 -0
- package/dist/core/binary-writer.d.ts.map +1 -0
- package/dist/core/binary-writer.js +156 -0
- package/dist/core/binary-writer.js.map +1 -0
- package/dist/core/checksum.d.ts +28 -0
- package/dist/core/checksum.d.ts.map +1 -0
- package/dist/core/checksum.js +62 -0
- package/dist/core/checksum.js.map +1 -0
- package/dist/core/huffman.d.ts +22 -0
- package/dist/core/huffman.d.ts.map +1 -0
- package/dist/core/huffman.js +66 -0
- package/dist/core/huffman.js.map +1 -0
- package/dist/core/index.d.ts +5 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +5 -0
- package/dist/core/index.js.map +1 -0
- package/dist/formats/d2i-reader.d.ts +53 -0
- package/dist/formats/d2i-reader.d.ts.map +1 -0
- package/dist/formats/d2i-reader.js +208 -0
- package/dist/formats/d2i-reader.js.map +1 -0
- package/dist/formats/d2i-writer.d.ts +63 -0
- package/dist/formats/d2i-writer.d.ts.map +1 -0
- package/dist/formats/d2i-writer.js +229 -0
- package/dist/formats/d2i-writer.js.map +1 -0
- package/dist/formats/d2s-reader.d.ts +104 -0
- package/dist/formats/d2s-reader.d.ts.map +1 -0
- package/dist/formats/d2s-reader.js +257 -0
- package/dist/formats/d2s-reader.js.map +1 -0
- package/dist/formats/d2s-writer.d.ts +52 -0
- package/dist/formats/d2s-writer.d.ts.map +1 -0
- package/dist/formats/d2s-writer.js +407 -0
- package/dist/formats/d2s-writer.js.map +1 -0
- package/dist/formats/detect.d.ts +18 -0
- package/dist/formats/detect.d.ts.map +1 -0
- package/dist/formats/detect.js +40 -0
- package/dist/formats/detect.js.map +1 -0
- package/dist/formats/index.d.ts +8 -0
- package/dist/formats/index.d.ts.map +1 -0
- package/dist/formats/index.js +8 -0
- package/dist/formats/index.js.map +1 -0
- package/dist/formats/item-parser.d.ts +97 -0
- package/dist/formats/item-parser.d.ts.map +1 -0
- package/dist/formats/item-parser.js +627 -0
- package/dist/formats/item-parser.js.map +1 -0
- package/dist/formats/item-writer.d.ts +55 -0
- package/dist/formats/item-writer.d.ts.map +1 -0
- package/dist/formats/item-writer.js +514 -0
- package/dist/formats/item-writer.js.map +1 -0
- package/dist/game-data/game-data.d.ts +90 -0
- package/dist/game-data/game-data.d.ts.map +1 -0
- package/dist/game-data/game-data.js +355 -0
- package/dist/game-data/game-data.js.map +1 -0
- package/dist/game-data/index.d.ts +4 -0
- package/dist/game-data/index.d.ts.map +1 -0
- package/dist/game-data/index.js +3 -0
- package/dist/game-data/index.js.map +1 -0
- package/dist/game-data/loader.d.ts +23 -0
- package/dist/game-data/loader.d.ts.map +1 -0
- package/dist/game-data/loader.js +32 -0
- package/dist/game-data/loader.js.map +1 -0
- package/dist/game-data/types.d.ts +428 -0
- package/dist/game-data/types.d.ts.map +1 -0
- package/dist/game-data/types.js +10 -0
- package/dist/game-data/types.js.map +1 -0
- package/dist/index.d.ts +166 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +197 -0
- package/dist/index.js.map +1 -0
- package/dist/inventory/dimensions.d.ts +42 -0
- package/dist/inventory/dimensions.d.ts.map +1 -0
- package/dist/inventory/dimensions.js +30 -0
- package/dist/inventory/dimensions.js.map +1 -0
- package/dist/inventory/grid.d.ts +53 -0
- package/dist/inventory/grid.d.ts.map +1 -0
- package/dist/inventory/grid.js +117 -0
- package/dist/inventory/grid.js.map +1 -0
- package/dist/inventory/index.d.ts +4 -0
- package/dist/inventory/index.d.ts.map +1 -0
- package/dist/inventory/index.js +4 -0
- package/dist/inventory/index.js.map +1 -0
- package/dist/inventory/placement.d.ts +68 -0
- package/dist/inventory/placement.d.ts.map +1 -0
- package/dist/inventory/placement.js +90 -0
- package/dist/inventory/placement.js.map +1 -0
- package/dist/items/index.d.ts +7 -0
- package/dist/items/index.d.ts.map +1 -0
- package/dist/items/index.js +7 -0
- package/dist/items/index.js.map +1 -0
- package/dist/items/item-dto.d.ts +47 -0
- package/dist/items/item-dto.d.ts.map +1 -0
- package/dist/items/item-dto.js +124 -0
- package/dist/items/item-dto.js.map +1 -0
- package/dist/items/item-icon.d.ts +27 -0
- package/dist/items/item-icon.d.ts.map +1 -0
- package/dist/items/item-icon.js +103 -0
- package/dist/items/item-icon.js.map +1 -0
- package/dist/items/item-serializer.d.ts +38 -0
- package/dist/items/item-serializer.d.ts.map +1 -0
- package/dist/items/item-serializer.js +92 -0
- package/dist/items/item-serializer.js.map +1 -0
- package/dist/items/item-stats-parser.d.ts +52 -0
- package/dist/items/item-stats-parser.d.ts.map +1 -0
- package/dist/items/item-stats-parser.js +671 -0
- package/dist/items/item-stats-parser.js.map +1 -0
- package/dist/items/item-types.d.ts +40 -0
- package/dist/items/item-types.d.ts.map +1 -0
- package/dist/items/item-types.js +198 -0
- package/dist/items/item-types.js.map +1 -0
- package/dist/items/item.d.ts +61 -0
- package/dist/items/item.d.ts.map +1 -0
- package/dist/items/item.js +335 -0
- package/dist/items/item.js.map +1 -0
- package/dist/operations/extract-item.d.ts +39 -0
- package/dist/operations/extract-item.d.ts.map +1 -0
- package/dist/operations/extract-item.js +204 -0
- package/dist/operations/extract-item.js.map +1 -0
- package/dist/operations/index.d.ts +4 -0
- package/dist/operations/index.d.ts.map +1 -0
- package/dist/operations/index.js +4 -0
- package/dist/operations/index.js.map +1 -0
- package/dist/operations/insert-item.d.ts +59 -0
- package/dist/operations/insert-item.d.ts.map +1 -0
- package/dist/operations/insert-item.js +210 -0
- package/dist/operations/insert-item.js.map +1 -0
- package/dist/operations/read-save.d.ts +25 -0
- package/dist/operations/read-save.d.ts.map +1 -0
- package/dist/operations/read-save.js +27 -0
- package/dist/operations/read-save.js.map +1 -0
- package/dist/types/constants.d.ts +76 -0
- package/dist/types/constants.d.ts.map +1 -0
- package/dist/types/constants.js +96 -0
- package/dist/types/constants.js.map +1 -0
- package/dist/types/errors.d.ts +47 -0
- package/dist/types/errors.d.ts.map +1 -0
- package/dist/types/errors.js +53 -0
- package/dist/types/errors.js.map +1 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/item.d.ts +112 -0
- package/dist/types/item.d.ts.map +1 -0
- package/dist/types/item.js +6 -0
- package/dist/types/item.js.map +1 -0
- package/dist/types/save-file.d.ts +74 -0
- package/dist/types/save-file.d.ts.map +1 -0
- package/dist/types/save-file.js +5 -0
- package/dist/types/save-file.js.map +1 -0
- package/dist/types/trade-item.d.ts +37 -0
- package/dist/types/trade-item.d.ts.map +1 -0
- package/dist/types/trade-item.js +5 -0
- package/dist/types/trade-item.js.map +1 -0
- package/package.json +70 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* d2r-saver — Blizzless D2R v105 save file reader/writer library.
|
|
3
|
+
*
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*/
|
|
6
|
+
import { GameData } from './game-data/game-data.js';
|
|
7
|
+
import { detectFormat } from './formats/detect.js';
|
|
8
|
+
import { readD2S } from './formats/d2s-reader.js';
|
|
9
|
+
import { readD2I } from './formats/d2i-reader.js';
|
|
10
|
+
import { writeD2S } from './formats/d2s-writer.js';
|
|
11
|
+
import { writeStash, buildStashWritePages, patchStashPage, } from './formats/d2i-writer.js';
|
|
12
|
+
import { extractItemD2S, extractItemD2I, } from './operations/extract-item.js';
|
|
13
|
+
import { insertItemD2S, insertItemD2I, } from './operations/insert-item.js';
|
|
14
|
+
import { readSave } from './operations/read-save.js';
|
|
15
|
+
import { serializeItem, deserializeItem, } from './items/item-serializer.js';
|
|
16
|
+
import { getItemIconPath, getItemIconSD } from './items/item-icon.js';
|
|
17
|
+
import { toTradeDTO } from './items/item-dto.js';
|
|
18
|
+
import { canPlaceItem, findFreeSlot, findFreeSlotInStash } from './inventory/placement.js';
|
|
19
|
+
import { D2RSaverError, ErrorCode } from './types/errors.js';
|
|
20
|
+
// ─── Re-exports ─────────────────────────────────────────────────
|
|
21
|
+
export { GameData } from './game-data/game-data.js';
|
|
22
|
+
export { D2RSaverError, ErrorCode } from './types/errors.js';
|
|
23
|
+
export { StashGrid } from './inventory/grid.js';
|
|
24
|
+
/**
|
|
25
|
+
* Main facade for all d2r-saver operations.
|
|
26
|
+
*
|
|
27
|
+
* Holds a `GameData` instance and delegates to internal modules.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```ts
|
|
31
|
+
* const saver = await D2RSaver.create({ dataPath: './data/data.json', stringsPath: './data/strings.json' });
|
|
32
|
+
* const result = saver.readD2S(buffer);
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export class D2RSaver {
|
|
36
|
+
/** Internal game data reference. */
|
|
37
|
+
gd;
|
|
38
|
+
constructor(gd) {
|
|
39
|
+
this.gd = gd;
|
|
40
|
+
}
|
|
41
|
+
// ── Factory methods ─────────────────────────────────────────
|
|
42
|
+
/**
|
|
43
|
+
* Create a D2RSaver by loading game data from file paths.
|
|
44
|
+
*
|
|
45
|
+
* @param options Paths to data.json and strings.json.
|
|
46
|
+
*/
|
|
47
|
+
static async create(options) {
|
|
48
|
+
const gd = await GameData.fromFile(options.dataPath, options.stringsPath);
|
|
49
|
+
return new D2RSaver(gd);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Create a D2RSaver from pre-parsed JSON objects.
|
|
53
|
+
*
|
|
54
|
+
* @param rawData Parsed data.json content.
|
|
55
|
+
* @param locale Parsed strings.json content.
|
|
56
|
+
*/
|
|
57
|
+
static fromData(rawData, locale) {
|
|
58
|
+
const gd = GameData.fromRaw(rawData, locale);
|
|
59
|
+
return new D2RSaver(gd);
|
|
60
|
+
}
|
|
61
|
+
// ── Format detection ────────────────────────────────────────
|
|
62
|
+
/**
|
|
63
|
+
* Detect file format.
|
|
64
|
+
*
|
|
65
|
+
* @throws {D2RSaverError} INVALID_FORMAT if file is unrecognized.
|
|
66
|
+
*/
|
|
67
|
+
detectFormat(buffer) {
|
|
68
|
+
const result = detectFormat(buffer);
|
|
69
|
+
if (!result) {
|
|
70
|
+
throw new D2RSaverError(ErrorCode.INVALID_FORMAT, 'File is not a valid Blizzless v105 d2s or d2i.');
|
|
71
|
+
}
|
|
72
|
+
return result;
|
|
73
|
+
}
|
|
74
|
+
// ── Reading ─────────────────────────────────────────────────
|
|
75
|
+
/** Read a .d2s character save file. */
|
|
76
|
+
readD2S(buffer) {
|
|
77
|
+
return readD2S(buffer, this.gd);
|
|
78
|
+
}
|
|
79
|
+
/** Read a .d2i shared stash file. */
|
|
80
|
+
readD2I(buffer) {
|
|
81
|
+
return readD2I(buffer, this.gd);
|
|
82
|
+
}
|
|
83
|
+
/** Auto-detect format and read a save file. */
|
|
84
|
+
readSave(buffer) {
|
|
85
|
+
return readSave(buffer, this.gd);
|
|
86
|
+
}
|
|
87
|
+
// ── Item serialization ──────────────────────────────────────
|
|
88
|
+
/** Serialize an item to a portable token (`d2r1:<base64>`). */
|
|
89
|
+
serializeItem(item, allItems) {
|
|
90
|
+
return serializeItem(item, allItems, this.gd);
|
|
91
|
+
}
|
|
92
|
+
/** Deserialize an item from a portable token. */
|
|
93
|
+
deserializeItem(token) {
|
|
94
|
+
return deserializeItem(token, this.gd);
|
|
95
|
+
}
|
|
96
|
+
// ── Placement helpers ───────────────────────────────────────
|
|
97
|
+
/** Get the grid size of an item in cells. */
|
|
98
|
+
getItemSize(item) {
|
|
99
|
+
const base = this.gd.items[item.base];
|
|
100
|
+
return {
|
|
101
|
+
width: base?.invwidth ?? 1,
|
|
102
|
+
height: base?.invheight ?? 1,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
/** Check if an item can be placed at a position on a grid. */
|
|
106
|
+
canPlaceItem(grid, x, y, item) {
|
|
107
|
+
return canPlaceItem(grid, x, y, item, this.gd);
|
|
108
|
+
}
|
|
109
|
+
/** Find the first free slot for an item on a grid. */
|
|
110
|
+
findFreeSlot(grid, item) {
|
|
111
|
+
return findFreeSlot(grid, item, this.gd);
|
|
112
|
+
}
|
|
113
|
+
/** Find the first free slot for an item across multiple stash grids. */
|
|
114
|
+
findFreeSlotInStash(grids, item) {
|
|
115
|
+
return findFreeSlotInStash(grids, item, this.gd);
|
|
116
|
+
}
|
|
117
|
+
// ── Item operations ─────────────────────────────────────────
|
|
118
|
+
/**
|
|
119
|
+
* Extract an item from a .d2s save file.
|
|
120
|
+
*
|
|
121
|
+
* @param buffer Original file buffer.
|
|
122
|
+
* @param itemId Item ID to extract.
|
|
123
|
+
*/
|
|
124
|
+
extractItemD2S(buffer, itemId) {
|
|
125
|
+
return extractItemD2S(buffer, itemId, this.gd);
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Extract an item from a .d2i shared stash.
|
|
129
|
+
*
|
|
130
|
+
* @param buffer Original file buffer.
|
|
131
|
+
* @param pageIndex Page index.
|
|
132
|
+
* @param x X position in grid.
|
|
133
|
+
* @param y Y position in grid.
|
|
134
|
+
*/
|
|
135
|
+
extractItemD2I(buffer, pageIndex, x, y) {
|
|
136
|
+
return extractItemD2I(buffer, pageIndex, x, y, this.gd);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Insert an item into a .d2s save file.
|
|
140
|
+
*
|
|
141
|
+
* @param buffer Original file buffer.
|
|
142
|
+
* @param item Item to insert.
|
|
143
|
+
* @param allItemsForItem All related items (including socketed sub-items).
|
|
144
|
+
* @param target Target container: 'stash' | 'inventory' | 'cube'.
|
|
145
|
+
* @param position Optional specific position. Auto-finds if omitted.
|
|
146
|
+
*/
|
|
147
|
+
insertItemD2S(buffer, item, allItemsForItem, target, position) {
|
|
148
|
+
return insertItemD2S(buffer, item, allItemsForItem, target, this.gd, position);
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Insert an item into a .d2i shared stash.
|
|
152
|
+
*
|
|
153
|
+
* @param buffer Original file buffer.
|
|
154
|
+
* @param item Item to insert.
|
|
155
|
+
* @param allItemsForItem All related items (including socketed sub-items).
|
|
156
|
+
* @param target Optional specific target page and position.
|
|
157
|
+
*/
|
|
158
|
+
insertItemD2I(buffer, item, allItemsForItem, target) {
|
|
159
|
+
return insertItemD2I(buffer, item, allItemsForItem, this.gd, target);
|
|
160
|
+
}
|
|
161
|
+
// ── Writing ─────────────────────────────────────────────────
|
|
162
|
+
/**
|
|
163
|
+
* Re-serialise a complete .d2s from a (possibly edited) profile + items.
|
|
164
|
+
* Lossless: the parsed profile must carry rawHeader/attributes (from readD2S);
|
|
165
|
+
* apply edits by mutating `profile.attributes` (raw values) before calling.
|
|
166
|
+
*/
|
|
167
|
+
writeD2S(profile, items, name) {
|
|
168
|
+
return writeD2S({ profile, items, gd: this.gd, name });
|
|
169
|
+
}
|
|
170
|
+
/** Convert parsed stash pages back to writable pages (for writeStash). */
|
|
171
|
+
buildStashWritePages(pages, allItems) {
|
|
172
|
+
return buildStashWritePages(pages, allItems, this.gd);
|
|
173
|
+
}
|
|
174
|
+
/** Re-serialise a complete .d2i shared stash from writable pages. */
|
|
175
|
+
writeStash(pages, allItems) {
|
|
176
|
+
return writeStash(pages, allItems, this.gd);
|
|
177
|
+
}
|
|
178
|
+
/** Patch a single .d2i sector (e.g. to change its gold) by raw sector index. */
|
|
179
|
+
patchStashPage(buffer, pageIndex, newPage, allItems) {
|
|
180
|
+
return patchStashPage(buffer, pageIndex, newPage, allItems, this.gd);
|
|
181
|
+
}
|
|
182
|
+
// ── Icons ───────────────────────────────────────────────────
|
|
183
|
+
/** Get the HD icon path key for an item. */
|
|
184
|
+
getItemIconPath(item) {
|
|
185
|
+
return getItemIconPath(item, this.gd);
|
|
186
|
+
}
|
|
187
|
+
/** Get the SD (invfile) icon name for an item. */
|
|
188
|
+
getItemIconSD(item) {
|
|
189
|
+
return getItemIconSD(item, this.gd);
|
|
190
|
+
}
|
|
191
|
+
// ── Trade DTO ───────────────────────────────────────────────
|
|
192
|
+
/** Convert an item to a TradeItemDTO for the backend. */
|
|
193
|
+
toTradeDTO(item, allItems) {
|
|
194
|
+
return toTradeDTO(item, allItems, this.gd);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inventory grid dimensions — Blizzless v105.
|
|
3
|
+
*
|
|
4
|
+
* Constants and helpers for stash/inventory/cube grid sizes.
|
|
5
|
+
*/
|
|
6
|
+
/** Shared stash grid dimensions. */
|
|
7
|
+
export declare const STASH: {
|
|
8
|
+
readonly rows: 13;
|
|
9
|
+
readonly columns: 16;
|
|
10
|
+
};
|
|
11
|
+
/** Character inventory grid dimensions. */
|
|
12
|
+
export declare const INVENTORY: {
|
|
13
|
+
readonly rows: 4;
|
|
14
|
+
readonly columns: 10;
|
|
15
|
+
};
|
|
16
|
+
/** Horadric cube grid dimensions. */
|
|
17
|
+
export declare const CUBE: {
|
|
18
|
+
readonly rows: 4;
|
|
19
|
+
readonly columns: 3;
|
|
20
|
+
};
|
|
21
|
+
/** Belt grid (4 columns, variable rows depending on belt type). */
|
|
22
|
+
export declare const BELT: {
|
|
23
|
+
readonly rows: 4;
|
|
24
|
+
readonly columns: 4;
|
|
25
|
+
};
|
|
26
|
+
/** Extended page misc tab (d2i type=1, virtual sub-page). */
|
|
27
|
+
export declare const EXTENDED_MISC: {
|
|
28
|
+
readonly rows: 10;
|
|
29
|
+
readonly columns: 10;
|
|
30
|
+
};
|
|
31
|
+
/** Grid dimensions descriptor. */
|
|
32
|
+
export interface GridSize {
|
|
33
|
+
readonly rows: number;
|
|
34
|
+
readonly columns: number;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Get grid dimensions for a storage type.
|
|
38
|
+
*
|
|
39
|
+
* @param storage Storage type: 'inventory' | 'cube' | 'stash' | 'belt'
|
|
40
|
+
*/
|
|
41
|
+
export declare function getGridSize(storage: 'inventory' | 'cube' | 'stash' | 'belt'): GridSize;
|
|
42
|
+
//# sourceMappingURL=dimensions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dimensions.d.ts","sourceRoot":"","sources":["../../src/inventory/dimensions.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,oCAAoC;AACpC,eAAO,MAAM,KAAK;;;CAAqC,CAAC;AAExD,2CAA2C;AAC3C,eAAO,MAAM,SAAS;;;CAAoC,CAAC;AAE3D,qCAAqC;AACrC,eAAO,MAAM,IAAI;;;CAAmC,CAAC;AAErD,mEAAmE;AACnE,eAAO,MAAM,IAAI;;;CAAmC,CAAC;AAErD,6DAA6D;AAC7D,eAAO,MAAM,aAAa;;;CAAqC,CAAC;AAIhE,kCAAkC;AAClC,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAOtF"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inventory grid dimensions — Blizzless v105.
|
|
3
|
+
*
|
|
4
|
+
* Constants and helpers for stash/inventory/cube grid sizes.
|
|
5
|
+
*/
|
|
6
|
+
// ─── Grid dimensions (Blizzless) ────────────────────────────────
|
|
7
|
+
/** Shared stash grid dimensions. */
|
|
8
|
+
export const STASH = { rows: 13, columns: 16 };
|
|
9
|
+
/** Character inventory grid dimensions. */
|
|
10
|
+
export const INVENTORY = { rows: 4, columns: 10 };
|
|
11
|
+
/** Horadric cube grid dimensions. */
|
|
12
|
+
export const CUBE = { rows: 4, columns: 3 };
|
|
13
|
+
/** Belt grid (4 columns, variable rows depending on belt type). */
|
|
14
|
+
export const BELT = { rows: 4, columns: 4 };
|
|
15
|
+
/** Extended page misc tab (d2i type=1, virtual sub-page). */
|
|
16
|
+
export const EXTENDED_MISC = { rows: 10, columns: 10 };
|
|
17
|
+
/**
|
|
18
|
+
* Get grid dimensions for a storage type.
|
|
19
|
+
*
|
|
20
|
+
* @param storage Storage type: 'inventory' | 'cube' | 'stash' | 'belt'
|
|
21
|
+
*/
|
|
22
|
+
export function getGridSize(storage) {
|
|
23
|
+
switch (storage) {
|
|
24
|
+
case 'inventory': return INVENTORY;
|
|
25
|
+
case 'cube': return CUBE;
|
|
26
|
+
case 'stash': return STASH;
|
|
27
|
+
case 'belt': return BELT;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=dimensions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dimensions.js","sourceRoot":"","sources":["../../src/inventory/dimensions.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,mEAAmE;AAEnE,oCAAoC;AACpC,MAAM,CAAC,MAAM,KAAK,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAW,CAAC;AAExD,2CAA2C;AAC3C,MAAM,CAAC,MAAM,SAAS,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAW,CAAC;AAE3D,qCAAqC;AACrC,MAAM,CAAC,MAAM,IAAI,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAW,CAAC;AAErD,mEAAmE;AACnE,MAAM,CAAC,MAAM,IAAI,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAW,CAAC;AAErD,6DAA6D;AAC7D,MAAM,CAAC,MAAM,aAAa,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAW,CAAC;AAUhE;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,OAAgD;IAC1E,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,WAAW,CAAC,CAAC,OAAO,SAAS,CAAC;QACnC,KAAK,MAAM,CAAC,CAAC,OAAO,IAAI,CAAC;QACzB,KAAK,OAAO,CAAC,CAAC,OAAO,KAAK,CAAC;QAC3B,KAAK,MAAM,CAAC,CAAC,OAAO,IAAI,CAAC;IAC3B,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StashGrid — occupancy grid for inventory/stash/cube placement.
|
|
3
|
+
*
|
|
4
|
+
* Ported from d2planner/src/logic/inventory.js, cleaned up as a class.
|
|
5
|
+
* Uses GameData for item base dimensions (invwidth, invheight).
|
|
6
|
+
*/
|
|
7
|
+
import type { GameData } from '../game-data/game-data.js';
|
|
8
|
+
import type { GridSize } from './dimensions.js';
|
|
9
|
+
/**
|
|
10
|
+
* A 2D occupancy grid for a storage area.
|
|
11
|
+
*
|
|
12
|
+
* Each cell is either free (0) or occupied (non-zero).
|
|
13
|
+
* Items occupy rectangular regions based on their `invwidth × invheight`.
|
|
14
|
+
*/
|
|
15
|
+
export declare class StashGrid {
|
|
16
|
+
readonly rows: number;
|
|
17
|
+
readonly columns: number;
|
|
18
|
+
/** Flat occupancy array: `cells[y * columns + x]`. 0 = free, else item ID. */
|
|
19
|
+
private cells;
|
|
20
|
+
constructor(size: GridSize);
|
|
21
|
+
constructor(rows: number, columns: number);
|
|
22
|
+
/** Check if a rectangular area is completely free. */
|
|
23
|
+
isFree(x: number, y: number, width: number, height: number): boolean;
|
|
24
|
+
/** Get the item ID at a cell, or 0 if free. */
|
|
25
|
+
at(x: number, y: number): number;
|
|
26
|
+
/** Mark a rectangular area as occupied by `itemId`. */
|
|
27
|
+
occupy(x: number, y: number, width: number, height: number, itemId?: number): void;
|
|
28
|
+
/** Free a rectangular area. */
|
|
29
|
+
free(x: number, y: number, width: number, height: number): void;
|
|
30
|
+
/** Clear the entire grid. */
|
|
31
|
+
clear(): void;
|
|
32
|
+
/**
|
|
33
|
+
* Find the first free slot (top-left corner) for an item of the given size.
|
|
34
|
+
* Scans left-to-right, top-to-bottom.
|
|
35
|
+
*
|
|
36
|
+
* @returns `{ x, y }` or `null` if no space.
|
|
37
|
+
*/
|
|
38
|
+
findFreeSlot(width: number, height: number): {
|
|
39
|
+
x: number;
|
|
40
|
+
y: number;
|
|
41
|
+
} | null;
|
|
42
|
+
/**
|
|
43
|
+
* Populate the grid from a slot array (as returned by d2i/d2s readers).
|
|
44
|
+
*
|
|
45
|
+
* @param slots Sparse array: `slots[slot] = itemId`. Slot = `y * columns + x`.
|
|
46
|
+
* @param items All items keyed by ID.
|
|
47
|
+
* @param gd GameData for item base dimensions.
|
|
48
|
+
*/
|
|
49
|
+
populate(slots: (number | string | undefined)[], items: Record<number | string, {
|
|
50
|
+
base: string;
|
|
51
|
+
}>, gd: GameData): void;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=grid.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grid.d.ts","sourceRoot":"","sources":["../../src/inventory/grid.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAIhD;;;;;GAKG;AACH,qBAAa,SAAS;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,8EAA8E;IAC9E,OAAO,CAAC,KAAK,CAAe;gBAEhB,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;IAczC,sDAAsD;IACtD,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO;IAUpE,+CAA+C;IAC/C,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM;IAOhC,uDAAuD;IACvD,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,SAAI,GAAG,IAAI;IAQ7E,+BAA+B;IAC/B,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAQ/D,6BAA6B;IAC7B,KAAK,IAAI,IAAI;IAMb;;;;;OAKG;IACH,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAW5E;;;;;;OAMG;IACH,QAAQ,CACN,KAAK,EAAE,CAAC,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC,EAAE,EACtC,KAAK,EAAE,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,EAChD,EAAE,EAAE,QAAQ,GACX,IAAI;CAwBR"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StashGrid — occupancy grid for inventory/stash/cube placement.
|
|
3
|
+
*
|
|
4
|
+
* Ported from d2planner/src/logic/inventory.js, cleaned up as a class.
|
|
5
|
+
* Uses GameData for item base dimensions (invwidth, invheight).
|
|
6
|
+
*/
|
|
7
|
+
// ─── StashGrid ──────────────────────────────────────────────────
|
|
8
|
+
/**
|
|
9
|
+
* A 2D occupancy grid for a storage area.
|
|
10
|
+
*
|
|
11
|
+
* Each cell is either free (0) or occupied (non-zero).
|
|
12
|
+
* Items occupy rectangular regions based on their `invwidth × invheight`.
|
|
13
|
+
*/
|
|
14
|
+
export class StashGrid {
|
|
15
|
+
rows;
|
|
16
|
+
columns;
|
|
17
|
+
/** Flat occupancy array: `cells[y * columns + x]`. 0 = free, else item ID. */
|
|
18
|
+
cells;
|
|
19
|
+
constructor(rowsOrSize, columns) {
|
|
20
|
+
if (typeof rowsOrSize === 'object') {
|
|
21
|
+
this.rows = rowsOrSize.rows;
|
|
22
|
+
this.columns = rowsOrSize.columns;
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
this.rows = rowsOrSize;
|
|
26
|
+
this.columns = columns;
|
|
27
|
+
}
|
|
28
|
+
this.cells = new Float64Array(this.rows * this.columns);
|
|
29
|
+
}
|
|
30
|
+
// ─── Query ──────────────────────────────────────────────────
|
|
31
|
+
/** Check if a rectangular area is completely free. */
|
|
32
|
+
isFree(x, y, width, height) {
|
|
33
|
+
if (x < 0 || y < 0 || x + width > this.columns || y + height > this.rows)
|
|
34
|
+
return false;
|
|
35
|
+
for (let dy = 0; dy < height; dy++) {
|
|
36
|
+
for (let dx = 0; dx < width; dx++) {
|
|
37
|
+
if (this.cells[(y + dy) * this.columns + (x + dx)] !== 0)
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
/** Get the item ID at a cell, or 0 if free. */
|
|
44
|
+
at(x, y) {
|
|
45
|
+
if (x < 0 || y < 0 || x >= this.columns || y >= this.rows)
|
|
46
|
+
return 0;
|
|
47
|
+
return this.cells[y * this.columns + x];
|
|
48
|
+
}
|
|
49
|
+
// ─── Mutation ─────────────────────────────────────────────────
|
|
50
|
+
/** Mark a rectangular area as occupied by `itemId`. */
|
|
51
|
+
occupy(x, y, width, height, itemId = 1) {
|
|
52
|
+
for (let dy = 0; dy < height; dy++) {
|
|
53
|
+
for (let dx = 0; dx < width; dx++) {
|
|
54
|
+
this.cells[(y + dy) * this.columns + (x + dx)] = itemId;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/** Free a rectangular area. */
|
|
59
|
+
free(x, y, width, height) {
|
|
60
|
+
for (let dy = 0; dy < height; dy++) {
|
|
61
|
+
for (let dx = 0; dx < width; dx++) {
|
|
62
|
+
this.cells[(y + dy) * this.columns + (x + dx)] = 0;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/** Clear the entire grid. */
|
|
67
|
+
clear() {
|
|
68
|
+
this.cells.fill(0);
|
|
69
|
+
}
|
|
70
|
+
// ─── Placement search ────────────────────────────────────────
|
|
71
|
+
/**
|
|
72
|
+
* Find the first free slot (top-left corner) for an item of the given size.
|
|
73
|
+
* Scans left-to-right, top-to-bottom.
|
|
74
|
+
*
|
|
75
|
+
* @returns `{ x, y }` or `null` if no space.
|
|
76
|
+
*/
|
|
77
|
+
findFreeSlot(width, height) {
|
|
78
|
+
for (let y = 0; y <= this.rows - height; y++) {
|
|
79
|
+
for (let x = 0; x <= this.columns - width; x++) {
|
|
80
|
+
if (this.isFree(x, y, width, height))
|
|
81
|
+
return { x, y };
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
// ─── Populate from items ──────────────────────────────────────
|
|
87
|
+
/**
|
|
88
|
+
* Populate the grid from a slot array (as returned by d2i/d2s readers).
|
|
89
|
+
*
|
|
90
|
+
* @param slots Sparse array: `slots[slot] = itemId`. Slot = `y * columns + x`.
|
|
91
|
+
* @param items All items keyed by ID.
|
|
92
|
+
* @param gd GameData for item base dimensions.
|
|
93
|
+
*/
|
|
94
|
+
populate(slots, items, gd) {
|
|
95
|
+
this.clear();
|
|
96
|
+
for (let slot = 0; slot < slots.length; slot++) {
|
|
97
|
+
const id = slots[slot];
|
|
98
|
+
if (id == null)
|
|
99
|
+
continue;
|
|
100
|
+
const item = items[id];
|
|
101
|
+
if (!item)
|
|
102
|
+
continue;
|
|
103
|
+
const baseItem = gd.items[item.base];
|
|
104
|
+
const w = baseItem?.invwidth || 1;
|
|
105
|
+
const h = baseItem?.invheight || 1;
|
|
106
|
+
const x = slot % this.columns;
|
|
107
|
+
const y = Math.floor(slot / this.columns);
|
|
108
|
+
// Grid stores numeric IDs; map preset string codes to a hashed numeric
|
|
109
|
+
// sentinel so the grid can still mark cells occupied.
|
|
110
|
+
const numericId = typeof id === 'number'
|
|
111
|
+
? id
|
|
112
|
+
: id.split('').reduce((s, c) => s * 31 + c.charCodeAt(0), 1) & 0x7fffffff;
|
|
113
|
+
this.occupy(x, y, w, h, numericId);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=grid.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grid.js","sourceRoot":"","sources":["../../src/inventory/grid.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { STASH, INVENTORY, CUBE, BELT, EXTENDED_MISC, getGridSize, type GridSize, } from './dimensions.js';
|
|
2
|
+
export { StashGrid } from './grid.js';
|
|
3
|
+
export { canPlaceItem, findFreeSlot, findFreeSlotInStash, placeItem, removeItem, buildGrid, type PlacementItem, } from './placement.js';
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/inventory/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EACL,SAAS,EACT,IAAI,EACJ,IAAI,EACJ,aAAa,EACb,WAAW,EACX,KAAK,QAAQ,GACd,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,mBAAmB,EACnB,SAAS,EACT,UAAU,EACV,SAAS,EACT,KAAK,aAAa,GACnB,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { STASH, INVENTORY, CUBE, BELT, EXTENDED_MISC, getGridSize, } from './dimensions.js';
|
|
2
|
+
export { StashGrid } from './grid.js';
|
|
3
|
+
export { canPlaceItem, findFreeSlot, findFreeSlotInStash, placeItem, removeItem, buildGrid, } from './placement.js';
|
|
4
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/inventory/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EACL,SAAS,EACT,IAAI,EACJ,IAAI,EACJ,aAAa,EACb,WAAW,GAEZ,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,mBAAmB,EACnB,SAAS,EACT,UAAU,EACV,SAAS,GAEV,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Placement logic — inventory/stash item placement helpers.
|
|
3
|
+
*
|
|
4
|
+
* Ported from d2planner/src/logic/inventory.js.
|
|
5
|
+
* Uses GameData for item base dimensions.
|
|
6
|
+
*/
|
|
7
|
+
import type { GameData } from '../game-data/game-data.js';
|
|
8
|
+
import { StashGrid } from './grid.js';
|
|
9
|
+
import type { GridSize } from './dimensions.js';
|
|
10
|
+
/** Minimal item descriptor needed for placement. */
|
|
11
|
+
export interface PlacementItem {
|
|
12
|
+
base: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Check if an item can be placed at a specific position in a grid.
|
|
16
|
+
*
|
|
17
|
+
* @param grid The occupancy grid.
|
|
18
|
+
* @param x Column position.
|
|
19
|
+
* @param y Row position.
|
|
20
|
+
* @param item The item to check.
|
|
21
|
+
* @param gd GameData for item dimensions.
|
|
22
|
+
*/
|
|
23
|
+
export declare function canPlaceItem(grid: StashGrid, x: number, y: number, item: PlacementItem, gd: GameData): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Find a free slot for an item in a grid.
|
|
26
|
+
*
|
|
27
|
+
* @param grid The occupancy grid.
|
|
28
|
+
* @param item The item to place.
|
|
29
|
+
* @param gd GameData for item dimensions.
|
|
30
|
+
* @returns `{ x, y }` or `null` if no space.
|
|
31
|
+
*/
|
|
32
|
+
export declare function findFreeSlot(grid: StashGrid, item: PlacementItem, gd: GameData): {
|
|
33
|
+
x: number;
|
|
34
|
+
y: number;
|
|
35
|
+
} | null;
|
|
36
|
+
/**
|
|
37
|
+
* Find a free slot for an item across multiple stash pages.
|
|
38
|
+
*
|
|
39
|
+
* @param grids Array of grids, one per stash page.
|
|
40
|
+
* @param item The item to place.
|
|
41
|
+
* @param gd GameData for item dimensions.
|
|
42
|
+
* @returns `{ pageIndex, x, y }` or `null` if no space in any page.
|
|
43
|
+
*/
|
|
44
|
+
export declare function findFreeSlotInStash(grids: StashGrid[], item: PlacementItem, gd: GameData): {
|
|
45
|
+
pageIndex: number;
|
|
46
|
+
x: number;
|
|
47
|
+
y: number;
|
|
48
|
+
} | null;
|
|
49
|
+
/**
|
|
50
|
+
* Place an item in a grid, marking cells as occupied.
|
|
51
|
+
*
|
|
52
|
+
* @returns `true` if placed, `false` if the space is not free.
|
|
53
|
+
*/
|
|
54
|
+
export declare function placeItem(grid: StashGrid, x: number, y: number, item: PlacementItem, gd: GameData, itemId?: number): boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Remove an item from a grid, freeing its cells.
|
|
57
|
+
*/
|
|
58
|
+
export declare function removeItem(grid: StashGrid, x: number, y: number, item: PlacementItem, gd: GameData): void;
|
|
59
|
+
/**
|
|
60
|
+
* Build a StashGrid populated from a slot array.
|
|
61
|
+
*
|
|
62
|
+
* @param size Grid dimensions.
|
|
63
|
+
* @param slots Sparse array: `slots[index] = itemId`.
|
|
64
|
+
* @param items All items keyed by ID.
|
|
65
|
+
* @param gd GameData for item dimensions.
|
|
66
|
+
*/
|
|
67
|
+
export declare function buildGrid(size: GridSize, slots: (number | string | undefined)[], items: Record<number | string, PlacementItem>, gd: GameData): StashGrid;
|
|
68
|
+
//# sourceMappingURL=placement.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"placement.d.ts","sourceRoot":"","sources":["../../src/inventory/placement.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAIhD,oDAAoD;AACpD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;CACd;AAID;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,SAAS,EACf,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,IAAI,EAAE,aAAa,EACnB,EAAE,EAAE,QAAQ,GACX,OAAO,CAGT;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,SAAS,EACf,IAAI,EAAE,aAAa,EACnB,EAAE,EAAE,QAAQ,GACX;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAGjC;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,SAAS,EAAE,EAClB,IAAI,EAAE,aAAa,EACnB,EAAE,EAAE,QAAQ,GACX;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAMpD;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,SAAS,EACf,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,IAAI,EAAE,aAAa,EACnB,EAAE,EAAE,QAAQ,EACZ,MAAM,SAAI,GACT,OAAO,CAKT;AAED;;GAEG;AACH,wBAAgB,UAAU,CACxB,IAAI,EAAE,SAAS,EACf,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,IAAI,EAAE,aAAa,EACnB,EAAE,EAAE,QAAQ,GACX,IAAI,CAGN;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,QAAQ,EACd,KAAK,EAAE,CAAC,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC,EAAE,EACtC,KAAK,EAAE,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,aAAa,CAAC,EAC7C,EAAE,EAAE,QAAQ,GACX,SAAS,CAIX"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Placement logic — inventory/stash item placement helpers.
|
|
3
|
+
*
|
|
4
|
+
* Ported from d2planner/src/logic/inventory.js.
|
|
5
|
+
* Uses GameData for item base dimensions.
|
|
6
|
+
*/
|
|
7
|
+
import { StashGrid } from './grid.js';
|
|
8
|
+
// ─── Public API ─────────────────────────────────────────────────
|
|
9
|
+
/**
|
|
10
|
+
* Check if an item can be placed at a specific position in a grid.
|
|
11
|
+
*
|
|
12
|
+
* @param grid The occupancy grid.
|
|
13
|
+
* @param x Column position.
|
|
14
|
+
* @param y Row position.
|
|
15
|
+
* @param item The item to check.
|
|
16
|
+
* @param gd GameData for item dimensions.
|
|
17
|
+
*/
|
|
18
|
+
export function canPlaceItem(grid, x, y, item, gd) {
|
|
19
|
+
const { w, h } = getItemSize(item, gd);
|
|
20
|
+
return grid.isFree(x, y, w, h);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Find a free slot for an item in a grid.
|
|
24
|
+
*
|
|
25
|
+
* @param grid The occupancy grid.
|
|
26
|
+
* @param item The item to place.
|
|
27
|
+
* @param gd GameData for item dimensions.
|
|
28
|
+
* @returns `{ x, y }` or `null` if no space.
|
|
29
|
+
*/
|
|
30
|
+
export function findFreeSlot(grid, item, gd) {
|
|
31
|
+
const { w, h } = getItemSize(item, gd);
|
|
32
|
+
return grid.findFreeSlot(w, h);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Find a free slot for an item across multiple stash pages.
|
|
36
|
+
*
|
|
37
|
+
* @param grids Array of grids, one per stash page.
|
|
38
|
+
* @param item The item to place.
|
|
39
|
+
* @param gd GameData for item dimensions.
|
|
40
|
+
* @returns `{ pageIndex, x, y }` or `null` if no space in any page.
|
|
41
|
+
*/
|
|
42
|
+
export function findFreeSlotInStash(grids, item, gd) {
|
|
43
|
+
for (let i = 0; i < grids.length; i++) {
|
|
44
|
+
const slot = findFreeSlot(grids[i], item, gd);
|
|
45
|
+
if (slot)
|
|
46
|
+
return { pageIndex: i, ...slot };
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Place an item in a grid, marking cells as occupied.
|
|
52
|
+
*
|
|
53
|
+
* @returns `true` if placed, `false` if the space is not free.
|
|
54
|
+
*/
|
|
55
|
+
export function placeItem(grid, x, y, item, gd, itemId = 1) {
|
|
56
|
+
const { w, h } = getItemSize(item, gd);
|
|
57
|
+
if (!grid.isFree(x, y, w, h))
|
|
58
|
+
return false;
|
|
59
|
+
grid.occupy(x, y, w, h, itemId);
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Remove an item from a grid, freeing its cells.
|
|
64
|
+
*/
|
|
65
|
+
export function removeItem(grid, x, y, item, gd) {
|
|
66
|
+
const { w, h } = getItemSize(item, gd);
|
|
67
|
+
grid.free(x, y, w, h);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Build a StashGrid populated from a slot array.
|
|
71
|
+
*
|
|
72
|
+
* @param size Grid dimensions.
|
|
73
|
+
* @param slots Sparse array: `slots[index] = itemId`.
|
|
74
|
+
* @param items All items keyed by ID.
|
|
75
|
+
* @param gd GameData for item dimensions.
|
|
76
|
+
*/
|
|
77
|
+
export function buildGrid(size, slots, items, gd) {
|
|
78
|
+
const grid = new StashGrid(size);
|
|
79
|
+
grid.populate(slots, items, gd);
|
|
80
|
+
return grid;
|
|
81
|
+
}
|
|
82
|
+
// ─── Internal ───────────────────────────────────────────────────
|
|
83
|
+
/** Get item width and height from GameData. */
|
|
84
|
+
function getItemSize(item, gd) {
|
|
85
|
+
const baseItem = gd.items[item.base];
|
|
86
|
+
const w = baseItem?.invwidth || 1;
|
|
87
|
+
const h = baseItem?.invheight || 1;
|
|
88
|
+
return { w, h };
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=placement.js.map
|