UNPKG

29.1 kBJavaScriptView Raw
1const common = require('@screeps/common');
2const C = common.configManager.config.common.constants;
3const config = common.configManager.config;
4const db = common.storage.db;
5const env = common.storage.env;
6const pubsub = common.storage.pubsub;
7const utils = require('../utils');
8const q = require('q');
9const fs = require('fs');
10const path = require('path');
11const _ = require('lodash');
12const zlib = require('zlib');
13
14exports.generateRoom = utils.withHelp([
15 `generateRoom(roomName, [opts]) - Generate a new room at the specified location. 'opts' is an object with the following optional properties:\r
16 * exits - an object with exit coordinates arrays, e.g. {top: [20,21,23], right: [], bottom: [27,28,29,40,41]}, default is random\r
17 * terrainType - the type of generated landscape, a number from 1 to 28, default is random\r
18 * swampType - the type of generated swamp configuration, a number from 0 to 14, default is random\r
19 * sources - the amount of sources in the room, default is random from 1 to 2\r
20 * mineral - the type of the mineral deposit in this room or false if no mineral, default is random type\r
21 * controller - whether this room should have the controller, default is true\r
22 * keeperLairs - whether this room should have source keeper lairs, default is false`,
23 function generateRoom(roomName, opts) {
24 opts = opts || {};
25
26 opts.exits = opts.exits || {};
27
28 if(!/^[WE]\d+[NS]\d+$/.test(roomName)) {
29 return q.reject("Invalid room name");
30 }
31
32 function _exitsArray(terrain, x, y) {
33 var exits = [];
34 for(var i=0;i<50;i++) {
35 if(!common.checkTerrain(terrain, x === undefined ? i : x, y === undefined ? i : y, C.TERRAIN_MASK_WALL)) {
36 exits.push(i);
37 }
38 }
39 return exits;
40 }
41
42 function _genExit() {
43 var exitLength = Math.floor(Math.random()*43)+1;
44 var intervalsCnt = [0,0,1,1,2][Math.floor(Math.random()*5)];
45 var exit = [],
46 exitStart = Math.floor(Math.random() * (46 - exitLength))+2,
47 intervals = {},
48 curStart = exitStart;
49
50 for(var j=0; j<intervalsCnt; j++) {
51 curStart += Math.floor(Math.random() * (exitLength/(intervalsCnt*2)))+5;
52 var length = Math.floor(Math.random() * (exitLength/(intervalsCnt*2)))+5;
53 if(length + curStart >= exitStart + exitLength - 5) {
54 length = exitStart + exitLength - curStart - 5;
55 }
56 intervals[j] = {
57 start: curStart,
58 length
59 };
60 curStart += length+1;
61 }
62
63 for(var x=exitStart; x<=exitStart+exitLength; x++) {
64 if(intervalsCnt > 0) {
65 if(intervals[0].length>0 && x >= intervals[0].start && x <= intervals[0].start+intervals[0].length) {
66 continue;
67 }
68 if(intervalsCnt > 1 && intervals[1].length>0 && x >= intervals[1].start && x <= intervals[1].start+intervals[1].length) {
69 continue;
70 }
71 }
72 if(x < 2 || x > 47) {
73 continue;
74 }
75 exit.push(x);
76 }
77
78 return exit;
79 }
80
81 function _matchExitWithNeighbors(exits, dir, neighbor) {
82 var x,y;
83 if(dir == 'top') {
84 y = 49;
85 }
86 if(dir == 'right') {
87 x = 0;
88 }
89 if(dir == 'bottom') {
90 y = 0;
91 }
92 if(dir == 'left') {
93 x = 49;
94 }
95 if(exits[dir]) {
96 if(neighbor) {
97 var neighborExits = _exitsArray(neighbor.terrain, x, y);
98 return neighborExits.length == exits[dir].length && _.intersection(neighborExits, exits[dir]).length == neighborExits.length;
99 }
100 else {
101 return true;
102 }
103 }
104 else {
105 if(neighbor) {
106 exits[dir] = _exitsArray(neighbor.terrain, x, y);
107 }
108 else {
109 exits[dir] = _genExit();
110 }
111 return true;
112 }
113 }
114
115 function _checkFlood(terrain) {
116
117 var startX, startY;
118
119 for(var x=0; x<50; x++) {
120 for(var y=0; y<50; y++) {
121 if(!terrain[y][x].wall) {
122 startX = x;
123 startY = y;
124 break;
125 }
126 }
127 if(startX && startY) {
128 break;
129 }
130 }
131
132 var visited = {};
133 for(var y=0; y<50; y++) {
134 visited[y] = {};
135 for (var x = 0; x < 50; x++) {
136 visited[y][x] = false;
137 }
138 }
139
140 var list = [[startX, startY]];
141 do {
142 var i = list.pop(),
143 x = i[0], y = i[1];
144
145 visited[y][x] = true;
146 for(var dx=-1; dx<=1; dx++) {
147 for(var dy=-1; dy<=1; dy++) {
148 if(!dx && !dy) {
149 continue;
150 }
151 if(x+dx >= 0 && x+dx <= 49 && y+dy >= 0 && y+dy <= 49 && !terrain[y+dy][x+dx].wall && !visited[y+dy][x+dx]) {
152 visited[y+dy][x+dx] = true;
153 list.push([x+dx,y+dy]);
154 }
155 }
156 }
157 }
158 while(list.length > 0);
159
160 for(var y=0; y<50; y++) {
161 for (var x = 0; x < 50; x++) {
162 if(!terrain[y][x].wall && !visited[y][x]) {
163 return false;
164 }
165 }
166 }
167
168 return true;
169 }
170
171 function _smoothTerrain(terrain, factor, key) {
172 var newTerrain = {};
173
174 for(var y=0; y<50; y++) {
175 newTerrain[y] = {};
176 for(var x=0; x<50; x++) {
177 newTerrain[y][x] = _.clone(terrain[y][x]);
178 var cnt = 0;
179 for(var dx=-1;dx<=1;dx++) {
180 for(var dy=-1;dy<=1;dy++) {
181 if(key == 'wall' && (x+dx < 0 || y+dy < 0 || x+dx > 49 || y+dy > 49) ||
182 x+dx >= 0 && x+dx <= 49 && y+dy >= 0 && y+dy <= 49 && terrain[y+dy][x+dx][key]) {
183 cnt++;
184 }
185 }
186 }
187 newTerrain[y][x][key] = cnt >= factor;
188 if(key == 'wall') {
189 if(x == 0 || x == 49 || y == 0 || y == 49) {
190 newTerrain[y][x].wall = true;
191 }
192 if(terrain[y][x].forceOpen) {
193 newTerrain[y][x].wall = false;
194 }
195 }
196 }
197 }
198
199 return newTerrain;
200 }
201
202 function _genTerrain(wallType, swampType, exits, sources, controller, keeperLair) {
203
204 var types = {
205 1: {fill: 0.4, smooth: 10, factor: 5},
206 2: {fill: 0.2, smooth: 20, factor: 4},
207 3: {fill: 0.2, smooth: 20, factor: 4},
208 4: {fill: 0.3, smooth: 18, factor: 4},
209 5: {fill: 0.3, smooth: 10, factor: 4},
210 6: {fill: 0.3, smooth: 10, factor: 4},
211 7: {fill: 0.3, smooth: 10, factor: 4},
212 8: {fill: 0.35, smooth: 15, factor: 4},
213 9: {fill: 0.3, smooth: 2, factor: 4},
214 10: {fill: 0.35, smooth: 2, factor: 4},
215 11: {fill: 0.35, smooth: 5, factor: 4},
216 12: {fill: 0.35, smooth: 5, factor: 4},
217 13: {fill: 0.25, smooth: 5, factor: 4},
218
219 14: {fill: 0.4, smooth: 3, factor: 5},
220 15: {fill: 0.5, smooth: 3, factor: 5},
221 16: {fill: 0.45, smooth: 4, factor: 5},
222 17: {fill: 0.45, smooth: 6, factor: 5},
223 18: {fill: 0.45, smooth: 10, factor: 5},
224 19: {fill: 0.5, smooth: 10, factor: 5},
225
226 20: {fill: 0.4, smooth: 3, factor: 5},
227 21: {fill: 0.5, smooth: 2, factor: 5},
228 22: {fill: 0.45, smooth: 4, factor: 5},
229 23: {fill: 0.45, smooth: 6, factor: 5},
230 24: {fill: 0.45, smooth: 10, factor: 5},
231 25: {fill: 0.5, smooth: 10, factor: 5},
232
233 26: {fill: 0.45, smooth: 10, factor: 5},
234 27: {fill: 0.45, smooth: 6, factor: 5},
235 28: {fill: 0.2, smooth: 20, factor: 4},
236 };
237
238 var swampTypes = {
239 1: {fill: 0.3, smooth: 3, factor: 5},
240 2: {fill: 0.35, smooth: 3, factor: 5},
241 3: {fill: 0.45, smooth: 3, factor: 5},
242 4: {fill: 0.25, smooth: 1, factor: 5},
243 5: {fill: 0.25, smooth: 30, factor: 4},
244 6: {fill: 0.52, smooth: 30, factor: 5},
245 7: {fill: 0.45, smooth: 3, factor: 5},
246 //7: {fill: 0.60, smooth: 3, factor: 5},
247 8: {fill: 0.3, smooth: 1, factor: 5},
248 9: {fill: 0.3, smooth: 1, factor: 4},
249 10: {fill: 0.3, smooth: 3, factor: 5},
250 11: {fill: 0.3, smooth: 3, factor: 5},
251 12: {fill: 0.3, smooth: 1, factor: 5},
252 13: {fill: 0.25, smooth: 1, factor: 5},
253 14: {fill: 0.35, smooth: 3, factor: 5},
254 };
255
256 var terrain, tries = 0;
257
258 do {
259 terrain = {};
260 tries++;
261
262 if(tries > 100) {
263 wallType = Math.floor(Math.random()*27)+1;
264 tries = 0;
265 }
266
267 for (var y = 0; y < 50; y++) {
268 terrain[y] = {};
269 for (var x = 0; x < 50; x++) {
270 terrain[y][x] = {};
271 }
272 }
273 for (var y = 0; y < 50; y++) {
274 for (var x = 0; x < 50; x++) {
275 if (y == 0 && _.isArray(exits.top) && _.contains(exits.top, x)) {
276 terrain[y][x].forceOpen = true;
277 terrain[y + 1][x].forceOpen = true;
278 terrain[y][x].exit = true;
279 continue;
280 }
281 if (y == 49 && _.isArray(exits.bottom) && _.contains(exits.bottom, x)) {
282 terrain[y][x].forceOpen = true;
283 terrain[y - 1][x].forceOpen = true;
284 terrain[y][x].exit = true;
285 continue;
286 }
287 if (x == 0 && _.isArray(exits.left) && _.contains(exits.left, y)) {
288 terrain[y][x].forceOpen = true;
289 terrain[y][x + 1].forceOpen = true;
290 terrain[y][x].exit = true;
291 continue;
292 }
293
294 if (x == 49 && _.isArray(exits.right) && _.contains(exits.right, y)) {
295 terrain[y][x].forceOpen = true;
296 terrain[y][x - 1].forceOpen = true;
297 terrain[y][x].exit = true;
298 continue;
299 }
300 terrain[y][x].wall = Math.random() < types[wallType].fill;
301 terrain[y][x].swamp = swampType ? Math.random() < swampTypes[swampType].fill : false;
302 }
303 }
304
305 for (var i = 0; i < types[wallType].smooth; i++) {
306 terrain = _smoothTerrain(terrain, types[wallType].factor, 'wall');
307 }
308 }
309 while(!_checkFlood(terrain));
310
311 if(swampType) {
312 for (var i = 0; i < swampTypes[swampType].smooth; i++) {
313 terrain = _smoothTerrain(terrain, swampTypes[swampType].factor, 'swamp');
314 }
315 }
316
317 for(var i=0; i<sources; i++) {
318
319 var x,y;
320 var tries = 0;
321
322 do {
323
324 tries++;
325
326 x = Math.floor(Math.random() * 44) + 3;
327 y = Math.floor(Math.random() * 44) + 3;
328
329 var passNearby = false;
330 for(var dx=-1; dx<=1; dx++) {
331 for(var dy=-1; dy<=1; dy++) {
332 if(x+dx < 0 || y+dy < 0 || x+dx > 49 || y+dy > 49) {
333 continue;
334 }
335 if(!terrain[y+dy][x+dx].wall) {
336 passNearby = true;
337 break;
338 }
339 }
340 }
341
342 if(tries > 1000) {
343 return _genTerrain(Math.floor(Math.random() * 27) + 1, swampType, exits, sources, controller, keeperLair);
344 }
345 }
346 while(!terrain[y][x].wall || !passNearby);
347
348 terrain[y][x].source = true;
349
350 if(keeperLair) {
351
352 var lairSpots = [],
353 list = [[x, y]],
354 visited = {[`${x},${y}`]: 0};
355
356 do {
357 var [cx,cy] = list.pop();
358 for (var dx = -1; dx <= 1; dx++) {
359 for (var dy = -1; dy <= 1; dy++) {
360 if (!dx && !dy || !_.isUndefined(visited[`${cx + dx},${cy + dy}`])) {
361 continue;
362 }
363 if (cx + dx < 0 || cy + dy < 0 || cx + dx > 49 || cy + dy > 49) {
364 continue;
365 }
366 var distance = visited[`${cx},${cy}`] + 1;
367 visited[`${cx + dx},${cy + dy}`] = distance;
368 if (distance >= 3 && distance <= 5 && terrain[cy + dy][cx + dx].wall && !terrain[cy + dy][cx + dx].source &&
369 (cx + dx > 0 && cx + dx < 49 && cy + dy > 0 && cy + dy < 49)) {
370 lairSpots.push([cx + dx, cy + dy]);
371 }
372 if (!terrain[cy + dy][cx + dx].wall && distance < 5) {
373 list.push([cx + dx, cy + dy]);
374 }
375 }
376 }
377 }
378 while (list.length > 0);
379
380
381 if (lairSpots.length > 0) {
382 terrain[y][x].source = true;
383 lairSpots = _.shuffle(lairSpots);
384 terrain[lairSpots[0][1]][lairSpots[0][0]].keeperLair = true;
385 }
386 else {
387 return _genTerrain(Math.floor(Math.random() * 27) + 1, swampType, exits, sources, controller, keeperLair);
388 }
389 }
390 }
391
392 if(controller) {
393 var x,y;
394 do {
395 x = Math.floor(Math.random() * 40) + 5;
396 y = Math.floor(Math.random() * 40) + 5;
397 var passNearby = false;
398 for(var dx=-1; dx<=1; dx++) {
399 for(var dy=-1; dy<=1; dy++) {
400 if(x+dx < 0 || y+dy < 0 || x+dx > 49 || y+dy > 49) {
401 continue;
402 }
403 if(!terrain[y+dy][x+dx].wall) {
404 passNearby = true;
405 break;
406 }
407 }
408 }
409 }
410 while(!terrain[y][x].wall || !passNearby || terrain[y][x].source || terrain[y][x].keeperLair);
411 terrain[y][x].controller = true;
412 }
413
414 return terrain;
415 }
416
417 return db.rooms.findOne({_id: roomName})
418 .then(data => data ? q.reject('This room already exists') : undefined)
419 .then(() => {
420 var [x,y] = utils.roomNameToXY(roomName);
421 return q.all([
422 db['rooms.terrain'].findOne({room: utils.roomNameFromXY(x, y - 1)}),
423 db['rooms.terrain'].findOne({room: utils.roomNameFromXY(x + 1, y)}),
424 db['rooms.terrain'].findOne({room: utils.roomNameFromXY(x, y + 1)}),
425 db['rooms.terrain'].findOne({room: utils.roomNameFromXY(x - 1, y)})
426 ]);
427 })
428 .then(neighborRooms => {
429 if(!_matchExitWithNeighbors(opts.exits, 'top', neighborRooms[0])) {
430 return q.reject(`Exits in room ${neighborRooms[0].room} don't match`);
431 }
432 if(!_matchExitWithNeighbors(opts.exits, 'right', neighborRooms[1])) {
433 return q.reject(`Exits in room ${neighborRooms[1].room} don't match`);
434 }
435 if(!_matchExitWithNeighbors(opts.exits, 'bottom', neighborRooms[2])) {
436 return q.reject(`Exits in room ${neighborRooms[2].room} don't match`);
437 }
438 if(!_matchExitWithNeighbors(opts.exits, 'left', neighborRooms[3])) {
439 return q.reject(`Exits in room ${neighborRooms[3].room} don't match`);
440 }
441
442 opts.exits.top = opts.exits.top || [];
443 opts.exits.left = opts.exits.left || [];
444 opts.exits.bottom = opts.exits.bottom || [];
445 opts.exits.right = opts.exits.right || [];
446
447 if(opts.terrainType === undefined) {
448 opts.terrainType = Math.floor(Math.random() * 27) + 1;
449 }
450 if(opts.swampType === undefined) {
451 opts.swampType = Math.floor(Math.random() * 14);
452 }
453 if(opts.sources === undefined) {
454 opts.sources = Math.random() > 0.5 ? 1 : 2;
455 }
456 if(opts.controller === undefined) {
457 opts.controller = true;
458 }
459 if(opts.keeperLairs === undefined) {
460 opts.keeperLairs = false;
461 }
462
463 var roomData = _genTerrain(opts.terrainType, opts.swampType, opts.exits, opts.sources, opts.controller, opts.keeperLairs);
464
465 var objects = [], terrain = [], x, y, sourceKeepers = false;
466
467 for (var y in roomData) {
468 y = parseInt(y);
469 for (var x in roomData[y]) {
470 x = parseInt(x);
471 if (roomData[y][x].wall) {
472 terrain.push({type: 'wall', x, y});
473 }
474 if (roomData[y][x].source) {
475 objects.push({
476 room: roomName,
477 type: 'source',
478 x,
479 y,
480 "energy": C.SOURCE_ENERGY_NEUTRAL_CAPACITY,
481 "energyCapacity": C.SOURCE_ENERGY_NEUTRAL_CAPACITY,
482 "ticksToRegeneration": C.ENERGY_REGEN_TIME
483 });
484 }
485 if (roomData[y][x].controller) {
486 objects.push({room: roomName, type: 'controller', x, y, level: 0});
487 }
488 if (roomData[y][x].keeperLair) {
489 objects.push({room: roomName, type: 'keeperLair', x, y});
490 sourceKeepers = true;
491 }
492 if (roomData[y][x].swamp) {
493 var flag = false;
494 for (var dx = -1; dx <= 1; dx++) {
495 for (var dy = -1; dy <= 1; dy++) {
496 if (x + dx >= 0 && y + dy >= 0 && x + dx <= 49 && y + dy <= 49 && !roomData[y + dy][x + dx].wall) {
497 flag = true;
498 break;
499 }
500 }
501 if (flag) {
502 break;
503 }
504 }
505 if (flag) {
506 terrain.push({type: 'swamp', x, y});
507 }
508 }
509 }
510 }
511
512 terrain = common.encodeTerrain(terrain);
513
514 if(opts.mineral === undefined) {
515 var types = ['H','H','H','H','H','H', 'O','O','O','O','O','O', 'Z','Z','Z', 'K','K','K', 'U','U','U', 'L','L','L', 'X'];
516 opts.mineral = types[Math.floor(Math.random()*types.length)];
517 }
518
519 if(opts.mineral) {
520 var mx,my,isWall,hasSpot,hasObjects;
521 do {
522 mx = 4 + Math.floor(Math.random()*42);
523 my = 4 + Math.floor(Math.random()*42);
524 isWall = common.checkTerrain(terrain, mx, my, C.TERRAIN_MASK_WALL);
525 hasSpot = false;
526 for(var dx=-1;dx<=1;dx++) {
527 for(var dy=-1;dy<=1;dy++) {
528 if(!common.checkTerrain(terrain,mx+dx,my+dy, C.TERRAIN_MASK_WALL)) {
529 hasSpot = true;
530 }
531 }
532 }
533 hasObjects = _.any(objects, i => (i.type == 'source' || i.type == 'controller') && Math.abs(i.x - mx) < 5 && Math.abs(i.y - my) < 5);
534 }
535 while(!isWall || !hasSpot || hasObjects);
536
537 var random = Math.random(), density;
538 for(var d in C.MINERAL_DENSITY_PROBABILITY) {
539 if(random <= C.MINERAL_DENSITY_PROBABILITY[d]) {
540 density = +d;
541 break;
542 }
543 }
544
545 objects.push({
546 type: 'mineral',
547 mineralType: opts.mineral,
548 density,
549 mineralAmount: C.MINERAL_DENSITY[density],
550 x: mx,
551 y: my,
552 room: roomName
553 });
554 }
555
556 return q.all([
557 db.rooms.insert({_id: roomName, status: 'normal', active: true, sourceKeepers}),
558 db['rooms.terrain'].insert({room: roomName, terrain}),
559 objects.length ? db['rooms.objects'].insert(objects) : q.when()
560 ]);
561 })
562 .then(() => exports.updateRoomImageAssets(roomName))
563 .then(() => exports.updateTerrainData())
564 .then(() => 'OK');
565 }
566]);
567
568exports.openRoom = utils.withHelp([
569 "openRoom(roomName, [timestamp]) - Make a room available for use. Specify a timestamp in the future if you want it to be opened later automatically.",
570 function openRoom(roomName, timestamp) {
571
572 var $set = {status: 'normal'};
573
574 if(timestamp) {
575 $set.openTime = timestamp;
576 }
577
578 return db.rooms.update({_id: roomName}, {$set});
579 }
580]);
581
582exports.closeRoom = utils.withHelp([
583 "closeRoom(roomName) - Make a room not available.",
584 function closeRoom(roomName) {
585 return db.rooms.update({$and: [{_id: roomName}, {status: 'normal'}]}, {$set: {status: 'out of borders'}});
586 }
587]);
588
589exports.removeRoom = utils.withHelp([
590 "removeRoom(roomName) - Delete the room and all room objects from the database.",
591 function removeRoom(roomName) {
592 return db.rooms.findOne({_id: roomName})
593 .then(data => !data ? q.reject(`The room ${roomName} is not found`) :
594 q.all([
595 db.rooms.removeWhere({_id: roomName}),
596 db['rooms.objects'].removeWhere({room: roomName}),
597 db['rooms.flags'].removeWhere({room: roomName}),
598 db['rooms.terrain'].removeWhere({room: roomName}),
599 db['rooms.intents'].removeWhere({room: roomName}),
600 db['market.stats'].removeWhere({room: roomName}),
601 env.del(env.keys.MAP_VIEW+roomName)
602 ])
603 .then(() => exports.updateTerrainData())
604 .then(() => {
605 fs.unlinkSync(path.resolve(process.env.ASSET_DIR, 'map', roomName+'.png'));
606 })
607 .then(() => 'OK'));
608 }
609]);
610
611exports.updateRoomImageAssets = utils.withHelp([
612 "updateRoomImageAssets(roomName) - Update images in assets folder for the specified room.",
613 function updateRoomImageAssets(roomName) {
614
615 return db['rooms.terrain'].findOne({room: roomName})
616 .then(terrainItem => utils.writeTerrainToPng(terrainItem.terrain,
617 path.resolve(process.env.ASSET_DIR, 'map', roomName + '.png'), true))
618 .then(() => {
619 var [x,y] = utils.roomNameToXY(roomName);
620 x = Math.floor(x / 4) * 4;
621 y = Math.floor(y / 4) * 4;
622 var firstRoomName = utils.roomNameFromXY(x,y);
623 var allRoomNames = [];
624 for(var xx=x; xx<=x+4; xx++) {
625 for(var yy=y; yy<=y+4; yy++) {
626 allRoomNames.push(utils.roomNameFromXY(xx,yy));
627 }
628 }
629 return db['rooms.terrain'].find({room: {$in: allRoomNames}})
630 .then(data => {
631 var mergedColors = {};
632 for(var yy=0; yy<200; yy++) {
633 mergedColors[yy] = {};
634 for(var xx=0; xx<200; xx++) {
635 mergedColors[yy][xx] = [0,0,0,0];
636 }
637 }
638 for(var xx=0; xx<4; xx++) {
639 for(var yy=0; yy<4; yy++) {
640
641 var terrainItem = _.find(data, {room: utils.roomNameFromXY(xx+x,yy+y)});
642 if(!terrainItem) {
643 continue;
644 }
645
646 var colors = utils.createTerrainColorsMap(terrainItem.terrain, false);
647 for(var cy in colors) {
648 for(var cx in colors[cy]) {
649 mergedColors[parseInt(cy)+yy*50][parseInt(cx)+xx*50] = colors[cy][cx];
650 }
651 }
652 }
653 }
654
655 return utils.writePng(mergedColors, 200, 200,
656 path.resolve(process.env.ASSET_DIR, 'map/zoom2', firstRoomName + '.png'));
657 })
658 });
659}]);
660
661exports.updateTerrainData = utils.withHelp([
662 "updateTerrainData() - Update cached world terrain data.",
663 function updateTerrainData() {
664
665 var walled = '';
666 for(var i=0; i<2500; i++) {
667 walled += '1';
668 }
669
670 return q.all([
671 db.rooms.find(),
672 db['rooms.terrain'].find()
673 ])
674 .then(result => {
675 var [rooms,terrain] = result;
676
677 rooms.forEach(room => {
678 if(room.status == 'out of borders') {
679 _.find(terrain, {room: room._id}).terrain = walled;
680 }
681 var m = room._id.match(/(W|E)(\d+)(N|S)(\d+)/);
682 var roomH = m[1]+(+m[2]+1)+m[3]+m[4], roomV = m[1]+m[2]+m[3]+(+m[4]+1);
683 if(!_.any(terrain, {room: roomH})) {
684 terrain.push({room: roomH, terrain: walled});
685 }
686 if(!_.any(terrain, {room: roomV})) {
687 terrain.push({room: roomV, terrain: walled});
688 }
689 });
690
691 return q.ninvoke(zlib, 'deflate', JSON.stringify(terrain));
692 })
693 .then(compressed => env.set(env.keys.TERRAIN_DATA, compressed.toString('base64')))
694 .then(() => 'OK');
695}]);
696
697
698exports._help = utils.generateCliHelp('map.', exports);
\No newline at end of file