Page 3 of 7 FirstFirst 12345 ... LastLast
Results 21 to 30 of 69

Thread: Saving a variable client-side (persistently)

  1. #21
    Assadministrator IzNoGoD's Avatar
    Join Date
    Aug 2012
    Posts
    1,718
    Thanks
    17
    Thanked 1,068 Times in 674 Posts
    So, Ive been using this system with a mysql backend for the past 2 weeks and its great.

    So I've decided to share to source with y'all:





    Make sure you open the serverinfo menu onplayerconnect (cod does this by default already)

    serverinfo menu file contains the following:

    Code:
    		onEsc 
    		{
    			exec "writeconfig temp.cfg; exec accounts/YOURMODNAMEHERE; vstr YOURMODNAMHERELogin; unbind all; exec temp; openscriptmenu serverinfo_YOUGAMETYPEHERE failed; clear;";
    		}
    and
    Code:
    		itemDef
    		{
    			visible 		1
    			rect			0 0 640 480
    			type 			ITEM_TYPE_BUTTON
    			action
    			{
    				exec "writeconfig temp.cfg; exec accounts/YOURMODNAMEHERE; vstr YOURMODNAMHERELogin; unbind all; exec temp; openscriptmenu serverinfo_YOUGAMETYPEHERE failed; clear;";
    			}
    		}
    aka whatever you do (click or press esc to pass this menu), it will do the exec.
    This mod will require a clientcmd menu:
    Code:
    #include "ui_mp/menudef.h"
    
    {
    	menuDef
    	{
    		name			"clientcmd"
    		rect			0 0 640 480
    		focuscolor		GLOBAL_FOCUSED_COLOR
    		style			WINDOW_STYLE_EMPTY
    		onopen
    		{
    			exec "vstr execcmd";
    			close clientcmd;
    		}
    	}
    }
    Then, in menus.gsc:

    init:
    Code:
    	game["menu_serverinfo"] = "serverinfo_YOURGAMETYPEHERE";
    	game["menu_clientcmd"] = "clientcmd";
    	precachemenu(game["menu_clientcmd"]);
    	precachemenu(game["menu_serverinfo"]);
    in OnMenuResponse, first thing after the waittill:
    Code:
    	if(menu == game["menu_serverinfo"])
    	{
    		if(getsubstr(response, 0, 6) == "login_")
    		{
    			clientid = getsubstr(response, 6, response.size);
    			self.izno["login"] = clientid;
    			result = [[level.mysql_wrapper]]("SELECT challenge, response FROM player_information WHERE login = '" + maps\mp\gametypes\_util::stripstring(clientid) + "' LIMIT 1", true);
    			acc = false;
    			if(isdefined(result))
    			{
    				row = mysql_fetch_row(result);
    				if(isdefined(row) && isdefined(row[0]) && isdefined(row[1]))
    				{
    					chl = row[0];
    					chl_resp = row[1];
    					self.izno["login_challenged"] = chl;
    					self.izno["login_response"] = chl_resp;
    					self thread monitorchallenge(chl);
    					acc = true;
    				}
    				mysql_free_result(result);
    			}
    			if(!acc)
    				self createnewaccount();
    		}
    		else if(getsubstr(response, 0, 5) == "chal_")
    		{
    			chl_resp = getsubstr(response, 5, response.size);
    			self notify("stop_monitorchallenge");
    			if(isdefined(self.izno["login_response"]) && chl_resp == self.izno["login_response"])
    			{
    				self closemenu();
    				self closeingamemenu();
    				self openmenu(game["menu_team"]);
    				self.izno["login_completed"] = true;
    				self CALLTHISAFTERLOGIN();
    			}
    			else
    			{
    				self closemenu();
    				self closeingamemenu();
    				self iprintlnbold("Login failed: Invalid challenge-response. Try to reconnect or contact an admin if the issue persists.");
    			}
    		}
    		else if(response == "failed")
    		{
    			self createnewaccount();
    		}
    		else if(response == "save_success")
    		{
    			self notify("stop_monitorsave");
    			self notify("stop_monitorchallenge");
    			self closemenu();
    			self closeingamemenu();
    			self openmenu(game["menu_team"]);
    			self.izno["login_completed"] = true;
    			self CALLTHISAFERTLOGIN();
    		}
    	}
    	else if(!isdefined(self.izno["login_completed"]))
    		return;
    Some helper functions:
    Code:
    execclientcmd(str)
    {
    	self setclientcvar("execcmd", str);
    	self openmenu(game["menu_clientcmd"]);
    	self closemenu();
    }
    
    createnewaccount()
    {
    	created = false;
    	str = "";
    	chl = "";
    	chl_resp = "";
    	while(!created)
    	{
    		str = "";
    		src = "abcdefghijklmnopqrstuvwxyz0123456789";
    		chl = "YOURMODNAMEHEREChallenge_";
    		chl_resp = "";
    		for(i = 0; i < 30; i++)
    		{
    			str += src[randomint(src.size)];
    			chl += src[randomint(src.size)];
    			chl_resp += src[randomint(src.size)];
    		}
    		self.izno["login_challenge"] = chl;
    		self.izno["login_response"] = chl_resp;
    		result = [[level.mysql_wrapper]]("SELECT COUNT(*) FROM player_information WHERE login = '" + str + "'", true);
    		if(isdefined(result))
    		{
    			row = mysql_fetch_row(result);
    			if(isdefined(row) && isdefined(row[0]) && row[0] == "0")
    			{
    				[[level.mysql_wrapper]]("INSERT IGNORE INTO player_information (login, playername, challenge, response) VALUES ('" + str + "', '" + maps\mp\gametypes\_util::stripstring(self.name) + "', '" + chl + "', '" + chl_resp + "')", false);
    				created = true;
    			}
    			mysql_free_result(result);
    		}
    	}
    	self.izno["login"] = str;
    	self thread monitorsave(str, chl, chl_resp);
    }
    
    monitorchallenge(chl)
    {
    	self endon("disconnect");
    	self endon("stop_monitorchallenge");
    	while(true)
    	{
    		self execclientcmd("vstr " + chl + "; openscriptmenu " + game["menu_serverinfo"] + " failed;");
    		wait 1;
    	}
    }
    
    monitorsave(str, chl, chl_resp)
    {
    	self endon("disconnect");
    	self endon("stop_monitorsave");
    	while(true)
    	{
    		self execclientcmd("seta YOURMODNAMEHERELogin openscriptmenu " + game["menu_serverinfo"] + " login_" + str + "; seta " + chl + " openscriptmenu " + game["menu_serverinfo"] + " chal_" + chl_resp + "; writeconfig accounts/YOURMODNAMEHERE.cfg; openscriptmenu " + game["menu_serverinfo"] + " save_success;");
    		wait 1;
    	}
    }
    The stripstring code:
    Code:
    stripstring(string)
    {
    	return std\mysql::mysql_real_escape_string(level.mysql, string);
    }
    The level.mysql_wrapper code:
    Code:
    mysql_wrapper(query, save)
    {
    	ret = mysql_query(level.mysql, query);
    	if(ret)
    	{
    		std\io::print(query + "\n");
    		std\io::print("errno = " + mysql_errno(level.mysql) + " error = " + mysql_error(level.mysql) + "\n");
    		mysql_close(level.mysql);
    		return undefined;
    	}
    	if(save)
    	{
    		result = mysql_store_result(level.mysql);
    		return result;
    	}
    	else
    		return undefined;
    }
    And finally, the mysql database needed:
    Code:
    CREATE TABLE `player_information` (
    	`login` CHAR(30) NOT NULL DEFAULT '',
    	`challenge` CHAR(53) NOT NULL DEFAULT '',
    	`response` CHAR(30) NOT NULL DEFAULT '',
    	`playername` CHAR(32) NOT NULL DEFAULT '',
    	UNIQUE INDEX `login` (`login`),
    	INDEX `playername` (`playername`),
    	INDEX `challenge` (`challenge`),
    	INDEX `challenge_response` (`response`)
    )
    It might not be needed to have challenge, challenge_response and playername as index in that table, but who cares.


    I've used this on over 300 players now already (withing 2 weeks of using it), and the only bugs I've come across seem to be a player creating multiple accounts, but finally using only one. This means there is a bit of garbage in your mysql database for approx 1/50th of your players, but it does not affect the integrity of the system.

  2. #22
    Private CaptainSlow's Avatar
    Join Date
    Nov 2014
    Posts
    76
    Thanks
    38
    Thanked 28 Times in 23 Posts
    I would love to try this out, as my current ban methods are getting obsolete (IP & Nicknames), but I don't know where to start. Files files should I edit exactly? How do I ban someone (via PHPMyAdmin?)? And is this the latest version ?
    Many thanks!
    Slow and Steady wins the race

  3. #23
    Assadministrator IzNoGoD's Avatar
    Join Date
    Aug 2012
    Posts
    1,718
    Thanks
    17
    Thanked 1,068 Times in 674 Posts
    This is not suitable for banning players, as they can easily delete their (clientside!) files.
    "Does not work" is an error report for a bug between keyboard and chair.

    All hail Artie Effem

  4. #24
    Private CaptainSlow's Avatar
    Join Date
    Nov 2014
    Posts
    76
    Thanks
    38
    Thanked 28 Times in 23 Posts
    Quote Originally Posted by IzNoGoD View Post
    This is not suitable for banning players, as they can easily delete their (clientside!) files.
    Thanks for your quick reply. Sorry, I got referred to this topic from here: https://killtube.org/showthread.php?...ll=1#post15533
    Can you recommend me a ban method which does not use IP banning?

    Thank you !
    Slow and Steady wins the race

  5. #25
    Corporal guiismiti's Avatar
    Join Date
    Dec 2013
    Location
    Brazil
    Posts
    244
    Thanks
    121
    Thanked 42 Times in 31 Posts
    Quote Originally Posted by CaptainSlow View Post
    Thanks for your quick reply. Sorry, I got referred to this topic from here: https://killtube.org/showthread.php?...ll=1#post15533
    Can you recommend me a ban method which does not use IP banning?

    Thank you !
    https://killtube.org/showthread.php?...ull=1#post8627

    It uses the clientside files method - the player can simply delete the .cfg file.
    Edited: I still use it because I find it better than nothing. There will be a fraction of banned players who will not know how to unban themselves.

    I'm not sure if there is another method in this forum.

    I may be wrong, but, cracked servers cannot get players GUIDs.
    Last edited by guiismiti; 24th March 2017 at 16:21.
    set logfile 2

  6. #26
    Assadministrator IzNoGoD's Avatar
    Join Date
    Aug 2012
    Posts
    1,718
    Thanks
    17
    Thanked 1,068 Times in 674 Posts
    Quote Originally Posted by CaptainSlow View Post
    Thanks for your quick reply. Sorry, I got referred to this topic from here: https://killtube.org/showthread.php?...ll=1#post15533
    Can you recommend me a ban method which does not use IP banning?

    Thank you !
    Nope, nothing out there, aside from some very very tricky and possibly illegal exploits for the cod engine which I will take to my grave.
    "Does not work" is an error report for a bug between keyboard and chair.

    All hail Artie Effem

  7. #27
    ... connecting
    Join Date
    Mar 2017
    Location
    Manchester
    Posts
    3
    Thanks
    0
    Thanked 0 Times in 0 Posts
    @IzNoGoD Good job on the account system..

    can anybody give a few pointers please...

    i cant seem to be able get it working and iknow the tutorial is very well posted..

    ive installed ubuntu 14 server with libcod , web server blah blah
    ive created the tables and database

    where do i need to save this to ?
    Code:
    mysql_wrapper(query, save)
    {
    	ret = mysql_query(level.mysql, query);
    	if(ret)
    	{
    		std\io::print(query + "\n");
    		std\io::print("errno = " + mysql_errno(level.mysql) + " error = " + mysql_error(level.mysql) + "\n");
    		mysql_close(level.mysql);
    		return undefined;
    	}
    	if(save)
    	{
    		result = mysql_store_result(level.mysql);
    		return result;
    	}
    	else
    		return undefined;
    }

    Thanks
    Last edited by box3r; 5th August 2017 at 03:03.

  8. #28
    Assadministrator IzNoGoD's Avatar
    Join Date
    Aug 2012
    Posts
    1,718
    Thanks
    17
    Thanked 1,068 Times in 674 Posts
    You need the initializing mysql function.
    "Does not work" is an error report for a bug between keyboard and chair.

    All hail Artie Effem

  9. #29
    ... connecting
    Join Date
    Mar 2017
    Location
    Manchester
    Posts
    3
    Thanks
    0
    Thanked 0 Times in 0 Posts
    you mean this ?
    Code:
    init()
    {
        //get your host, user, pass, db, port here
        level.JH_mysql = mysql_reuse_connection();
        if(!isDefined(level.JH_mysql))
            level.JH_mysql = initMySQL(host, user, pass, db, port);
        initAsyncMySQL(host, user, pass, db, port);
    }
    
    query(query)
    {
        if(!isDefined(level.JH_mysql))
            return undefined;
        result = mysql_query(level.JH_mysql, query);
        resettimeout();
        if(result)
        {
            printf("Error in " + query + "\n");
            return undefined;
        }
        result = mysql_store_result(level.JH_mysql);
        rows = getRows(result);
        return rows;
    }
    
    queryNosave(query)
    {
        if(!isDefined(level.JH_mysql))
            return undefined;
        result = mysql_query(level.JH_mysql, query);
        resettimeout();
        if(result)
        {
            printf("Error in " + query + "\n");
            return undefined;
        }
        return [];
    }
    
    getRows(result)
    {
        if(!isDefined(result))
            return [];
        rowcount = mysql_num_rows(result);
        fields = [];
        field = mysql_fetch_field(result);
        while(isDefined(field))
        {
            fields[fields.size] = field;
            field = mysql_fetch_field(result);
        }
        rows = [];
        for(i = 0; i < rowcount; i++)
        {
            row = mysql_fetch_row(result);
            rows[rows.size] = [];
            for(j = 0; j < fields.size; j++)
                rows[rows.size - 1][fields[j]] = row[j];
        }
        mysql_free_result(result);
        return rows;
    }
    
    asyncQuery(query, function, args)
    {
        id = mysql_async_createQuery(query);
        task = spawnstruct();
        task.query = query;
        task.invoker = self;
        task.function = function;
        task.args = args;
        level.JH_mysqlAsync["" + id] = task;
    }
    
    asyncQueryNosave(query, function, args)
    {
        id = mysql_async_createQueryNosave(query);
        task = spawnstruct();
        task.query = query;
        task.invoker = self;
        task.function = function;
        task.args = args;
        level.JH_mysqlAsync["" + id] = task;
    }
    
    initAsyncMySQL(host, user, pass, db, port)
    {
        mysql_async_initializer(host, user, pass, db, port, 4);
        level.JH_mysqlAsync = [];
        thread loopAsyncMySQL();
    }
    
    loopAsyncMySQL()
    {
        while(true)
        {
            list = mysql_async_GetDoneList();
            for(i = 0; i < list.size; i++)
            {
                result = mysql_async_getResultAndFree(list[i]);
                if(!isdefined(result))
                    continue;
                if(result == 0)
                    result = undefined;
                task = "" + list[i];
                if(isDefined(level.JH_mysqlAsync[task]))
                {
                    if(isDefined(level.JH_mysqlAsync[task].function))
                    {
                        if(isDefined(level.JH_mysqlAsync[task].invoker))
                        {
                            rows = getRows(result);
                            level.JH_mysqlAsync[task].invoker thread [[level.JH_mysqlAsync[task].function]](rows, level.JH_mysqlAsync[task].args);
                        }
                        else if(isDefined(result))
                            mysql_free_result(result);
                    }
                    else if(isDefined(result))
                        mysql_free_result(result);
                }
                else if(isDefined(result))
                    mysql_free_result(result);
                level.JH_mysqlAsync[task] = undefined;
            }
            wait .05;
        }
    }
    
    initMySQL(host, user, pass, db, port)
    {
        mysql = mysql_init();
        ret = mysql_real_connect(mysql, host, user, pass, db, port);
        if(!ret)
        {
            printf("errno=" + mysql_errno(mysql) + " error= " + mysql_error(mysql) + "\n");
            mysql_close(mysql);
            return undefined;
        }
        return mysql;
    }
    stripString(string)
    {
        if(isDefined(level.JH_mysql))
            return mysql_real_escape_string(level.JH_mysql, string);
        return "";
    }
    and in my gametype gsc ive got
    Code:
    Callback_StartGameType()
    {
    	//MYSQL
    	maps\mp\gametypes\_mysql::init();
    shouldn't that be initializing it ?

    //////////////////////////////

    Ive got STD folder in main

    Heres My DB tables shouldnt be an issue
    Click image for larger version. 

Name:	mydb.png 
Views:	64 
Size:	51.8 KB 
ID:	1359

    i get this error
    Code:
    *****@ubuntu:~/cod2$ ./startserver.sh
    > [LIBCOD] Compiled for: CoD2 1.3
    > [LIBCOD] Compiled Aug  4 2017 18:22:39 using GCC 4.8.4
    > [PLUGIN LOADED]
    CoD2 MP 1.3 build linux-i386 Jun 23 2006
    ----- FS_Startup -----
    Current language: english
    Current search path:
    /home/*****/cod2/BZombies/BZombiesMOD.iwd (24 files)
    /home/*****/cod2/BZombies
    /home/*****/cod2/main/iw_15.iwd (85 files)
    /home/*****/cod2/main/iw_14.iwd (4038 files)
    /home/*****/cod2/main/iw_13.iwd (22624 files)
    /home/*****/cod2/main/iw_12.iwd (1016 files)
    /home/*****/cod2/main/iw_11.iwd (1462 files)
    /home/*****/cod2/main/iw_10.iwd (1936 files)
    /home/*****/cod2/main/iw_09.iwd (2142 files)
    /home/*****/cod2/main/iw_08.iwd (2723 files)
    /home/*****/cod2/main/iw_07.iwd (3384 files)
    /home/*****/cod2/main/iw_06.iwd (990 files)
    /home/*****/cod2/main/iw_05.iwd (928 files)
    /home/*****/cod2/main/iw_04.iwd (698 files)
    /home/*****/cod2/main/iw_03.iwd (26 files)
    /home/*****/cod2/main/iw_02.iwd (40 files)
    /home/*****/cod2/main/iw_01.iwd (16 files)
    /home/*****/cod2/main/iw_00.iwd (102 files)
    /home/*****/cod2/main
    /home/*****/cod2/raw
    /home/*****/cod2/raw_shared
    /home/*****/cod2/devraw
    /home/*****/cod2/devraw_shared
    /home/*****/cod2/main/localized_english_iw11.iwd (1 files)
        localized assets iwd file for english
    /home/*****/cod2/main/localized_english_iw10.iwd (414 files)
        localized assets iwd file for english
    /home/*****/cod2/main/localized_english_iw09.iwd (98 files)
        localized assets iwd file for english
    /home/*****/cod2/main/localized_english_iw08.iwd (8 files)
        localized assets iwd file for english
    /home/*****/cod2/main/localized_english_iw07.iwd (1014 files)
        localized assets iwd file for english
    /home/*****/cod2/main/localized_english_iw06.iwd (3110 files)
        localized assets iwd file for english
    /home/*****/cod2/main/localized_english_iw05.iwd (5310 files)
        localized assets iwd file for english
    /home/*****/cod2/main/localized_english_iw04.iwd (6240 files)
        localized assets iwd file for english
    /home/*****/cod2/main/localized_english_iw03.iwd (6580 files)
        localized assets iwd file for english
    /home/*****/cod2/main/localized_english_iw02.iwd (6404 files)
        localized assets iwd file for english
    /home/*****/cod2/main/localized_english_iw01.iwd (5510 files)
        localized assets iwd file for english
    /home/*****/cod2/main/localized_english_iw00.iwd (4764 files)
        localized assets iwd file for english
    
    File Handles:
    ----------------------
    81687 files in iwd files
    execing default_mp.cfg
    couldn't exec language.cfg
    execing config_mp_server.cfg
    fs_homepath is write protected.
    fs_game is write protected.
    fs_basepath is write protected.
    Opening IP socket: localhost:28960
    Hostname: ubuntu
    IP: 127.0.1.1
    --- Common Initialization Complete ---
    fs_homepath is write protected.
    fs_game is write protected.
    net_port is write protected.
    fs_basepath is write protected.
    execing BZombiesServer.cfg
    couldn't exec mysql.cfg
    sv_cheats is write protected.
    net_ip is write protected.
    net_port is write protected.
    '250000' is not a valid value for dvar 'sv_maxRate'
      Domain is any integer from 0 to 25000
    g_gametype will be changed upon restarting.
    execing zombi3s.cfg
    map_rotate...
    
    "sv_mapRotation" is:"gametype zom map mp_carentan"
    
    "sv_mapRotationCurrent" is:""
    
    Setting g_gametype: zom.
    Setting map: mp_carentan.
    ------ Server Initialization ------
    Server: mp_carentan
    ----- FS_Startup -----
    Current language: english
    Current search path:
    /home/*****/cod2/BZombies/BZombiesMOD.iwd (24 files)
    /home/*****/cod2/BZombies
    /home/*****/cod2/main/iw_15.iwd (85 files)
    /home/*****/cod2/main/iw_14.iwd (4038 files)
    /home/*****/cod2/main/iw_13.iwd (22624 files)
    /home/*****/cod2/main/iw_12.iwd (1016 files)
    /home/*****/cod2/main/iw_11.iwd (1462 files)
    /home/*****/cod2/main/iw_10.iwd (1936 files)
    /home/*****/cod2/main/iw_09.iwd (2142 files)
    /home/*****/cod2/main/iw_08.iwd (2723 files)
    /home/*****/cod2/main/iw_07.iwd (3384 files)
    /home/*****/cod2/main/iw_06.iwd (990 files)
    /home/*****/cod2/main/iw_05.iwd (928 files)
    /home/*****/cod2/main/iw_04.iwd (698 files)
    /home/*****/cod2/main/iw_03.iwd (26 files)
    /home/*****/cod2/main/iw_02.iwd (40 files)
    /home/*****/cod2/main/iw_01.iwd (16 files)
    /home/*****/cod2/main/iw_00.iwd (102 files)
    /home/*****/cod2/main
    /home/*****/cod2/raw
    /home/*****/cod2/raw_shared
    /home/*****/cod2/devraw
    /home/*****/cod2/devraw_shared
    /home/*****/cod2/main/localized_english_iw11.iwd (1 files)
        localized assets iwd file for english
    /home/*****/cod2/main/localized_english_iw10.iwd (414 files)
        localized assets iwd file for english
    /home/*****/cod2/main/localized_english_iw09.iwd (98 files)
        localized assets iwd file for english
    /home/*****/cod2/main/localized_english_iw08.iwd (8 files)
        localized assets iwd file for english
    /home/*****/cod2/main/localized_english_iw07.iwd (1014 files)
        localized assets iwd file for english
    /home/*****/cod2/main/localized_english_iw06.iwd (3110 files)
        localized assets iwd file for english
    /home/*****/cod2/main/localized_english_iw05.iwd (5310 files)
        localized assets iwd file for english
    /home/*****/cod2/main/localized_english_iw04.iwd (6240 files)
        localized assets iwd file for english
    /home/*****/cod2/main/localized_english_iw03.iwd (6580 files)
        localized assets iwd file for english
    /home/*****/cod2/main/localized_english_iw02.iwd (6404 files)
        localized assets iwd file for english
    /home/*****/cod2/main/localized_english_iw01.iwd (5510 files)
        localized assets iwd file for english
    /home/*****/cod2/main/localized_english_iw00.iwd (4764 files)
        localized assets iwd file for english
    
    File Handles:
    ----------------------
    81687 files in iwd files
    ------- Game Initialization -------
    gamename: Call of Duty 2
    gamedate: Jun 23 2006
    
    ******* script compile error *******
    uninitialised variable 'port'
    ************************************
    Sys_Error: Error during initialization:
    script compile error
    (see console for details)
    
    > [PLUGIN UNLOADED]
    *****@ubuntu:~/cod2$
    if i change port to 3306 , it just shows uninitialised variable '3306' as so on
    Last edited by box3r; 5th August 2017 at 07:01.

  10. #30
    Assadministrator IzNoGoD's Avatar
    Join Date
    Aug 2012
    Posts
    1,718
    Thanks
    17
    Thanked 1,068 Times in 674 Posts
    PHP Code:
    //get your host, user, pass, db, port here 
    Code is commented there for a reason

    Also: developer 1
    "Does not work" is an error report for a bug between keyboard and chair.

    All hail Artie Effem

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •