-
-
Notifications
You must be signed in to change notification settings - Fork 139
Full documentation
This document is for developpers / integrator for the eBot tools. If you are a common user, just don't read it, it will confuse yourself ! :)
To understand how eBot works, you need to understand the scheme. eBot has 2 distingued parts:
- The PHP daemon + NodeJS server
- The web pannel
eBot can works without the web pannel, this is just to control eBot and see the results / stats. You can develop one on your own !
To understand how the eBot works, you need to know how the bot grab the datas. CS:GO have a log stream in UDP that we read. With a simple rcon commands, the bot add his own server address/port that it listen and the server begin to send the data.
Major common issue is a firewall who is blocking the UDP stream between the server and eBot, if you don't have any output on the eBot daemon, it's that kind of issue.
The eBot daemon works like this:
- Each 3 seconds, it check in the database for new matchs
- Each loop time, it read from the UDP Socket
- Each loop time, the TaskManager is executed to process all tasks
eBot has a control interface trought the UDP server. Here is the list of the commands available:
- stop
- stopNoRs
- executeCommand
- passknife
- forceknife
- forceknifeend
- forcestart
- stopback
- pauseunpause
- fixsides
- streamerready
- goBackRounds
- skipmap
We will see later how to communicate and send this kind of command
The NodeJS server is just a forwarder, it forward some messages to all connected users. It's the bot who send the datas.
The server can send too some commands to the eBot server, it's not required, you can make it on your own. The NodeJS server is required for the auto demos upload, when a match end, the demos it pushed to the server, who archive and rename the file into the right dir.
Since Socket.io update, we dropped native WebSocket support for better performance. We won't have no more issue with strange disconnection or something like that
A match entry describe a whole match. Rules, overtime, knife round, max round, ... Matchs are linked with the maps table. When you insert a match, you need to insert a maps. A match without a map won't work.
eBot poll each 3 seconds for new match to engage on the database. eBot engage only at one time a match on a server IP. If 2 matchs are launched on the same server, eBot will start one, and when the second finish, it will start the second.
There is a "status" and a "flag" to describe a match status, the 2 columns are named status and enable. The status column is a number who describe a match status, those match status are linked with maps too. The enabled flag is just 1 or 0. If set to 1, eBot will "read" it to engage the match.
Here is the status list:
- 0: not started (match won't be engage if enabled set to 1)
- 1: starting (the status to engage a match, maps & co)
- 2: warmup knife round
- 3: knife round
- 4: end of the knife round (the winner team have to write !stay / !switch)
- 5: warmup 1st side
- 6: first side
- 7: warmup 2nd side
- 8: second side
- 9: warmup overtime
- 10: first side OT
- 11: warmup 2nd side OT
- 12: second side OT
- 13: finished
- 14: archived
If you followed the whole, when you create a match with a SQL query, if you want to start the match, you just need to put enabled and status to 1!
When you start a match, you need to put a server for it. There is 2 fields for it. The first is server_ip and the second ip. Server IP is just the address (a string), ip is the server id in the table servers.
Here is the rest of the column in the matchs table:
- team_a: it's the team id in the table teams
- team_a_name: if you don't have a team, you can put his name without create a team entity
- team_a_flag: same as before but the ISO code of the country
- team_b: it's the team id in the table teams
- team_b_name: if you don't have a team, you can put his name without create a team entity
- team_b_flag: same as before but the ISO code of the country
- is_paused: it's a flag to show if the game is paused or not (only works with !pause command)
- score_a: calculated score from map entry
- score_b: calculated score from map entry
- max_round: the "Max Round" (exemple: 15 or MR15 (or 30 rounds))
- rules: the config files to be use at the match start
- overtime_startmoney: startmoney for overtime (10000 - 16000)
- overtime_max_round: as max_round, but for overtime
- config_full_score: all round will be play, not when a team "win" the game at 16-x (0 or 1)
- config_ot: enable/disable overtime (0 or 1)
- config_streamer: this config enable "streamer ready mode", this disable the !ready ingame for players and when you send a message to eBot to tell that streamer are ready, players can trigger !ready !
- config_knife_round: enable/disable knife round (0 or 1)
- config_switch_auto: not used for now
- config_auto_change_password: enable/disable auto password change at match start (0 or 1)
- config_password: if config_auto_change_password enabled, this is the password who will take
- config_heatmap: this config is updated by eBot, and tell if the heatmap is available for the match
- config_authkey: a generated key that you need to fill to communicate with eBot backend. We use a uniqid in php with a timestamp
- map_selection_mode: for now, normal, we will update soon to allow BO3
- ingame_enable: flag used by eBot to display if the match is "enabled" ingame, when players say !stop, the flag is set to 0
- current_map: the current map on the match who is engage
- identifier_id: an external ID that you can put to describe the match for your system
- startdate: start date flag
- auto_start: if set to 1, it will be enable the auto start
- auto_start_time: autostart date
- created_at: symfony column to tell when the match is created
- updated_at: symfony column to tell when the match is updated
This describe a match entry, but it won't works if you don't link a map ! The maps table is quite simple.
- match_id: the match id in the table matchs
- map_name: the map name, have to be without .bsp !
- score_1: calculated from maps_score
- score_2: calculated from maps_score
- current_side: the current side for team A (ct/t)
- status: maps have their own status, it's the same than the match, but you just to put it to 0.
- maps_for: flag to tell to which team is the map (not used for now)
- nb_ot: number of overtime done
- identifier_id: map identifier id for your data
- tv_record_file: the TV record file name
- created_at: symfony column to tell when the match is created
- updated_at: symfony column to tell when the match is updated
After inserting a map, you will need to update matchs table (the record current_map)
Here is a sample insert query:
```sql
INSERT INTO matchs
(`ip`,`server_id`,`team_a_flag`,`team_a_name`,`team_b_flag`,`team_b_name`,`status`,`score_a`,`score_b`,`max_round`,`rules`,`overtime_startmoney`,`overtime_max_round`,`config_full_score`,`config_ot`,`config_streamer`,`config_knife_round`,`enable`,`map_selection_mode`,`created_at`,`updated_at)
VALUES
('192.168.1.1:27015', 1, 'FR', 'Team A', 'FR', 'Team B', 0, 0, 0, 15, 'rules_csgo', 10000, 3, 0, 1, 0, 1, 0, 'normal', NOW(), NOW());
INSERT INTO maps
(match_id
,map_name
,score_1
,score_2
,current_side
,status
,created_at
,updated_at
)
VALUES
(1, "de_dust2_se", 0, 0, 'ct', 0, NOW(), NOW());
```
Teams is used to link stats between all matchs. It's not fully used for now, but it will in the future ! I let you check the database.
Seasons is a system to regroup the matchs into a "season". Season is usefull when you have more than one tournament to seperate the stats.
Adverts is used ingame during the warmup. You can put many message that you want. You can assign an advert to a season.
To interact with eBot, we have developped an encrypted system to send secured message to eBot. As eBot is listenning a public server IP/PORT, anybody can send an UDP packet to the server. To secure the whole, we use AES encryption with an unique key per match.
It's simple, each match have his own cryptkey, and to detect the match_id / encrypted message, we use a JSON string. You will need to send a string like this:
The cryptkey field on the database is "config_authkey"
["COMMAND ENCRYPTED", "#MATCH_ID"]
The order is very important, as for now we don't use an associative array for the data. It's an upgrade that we will do in the future
For now, when you send a command from the eBot-WEB, the command is sent via the NodeJS server who forward it to the eBot server.
You can too send this kind of packet to the eBot server directly instead of sending the message to the NodeJS server.
As we are PHP Developper, we will put some example soon online :)
When you encrypt your message, you have to follow a format. We plan to change this format soon.
-
stopNoRs: Stop the match without restart round
- Structure: #matchid stopNoRs #serverip
- Sample: 1 stopNoRs 192.168.1.1:27015
-
stop: Stop the match with a restart round
- Structure: #matchid stop #serverip
- Sample: 1 stop 192.168.1.1:27015
-
executeCommand: Send an rcon command to the game server, reply will follow on the NodeJS server on the rcon channels
- Structure: #matchid executeCommand #serverip #command
- Sample: 1 executeCommand 192.168.1.1:27015 mp_restartgame 1
-
passknife: Pass the knife round (if in warmup knife)
- Structure: #matchid passknife #serverip
- Sample: 1 passknife 192.168.1.1:27015
-
forceknife: Force the start of the knife round
- Structure: #matchid forceknife #serverip
- Sample: 1 forceknie 192.168.1.1:27015
-
forceknifeend: End the knife round and go on the warmup
- Structure: #matchid forceknifeend #serverip
- Sample: 1 forceknifeend 192.168.1.1:27015
-
forcestart: For the start of a match (if in warmup)
- Structure: #matchid forcestart #serverip
- Sample: 1 forcestart 192.168.1.1:27015
-
stopBack: Stop the match
- Structure: #matchid stopBack #serverip
- Sample: 1 stopBack 192.168.1.1:27015
-
pauseunpause: If match is paused, it will unpause, if match is unpaused, it will pause
- Structure: #matchid pauseunpause #serverip
- Sample: sample: 1 pauseunpause 192.168.1.1:27015
-
fixsides: Force to send the team names on the server
- Structure: #matchid fixsides #serverip
- Sample: 1 fixsides 192.168.1.1:27015
-
streamerready: If the config stream ready is set, it will send a message to set that streamer are ready
- Structure: #matchid streamready #serverip
- Sample: 1 streamerready 192.168.1.1:27015
-
goBackRounds: Load a backup round, be carrefull when using this func !
- Structure: #matchid goBackRounds #serverip #roundId
- Sample: 1 goBackRounds 192.168.1.1:27015 5
On the eBot-WEB platform, we integrated an encryption class for JavaScript.
Here is a sample code:
javascript function encryptCommand(matchId, eventData, serverIp, authkey) { var data = matchId + " " + eventData + " " + serverIp; data = Aes.Ctr.encrypt(data, authkey, 256); var content = JSON.stringify([data, serverIp]); return content; }
If the socket.io is declared, you just need to make this to send the packet:
javascript socket.emit("matchCommandSend", encryptedData);
To send a command via PHP, it's the same than JS but with other class.
For the class, you should use this: https://github.com/deStrO/eBot-CSGO/blob/master/src/eTools/Utils/Encryption.php
Here is a code sample: ```php <?php function encryptCommand($matchId, $eventData, $serverIp, $authkey) { $data = $matchId . " " . $eventData . " " . $serverIp; $data = Encryption::encrypt($data, $authkey, 256); $content = json_encode(array($data, $serverIp)); return content; }
function sendCommandToeBot($message) {
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
socket_sendto($socket, $message, strlen($message), 0, "192.168.1.1", 12340);
}
?>
```
eBot use a node js server with socket.io to broadcast live events and some control "panel". You have to subscribe to the "namespace" and the match that you want to follow.
```js
$.getScript("http://"+socketIoAddress+"/socket.io/socket.io.js", function(){ socket = io.connect("http://"+socketIoAddress); socket.on('connect', function(){ socket.emit("identify", { type: "matchs" }); socket.on("matchsHandler", function (data) { var data = jQuery.parseJSON(data); // your code here }); }); }); ```
There is multiple interface and handler. Just read the code of eBot-Web ! :)