-
Notifications
You must be signed in to change notification settings - Fork 15
Expand file tree
/
Copy pathsplitmap.mjs
More file actions
167 lines (144 loc) · 5.09 KB
/
Copy pathsplitmap.mjs
File metadata and controls
167 lines (144 loc) · 5.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
/**
* Created by Jerome Renaux (jerome.renaux@gmail.com) on 07-02-18.
* Modified by Jakub Kasprzyk (github.com/neu5)
*/
import { existsSync, mkdirSync, readFile, writeFile } from "fs";
import { join } from "path";
import rimraf from "rimraf";
import optimist from "optimist";
import { fileURLToPath } from "url";
const getDirname = (meta) => fileURLToPath(meta.url);
const dirname = getDirname(import.meta);
const splitMap = (
fullFileName,
out = "chunks",
chunkWidth = 20,
chunkHeight = 20,
verbose = false
) => {
if (!fullFileName) {
console.log(`ERROR : No file name specified!
-i = path to JSON file of the map to split, relative to assets/map (with or without json extension)
-o = (optional) name of directory where chunks have to be generated (default assets/map/chunks)
-w = (optional) width of the chunks, in tiles (default ${chunkWidth})
-h = (optional) height of the chunks, in tiles (default ${chunkHeight})
-v = (optional) verbose, print out the progress of creating the chunks`);
return;
}
const fileName =
fullFileName.substr(-5) === ".json"
? fullFileName.slice(0, -5)
: fullFileName;
const mapsPath = join("..", "..", "assets", "map");
const outputDirectory = join(dirname, mapsPath, out);
rimraf.sync(outputDirectory);
console.log(`Output directory ${out} cleared`);
if (!existsSync(outputDirectory)) {
mkdirSync(outputDirectory);
}
readFile(
join(dirname, mapsPath, `${fileName}.json`),
"utf8",
(readMapErr, data) => {
if (readMapErr) {
throw readMapErr;
}
const map = JSON.parse(data);
const mapWidth = map.width;
const mapHeight = map.height;
const nbChunksX = Math.ceil(mapWidth / chunkWidth);
const nbChunksY = Math.ceil(mapHeight / chunkHeight);
const nbChunks = nbChunksX * nbChunksY;
console.log(
`Splitting into ${nbChunks} chunks (${nbChunksX} x ${nbChunksY}) of size (${chunkWidth} x ${chunkHeight})`
);
console.log(`Writing to ${outputDirectory}`);
// Creates a master file that contains information needed to properly manage the chunks
const master = {
tilesets: map.tilesets, // Up to you to decide if having the tilesets data in the master file is useful or not, adapt accordingly (in this case it's not)
chunkWidth,
chunkHeight,
nbChunksX,
nbChunksY,
nbLayers: map.layers.length,
mapHeight: map.height,
mapWidth: map.width,
tileWidth: map.tilewidth,
tileHeight: map.tileheight,
};
const tilesets = map.tilesets.map((tileset) => ({
...tileset,
image: join("..", tileset.image),
}));
writeFile(
join(outputDirectory, "master.json"),
JSON.stringify(master),
(writeMasterFileErr) => {
if (writeMasterFileErr) {
throw writeMasterFileErr;
}
console.log("Master file written");
}
);
let counter = 0;
for (let i = 0; i < nbChunks; i += 1) {
const chunk = {
...map,
layers: map.layers.map((layer) => ({
...layer,
data: [...layer.data],
})),
};
// Compute the coordinates of the top-left corner of the chunk in the initial map
const x = (i % nbChunksX) * chunkWidth;
const y = Math.floor(i / nbChunksX) * chunkHeight;
chunk.width = Math.min(chunkWidth, mapWidth - x);
chunk.height = Math.min(chunkHeight, mapHeight - y);
chunk.id = i;
// Compute the index of the tiles array of the initial map that corresponds to the top-left tile of the chunk
const liststart = mapWidth * y + x;
for (let j = 0; j < chunk.layers.length; j += 1) {
// Scan all layers one by one
const layer = chunk.layers[j];
layer.width = chunk.width;
layer.height = chunk.height;
if (layer.type === "tilelayer") {
let tmpdata = [];
// In the initial tiles array, fetch the "slices" of tiles that belong to the chunk of interest
for (let yi = 0; yi < layer.height; yi += 1) {
const begin = liststart + yi * mapWidth;
const end = begin + layer.width;
const line = layer.data.slice(begin, end);
tmpdata = tmpdata.concat(line);
}
layer.data = tmpdata;
}
}
// Update tileset paths
chunk.tilesets = tilesets;
if (verbose) {
console.log(
`writing chunk ${i} from ${nbChunks} created (${
(i / nbChunks) * 100
}%)`
);
}
writeFile(
join(outputDirectory, `chunk${i}.json`),
JSON.stringify(chunk),
function (writeChunkErr) { // eslint-disable-line
if (writeChunkErr) {
throw writeChunkErr;
}
counter += 1;
if (counter === nbChunks) {
console.log("All chunks created");
}
}
);
}
}
);
};
const { argv } = optimist;
splitMap(argv.i, argv.o, argv.w, argv.h, argv.v);