[Tutorial] Saving weapon data (MySQL)
#41

Sorry for bumping, But i really need this.
It's keep showing this errors whenever i save the weapons:
Code:
[19:08:31] [ERROR] CMySQLQuery::Execute[] - (error #1452) Cannot add or update a child row: a foreign key constraint fails (`oma`.`weapondata`, CONSTRAINT `weapondata_ibfk_1` FOREIGN KEY (`ID`) REFERENCES `weapondata` (`ID`) ON DELETE CASCADE ON UPDATE CASCADE)
[19:08:31] [ERROR] CMySQLQuery::Execute[] - (error #1452) Cannot add or update a child row: a foreign key constraint fails (`oma`.`weapondata`, CONSTRAINT `weapondata_ibfk_1` FOREIGN KEY (`ID`) REFERENCES `weapondata` (`ID`) ON DELETE CASCADE ON UPDATE CASCADE)
[19:08:31] [ERROR] CMySQLQuery::Execute[] - (error #1452) Cannot add or update a child row: a foreign key constraint fails (`oma`.`weapondata`, CONSTRAINT `weapondata_ibfk_1` FOREIGN KEY (`ID`) REFERENCES `weapondata` (`ID`) ON DELETE CASCADE ON UPDATE CASCADE)
Also i have set the ID, WeaponID as UNIQUE and PRIMARY KEY.
Reply
#42

This error is given when trying to insert or update a row in the child table but there is no such value (for ID in your case) in the parent table. I also noticed that it says "references `weapondata` (`ID`)", it should have been the parent table instead. Post some screenshots from the table's structure -> Relation view
Reply
#43

Could someone show an example on the `deleting` of the row in case someone lost his weapons?
Reply
#44

@Vince

Can you upload a database file?
Reply
#45

Quote:
Originally Posted by knuckleduster5
View Post
@Vince

Can you upload a database file?
If you follow the tutorial, you might probably don't need that.
Reply
#46

Quote:
Originally Posted by X337
View Post
If you follow the tutorial, you might probably don't need that.
I'm trying it but I can't set foreign key. My MySQL knowledge is very poor.
Reply
#47

Quote:
Originally Posted by knuckleduster5
View Post
I'm trying it but I can't set foreign key. My MySQL knowledge is very poor.
You can read this tutorial about creating foreign key: https://dev.mysql.com/doc/refman/5.6...eign-keys.html

Or you can use "designer" or using "relation view" in phpmyadmin as already explained in this tutorial, it's much easier.

Reply
#48

Code:
warning 213: tag mismatch
warning 213: tag mismatch
 warning 213: tag mismatch
Code:
forward OnLoadPlayerWeapons(playerid);
public OnLoadPlayerWeapons(playerid)
{
	new
	    weaponid,
	    ammo;

	for(new i, j = cache_get_row_count(g_SQL); i < j; i++) // loop through all the rows that were found
	{
	    weaponid 	= cache_get_value_int(i, 0, g_SQL);
	    ammo    	= cache_get_value_int(i, 1, g_SQL);

		if(!(0 <= weaponid <= 46)) // check if weapon is valid (should be)
		{
			printf("[info] Warning: OnLoadPlayerWeapons - Unknown weaponid '%d'. Skipping.", weaponid);
			continue;
		}

		GivePlayerWeapon(playerid, weaponid, ammo);
	}
	return;
}
Bold code = lines with errors.

Guys, what's is the problem here? And where should I put my SELECT query? before the new weaponid?
Reply
#49

Quote:
Originally Posted by nikotragedy
View Post
Code:
warning 213: tag mismatch
warning 213: tag mismatch
 warning 213: tag mismatch
Code:
forward OnLoadPlayerWeapons(playerid);
public OnLoadPlayerWeapons(playerid)
{
	new
	    weaponid,
	    ammo;

	for(new i, j = cache_get_row_count(g_SQL); i < j; i++) // loop through all the rows that were found
	{
	    weaponid 	= cache_get_value_int(i, 0, g_SQL);
	    ammo    	= cache_get_value_int(i, 1, g_SQL);

		if(!(0 <= weaponid <= 46)) // check if weapon is valid (should be)
		{
			printf("[info] Warning: OnLoadPlayerWeapons - Unknown weaponid '%d'. Skipping.", weaponid);
			continue;
		}

		GivePlayerWeapon(playerid, weaponid, ammo);
	}
	return;
}
Bold code = lines with errors.

Guys, what's is the problem here? And where should I put my SELECT query? before the new weaponid?
cache_get_value_int(i, 0, weaponid);
cache_get_value_int(i, 1, ammo);

no?

https://sampwiki.blast.hk/wiki/MySQL/R40...alue_index_int
Reply
#50

----
Reply
#51

I have a problem when i insert the code for load weapons when a player connect to the server, pawno get me that error how i can fix it?
pawn Code:
C:\Users\ouday\OneDrive\Desktop\Giochi\samp\samp rp\samp03DL_svr_R1_win32\gamemodes\provabella.pwn(842) : error 017: undefined symbol "weaponid"
C:\Users\ouday\OneDrive\Desktop\Giochi\samp\samp rp\samp03DL_svr_R1_win32\gamemodes\provabella.pwn(904) : warning 219: local variable "weaponid" shadows a variable at a preceding level
C:\Users\ouday\OneDrive\Desktop\Giochi\samp\samp rp\samp03DL_svr_R1_win32\gamemodes\provabella.pwn(905) : warning 219: local variable "ammo" shadows a variable at a preceding level
C:\Users\ouday\OneDrive\Desktop\Giochi\samp\samp rp\samp03DL_svr_R1_win32\gamemodes\provabella.pwn(907) : error 017: undefined symbol "dbrp"
C:\Users\ouday\OneDrive\Desktop\Giochi\samp\samp rp\samp03DL_svr_R1_win32\gamemodes\provabella.pwn(909) : error 017: undefined symbol "cache_get_row_int"
C:\Users\ouday\OneDrive\Desktop\Giochi\samp\samp rp\samp03DL_svr_R1_win32\gamemodes\provabella.pwn(910) : error 017: undefined symbol "cache_get_row_int"
C:\Users\ouday\OneDrive\Desktop\Giochi\samp\samp rp\samp03DL_svr_R1_win32\gamemodes\provabella.pwn(901) : warning 203: symbol is never used: "ammo"
C:\Users\ouday\OneDrive\Desktop\Giochi\samp\samp rp\samp03DL_svr_R1_win32\gamemodes\provabella.pwn(901) : warning 203: symbol is never used: "weaponid"
Pawn compiler 3.2.3664          Copyright (c) 1997-2006, ITB CompuPhase


4 Errors.
this is the GM GM link
Quote:
Originally Posted by Vince
View Post
This is, in part, an extension on my previous tutorial regarding the general table structure and foreign keys. If you haven't read that one, I suggest you do that first.

Weapon Information
There are 13 different weapon slots and thus a player can theoretically hold up to 13 different weapons. In practice, though, this is usually more like 4 or 5.

Why this structure?
The table we will be creating will look like this:

This structure allows for a more compact view and allows for the use of aggregate functions such as COUNT(). This allows me to find out how many weapons each player has, how many players have an M4 or even the total amount of ammo currently circulating (for a specific weapon). This may all seem trivial but it is difficult, if not impossible, to achieve with your average non-normalized "weapon1, ammo1 ... weapon13, ammo13" approach.

From the above screenshot we can deduct that the player 1 has 3 weapons: a nite stick (id 3) with 1 ammo, a desert eagle (id 24) with 21 ammo and an M4 (id 31) with 266 ammo.

Creating the table
userid is a reference to the player's unique ID which is stored in another table, along with their name, password, etc. Notice that phpMyAdmin conveniently makes the userid clickable if a foreign key exists. weaponid is simply the weaponid as is returned from functions like GetPlayerWeapon and GetPlayerWeaponData. ammo holds the ammunition associated with aforementioned weaponid.



The options you need to edit are marked in yellow. Note that the type and attributes of the userid may differ in your case: this field needs to be declared with the exact same definition as your main userid. This may mean that you do not need to set that field to unsigned. The userid does need to be declared as an index though. It is neither a primary key, nor an unique key. For the weaponid we choose an unsigned tinyint since we're only dealing with non-negative numbers up to 46. The ammo is declared unsigned as well since there's no such thing as negative ammunition. Lastly, don't forget to set the engine to InnoDB. Click Save to create the table.

Setting limits
You should've been brought to the structures tab of the table you just created. Navigate there if this isn't the case.
Before continuing, we will first impose some extra limits to avoid cluttering the table with useless data later on. Each player (userid) can only hold exactly one specific weapon (weaponid) at once. This is a UNIQUE property. Therefore, tick the checkboxes in front of userid and weaponid. Then click on the UNIQUE button underneath the table.


Update 31/01/2016: click the PRIMARY KEY button instead. Each table should have a primary key.

Creating the foreign key
You should've been brought back to the structures tab. Navigate there if this isn't the case. Underneath the structure definition you should see a link titled Relation view. Click this to be brought to the "relation creator".



I'm creating a link to the id field in the table playerinfo in the database vcnr. Your table and database will be called differently. Select the proper ID. Note that for fields to show up in this list, they need to be defined as a key! We also want any changes made in the main table to be CASCADED into this table. Click Save. This concludes the table creation part in phpMyAdmin. Now back to Pawn.

Saving
For this table, we will only use SELECT, INSERT and DELETE queries. There will be no real UPDATE queries. Instead, we will only use a special insert query:
PHP Code:
INSERT INTO ... ON DUPLICATE KEY UPDATE ... 
This query will try to insert the data as normal. If this fails because the data already exists (duplicate key) it will instead perform an update. In our context this means that we will merely update the ammo if a weaponid is already present for a specific user.

pawn Code:
new
    weaponid,
    ammo;
   
for(new i; i < 13; i++) // looping through all weapon slots (0 - 12)
{
    GetPlayerWeaponData(playerid, i, weaponid, ammo); // get weaponid and ammo

    if(!weaponid) continue; // don't insert if there's no weapon in this slot
   
    mysql_format(userDB, mysqlquery, sizeof(mysqlquery), "INSERT INTO player_weapons VALUES (%d, %d, %d) ON DUPLICATE KEY UPDATE ammo = %d;", PlayerInfo[playerid][pSQLID], weaponid, ammo, ammo);
    mysql_pquery(userDB, mysqlquery); // parallel queries
}
The above snippet will insert or update all the weapons the player currently has. I am using parallel queries for speed: the order in which the inserts are performed isn't at all important. You will need to substitute the userid variable with your own. The same query can also be used stand-alone in other places. You can, for example, write a hook for GivePlayerWeapon which immediately performs an insert as soon as the weapon is given.

Loading
Now to retrieve this data and give the players their weapons back. Our standard select query;
PHP Code:
SELECT weaponidammo FROM player_weapons WHERE userid = %d
pawn Code:
public OnLoadPlayerWeapons(playerid)
{
    new
        weaponid,
        ammo;
   
    for(new i, j = cache_get_row_count(userDB); i < j; i++) // loop through all the rows that were found
    {
        weaponid    = cache_get_row_int(i, 0, userDB);
        ammo        = cache_get_row_int(i, 1, userDB);
       
        if(!(0 <= weaponid <= 46)) // check if weapon is valid (should be)
        {
            printf("[info] Warning: OnLoadPlayerWeapons - Unknown weaponid '%d'. Skipping.", weaponid);
            continue;
        }
       
        GivePlayerWeapon(playerid, weaponid, ammo);
    }
    return;
}
Purging obsolete data
Whenever a weapon is taken away, do not forget to delete it from the database otherwise it will be returned to the player when they next join. You could write a hook for ResetPlayerWeapons. It may also be possible that weapons that have no ammo are left behind in the table. This doesn't affect anything in-game and can be cleaned up with a query (delete where ammo = 0) when the server starts, or on a cron job.
Reply
#52

I have a problem compiling my code:
Code:
public OnPlayerSpawn(playerid)
{
	new WQ[256];
   
    mysql_format(Database, WQ, sizeof(WQ), "SELECT `WEAPONID`, `AMMO` FROM `WEAPONDATA` WHERE `ID` = '%d'", pInfo[playerid][ID]);
	mysql_tquery(Database, WQ, "OnLoadPlayerWeapons", "ii", playerid);
    
    
    
    
    
	return 1;
}




forward public OnLoadPlayerWeapons(playerid);
public OnLoadPlayerWeapons(playerid)
{
   

    for(new i, j = cache_get_row_count(WQ); i < j; i++) // loop through all the rows that were found
    {
        weaponid    = cache_get_row_int(i, 0, WQ);
        ammo        = cache_get_row_int(i, 1, WQ);

        if(!(0 <= weaponid <= 46)) // check if weapon is valid (should be)
        {
            printf("[info] Warning: OnLoadPlayerWeapons - Unknown weaponid '%d'. Skipping.", weaponid);
            continue;
        }

        GivePlayerWeapon(playerid, weaponid, ammo);
    }
    return;
}
Geting this error:
PHP Code:
E:\Projektai\SAMP\Win servas prog\gamemodes\naujas.pwn(550) : error 017undefined symbol "WQ"
E:\Projektai\SAMP\Win servas prog\gamemodes\naujas.pwn(552) : error 017undefined symbol "cache_get_row_int"
E:\Projektai\SAMP\Win servas prog\gamemodes\naujas.pwn(553) : error 017undefined symbol "cache_get_row_int"
Pawn compiler 3.2.3664              Copyright (c1997-2006ITB CompuPhase
3 Errors

Reply
#53

Hello guys, I've just updated to this method, and I wonder..
My weapons don't get deleted from the database, how should I make a query to delete everything for the player before inserting new weapon values

Thanks if anyone would explain to me
Reply
#54

Quote:
Originally Posted by Nawickaz
View Post
I have a problem compiling my code:
Code:
public OnPlayerSpawn(playerid)
{
	new WQ[256];
   
    mysql_format(Database, WQ, sizeof(WQ), "SELECT `WEAPONID`, `AMMO` FROM `WEAPONDATA` WHERE `ID` = '%d'", pInfo[playerid][ID]);
	mysql_tquery(Database, WQ, "OnLoadPlayerWeapons", "ii", playerid);
    
    
    
    
    
	return 1;
}




forward public OnLoadPlayerWeapons(playerid);
public OnLoadPlayerWeapons(playerid)
{
   

    for(new i, j = cache_get_row_count(WQ); i < j; i++) // loop through all the rows that were found
    {
        weaponid    = cache_get_row_int(i, 0, WQ);
        ammo        = cache_get_row_int(i, 1, WQ);

        if(!(0 <= weaponid <= 46)) // check if weapon is valid (should be)
        {
            printf("[info] Warning: OnLoadPlayerWeapons - Unknown weaponid '%d'. Skipping.", weaponid);
            continue;
        }

        GivePlayerWeapon(playerid, weaponid, ammo);
    }
    return;
}
Geting this error:
PHP Code:
E:\Projektai\SAMP\Win servas prog\gamemodes\naujas.pwn(550) : error 017undefined symbol "WQ"
E:\Projektai\SAMP\Win servas prog\gamemodes\naujas.pwn(552) : error 017undefined symbol "cache_get_row_int"
E:\Projektai\SAMP\Win servas prog\gamemodes\naujas.pwn(553) : error 017undefined symbol "cache_get_row_int"
Pawn compiler 3.2.3664              Copyright (c1997-2006ITB CompuPhase
3 Errors


pawn Code:
// AssignPlayerWeapons
forward AssignPlayerWeapons(playerid);
public AssignPlayerWeapons(playerid)
{

    if(!cache_num_rows()) return 0;
   
    new
        weaponid,
        ammo;
   
    for(new i; i < cache_num_rows(); i++)
    {
        cache_get_value_name_int(i, "weapon_colum", weaponid);
        cache_get_value_name_int(i, "ammo_column", ammo);
       
        if(!(0 <= weaponid <= 46))
        {
            printf("[info] Warning: OnLoadPlayerWeapons - Unknown weaponid '%d'. Skipping.", weaponid);
            continue;
        }
        GivePlayerWeapon(playerid, weaponid, ammo);
    }
    return 1;
}
Reply
#55

Quote:
Originally Posted by Arramis
View Post
Hello guys, I've just updated to this method, and I wonder..
My weapons don't get deleted from the database, how should I make a query to delete everything for the player before inserting new weapon values

Thanks if anyone would explain to me
+1 same problem here, anyone?
Reply
#56

Thanks for this, I'm gonna use this.
Reply
#57

Quote:

public OnLoadPlayerWeapons(playerid)
{
new
weaponid,
ammo;

for(new i, j = cache_get_row_count (userDB); i < j; i++) // loop through all the rows that were found
{
weaponid = cache_get_row_int(i, 0, userDB);
ammo = cache_get_row_int(i, 1, userDB);

if(!(0 <= weaponid <= 46)) // check if weapon is valid (should be)
{
printf("[info] Warning: OnLoadPlayerWeapons - Unknown weaponid '%d'. Skipping.", weaponid);
continue;
}

GivePlayerWeapon(playerid, weaponid, ammo);
}
return;
}

Deu esse error nessa parte:

Quote:

C:\Users\pawn\Desktop\servidor\gamemodes\Cauezin.p wn(378 : warning 235: public function lacks forward declaration (symbol "OnLoadPlayerWeapons")
C:\Users\pawn\Desktop\servidor\gamemodes\Cauezin.p wn(3794) : warning 213: tag mismatch
C:\Users\pawn\Desktop\servidor\gamemodes\Cauezin.p wn(3796) : error 017: undefined symbol "cache_get_row_int"
C:\Users\pawn\Desktop\servidor\gamemodes\Cauezin.p wn(3797) : error 017: undefined symbol "cache_get_row_int"
Pawn compiler 3.2.3664 Copyright © 1997-2006, ITB CompuPhase


2 Errors.

Eu defini no topo da gm:

Quote:

new MySQL:userDB;

e coloquei em OnPlayerDisconnect:

Quote:

{
new
weaponid,
ammo;
new mysqlquery[900];

for(new i; i < 13; i++) // looping through all weapon slots (0 - 12)
{
GetPlayerWeaponData(playerid, i, weaponid, ammo); // get weaponid and ammo

if(!weaponid) continue; // don't insert if there's no weapon in this slot

mysql_format(userDB, mysqlquery, sizeof(mysqlquery), "INSERT INTO player_weapons VALUES (%d, %d, %d) ON DUPLICATE KEY UPDATE ammo = %d;", Player[playerid][pSQLID], weaponid, ammo, ammo);
mysql_pquery(userDB, mysqlquery); // parallel queries mysql_format
}

Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)