UNPKG

8.33 kBJavaScriptView Raw
1const _ = require('lodash');
2const common = require('@screeps/common');
3const config = common.configManager.config;
4const C = config.common.constants;
5const db = common.storage.db;
6const env = common.storage.env;
7const q = require('q');
8const png = require('pngjs').PNG;
9const fs = require('fs');
10const path = require('path');
11
12exports.roomNameFromXY = function(x,y) {
13 if(x < 0) {
14 x = 'W'+(-x-1);
15 }
16 else {
17 x = 'E'+(x);
18 }
19 if(y < 0) {
20 y = 'N'+(-y-1);
21 }
22 else {
23 y = 'S'+(y);
24 }
25 return ""+x+y;
26}
27
28exports.roomNameToXY = function(name) {
29 var [match,hor,x,ver,y] = name.match(/^(\w)(\d+)(\w)(\d+)$/);
30 if(hor == 'W') {
31 x = -x-1;
32 }
33 else {
34 x = +x;
35 //x--;
36 }
37 if(ver == 'N') {
38 y = -y-1;
39 }
40 else {
41 y = +y;
42 //y--;
43 }
44 return [x,y];
45}
46
47exports.translateModulesFromDb = function(modules) {
48 modules = modules || {};
49
50 for(var key in modules) {
51 var newKey = key.replace(/\$DOT\$/g, '.');
52 newKey = newKey.replace(/\$SLASH\$/g, '/');
53 newKey = newKey.replace(/\$BACKSLASH\$/g, '\\');
54 if(newKey != key) {
55 modules[newKey] = modules[key];
56 delete modules[key];
57 }
58 }
59 return modules;
60};
61
62exports.translateModulesToDb = function(modules) {
63 modules = modules || {};
64
65 for(var key in modules) {
66 var newKey = key.replace(/\./g,'$DOT$');
67 newKey = newKey.replace(/\//g,'$SLASH$');
68 newKey = newKey.replace(/\\/g,'$BACKSLASH$');
69
70 if(newKey[0] == '$') {
71 delete modules[key];
72 continue;
73 }
74
75 if(newKey != key) {
76 modules[newKey] = modules[key];
77 delete modules[key];
78 }
79 }
80
81 if(!modules.main) {
82 modules.main = '';
83 }
84
85 return modules;
86};
87
88exports.getUserWorldStatus = function(user) {
89 return db['rooms.objects'].count({user: ""+user._id})
90 .then((objectsCnt) => {
91 if(!objectsCnt) {
92 return {status: 'empty'};
93 }
94 return db['rooms.objects'].find({$and: [
95 {user: ""+user._id},
96 {type: {$in: ['spawn','controller']}}
97 ]}).then((objects) => {
98 var spawns = false;
99 if(objects) {
100 objects.forEach((i) => {
101 if (i.type == 'spawn') {
102 if(!_.any(objects, {type: 'controller', room: i.room, user: i.user})) {
103 return;
104 }
105 spawns = true;
106 }
107 })
108 }
109 return {status: spawns ? 'normal' : 'lost'};
110 })
111 })
112};
113
114
115exports.respawnUser = function(userId) {
116
117 return db['users'].findOne({username: C.SYSTEM_USERNAME})
118 .then(systemUser => {
119 if(!systemUser) {
120 return q.reject('no system user');
121 }
122
123 return db['rooms.objects'].removeWhere({$and: [{user: ""+userId}, {type: {$in: ['creep','powerCreep','constructionSite']}}]})
124
125 .then(() => db['users.power_creeps'].removeWhere({user: ""+userId}))
126
127 .then(() => db['rooms.objects'].update({$and: [{user: ""+userId}, {type: 'rampart'}]},
128 {$set: {isPublic: true}}))
129
130 .then(() => db['rooms.objects'].update({$and: [{user: ""+userId}, {type: {$ne: 'controller'}}]},
131 {$set: {user: ""+systemUser._id}}))
132
133 .then(() => db['rooms.flags'].removeWhere({user: ""+userId}))
134
135 .then(() => db['rooms.objects'].find({$and: [{user: ""+userId}, {type: 'controller'}]}))
136
137 .then((controllers) => q.all(_.map(controllers, (i) => db.rooms.update({_id: i.room}, {$set: {status: 'normal'}}))))
138
139 .then(() => db['rooms.objects'].update({$and: [{user: "" + userId}, {type: 'controller'}]}, {
140 $set: {
141 level: 0,
142 hits: 0,
143 hitsMax: 0,
144 progress: 0,
145 progressTotal: 0,
146 user: null,
147 downgradeTime: null,
148 safeMode: null,
149 safeModeAvailable: 0,
150 safeModeCooldown: null
151 }
152 }))
153
154 .then(() => db['users'].update({_id: "" + userId}, {$set: {rooms: []}}));
155 });
156};
157
158exports.withHelp = function(array) {
159 var fn = array[1];
160 fn._help = array[0];
161 return fn;
162};
163
164exports.generateCliHelp = function(prefix, container) {
165 return `Available methods:\r\n`+Object.keys(container).filter(i => _.isFunction(container[i])).map(i => ' - ' + prefix + (container[i]._help || i)).join('\r\n');
166};
167
168exports.writePng = function(colors, width, height, filename) {
169
170 var image = new png({width, height});
171
172 for(var y=0; y<height; y++) {
173 for(var x=0; x<width; x++) {
174 var idx = (width*y + x) << 2;
175
176 image.data[idx] = colors[y][x][0];
177 image.data[idx+1] = colors[y][x][1];
178 image.data[idx+2] = colors[y][x][2];
179 image.data[idx+3] = colors[y][x][3] === undefined ? 255 : colors[y][x][3];
180 }
181 }
182
183 var defer = q.defer();
184 image.pack().pipe(fs.createWriteStream(filename)).on('finish', () => defer.resolve());
185 return defer.promise;
186};
187
188exports.createTerrainColorsMap = function(terrain, zoomIn) {
189 var colors = {},
190 width = 50, height = 50;
191
192 for(var y=0; y<height; y++) {
193 if(zoomIn) {
194 colors[y * 3] = {};
195 colors[y * 3 + 1] = {};
196 colors[y * 3 + 2] = {};
197 }
198 else {
199 colors[y] = {};
200 }
201 for(var x=0; x<width; x++) {
202
203 var color;
204 if(common.checkTerrain(terrain,x,y,C.TERRAIN_MASK_WALL)) {
205 color = [0,0,0];
206 }
207 else if(common.checkTerrain(terrain,x,y,C.TERRAIN_MASK_SWAMP)) {
208 color = [35,37,19];
209 }
210 else if(x == 0 || y == 0 || x == 49 || y == 49) {
211 color = [50,50,50];
212 }
213 else {
214 color = [43,43,43];
215 }
216 if(zoomIn) {
217 for (var dx = 0; dx < 3; dx++) {
218 for (var dy = 0; dy < 3; dy++) {
219 colors[y * 3 + dy][x * 3 + dx] = color;
220 }
221 }
222 }
223 else {
224 colors[y][x] = color;
225 }
226 }
227 }
228
229 return colors;
230};
231
232exports.writeTerrainToPng = function(terrain, filename, zoomIn) {
233
234 var colors = exports.createTerrainColorsMap(terrain, zoomIn);
235 return exports.writePng(colors, 50*(zoomIn?3:1), 50*(zoomIn?3:1), filename);
236};
237
238exports.loadBot = function(name) {
239 var dir = config.common.bots[name];
240 if(!dir) {
241 throw new Error(`Bot AI with the name "${name}" doesn't exist`);
242 }
243 var stat = fs.statSync(dir);
244 if (!stat.isDirectory()) {
245 throw new Error(`"${dir}" is not a directory`);
246 }
247 fs.statSync(path.resolve(dir, 'main.js'));
248 var files = fs.readdirSync(dir), modules = {};
249 files.forEach(file => {
250 var m = file.match(/^(.*)\.js$/);
251 if(!m) {
252 return;
253 }
254 modules[m[1]] = fs.readFileSync(path.resolve(dir, file), {encoding: 'utf8'});
255 });
256 return exports.translateModulesToDb(modules);
257};
258
259exports.reloadBotUsers = function(name) {
260
261 return db.users.find({bot: name})
262 .then(users => {
263 if(!users.length) {
264 return 'No bot players found';
265 }
266 var modules = exports.loadBot(name);
267 var timestamp = Date.now();
268
269 return db['users.code'].insert(users.map(i => ({
270 user: i._id,
271 branch: 't'+timestamp,
272 timestamp,
273 activeWorld: true,
274 activeSim: true,
275 modules
276 })))
277 .then(() => db['users.code'].removeWhere({$and: [
278 {user: {$in: users.map(i => i._id)}},
279 {branch: {$ne: 't'+timestamp}}
280 ]}))
281 .then(() => 'Reloaded scripts for users: '+users.map(i => i.username).join(', '));
282 })
283};
\No newline at end of file