├── .github
├── ISSUE_TEMPLATE.md
└── PULL_REQUEST_TEMPLATE.md
├── .travis.yml
├── LICENSE
├── README.md
├── cpu.js
├── heap.js
├── index.js
├── install.json
├── package.json
├── source
├── ai
│ ├── Bot.js
│ ├── Minion.js
│ ├── botAI.js
│ └── fakePlayer.js
├── child
│ ├── Player.js
│ ├── index.js
│ ├── manager.js
│ └── node.js
├── commands
│ ├── index.js
│ └── lib
│ │ ├── addBot.js
│ │ ├── ban.js
│ │ ├── debug.js
│ │ ├── kick.js
│ │ ├── kickbots.js
│ │ ├── libraries
│ │ ├── list.js
│ │ ├── pause.js
│ │ ├── plugin.js
│ │ ├── redraw.js
│ │ ├── reload.js
│ │ ├── reset.js
│ │ ├── restart.js
│ │ ├── save.js
│ │ ├── server.js
│ │ ├── startv.js
│ │ ├── stop.js
│ │ └── update.js
├── core
│ ├── GUIHandler.js
│ ├── GraphicalInterface.js
│ ├── Player.js
│ ├── PlayerTemplate.js
│ ├── Statistics.js
│ ├── binaryNodes.js
│ ├── childHolder.js
│ ├── childManager.js
│ ├── childService.js
│ ├── collisionHandler.js
│ ├── configService.js
│ ├── controller.js
│ ├── dataService.js
│ ├── errorManager.js
│ ├── foodService.js
│ ├── gameData.js
│ ├── gameMode.js
│ ├── globalData.js
│ ├── main.js
│ ├── pluginParser.js
│ ├── pluginService.js
│ ├── serverService.js
│ ├── shellService.js
│ ├── skinHandler.js
│ ├── socket.js
│ ├── socketService.js
│ ├── stringBuilder.js
│ ├── uid.js
│ ├── updater.js
│ ├── utilities.js
│ └── worldModel.js
├── entities
│ ├── MotherCell.js
│ ├── bullet.js
│ ├── cell.js
│ ├── ejectedMass.js
│ ├── food.js
│ ├── index.js
│ ├── playerCell.js
│ ├── template.js
│ ├── virus.js
│ └── wormHole.js
├── modes
│ ├── Experimental.js
│ ├── FFA.js
│ ├── HideNSeek.js
│ ├── Minions.js
│ ├── Teams.js
│ ├── advTeams.js
│ ├── index.js
│ └── template.js
├── modules
│ ├── FastBuffers.js
│ ├── HashBounds.js
│ ├── LZString.js
│ ├── fastSquares.js
│ └── ini.js
├── plugins
│ └── README.md
├── settings
│ ├── botnames.txt
│ ├── clientConfig.ini
│ ├── config.ini
│ ├── customSkins.ini
│ ├── physicsConfig.ini
│ ├── pluginConfig.ini
│ ├── pluginConfig
│ │ └── README.md
│ ├── serverConfig.ini
│ └── servers
│ │ └── README.md
└── sounds
│ ├── README.md
│ ├── alert.mp3
│ ├── start.mp3
│ └── tone.mp3
└── start.bat
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | Important rules for pull requests:
2 |
3 |
4 | 1. Everything must be tested.
5 | 2. Everything must be optimised to the highest degree.
6 | 3. Profile the server before and after your changes.
7 | 4. Avoid bad practices.
8 | 5. Use the log function instead of console.log
9 | 6. Avoid circlular data structures
10 |
11 |
12 | IF THE PR's FUNCTIONALITY CAN BE MADE INTO A PLUGIN, DO THAT INSTEAD
13 |
14 |
15 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "5.9.0"
4 |
5 | script:
6 | node source/core/main.js
7 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | OpenAgar - Open source web game
2 | Copyright (C) 2016 Andrew S
3 |
4 | This program is free software: you can redistribute it and/or modify
5 | it under the terms of the GNU Affero General Public License as published
6 | by the Free Software Foundation, either version 3 of the License, or
7 | (at your option) any later version.
8 |
9 | This program is distributed in the hope that it will be useful,
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | GNU Affero General Public License for more details.
13 |
14 | You should have received a copy of the GNU Affero General Public License
15 | along with this program. If not, see .
16 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # CLOSED!!!
2 |
3 | This project has been closed. Please do not go to opnagar.us, it is a scam.
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | [](https://travis-ci.org/AJS-development/OpenAgar) [](http://home.opnagar.us) [](https://discord.gg/8JPsyDn)   [](https://github.com/AJS-development/OAPlugins) 
12 |
13 | Hello, we are AJS Development! We are the same team that brought you OgarUl! In AJS, we have many members. The main members are Andrews54757 and LegitSoulja. We decided to create this project after OgarUl's Ogar infrastructure couldnt hold with all those cool features! So, we created our own, completely from scratch. Now, OpenAgar is the most efficient Ogar-like game server available! Twice as efficient as MultiOgar, a gazillion times efficient than OgarUL, and 5 times efficient than Ogar! ([Proof](https://github.com/AJS-development/OpenAgar/issues/1)) We also decided to make OpenAgar as interesting as possible! New physics, new features, new gameplay and more!
14 |
15 | ## What game?
16 | It is a web game that we are making, similar to [agar.io](https://agar.io), but very different
17 |
18 | ## How to Use
19 |
20 | **Please note that a key is required, that it's distribution is limited! This is so that computer newbies wont waste our time**
21 |
22 | #### Dependencies
23 | * Nodejs (**v5.10.0**+)
24 | * Npm (included with Nodejs)
25 |
26 | #### Guide
27 |
28 | 1. Download this repo, or do `git clone https://github.com/AJS-development/OpenAgar.git` to download from command line.
29 | 2. Change directory to the project folder `cd OpenAgar`
30 | 3. Make sure all the dependancies are installed
31 | 4. Install npm dependancies `npm install`
32 | 5. Run index.js using node `node index.js`
33 | 6. Record the ID given and register by going here: http://login.opnagar.us. (OPTIONAL but recommended)
34 | 8. Run index.js again
35 | 9. Connect using `opnagar.us`
36 |
37 | #### Registration
38 | While you do not need to registrate to run openagar (not anymore), you need to registrate to use services provided by AJS. Such include:
39 |
40 | 1. Statistics - Publishing your server online to opnagar.us
41 | 2. Plugins - Use of our libraries (One plugins is allowed for unregistered copies)
42 | 3. Socket Protection
43 | 4. Skin publishing - globally to opnagar.us
44 | 5. Auto issue reports
45 | 6. Our client.
46 |
47 |
48 | If you dont registrate, you are unable to:
49 |
50 | 1. Publish server on stats
51 | 2. Use more than 1 plugin
52 | 3. No socket protection
53 | 4. Inability to use our client (excluding localhost and lan)
54 | 5. Inability to publish global skins
55 | 6. Auto issue reports
56 |
57 | ##### Login.opnagar.us
58 | This is the website to generate keys from. You will have to sign up/sign in using your github account. We are using github because:
59 |
60 | 1. We would rather have developers, not noobs
61 | 2. We dont want to deal with managing accounts (ie, making sure they are real)
62 |
63 | Then, once you are logged in, you can register servers. You may only have two registrated servers in your account. You may delete or deactivate unused registrations
64 |
65 | #### Please do not misuse the registration system
66 | Please do not be an idiot and try to make money off of ths system. We will monitor accounts and suspend them that are known for misuse.
67 |
68 | ## NEVER BUY OPENAGAR!
69 | If you bought a copy of openagar, wow, you have been ripped. People who have a registrated version might try to sell it for money. While sharing of servers is allowed, however note that if multiple people are using it at the same time - your server will become unjoinable - I suggest not doing this unless you are his/her friend. Another thing, is that openagar is free. Yes, its FREE. Also, the registration is FREE and UNLIMITED.
70 |
71 | ## Commands
72 | There are commands you can type in command line.
73 |
74 | |Command | Desc |
75 | |-----------|--------|
76 | |help |Displays a list of commands|
77 | |startv |Start visual gui, not implemented|
78 | |plugin |Plugin command, the core feature of OpenAgar|
79 | |list |List the players/bots/minions in the game|
80 | |server |Create servers, remove servers, select servers, and list them |
81 | |pause |Pause/unpause the game|
82 | |restart |Restart. Use just like you would use in command prompt. Do restart all [time] to restart all servers|
83 | |kick |Kick a player|
84 | |kickbots |Kick bots|
85 | |addbots |Add bots|
86 | |ban |Ban players|
87 | |debug |Toggle the debug console|
88 | |update |Updates the software|
89 | |stop |Stops the server|
90 |
91 |
92 | ## Chat Commands
93 | There are also chat commands
94 |
95 | |Command | Desc |
96 | |-----------|--------|
97 | |help |Displays a list of commands|
98 |
99 | ## Gamemodes
100 | There are also some gamemodes
101 |
102 | | ID | Mode |
103 | |----|------------|
104 | |0 |FFA |
105 | |1 |Teams |
106 | |2 |Experimental|
107 | |3 |Minions |
108 | |4 |Hide n seek |
109 | |5 |Adv Teams |
110 | |6 |Get rich or die trying (not finished)|
111 | |7 |Leap (not finished)|
112 | |8 |Timed FFA (not finished)|
113 | |9 |Hunger Games (not finished)|
114 |
115 | ## Minigames
116 | Minigames are planned for OpenAgar, we dont know exactly how they will work, but we have an idea. Some ideas:
117 |
118 | * Pool: Like 8-ball pool with some tweaks. (2 players)
119 | * Maze: A maze, with teams and the first team to solve first wins (2-20 players)
120 | * Get the F off my turf: A game where you defend your turf from others.
121 |
122 | ## Statistics
123 | Statistics allow you to host a public server. To post your server to statistics, edit serverConfig.ini's statistics config values. Then, your server will be listed and it will be joinable at `http://opnagar.us/server/yoururl`.
124 |
125 | ## Plugins
126 | Since most of OpenAgar's features doesnt come in the box, plugins are very important. So we made it very easy to install plugins.
127 |
128 | #### The Plugin Command
129 | The plugin command has four important actions.
130 |
131 | ##### 1. install
132 | > plugin install [name]
133 |
134 | Install a plugin from plugin library. The default library is [this](https://github.com/AJS-development/OAPlugins). Note that plugins are case sensitive.
135 |
136 | ##### 2. search
137 | > plugin search [search term]
138 |
139 | Search plugin librarys for plugins matching your search term
140 |
141 | ##### 3. library
142 | > plugin library [url]
143 |
144 | This adds a library to install/search plugins from. The url is the plugin JSON file with all the plugin data ([example](https://github.com/AJS-development/OAPlugins/blob/master/plugins.json)). All the libraries are stored in `source/commands/lib/libraries`. It is a line-break separated list of urls.
145 |
146 | ##### 4. add
147 | > plugin add [name] [url]
148 |
149 | This adds a plugin from it's url.
150 |
151 | ## Multi-Server system
152 | OpenAgar is made so you can host multiple servers on one port. There are two ways to create additional servers in the multi-server system
153 |
154 | #### The settings/server folder
155 | Using this folder, you can automatically have OpenAgar create additional servers for you. Also, this allows you to easily change the configurations of the individual servers.
156 |
157 | ##### Usage
158 | 1. Create a file in the source/settings/server folder, the file should be `[Server name].ini`
159 | 2. Then, you can override configs in that file. For example, I can put the line `gameMode = 1` to have the server be in teams
160 | 3. Start the server. Your server will automatically be created.
161 |
162 | #### The server command
163 | The server command has 4 different usages
164 |
165 | ##### 1. create
166 | > server create [name] [configs (optional)]
167 |
168 | This adds an additional server. The configs argument overrides default configs and looks like this: `configname1:value1,configname2:value2`. You do not have to specify every config values.
169 |
170 | ##### 2. remove
171 | > server remove [id]
172 |
173 | This removes a server by id
174 |
175 | ##### 3. select
176 | > server select [id]
177 |
178 | This selects a server for you to control via console.
179 |
180 | ##### 4. list
181 | > server list
182 |
183 | This lists all servers: their ids, names, players/bots, uptime, and status
184 |
185 | ## SSL
186 | OpenAgar is compatable with SSL. To use, set ssl to true in serverConfig.ini.
187 |
188 | #### rsa.json
189 | SSL uses this file to configure SSL.
190 |
191 | ```
192 | {
193 | "key": "", // RSA Private key (PEM format)
194 | "certificate": "", // RSA Signed Certificate
195 | "ca": "", // certificate authority
196 | "expire": int // Expiration (in milliseconds) (Optional)
197 | }
198 | ```
199 |
200 | #### Self-Signed-cert
201 | OpenAgar can generate its own self-signed RSA certificate. To use, just set ssl to true, without adding the rsa.json file. However, to be able to connect however (in most browsers), you must go to `https:yourip:yourport` in the browser and verify the certificate. (Since no CA is used)
202 |
203 | ## Developers
204 |
205 | * Andrews54757
206 | * LegitSoulja
207 |
208 | # Support
209 | One thing we decided, was that we are not going to help other people run this project. If you cant... Too bad, use ogar. We are really trying to have this project be semi-private.
210 |
211 | ## More like ClosedAgar
212 | People have complained to me about this project being semi private. But in order to have everybody enjoy it, we must, since being too open means disaster. This was the problem with OgarUL, it got too big it collapsed on itself. Resources cost money you know.
213 |
214 | ## FAQ
215 | #### How can I help?
216 | Make a pr. But please make good ones
217 |
218 | #### How come features are so limited?
219 | Actually, there are a lot of features, but none come in the box. You must use the plugin command to add them
220 |
221 | #### Can I make a Pull Request?
222 | Yes, but note that we are very very strict. So many pull requests wont be accepted
223 |
224 | #### Can I make a fork?
225 | Yes, you may.
226 |
227 | #### I want to post a server to stats, however I am worried over ddos attacks and other things
228 | Statistics will not show your ip, minimising ddos attacks. Also, OpenAgar is made to handle them. It will detect those attacks and mitigate them. DDOSers have no life.
229 |
230 | #### Why are some files encrypted?
231 | Some files are encrypted because they are needed to secure things such as sockets, or because they use our assets (our servers, other resources...).
232 |
--------------------------------------------------------------------------------
/cpu.js:
--------------------------------------------------------------------------------
1 | // SOURCE: https://gist.github.com/danielkhan/9cfa77b97bc7ba0a3220#file-cpuprofiler-js-L5
2 |
3 | /**
4 | * Simple userland CPU profiler using v8-profiler
5 | * Usage: require('[path_to]/CpuProfiler').init('datadir')
6 | *
7 | * @module CpuProfiler
8 | * @type {exports}
9 | */
10 |
11 | var fs = require('fs');
12 | var profiler = require('v8-profiler');
13 | var _datadir = null;
14 |
15 | /**
16 | * Init and schedule profiler runs
17 | *
18 | * @param datadir Folder to save the data to
19 | */
20 | module.exports.init = function (datadir) {
21 | _datadir = datadir;
22 | setInterval(startProfiling, 10 * 1000);
23 | };
24 |
25 | /**
26 | * Starts profiling and schedules its end
27 | */
28 | function startProfiling() {
29 | var stamp = Date.now();
30 | var id = 'profile-' + stamp;
31 |
32 | // Use stdout directly to bypass eventloop
33 | fs.writeSync(1, 'Start profiler with Id [' + id + ']\n');
34 |
35 | // Start profiling
36 | profiler.startProfiling(id);
37 |
38 |
39 | // Schedule stop of profiling in x seconds
40 | setTimeout(function () {
41 | stopProfiling(id)
42 | }, 5000);
43 | }
44 |
45 | /**
46 | * Stops the profiler and writes the data to a file
47 | * @param id the id of the profiler process to stop
48 | */
49 | function stopProfiling(id) {
50 | var profile = profiler.stopProfiling(id);
51 | fs.writeFile(_datadir + '/' + id + '.cpuprofile', JSON.stringify(profile), function () {
52 | console.log('Profiler data written');
53 | });
54 | }
55 |
--------------------------------------------------------------------------------
/heap.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | var fs = require('fs');
4 | var profiler = require('heapdump');
5 | var _datadir = null;
6 |
7 | var startProfiling = function() {
8 | var stamp = Date.now();
9 | var id = 'profile-' + stamp;
10 |
11 | // Use stdout directly to bypass eventloop
12 | fs.writeSync(1, 'Start profiler with Id [' + id + ']\n');
13 |
14 | // Start profiling
15 | profiler.writeSnapshot(_datadir + '/' + id + '.heapsnapshot',function() {
16 | console.log("Done profiling")
17 | setTimeout(function () {
18 | startProfiling()
19 | }, 5000);
20 | });
21 |
22 |
23 |
24 |
25 | }
26 |
27 | module.exports.init = function (datadir) {
28 | _datadir = datadir;
29 | startProfiling()
30 | };
31 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | var fs = require('fs')
2 |
3 | var toCheck = JSON.parse(fs.readFileSync(__dirname + "/install.json", "utf8"))
4 | var exec = require('child_process').exec;
5 | var modules = []
6 | console.log("Checking Modules")
7 | try {
8 | var f = JSON.parse(fs.readFileSync("modules.json", "utf8"));
9 | var u = 0,
10 | a = 0
11 | for (var i = 0; i < toCheck.length; i++) {
12 | var m = toCheck[i],
13 | b = f[i];
14 |
15 | if (!b) {;
16 | a++;
17 | modules.push(b)
18 | } else if (m.version != b.version) {;
19 | u++;
20 | modules.push(b)
21 | }
22 | }
23 | console.log(a + " Modules need to be installed; " + u + " modules need to be updated")
24 | } catch (e) {
25 | modules = toCheck;
26 | console.log(toCheck.length + " Modules need to be installed")
27 | }
28 | if (!modules.length) return callback();
29 | console.log("Installing Module(s)")
30 | var todo = 1;
31 | var done = 0;
32 |
33 | function loading(ne) {
34 | done++;
35 | var percent = Math.round(done / todo * 10)
36 | var bar = ""
37 | for (var i = 0; i < percent; i++) {
38 | bar = bar + "===";
39 | }
40 | if (percent == 10) bar = bar + "=";
41 | else bar = bar + ">";
42 | var extras = 31 - bar.length;
43 | var extra = "";
44 | for (var i = 0; i < extras; i++) extra = extra + " ";
45 | process.stdout.write("\u001B[?25l\r\x1b[K[npm] [" + bar + extra + "] " + percent * 10 + "% " + ne);
46 | }
47 | var index = 0;
48 | todo += modules.length * 2;
49 | install()
50 |
51 | function install() {
52 | var b = modules[index]
53 | if (!b) {
54 | loading("Done!");
55 | process.stdout.write("\n\u001B[?25h")
56 | return callback()
57 | }
58 | setTimeout(function () {
59 | loading("Installing " + b.name);
60 | }, 500)
61 | exec("npm install " + b.name + "@" + b.version, function (error, stdout, stderr) {
62 | if (error) {
63 | console.log("Error with installing module: " + b.name + "\n" + error + "\n");
64 | }
65 | loading("Installed " + b.name);
66 | index++;
67 | install();
68 | });
69 | }
70 |
71 | function callback() {
72 | fs.writeFileSync("modules.json", JSON.stringify(toCheck), "utf8")
73 | var main = require('./source/core/controller.js')
74 | //require('./cpu.js').init('./data')
75 | //require('./heap.js').init('./data')
76 |
77 |
78 | Map.prototype.every = function (c) {
79 | var a = this.entries()
80 | var b;
81 | while (b = a.next().value) {
82 | if (!c(b[1], b[0])) return false;
83 | }
84 |
85 | return true;
86 | }
87 | Map.prototype.toArray = function () {
88 | var array = [];
89 | this.forEach(function (a) {
90 | array.push(a)
91 | })
92 | return array
93 | }
94 |
95 | Map.prototype.map = function (c) {
96 | var f = new Map();
97 | var a = this.entries()
98 | var b;
99 | while (b = a.next().value) {
100 | f.set(b[0], c(b[1], b[0]))
101 | }
102 | return f;
103 |
104 | }
105 | Map.prototype.filter = function (c) {
106 | var f = new Map();
107 | var a = this.entries()
108 | var b;
109 | while (b = a.next().value) {
110 | if (c(b[1], b[0])) f.set(b[0], b[1])
111 | }
112 | return f;
113 |
114 | }
115 | Map.prototype.peek = function () {
116 | var a = this.entries();
117 | var b = a.next().value;
118 | return (b) ? b[1] : false;
119 | }
120 |
121 |
122 |
123 | main()
124 |
125 | }
126 |
--------------------------------------------------------------------------------
/install.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "name": "cli-gui",
4 | "version": "latest"
5 | },
6 | {
7 | "name": "toobusy-js",
8 | "version": "latest"
9 | },
10 | {
11 | "name": "rson",
12 | "version": "latest"
13 | },
14 | {
15 | "name": "quickmap",
16 | "version": "latest"
17 | },
18 | {
19 | "name": "hashbounds",
20 | "version": "4.2.2"
21 | },
22 | {
23 | "name": "styleme",
24 | "version": "latest"
25 | },
26 | {
27 | "name": "node-cryptojs-aes",
28 | "version": "latest"
29 | },
30 | {
31 | "name": "minirequest",
32 | "version": "latest"
33 | },
34 | {
35 | "name": "asyncconsole",
36 | "version": "latest"
37 | },
38 | {
39 | "name": "nodesounds",
40 | "version": "latest"
41 | },
42 | {
43 | "name": "cligui2",
44 | "version": "latest"
45 | },
46 | {
47 | "name": "express",
48 | "version": "4"
49 | },
50 | {
51 | "name": "pem",
52 | "version": "latest"
53 | },
54 | {
55 | "name": "simplesockets",
56 | "version": "1.0.3"
57 | }
58 | ]
59 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "OpenAgar",
3 | "version": "4.5.0",
4 | "description": "An open source web game",
5 | "main": "index.js",
6 | "dependencies": {
7 | "SmartConfig": "latest",
8 | "asyncconsole": "^1.3.9",
9 | "cli-gui": "^2.5.9",
10 | "cligui2": "^2.0.0",
11 | "express": "^4.15.3",
12 | "hashbounds": "^4.2.2",
13 | "minirequest": "^1.4.0",
14 | "nodesounds": "^1.7.0",
15 | "pem": "^1.9.7",
16 | "quickmap": "^1.2.9",
17 | "rson": "^1.5.8",
18 | "simplesockets": "1.0.3",
19 | "styleme": "^2.5.4",
20 | "toobusy-js": "^0.5.1"
21 | },
22 | "devDependencies": {},
23 | "scripts": {
24 | "test": "node build.js",
25 | "start": "node index.js"
26 | },
27 | "repository": {
28 | "type": "git",
29 | "url": "https://github.com/AJS-development/OpenAgar"
30 | },
31 | "author": "AJS-development",
32 | "license": "AGPL-3.0",
33 | "bugs": {
34 | "url": "https://github.com/AJS-development/OpenAgar/issues"
35 | },
36 | "homepage": "https://github.com/AJS-development/OpenAgar"
37 | }
38 |
--------------------------------------------------------------------------------
/source/ai/Bot.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /*
3 | OpenAgar - Open source web game
4 | Copyright (C) 2016 Andrew S
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Affero General Public License as published
8 | by the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Affero General Public License for more details.
15 |
16 | You should have received a copy of the GNU Affero General Public License
17 | along with this program. If not, see .
18 | */
19 | var BotAi = require('./botAI.js')
20 | module.exports = class Bot {
21 | constructor(id, server, botid) {
22 | this.id = id
23 | this.botid = botid
24 | this.score = 0;
25 | this.mouse = {
26 | x: 0,
27 | y: 0
28 | }
29 |
30 | this.center = {
31 | x: 0,
32 | y: 0
33 | }
34 | this.team = 0;
35 |
36 | this.server = server;
37 | this.cells = [];
38 | this.send = false;
39 | this.ai = new BotAi(this)
40 | }
41 | onRemove(main) {
42 |
43 | this.cells.forEach((cell) => {
44 | main.removeNode(cell)
45 | })
46 |
47 | }
48 | addCell(cell) {
49 |
50 | if (this.cells.indexOf(cell) != -1) return;
51 | this.cells.push(cell)
52 |
53 | }
54 |
55 | onDeath() {
56 |
57 |
58 | }
59 | spawn() {
60 |
61 | this.server.spawn(this)
62 |
63 | }
64 | getScore(re) {
65 | if (this.cells.length == 0) return 0;
66 |
67 | var l = 0;
68 | this.cells.forEach((n) => {
69 | l += n.mass;
70 | })
71 | this.mass = l;
72 | this.score = Math.max(this.score, l)
73 | return this.score
74 | }
75 |
76 | setRandom() {
77 | if (!this.a) return;
78 | var a = this.a
79 | this.mouse.x = Math.floor(a.width * Math.random()) + a.x;
80 | this.mouse.y = Math.floor(a.height * Math.random()) + a.y
81 |
82 | }
83 | ejectMass() {
84 | this.server.ejectMass(this)
85 | }
86 | splitCells() {
87 | this.server.splitPlayer(this)
88 | }
89 | getSmallest() {
90 | if (this.cells.length == 0) return;
91 | var min = this.cells[0]
92 |
93 | this.cells.forEach((cell) => {
94 | if (cell.mass < min.mass) min = cell;
95 | })
96 | return min;
97 | }
98 | update() { // 0.05 sec
99 |
100 | if (this.cells.length == 0) this.spawn()
101 | var a = this.calcView()
102 | if (!a) return
103 |
104 | // if (this.center.x == this.mouse.x || this.center.y == this.mouse.y)
105 | this.view = a;
106 | this.nodes = this.server.nodes.toArray(this.view)
107 | this.ai.update()
108 |
109 | // this.checkDeath()
110 | /*
111 | if (this.timers.changeDir >= 20) {
112 | this.timers.changeDir = 0;
113 | var a = this.calcView()
114 | this.mouse.x = Math.floor(a.width * Math.random()) + a.x;
115 | this.moude.y = Math.floor(a.height * Math.random()) + a.y
116 | this.checkDeath()
117 | } else {
118 | this.timers.changeDir ++;
119 | }
120 | */
121 |
122 |
123 | }
124 |
125 | calcView() {
126 | if (this.cells.length == 0) return
127 | var totalSize = 1.0;
128 | var x = 0,
129 | y = 0;
130 | // console.log(this.cells)
131 | this.cells.forEach((cell) => {
132 |
133 | if (!cell) return
134 | x += cell.position.x
135 | y += cell.position.y
136 | totalSize += cell.getSize();
137 | })
138 | this.center.x = x / this.cells.length
139 | this.center.y = y / this.cells.length
140 | var factor = Math.pow(Math.min(64.0 / totalSize, 1), 0.4);
141 | this.sightRangeX = this.server.getConfig().serverViewBaseX / factor;
142 | this.sightRangeY = this.server.getConfig().serverViewBaseY / factor;
143 | this.a = {
144 | x: this.center.x - this.sightRangeX,
145 | y: this.center.y - this.sightRangeY,
146 | height: 2 * this.sightRangeY,
147 | width: 2 * this.sightRangeX
148 | }
149 | return this.a
150 | }
151 | shouldSend() {
152 | var a = this.send
153 | if (this.send) this.send = false;
154 | return a
155 | }
156 | changeColor(color) {
157 |
158 |
159 | }
160 | changeName(name) {
161 |
162 |
163 | }
164 | removeCell(cell) {
165 | var ind = this.cells.indexOf(cell)
166 | if (ind != -1) this.cells.splice(ind, 1)
167 | // console.log(this.cells.length)
168 | if (this.cells.length == 0) return this.onDeath()
169 | }
170 |
171 | }
--------------------------------------------------------------------------------
/source/ai/Minion.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /*
3 | OpenAgar - Open source web game
4 | Copyright (C) 2016 Andrew S
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Affero General Public License as published
8 | by the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Affero General Public License for more details.
15 |
16 | You should have received a copy of the GNU Affero General Public License
17 | along with this program. If not, see .
18 | */
19 | var Template = require('../core/PlayerTemplate.js');
20 |
21 | module.exports = class Minion extends Template {
22 | constructor(server, id, name, botid, parent) {
23 | super(id, server)
24 | this.parent = parent
25 | this.botid = botid
26 | this.isBot = true;
27 | this.isMinion = true;
28 | this.mouse = this.parent.mouse
29 |
30 | this.timer = {
31 | changeDir: 0,
32 | }
33 | this.gameData = {
34 | name: name,
35 | color: server.getRandomColor(),
36 | chatname: "",
37 | reservedChatNames: [],
38 | chkDeath: false
39 | }
40 |
41 | this.spawn()
42 | }
43 |
44 |
45 | onRemove(main) {
46 | this.parent.removeMinion(this)
47 | this.removed = true;
48 | }
49 | kick() {
50 | this.server.removeMinion(this)
51 | }
52 |
53 |
54 |
55 | spawn() {
56 | if (this.cells.size > 0 || this.removed) return;
57 |
58 |
59 | this.server.spawn(this)
60 |
61 |
62 | if (this.parent.pausem) this.frozen = true;
63 | }
64 |
65 |
66 | setRandom() {
67 | if (!this.a) return;
68 | var a = this.a
69 | this.mouse.x = Math.floor(a.width * Math.random()) + a.x;
70 | this.mouse.y = Math.floor(a.height * Math.random()) + a.y
71 | }
72 |
73 |
74 |
75 | }
--------------------------------------------------------------------------------
/source/ai/fakePlayer.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /*
3 | OpenAgar - Open source web game
4 | Copyright (C) 2016 Andrew S
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Affero General Public License as published
8 | by the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Affero General Public License for more details.
15 |
16 | You should have received a copy of the GNU Affero General Public License
17 | along with this program. If not, see .
18 | */
19 | var Template = require('../core/PlayerTemplate.js');
20 |
21 | module.exports = class FakePlayer extends Template {
22 | constructor(server, id, name, botid) {
23 | super(id, server)
24 |
25 | this.botid = botid
26 |
27 | this.isBot = true;
28 | this.gameData = {
29 | name: name,
30 | color: server.getRandomColor(),
31 | chatname: "",
32 | reservedChatNames: [],
33 | chkDeath: false
34 | }
35 |
36 | server.spawn(this)
37 | }
38 | onRemove(main) {
39 |
40 | }
41 |
42 | kick() {
43 | this.server.removeBot(this)
44 | }
45 |
46 | onDeath() {
47 | this.mass = 0;
48 | this.score = 0;
49 | }
50 | onSpawn() {
51 | this.alive = this.server.timer.time;
52 | }
53 |
54 | }
--------------------------------------------------------------------------------
/source/child/Player.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /*
3 | OpenAgar - Open source web game
4 | Copyright (C) 2016 Andrew S
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Affero General Public License as published
8 | by the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Affero General Public License for more details.
15 |
16 | You should have received a copy of the GNU Affero General Public License
17 | along with this program. If not, see .
18 | */
19 | module.exports = class Bot {
20 | constructor(id, server) {
21 | this.id = id
22 | this.team = 0;
23 | this.score = 0;
24 | this.mouse = {
25 | x: 0,
26 | y: 0
27 | }
28 | this.center = {
29 | x: 0,
30 | y: 0
31 | }
32 |
33 | this.server = server;
34 | this.cells = [];
35 |
36 | }
37 | onRemove(main) {
38 | this.cells.forEach((cell) => {
39 | main.removeNode(cell)
40 | })
41 | }
42 | addCell(cell) {
43 |
44 | if (this.cells.indexOf(cell) != -1) return;
45 | this.cells.push(cell)
46 |
47 | }
48 |
49 | onDeath() {
50 |
51 |
52 | }
53 | spawn() {
54 |
55 | this.server.spawn(this)
56 |
57 | }
58 | getScore(re) {
59 | if (this.cells.length == 0) return 0;
60 |
61 | var l = 0;
62 | this.cells.forEach((n) => {
63 | l += n.mass;
64 | })
65 | this.mass = l;
66 | this.score = Math.max(this.score, l)
67 | return this.score
68 |
69 | }
70 |
71 | getRandom() {
72 | if (!this.a) return;
73 | var a = this.a
74 | return {
75 | x: Math.floor(a.width * Math.random()) + a.x,
76 | y: Math.floor(a.height * Math.random()) + a.y
77 | }
78 |
79 | }
80 |
81 | calcView() {
82 | if (this.cells.length == 0) return
83 | var totalSize = 1.0;
84 | var x = 0,
85 | y = 0;
86 | // console.log(this.cells)
87 | this.cells.forEach((cell) => {
88 |
89 | if (!cell) return
90 | x += cell.position.x
91 | y += cell.position.y
92 | totalSize += cell.getSize();
93 | })
94 | this.center.x = x / this.cells.length
95 | this.center.y = y / this.cells.length
96 | var factor = Math.pow(Math.min(64.0 / totalSize, 1), 0.4);
97 | this.sightRangeX = this.server.getConfig().serverViewBaseX / factor;
98 | this.sightRangeY = this.server.getConfig().serverViewBaseY / factor;
99 | this.a = {
100 | x: this.center.x - this.sightRangeX,
101 | y: this.center.y - this.sightRangeY,
102 | height: 2 * this.sightRangeY,
103 | width: 2 * this.sightRangeX
104 | }
105 | return this.a
106 | }
107 |
108 | changeColor(color) {
109 |
110 |
111 | }
112 | changeName(name) {
113 |
114 |
115 | }
116 | removeCell(cell) {
117 | var ind = this.cells.indexOf(cell)
118 | if (ind != -1) this.cells.splice(ind, 1)
119 | // console.log(this.cells.length)
120 | if (this.cells.length == 0) return this.onDeath()
121 | }
122 |
123 | }
--------------------------------------------------------------------------------
/source/child/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | OpenAgar - Open source web game
3 | Copyright (C) 2016 Andrew S
4 | This program is free software: you can redistribute it and/or modify
5 | it under the terms of the GNU Affero General Public License as published
6 | by the Free Software Foundation, either version 3 of the License, or
7 | (at your option) any later version.
8 | This program is distributed in the hope that it will be useful,
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | GNU Affero General Public License for more details.
12 | You should have received a copy of the GNU Affero General Public License
13 | along with this program. If not, see .
14 | */
15 | var Manager = require('./manager.js')
16 | var manager = new Manager()
17 | var managers = new Map()
18 | //require('../../cpu.js').init('./data')
19 | process.on('message', function (msg) {
20 |
21 |
22 | if (msg.sid || msg.sid == 0) {
23 | var manager = managers.get(msg.sid)
24 | if (!manager) return;
25 | }
26 |
27 | switch (msg.type) {
28 | case 0: // init
29 |
30 | manager.init(msg)
31 | break;
32 | case 1: // addnodes
33 | manager.addNodes(msg.nodes)
34 | break;
35 | case 2: // deletenodes
36 | manager.removeNodes(msg.nodes)
37 | break;
38 | case 3: // movecode
39 | manager.moveCode(msg.nodes)
40 | break;
41 | case 4: // assign
42 | manager.assign(msg.nodes)
43 | break;
44 | case 5:
45 | manager.addBot(msg.id, msg.bot)
46 | break;
47 | case 6: // stop
48 | managers.forEach(function (m) {
49 | m.onRemove()
50 | })
51 | process.exit(0)
52 | break;
53 | case 7: // event
54 | manager.event(msg)
55 | break;
56 |
57 | case 8: // assign/deassign
58 | if (msg.a || msg.a === 0) {
59 | var mn = new Manager(msg.a)
60 |
61 | managers.set(msg.a, mn)
62 | } else if (msg.da || msg.a === 0) {
63 | var mn = manager.get(msg.da)
64 | if (mn) mn.onRemove()
65 | manager.delete(msg.da)
66 | }
67 |
68 |
69 | break;
70 | case 9: // pause;
71 |
72 | manager.pause(msg)
73 | break;
74 |
75 | }
76 |
77 |
78 | })
--------------------------------------------------------------------------------
/source/child/manager.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /*
3 | OpenAgar - Open source web game
4 | Copyright (C) 2016 Andrew S
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU Affero General Public License as published
7 | by the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 | This program is distributed in the hope that it will be useful,
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | GNU Affero General Public License for more details.
13 | You should have received a copy of the GNU Affero General Public License
14 | along with this program. If not, see .
15 | */
16 | var HashBounds = require('../modules/HashBounds.js')
17 | var Node = require('./node.js')
18 | var Bot = require('../ai/Bot.js')
19 | var Player = require('./Player.js')
20 | var TooBusy = require('toobusy-js')
21 |
22 |
23 |
24 |
25 | module.exports = class Manager {
26 | constructor(id) {
27 | this.id = id;
28 | this.addedHash = [];
29 |
30 | this.lagDel = false;
31 | this.toSend = [];
32 | this.map = new Map()
33 | this.bots = new Map()
34 | this.config = {};
35 | this.s = false;
36 |
37 | this.haveTeams = false;
38 | this.paused = false;
39 | this.events = {}
40 | this.bounds;
41 | this.timers = {
42 | a: 0,
43 | b: 0,
44 | c: 0
45 | }
46 | this.lag = false
47 | this.players = new Map();
48 | setInterval(function () {
49 | var lag = TooBusy.lag();
50 | this.lag = lag > 150
51 | if (this.lag) this.emit("lag", lag)
52 | }.bind(this), 4000)
53 | }
54 | addNodes(nodes) {
55 |
56 | nodes.forEach((node) => {
57 |
58 | if (this.addedHash[node.id]) {
59 |
60 | var n = this.map.get(node.id)
61 | n.set(node)
62 | this.nodes.update(n)
63 | return;
64 |
65 | };
66 |
67 | this.addedHash[node.id] = true;
68 | var owner = false
69 | if (node.owner && node.type == 0) {
70 | owner = this.bots.get(node.owner)
71 | if (!owner) {
72 | owner = this.players.get(node.owner)
73 | if (!owner) {
74 | owner = new Player(node.owner, this)
75 | this.players.set(node.owner, owner)
76 | }
77 | }
78 |
79 | }
80 |
81 |
82 | var n = new Node(node, owner)
83 | n.bounds = {
84 | x: n.position.x - n.size,
85 | y: n.position.y - n.size,
86 | width: n.size * 2,
87 | height: n.size * 2
88 | }
89 | this.nodes.insert(n)
90 | this.map.set(node.id, n)
91 |
92 | })
93 | }
94 | pause(msg) {
95 | this.paused = msg.p
96 | }
97 | updateLB() {
98 | var players = [];
99 |
100 | function insert(pl) {
101 | if (!pl.cells.length) return;
102 | pl.getScore()
103 | if (!pl.mass) return;
104 | players.push({
105 | i: pl.id,
106 | m: pl.mass
107 | })
108 | }
109 |
110 | this.bots.forEach((bot) => {
111 | insert(bot)
112 | })
113 | this.players.forEach((player) => {
114 | insert(player)
115 |
116 | })
117 |
118 | var amount = this.getConfig().leaderBoardLen;
119 |
120 | var lb = players.sort(function (a, b) {
121 | return b.m - a.m;
122 | }).slice(0, amount);
123 |
124 | return lb;
125 | }
126 |
127 | spawn(bot) {
128 | this.toSend.push({
129 | id: bot.id,
130 | action: 1
131 | })
132 |
133 | }
134 | ejectMass(bot) {
135 | this.toSend.push({
136 | id: bot.id,
137 | action: 2
138 | })
139 | }
140 | splitPlayer(bot) {
141 | this.toSend.push({
142 | id: bot.id,
143 | action: 3
144 | })
145 | }
146 | removeNode(node) {
147 | node.destroyed = true;
148 | node.dead = true;
149 | this.nodes.delete(node)
150 | this.map.delete(node.id)
151 | this.addedHash[node.id] = false;
152 | node.onDelete(this)
153 | }
154 |
155 | removeNodes(nodes) {
156 | nodes.forEach((node) => {
157 | var n = this.map.get(node.id)
158 | if (n) this.removeNode(n)
159 | })
160 |
161 | }
162 | asign() {
163 |
164 | }
165 | getConfig() {
166 | return this.config
167 | }
168 | moveCode(nodes) {
169 |
170 | nodes.forEach((node) => {
171 | var n = this.map.get(node.id)
172 | if (n) {
173 |
174 | n.position.x = node.x
175 | n.position.y = node.y
176 | n.bounds = {
177 | x: n.position.x - n.size,
178 | y: n.position.y - n.size,
179 | width: n.size * 2,
180 | height: n.size * 2
181 | }
182 | this.nodes.update(n)
183 | }
184 | })
185 | }
186 | getRandomPos() {
187 | var x = Math.floor(this.bounds.width * Math.random());
188 | var y = Math.floor(Math.random() * this.bounds.height);
189 | return {
190 | x: x,
191 | y: y
192 | };
193 | }
194 | init(msg) {
195 |
196 | this.config = msg.config;
197 | this.haveTeams = msg.teams;
198 | this.bounds = msg.bounds;
199 | this.nodes = new HashBounds(5, 3, Math.max(this.bounds.width, this.bounds.height) + 700, 700); // 32 min, 256 max
200 | try {
201 |
202 | clearInterval(this.interval)
203 | } catch (e) {
204 |
205 | }
206 | this.interval = setInterval(function () {
207 | if (this.paused) return;
208 | this.loop()
209 | }.bind(this), 50)
210 | this.slowInt = setInterval(function () {
211 | this.slowLoop()
212 | }.bind(this), 5000)
213 | this.on('delPlayer', function (ps) {
214 |
215 | this.removeClient(ps)
216 |
217 |
218 | }.bind(this))
219 | }
220 | onRemove() {
221 | try {
222 | clearInterval(this.interval)
223 | } catch (e) {
224 |
225 | }
226 | try {
227 | clearInterval(this.slowInt)
228 | } catch (e) {
229 |
230 | }
231 | this.bots.forEach((b) => {
232 | b.onRemove(this)
233 | })
234 | this.players.forEach((b) => {
235 | b.onRemove(this)
236 | })
237 | this.addedHash = false;
238 | this.nodes = false
239 | this.toSend = false;
240 | this.map = false
241 | this.bots = false
242 | this.config = false;
243 | this.s = false;
244 | this.haveTeams = false;
245 | this.events = false
246 | this.timers = false
247 | this.players = false
248 |
249 | }
250 |
251 | removeClient(id) {
252 | var a = this.bots.get(id)
253 | if (a) {
254 | this.bots.delete(id)
255 | a.onRemove(this)
256 | return;
257 | }
258 | var a = this.players.get(id)
259 | if (a) {
260 | this.players.delete(id)
261 | a.onRemove(this)
262 | return;
263 | }
264 | }
265 | addBot(id, bot) {
266 | this.bots.set(id, new Bot(id, this, bot))
267 | }
268 | emit(event, data) {
269 | var a = {
270 | e: event,
271 | d: data
272 | }
273 | this.toSend.push(a)
274 | }
275 | event(msg) {
276 | var e = msg.e
277 | var d = msg.d
278 | if (this.events[e]) this.events[e](d)
279 | }
280 | on(e, f) {
281 |
282 | this.events[e] = f
283 | }
284 | clearEvents() {
285 | this.events = {};
286 | }
287 | slowLoop() { // 5 s
288 | if (this.timers.c >= 1) {
289 | var mass = this.getTotalMass()
290 |
291 | this.emit('totmass', mass)
292 |
293 | this.timers.c = 12
294 | } else this.timers.c++;
295 | }
296 | loop() { // 0.005 s
297 | if (this.lag) {
298 | this.lagDel = !this.lagDel
299 | if (this.lagDel) return;
300 |
301 | }
302 | setTimeout(function () {
303 | this.updatePlayers()
304 | }.bind(this), 1)
305 |
306 |
307 | if (this.timers.a >= 100) {
308 | var lb = this.updateLB()
309 | this.checkMass()
310 | if (lb.length != 0) this.emit('lb', lb)
311 |
312 | this.timers.a = 0;
313 | } else this.timers.a++;
314 |
315 |
316 | if (this.timers.b >= 10) {
317 | if (this.bots.size > 0) {
318 |
319 | this.bots.forEach((bot) => {
320 | setTimeout(function () {
321 | bot.update()
322 | }, 1)
323 | if (bot.shouldSend()) this.toSend.push({
324 | i: bot.id,
325 | m: bot.mouse
326 | })
327 | })
328 |
329 | }
330 | if (this.toSend[0]) this.send(this.toSend)
331 |
332 | this.toSend = [];
333 | this.timers.b = 0;
334 | } else this.timers.b++;
335 |
336 |
337 |
338 |
339 |
340 | }
341 | updatePlayers() {
342 | var final = [];
343 | if (this.players.size == 0 && this.bots.size == 0) return;
344 | this.players.forEach((player) => {
345 | if (player.cells.length == 0) return;
346 | player.cells.forEach((cell) => {
347 | var list = [];
348 | this.nodes.forEach(cell.getCheck(), (node) => {
349 | if (node.id != cell.id) {
350 |
351 | if (this.lag || cell.checkSend(node)) list.push(node.id)
352 |
353 | }
354 | })
355 | final.push({
356 | i: cell.id,
357 | l: list
358 | })
359 | })
360 | })
361 | this.bots.forEach((player) => {
362 | if (player.cells.length == 0) return;
363 | player.cells.forEach((cell) => {
364 | var list = [];
365 | this.nodes.forEach(cell.getCheck(), (node) => {
366 | if (node.id != cell.id) {
367 |
368 | if (this.lag || cell.checkSend(node)) list.push(node.id)
369 | }
370 | })
371 |
372 | final.push({
373 | i: cell.id,
374 | l: list
375 | })
376 | })
377 | })
378 | if (final.length == 0) return;
379 | var a = {
380 | d: final,
381 | p: true
382 | }
383 |
384 | this.send(a)
385 |
386 | }
387 | send(data) {
388 |
389 | try {
390 | process.send({
391 | id: this.id,
392 | data: data
393 | })
394 |
395 | } catch (e) {
396 | process.exit(0)
397 | }
398 | }
399 | getTotalMass() {
400 | var amount = 0;
401 |
402 | this.map.forEach((node, i) => {
403 | if (node.dead) {
404 | this.nodes.delete(i)
405 | this.map.delete(i)
406 | this.addedHash[node.id] = false;
407 | return;
408 | }
409 | amount += node.mass
410 | })
411 | return amount;
412 | }
413 | checkMass() {
414 | var list = [];
415 | var max = this.config.playerMaxMass
416 | this.players.forEach((player) => {
417 | player.cells.forEach((cell) => {
418 | if (cell.mass > max) list.push(cell.id)
419 | })
420 |
421 | })
422 | this.bots.forEach((player) => {
423 | player.cells.forEach((cell) => {
424 | if (cell.mass > max) list.push(cell.id)
425 | })
426 |
427 | })
428 | if (list.length == 0) return;
429 | this.emit('mass', list)
430 | }
431 |
432 | other() {
433 |
434 | }
435 |
436 | }
437 |
--------------------------------------------------------------------------------
/source/child/node.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | module.exports = class Node {
4 | constructor(node, owner) {
5 | this.type = node.type;
6 | this.position = node.position;
7 | this.bounds = null;
8 | this.id = node.id;
9 | this.owner = owner
10 | this.size = node.size;
11 | this.speed = node.speed
12 |
13 | this.mass = node.mass;
14 |
15 | this.destroyed = false;
16 | this.init()
17 |
18 | }
19 |
20 | init() {
21 |
22 | if (this.owner) {
23 | this.owner.addCell(this)
24 | }
25 | }
26 | getCheck() { // get checking bounds
27 | var dif = Math.min(100 / this.size, 2) * 25; // smaller nodes have bigger collision range since they go faster.
28 |
29 | return {
30 | x: this.bounds.x - dif,
31 | y: this.bounds.y - dif,
32 | width: this.bounds.width + dif * 2,
33 | height: this.bounds.height + dif * 2
34 |
35 | }
36 |
37 | }
38 |
39 |
40 |
41 | checkSend(node) {
42 | var size = node.size + this.size + (Math.min(100 / this.size, 1.1) * 100) // smaller nodes have bigger collision range since they go faster. Fine tunes previous check.
43 |
44 | /*
45 | ____________________________________
46 | / I tried to make a flowchart, but I \
47 | \ failed. /
48 | ------------------------------------
49 | \
50 | \
51 |
52 | [-]
53 | (+)=C
54 | | |
55 | OOO
56 |
57 |
58 | */
59 |
60 | var x = this.position.x - node.position.x
61 | var y = this.position.y - node.position.y
62 | return (size * size >= x * x + y * y)
63 | }
64 | set(node) {
65 | this.type = node.type || this.type;
66 | this.position = node.position || this.position;
67 | this.bounds = node.bounds || this.bounds;
68 |
69 | this.size = node.size || this.size;
70 |
71 |
72 | this.mass = node.mass || this.mass;
73 | this.speed = node.speed || this.speed
74 | }
75 | getSize() {
76 | return this.mass
77 | }
78 | onDelete(main) {
79 | if (this.owner) this.owner.removeCell(this)
80 | }
81 |
82 |
83 |
84 | }
--------------------------------------------------------------------------------
/source/commands/index.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 |
3 | list: {
4 | addbot: require('./lib/addBot.js'),
5 | kick: require('./lib/kick.js'),
6 | pause: require('./lib/pause.js'),
7 | kickbots: require('./lib/kickbots.js'),
8 | list: require('./lib/list.js'),
9 | help: function (str, main, log) {
10 | log("|-----------------Available Commands------------------|")
11 | log("| Help | Shows help for commands |")
12 | log("| Stop | Stops the server |")
13 | log("| List | List players, bots, etc |")
14 | log("| Plugin | Plugin command |")
15 | log("| Kick | Kick a player |")
16 | log("| Ban | Ban a player |")
17 | log("| Server | Multi-Server command |")
18 | log("| Pause | Pause the game |")
19 | log("| Addbot | Add bots |")
20 | log("| Debug | Toggle debug console |")
21 | log("| Update | Update software |")
22 | log("| Restart | Schedule restarts |")
23 | log("| Kickbots | Kick bots |");
24 |
25 | if (_lvl() != 0) {
26 | log("| Mod | OpenAgar Sys Moderation |");
27 | }
28 | main.pluginService.addToHelp.forEach((cmd) => {
29 | log(cmd)
30 | })
31 | log("|-----------------------------------------------------|")
32 |
33 | }
34 | },
35 | serverService: {
36 | server: require('./lib/server.js'),
37 | startv: require('./lib/startv.js'),
38 | stop: require('./lib/stop.js'),
39 | ban: require('./lib/ban.js'),
40 | redraw: require('./lib/redraw.js'),
41 | plugin: require('./lib/plugin.js'),
42 | update: require('./lib/update.js'),
43 | restart: require('./lib/restart.js'),
44 | debug: require('./lib/debug.js'),
45 | mod: function (a, b, c) {
46 | _mod(a, b, c)
47 | }
48 | },
49 | chat: {
50 | help: function (str, main, player, log) {
51 | log("================= Commands =================")
52 | log("Help | Shows help for commands")
53 | main.pluginService.chatA.forEach((cmd) => {
54 | log(cmd)
55 | })
56 | log("============================================")
57 |
58 | }
59 |
60 | }
61 |
62 |
63 | };
64 |
--------------------------------------------------------------------------------
/source/commands/lib/addBot.js:
--------------------------------------------------------------------------------
1 | module.exports = function (str, main, log) {
2 | str = str.split(" ")
3 | var amount = parseInt(str[1])
4 |
5 | if (isNaN(amount)) amount = 1
6 | main.addBots(amount)
7 |
8 | log("gre{[OpenAgar]} ".styleMe() + amount + " bots added")
9 | }
--------------------------------------------------------------------------------
/source/commands/lib/ban.js:
--------------------------------------------------------------------------------
1 | module.exports = function (str, ss, log) {
2 | var split = str.split(" ")
3 | if (split[1] == "record") {
4 |
5 | require('fs').writeFileSync(__dirname + '/../../../ban.txt', ss.globalData.ban.join("\n"))
6 | log("gre{[OpenAgar]} Succesfully recorded ban".styleMe())
7 |
8 | return;
9 |
10 | }
11 | var id = parseInt(split[1])
12 | if (isNaN(id)) {
13 |
14 | return log("cya{[OpenAgar]} Please specify a player id!".styleMe())
15 | }
16 | var player = ss.getPlayer(id)
17 | if (!player) return log("cya{[OpenAgar]} That player wasnt found!".styleMe())
18 | if (player.isBot) return log("cya{[OpenAgar]} That player is a bot!".styleMe())
19 | var ip = player.socket.remoteAddress
20 | ss.globalData.ban.push(ip)
21 | var count = 0;
22 | ss.clients.forEach((client) => {
23 | if (client._remoteAddress == ip) {
24 | count++;
25 | client._player.kick("You have been banned!")
26 | }
27 |
28 | })
29 |
30 | log("gre{[OpenAgar]} Banned ".styleMe() + count + " players with an ip of " + player.socket.remoteAddress)
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/source/commands/lib/debug.js:
--------------------------------------------------------------------------------
1 | module.exports = function(str,ss,log) {
2 | if (ss._DEBUG) {
3 | ss._DEBUG = false;
4 |
5 | ss.controller.shellService.select(ss.selected.id)
6 | console.log("Gettting off the debug console...")
7 | } else {
8 | ss._DEBUG = true;
9 |
10 | ss.controller.shellService.select(0)
11 | console.log("Debug console loading...")
12 | }
13 |
14 | }
--------------------------------------------------------------------------------
/source/commands/lib/kick.js:
--------------------------------------------------------------------------------
1 | module.exports = function (str, main, log) {
2 | var id = parseInt(str.split(" ")[1])
3 | if (isNaN(id)) {
4 |
5 | return log("cya{[OpenAgar]} Please specify a player id!".styleMe())
6 | }
7 | var player = main.getPlayer(id)
8 | if (!player) return log("cya{[OpenAgar]} That player wasnt found!".styleMe())
9 |
10 | player.kick()
11 | log("gre{[OpenAgar]} Succesfully kicked ".styleMe() + player.gameData.name)
12 |
13 | }
--------------------------------------------------------------------------------
/source/commands/lib/kickbots.js:
--------------------------------------------------------------------------------
1 | module.exports = function(str,main,log) {
2 | str = str.split(" ");
3 | var count = parseInt(str[1])
4 | if (isNaN(count)) count = -1;
5 | var kicked = 0;
6 | main.bots.every(function(bot) {
7 | main.removeBot(bot)
8 | kicked ++;
9 | if (kicked >= count && count > 0) return false;
10 | return true;
11 | })
12 | log("gre{[OpenAgar]} Kicked ".styleMe() + kicked + " bots")
13 | }
14 |
--------------------------------------------------------------------------------
/source/commands/lib/libraries:
--------------------------------------------------------------------------------
1 | https://raw.githubusercontent.com/AJS-development/OAPlugins/master/plugins.json
--------------------------------------------------------------------------------
/source/commands/lib/list.js:
--------------------------------------------------------------------------------
1 | "use strict"
2 | module.exports = function (str, main, log) {
3 | var fill = function (a, num, char) {
4 | char = char || " "
5 | num -= a.length
6 | for (var i = 0; i < num; i++) {
7 | a += char
8 | }
9 | return a
10 | }
11 | str = str.split(" ")
12 | if (str[1] == "players") {
13 |
14 | if (main.clients.size == 0) return log("cya{[OpenAgar]} There are no players in the game!".styleMe())
15 | // 50
16 | log("|------------------------------------Players-----------------------------------|")
17 | log("| Id | Ip | Name | ChatName | LBrank | posX | posY |")
18 | main.clients.forEach((client) => {
19 |
20 |
21 | var name = client.gameData.name
22 | var chatname = client.gameData.chatName
23 | name = name || "An Unamed Cell";
24 | var rank = client.rank || "NA";
25 | var center = {
26 | x: "NA",
27 | y: "NA"
28 | }
29 |
30 | if (client.center.x) {
31 | center = client.center
32 | center.y = Math.round(center.y)
33 | center.x = Math.round(center.x)
34 | }
35 | log("|" + fill(client.id.toString(), 5) + "|" + fill(client.socket.remoteAddress, 12) + "|" + fill(name, 16) + "|" + fill(chatname, 18) + "|" + fill(rank.toString(), 8) + "|" + fill(center.x.toString(), 7) + "|" + fill(center.y.toString(), 6) + "|")
36 | })
37 |
38 | } else if (str[1] == "bots") {
39 | if (main.bots.size == 0) return log("cya{[OpenAgar]} There are no bots in the game!".styleMe())
40 | log("|-------------------------------------Bots-------------------------------------|")
41 | log("| Id | BotId | Name | LBrank | posX | posY | Alive | Mass |")
42 | main.bots.forEach((client) => {
43 |
44 |
45 | var name = client.gameData.name
46 | var chatname = client.gameData.chatName
47 | name = name || "An Unamed Cell";
48 | var rank = client.rank || "NA";
49 | var center = {
50 | x: "NA",
51 | y: "NA"
52 | }
53 | var alive = main.timer.time - client.alive
54 | alive = Math.round(alive / 6000)
55 | alive = alive / 10
56 |
57 | if (client.cells.peek()) {
58 | center = client.cells.peek().position
59 | center.y = Math.round(center.y)
60 | center.x = Math.round(center.x)
61 | }
62 |
63 | log("|" + fill(client.id.toString(), 5) + "|" + fill(client.botid.toString(), 7) + "|" + fill(name, 16) + "|" + fill(rank.toString(), 8) + "|" + fill(center.x.toString(), 9) + "|" + fill(center.y.toString(), 9) + "|" + fill(alive.toString(), 9) + "|" + fill(Math.round(client.mass).toString(), 8) + "|")
64 | })
65 | } else if (str[1] == "minions") {
66 | if (main.minions.size == 0) return log("cya{[OpenAgar]} There are no minions in the game!".styleMe())
67 | log("|-----------------------------------Minions------------------------------------|")
68 | log("| Id | BotId | Name | LBrank | posX | posY | OwnerId | Mass |")
69 | main.minions.forEach((client) => {
70 |
71 |
72 | var name = client.gameData.name
73 | var chatname = client.gameData.chatName
74 | name = name || "An Unamed Cell";
75 | var rank = client.rank || "NA";
76 | var center = {
77 | x: "NA",
78 | y: "NA"
79 | }
80 |
81 |
82 | if (client.cells.peek()) {
83 | center = client.cells.peek().position
84 | center.y = Math.round(center.y)
85 | center.x = Math.round(center.x)
86 | }
87 |
88 | log("|" + fill(client.id.toString(), 5) + "|" + fill(client.botid.toString(), 7) + "|" + fill(name, 16) + "|" + fill(rank.toString(), 8) + "|" + fill(center.x.toString(), 9) + "|" + fill(center.y.toString(), 9) + "|" + fill(client.parent.id.toString(), 9) + "|" + fill(Math.round(client.mass).toString(), 8) + "|")
89 | })
90 | } else if (str[1] == "help") {
91 | log("|-------Available Commands for List-------|")
92 | log("|players | Lists the players in the server|")
93 | log("|bots | Lists the bots in the server |")
94 | log("|minions | Lists the minions in the server|")
95 | log("|help | Displays a list of actions |")
96 | log("|-----------------------------------------|")
97 | } else {
98 | log("cya{[OpenAgar]} Action not found, please do list help to see a list of actions".styleMe())
99 |
100 | }
101 |
102 | }
--------------------------------------------------------------------------------
/source/commands/lib/pause.js:
--------------------------------------------------------------------------------
1 | module.exports = function(str,main,log) {
2 | main.pause()
3 | if (main.paused) {
4 | log("gre{[OpenAgar]} Paused the game".styleMe())
5 | } else {
6 | log("gre{[OpenAgar]} Unpaused the game".styleMe())
7 | }
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/source/commands/lib/plugin.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var request = require('minirequest')
3 | var fs = require('fs')
4 | function search(a,list) {
5 |
6 | var title = [];
7 | var desc = [];
8 | var others = []
9 | list.forEach((item)=>{
10 | if (item.name) {
11 | var b = item.name.toLowerCase();
12 | if (b.indexOf(a.toLowerCase()) != -1) {
13 | title.push(item)
14 | return;
15 | }
16 | }
17 | if (item.description) {
18 | if (item.description.toLowerCase().indexOf(a.toLowerCase()) != -1) {
19 | desc.push(item)
20 | return;
21 | }
22 | }
23 | var b = a.split(" ")
24 | var f = 0;
25 | b.every((c)=>{
26 | if (f > 5) {
27 | others.push(item)
28 | return false;
29 |
30 | }
31 | if (item.name && item.name.toLowerCase().indexOf(c.toLowerCase()) != -1) {
32 | f += 2;
33 | return true;
34 | }
35 | if (item.description && item.description.toLowerCase().indexOf(c.toLowerCase()) != -1) {
36 | f ++;
37 | return true;
38 | }
39 | })
40 |
41 |
42 | })
43 | var final = [];
44 |
45 | final = final.concat(title);
46 | final = final.concat(desc);
47 | final = final.concat(others);
48 | return final
49 |
50 | }
51 |
52 | module.exports = function(str,ss,log) {
53 | var main = ss.selected
54 | str = str.split(" ")
55 | var action = str[1]
56 |
57 | switch (action) {
58 | case "add":
59 | if (!str[2]) return log("Please specify the plugin name!")
60 | if (!str[3]) return log("Please specify the plugin url!")
61 | log("Connecting to " + str[3])
62 | request(str[3],function(e,r,b) {
63 | if (!e && r.responseCode == 200 && b) {
64 | fs.writeFileSync(__dirname + '/../../plugins/' + str[2] + '.ajs',b)
65 | log("Plugin succesfully downloaded. Reloading plugins")
66 | setTimeout(function() {
67 | main.pluginService.reload()
68 | },1000)
69 | } else {
70 | return log("That URL was not found!")
71 | }
72 |
73 | })
74 | break;
75 | case "install":
76 | if (!str[2]) return log("Please specify a plugin name!")
77 | var libraries = fs.readFileSync(__dirname + '/libraries',"utf8")
78 | libraries = libraries.split('\n')
79 | var done = false;
80 | var count = 0;
81 | var am = 0;
82 | libraries.forEach((library)=>{
83 | library = library.replace(/\s/g,"")
84 | if (!library) return;
85 | count ++;
86 | am ++;
87 | request(library + "?" + Math.floor(Math.random() * 1000),(e,r,b)=>{
88 |
89 | if (!e && r.statusCode == 200 && b) {
90 | var plugins = JSON.parse(b)
91 | plugins.every((plugin)=>{
92 | if (done) return false;
93 | if (!plugin.name || !plugin.src || str[2] != plugin.name) return true;
94 | done = true;
95 | log("Found plugin. Downloading...")
96 | request(plugin.src + "?" + Math.floor(Math.random() * 1000),(e,r,b)=>{
97 | if (!e && r.statusCode == 200 && b) {
98 | fs.writeFileSync(__dirname + '/../../plugins/' + plugin.name + '.ajs',b)
99 | log("Plugin succesfully downloaded. Reloading plugins")
100 | setTimeout(function() {
101 | main.pluginService.reload()
102 | },1000)
103 | } else {
104 | log("URL " + plugin.src + " is not accesable!")
105 | }
106 | })
107 | return false;
108 | })
109 | } else {
110 | log("Failed to connect to library " + library)
111 | }
112 | am --;
113 | if (am <= 0) {
114 | if (!done) log("Plugin " + str[2] + " was not found. Search for plugins using plugin search [keyword]")
115 | }
116 | })
117 | })
118 | log("Requesting plugins from " + count + " libraries")
119 |
120 | break;
121 | case "reload":
122 | log("Reloading plugins...")
123 | main.pluginService.reload()
124 | break;
125 | case "library":
126 | if (!str[2]) return log("Please specify the library file url")
127 | var libraries = fs.readFileSync(__dirname + '/libraries',"utf8")
128 | libraries = libraries.split('\n')
129 | var out = [];
130 | libraries.forEach((library)=>{
131 | library = library.replace(/\s/g,"")
132 | if (library) out.push(library)
133 | })
134 | out.push(str[2])
135 | fs.writeFileSync(__dirname + '/libraries',out.join("\n"))
136 | log("Added library " + str[2])
137 | break;
138 | case "search":
139 | var a = str.slice(2).join(" ")
140 | if (!a) return log("Please enter something to search")
141 | var libraries = fs.readFileSync(__dirname + '/libraries',"utf8").split("\n")
142 | var list = [];
143 | var count = 0;
144 | var out = [];
145 | libraries.forEach((library)=>{
146 | library = library.replace(/\s/g,"")
147 | if (!library) return;
148 | count ++;
149 | request(library + "?" + Math.floor(Math.random() * 1000),(e,r,b)=>{
150 |
151 | if (!e && r.statusCode == 200 && b) {
152 | list = list.concat(JSON.parse(b))
153 | } else {
154 |
155 | log("Couldnt connect to " + library)
156 |
157 | }
158 | count --;
159 | if (count <= 0) {
160 | var items = search(a,list)
161 |
162 | if (items.length == 0) return log("No items were found with the search " + a)
163 | log("Search results for " + a + " :");
164 | items.forEach((item)=>{
165 | log(" " + item.name + "\n Description: "+ item.description);
166 |
167 | })
168 | }
169 | })
170 | })
171 | break;
172 | default:
173 | log("Command not found. Available commands: install, add, library, search")
174 | break;
175 |
176 | }
177 | }
178 |
--------------------------------------------------------------------------------
/source/commands/lib/redraw.js:
--------------------------------------------------------------------------------
1 | module.exports = function(str,ss,log) {
2 | log("gre{[OpenAgar]} Redrawing...".styleMe())
3 | ss.controller.shellService.writeLog(function() {
4 | log("gre{[OpenAgar]} Done".styleMe())
5 | })
6 |
7 | }
--------------------------------------------------------------------------------
/source/commands/lib/reload.js:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/source/commands/lib/reset.js:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/source/commands/lib/restart.js:
--------------------------------------------------------------------------------
1 | module.exports = function(str,ss,log) {
2 |
3 | str = str.split(" ")
4 |
5 | if (str[1] == "all") {
6 | var time = parseInt(str[2])
7 | if (str[2] == "now" || time == 0) {
8 |
9 |
10 | ss.restartAll()
11 | ss.controller.shellService.drawSplash()
12 | log("gre{[OpenAgar]} Restarted all servers".styleMe())
13 | return;
14 | }
15 | if (isNaN(time)) return log("Please specify time, in minutes, or type 'restart now' to restart now")
16 | setTimeout(function() {
17 | console.log('\033[2J');
18 |
19 | ss.restartAll()
20 | ss.controller.shellService.drawSplash()
21 | log("gre{[OpenAgar]} Restarted all servers".styleMe())
22 | },60000 * time)
23 |
24 | } else {
25 | var time = parseInt(str[1])
26 | if (str[1] == "now" || time == 0) {
27 | process.stdout.write("\u001b[2J\u001b[0;0H");
28 | ss.restartSelected()
29 | log("gre{[OpenAgar]} Restarted selected server".styleMe())
30 | return;
31 | }
32 | if (isNaN(time)) return log("Please specify time, in minutes, or type 'restart now' to restart now")
33 | setTimeout(function() {
34 | process.stdout.write("\u001b[2J\u001b[0;0H");
35 | ss.restartSelected()
36 | log("gre{[OpenAgar]} Restarted selected server".styleMe())
37 | },60000 * time)
38 |
39 |
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/source/commands/lib/save.js:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/source/commands/lib/server.js:
--------------------------------------------------------------------------------
1 | module.exports = function (str, ss, log) {
2 | var split = str.split(" ")
3 |
4 | if (split[1] == "list") {
5 | log("gre{[OpenAgar]} Listing servers...".styleMe())
6 | var servers = ss.servers
7 | log("|------------------------------------Servers-----------------------------------|")
8 | log("| Id | Name | ScreenName | Players | Bots | Uptime | Status |")
9 | var fill = function (a, num, char) {
10 | char = char || " "
11 | num -= a.length
12 | for (var i = 0; i < num; i++) {
13 | a += char
14 | }
15 | return a
16 | }
17 |
18 | var time = Date.now()
19 | servers.forEach(function (server) {
20 | var upt = time - server.timer.init
21 | upt = (upt / 6000) >> 0
22 | upt = upt / 10
23 | var status = "";
24 |
25 | if (server.selected && server.isMain) {
26 | status = "[Selected][M]";
27 | } else if (server.selected) {
28 | status = "[Selected]"
29 | } else if (server.isMain) {
30 | status = "[Main]"
31 | }
32 |
33 | log("|" + fill(server.id.toString(), 5) + "|" + fill(server.name, 15) + "|" + fill(server.scname, 16) + "|" + fill(server.clients.size.toString(), 9) + "|" + fill(server.bots.size.toString(), 6) + "|" + fill(upt.toString(), 8) + "|" + fill(status, 13) + "|")
34 | });
35 |
36 | } else if (split[1] == "create") {
37 | var name = split[2]
38 |
39 | if (!name) {
40 |
41 | return log("cya{[OpenAgar]} Please provide a name!".styleMe())
42 | }
43 | var configOv = Util.argsParser(str, 3);
44 |
45 | var config = {};
46 | for (var i in ss.defconfig) {
47 | config[i] = ss.defconfig[i];
48 | }
49 | for (var i in configOv) {
50 | config[i] = configOv[i];
51 | }
52 | if (ss.createServer(name, name, config, false)) log("gre{[OpenAgar]} Server succesfully created".styleMe());
53 | else return log("yel{[OpenAgar]} Could not create server".styleMe())
54 |
55 | ss.reloadInfoP()
56 |
57 | } else if (split[1] == "remove") {
58 | var id = parseInt(split[2])
59 | if (isNaN(id)) return log("cya{[OpenAgar]} Please specify a server id!".styleMe())
60 |
61 | if (ss.removeServer(id)) log("gre{[OpenAgar]} Removed server".styleMe());
62 | else return log("yel{[OpenAgar]} Failed to remove server. Check to make sure it is not main or is not selected.".styleMe())
63 | ss.reloadInfoP()
64 | } else if (split[1] == "select") {
65 | if (!split[2]) {
66 | log("cya{[OpenAgar]} Please specify a server ids".styleMe());
67 | return;
68 | }
69 | if (ss.select(parseInt(split[2]), function () {
70 | log("gre{[OpenAgar]} Successfully switched servers".styleMe())
71 |
72 | })) console.log("gre{[OpenAgar]} Switching servers...".styleMe());
73 | else
74 | log("yel{[OpenAgar]} That server doesnt exist or is already selected!".styleMe());
75 | } else {
76 | log("cya{[OpenAgar]} Please specify a command! (list, select,remove,create)".styleMe());
77 | }
78 |
79 |
80 | }
--------------------------------------------------------------------------------
/source/commands/lib/startv.js:
--------------------------------------------------------------------------------
1 | module.exports = function(serverService,txt) {
2 |
3 |
4 | }
5 |
--------------------------------------------------------------------------------
/source/commands/lib/stop.js:
--------------------------------------------------------------------------------
1 | module.exports = function(str,serverService) {
2 | console.log("gre{[OpenAgar]} Closing Server".styleMe())
3 | exit(0);
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/source/commands/lib/update.js:
--------------------------------------------------------------------------------
1 | module.exports = function(str,ss,log) {
2 | if (ss._dwe) ss.updater.update(); else {
3 | ss._dwe = true;
4 | setTimeout(function() {
5 | ss._dwe = false;
6 | },5000)
7 | log("Are you sure you want to update? Enter command again to proceed.")
8 |
9 |
10 | }
11 |
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/source/core/GUIHandler.js:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/source/core/GraphicalInterface.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 |
--------------------------------------------------------------------------------
/source/core/PlayerTemplate.js:
--------------------------------------------------------------------------------
1 | "use strict"
2 | /*
3 | OpenAgar - Open source web game
4 | Copyright (C) 2016 Andrew S
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Affero General Public License as published
8 | by the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Affero General Public License for more details.
15 |
16 | You should have received a copy of the GNU Affero General Public License
17 | along with this program. If not, see .
18 | */
19 |
20 |
21 | module.exports = class PlayerTemplate {
22 | constructor(id, server) {
23 | this.id = id;
24 |
25 | this.server = server;
26 |
27 | this.mouse = {
28 | x: 0,
29 | y: 0
30 | }
31 | this.center = {
32 | x: 0,
33 | y: 0
34 | }
35 | this.owning = new Map();
36 | this.mass = 0;
37 | this.frozen = false;
38 |
39 | this.score = 0;
40 | this.golden = false;
41 | this.gameData = {
42 | name: "",
43 | color: Util.getRandomColor(),
44 | chatColor: Util.getRandomColor(),
45 | reservedChatNames: [],
46 | chatName: "",
47 | chkDeath: false,
48 | chatBan: false,
49 | reservedNamesMap: []
50 | }
51 |
52 | this.bulletsleft = 0
53 | this.killer = false;
54 |
55 |
56 | this.minions = new Map();
57 | this.cells = new Map();
58 |
59 |
60 | this.alive = Date.now()
61 |
62 | }
63 | msg() {
64 |
65 | }
66 | setOwn(node) {
67 | this.owning.set(node.id, node)
68 | }
69 | removeOwn(node) {
70 | this.owning.delete(node.id)
71 | }
72 | addMinion(minion) {
73 | this.minions.set(minion.id, minion)
74 |
75 | }
76 | addCell(cell) {
77 | this.cells.set(cell.id, cell)
78 | }
79 | setMass(m) {
80 | this.cells.forEach((cell) => {
81 | cell.updateMass(m)
82 | })
83 | }
84 | removeMinion(minion) {
85 | this.minions.delete(minion.id)
86 | }
87 | reset() {
88 | this.minions.clear();
89 | this.cells.clear();
90 | this.visible = [];
91 | this.gameData = {
92 | name: "",
93 | color: this.server.getRandomColor(),
94 | chatColor: this.server.getRandomColor(),
95 | reservedChatNames: [],
96 | chatName: "",
97 | chkDeath: false,
98 | chatBan: false,
99 | reservedNamesMap: []
100 | }
101 | this.owning.clear()
102 |
103 | this.sendData = false;
104 | }
105 |
106 | setColor(color) {
107 | this.gameData.color = color
108 | this.cells.forEach((cell) => {
109 | cell.color = color
110 | })
111 |
112 | }
113 | setName(name) {
114 | this.gameData.name = name
115 | this.cells.forEach((cell) => {
116 | cell.name = name
117 | cell.updCode()
118 | })
119 |
120 |
121 | }
122 | onDeath() {
123 | this.mass = 0;
124 | this.score = 0;
125 | this.alive = this.server.timer.time;
126 |
127 | this.spawn()
128 | }
129 | removeCell(cell) {
130 | this.cells.delete(cell.id)
131 |
132 | if (this.cells.size == 0) this.onDeath(cell.killer)
133 | }
134 |
135 |
136 | getBiggest() {
137 | var cell = false;
138 | this.cells.forEach((c) => {
139 | if (!cell || c.mass > cell.mass) cell = c
140 | })
141 | return cell;
142 | }
143 | getScore(re) {
144 |
145 | if (re) {
146 | var l = 0;
147 | this.cells.forEach((n) => {
148 | l += n.mass;
149 | })
150 | this.mass = l;
151 | this.score = Math.max(this.score, l)
152 | return l
153 | }
154 | this.score = Math.max(this.score, this.mass)
155 | return this.score
156 | }
157 | deleteNodes(main) {
158 |
159 | this.socket.sendDelete(main.deleteR)
160 | }
161 |
162 | }
--------------------------------------------------------------------------------
/source/core/childHolder.js:
--------------------------------------------------------------------------------
1 | "use strict"
2 | /*
3 | OpenAgar - Open source web game
4 | Copyright (C) 2016 Andrew S
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Affero General Public License as published
8 | by the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Affero General Public License for more details.
15 |
16 | You should have received a copy of the GNU Affero General Public License
17 | along with this program. If not, see .
18 | */
19 |
20 | module.exports = class ChildHolder {
21 | constructor(id, child) {
22 | this.id = id;
23 | this.child = child;
24 | this.listeners = [];
25 | this.assigned = 0;
26 | this.init()
27 | }
28 | _send(data) {
29 | this.child.send(data)
30 | }
31 | init() {
32 | this.child.on('message', function (msg) {
33 | if (this.listeners[msg.id]) this.listeners[msg.id](msg.data)
34 | }.bind(this))
35 | }
36 | send(id, data) {
37 | data.sid = id;
38 | try {
39 |
40 | this._send(data)
41 |
42 | } catch (e) {
43 |
44 | }
45 |
46 | }
47 | removeListener(id) {
48 | delete this.listeners[id]
49 | }
50 | assign(sid) {
51 |
52 | this.assigned++;
53 | this._send({
54 | type: 8,
55 | a: sid
56 | })
57 | }
58 | deAssign(sid) {
59 | this.assigned--;
60 | }
61 | stop() {
62 | this._send({
63 | type: 6
64 | })
65 | delete this.child
66 |
67 | }
68 | on(id, func) {
69 | this.listeners[id] = func
70 | }
71 | }
--------------------------------------------------------------------------------
/source/core/childManager.js:
--------------------------------------------------------------------------------
1 | "use strict"
2 | /*
3 | OpenAgar - Open source web game
4 | Copyright (C) 2016 Andrew S
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Affero General Public License as published
8 | by the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Affero General Public License for more details.
15 |
16 | You should have received a copy of the GNU Affero General Public License
17 | along with this program. If not, see .
18 | */
19 |
20 | var Child = require('child_process')
21 |
22 | var ChildHolder = require('./childHolder.js')
23 | module.exports = class childManager {
24 | constructor(ss) {
25 | this.ss = ss;
26 | this.cpus = require('os').cpus()
27 | this.childs = new Map();
28 | this.cid = 0
29 | this.init()
30 |
31 | }
32 | debug(a) {
33 | this.ss.controller.shellService.log(0, a)
34 | }
35 | init() {
36 | this.debug("gre{[Debug]} Number of computer cores detected: ".styleMe() + this.cpus.length)
37 | if (this.cpus.length <= 1) {
38 | console.log("red{[OpenAgar]} Your computer must have more than one core in order to run this program.".styleMe())
39 | exit(0)
40 | }
41 | process.on('exit', function () {
42 | var count = 0;
43 | this.childs.forEach((child) => {
44 | child.stop()
45 | count++;
46 | })
47 | Sounds.play('alert')
48 | this.debug("gre{[Debug]} Killed ".styleMe() + count + " processes")
49 | console.log("\ngre{[OpenAgar]} Killed all processes".styleMe())
50 | }.bind(this));
51 | }
52 |
53 | assignChild(sid) {
54 | if (this.childs.size < this.cpus.length - 1) {
55 | var child = this.createNewChild()
56 | child.assign(sid)
57 | this.debug("gre{[Debug]} Created new child (ID: ".styleMe() + child.id + ") and assigned server " + sid + " to it.")
58 | return child
59 | }
60 | var lowest = false;
61 | this.childs.forEach((child) => {
62 | if (!lowest || child.assigned < lowest.assigned) lowest = child
63 |
64 | })
65 | if (!lowest) throw "ERR: Child was not found"
66 |
67 | lowest.assign(sid)
68 | this.debug("gre{[Debug]} Assigned server ".styleMe() + sid + " to child (ID: " + lowest.id + " ASSIGNED: " + lowest.assigned + ")")
69 | return lowest
70 |
71 | }
72 | deAssignChild(id, sid) {
73 | var child = this.childs.get(id)
74 | if (!child) throw "ERR: Cannot deassign child that doesnt exsist!"
75 |
76 | child.deAssign(sid)
77 | this.debug("gre{[Debug]} Deassigned server ".styleMe() + sid + " to child (ID: " + child.id + " ASSIGNED: " + child.assigned + ")")
78 | if (child.assigned <= 0) {
79 | child.stop()
80 | this.childs.delete(id)
81 | this.debug("gre{[Debug]} Killed child (ID: ".styleMe() + id + ")")
82 | }
83 |
84 | }
85 |
86 | getNextCID() {
87 | return this.cid++;
88 | }
89 | createNewChild() {
90 | var child = Child.fork(__dirname + '/../child/index.js')
91 | var id = this.getNextCID()
92 | var data = new ChildHolder(id, child)
93 | this.childs.set(id, data)
94 | return data;
95 | }
96 |
97 | }
98 |
--------------------------------------------------------------------------------
/source/core/childService.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /*
3 | OpenAgar - Open source web game
4 | Copyright (C) 2016 Andrew S
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU Affero General Public License as published
7 | by the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 | This program is distributed in the hope that it will be useful,
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | GNU Affero General Public License for more details.
13 | You should have received a copy of the GNU Affero General Public License
14 | along with this program. If not, see .
15 | */
16 |
17 | module.exports = class childService {
18 | constructor(main, child) {
19 |
20 |
21 | this.child = child
22 |
23 | this.main = main;
24 | this.totalMass = 0;
25 | this.toSend = [];
26 | this.buf = 0;
27 | this.updHash = {};
28 | this.movHash = {};
29 | this.movCode = [];
30 | this.hash = [];
31 | this.events = {}
32 | this.lb = [];
33 |
34 |
35 | }
36 |
37 | init() {
38 | this.child.on(this.main.id, function (data) {
39 |
40 | this.onData(data)
41 | }.bind(this))
42 | this.send(0, {
43 | hello: "hello",
44 | config: this.main.getConfig(),
45 | teams: this.main.haveTeams,
46 | bounds: this.main.bounds
47 | })
48 | this.on('lb', function (lb) {
49 | this.lb = lb
50 | }.bind(this))
51 | this.on('mass', function (m) {
52 | var nodes = this.main.getWorld().getNodes('player'),
53 | max = this.main.getConfig().playerMaxMass,
54 | maxCells = this.main.getConfig().playerMaxCells,
55 | splitSpeed = this.main.getConfig().splitSpeed,
56 | splitDecay = this.main.getConfig().splitDecay;
57 | m.forEach((k) => {
58 | var node = nodes.get(k)
59 |
60 | if (node) {
61 | if (node.owner.cells.size >= maxCells) node.mass = Math.min(node.mass, max);
62 | else this.main.splitPlayerCell(node, Math.random() * 6.28, splitSpeed, splitDecay)
63 | node.updCode()
64 | }
65 | })
66 | }.bind(this))
67 | this.on('totmass', function (m) {
68 | this.totalMass = m;
69 | }.bind(this))
70 | this.on('lag', function (lag) {
71 | this.main.debug("yel{[Debug]} Lag detected for child ".styleMe() + this.child.id + " Latency: " + lag)
72 | }.bind(this))
73 | }
74 | pause(state) {
75 | this.send(9, {
76 | p: state
77 | })
78 |
79 | }
80 | on(e, f) {
81 | this.events[e] = f
82 | }
83 | emit(e, d) {
84 | this.send(7, {
85 | e: e,
86 | d: d
87 | })
88 | }
89 | clearEvents() {
90 | this.events = {}
91 | }
92 | action(bot, action, data) {
93 | switch (action) {
94 | case 1: // spawn
95 | bot.onSpawn()
96 | this.main.spawn(bot)
97 |
98 | break;
99 | case 2: // eject
100 | this.main.ejectMass(bot)
101 | break;
102 | case 3: // split
103 | this.main.splitPlayer(bot)
104 | break;
105 | }
106 | }
107 | event(event, data) {
108 | if (this.events[event]) this.events[event](data)
109 | }
110 |
111 | onData(data) {
112 | if (this.main.destroyed) return
113 | if (data.p) {
114 |
115 | var world = this.main.getWorld().getNodes('map')
116 | data.d.forEach((c) => {
117 | var cell = world.get(c.i)
118 | if (!cell) return;
119 | cell.nearby = []
120 | c.l.forEach((n) => {
121 |
122 | var node = world.get(n)
123 |
124 | if (node) cell.nearby.push(node)
125 | })
126 | })
127 | return;
128 | }
129 |
130 |
131 | // console.log(data)
132 | data.forEach((bot) => {
133 | if (bot.e) {
134 | this.event(bot.e, bot.d)
135 | } else
136 | if (bot.action) {
137 | var b = this.main.bots.get(bot.id)
138 | if (!b) return
139 | this.action(b, bot.action, bot)
140 | } else {
141 | var b = this.main.bots.get(bot.i)
142 | if (!b) return
143 | b.mouse.x = bot.m.x
144 | b.mouse.y = bot.m.y
145 | }
146 | })
147 | }
148 | stop() {
149 | this.child.removeListener(this.main.id)
150 | delete this.child
151 |
152 | }
153 | send(type, data) {
154 | data.type = type;
155 | try {
156 | this.child.send(this.main.id, data)
157 | } catch (e) {
158 |
159 | }
160 | }
161 | addBot(bot) {
162 |
163 | this.send(5, {
164 | id: bot.id,
165 | bot: bot.botid
166 | })
167 | }
168 | removeClient(client) {
169 | this.emit('delPlayer', client.id)
170 | }
171 | addNode(node) {
172 |
173 | if (this.hash[node.id]) return;
174 | this.toSend.push({
175 | id: node.id,
176 | size: node.size,
177 | type: node.type,
178 | position: node.position,
179 | owner: (node.owner) ? node.owner.id : false,
180 | mass: node.mass,
181 | speed: node.speed
182 |
183 |
184 | })
185 | this.hash[node.id] = true;
186 |
187 | }
188 | deleteNodes(nodes) {
189 | if (nodes[0])
190 | this.send(2, {
191 | nodes: nodes
192 | })
193 |
194 | }
195 | sendMove(node) {
196 | this.movCode.push({
197 | id: node.id,
198 | x: node.position.x,
199 | y: node.position.y
200 | })
201 |
202 | }
203 | update() {
204 | if (this.main.lag > 0) {
205 | if (this.buf > 5) {
206 | this.buf = 0
207 |
208 | } else {
209 | this.buf++;
210 | }
211 | }
212 |
213 | var nodes = this.main.getWorld().getNodes('player')
214 |
215 | nodes.forEach((node) => {
216 |
217 | if (node.updateCode != this.updHash[node.id]) {
218 | this.hash[node.id] = false;
219 | this.updHash[node.id] = node.updateCode
220 | this.addNode(node)
221 | } else if (node.moveCode != this.movHash[node.id]) {
222 |
223 | this.movHash[node.id] = node.moveCode
224 | this.movCode.push({
225 | id: node.id,
226 | x: node.position.x,
227 | y: node.position.y
228 | })
229 | }
230 |
231 | })
232 | if (this.movCode[0]) this.send(3, {
233 | nodes: this.movCode
234 | })
235 | this.movCode = [];
236 |
237 | }
238 |
239 | sendNodes() {
240 | if (this.toSend.length == 0) return
241 | this.send(1, {
242 | nodes: this.toSend
243 | })
244 |
245 | this.toSend = [];
246 | }
247 |
248 | }
--------------------------------------------------------------------------------
/source/core/collisionHandler.js:
--------------------------------------------------------------------------------
1 | "use strict"
2 | /*
3 | OpenAgar - Open source web game
4 | Copyright (C) 2016 Andrew S
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Affero General Public License as published
8 | by the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Affero General Public License for more details.
15 |
16 | You should have received a copy of the GNU Affero General Public License
17 | along with this program. If not, see .
18 | */
19 | module.exports = class CollisionHandler {
20 | constructor(main) {
21 | this.main = main;
22 | this.timer = 0;
23 | }
24 | collidePlayer(cell) {
25 |
26 | cell.nearby.forEach((node) => {
27 |
28 | if (!node || node.dead) return;
29 |
30 | // relative collision
31 | if (node.type == 0 && node.owner == cell.owner) {
32 | if (node.canMerge && cell.canMerge || node.getAge(this.main) < 500) return;
33 | this.relativeCollision2(cell, node);
34 | //this.relativeCollision2(cell,node);
35 |
36 |
37 | } else if (node.type == 5 && node.owner == cell.owner && node.getAge(this.main) < 500) {
38 | this.relativeCollision2(cell, node);
39 | } else if (cell.doesCollide(node, this.main)) {
40 | this.relativeCollision2(cell, node);
41 | }
42 | });
43 | }
44 | rigidCollision(cell, node) { // where one is stationary
45 | var dist = cell.getDistance(node.position.x, node.position.y)
46 | if (dist <= 1) return;
47 |
48 | var midpointx = (cell.position.x + node.position.x) / 2,
49 | midpointy = (cell.position.y + node.position.y) / 2,
50 | x1 = midpointx + cell.size * (cell.position.x - node.position.x) / dist,
51 | y1 = midpointy + cell.size * (cell.position.y - node.position.y) / dist,
52 | x2 = midpointx + node.size * (node.position.x - cell.position.x) / dist,
53 | y2 = midpointy + node.size * (node.position.y - cell.position.y) / dist;
54 |
55 | cell.setPos(x1, y1)
56 | node.setPos(x2, y2)
57 | }
58 | relativeCollision2(cell, node) { // From multiogar SRC: https://github.com/Barbosik/MultiOgar/blob/master/src/GameServer.js
59 |
60 | // distance from cell1 to cell2
61 | var d = cell.getDistance(node.position.x, node.position.y)
62 | if (d <= 0) return;
63 | var invd = 1 / d;
64 | var dx = node.position.x - cell.position.x
65 | var dy = node.position.y - cell.position.y
66 | // normal
67 | var nx = dx * invd;
68 | var ny = dy * invd;
69 | var r = node.size + cell.size
70 | // body penetration distance
71 | var penetration = r - d;
72 | if (penetration <= 0) return;
73 |
74 | // penetration vector = penetration * normal
75 | var px = penetration * nx;
76 | var py = penetration * ny;
77 |
78 | // body impulse
79 |
80 |
81 | // cell1 = this
82 | // cell2 = node
83 | var cs1 = cell.size * cell.size
84 | var cs2 = node.size * node.size
85 | var totalMass = cs1 + cs2;
86 | if (totalMass <= 0) return;
87 | var invTotalMass = 1 / totalMass;
88 | var impulse1 = cs2 * invTotalMass;
89 | var impulse2 = cs1 * invTotalMass;
90 |
91 | // apply extrusion force
92 |
93 |
94 |
95 | cell.addPos(-px * impulse1, -py * impulse1)
96 |
97 | node.addPos(px * impulse2, py * impulse2)
98 |
99 | if (!node.moving) {
100 | node.checkGameBorders(this.main)
101 | node.movCode()
102 |
103 | }
104 | }
105 | relativeCollision(cell, node) { // considering mass
106 | var coll = cell.size + node.size;
107 | var dist = cell.getDistance(node.position.x, node.position.y)
108 | var angle = Math.atan(cell.getSlope(node.position.x, node.position.y))
109 | if (dist - coll > 0 || node == cell) return;
110 | var frac = node.mass / cell.mass
111 | var a = Math.sqrt(frac) / 2;
112 | var push = a * (coll - dist);
113 | push = Math.min(push, coll - dist);
114 |
115 | cell.addPos(Math.sin(angle) * push, Math.cos(angle) * push)
116 | }
117 |
118 | }
--------------------------------------------------------------------------------
/source/core/configService.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*
3 | OpenAgar - Open source web game
4 | Copyright (C) 2016 Andrew S
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU Affero General Public License as published
7 | by the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 | This program is distributed in the hope that it will be useful,
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | GNU Affero General Public License for more details.
13 | You should have received a copy of the GNU Affero General Public License
14 | along with this program. If not, see .
15 | */
16 | const fs = require("fs");
17 | const ini = require('../modules/ini.js');
18 |
19 |
20 | module.exports = {
21 |
22 | loadSConfig: function (d) {
23 | try {
24 | var config = ini.parse(fs.readFileSync(__dirname + '/../settings/serverConfig.ini', "utf8"))
25 | console.log("gre{[OpenAgar]} Loaded server configs".styleMe())
26 | return config;
27 |
28 | } catch (e) {
29 | if (d) {
30 | console.log("red{[OpenAgar]} Error with getting config:".styleMe())
31 | throw e
32 | }
33 | return false
34 | }
35 | },
36 | loadSkins: function (d) {
37 | try {
38 | var skins = ini.parse(fs.readFileSync(__dirname + '/../settings/customSkins.ini', "utf8"))
39 | console.log("gre{[OpenAgar]} Loaded custom skins".styleMe())
40 | return skins;
41 |
42 | } catch (e) {
43 | if (d) {
44 | console.log("red{[OpenAgar]} Error with getting custom skins:".styleMe())
45 | throw e
46 | }
47 | return false
48 | }
49 | },
50 | loadBan: function () {
51 | var ban = [];
52 | try {
53 | var file = fs.readFileSync(__dirname + '/../../ban.txt', "utf8")
54 | console.log("gre{[OpenAgar]} Loaded ban file and cleaned it".styleMe())
55 | if (!file) return ban
56 | file = file.split("\n")
57 |
58 | file.forEach((b) => {
59 | if (b) {
60 | b = b.replace(/\s/g, "")
61 |
62 | ban.push(b)
63 | }
64 | })
65 |
66 | fs.writeFileSync(__dirname + '/../../ban.txt', ban.join("\n"))
67 | } catch (e) {
68 |
69 | console.log("yel{[OpenAgar]} Ban file not found. Generating...".styleMe())
70 | fs.writeFileSync(__dirname + '/../../ban.txt', "")
71 | }
72 | return ban
73 | },
74 | loadConfig: function (dir, d) {
75 | try {
76 | var physics = ini.parse(fs.readFileSync(dir + '/physicsConfig.ini', "utf8"))
77 | var config = ini.parse(fs.readFileSync(dir + '/config.ini', "utf8"))
78 | var client = ini.parse(fs.readFileSync(dir + '/clientConfig.ini', "utf8"))
79 | for (var i in physics) {
80 | if (!config[i]) config[i] = physics[i]
81 | }
82 | for (var i in client) {
83 | if (!config[i]) config[i] = client[i]
84 | }
85 | console.log("gre{[OpenAgar]} Loaded game server configs".styleMe())
86 | return config;
87 |
88 | } catch (e) {
89 | if (d) {
90 | console.log("red{[OpenAgar]} Error with getting config:".styleMe())
91 | throw e
92 | }
93 | return false
94 | }
95 |
96 |
97 | },
98 | loadServers: function (defaultconf) {
99 | var servers = {};
100 | var files = fs.readdirSync(__dirname + '/../settings/servers/');
101 | files.forEach((file) => {
102 | var split = file.split(".");
103 | if (split[1] != "ini") return;
104 |
105 | var f = __dirname + '/../settings/servers/' + file;
106 | var configs = ini.parse(fs.readFileSync(f, "utf8"));
107 | for (var i in defaultconf) {
108 | if (configs[i] === undefined) configs[i] = defaultconf[i];
109 | }
110 | servers[split[0]] = configs;
111 |
112 | })
113 | return servers;
114 | },
115 | loadBotNames: function () {
116 | try {
117 | var file = fs.readFileSync(__dirname + "/../settings/botnames.txt", "utf8");
118 |
119 | file = file.split("\n");
120 |
121 |
122 | var out = [];
123 | for (var i = 0; i < file.length; i++) {
124 | var b = file[i].trim();
125 | if (b && b.length > 0) out.push(b)
126 | }
127 |
128 | fs.writeFileSync(__dirname + "/../settings/botnames.txt", out.join("\n"));
129 |
130 | console.log("gre{[OpenAgar]} Retrieved ".styleMe() + out.length + " botnames");
131 | return out;
132 |
133 | } catch (e) {
134 |
135 | fs.writeFileSync(__dirname + "/../settings/botnames.txt", "")
136 | console.log("yel{[OpenAgar]} Created botnames.txt".styleMe())
137 | return [];
138 | }
139 | }
140 |
141 |
142 |
143 | };
144 |
--------------------------------------------------------------------------------
/source/core/controller.js:
--------------------------------------------------------------------------------
1 | // DO NOT USE STRICT AS IT WONT ALLOW GLOBAL VARS
2 | /*
3 | OpenAgar - Open source web game
4 | Copyright (C) 2016 Andrew S
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Affero General Public License as published
8 | by the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Affero General Public License for more details.
15 |
16 | You should have received a copy of the GNU Affero General Public License
17 | along with this program. If not, see .
18 | */
19 | var ServerService = require('./serverService.js');
20 | var GlobalData = require('./globalData.js');
21 | var request = require('minirequest')
22 | var ShellService = require('./shellService.js')
23 | var Config = require('./configService.js')
24 |
25 | Util = require('./utilities.js')
26 | Style = require('styleme')
27 | Style.extend()
28 | var a = require('../modules/fastSquares.js')
29 | Sqrt = new a()
30 |
31 | var a = require('nodesounds')
32 | Sounds = new a(__dirname + '/../sounds')
33 | Sounds.add('start', 'start.mp3')
34 | Sounds.add('alert', 'alert.mp3')
35 | Sounds.add('tone', 'tone.mp3')
36 |
37 | _version = "5.0.5"
38 | _key = ""
39 | exit = function (a) {
40 | process.exit(a)
41 | }
42 |
43 | var UID = require('./uid.js');
44 |
45 | module.exports = function () {
46 | _getUID(function (code) {
47 |
48 | if (!code) {
49 | setTimeout(function () {
50 | console.log("yel{[OpenAgar]} This is an unregistered copy. Please register at login.opnagar.us. Your id is ".styleMe() + _uid());
51 | }, 1000);
52 |
53 | }
54 |
55 | if (_lvl() == 1) {
56 | setTimeout(function () {
57 | console.log("gre{[OpenAgar]} rai{Welcome} back, system moderator.".styleMe());
58 | }, 1000);
59 |
60 | } else if (_lvl() == 2) {
61 | setTimeout(function () {
62 | console.log("gre{[OpenAgar]} rai{Welcome} back, system administrator.".styleMe());
63 | }, 1000);
64 | }
65 |
66 | require("./errorManager.js");
67 |
68 | var main = new Controller();
69 | main.start();
70 | });
71 |
72 |
73 |
74 | function Controller() {
75 |
76 | console.log("gre{[OpenAgar]} Starting OpenAgar V".styleMe() + _version)
77 | this.config = Config.loadSConfig(true)
78 | var ban = Config.loadBan()
79 | var skins = Config.loadSkins(true)
80 | var botnames = Config.loadBotNames();
81 |
82 | this.globalData = new GlobalData(this.config, ban, skins, botnames);
83 | this.shellService = new ShellService(this)
84 | this.serverService = new ServerService(this, this.globalData);
85 |
86 | }
87 |
88 | Controller.prototype.start = function () {
89 |
90 |
91 |
92 | this.shellService.init()
93 | this.serverService.start();
94 |
95 | }
96 | Controller.prototype.execCommand = function (str) {
97 | this.serverService.execCommand(str)
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/source/core/dataService.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /*
3 | OpenAgar - Open source web game
4 | Copyright (C) 2016 Andrew S
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Affero General Public License as published
8 | by the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Affero General Public License for more details.
15 |
16 | You should have received a copy of the GNU Affero General Public License
17 | along with this program. If not, see .
18 | */
19 | const WorldModel = require('./worldModel.js');
20 | const GameData = require('./gameData.js');
21 | module.exports = class DataService {
22 | constructor(main,globalData,config) {
23 | this.globalData = globalData;
24 | this.config = config;
25 |
26 | this.world = new WorldModel(main);
27 | }
28 | };
29 |
--------------------------------------------------------------------------------
/source/core/foodService.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /*
3 | OpenAgar - Open source web game
4 | Copyright (C) 2016 Andrew S
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Affero General Public License as published
8 | by the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Affero General Public License for more details.
15 |
16 | You should have received a copy of the GNU Affero General Public License
17 | along with this program. If not, see .
18 | */
19 | module.exports = class FoodService {
20 | constructor(main) {
21 | this.main = main;
22 | this.loops = [];
23 | }
24 | checkFood() {
25 | // console.log(this.main.dataService.world.nodes.getWithMerged(this.main.bounds).length)
26 | if (this.main.food < this.main.getConfig().minFood) {
27 | this.addFood(this.main.getConfig().minFood - this.main.food);
28 | } else {
29 | // console.log(this.main.dataService.world.getNodes())
30 | }
31 |
32 | }
33 | getRandomPos() {
34 | var x = Math.floor(this.main.bounds.width * Math.random());
35 | var y = Math.floor(Math.random() * this.main.bounds.height);
36 | return {
37 | x: x,
38 | y: y
39 | };
40 | }
41 | addFood(m) {
42 | for (var i = 0; i < m; i++) {
43 | var pos = this.getRandomPos();
44 | // console.log(pos)
45 | this.main.addNode(pos, 2, 4);
46 | }
47 | }
48 | checkVirus() {
49 | if (this.main.viruses < this.main.getConfig().minVirus) {
50 | this.addVirus(this.main.getConfig().minVirus - this.main.viruses);
51 | } else {
52 | // console.log(this.main.dataService.world.getNodes())
53 | }
54 | }
55 | addWormHole(m) {
56 | for (var i = 0; i < m; i++) {
57 | var pos = this.getRandomPos();
58 | // console.log(pos)
59 | var mass = Math.floor(Math.random() * 500) + 100
60 | if (this.main.checkCollide(pos, Math.ceil(Math.sqrt(this.mass) * 10) + 5)) {
61 | --i;
62 | continue;
63 | };
64 | this.main.addNode(pos, mass, 6);
65 | }
66 | }
67 | checkWormHole() {
68 | if (this.main.wormHoles < this.main.getConfig().minWormHole) {
69 | this.addWormHole(this.main.getConfig().minWormHole - this.main.wormHoles);
70 | } else {
71 | // console.log(this.main.dataService.world.getNodes())
72 | }
73 | }
74 | addVirus(m) {
75 |
76 | for (var i = 0; i < m; i++) {
77 | var pos = this.getRandomPos();
78 | if (this.main.checkCollide(pos, 120)) {
79 | --i;
80 | continue;
81 | };
82 | // console.log(pos)
83 | this.main.addNode(pos, this.main.getConfig().virusMass, 2);
84 | }
85 | }
86 | loop() {
87 | this.loops.forEach((l) => {
88 | this.checkNode(l.min, l.id, l.name, l.start)
89 | });
90 | }
91 | addLoop(min, id, name, start) {
92 | this.loops.push({
93 | min: min,
94 | id: id,
95 | name: name,
96 | start: start
97 | })
98 | }
99 |
100 | checkNode(min, id, name, start) {
101 | var amount = this.main.getWorld().getNodes(name).size
102 | if (amount < min) {
103 | this.addNode(min - amount, id, start)
104 | }
105 | }
106 | addNode(m, id, start) {
107 | for (var i = 0; i < m; i++) {
108 | var pos = this.getRandomPos();
109 | // console.log(pos)
110 | this.main.addNode(pos, start, id);
111 | }
112 | }
113 | };
--------------------------------------------------------------------------------
/source/core/gameData.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /*
3 | OpenAgar - Open source web game
4 | Copyright (C) 2016 Andrew S
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Affero General Public License as published
8 | by the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Affero General Public License for more details.
15 |
16 | You should have received a copy of the GNU Affero General Public License
17 | along with this program. If not, see .
18 | */
19 | module.exports = class gameData {
20 | constructor() {
21 | this.data = {};
22 | }
23 | getData() {
24 | return this.data;
25 | }
26 | addData(name,value) {
27 | this.data[name] = value;
28 | }
29 | removeData(name) {
30 | this.data[name] = null;
31 | }
32 | };
33 |
--------------------------------------------------------------------------------
/source/core/gameMode.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /*
3 | OpenAgar - Open source web game
4 | Copyright (C) 2016 Andrew S
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU Affero General Public License as published
7 | by the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 | This program is distributed in the hope that it will be useful,
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | GNU Affero General Public License for more details.
13 | You should have received a copy of the GNU Affero General Public License
14 | along with this program. If not, see .
15 | */
16 | var ingame = require('../modes/index.js')
17 | module.exports = class gameModeHandler {
18 | constructor(main) {
19 | this.main = main;
20 | this.mode = false;
21 | this.init()
22 | }
23 | init() {
24 | this.setMode(this.main.getConfig().gameMode)
25 |
26 |
27 | this.event('onServerInit')
28 | this.main.log("gre{[OpenAgar]} Current gamemode is ".styleMe() + this.main.getConfig().gameMode + " (" + this.mode.name + ")")
29 | }
30 | setMode(mode) {
31 | this.mode = ingame.get(mode)
32 | if (!this.mode) this.mode = this.main.pluginService.gamemodes[mode]
33 | if (!this.mode) throw "ERROR: Invalid gamemode! Gamemode doesnt exsist"
34 | }
35 | event(event, data) {
36 | if (!data) data = {}
37 | if (!this.mode) return true;
38 | if (!this.mode[event]) return true;
39 | data.main = this.main;
40 | data.log = this.main.log
41 | if (this.mode[event](data) === false) return false
42 | return true;
43 | }
44 |
45 | }
--------------------------------------------------------------------------------
/source/core/globalData.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /*
3 | OpenAgar - Open source web game
4 | Copyright (C) 2016 Andrew S
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Affero General Public License as published
8 | by the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Affero General Public License for more details.
15 |
16 | You should have received a copy of the GNU Affero General Public License
17 | along with this program. If not, see .
18 | */
19 | module.exports = class GlobalData {
20 | constructor(config, ban, skins, botnames) {
21 | this.data = {};
22 | var fin = {};
23 | var id = -1
24 | var f = [];
25 | for (var i in skins) {
26 | fin[i] = {
27 | skin: skins[i],
28 | id: id
29 | }
30 | f[id--] = skins[i]
31 | }
32 |
33 | this.skins = fin;
34 | this.skins2 = f
35 | this.config = config;
36 | this.id = 1;
37 | this.ban = ban
38 | this.botnames = botnames;
39 | this.nameList = botnames.slice(0)
40 | this.globalBan = {};
41 | }
42 | getNextId() {
43 |
44 | if (this.id >= 4294967295) this.id = 0;
45 |
46 | return this.id++;
47 | }
48 | getRandomName() {
49 |
50 | if (this.nameList.length === 0) this.nameList = this.botnames.slice(0)
51 | var index = Math.floor(Math.random() * this.nameList.length);
52 |
53 | var name = this.nameList[index];
54 |
55 | this.nameList.splice(index, 1);
56 |
57 | return name;
58 | }
59 |
60 | getData() {
61 | return this.data;
62 | }
63 | addData(name, value) {
64 | this.data[name] = value;
65 | }
66 | removeData(name) {
67 | this.data[name] = null;
68 | }
69 | updateGlobalBan(data) {
70 | this.globalBan = {};
71 | for (var i = 0; i < data.length; i++) {
72 | this.globalBan[data[i].ip] = data[i];
73 | }
74 |
75 | }
76 | };
77 |
--------------------------------------------------------------------------------
/source/core/pluginService.js:
--------------------------------------------------------------------------------
1 | "use strict"
2 | /*
3 | OpenAgar - Open source web game
4 | Copyright (C) 2016 Andrew S
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU Affero General Public License as published
7 | by the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 | This program is distributed in the hope that it will be useful,
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | GNU Affero General Public License for more details.
13 | You should have received a copy of the GNU Affero General Public License
14 | along with this program. If not, see .
15 | */
16 | var pluginParser = require('./pluginParser.js')
17 | var fs = require('fs')
18 | var ini = require('../modules/ini.js')
19 | module.exports = class PluginService {
20 | constructor(main) {
21 | this.vars = ["configs","commands","addToHelp","gamemodes","chatCommands","chatHelp"]
22 | this.main = main
23 | this.plugins = {};
24 | this.pdata = {}
25 | this.pluginNames = [];
26 | this.commands = {};
27 | this.addToHelp = [];
28 | this.data = {
29 | main: main,
30 | log: main.log
31 |
32 | }
33 | this.chatC = {};
34 | this.chatA = [];
35 | this.gamemodes = []
36 | this.configs = ini.parse(fs.readFileSync(__dirname + '/../settings/pluginConfig.ini',"utf8"))
37 | if (this.configs.allowed) this.configs.allowed = this.configs.allowed.split(",")
38 | this.parser = new pluginParser(function(a) {main.log("gre{[PluginService]} ".styleMe() + a)}.bind(this),__dirname + "/../plugins",this.vars,this.data,_version,this.configs.allowed,this.configs.dev == 1)
39 |
40 |
41 | }
42 | stop() {
43 | for (var i in this.plugins) {
44 | var plugin = this.plugins[i]
45 | if (plugin.stop) plugin.stop()
46 | }
47 | this.plugins = {};
48 | this.pdata = {};
49 | }
50 | init() {
51 | this.parser.init()
52 | this.plugins = this.parser.getPlugins()
53 | this.pdata = this.parser.getData()
54 | var command = this.getData('chatCommands')
55 | var help = this.getData('chatHelp')
56 | this.chatC = {}
57 | this.chatA = []
58 | command.forEach((comm)=>{
59 | if (!comm) return;
60 | for (var i in comm) {
61 | this.chatC[i] = comm[i]
62 |
63 | }
64 | })
65 | help.forEach((help)=>{
66 | this.chatA = this.chatA.concat(help)
67 | })
68 | var command = this.getData('commands')
69 | var help = this.getData('addToHelp')
70 | var gamemodes = this.getData('gamemodes')
71 | this.commands = {};
72 |
73 | this.addToHelp = [];
74 | help.forEach((help)=>{
75 | this.addToHelp = this.addToHelp.concat(help)
76 | })
77 | command.forEach((comm)=>{
78 | if (!comm) return;
79 | for (var i in comm) {
80 | this.commands[i] = comm[i]
81 |
82 | }
83 | })
84 | gamemodes.forEach((gamemode)=>{
85 | if (!gamemode) return;
86 | gamemode.forEach((g,i)=>{
87 | if (!g || !g.id || !g.name) return;
88 | this.gamemodes[parseInt(g.id)] = g
89 | })
90 | })
91 | for (var i in this.plugins) {
92 | var plugin = this.plugins[i];
93 | this.pluginNames.push(plugin.name);
94 | }
95 |
96 | }
97 | reload() {
98 | this.init()
99 | }
100 | getData(data) {
101 | if (data) {
102 | return this.pdata[data]
103 | } else {
104 | return this.pdata
105 | }
106 | }
107 | send(event,data) {
108 | if (!data.log) data.log = this.main.log;
109 | if (!data.main) data.main = this.main;
110 | if (!data.pluginService) data.pluginService = this;
111 | for (var i in this.plugins) {
112 | var plugin = this.plugins[i]
113 | if (plugin && plugin[event]) {
114 | if (plugin[event](data) === false) return false;
115 | }
116 | continue;
117 | }
118 | return true;
119 | }
120 | getPlugins() {
121 | return this.plugins
122 | }
123 |
124 |
125 |
126 |
127 | }
128 |
--------------------------------------------------------------------------------
/source/core/shellService.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /*
3 | OpenAgar - Open source web game
4 | Copyright (C) 2016 Andrew S
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Affero General Public License as published
8 | by the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Affero General Public License for more details.
15 |
16 | You should have received a copy of the GNU Affero General Public License
17 | along with this program. If not, see .
18 | */
19 |
20 | const AsyncConsole = require('asyncconsole')
21 | const EOL = require('os').EOL
22 | module.exports = class ShellService {
23 | constructor(controlservice) {
24 | this.controller = controlservice;
25 | this.text = ""
26 | this.commands = [];
27 | this.redrawing = false
28 |
29 | this.input = new AsyncConsole(">", function (command) {
30 | this.parseCommands(command)
31 | }.bind(this), function (key) {
32 | if (this.redrawing || !this.controller.serverService.selected.interface) return false;
33 | return true;
34 |
35 | }.bind(this),function() {
36 | exit();
37 | })
38 | this.ind = 0;
39 | this.console = []
40 |
41 | this.selected = 1;
42 |
43 |
44 | }
45 | select(id, c) {
46 | if (this.selected == id) return;
47 | this.selected = id
48 | this.writeLog(c)
49 | }
50 | removeServ(id) {
51 | delete this.console[id]
52 | }
53 | clearAnim(height, width, callback) {
54 | process.stdout.write(" ")
55 | var a = false
56 | var text = ""
57 | for (var i = 0; i < width; i++) {
58 | text += " "
59 | }
60 | var interval = setInterval(function () {
61 | if (a) process.stdout.write(EOL)
62 | a = true;
63 |
64 | process.stdout.write(text)
65 | height--;
66 | if (height <= 0) {
67 | clearInterval(interval)
68 | callback()
69 | }
70 | }.bind(this), 30)
71 | }
72 | interval(num, func, call, time) {
73 | var int = setInterval(function () {
74 | func()
75 | num--;
76 | if (num <= 1) {
77 | clearInterval(int)
78 | call()
79 | }
80 | }.bind(this), time)
81 | }
82 | writeLog(cbk) { // CALLBACK HELL! (Yet too cool)
83 | var eol = require('os').EOL;
84 |
85 | var logs = this.console[this.selected]
86 | if (!logs) return
87 | var height = process.stdout.rows
88 | var width = process.stdout.columns
89 |
90 | process.stdout.write('\u001B[H\u001B[2r')
91 | this.redrawing = true;
92 |
93 | this.clearAnim(height, width - 1, function () {
94 | process.stdout.write("\x1b[K")
95 |
96 | this.interval(height, function () {
97 | process.stdout.write("\x1b[1A")
98 | }, function () {
99 | this.interval(width, function () {
100 | process.stdout.write("\x1b[1D")
101 | }, function () {
102 | process.stdout.write('\u001B[0r')
103 | var sel = Math.max(logs.length - height, 0);
104 | var self = this;
105 |
106 | function set() {
107 | var ind = 0;
108 | var int = setInterval(function () {
109 | if (logs[sel]) {
110 | var d = logs[sel].charAt(ind)
111 | if (!d) {
112 | process.stdout.write(eol)
113 |
114 | sel++;
115 | clearInterval(int)
116 | set()
117 | }
118 | process.stdout.write(d)
119 | ind++;
120 | } else {
121 | clearInterval(int)
122 | if (cbk) cbk()
123 | self.redrawing = false
124 | }
125 | }, 3)
126 | }
127 |
128 | set()
129 | }.bind(this), 6)
130 | }.bind(this), 15)
131 |
132 |
133 |
134 |
135 |
136 | /*
137 |
138 | for (var i = 0; i < logs.length; i ++) {
139 | process.stdout.write(logs[i] +"\n")
140 | }
141 | */
142 |
143 | }.bind(this))
144 |
145 | }
146 | log(id, a, log) {
147 | if (id == this.selected && !log && !this.redrawing) console.log(a)
148 | if (!this.console[id]) this.console[id] = [];
149 | this.console[id].push(a.toString())
150 | }
151 | drawSplash() {
152 | Sounds.play('start')
153 | this.log(1, "\u001b[2J\u001b[0;0H");
154 | this.log(1, "cya{ ___ }yel{ _ }".styleMe())
155 | this.log(1, "cya{ / _ \\ _ __ ___ _ __ }yel{ / \\ __ _ __ _ _ __ }".styleMe())
156 | this.log(1, "cya{ | | | | '_ \\ / _ \\ '_ \\}yel{ / _ \\ / _` |/ _` | '__|}".styleMe())
157 | this.log(1, "cya{ | |_| | |_) | __/ | | |}yel{/ ___ \\ (_| | (_| | | }".styleMe())
158 | this.log(1, "cya{ \\___/| .__/ \\___|_| |_}yel{/_/ \\_\\__, |\\__,_|_| }".styleMe())
159 | this.log(1, "cya{ |_| }yel{ |___/ }".styleMe())
160 | this.log(1, " gre{OpenAgar} - cya{An open source web game}".styleMe())
161 | this.log(1, " yel{Also by the cya{AJS} Development team}".styleMe())
162 |
163 | }
164 | init() {
165 | this.drawSplash()
166 |
167 | }
168 |
169 |
170 | parseCommands(str) {
171 |
172 | // this.controller.logger.onCommand(str);
173 | if (str === '') return;
174 |
175 | this.controller.execCommand(str)
176 | }
177 | };
--------------------------------------------------------------------------------
/source/core/skinHandler.js:
--------------------------------------------------------------------------------
1 | "use strict"
2 | /*
3 | OpenAgar - Open source web game
4 | Copyright (C) 2016 Andrew S
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Affero General Public License as published
8 | by the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Affero General Public License for more details.
15 |
16 | You should have received a copy of the GNU Affero General Public License
17 | along with this program. If not, see .
18 | */
19 | module.exports = class SkinHandler {
20 | constructor(player) {
21 | this.player = player
22 | this.skin = 0;
23 | this.sentHash = {};
24 |
25 | }
26 |
27 | setSkin(name) {
28 |
29 | if (name.charAt(0) == "<") {
30 | var a = name.indexOf(">")
31 | if (a == -1) return name;
32 | var skin = name.substring(1, a)
33 | if (!skin) return name.substr(a + 1);
34 |
35 | var b = this.player.globalData.skins[skin.toLowerCase()];
36 | if (!b) return name.substr(a + 1);
37 | this.skin = b.id;
38 | return name.substr(a + 1)
39 | }
40 | return name;
41 | }
42 | getSend(skin) {
43 |
44 | if (skin > 0 || this.sentHash[skin]) {
45 | return skin.toString();
46 | } else {
47 | if (this.player.globalData.skins2[skin]) {
48 | this.sentHash[skin] = true;
49 |
50 | return skin + "|" + this.player.globalData.skins2[skin];
51 |
52 | } else {
53 | return "";
54 | }
55 | }
56 | }
57 |
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/source/core/socket.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /*
3 | OpenAgar - Open source web game
4 | Copyright (C) 2016 Andrew S
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Affero General Public License as published
8 | by the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Affero General Public License for more details.
15 |
16 | You should have received a copy of the GNU Affero General Public License
17 | along with this program. If not, see .
18 | */
19 | const RSON = require('rson')
20 | const LZString = require('../modules/LZString.js')
21 | module.exports = class Socket {
22 | constructor(socket, player) {
23 | this.player = player;
24 | this.socket = socket
25 |
26 |
27 | this.remoteAddress = socket.IP;
28 | this.IPv6 = socket.IPv6;
29 | }
30 | sendNodes(dt) {
31 |
32 | this.socket.socket.send(dt, {
33 | binary: true
34 | });
35 |
36 | }
37 | sendDelete(tex) {
38 |
39 | this.socket.hasBinary(false).emit('delnodes', tex)
40 | }
41 | disconnect() {
42 | this.socket._diconnect = true;
43 | this.socket.disconnect()
44 |
45 | }
46 | emit(a, b) {
47 |
48 | this.socket.emit(a, b)
49 | }
50 |
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/source/core/stringBuilder.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | // No license here. Link: https://github.com/AJS-development/SimpleStringBuilder/blob/master/index.js
3 | module.exports = class SB {
4 | constructor(string) {
5 | this.t = [];
6 | this.t.push(string)
7 | }
8 | append(/**/) {
9 | if (!arguments) return false;
10 | arguments.forEach((str)=>{
11 | this.t.push(str)
12 | })
13 | return true;
14 | }
15 | toString() {
16 | return this.t.join("")
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/source/core/updater.js:
--------------------------------------------------------------------------------
1 | "use strict"
2 | var request = require('minirequest')
3 | var fs = require('fs')
4 | var exec = require('child_process').exec
5 | module.exports = class Updater {
6 | constructor(ss) {
7 | this.ss = ss;
8 | this.dir = 'https://raw.githubusercontent.com/AJS-development/OpenAgar/master'
9 | this.tobe = 0;
10 | this.dow = 0;
11 | }
12 | updateDone() {
13 | this.loading("done. Installing modules..")
14 | this.install(function (e) {
15 | if (e) throw e;
16 | else {
17 | this.loading("done. Restarting... ");
18 | exit(0);
19 | }
20 | }.bind(this))
21 |
22 | }
23 | install(call) {
24 | var child = exec("npm install", function (error, stdout, stderr) {
25 | call(error)
26 | });
27 | }
28 | update() {
29 | this.dow = 0;
30 | this.tobe = 2;
31 | console.log("gre{[Update]} Updating...".styleMe())
32 | request('https://raw.githubusercontent.com/AJS-development/OpAgMS/master/files.json', function (e, r, b) {
33 | try {
34 | if (!e && r.statusCode == 200) {
35 | var data = JSON.parse(b)
36 | this.count = 0;
37 | data.forEach((dt) => {
38 | if (!dt) return;
39 | this.count++;
40 | this.tobe++;
41 |
42 | this.downloadFile(dt, function (e) {
43 | if (e) throw e
44 |
45 | this.count--;
46 | if (this.count <= 0) {
47 | this.updateDone()
48 |
49 | }
50 | }.bind(this))
51 | })
52 |
53 | }
54 | } catch (e) {
55 | throw e
56 | }
57 | }.bind(this))
58 | }
59 | writeFileSafe(dir, file, data, call) {
60 |
61 | file = file.split("/")
62 | if (!file[0]) {
63 | file = file.slice(1)
64 | }
65 | try {
66 | fs.lstatSync(dir + "/" + file.join("/"))
67 | } catch (e) {
68 | var test = dir
69 | for (var i = 0; i < file.length - 1; i++) {
70 | var a = file[i]
71 | test += "/" + a
72 | try {
73 |
74 | fs.lstatSync(test)
75 | } catch (e) {
76 |
77 | fs.mkdir(test)
78 | }
79 | }
80 | }
81 |
82 |
83 | fs.writeFile(dir + "/" + file.join("/"), data, function () {
84 | call()
85 | })
86 |
87 | }
88 | loading(action) {
89 | this.dow++;
90 | var percent = Math.round(this.dow / this.tobe * 10)
91 | var bar = ""
92 | for (var i = 0; i < percent; i++) {
93 | bar = bar + "===";
94 | }
95 | if (percent == 10) bar = bar + "=";
96 | else bar = bar + ">";
97 | var extras = 31 - bar.length;
98 | var extra = "";
99 | for (var i = 0; i < extras; i++) extra = extra + " ";
100 | process.stdout.write("gre{[Update]} [".styleMe() + bar + extra + "] " + percent * 10 + "% " + action + "\r");
101 |
102 |
103 |
104 | }
105 | downloadFile(data, call) {
106 | var src = data.src
107 | var url = this.dir + data.url
108 |
109 |
110 | request(url, function (e, r, b) {
111 | if (!e && r.statusCode == 200 && b) {
112 | this.loading("Downloading");
113 | this.writeFileSafe(__dirname + "/../../", src, b, call)
114 |
115 |
116 | } else {
117 |
118 | call("Could not locate " + this.dir + data.url)
119 | }
120 |
121 | }.bind(this))
122 |
123 |
124 |
125 | }
126 |
127 |
128 | }
--------------------------------------------------------------------------------
/source/core/utilities.js:
--------------------------------------------------------------------------------
1 | // No license here!
2 |
3 | module.exports = {
4 | argsParser: function(str,splitpoint) { // commandname first:hello,secound:just,third:testing --> Object{first:"hello",secound:"just",third:"testing" }
5 | var cmd = str.split(" ");
6 | if (!splitpoint) splitpoint = 1;
7 | var args = cmd.slice(splitpoint,cmd.length).join(" ").split(",");
8 | var results = [];
9 | for (var i in args) {
10 | var arg = args[i];
11 | var a = arg.split(":");
12 | results[a[0]] = a[1];
13 | }
14 | return results;
15 | },
16 | dirEscape: function(before,dir,ext) {
17 |
18 | dir = dir.split('/')
19 | var file = dir[dir.length-1]
20 | var ex = file.split(".")[1]
21 | if (ext && ex != ext ) return false;
22 | var f = dir.slice(0,dir.length-1)
23 | f = f.join("/")
24 | if (f) f = f.replace(/\./g,"")
25 | return before + f + "/" + file
26 | },
27 | getRandomColor: function() {
28 | var colorRGB = [0xFF, 0x07, (Math.random() * 256) >> 0];
29 | colorRGB.sort(function () {
30 | return 0.5 - Math.random();
31 | });
32 |
33 | return {
34 | r: colorRGB[0],
35 | b: colorRGB[1],
36 | g: colorRGB[2]
37 | };
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/source/core/worldModel.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /*
3 | OpenAgar - Open source web game
4 | Copyright (C) 2016 Andrew S
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Affero General Public License as published
8 | by the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Affero General Public License for more details.
15 |
16 | You should have received a copy of the GNU Affero General Public License
17 | along with this program. If not, see .
18 | */
19 |
20 | const HashBounds = require('../modules/HashBounds.js');
21 | module.exports = class WorldModel {
22 | constructor(main) {
23 | this.nodes = new HashBounds(8, 2, Math.max(main.bounds.width, main.bounds.height) + 700, 700);
24 | this.main = main
25 | this.mapnodes = new Map();
26 | this.playerNodes = new Map();
27 | this.virusNodes = new Map();
28 | this.ejectedNodes = new Map();
29 | this.movingNodes = new Map();
30 | this.mergeNodes = new Map();
31 | this.lastID = 2;
32 | this.rainbowNodes = new Map();
33 | this.bulletNodes = new Map();
34 | this.wormHoleNodes = new Map();
35 | this.entities = {};
36 | this.entMap = [];
37 | }
38 |
39 | getNodes(s) {
40 | switch (s) {
41 | case "all":
42 | return this.nodes.allnodes;
43 | break;
44 | case "map":
45 | return this.mapnodes;
46 | break;
47 | case "hash":
48 | return this.nodes;
49 | break;
50 | case "moving":
51 | return this.movingNodes;
52 | break;
53 | case "player":
54 | return this.playerNodes;
55 | break;
56 | case "virus":
57 | return this.virusNodes;
58 | case "ejected":
59 | return this.ejectedNodes;
60 | case "merge":
61 | return this.mergeNodes;
62 | break;
63 | case "bullet":
64 | return this.bulletNodes;
65 | break;
66 | case "wormhole":
67 | return this.wormHoleNodes;
68 | break;
69 | default:
70 | if (!s) return this.nodes.allnodes;
71 | if (!this.entities[s]) return false;
72 | return this.entities[s];
73 | break;
74 |
75 | }
76 | }
77 |
78 | getNextID() {
79 | if (this.lastID >= 4294967295) {
80 | this.lastID = 0;
81 | }
82 |
83 | return this.lastID++;
84 | }
85 | update(node) {
86 | this.nodes.update(node)
87 |
88 | }
89 | addEntity(id, name) {
90 | this.entMap[id] = name;
91 | this.entities[name] = new Map();
92 | }
93 | addNode(node, type, flags) {
94 |
95 | var id = this.getNextID();
96 | node.bounds = {
97 | x: node.position.x - node.size,
98 | y: node.position.y - node.size,
99 | width: node.size * 2,
100 | height: node.size * 2
101 | }
102 | node.onAdd(id);
103 |
104 | this.nodes.insert(node);
105 |
106 | this.mapnodes.set(id, node);
107 | this.main.gameMode.event('onAllAdd', {
108 | cell: node
109 | })
110 | // add specified nodes
111 | switch (type) {
112 | case 0: // player
113 | this.playerNodes.set(id, node);
114 | this.main.gameMode.event('onCellAdd', {
115 | cell: node
116 | })
117 | break;
118 | case 1: // cell
119 | break;
120 | case 2: // virus
121 | this.virusNodes.set(id, node);
122 | break;
123 | case 3: // ejected
124 | this.ejectedNodes.set(id, node);
125 | break;
126 | case 4: // food
127 | break;
128 | case 5: // bullets
129 | this.bulletNodes.set(id, node)
130 | break;
131 | case 6: // wormhole
132 | this.wormHoleNodes.set(id, node)
133 | break;
134 | default:
135 | if (!this.entMap[type]) return false;
136 | this.entities[this.entMap[type]].set(id, node)
137 | break;
138 | }
139 |
140 | // set node as moving
141 | this.setFlags(node, flags)
142 | }
143 | setFlags(node, flags) {
144 | if (!flags) return;
145 | flags = flags.split(",");
146 | flags.forEach((flag) => {
147 | if (!flag) return;
148 | switch (flag) {
149 | case "m": // moving
150 |
151 | this.movingNodes.set(node.id, node);
152 | node.moving = true;
153 | break;
154 | case "r": // rainbow
155 | this.rainbowNodes.set(node.id, node)
156 | break;
157 | case "merge": // merge
158 | this.mergeNodes.set(node.id, node)
159 | break;
160 | default:
161 | return;
162 | break;
163 | }
164 |
165 | });
166 | }
167 |
168 | removeFlags(node, flags) {
169 |
170 | if (!flags) return;
171 | flags = flags.split(",");
172 | flags.forEach((flag) => {
173 | if (!flag) return;
174 | switch (flag) {
175 | case "m": // moving
176 | this.movingNodes.delete(node.id);
177 | if (node.type != 0) node.moving = false;
178 | this.main.childService.sendMove(node)
179 | break;
180 | case "r": // rainbow
181 | this.rainbowNodes.delete(node.id)
182 | break;
183 | case "merge":
184 | this.mergeNodes.delete(node.id)
185 | break;
186 | default:
187 | return;
188 | break;
189 | }
190 |
191 | });
192 | }
193 | deleteFromEnt(node) {
194 | for (var i in this.entities) {
195 | this.entities[i].delete(node.id)
196 | }
197 | }
198 | clear() {
199 | this.nodes.clear();
200 | this.mapnodes.clear();
201 | this.playerNodes.clear();
202 | this.virusNodes.clear();
203 | this.ejectedNodes.clear();
204 | this.movingNodes.clear();
205 | this.mergeNodes.clear();
206 | this.lastID = 2;
207 | this.rainbowNodes.clear();
208 | this.bulletNodes.clear();
209 | this.wormHoleNodes.clear();
210 | for (var i in this.entities) {
211 | this.entities[i].clear();
212 | }
213 | }
214 | removeNode(node) {
215 |
216 | if (node.hash) this.nodes.delete(node);
217 | this.main.gameMode.event('onAllRemove', {
218 | cell: node
219 | });
220 | this.rainbowNodes.delete(node.id)
221 | this.mapnodes.delete(node.id);
222 | this.movingNodes.delete(node.id);
223 | this.deleteFromEnt(node)
224 | node.moving = false
225 | this.ejectedNodes.delete(node.id);
226 | if (this.playerNodes.delete(node.id)) {
227 | this.main.gameMode.event('onCellRemove', {
228 | cell: node
229 | });
230 | return this.mergeNodes.delete(node.id)
231 | }
232 |
233 | if (this.bulletNodes.delete(node.id)) return;
234 | if (this.wormHoleNodes.delete(node.id)) return;
235 | if (this.virusNodes.delete(node.id)) return;
236 | }
237 | };
238 |
--------------------------------------------------------------------------------
/source/entities/MotherCell.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /*
3 | OpenAgar - Open source web game
4 | Copyright (C) 2016 Andrew S
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Affero General Public License as published
8 | by the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Affero General Public License for more details.
15 |
16 | You should have received a copy of the GNU Affero General Public License
17 | along with this program. If not, see .
18 | */
19 | var template = require('./template.js');
20 | module.exports = class MotherCell extends template {
21 | constructor(position, mass, type, owner, name) {
22 | super(position, mass, type, owner);
23 |
24 | this.color = {
25 | r: 190 + Math.floor(30 * Math.random()),
26 | g: 70 + Math.floor(30 * Math.random()),
27 | b: 85 + Math.floor(30 * Math.random())
28 | };
29 |
30 | this.type = 7;
31 |
32 | this.spiked = true;
33 |
34 |
35 | }
36 | feed(node, main) {
37 |
38 | node.eat(this, main)
39 | }
40 |
41 | getEatRange() {
42 |
43 | return this.size * -0.8;
44 |
45 | }
46 | collide(node, main) {
47 | if (node.mass < this.mass) {
48 | node.eat(this, main)
49 | } else if (node.mass > this.mass * 1.1) {
50 | var split = main.getConfig().playerMaxCells - node.owner.cells.size;
51 | if (split == 0) {
52 | node.addMass(this.mass)
53 | }
54 | var defaultmass = ~~(node.mass / (split + 2))
55 | var big = defaultmass * 2 + defaultmass / 2
56 | var medium = defaultmass / 2 + defaultmass
57 | var angle = (Math.random() * 6.28318530718) // Math.floor(Math.random() * max) + min
58 | node.updateMass(big)
59 | this.eat(node, main)
60 |
61 | // need to divide angle in order to spread them evenly
62 | // 360 degrees -> 2PI radians -> 6.28318530718
63 | var increment = 6.28318530718 / (split + 1) // want to add some randomness
64 | var g = ~~(split.length / 2)
65 | for (var i = 0; i < split; i++) {
66 | var mass = (i == 0) ? medium : defaultmass;
67 | var a = main.splitCell(node, angle, main.getConfig().splitSpeed, main.getConfig().splitDecay, mass)
68 | a.setMerge(main, main.getConfig().playerMerge, main.getConfig().playerMergeMult)
69 | main.getWorld().setFlags(a, "merge")
70 | main.getWorld().setFlags(node, "merge")
71 | angle += increment + (Math.random() * 0.03)
72 | if (angle > 6.28318530718) angle += -6.28318530718 // radians dims 0 < x < 2PI
73 | }
74 | }
75 | }
76 | update(main) {
77 | if (Math.random() > 0.971) {
78 | var maxFood = Math.random() * 2; // Max food spawned per tick
79 | var i = 0; // Food spawn counter
80 | while (i < maxFood) {
81 |
82 | this.spawnFood(main);
83 |
84 |
85 | // Increment
86 | i++;
87 | }
88 | }
89 |
90 | if (this.mass > 222) {
91 |
92 |
93 | var remaining = this.mass - 222;
94 | var maxAmount = Math.min(Math.floor(remaining / 2), 2);
95 | for (var i = 0; i < maxAmount; i++) {
96 | this.spawnFood(main);
97 | this.addMass(-2);
98 | }
99 | }
100 | }
101 | spawnFood(main) {
102 |
103 | if (main.food >= main.getConfig().maxFood) return
104 | var angle = Math.random() * 6.28;
105 | var pos = {
106 | x: this.position.x + (this.size * Math.cos(angle)),
107 | y: this.position.y + (this.size * Math.sin(angle))
108 | };
109 | var food = main.addNode(pos, 2, 4, false, false, "m");
110 | food.setEngine1(angle, 20, (Math.random() * 4) + 4)
111 |
112 | }
113 | move(main, sp) {
114 |
115 | // dont move
116 |
117 | }
118 | };
119 |
--------------------------------------------------------------------------------
/source/entities/bullet.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /*
3 | OpenAgar - Open source web game
4 | Copyright (C) 2016 Andrew S
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Affero General Public License as published
8 | by the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Affero General Public License for more details.
15 |
16 | You should have received a copy of the GNU Affero General Public License
17 | along with this program. If not, see .
18 | */
19 | var template = require('./template.js');
20 | module.exports = class Bullet extends template {
21 | constructor(position, mass, type, owner, name) {
22 | super(position, mass, type, owner);
23 | if (this.owner.golden) {
24 | this.golden = true;
25 | this.color = {
26 | r: 200,
27 | g: 200,
28 | b: 20
29 | }
30 | } else {
31 | this.golden = false;
32 | this.color = {
33 | r: 200,
34 | g: 200,
35 | b: 200
36 | }
37 | }
38 | this.fed = 0;
39 | this.type = 5;
40 |
41 | this.agit = true;
42 | this.nearby = [];
43 | this.own = owner
44 |
45 | }
46 | moveDone(main, method) {
47 |
48 | if (!this.moveEngine.useEngine && !this.moveEngine2.useEngine) main.removeNode(this)
49 |
50 | }
51 | feed(node, main) {
52 |
53 | var m1 = 4;
54 | var m2 = 100;
55 | var v1 = node.moveEngine.velocity;
56 | var v2 = this.moveEngine.velocity;
57 | var angle1 = node.moveEngine.angle;
58 | var angle2 = this.moveEngine.angle;
59 |
60 | var px = m1 * v1 * Math.cos(angle1) + m2 * v2 * Math.cos(angle1);
61 | var py = m1 * v1 * Math.sin(angle2) + m2 * v2 * Math.sin(angle2);
62 |
63 | var angle = Math.atan2(py, px);
64 |
65 |
66 |
67 | this.moveEngine.angle = angle;
68 | this.moveEngine.cos = Math.cos(angle)
69 | this.moveEngine.sin = Math.sin(angle)
70 | this.moveEngine.deltaT = 0;
71 |
72 | main.removeNode(node)
73 | }
74 | doesCollide(node, main) {
75 | return true;
76 |
77 | }
78 |
79 | onDeletion(main) {
80 | this.own.removeOwn(this)
81 | }
82 | onCreation(main) {
83 | this.own.setOwn(this)
84 | }
85 | getEatRange() {
86 |
87 | return this.size * -0.5;
88 |
89 | }
90 | explodeCell(node, main) {
91 |
92 |
93 | while (node.mass > 10) {
94 | node.addMass(-main.getConfig().ejectedMass);
95 | var pos = {
96 | x: node.position.x + Math.floor(Math.random() * 1000) - 500,
97 | y: node.position.y + Math.floor(Math.random() * 1000) - 500
98 |
99 | }
100 | var ejected = main.addNode(pos, main.getConfig().ejectedMass, 3, node.owner, [], "m")
101 | ejected.setEngine1(6.28 * Math.random(), main.getConfig().ejectedSpeed, main.getConfig().ejectedDecay)
102 | ejected.setCurve(10)
103 |
104 |
105 |
106 | }
107 |
108 |
109 | }
110 | collide(node, main) {
111 | if (this.owner == node.owner || node.owner.mass <= 500) {
112 |
113 | this.eat(node, main)
114 | node.addMass(2)
115 | node.owner.bulletsleft++;
116 | return;
117 | }
118 | if (this.golden) {
119 | this.explodeCell(node, main)
120 | return
121 | }
122 | var split = main.getConfig().playerMaxCells - node.owner.cells.size;
123 |
124 | var defaultmass = ~~(node.mass / (split + 15))
125 | var big = defaultmass * 3
126 | var medium = defaultmass / 2 + defaultmass * 2
127 | var angle = (Math.random() * 6.28318530718) // Math.floor(Math.random() * max) + min
128 | node.updateMass(big)
129 | this.eat(node, main)
130 |
131 | // need to divide angle in order to spread them evenly
132 | // 360 degrees -> 2PI radians -> 6.28318530718
133 | var increment = 6.28318530718 / (split + 1) // want to add some randomness
134 | var g = ~~(split.length / 2)
135 | for (var i = 0; i < split + 10; i++) {
136 | var mass = (i == 0) ? medium : defaultmass;
137 | var a = main.splitCell(node, angle, main.getConfig().splitSpeed, main.getConfig().splitDecay, mass)
138 | main.getWorld().setFlags(a, "merge")
139 | main.getWorld().setFlags(node, "merge")
140 | angle += increment + (Math.random() * 0.03)
141 | if (angle > 6.28318530718) angle += -6.28318530718 // radians dims 0 < x < 2PI
142 | }
143 |
144 | }
145 |
146 | };
147 |
--------------------------------------------------------------------------------
/source/entities/cell.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /*
3 | OpenAgar - Open source web game
4 | Copyright (C) 2016 Andrew S
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Affero General Public License as published
8 | by the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Affero General Public License for more details.
15 |
16 | You should have received a copy of the GNU Affero General Public License
17 | along with this program. If not, see .
18 | */
19 | var template = require('./template.js');
20 | module.exports = class Cell extends template {
21 | constructor(position, mass, type, owner, other) {
22 | super(position, mass, type, owner, other);
23 | }
24 | };
--------------------------------------------------------------------------------
/source/entities/ejectedMass.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /*
3 | OpenAgar - Open source web game
4 | Copyright (C) 2016 Andrew S
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Affero General Public License as published
8 | by the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Affero General Public License for more details.
15 |
16 | You should have received a copy of the GNU Affero General Public License
17 | along with this program. If not, see .
18 | */
19 | var template = require('./template.js');
20 | module.exports = class EjectedMass extends template {
21 | constructor(position, mass, type, owner, other) {
22 | super(position, mass, type, owner, other);
23 | this.color = owner.gameData.color;
24 | this.type = 3;
25 | this.viruses = [];
26 | this.up = false
27 | this.own = owner
28 |
29 | }
30 | onDeletion(main) {
31 | this.own.removeOwn(this)
32 | }
33 | onCreation(main) {
34 | this.own.setOwn(this)
35 | }
36 | move(main, speed) { // Speed code: 0 = 0.05, 1 = 0.1, 2 = 0.2
37 | if (this.moveEngine2.useEngine) this.calcMove2(main, speed)
38 | if (this.moveEngine.useEngine) this.calcMove(main, speed)
39 |
40 |
41 | this.checkGameBorders(main)
42 |
43 | main.updateHash(this)
44 | this.checkVirus(main)
45 | this.movCode()
46 |
47 | }
48 | checkVirus(main) {
49 | this.up = !this.up
50 | if (this.up)
51 |
52 |
53 | main.getWorld().getNodes('hash').every(this.bounds, (node) => {
54 |
55 | if (node.type == 2) {
56 |
57 | if (!node.collisionCheckCircle(this, true)) return true;
58 | node.feed(this, main)
59 |
60 | return false;
61 | } else
62 | if (node.type == 5) {
63 | if (!node.collisionCheckCircle(this)) return true;
64 | node.feed(this, main)
65 | return false;
66 | } else
67 | if (node.type == 0) {
68 | if (!node.collisionCheckCircle(this)) return true;
69 | this.eat(node, main)
70 | return false;
71 | } else if (node.type == 6) {
72 |
73 | if (!node.collisionCheckCircle(this)) return true;
74 | node.feed(this, main);
75 | return false;
76 | } else if (main.feedListeners[node.type]) {
77 | if (!node.collisionCheckCircle(this)) return true;
78 | node.feed(this, main)
79 | return false;
80 | }
81 |
82 | return true;
83 |
84 | })
85 | }
86 | };
--------------------------------------------------------------------------------
/source/entities/food.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /*
3 | OpenAgar - Open source web game
4 | Copyright (C) 2016 Andrew S
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Affero General Public License as published
8 | by the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Affero General Public License for more details.
15 |
16 | You should have received a copy of the GNU Affero General Public License
17 | along with this program. If not, see .
18 | */
19 | var template = require('./template.js');
20 | module.exports = class Food extends template {
21 | constructor(position, mass, type, owner, other) {
22 | super(position, mass, type, owner, other);
23 | this.type = 4;
24 | }
25 | onDeletion(main) {
26 | main.food--;
27 | }
28 | onCreation(main) {
29 | main.food++;
30 | }
31 | getEatRange() {
32 |
33 | return -this.size;
34 |
35 | }
36 | };
--------------------------------------------------------------------------------
/source/entities/index.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | cell: require('./cell.js'),
3 | food: require('./food.js'),
4 | playerCell: require('./playerCell.js'),
5 | ejectedMass: require('./ejectedMass.js'),
6 | virus: require('./virus.js'),
7 | bullet: require('./bullet.js'),
8 | wormHole: require('./wormHole.js')
9 | };
--------------------------------------------------------------------------------
/source/entities/playerCell.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /*
3 | OpenAgar - Open source web game
4 | Copyright (C) 2016 Andrew S
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Affero General Public License as published
8 | by the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Affero General Public License for more details.
15 |
16 | You should have received a copy of the GNU Affero General Public License
17 | along with this program. If not, see .
18 | */
19 | var template = require('./template.js');
20 | module.exports = class PlayerCell extends template {
21 | constructor(position, mass, type, owner) {
22 | super(position, mass, type, owner);
23 | this.name = owner.gameData.name;
24 | this.color = owner.gameData.color;
25 | if (owner.skinHandler) this.skin = owner.skinHandler.skin;
26 | this.mergeage = 0;
27 | this.canMerge = false;
28 | this.mergeMult = 1;
29 | this.mergeStatus = 1
30 | this.type = 0;
31 |
32 | this.moving = true;
33 | this.nearby = [];
34 | this.owner.mass += mass
35 | }
36 |
37 | onCreation(main) {
38 | this.owner.addCell(this);
39 | }
40 |
41 | onDeletion(main) {
42 | this.owner.mass -= this.mass
43 | this.owner.removeCell(this);
44 | }
45 |
46 | mergeDone(main) {
47 |
48 | }
49 | setMerge(main, num, mult) {
50 | this.mergeage = num
51 | this.canMerge = false;
52 | this.mergeMult = mult || 0
53 | main.getWorld().setFlags(this, 'merge')
54 | }
55 | calcMerge(main) { // once every 0.5 sec
56 | if (this.mergeStatus == 3) return; // 0 = instant merge, 3 = never merge
57 | if (this.mergeStatus == 0) {
58 | this.canMerge = true;
59 |
60 | main.getWorld().removeFlags(this, 'merge')
61 |
62 | this.mergeDone(main)
63 | return;
64 | }
65 | if (this.mergeage <= this.mass * -this.mergeMult) {
66 | this.canMerge = true;
67 | main.getWorld().removeFlags(this, 'merge')
68 |
69 | this.mergeDone(main)
70 | return;
71 | }
72 | this.mergeage--;
73 |
74 | //console.log(this.mergeage, this.mass * this.mergeMult, this.canMerge)
75 |
76 | }
77 | updateMass(mass) {
78 |
79 | if (this.mass === mass) return;
80 |
81 | var add = Math.max(mass, 10)
82 | var dif = add - this.mass
83 | this.owner.mass += dif
84 | this.mass = add
85 |
86 | this.getSize()
87 | this.speed = Math.pow(this.mass, -0.222) * 1.25;
88 | this.updCode()
89 | }
90 | moveToMouse(main, sp) {
91 |
92 | var speed = 0;
93 | if (sp == 0) {
94 | speed = this.speed
95 | } else if (sp == 1) {
96 | speed = this.speed * 2
97 | } else if (sp == 2) {
98 | speed = this.speed * 4
99 | }
100 | var mouse = this.owner.mouse,
101 |
102 | distx = mouse.x - this.position.x,
103 | disty = mouse.y - this.position.y,
104 | // y^2 = x^2 + b^2 -> y = sq(x^2 + b^2)
105 | num = Math.min(distx * distx + disty * disty, 625),
106 |
107 | dist = ~~(Sqrt.sqrt(num));
108 |
109 | var angle = Math.atan2(disty, distx)
110 | if (!dist) return; // dont want 0
111 | // want cell to slow down as it gets closer to mouse
112 | var k = Math.min(Math.abs(dist), 25) / 25, // max is 1
113 | p = speed * k * main.getConfig().playerSpeed,
114 | x = Math.cos(angle) * p,
115 | y = Math.sin(angle) * p;
116 | // console.log((speed * k * main.getConfig().playerSpeed)/50)
117 | this.position.x += Math.round(x);
118 | this.position.y += Math.round(y);
119 |
120 | }
121 | move(main, sp) {
122 | this.moveToMouse(main, sp)
123 | if (this.moveEngine2.useEngine) this.calcMove2(main, sp);
124 | if (this.moveEngine.useEngine) this.calcMove(main, sp);
125 |
126 |
127 |
128 | }
129 | };
130 |
--------------------------------------------------------------------------------
/source/entities/virus.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /*
3 | OpenAgar - Open source web game
4 | Copyright (C) 2016 Andrew S
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Affero General Public License as published
8 | by the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Affero General Public License for more details.
15 |
16 | You should have received a copy of the GNU Affero General Public License
17 | along with this program. If not, see .
18 | */
19 | var template = require('./template.js');
20 | module.exports = class Virus extends template {
21 | constructor(position, mass, type, owner, name) {
22 | super(position, mass, type, owner);
23 |
24 | this.color = {
25 | r: 0,
26 | g: 255,
27 | b: 0
28 | }
29 | this.fed = 0;
30 | this.type = 2;
31 |
32 | this.spiked = true;
33 | this.nearby = [];
34 |
35 | }
36 | feed(node, main) {
37 |
38 | /*
39 | Viruses have a completely different mech for OpenAgar. Instead of using the angle of the ejected mass, we get the point of collision and get the angle from that. The result? If you eject mass and it hits the edge of the virus, then it will travel the opposite direction. Like so
40 | \ // the path of split one is relative to the position collision
41 | \
42 | ()
43 | | // ejected mass hits edge of virus
44 |
45 | */
46 |
47 | node.eat(this, main)
48 | if (this.mass > main.getConfig().maxVirusMass) this.updateMass(main.getConfig().maxVirusMass)
49 |
50 |
51 | if (Math.random() < 0.8) this.fed++;
52 | if (this.fed > main.getConfig().virusFeedMin && main.viruses < main.getConfig().maxVirus) {
53 | var x1 = this.position.x,
54 | y1 = this.position.y,
55 | x2 = node.position.x,
56 | y2 = node.position.y
57 |
58 | var difx = x1 - x2
59 | var dify = y1 - y2
60 | var angle = Math.atan2(dify, difx)
61 | this.split(angle, main)
62 | this.fed = 0;
63 | this.updateMass(main.getConfig().virusMass)
64 |
65 | }
66 |
67 | }
68 | split(angle, main) {
69 | main.splitCell(this, angle, main.getConfig().virusSpeed, main.getConfig().virusDecay, main.getConfig().virusMass)
70 | }
71 |
72 |
73 | onDeletion(main) {
74 | main.viruses--;
75 | }
76 | onCreation(main) {
77 | main.viruses++;
78 | }
79 | getEatRange() {
80 |
81 | return this.size * -0.5;
82 |
83 | }
84 | collide(node, main) {
85 | this.eat(node, main);
86 | var split = main.getConfig().playerMaxCells - node.owner.cells.size;
87 |
88 |
89 |
90 | var defaultmass = ~~(node.mass / (split + 3))
91 | var big = defaultmass * 2 + (defaultmass / 2) // 2.5
92 | var medium = defaultmass / 2 + defaultmass // 1.5
93 | var angle = (Math.random() * 6.28318530718) // Math.floor(Math.random() * max) + min
94 | node.updateMass(big)
95 |
96 |
97 | // need to divide angle in order to spread them evenly
98 | // 360 degrees -> 2PI radians -> 6.28318530718
99 | var increment = 6.28318530718 / (split + 1) // want to add some randomness
100 | var g = ~~(split.length / 2)
101 | for (var i = 0; i < split; i++) {
102 | var mass = (i == 0) ? medium : defaultmass;
103 | var a = main.splitCell(node, angle, main.getConfig().splitSpeed, main.getConfig().splitDecay, mass)
104 | a.setMerge(main, main.getConfig().playerMerge, main.getConfig().playerMergeMult)
105 | main.getWorld().setFlags(a, "merge")
106 | main.getWorld().setFlags(node, "merge")
107 | angle += increment + (Math.random() * 0.03)
108 | if (angle > 6.28318530718) angle += -6.28318530718 // radians dims 0 < x < 2PI
109 | }
110 |
111 | }
112 | move(main, sp) {
113 |
114 | if (this.moveEngine2.useEngine) this.calcMove2(main, sp)
115 | if (this.moveEngine.useEngine) this.calcMove(main, sp);
116 | this.checkGameBorders(main)
117 | main.updateHash(this)
118 | this.movCode()
119 |
120 |
121 | }
122 | };
123 |
--------------------------------------------------------------------------------
/source/entities/wormHole.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /*
3 | OpenAgar - Open source web game
4 | Copyright (C) 2016 Andrew S
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU Affero General Public License as published
7 | by the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 | This program is distributed in the hope that it will be useful,
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | GNU Affero General Public License for more details.
13 | You should have received a copy of the GNU Affero General Public License
14 | along with this program. If not, see .
15 | */
16 | var template = require('./template.js');
17 | module.exports = class WormHole extends template {
18 | constructor(position, mass, type, owner, name) {
19 | super(position, mass, type, owner);
20 |
21 | this.color = {
22 | r: 0,
23 | g: 0,
24 | b: 0
25 | }
26 | this.okay = [];
27 |
28 | this.agit = true;
29 | this.type = 6;
30 |
31 |
32 | this.nearby = [];
33 |
34 |
35 | }
36 | feed(node, main) {
37 | this.teleport(node, main)
38 | }
39 | onDeletion(main) {
40 | main.wormHoles--;
41 | }
42 | onCreation(main) {
43 | main.wormHoles++;
44 | }
45 |
46 | tpa(node, main) {
47 |
48 | node.position.x = this.position.x
49 | node.position.y = this.position.y
50 | this.okay[node.id] = true;
51 | setTimeout(function () {
52 | this.okay[node.id] = false
53 | }.bind(this), 5000)
54 |
55 | }
56 | teleport(node, main) {
57 | var a = main.getWorld().getNodes('wormhole').toArray()
58 |
59 | a = a[Math.floor(Math.random() * a.length)]
60 |
61 | if (a) {
62 | a.tpa(node, main)
63 | }
64 | }
65 | explode(node, main) {
66 | var split = main.getConfig().playerMaxCells - node.owner.cells.size;
67 |
68 | var defaultmass = ~~(node.mass / (split + 7))
69 | var big = defaultmass * 3
70 | var medium = defaultmass / 2 + defaultmass * 2
71 | var angle = (Math.random() * 6.28318530718) // Math.floor(Math.random() * max) + min
72 | node.updateMass(big)
73 | this.eat(node, main)
74 |
75 | // need to divide angle in order to spread them evenly
76 | // 360 degrees -> 2PI radians -> 6.28318530718
77 | var increment = 6.28318530718 / (split + 1) // want to add some randomness
78 | var g = ~~(split.length / 2)
79 | for (var i = 0; i < split + 3; i++) {
80 | var mass = (i == 0) ? medium : defaultmass;
81 | var a = main.splitCell(node, angle, main.getConfig().splitSpeed, main.getConfig().splitDecay, mass)
82 | a.setMerge(main, main.getConfig().playerMerge, main.getConfig().playerMergeMult)
83 | main.getWorld().setFlags(a, "merge")
84 | main.getWorld().setFlags(node, "merge")
85 | angle += increment + (Math.random() * 0.03)
86 | if (angle > 6.28318530718) angle += -6.28318530718 // radians dims 0 < x < 2PI
87 | }
88 | }
89 | collide(node, main) {
90 |
91 | if (this.okay[node.id]) return;
92 | if (node.mass > this.mass) {
93 | var random = Math.random() * 100
94 | if (random <= 50) {
95 |
96 | } else if (random <= 80) {
97 |
98 | this.explode(node, main)
99 | return;
100 | } else {
101 | this.okay[node.id] = true;
102 | setTimeout(function () {
103 | this.okay[node.id] = false
104 | }.bind(this), 30000)
105 | return;
106 | }
107 | }
108 |
109 | if (node.owner.cells.size == 1) {
110 | this.teleport(node, main)
111 | } else {
112 | node.owner.cells.forEach((cell) => {
113 | if (cell == node) return;
114 | main.removeNode(cell)
115 |
116 | })
117 |
118 | this.teleport(node, main)
119 |
120 | }
121 |
122 | }
123 |
124 | };
--------------------------------------------------------------------------------
/source/modes/Experimental.js:
--------------------------------------------------------------------------------
1 | "use strict"
2 | /*
3 | OpenAgar - Open source web game
4 | Copyright (C) 2016 Andrew S
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Affero General Public License as published
8 | by the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Affero General Public License for more details.
15 |
16 | You should have received a copy of the GNU Affero General Public License
17 | along with this program. If not, see .
18 | */
19 |
20 | var template = require('./template.js');
21 | module.exports = class Experimental extends template {
22 | constructor() {
23 | super()
24 | this.id = 2;
25 | this.name = "Experimental";
26 |
27 | }
28 | onServerInit(data) {
29 | var main = data.main;
30 | main.addEntityType(7, "mother", require('../entities/MotherCell.js')); // add the mothercell entity. Type = 7, AccessName = "mother".
31 | main.addCollisionListener(7); // Add a player collision listener
32 | main.addFeedListener(7); // Add a ejected mass feed listener
33 |
34 | main.override("virus", "feed", function (node, main) {
35 | main.setFlags(this, "m")
36 | this.setEngine1(node.moveEngine.angle, 50, 2)
37 |
38 | main.removeNode(node);
39 | })
40 |
41 | main.addGenerationLoop(20, 7, "mother", 222) // set generation of mothercells. 20 mothercells min.
42 | } // override
43 |
44 | onTick(data) {
45 | data.main.getWorld().getNodes('mother').forEach((m) => {
46 | m.update(data.main);
47 | })
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/source/modes/FFA.js:
--------------------------------------------------------------------------------
1 | "use strict"
2 | var template = require('./template.js');
3 | module.exports = class FFA extends template {
4 | constructor() {
5 | super()
6 | this.id = 0;
7 | this.name = "FFA";
8 |
9 | }
10 |
11 |
12 | }
--------------------------------------------------------------------------------
/source/modes/Minions.js:
--------------------------------------------------------------------------------
1 | "use strict"
2 | /*
3 | OpenAgar - Open source web game
4 | Copyright (C) 2016 Andrew S
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Affero General Public License as published
8 | by the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Affero General Public License for more details.
15 |
16 | You should have received a copy of the GNU Affero General Public License
17 | along with this program. If not, see .
18 | */
19 | var template = require('./template.js');
20 | module.exports = class Minions extends template {
21 | constructor() {
22 | super()
23 | this.id = 3;
24 | this.name = "Minions";
25 |
26 | }
27 | onPlayerInit(data) {
28 |
29 | var num = 5,
30 | player = data.player,
31 | main = data.main;
32 | main.addMinions(player, num);
33 | }
34 |
35 |
36 | }
--------------------------------------------------------------------------------
/source/modes/Teams.js:
--------------------------------------------------------------------------------
1 | "use strict"
2 | var template = require('./template.js');
3 | module.exports = class Teams extends template {
4 | constructor() {
5 | super()
6 | this.id = 1;
7 | this.name = "Teams";
8 | this.lowest = 0;
9 | this.highest = false;
10 | this.colors = [{
11 | 'r': 223,
12 | 'g': 0,
13 | 'b': 0
14 | }, {
15 | 'r': 0,
16 | 'g': 223,
17 | 'b': 0
18 | }, {
19 | 'r': 0,
20 | 'g': 0,
21 | 'b': 223
22 | }, ];
23 | }
24 |
25 | onServerInit(data) {
26 | var main = data.main
27 | main.haveTeams = true;
28 |
29 | }
30 | onAllInit(data) {
31 | data.player.team = this.lowest;
32 |
33 | data.player.setColor(this.colors[data.player.team]);
34 |
35 | }
36 | onCellAdd(data) {
37 | data.cell.doesCollide = function (cell) {
38 |
39 | if (cell.type == 0 && this.owner.team == cell.owner.team) return true;
40 | return false;
41 | }
42 | data.cell.canEat = function (cell, main) {
43 | if (cell.type != 0 || this.owner.team != cell.owner.team) return true;
44 | return false;
45 | }
46 | }
47 | updateLB(data) {
48 | var main = data.main;
49 | var data = [];
50 | data[0] = 0;
51 | data[1] = 0;
52 | data[2] = 0;
53 | var total = 0;
54 | main.loopPlayers((player) => {
55 |
56 | data[player.team] += player.mass;
57 | total += player.mass;
58 | })
59 | var g = 0,
60 | h = 0,
61 | l = data[0],
62 | j = 0;
63 |
64 | data.forEach((n, i) => {
65 |
66 | if (n > h) {
67 | h = n;
68 | g = i;
69 | }
70 | if (n < l) {
71 | l = n;
72 | j = i;
73 | }
74 | })
75 |
76 | this.lowest = j;
77 | this.highest = g;
78 |
79 | data[0] = data[0] / total;
80 | data[1] = data[1] / total;
81 | data[2] = data[2] / total;
82 | var lb = {
83 | lb: data,
84 | conf: {
85 | lbtype: 1
86 | }
87 |
88 | }
89 | main.clients.forEach((client) => {
90 |
91 | client.socket.emit('lb', lb);
92 | })
93 | return false;
94 | }
95 | }
--------------------------------------------------------------------------------
/source/modes/advTeams.js:
--------------------------------------------------------------------------------
1 | "use strict"
2 | var template = require('./template.js');
3 | module.exports = class Teams extends template {
4 | constructor() {
5 | super()
6 | this.id = 1;
7 | this.name = "Advanced Teams";
8 | this.lowest = 0;
9 | this.highest = false;
10 | this.colors = [{
11 | 'r': 223,
12 | 'g': 0,
13 | 'b': 0
14 | }, {
15 | 'r': 0,
16 | 'g': 223,
17 | 'b': 0
18 | }, {
19 | 'r': 0,
20 | 'g': 0,
21 | 'b': 223
22 | }, ];
23 | }
24 |
25 | onServerInit(data) {
26 | var main = data.main
27 | main.haveTeams = true;
28 |
29 | }
30 | onAllInit(data) {
31 | data.player.team = this.lowest;
32 |
33 | data.player.setColor(this.colors[data.player.team]);
34 |
35 | }
36 |
37 | onCellAdd(data) {
38 |
39 | data.cell.doesCollide = function (cell) {
40 |
41 | if (cell.type == 0 && this.owner.team == cell.owner.team && cell.owner.cells.size <= 1 && this.owner.cells.size <= 1) return true;
42 |
43 | return false;
44 | }
45 | data.cell.canEat = function (cell, main) {
46 |
47 | if (cell.type != 0 || this.owner.team != cell.owner.team || cell.owner.cells.size > 1) return true;
48 | return false;
49 | }
50 | }
51 | updateLB(data) {
52 | var main = data.main;
53 | var data = [];
54 | data[0] = 0;
55 | data[1] = 0;
56 | data[2] = 0;
57 | var total = 0;
58 | main.loopPlayers((player) => {
59 |
60 | data[player.team] += player.mass;
61 | total += player.mass;
62 | })
63 | var g = 0,
64 | h = 0,
65 | l = data[0],
66 | j = 0;
67 |
68 | data.forEach((n, i) => {
69 |
70 | if (n > h) {
71 | h = n;
72 | g = i;
73 | }
74 | if (n < l) {
75 | l = n;
76 | j = i;
77 | }
78 | })
79 |
80 | this.lowest = j;
81 | this.highest = g;
82 |
83 | data[0] = data[0] / total;
84 | data[1] = data[1] / total;
85 | data[2] = data[2] / total;
86 | var lb = {
87 | lb: data,
88 | conf: {
89 | lbtype: 1
90 | }
91 |
92 | }
93 | main.clients.forEach((client) => {
94 |
95 | client.socket.emit('lb', lb);
96 | })
97 | return false;
98 | }
99 | }
--------------------------------------------------------------------------------
/source/modes/index.js:
--------------------------------------------------------------------------------
1 | "use strict"
2 | module.exports = {
3 | modes: [require('./FFA.js'), require('./Teams.js'), require('./Experimental.js'), require('./Minions.js'), require('./HideNSeek.js'), require('./advTeams.js')],
4 | get: function (id) {
5 | if (!this.modes[id]) return false;
6 | var a = new this.modes[id]()
7 | return a;
8 | },
9 |
10 | }
--------------------------------------------------------------------------------
/source/modes/template.js:
--------------------------------------------------------------------------------
1 | "use strict"
2 |
3 | module.exports = class Template { // made gamemodes very alike ogar because then people will already know what to do
4 | constructor() {
5 | this.id = -1;
6 | this.name = "Template";
7 | this.decayMod = 1;
8 | }
9 |
10 | onServerInit(data) { // Called when the server starts
11 |
12 |
13 | }
14 | onTick(data) { // Called at every 0.1s
15 |
16 | }
17 | onChange(data) { // Called when someone changes the gamemode via console commands
18 |
19 | }
20 |
21 | onPlayerInit(data) { // Called when a player joins a server
22 |
23 | }
24 |
25 | onPlayerSpawn(data) { // Called on spawn
26 |
27 |
28 | }
29 | onAllInit(data) { // Called when a player/bot/minion joins
30 |
31 | }
32 |
33 | pressQ(data) { // Called when the Q key is pressed
34 |
35 | // returning nothing will make it use the default action, returning false will make it be disabled entirely
36 | }
37 |
38 | pressW(data) { // Called when the W key is pressed
39 |
40 |
41 | }
42 | pressSpace(data) { // Called when the Space bar is pressed
43 |
44 |
45 | }
46 | onCellAdd(data) {
47 | // Called when a player cell is added
48 | }
49 | onCellRemove(data) {
50 | // Called when a player cell is removed
51 | }
52 | onAllAdd(data) { // Called when a cell is added
53 |
54 | }
55 | onAllRemove(data) {
56 | // Called when a cell is removed
57 | }
58 | updateLB(data) {
59 | // Called when the leaderboard update function is called
60 |
61 | }
62 |
63 | }
--------------------------------------------------------------------------------
/source/modules/FastBuffers.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /*
3 | Copyright 2016 Andrew S
4 |
5 | You may use this without this copyright header, this header is only so people cant sue me if they claim it as theirs.
6 | */
7 | module.exports = {
8 | writer: class Writer {
9 | constructor(size) {
10 | this.index = 0;
11 | this.buffer = Buffer.alloc(size);
12 | }
13 | writeString8(string) {
14 |
15 | for (var i = 0; i < string.length; i++) {
16 | var c = string.charCodeAt(i);
17 | this.writeUInt8(c);
18 | }
19 | this.writeUInt8(0)
20 | }
21 | writeString16(string) {
22 |
23 | for (var i = 0; i < string.length; i++) {
24 | var c = string.charCodeAt(i);
25 |
26 | this.writeUInt16BE(c);
27 | }
28 |
29 | this.writeUInt16BE(0);
30 |
31 | }
32 | writeString32(string) {
33 |
34 | for (var i = 0; i < string.length; i++) {
35 | var c = string.charCodeAt(i)
36 | if (c) this.writeUInt32BE(c)
37 | }
38 | this.writeUInt32BE(0);
39 | }
40 | writeDynamic(a) {
41 | var i;
42 | if (a > 270549119) {
43 | throw "ERR: OUT OF BOUNDS"
44 | } else if (a > 2113663) {
45 | a = a - 2113664;
46 | i = 3;
47 | } else if (a > 16511) {
48 | a = a - 16512;
49 | i = 2;
50 | } else if (a > 127) {
51 | a = a - 128;
52 | i = 1;
53 | } else {
54 | i = 0;
55 | }
56 |
57 | for (var j = 0; j < i; j++) {
58 |
59 | this.writeUInt8((a & 127) | 128);
60 | a = a >> 7;
61 | }
62 | this.writeUInt8(a);
63 | }
64 |
65 | writeInt8(n) {
66 | this.buffer.writeInt8(n, this.index++)
67 | }
68 | writeInt16BE(n) {
69 | this.buffer.writeInt16BE(n, this.index)
70 | this.index += 2;
71 | }
72 | writeInt16LE(n) {
73 | this.buffer.writeInt16LE(n, this.index)
74 | this.index += 2;
75 | }
76 | writeInt32BE(n) {
77 | this.buffer.writeInt32BE(n, this.index)
78 | this.index += 4;
79 | }
80 | writeInt32LE(n) {
81 | this.buffer.writeInt32LE(n, this.index)
82 | this.index += 4;
83 | }
84 | writeUInt8(n) {
85 | this.buffer.writeUInt8(n, this.index++)
86 | }
87 | writeUInt16BE(n) {
88 | this.buffer.writeUInt16BE(n, this.index)
89 | this.index += 2;
90 | }
91 | writeUInt16LE(n) {
92 | this.buffer.writeUInt16LE(n, this.index)
93 | this.index += 2;
94 | }
95 | writeUInt32BE(n) {
96 | this.buffer.writeUInt32BE(n, this.index)
97 | this.index += 4;
98 | }
99 | writeUInt32LE(n) {
100 | this.buffer.writeUInt32LE(n, this.index)
101 | this.index += 4;
102 | }
103 | toBuffer() {
104 | return this.buffer;
105 | }
106 | },
107 | getDynamicSize: function (a) {
108 | if (a > 270549119) {
109 | throw "ERR: OUT OF BOUNDS"
110 | } else if (a > 2113663) {
111 | return 4;
112 | } else if (a > 16511) {
113 | return 3;
114 | } else if (a > 127) {
115 | return 2;
116 | } else {
117 | return 1;
118 | }
119 | },
120 | reader: class Reader {
121 | constructor(buf) {
122 | this.index = 0;
123 | this.buffer = buf;
124 | }
125 | readString8() {
126 | var data = "";
127 | while (this.index <= this.buffer.length) {
128 | var d = this.readUInt8();
129 | if (!d) break;
130 | data += String.fromCharCode(d);
131 | }
132 | return data;
133 | }
134 | readString16() {
135 | var data = "";
136 | while (this.index <= this.buffer.length) {
137 | var d = this.readUInt16BE();
138 | if (!d) break;
139 | data += String.fromCharCode(d);
140 | }
141 | return data;
142 | }
143 | readString32() {
144 | var data = "";
145 | while (this.index <= this.buffer.length) {
146 | var d = this.readUInt32BE();
147 | if (!d) break;
148 | data += String.fromCharCode(d);
149 | }
150 | return data;
151 | }
152 | readDynamic() {
153 | var num = 0;
154 |
155 | for (var i = 0; i < 4; i++) {
156 |
157 | var n = this.readUInt8();
158 |
159 | num += (n & 127) << (i * 7);
160 |
161 |
162 | if (n < 127) {
163 | break;
164 | }
165 | }
166 |
167 | if (i === 2) num += 128;
168 | else if (i === 3) num += 16512;
169 | else if (i === 4) num += 2113664;
170 |
171 | return num;
172 | }
173 | readInt8() {
174 | return this.buffer.readInt8(this.index++);
175 | }
176 | readUInt8() {
177 | return this.buffer.readUInt8(this.index++);
178 | }
179 | readInt16BE() {
180 | var data = this.buffer.readInt16BE(this.index);
181 | this.index += 2;
182 | return data;
183 | }
184 | readInt16LE() {
185 | var data = this.buffer.readInt16LE(this.index);
186 | this.index += 2;
187 | return data;
188 | }
189 | readUInt16BE() {
190 | var data = this.buffer.readUInt16BE(this.index);
191 | this.index += 2;
192 | return data;
193 | }
194 | readUInt16LE() {
195 | var data = this.buffer.readUInt16LE(this.index);
196 | this.index += 2;
197 | return data;
198 | }
199 | readInt32BE() {
200 | var data = this.buffer.readInt32BE(this.index);
201 | this.index += 4;
202 | return data;
203 | }
204 | readInt32LE() {
205 | var data = this.buffer.readInt32LE(this.index);
206 | this.index += 4;
207 | return data;
208 | }
209 | readUInt32BE() {
210 | var data = this.buffer.readUInt32BE(this.index);
211 | this.index += 4;
212 | return data;
213 | }
214 | readUInt32LE() {
215 | var data = this.buffer.readUInt32LE(this.index);
216 | this.index += 4;
217 | return data;
218 | }
219 |
220 | }
221 |
222 | }
223 |
--------------------------------------------------------------------------------
/source/modules/HashBounds.js:
--------------------------------------------------------------------------------
1 | "use strict"
2 | /*
3 | HashBounds - A hierarchical spacial hashing system
4 | Copyright (C) 2016 Andrew S
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Affero General Public License as published
8 | by the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Affero General Public License for more details.
15 |
16 | You should have received a copy of the GNU Affero General Public License
17 | along with this program. If not, see .
18 | */
19 |
20 |
21 | class Holder {
22 | constructor(parent, x, y, power, lvl) {
23 | this.PARENT = parent;
24 | this.PARENT.CHILDREN.push(this)
25 | // this.MAP = new QuickMapV2();
26 | this.MAP = [];
27 | this.POWER = power;
28 | this.LVL = lvl
29 | this.LEN = 0; // problem with lots of objs
30 | this.X = x;
31 | this.Y = y;
32 | this.BOUNDS = {
33 | x: x << power,
34 | y: y << power,
35 | width: 1 << power,
36 | height: 1 << power
37 | }
38 | this.CHILDREN = []
39 |
40 | }
41 | checkIntersect(r1, r2) {
42 | var mx1 = r1.x + r1.width,
43 | mx2 = r2.x + r2.width,
44 | my1 = r1.y + r1.height,
45 | my2 = r2.y + r2.height;
46 | /*
47 | !(r2.left > r1.right ||
48 | r2.right < r1.left ||
49 | r2.top > r1.bottom ||
50 | r2.bottom < r1.top);
51 |
52 | */
53 |
54 |
55 |
56 | return !(r2.x >= mx1 || mx2 <= r1.x || r2.y >= my1 || my2 <= r1.y)
57 |
58 | }
59 |
60 | set(node) {
61 |
62 | this.MAP.push(node);
63 | this.add()
64 | }
65 | delete(node) {
66 | var ind = this.MAP.indexOf(node)
67 |
68 | this.MAP[ind] = this.MAP[this.MAP.length - 1];
69 | this.MAP.pop();
70 | this.sub()
71 | }
72 | add() {
73 | ++this.LEN;
74 | this.PARENT.add();
75 |
76 |
77 | }
78 |
79 | getQuad(bounds, bounds2) {
80 | if (!this.CHILDREN[0]) return -2;
81 |
82 | var minX = bounds.x,
83 | minY = bounds.y,
84 | maxX = bounds.x + bounds.width,
85 | maxY = bounds.y + bounds.height,
86 | minX2 = bounds2.x,
87 | minY2 = bounds2.y,
88 | maxX2 = bounds2.x + bounds2.width,
89 | maxY2 = bounds2.y + bounds2.height,
90 | halfY = bounds2.y + (bounds2.height >> 1),
91 | halfX = bounds2.x + (bounds2.width >> 1);
92 |
93 |
94 | var top = maxY <= halfY;
95 | var bottom = minY > halfY;
96 | var left = maxX <= halfX;
97 | var right = minX > halfX;
98 |
99 |
100 | if (top) {
101 | if (left) return [0];
102 | else if (right) return [2];
103 | return [0, 2];
104 | } else if (bottom) {
105 | if (left) return [1];
106 | else if (right) return [3];
107 | return [1, 3];
108 | }
109 |
110 | if (left) {
111 | return [0, 1];
112 | } else if (right) {
113 | return [2, 3];
114 | }
115 |
116 | if (bounds.width < bounds2.width || bounds.height < bounds2.height) return [0, 1, 2, 3];
117 | return -1; // too big
118 | }
119 |
120 |
121 |
122 | forEachAll(call) {
123 | if (!this.LEN) return;
124 | this.MAP.forEach(call)
125 |
126 | for (var i = 0; i < this.CHILDREN.length; ++i) {
127 | this.CHILDREN[i].forEachAll(call)
128 | }
129 |
130 |
131 | }
132 | forEach(bounds, call) {
133 | if (!this.LEN) return;
134 |
135 |
136 | var quads = this.getQuad(bounds, this.BOUNDS)
137 |
138 | if (quads === -1) return this.forEachAll(call);
139 |
140 | this.MAP.forEach(call)
141 |
142 | if (quads === -2) return
143 |
144 | for (var i = 0, l = quads.length; i < l; i++) {
145 | var child = this.CHILDREN[quads[i]];
146 | if (child) child.forEach(bounds, call)
147 | }
148 |
149 |
150 | return;
151 | }
152 | every(bounds, call) {
153 | if (!this.LEN) return true;
154 |
155 | var quads = this.getQuad(bounds, this.BOUNDS)
156 |
157 | if (quads === -1) return this.everyAll(call);
158 |
159 | if (!this.MAP.every(call)) return false;
160 |
161 | if (quads === -2) return true;
162 |
163 | return quads.every((q) => {
164 | var child = this.CHILDREN[q];
165 | if (!child) return true;
166 | return child.every(bounds, call)
167 | })
168 | }
169 | everyAll(call) {
170 | if (!this.LEN) return true;
171 | if (!this.MAP.every(call)) return false;
172 | for (var i = 0; i < this.CHILDREN.length; ++i) {
173 | if (!this.CHILDREN[i].everyAll(call)) return false;
174 | }
175 | return true;
176 | }
177 |
178 | sub() {
179 | --this.LEN;
180 | this.PARENT.sub();
181 | }
182 |
183 |
184 | }
185 | class Grid {
186 | constructor(g, p, size, prev) {
187 | this.POWER = g;
188 | this.LEVEL = p;
189 | this.PREV = prev;
190 | this.SIZE = size;
191 |
192 | this.DATA = {};
193 | this.init()
194 | }
195 |
196 | init() {
197 | if (this.SIZE >= 65535) {
198 | throw "Maximum amount of buckets are 65535^2"
199 | } // Max limit is 65535 (16 bits)
200 | // console.log(this.SIZE)
201 | for (var j = 0; j < this.SIZE; ++j) {
202 | var x = j * this.SIZE;
203 | if (this.PREV) var bx = (j >> 1) * this.PREV.SIZE;
204 | for (var i = 0; i < this.SIZE; ++i) {
205 |
206 | var by = i >> 1;
207 | var key = x + i;
208 |
209 |
210 | if (this.PREV) var l = this.PREV.DATA[bx + by];
211 | else
212 | var l = {
213 | CHILDREN: [],
214 | add: function () {},
215 | sub: function () {}
216 | }
217 | this.DATA[key] = new Holder(l, j, i, this.POWER, this.LEVEL);
218 |
219 | }
220 | }
221 | }
222 |
223 | getKey(x, y) {
224 | return {
225 | x: Math.max(x >> this.POWER, 0),
226 | y: Math.max(y >> this.POWER, 0)
227 | }
228 | }
229 | _getKey(x, y) {
230 | return x | y
231 |
232 | }
233 | _get(bounds, call) {
234 | var x1 = bounds.x,
235 | y1 = bounds.y,
236 | x2 = bounds.x + bounds.width,
237 | y2 = bounds.y + bounds.height;
238 |
239 | var k1 = this.getKey(x1, y1)
240 | var k2 = this.getKey(x2, y2)
241 |
242 | for (var j = k1.x; j <= k2.x; ++j) {
243 |
244 | var x = j * this.SIZE;
245 |
246 | for (var i = k1.y; i <= k2.y; ++i) {
247 |
248 |
249 | var key = x + i;
250 | if (this.DATA[key]) {
251 | if (!call(this.DATA[key])) return false
252 | }
253 |
254 | }
255 | }
256 | return true;
257 | }
258 |
259 | insert2(node) {
260 |
261 | // var a = this.getKey(node.bounds.width, node.bounds.height);
262 | // if (a.x + a.y >= 2 && this.LEVEL != 0) return false;
263 |
264 | var x1 = node.bounds.x,
265 | y1 = node.bounds.y,
266 | x2 = node.bounds.x + node.bounds.width,
267 | y2 = node.bounds.y + node.bounds.height;
268 |
269 | var k1 = this.getKey(x1, y1)
270 | var k2 = this.getKey(x2, y2)
271 | node.hash.k1 = k1
272 | node.hash.k2 = k2
273 | node.hash.level = this.LEVEL;
274 |
275 | for (var j = k1.x; j <= k2.x; ++j) {
276 | var x = j * this.SIZE;
277 | for (var i = k1.y; i <= k2.y; ++i) {
278 |
279 | var ke = x + i;
280 |
281 | // console.log(ke)
282 | if (this.DATA[ke]) this.DATA[ke].set(node)
283 |
284 |
285 |
286 | }
287 |
288 | }
289 |
290 |
291 | return true;
292 | }
293 | delete(node) {
294 | var k1 = node.hash.k1
295 | var k2 = node.hash.k2
296 | var lenX = k2.x,
297 | lenY = k2.y;
298 | for (var j = k1.x; j <= lenX; ++j) {
299 | var x = j * this.SIZE;
300 | for (var i = k1.y; i <= lenY; ++i) {
301 |
302 |
303 | var ke = x + i;
304 |
305 | if (this.DATA[ke]) this.DATA[ke].delete(node)
306 | }
307 |
308 | }
309 | }
310 | toArray(bounds) {
311 | var hsh = {};
312 | var array = [];
313 | this._get(bounds, function (cell) {
314 |
315 | cell.forEach(bounds, function (obj) {
316 | if (hsh[obj._HashID]) return;
317 | hsh[obj._HashID] = true;
318 | array.push(obj);
319 |
320 | })
321 | return true;
322 | })
323 | return array;
324 | }
325 | every(bounds, call) {
326 | var hsh = {};
327 |
328 | return this._get(bounds, function (cell) {
329 |
330 | return cell.every(bounds, function (obj, i) {
331 | if (hsh[obj._HashID]) return true;
332 | hsh[obj._HashID] = true;
333 | return call(obj);
334 |
335 | })
336 | })
337 | }
338 | forEach(bounds, call) {
339 |
340 | var hsh = {};
341 |
342 | this._get(bounds, function (cell) {
343 |
344 | cell.forEach(bounds, function (obj, i) {
345 | if (hsh[obj._HashID]) return;
346 | hsh[obj._HashID] = true;
347 | call(obj);
348 |
349 | })
350 | return true;
351 | })
352 | }
353 | }
354 |
355 | module.exports = class HashBounds {
356 | constructor(power, lvl, max) {
357 | this.INITIAL = power;
358 | this.LVL = lvl;
359 | this.MAX = max;
360 |
361 | this.MIN = power;
362 | this.LEVELS = []
363 | this.lastid = 0;
364 | this.BASE = false;
365 | this.createLevels()
366 | this.log2 = [];
367 | this.setupLog2()
368 | }
369 | setupLog2() {
370 | var pow = 1 << this.LVL;
371 | for (var i = 0; i < pow; ++i) {
372 | this.log2[i - 1] = Math.floor(Math.log2(i))
373 | }
374 | }
375 | createLevels() {
376 | this.LEVELS = [];
377 |
378 | var last = false;
379 | for (var i = this.LVL - 1; i >= 0; --i) {
380 | var a = this.INITIAL + i;
381 | var b = 1 << a;
382 | var grid = new Grid(a, i, Math.ceil(this.MAX / b), last)
383 | if (!this.BASE) this.BASE = grid;
384 | this.LEVELS[i] = grid;
385 | last = grid;
386 | }
387 |
388 | }
389 | clear() {
390 | this.createLevels();
391 | }
392 | update(node) {
393 | this.delete(node)
394 | this.insert(node)
395 | }
396 | insert(node) {
397 | if (node._IsInHash) throw "ERR: A node cannot be already in a hash!"
398 | var bounds = node.bounds;
399 | node._IsInHash = true;
400 |
401 | if (node._HashSizeX === bounds.width && node._HashSizeY === bounds.height) {
402 | this.LEVELS[node._HashIndex].insert2(node);
403 | return;
404 | }
405 |
406 | if (!node._HashID) {
407 | node._HashID = ++this.lastid;
408 | node.hash = {};
409 | }
410 |
411 | var index = this.log2[(Math.max(bounds.width, bounds.height) >> this.MIN)]
412 | if (index === undefined) index = this.LVL - 1;
413 |
414 | node._HashIndex = index;
415 | node._HashSizeX = bounds.width;
416 | node._HashSizeY = bounds.height;
417 |
418 | this.LEVELS[index].insert2(node);
419 |
420 | //for (var i = 0; i < len; ++i) {
421 | // if (this.LEVELS[len - i - 1].insert(node)) break;
422 | //}
423 | }
424 |
425 |
426 | delete(node) {
427 | if (!node._IsInHash) throw "ERR: Node is not in a hash!"
428 | this.LEVELS[node.hash.level].delete(node)
429 | node._IsInHash = false;
430 | }
431 | toArray(bounds) {
432 | return this.BASE.toArray(bounds);
433 | }
434 | every(bounds, call) {
435 | return this.BASE.every(bounds, call);
436 | }
437 | forEach(bounds, call) {
438 |
439 |
440 | this.BASE.forEach(bounds, call)
441 |
442 |
443 |
444 | }
445 |
446 | }
--------------------------------------------------------------------------------
/source/modules/fastSquares.js:
--------------------------------------------------------------------------------
1 | // No license here! This is free to the public!
2 |
3 | // Use: A faster alternative to Math.sqrt()
4 |
5 | /*
6 | How to use:
7 |
8 | var a = require('path to fastsquares')
9 | Sqrt = new a()
10 |
11 | Then you can use this anywhere in your code by doing
12 |
13 | Sqrt.sqrt(num)
14 |
15 | */
16 |
17 | "use strict"
18 |
19 | module.exports = class FastSquares {
20 | constructor() {
21 | this.lib = [];
22 | this.init()
23 | }
24 | init() {
25 |
26 |
27 | for (var i = 0; i < 1000000; i ++) {
28 | this.lib.push(Math.sqrt(i))
29 | }
30 |
31 |
32 | }
33 | sqrt(a) {
34 | var b = this.lib[~~a]
35 | if (b === undefined) {
36 | return Math.sqrt(~~a)
37 | }
38 | return b
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/source/modules/ini.js:
--------------------------------------------------------------------------------
1 |
2 | exports.parse = exports.decode = decode;
3 | exports.stringify = exports.encode = encode;
4 |
5 | exports.safe = safe;
6 | exports.unsafe = unsafe;
7 |
8 | var eol = process.platform === "win32" ? "\r\n" : "\n";
9 |
10 | function encode (obj, opt) {
11 | var children = [],
12 | out = "";
13 |
14 | if (typeof opt === "string") {
15 | opt = {
16 | section: opt,
17 | whitespace: false
18 | };
19 | } else {
20 | opt = opt || {};
21 | opt.whitespace = opt.whitespace === true;
22 | }
23 |
24 | var separator = " = ";
25 |
26 | Object.keys(obj).forEach(function (k, _, __) {
27 | var val = obj[k];
28 | if (val && Array.isArray(val)) {
29 | val.forEach(function(item) {
30 | out += safe(k + "[]") + separator + safe(item) + "\n";
31 | });
32 | }
33 | else if (val && typeof val === "object") {
34 | children.push(k);
35 | } else {
36 | out += safe(k) + separator + safe(val) + eol;
37 | }
38 | });
39 |
40 | if (opt.section && out.length) {
41 | out = "[" + safe(opt.section) + "]" + eol + out;
42 | }
43 |
44 | children.forEach(function (k, _, __) {
45 | var nk = dotSplit(k).join('\\.');
46 | var section = (opt.section ? opt.section + "." : "") + nk;
47 | var child = encode(obj[k], {
48 | section: section,
49 | whitespace: opt.whitespace
50 | });
51 | if (out.length && child.length) {
52 | out += eol;
53 | }
54 | out += child;
55 | });
56 |
57 | return out;
58 | }
59 |
60 | function dotSplit (str) {
61 | return str.replace(/\1/g, '\u0002LITERAL\\1LITERAL\u0002')
62 | .replace(/\\\./g, '\u0001')
63 | .split(/\./).map(function (part) {
64 | return part.replace(/\1/g, '\\.')
65 | .replace(/\2LITERAL\\1LITERAL\2/g, '\u0001');
66 | });
67 | }
68 |
69 | function decode (str) {
70 | var out = {},
71 | p = out,
72 | state = "START",
73 | // section |key = value
74 | re = /^\[([^\]]*)\]$|^([^=]+)(=(.*))?$/i,
75 | lines = str.split(/[\r\n]+/g),
76 | section = null;
77 |
78 | lines.forEach(function (line, _, __) {
79 | if (!line || line.match(/^\s*(\/\/|[#;])/)) {
80 | return;
81 | }
82 |
83 | var match = line.match(re);
84 |
85 | if (!match) {
86 | return;
87 | }
88 |
89 | if (match[1] !== undefined) {
90 | section = unsafe(match[1]);
91 | p = out[section] = out[section] || {};
92 | return;
93 | }
94 |
95 | var key = unsafe(match[2]),
96 | value = match[3] ? unsafe((match[4] || "")) : true;
97 |
98 | // Convert keys with '[]' suffix to an array
99 | if (key.length > 2 && key.slice(-2) === "[]") {
100 | key = key.substring(0, key.length - 2);
101 | if (!p[key]) {
102 | p[key] = [];
103 | } else if (!Array.isArray(p[key])) {
104 | p[key] = [p[key]];
105 | }
106 | }
107 |
108 | // safeguard against resetting a previously defined
109 | // array by accidentally forgetting the brackets
110 | if (isNaN(value)) {
111 | if (value == 'true') { // Booleans
112 | p[key] = true;
113 | } else if (value == 'false') {
114 | p[key] = false;
115 | } else {
116 | p[key] = value;
117 | }
118 | } else {
119 | if (isInt(value)) {
120 | p[key] = parseInt(value);
121 | } else {
122 | p[key] = parseFloat(value);
123 | }
124 | }
125 | });
126 |
127 | // {a:{y:1},"a.b":{x:2}} --> {a:{y:1,b:{x:2}}}
128 | // use a filter to return the keys that have to be deleted.
129 | Object.keys(out).filter(function (k, _, __) {
130 | if (!out[k] || typeof out[k] !== "object" || Array.isArray(out[k])) return false
131 | // see if the parent section is also an object.
132 | // if so, add it to that, and mark this one for deletion
133 | var parts = dotSplit(k),
134 | p = out,
135 | l = parts.pop(),
136 | nl = l.replace(/\\\./g, '.');
137 | parts.forEach(function (part, _, __) {
138 | if (!p[part] || typeof p[part] !== "object") {
139 | p[part] = {};
140 | }
141 | p = p[part];
142 | });
143 | if (p === out && nl === l) {
144 | return false;
145 | }
146 | p[nl] = out[k];
147 | return true;
148 | }).forEach(function (del, _, __) {
149 | delete out[del];
150 | });
151 |
152 | return out;
153 | }
154 |
155 | function isQuoted (val) {
156 | return (val.charAt(0) === "\"" && val.slice(-1) === "\"")
157 | || (val.charAt(0) === "'" && val.slice(-1) === "'");
158 | }
159 |
160 | function safe (val) {
161 | return (typeof val !== "string"
162 | || val.match(/[=\r\n]/)
163 | || val.match(/^\[/)
164 | || (val.length > 1
165 | && isQuoted(val))
166 | || val !== val.trim())
167 | ? JSON.stringify(val)
168 | : val.replace(/;/g, '\\;').replace(/#/g, "\\#");
169 | }
170 |
171 | function unsafe (val, doUnesc) {
172 | val = (val || "").trim();
173 | if (isQuoted(val)) {
174 | // remove the single quotes before calling JSON.parse
175 | if (val.charAt(0) === "'") {
176 | val = val.substr(1, val.length - 2);
177 | }
178 | try {
179 | val = JSON.parse(val);
180 | } catch (_) {}
181 | } else {
182 | // walk the val to find the first not-escaped ; character
183 | var esc = false;
184 | var unesc = "";
185 | for (var i = 0, l = val.length; i < l; i++) {
186 | var c = val.charAt(i);
187 | if (esc) {
188 | if ("\\;#".indexOf(c) !== -1)
189 | unesc += c;
190 | else
191 | unesc += "\\" + c;
192 | esc = false;
193 | } else if (";#".indexOf(c) !== -1) {
194 | break;
195 | } else if (c === "\\") {
196 | esc = true;
197 | } else {
198 | unesc += c;
199 | }
200 | }
201 | if (esc)
202 | unesc += "\\";
203 | return unesc;
204 | }
205 | return val;
206 | }
207 |
208 | var isInt = function(n) {
209 | return parseInt(n) === n;
210 | };
--------------------------------------------------------------------------------
/source/plugins/README.md:
--------------------------------------------------------------------------------
1 | # Plugins
2 |
3 |
--------------------------------------------------------------------------------
/source/settings/botnames.txt:
--------------------------------------------------------------------------------
1 | 8
2 | 8ch
3 | argentina
4 | australia
5 | austria
6 | ayy lmao
7 | bait
8 | bangladesh
9 | belgium
10 | bosnia
11 | botswana
12 | brazil
13 | bulgaria
14 | byzantium
15 | cambodia
16 | canada
17 | chile
18 | china
19 | cia
20 | confederate
21 | Croatia
22 | cuba
23 | denmark
24 | doge
25 | ea
26 | earth
27 | estonia
28 | european union
29 | facebook
30 | facepunch
31 | feminism
32 | finland
33 | france
34 | french kingdom
35 | german empire
36 | germany
37 | greece
38 | hong kong
39 | hungary
40 | imperial japan
41 | india
42 | indiana
43 | indonesia
44 | iran
45 | iraq
46 | ireland
47 | irs
48 | italy
49 | jamaica
50 | japan
51 | kc
52 | latvia
53 | lithuania
54 | luxembourg
55 | maldivas
56 | mars
57 | matriarchy
58 | mexico
59 | moon
60 | nasa
61 | netherlands
62 | nigeria
63 | north korea
64 | norway
65 | origin
66 | pakistan
67 | patriarchy
68 | peru
69 | piccolo
70 | pokerface
71 | poland
72 | portugal
73 | prodota
74 | prussia
75 | qing dynasty
76 | quebec
77 | receita federal
78 | reddit
79 | romania
80 | russia
81 | sanik
82 | scotland
83 | sealand
84 | sir
85 | somalia
86 | south korea
87 | spain
88 | stalin
89 | steam
90 | stussy
91 | sweden
92 | switzerland
93 | taiwan
94 | texas
95 | thailand
96 | tsarist russia
97 | tumblr
98 | turkey
99 | ukraine
100 | united kingdom
101 | usa
102 | ussr
103 | vinesauce
104 | wojak
105 | yaranaika
--------------------------------------------------------------------------------
/source/settings/clientConfig.ini:
--------------------------------------------------------------------------------
1 | // Client Configs. Alters the client (play.ogarul.io)
2 |
3 | // [Macros]
4 | // 0 = off, 1 = on. (SMacro = SpaceMacro)
5 | clientSMacro = 0
6 | clientWMacro = 0
7 | clientQMacro = 0
8 | clientEMacro = 0
9 | clientRMacro = 0
10 |
11 | // [Configs]
12 | // 0 = disabled, 1 = disabled on default but changeable, 2 = enabled on default but changeable, 3 = always on
13 | clientDarkBG = 1
14 | clientChat = 2
15 | clientSkins = 2
16 | clientGrid = 1
17 | clientAcid = 1
18 | clientColors = 2
19 | clientNames = 2
20 | clientShowMass = 1
21 | clientSmooth = 1
22 |
23 | // [Others]
24 | // clientMaxName: Number of maximum charactors in the name box
25 | // Title: What to display at the header
26 | // Instructions: Text to show in the instructions area
27 | // defaultUsername: The default username
28 | // nickPlaceHolder: The placeholder for the nickname box
29 | // leavemessage: What to display when a player closes the tab
30 | clientMaxName = 15
31 | clientTitle = ""
32 | clientInstructions = ""
33 | clientNickPlaceholder = ""
34 | clientDefaultUsername = ""
35 | clientLeaveMessage = ""
--------------------------------------------------------------------------------
/source/settings/config.ini:
--------------------------------------------------------------------------------
1 | // OpenAgar server configs.
2 |
3 | gameMode = 0
4 | serverViewBaseX = 1380
5 | serverViewBaseY = 820
6 | boundX = 0
7 | boundY = 0
8 | boundWidth = 14000
9 | boundHeight = 14000
10 | serverBots = 0
11 | leaderBoardLen = 10
12 | disconnectTime = 30
13 | botMaxSplit = 4
14 |
--------------------------------------------------------------------------------
/source/settings/customSkins.ini:
--------------------------------------------------------------------------------
1 | andrews54757 = "https://avatars1.githubusercontent.com/u/13282284?v=3&s=460"
2 | legitsoulja = "https://avatars2.githubusercontent.com/u/4976824?v=3&s=400"
3 |
--------------------------------------------------------------------------------
/source/settings/physicsConfig.ini:
--------------------------------------------------------------------------------
1 | // OpenAgar server configs.
2 |
3 | startMass = 20
4 | playerMaxMass = 25000
5 | minFood = 900
6 | maxFood = 1400
7 | playerSpeed = 40
8 | playerMinMass = 10
9 | splitSpeed = 100
10 | splitDecay = 10
11 | playerMaxCells = 16
12 | ejectedMass = 10
13 | ejectedSpeed = 100
14 | ejectedDecay = 5
15 | ejectMassCooldown = 100
16 | ejectMassMin = 25
17 | bulletSpeed = 20
18 | bulletDecay = 30
19 | bulletReload = 25
20 | bulletReloadMin = 1000
21 | playerMergeMult = 0.06
22 | playerMerge = 10
23 | maxVirusMass = 1000
24 | virusMass = 100
25 | virusFeedMin = 5
26 | maxVirus = 130
27 | minVirus = 90
28 | virusSpeed = 50
29 | virusDecay = 12
30 | splitMin = 32
31 | minWormHole = 0
32 | decayRate = .03
33 | decayRateMax = 10
34 | decayMax = 25000
35 |
36 |
--------------------------------------------------------------------------------
/source/settings/pluginConfig.ini:
--------------------------------------------------------------------------------
1 | // allowed: A comma separated list of plugins to allow if they dont pass the security test
2 | // dev: If 1, uncompiled (folder) plugins are allowed and errors will be thrown
3 |
4 | allowed=""
5 | dev = 0
6 |
--------------------------------------------------------------------------------
/source/settings/pluginConfig/README.md:
--------------------------------------------------------------------------------
1 | This is where all the plugin configs go
2 |
--------------------------------------------------------------------------------
/source/settings/serverConfig.ini:
--------------------------------------------------------------------------------
1 | // OpenAgar server config file.
2 |
3 | // serverPort: Port in which to run the server
4 | // socketProtection: Sets if sockets are secure or not. Protects server against bots.
5 | // SSL: Secure sockets - Please see the readme
6 |
7 | serverPort = 8080
8 | socketProtection = true
9 | ssl = false
10 |
11 | // Statistics configurations
12 | // serverName: Name of server to display
13 | // url: The url to access the server. Your server then can be accessed by going to http://opnagar.us/server/yoururl
14 | // logo: Url of logo to display on list
15 |
16 | serverName = ""
17 | url = ""
18 | logo = "http://opnagar.us/woa.png"
19 |
20 |
21 |
--------------------------------------------------------------------------------
/source/settings/servers/README.md:
--------------------------------------------------------------------------------
1 | ## Multi-Servers configuration
2 | Using this folder, you can automatically have OpenAgar create additional servers for you. That way, you dont have to use the servers command every time you restart. Also, this allows you to easily change the configurations of the individual servers.
3 |
4 | ## Usage:
5 |
6 | 1. Create a file in this directory, the file should be `[Server name].ini`
7 | 2. Then, you can override configs in that file. For example, I can put the line `gameMode = 2` to have the server be in teams
8 | 3. Start the server. Your server will automatically be created.
9 |
--------------------------------------------------------------------------------
/source/sounds/README.md:
--------------------------------------------------------------------------------
1 | ## The place where all the sounds go
2 |
3 | ### Credits:
4 | Since I dont have time to create sound effects. I got these sound effects from websites. Currently used website: http://soundbible.com. When I have time, I will make them myself
5 |
6 |
7 | ### NOTE:
8 | Although plugins can play sounds from this directory, plugins are unable to add sounds as a security feature, since they run in a separate process.
9 |
--------------------------------------------------------------------------------
/source/sounds/alert.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AJS-development/OpenAgar/90fefe007da2c9ebd8221b9f75cac4afdf4ad9cd/source/sounds/alert.mp3
--------------------------------------------------------------------------------
/source/sounds/start.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AJS-development/OpenAgar/90fefe007da2c9ebd8221b9f75cac4afdf4ad9cd/source/sounds/start.mp3
--------------------------------------------------------------------------------
/source/sounds/tone.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AJS-development/OpenAgar/90fefe007da2c9ebd8221b9f75cac4afdf4ad9cd/source/sounds/tone.mp3
--------------------------------------------------------------------------------
/start.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | node index.js
3 | pause
4 |
--------------------------------------------------------------------------------