Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**********************************************************************************************
- * Serverinfo 1.10, by p3tsin
- *
- ***********************************************************************************************
- *
- * Description:
- * Get status of defined servers (server name, current map, players/maxplayers, etc)
- *
- *
- * Settings:
- * Place serverlist.ini in amxmodx/data directory and add the addresses you want.
- * (Note MAX_SERVERS definition!)
- *
- *
- * Cvars & Commands:
- * srv_format response format for queries
- * srv_format2 response format when couldn't get server status
- *
- * say /servers prints the status of servers defined in serverlist.ini
- *
- *
- * Response format variables:
- * $type HL1 / HL2
- * $ip ip address
- * $host hostname
- * $map current map
- * $mod modname (e.g. Counter-Strike)
- * $players players/maxplayers
- * $pw password protected? (Yes/No)
- *
- * $timeleft time remaining on current map
- * $nextmap next map
- *
- * Changelog:
- * 1.00 - Initial release
- * 1.01 - Fixed maxplayers showing as 0 when there are no players
- * 1.10 - Added $timeleft and $nextmap
- * - Improved speed
- *
- *
- * Thanks to:
- * Kraugh for helping me with the byte values in the response
- *
- ***********************************************************************************************/
- #include <amxmodx>
- #include <sockets>
- #define MAX_SERVERS 5 //max. number of servers the plugin can handle
- #define DELAY_SHOW 0.5 //delay before showing the results
- #define COOLDOWN 3.0 //antiflood for /servers
- #define TASK_RECV 321897 //task id for receive_info()
- new bool:plugin_enabled
- new bool:allow_query
- new sockets[MAX_SERVERS]
- new server_address[MAX_SERVERS][32]
- new server_port[MAX_SERVERS]
- new servernum
- new response[MAX_SERVERS][192]
- new rules[MAX_SERVERS][2][32] //0: timeleft, 1: nextmap
- new rulesgot[MAX_SERVERS]
- new totalpackets[MAX_SERVERS]
- new part[MAX_SERVERS]
- public plugin_init() {
- register_plugin("Serverinfo", "1.10", "p3tsin")
- register_clcmd("say /servers", "cmd_servers")
- register_cvar("srv_format", "* $host .:. $map $players (Timeleft: $timeleft) .:. $ip")
- register_cvar("srv_format2","* No response .:. $ip")
- }
- public plugin_cfg() {
- new filename[256], datadir[192]
- get_localinfo("amxx_datadir", datadir,191)
- format(filename,255, "%s/serverlist.ini", datadir)
- if(file_exists(filename)) {
- new line, data[64], txt, address[64]
- while(read_file(filename,line++,data,63,txt) > 0) {
- if(data[0] == ';' || !txt) continue
- else if(servernum == MAX_SERVERS) break
- strbreak(data, address,63, data,63)
- strtok(address, server_address[servernum],31, data,63, ':',1)
- server_port[servernum] = str_to_num(data)
- servernum++
- }
- if(servernum > 0) {
- plugin_enabled = true
- allow_query = true
- }
- else plugin_enabled = false
- }
- else {
- log_amx("%s not found!", filename)
- plugin_enabled = false
- }
- }
- public client_putinserver(id) {
- if(plugin_enabled) set_task(15.0, "advert",id)
- }
- public advert(id) {
- client_print(id,print_chat, "Say /servers to get status of other servers")
- return PLUGIN_HANDLED
- }
- public cmd_servers(id) {
- if(plugin_enabled) {
- if(!allow_query) {
- client_print(id,print_chat, "Someone just used this function, please wait a while..")
- return PLUGIN_HANDLED
- }
- else if(connect_servers()) {
- allow_query = false
- send_info_request()
- set_task(COOLDOWN, "antiflood_off")
- set_task(DELAY_SHOW, "show_results")
- }
- else client_print(0,print_chat, "Couldn't connect to server(s)")
- return PLUGIN_CONTINUE
- }
- else client_print(id,print_chat, "No servers defined in serverlist")
- return PLUGIN_HANDLED
- }
- public antiflood_off() {
- allow_query = true
- return PLUGIN_HANDLED
- }
- public show_results() {
- remove_task(TASK_RECV)
- new message[192]
- for(new i = 0; i < servernum; i++) {
- if(!strlen(response[i])) {
- new address[32]
- get_cvar_string("srv_format2", message,191)
- format(address,31, "%s:%d", server_address[i], server_port[i])
- while(contain(message,"$ip") > -1) replace(message,191, "$ip", address)
- }
- else {
- copy(message,191, response[i])
- while(contain(message,"$timeleft") > -1) replace(message,191, "$timeleft", rules[i][0])
- while(contain(message,"$nextmap") > -1) replace(message,191, "$nextmap", rules[i][1])
- }
- client_print(0,print_chat, "%s",message)
- }
- disconnect_servers()
- return PLUGIN_HANDLED
- }
- connect_servers() {
- new error, err[40], srv, i
- for(i = 0; i < servernum; i++) {
- if(sockets[i] > 0) { //already connected
- srv++
- continue
- }
- sockets[i] = socket_open(server_address[i],server_port[i], SOCKET_UDP,error)
- if(sockets[i] <= 0 || error) {
- switch(error) {
- case 0: err = "no error"
- case 1: err = "error while creating socket"
- case 2: err = "couldn't resolve hostname"
- case 3: err = "couldn't connect to given hostname:port"
- }
- log_amx("Couldn't connect to %s:%d, error: %s",server_address[i],server_port[i],err)
- continue
- }
- srv++
- }
- return srv
- }
- disconnect_servers() {
- for(new i = 0; i < servernum; i++) {
- if(sockets[i] <= 0) continue
- socket_close(sockets[i])
- sockets[i] = 0
- }
- return
- }
- public send_info_request() {
- new cmd[32], i
- setc(cmd,4,0xFF)
- format(cmd[4],31,"TSource Engine Query")
- setc(cmd[24],1,0x00)
- for(i = 0; i < servernum; i++) {
- if(sockets[i] <= 0) continue
- socket_send(sockets[i], cmd,25)
- response[i][0] = 0
- }
- new form[256], bool:req_rules
- get_cvar_string("srv_format",form,255)
- if(contain(form,"$timeleft") > -1) req_rules = true
- else if(contain(form,"$nextmap") > -1) req_rules = true
- if(req_rules) {
- setc(cmd,4,0xFF)
- format(cmd[4],31,"W")
- setc(cmd[5],1,0x00)
- for(i = 0; i < servernum; i++) {
- if(sockets[i] <= 0) continue
- socket_send(sockets[i], cmd,6)
- rules[i][0] = "--:--", rules[i][1] = "-"
- part[i] = 0, totalpackets[i] = 0, rulesgot[i] = 0
- }
- }
- set_task(0.1, "receive_info", TASK_RECV, "",0, "b")
- return PLUGIN_HANDLED
- }
- public receive_info() {
- new recv[1450], len
- for(new i = 0; i < servernum; i++) {
- if(sockets[i] <= 0) continue
- else if(socket_change(sockets[i],1)) {
- len = socket_recv(sockets[i], recv,1449)
- parse_response(recv,i,len)
- }
- }
- return PLUGIN_HANDLED
- }
- parse_response(text[],id,len) {
- new end = strlen(text)+1
- new type = text[4], i
- switch(type) {
- case 'A': { //challenge
- new cmd[10]
- setc(cmd,4,0xFF)
- cmd[4] = 'V'
- for(i = 0; i < 4; i++) cmd[5+i] = text[5+i]
- socket_send(sockets[id], cmd,9)
- }
- case 'm', 'I': { //status: m = hl1, I = hl2
- new info[6][64]
- copy(info[0],63, text[5]) //data till the first null
- for(i = 1; i < 6; i++) { //last value is for password, no more needed
- copy(info[i],63, text[end])
- end += strlen(info[i])+1
- }
- if(!info[5][0]) { //no players on the server, info[5][0] == null
- info[5][1] = text[end]
- info[5][5] = text[end+4]
- }
- new message[192], players[10], game[10]
- get_cvar_string("srv_format", message,191)
- format(players,9, "%d/%d", info[5][0], info[5][1])
- format(game,9, "HL%d", type == 'm' ? 1 : 2)
- while(contain(message,"$type") > -1) replace(message,191, "$type", game)
- while(contain(message,"$ip") > -1) replace(message,191, "$ip", info[0])
- while(contain(message,"$host") > -1) replace(message,191, "$host", info[1])
- while(contain(message,"$map") > -1) replace(message,191, "$map", info[2])
- while(contain(message,"$mod") > -1) replace(message,191, "$mod", info[4])
- while(contain(message,"$players") > -1) replace(message,191, "$players", players)
- while(contain(message,"$pw") > -1) replace(message,191, "$pw", info[5][5] ? "Yes" : "No")
- copy(response[id],191, message)
- }
- default: { //rules
- if(rulesgot[id] == 2) return //already got both values, skip the packet
- else if(text[0] == -2) {
- if(!part[id]) totalpackets[id] = text[8]
- if(0 < part[id] < totalpackets[id]) end = 0
- else end = 16
- }
- else end = 7
- new name[64], rlen
- while(end < len) {
- rlen = copy(name,63, text[end])
- if(equal(name,"amx_timeleft")) {
- end += 13, rulesgot[id]++
- copy(rules[id][0],31, text[end])
- }
- else if(equal(name,"amx_nextmap")) {
- end += 12, rulesgot[id]++
- copy(rules[id][1],31, text[end])
- }
- else end += rlen+1 //skip cvar name
- end += strlen(text[end])+1 //skip cvar value
- if(rulesgot[id] == 2) break //got both values, ignore rest
- }
- part[id]++
- }
- }
- return
- }
Advertisement
Add Comment
Please, Sign In to add comment