[HELP] Duplicate Server Info
this plugin was approved, contains more errors, fix anyone know?
when copy 32/32 = crash
PHP Code:
/*
AMXX Plugin: DuplicateServerInfo
Author: Sylwester
Plugin information and updates available at:
http://forums.alliedmods.net/showthread.php?p=1326999
*/
#include <amxmodx>
#include <amxmisc>
#include <fakemeta>
#include <fun>
#include <sockets>
#define UPDATE_INTERVAL 1.0
#define TID_TIMER 3536
new pcvar_target
new pcvar_password
new pcvar_fake_map
new pcvar_query_interval
new g_socket = 0
new g_ch_ret[4] = {255,255,255,255}
new g_s_hostname[128]
new g_s_map[64]
new g_s_desc[64]
new g_s_max_players
new g_s_players
new g_s_bots
new g_s_player_name[33][33]
new g_s_player_kills[33]
new g_timer_entid
new Float:g_t_time
new g_max_players
new pcvar_hostname
new pcvar_visiblemaxplayers
new pcvar_dsi_hostname
new pcvar_dsi_gamedesc
new pcvar_dsi_map
new pcvar_dsi_players
new pcvar_dsi_nobots_str
new pcvar_dsi_bots_str
new pcvar_dsi_maxplayers
new g_map[64]
new g_base_hostname[128]
public plugin_init(){
register_plugin("DuplicateServerInfo", "1.44", "Sylwester")
g_max_players = get_maxplayers()
pcvar_target = register_cvar("dsi_target", "0.0.0.0:0")
pcvar_password = register_cvar("dsi_password", "")
pcvar_fake_map = register_cvar("dsi_fake_map", "dummy.bsp")
pcvar_query_interval = register_cvar("dsi_query_interval", "10")
pcvar_visiblemaxplayers = get_cvar_pointer("sv_visiblemaxplayers")
pcvar_dsi_hostname = register_cvar("dsi_hostname", "1")
pcvar_dsi_gamedesc = register_cvar("dsi_gamedesc", "1")
pcvar_dsi_map = register_cvar("dsi_map", "1")
pcvar_dsi_players = register_cvar("dsi_players", "1")
pcvar_dsi_maxplayers = register_cvar("dsi_maxplayers", "1")
pcvar_dsi_nobots_str = register_cvar("dsi_nobots_str", "")
pcvar_dsi_bots_str = register_cvar("dsi_bots_str", "")
pcvar_hostname = get_cvar_pointer("hostname")
get_mapname(g_map, 63)
register_forward(FM_GetGameDescription, "GameDescryption")
set_task(1.0, "start_dsi")
//create (if necessary) and execute cfg file storing name of dummy map
new cfgdir[256], fh
get_configsdir(cfgdir, 255)
format(cfgdir, 255, "%s%s", cfgdir, "/dsi_fake_map.cfg")
if(!file_exists(cfgdir)){
fh = fopen(cfgdir, "wt")
if(!fh){
log_amx("Error: Could not open file for writing (%s).", cfgdir)
return
}else{
fputs(fh, "dsi_fake_map dummy.bsp^n")
fclose(fh)
}
}
server_cmd("exec %s", cfgdir)
}
public start_dsi(){
set_cvar_num("sv_allowdownload", 0) //make sure it's impossible to download fake map
get_pcvar_string(pcvar_hostname, g_base_hostname, 127)
create_timer()
if(connect_server())
send_request()
}
public timer_cycle(){
static cycles
cycles++
check_socket()
if(cycles*UPDATE_INTERVAL >= get_pcvar_num(pcvar_query_interval)){
cycles = 0
disconnect_server()
if(!connect_server())
return
send_request()
}
}
public plugin_end(){
if(g_socket > 0){
socket_close(g_socket)
g_socket = 0
}
set_pcvar_string(pcvar_hostname, g_base_hostname)
}
public update_hostname(){
static hostname[128], tmp[32], dsi_hostname
dsi_hostname = get_pcvar_num(pcvar_dsi_hostname)
if(dsi_hostname==0){
copy(hostname, 127, g_base_hostname)
}else{
copy(hostname, 127, g_s_hostname)
}
if(g_s_bots <= 0){
get_pcvar_string(pcvar_dsi_nobots_str, tmp, 31)
}else{
get_pcvar_string(pcvar_dsi_bots_str, tmp, 31)
}
if(strlen(tmp)>1 && containi(hostname, tmp)==-1)
add(hostname, 127, tmp)
set_pcvar_string(pcvar_hostname, hostname)
}
public update_maxplayers(){
if(get_pcvar_num(pcvar_dsi_maxplayers)==0)
return
if(g_s_max_players < 1)
return
set_pcvar_num(pcvar_visiblemaxplayers, g_s_max_players)
}
public update_players(){
static players, p_list[32]
static p_list2[32], p_list2_cnt, userid, tmp[128]
static p_name[32], fc_id
if(get_pcvar_num(pcvar_dsi_players)==0){
g_s_players = 0
}
//now update fake clients - amount, names, frags
if(g_s_players > g_max_players)
g_s_players = g_max_players
players = 0
for(new i=1; i<=g_max_players; i++)
if(is_user_connected(i))
p_list[players++] = i
p_list2_cnt = g_s_players
for(new i=0; i<p_list2_cnt; i++)
p_list2[i]=i
//remove fakeclients with names that do not appear in info of target server
//update score of fakeclients
for(new i=0; i<players; i++){
new j
get_user_name(p_list[i], p_name, 31)
while(j<p_list2_cnt && !equal(p_name, g_s_player_name[p_list2[j]]))
j++
if(j==p_list2_cnt){
//name not found - kick
userid = get_user_userid(p_list[i])
server_cmd("kick #%d", userid)
}else{
//name found - update data
set_user_frags(p_list[i], g_s_player_kills[p_list2[j]])
p_list2[j] = p_list2[--p_list2_cnt]
}
}
//create fakeclients for remaining names
for(new i=0; i<p_list2_cnt; i++){
fc_id = engfunc(EngFunc_CreateFakeClient, g_s_player_name[p_list2[i]])
dllfunc(DLLFunc_ClientConnect, fc_id, g_s_player_name[p_list2[i]], "127.0.0.1", tmp)
dllfunc(DLLFunc_ClientPutInServer, fc_id)
if(0 < fc_id < 33)
set_user_frags(fc_id, g_s_player_kills[p_list2[i]])
}
}
public check_socket(){
if(g_socket <= 0)
return
new cnt
while(socket_change(g_socket, 1) && cnt < 10){
cnt++
receive_data()
}
}
public connect_server(){
static host[64], port, tmp[128], error, szError[64], tmp2[32]
get_pcvar_string(pcvar_target, tmp, 127)
strtok(tmp, host, 63, tmp2, 31, ':')
port = str_to_num(tmp2)
if(strlen(host) < 2 || port <=0 || port >= 65536){
log_amx("incorrect data stored in dsi_target cvar ( ^"%s^" ), must be ^"ip:port^" or ^"dns:port^"", tmp)
return false
}
if(g_socket > 0){
socket_close(g_socket)
g_socket = 0
}
g_socket = socket_open(host, port, SOCKET_UDP, error)
if(g_socket <= 0 || error){
switch(error){
case 0: szError = "unknown"
case 1: szError = "error while creating socket"
case 2: szError = "could not resolve hostname"
case 3: format(szError, 63, "could not connect to %s:%d", host, port)
}
log_amx("Socket error: %s", szError)
return false
}
return true
}
public disconnect_server(){
if(g_socket > 0){
socket_close(g_socket)
g_socket = 0
}
}
public client_connect(id){
static ip[32], pw[64]
get_pcvar_string(pcvar_password, pw, 63)
if(strlen(pw)>0){
client_cmd(id, "password %s", pw)
}
get_pcvar_string(pcvar_target, ip, 31)
client_cmd(id, "Connect %s", ip)
}
public create_timer(){
g_timer_entid = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString,"info_target"))
if(pev_valid(g_timer_entid)){
set_pev(g_timer_entid, pev_classname, "dsi_timer")
global_get(glb_time, g_t_time)
set_pev(g_timer_entid, pev_nextthink, g_t_time + UPDATE_INTERVAL)
register_forward(FM_Think,"fwd_Think")
}else{
log_amx("Warning: Failed to create timer entity, using task instead")
set_task(UPDATE_INTERVAL, "timer_cycle", TID_TIMER, "", 0, "b")
}
}
public GameDescryption(){
if(get_pcvar_num(pcvar_dsi_gamedesc)==0)
return FMRES_IGNORED
if(strlen(g_s_desc)<=1)
return FMRES_IGNORED
forward_return(FMV_STRING, g_s_desc)
return FMRES_SUPERCEDE
}
public update_map(){
if(get_pcvar_num(pcvar_dsi_map)==0)
return
if(!equal(g_map, g_s_map)){
if(!is_map_valid(g_s_map))
create_fake_map()
if(is_map_valid(g_s_map)){
server_cmd("changelevel ^"%s^"", g_s_map)
}else{
log_amx("Warning: Unable to change map to %s (map file is not valid or does not exist)", g_s_map)
}
}
}
public ret_ac(num){ //change byte -128..127 into 0..255
if(num<0)
return 256+num
return num
}
public send_request(){
if(g_socket <= 0)
return
new cache[32]
//http://developer.valvesoftware.com/wiki/Server_Queries#A2S_INFO
format(cache, 25, "%c%c%c%c%c%s%c", 255, 255, 255, 255, 84, "Source Engine Query", 0 )
socket_send2(g_socket, cache, 25)
//http://developer.valvesoftware.com/wiki/Server_Queries#A2S_PLAYER
format(cache, 25, "%c%c%c%c%c%c%c%c%c", 255, 255, 255, 255, 85, g_ch_ret[0], g_ch_ret[1], g_ch_ret[2], g_ch_ret[3]) //ping
socket_send2(g_socket, cache, 9)
}
public create_fake_map(){
new map[64], path_src[128], path_dest[128]
get_pcvar_string(pcvar_fake_map, map, 63)
format(path_src, 127, "maps/%s", map)
format(path_dest, 127, "maps/%s.bsp", g_s_map)
if(!file_exists(path_src)){
log_amx("Warning: unable to create fake map file, source file %s does not exist", path_src)
return
}
if(file_exists(path_dest)){
log_amx("Warning: unable to create fake map file, map file already exists %s (but is not valid map)", path_dest)
return
}
if(!rename_file(path_src, path_dest, 1)){
log_amx("Warning: unable to create fake map file, renaming failed (%s -> %s)", path_src, path_dest)
return
}
new cfgdir[256], cache[128], fh
get_configsdir(cfgdir, 255)
format(cfgdir, 255, "%s%s", cfgdir, "/dsi_fake_map.cfg")
fh = fopen(cfgdir, "wt")
if(!fh){
log_amx("Error: Could not open file for writing (%s).", cfgdir)
return
}else{
format(cache, 127, "dsi_fake_map %s.bsp^n", g_s_map)
fputs(fh, cache)
fclose(fh)
}
}
public fwd_Think(Ent){
if(Ent != g_timer_entid)
return FMRES_IGNORED
g_t_time += UPDATE_INTERVAL
set_pev(Ent, pev_nextthink, g_t_time)
timer_cycle()
return FMRES_IGNORED
}
public receive_data(){
static cache[2048], len
len = socket_recv(g_socket, cache, 2047)
if(len < 5)
return
if(!equal( cache, { -1, -1, -1, -1 }, 4 ) )
return
if(cache[4] == 'D'){ //(players details) A2S_PLAYER reply if sent challange number is correct
g_s_players = cache[5]
new j=6
for(new i=0; i<g_s_players; i++){
j++
j += copyc(g_s_player_name[i], 31, cache[j], 0)+1
g_s_player_kills[i] = ret_ac(cache[j+3])<<24|ret_ac(cache[j+2])<<16|ret_ac(cache[j+1])<<8|ret_ac(cache[j])
j+=8
}
update_players()
}
//(correct challange number) A2S_PLAYER reply if sent challange number is unknown/incorrect
if(cache[4] == 'A'){
g_ch_ret[0] = cache[5]
g_ch_ret[1] = cache[6]
g_ch_ret[2] = cache[7]
g_ch_ret[3] = cache[8]
new tmp[16]
format(tmp, 15, "%c%c%c%c%c%c%c%c%c", 255, 255, 255, 255, 85, g_ch_ret[0], g_ch_ret[1], g_ch_ret[2], g_ch_ret[3]) //ping
socket_send2(g_socket, cache, 9)
}
if(cache[4] == 'I'){ //(server details) A2S_INFO reply
new i = 6, dir[64]
i += copyc(g_s_hostname, 127, cache[i], 0)+1
i += copyc(g_s_map, 63, cache[i], 0)+1
i += copyc(dir, 63, cache[i], 0)+1
i += copyc(g_s_desc, 63, cache[i], 0)+1
g_s_max_players = cache[i+3]
g_s_bots = cache[i+4]
new pw[63]
get_pcvar_string(pcvar_password, pw, 63)
if(cache[i+7] && strlen(pw)<=0){
log_amx("Warning: target server is password protected, set dsi_password to allow redirected players to join target server")
}
update_map()
update_hostname()
update_maxplayers()
}
}
|