[Tutorial] Cool stuff in BlueG R15, and fixing strings
#1

I'll assume that you are already using R7 and know how to use it ( https://sampforum.blast.hk/showthread.php?tid=337810 ).

Let's take a look at this example for R7
pawn Код:
#include <a_samp>
#include <a_mysql>

#define DEBUG 1

#if DEBUG
    #define Debug(%0) printf(%0)
#else
    #define stock Debug({Float,_}:...)
#endif

enum PInfo {
    dbID,
    nick[65],
    Float:lastPos[4],
    bankMoney,
    lastSeen
}

static Player[MAX_PLAYERS][PInfo];

#define DBPREFIX "myrp_"

enum {
    TB_PLAYERS,
    TB_SESSIONS
}
static dbhandle;
#define MAX_TABLE_LEN 32

static tables[][MAX_TABLE_LEN] = {
    DBPREFIX"players",
    DBPREFIX"sessions"
};

public OnGameModeInit() {
    if((dbhandle = mysql_connect(...)) && dbhandle) {
        Debug("Awwright");
    } else {
        Debug("DB Connection failed!");
    }
    return 1;
}

public OnGameModeExit() {
    mysql_close(dbhandle);
    return 1;
}

public OnPlayerConnect(playerid) {
    new tmp[174 + MAX_TABLE_LEN + MAX_TABLE_LEN + MAX_PLAYER_NAME + 1];
    GetPlayerName(playerid, tmp);
    mysql_format(dbhandle, tmp, "SELECT t1.dbID, t1.nick, t1.posX, t1.posY, t1.posZ, t1.posR, t1.bankMoney, t2.session_end FROM `%s` t1 LEFT JOIN `%s` t2 ON t2.uid = t1.dbID WHERE t1.name = '%e' ORDER BY t2.session_end DESC LIMIT 0,1", tables[TB_PLAYERS], tables[TB_SESSIONS], tmp);
    mysql_function_query(dbhandle, tmp, true, "OnPlayerLoad", "i", playerid);
    return 1;
}

forward OnPlayerLoad(pid);
public OnPlayerLoad(pid) {
    new rows, fields, tmp[64];
    cache_get_data(rows, fields, dbhandle);
    if(rows == 0) {
        SendClientMessage(pid, -1, "You don't have an account here!");
        return Kick(pid);
    }
    cache_get_row(0, 0, tmp, dbhandle);
    Player[pid][dbID] = strval(tmp);
    cache_get_row(0, 1, Player[pid][nick], dbhandle);
    cache_get_row(0, 2, tmp, dbhandle);
    Player[pid][lastPos][0] = floatstr(tmp);
    cache_get_row(0, 3, tmp, dbhandle);
    Player[pid][lastPos][1] = floatstr(tmp);
    cache_get_row(0, 4, tmp, dbhandle);
    Player[pid][lastPos][2] = floatstr(tmp);
    cache_get_row(0, 5, tmp, dbhandle);
    Player[pid][lastPos][3] = floatstr(tmp);
    cache_get_row(0, 6, tmp, dbhandle);
    Player[pid][bankMoney] = strval(tmp);
    cache_get_row(0, 7, tmp, dbhandle);
    Player[pid][lastSeen] = strval(tmp);
    Debug("Loaded player with nick %s!", Player[pid][nick]);
    return 1;
}

public OnQueryError(errorid, error[], callback[], query[], connectionHandle) {
    Debug("Error while executing query!\nQ: %s\nErrno: %d\nError: %s", query, errorid, error);
    return 1;
}
There should be more logic, like logging in, registration, etc, but I won't cover it in this tut.

Let's focus on this:
pawn Код:
cache_get_row(0, 0, tmp, dbhandle);
Player[pid][dbID] = strval(tmp);
cache_get_row(0, 1, Player[pid][nick], dbhandle);
cache_get_row(0, 2, tmp, dbhandle);
Player[pid][lastPos][0] = floatstr(tmp);
cache_get_row(0, 3, tmp, dbhandle);
Player[pid][lastPos][1] = floatstr(tmp);
cache_get_row(0, 4, tmp, dbhandle);
Player[pid][lastPos][2] = floatstr(tmp);
cache_get_row(0, 5, tmp, dbhandle);
Player[pid][lastPos][3] = floatstr(tmp);
cache_get_row(0, 6, tmp, dbhandle);
Player[pid][bankMoney] = strval(tmp);
cache_get_row(0, 7, tmp, dbhandle);
Player[pid][lastSeen] = strval(tmp);
In some update there were added functions cache_get_row_(int/float). Let's use them!

pawn Код:
cache_get_row_int(0, 0, Player[pid][dbID], dbhandle);
cache_get_row(0, 1, Player[pid][nick], dbhandle);
Player[pid][lastPos][0] = cache_get_row_float(0, 2, dbhandle);
Player[pid][lastPos][1] = cache_get_row_float(0, 3, dbhandle);
Player[pid][lastPos][2] = cache_get_row_float(0, 4, dbhandle);
Player[pid][lastPos][3] = cache_get_row_float(0, 5, dbhandle);
Player[pid][bankMoney] = cache_get_row_int(0, 6, dbhandle);
Player[pid][lastSeen] = cache_get_row_int(0, 7, dbhandle);
Cool, we can even get rid of tmp! Now, there is something bad happening. The nick isn't loaded properly! Why?
Let's take a look at a_mysql.inc

pawn Код:
native cache_get_row(row, idx, destination[], connectionHandle = 1, max_len=sizeof(destination));
max_len argument, it wasn't there in r7! How to fix this?
By default the function will assume that
pawn Код:
max_len = sizeof(Player[pid]);
This code isn't correct for our situation, because we will get size of an enum instead of string. Maybe sizeof Player[pid][nick]? Nope, won't work. We have 3 options:
pawn Код:
//1. Hardcoded
cache_get_row(0, 1, Player[pid][nick], dbhandle, 65);
//2. Hardcoded as well
#define MAX_NICK_LEN 65
//(...)
nick[65] => nick[MAX_NICK_LEN]
//(...)
cache_get_row(0, 1, Player[pid][nick], dbhandle, MAX_NICK_LEN);
//3. Little trick, consuming some of the stack
new PTmp[PInfo];
cache_get_row(0, 1, Player[pid][nick], dbhandle, sizeof PTmp[nick]);
Now string should get loaded properly.

That's all folks!
Reply
#2

I like the hardcore way ) well done sir
Reply
#3

Brilliant, thanks for posting this.
Reply
#4

I just looked at the a_mysql, you know that cache_get_row_int/float does not have a destination so what you have wrote about above will return
Код:
 warning 202: number of arguments does not match definition
Reply
#5

Hah, I was rewriting R7 example and forgot about this. Of course you are right, good catch
Reply
#6

Quote:
Originally Posted by Misiur
Посмотреть сообщение
pawn Код:
//1. Hardcoded
cache_get_row(0, 1, Player[pid][nick], dbhandle, 65);
This is what I wanted! I was converting a racing system I've made into MySQL r15 and I came across with it yesterday.
Thanks for the information!
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)