1 | const common = require('@screeps/common');
|
2 | const C = common.configManager.config.common.constants;
|
3 | const bots = common.configManager.config.common.bots;
|
4 | const db = common.storage.db;
|
5 | const env = common.storage.env;
|
6 | const utils = require('../utils');
|
7 | const q = require('q');
|
8 | const fs = require('fs');
|
9 | const path = require('path');
|
10 | const _ = require('lodash');
|
11 |
|
12 | var boyNames = [ 'Jackson', 'Aiden', 'Liam', 'Lucas', 'Noah', 'Mason', 'Jayden', 'Ethan', 'Jacob', 'Jack', 'Caden', 'Logan', 'Benjamin', 'Michael', 'Caleb', 'Ryan', 'Alexander', 'Elijah', 'James', 'William', 'Oliver', 'Connor', 'Matthew', 'Daniel', 'Luke', 'Brayden', 'Jayce', 'Henry', 'Carter', 'Dylan', 'Gabriel', 'Joshua', 'Nicholas', 'Isaac', 'Owen', 'Nathan', 'Grayson', 'Eli', 'Landon', 'Andrew', 'Max', 'Samuel', 'Gavin', 'Wyatt', 'Christian', 'Hunter', 'Cameron', 'Evan', 'Charlie', 'David', 'Sebastian', 'Joseph', 'Dominic', 'Anthony', 'Colton', 'John', 'Tyler', 'Zachary', 'Thomas', 'Julian', 'Levi', 'Adam', 'Isaiah', 'Alex', 'Aaron', 'Parker', 'Cooper', 'Miles', 'Chase', 'Muhammad', 'Christopher', 'Blake', 'Austin', 'Jordan', 'Leo', 'Jonathan', 'Adrian', 'Colin', 'Hudson', 'Ian', 'Xavier', 'Camden', 'Tristan', 'Carson', 'Jason', 'Nolan', 'Riley', 'Lincoln', 'Brody', 'Bentley', 'Nathaniel', 'Josiah', 'Declan', 'Jake', 'Asher', 'Jeremiah', 'Cole', 'Mateo', 'Micah', 'Elliot' ],
|
13 | girlNames = [ 'Sophia', 'Emma', 'Olivia', 'Isabella', 'Mia', 'Ava', 'Lily', 'Zoe', 'Emily', 'Chloe', 'Layla', 'Madison', 'Madelyn', 'Abigail', 'Aubrey', 'Charlotte', 'Amelia', 'Ella', 'Kaylee', 'Avery', 'Aaliyah', 'Hailey', 'Hannah', 'Addison', 'Riley', 'Harper', 'Aria', 'Arianna', 'Mackenzie', 'Lila', 'Evelyn', 'Adalyn', 'Grace', 'Brooklyn', 'Ellie', 'Anna', 'Kaitlyn', 'Isabelle', 'Sophie', 'Scarlett', 'Natalie', 'Leah', 'Sarah', 'Nora', 'Mila', 'Elizabeth', 'Lillian', 'Kylie', 'Audrey', 'Lucy', 'Maya', 'Annabelle', 'Makayla', 'Gabriella', 'Elena', 'Victoria', 'Claire', 'Savannah', 'Peyton', 'Maria', 'Alaina', 'Kennedy', 'Stella', 'Liliana', 'Allison', 'Samantha', 'Keira', 'Alyssa', 'Reagan', 'Molly', 'Alexandra', 'Violet', 'Charlie', 'Julia', 'Sadie', 'Ruby', 'Eva', 'Alice', 'Eliana', 'Taylor', 'Callie', 'Penelope', 'Camilla', 'Bailey', 'Kaelyn', 'Alexis', 'Kayla', 'Katherine', 'Sydney', 'Lauren', 'Jasmine', 'London', 'Bella', 'Adeline', 'Caroline', 'Vivian', 'Juliana', 'Gianna', 'Skyler', 'Jordyn' ];
|
14 |
|
15 | function genRandomUserName(c) {
|
16 | c = c || 0;
|
17 |
|
18 | var name;
|
19 |
|
20 |
|
21 | var list = Math.random() > 0.5 ? boyNames : girlNames;
|
22 | name = list[Math.floor(Math.random()*list.length)];
|
23 |
|
24 | if(c > 3) {
|
25 | name += list[Math.floor(Math.random()*list.length)];
|
26 | }
|
27 |
|
28 | return db.users.findOne({username: name+'Bot'})
|
29 | .then(result => {
|
30 | if(result) {
|
31 | return genRandomUserName(c+1);
|
32 | }
|
33 | return name+'Bot';
|
34 | });
|
35 | }
|
36 |
|
37 | function genRandomBadge() {
|
38 | var badge = {};
|
39 | badge.type = Math.floor(Math.random()*24)+1;
|
40 | badge.color1 = '#'+Math.floor(Math.random()*0xffffff).toString(16);
|
41 | badge.color2 = '#'+Math.floor(Math.random()*0xffffff).toString(16);
|
42 | badge.color3 = '#'+Math.floor(Math.random()*0xffffff).toString(16);
|
43 | badge.flip = Math.random() > 0.5;
|
44 | badge.param = Math.floor(Math.random()*200) - 100;
|
45 | return badge;
|
46 | }
|
47 |
|
48 | exports.spawn = utils.withHelp([
|
49 | `spawn(botAiName, roomName, [opts]) - Create a new NPC player with bot AI scripts, and spawn it to the specified room. 'opts' is an object with the following optional properties:\r
|
50 | * username - the name of a bot player, default is randomly generated\r
|
51 | * cpu - the CPU limit of a bot user, default is 100\r
|
52 | * gcl - the Global Control Level of a bot user, default is 1\r
|
53 | * x - the X position of the spawn in the room, default is random\r
|
54 | * y - the Y position of the spawn in the room, default is random`,
|
55 | function spawn(botAiName, roomName, opts) {
|
56 | opts = opts || {};
|
57 | try {
|
58 | var modules = utils.loadBot(botAiName), user;
|
59 | return db['rooms.objects'].findOne({$and: [{room: roomName}, {type: 'controller'}]})
|
60 | .then(controller => {
|
61 | if(!controller) {
|
62 | return q.reject(`Room controller not found in ${roomName}`);
|
63 | }
|
64 | if(controller.user) {
|
65 | return q.reject(`Room ${roomName} is already owned`);
|
66 | }
|
67 | })
|
68 | .then(() => !opts.username ? genRandomUserName() :
|
69 | db.users.findOne({username: opts.username}).then(user => user ? q.reject(`User with the name "${opts.username}" already exists`) : opts.username))
|
70 | .then(username => {
|
71 | var _user = {
|
72 | username,
|
73 | usernameLower: username.toLowerCase(),
|
74 | cpu: opts.cpu || 100,
|
75 | gcl: opts.gcl ? C.GCL_MULTIPLY * Math.pow(opts.gcl - 1, C.GCL_POW) : 0,
|
76 | cpuAvailable: 0,
|
77 | registeredDate: new Date(),
|
78 | bot: botAiName,
|
79 | active: 10000,
|
80 | badge: genRandomBadge()
|
81 | };
|
82 | return db.users.insert(_user);
|
83 | })
|
84 | .then(_user => {
|
85 | user = _user;
|
86 | return db['users.code'].insert({
|
87 | user: user._id,
|
88 | modules,
|
89 | branch: 'default',
|
90 | activeWorld: true,
|
91 | activeSim: true
|
92 | });
|
93 | })
|
94 | .then(() => env.set(env.keys.MEMORY+user._id, "{}"))
|
95 | .then(() => db['rooms.terrain'].findOne({room: roomName}))
|
96 | .then(terrainItem => {
|
97 | var x = opts.x || Math.floor(3 + Math.random()*46);
|
98 | var y = opts.y || Math.floor(3 + Math.random()*46);
|
99 | while(common.checkTerrain(terrainItem.terrain, x, y, C.TERRAIN_MASK_WALL)) {
|
100 | x = Math.floor(3 + Math.random()*46);
|
101 | y = Math.floor(3 + Math.random()*46);
|
102 | }
|
103 | return db['rooms.objects'].insert({
|
104 | type: 'spawn',
|
105 | room: roomName,
|
106 | x,
|
107 | y,
|
108 | name: 'Spawn1',
|
109 | user: user._id,
|
110 | energy: C.SPAWN_ENERGY_START,
|
111 | energyCapacity: C.SPAWN_ENERGY_CAPACITY,
|
112 | hits: C.SPAWN_HITS,
|
113 | hitsMax: C.SPAWN_HITS,
|
114 | spawning: null,
|
115 | notifyWhenAttacked: false
|
116 | });
|
117 | })
|
118 | .then(common.getGametime)
|
119 | .then(gameTime => db['rooms.objects'].update({$and: [{room: roomName}, {type: 'controller'}]}, {$set: {
|
120 | user: user._id, level: 1, progress: 0, downgradeTime: null, safeMode: gameTime + 20000
|
121 | }}))
|
122 | .then(() => db.rooms.update({_id: roomName}, {$set: {active: true, invaderGoal: 1000000}}))
|
123 | .then(() => `User ${user.username} with bot AI "${botAiName}" spawned in ${roomName}`);
|
124 | }
|
125 | catch(e) {
|
126 | return q.reject(e);
|
127 | }
|
128 | }
|
129 | ]);
|
130 |
|
131 | exports.reload = utils.withHelp([
|
132 | "reload(botAiName) - Reload scripts for the specified bot AI.",
|
133 | function reload(botAiName) {
|
134 | return utils.reloadBotUsers(botAiName);
|
135 | }
|
136 | ]);
|
137 |
|
138 | exports.removeUser = utils.withHelp([
|
139 | "removeUser(username) - Delete the specified bot player and all its game objects.",
|
140 | function removeUser(username) {
|
141 | return db.users.findOne({username})
|
142 | .then(user => {
|
143 | if(!user) {
|
144 | return q.reject('User not found');
|
145 | }
|
146 | if(!user.bot) {
|
147 | return q.reject('User is not a bot');
|
148 | }
|
149 | return utils.respawnUser(user._id)
|
150 | .then(db.users.removeWhere({_id: user._id}))
|
151 | .then(db['users.code'].removeWhere({user: user._id}))
|
152 | .then(env.del(env.keys.MEMORY+user._id))
|
153 | .then(() => `User removed successfully`);
|
154 | })
|
155 | }
|
156 | ]);
|
157 |
|
158 | exports._help = utils.generateCliHelp('bots.', exports)+`\r\nBot AIs:\r\n`+
|
159 | Object.keys(bots).map(botName => ` - ${botName} [${bots[botName]}]`).join(`\r\n`);
|