Сбивается сохранения

Сообщения
32
Реакции
0
Всё нормально сохраняется,после того как n раз сервере рестартишь(перезапуск,смена карты),они сбрасываются. Я хз в чём может быть вопрос и как так может быть,чтобы 1 раз сохранилось,а потом после несколько раз перезапуска сбрасывалось

Код:
#include amxmodx
#include a_main
#include sqlx

new g_iUserLevel[33];
new g_iUserExp[33];
new const g_szTotalExp[15] =
{
    5,
    10,
    20,
    35,
    55,
    73,
    100,
    150,
    210,
    300,
    400,
    470,
    590,
};

#define dbHost  ""
#define dbUser  ""
#define dbPass  ""
#define dbName  ""
#define dbTable     ""
new g_szSteamID[33][34], g_szQuery[2048];
new Handle:g_hDBTuple, Handle:g_hConnect;
public plugin_init()
{
    register_plugin("iCore LVL System", "18/10/2019", "AlexaCarra");
    RegisterCmd("rang_plus", "CmdTest");
}
public plugin_cfg()
{
    set_task(0.5, "Func_LoadDB");
}
public Func_LoadDB()
{
    new szError[512], iErrNo;
   
    g_hDBTuple = SQL_MakeDbTuple(dbHost, dbUser, dbPass, dbName);
    g_hConnect = SQL_Connect(g_hDBTuple, iErrNo, szError, charsmax(szError));
   
    if(g_hConnect == Empty_Handle)
    {
   
        server_print("[LVL] - DBConnection Error #%d: %s", iErrNo, szError);
        //set_fail_state("[SYSTEM ACC] - DBConnection Error %d: %s", iErrNo, szError);
   
    }
   
    new Handle:hQuery;
    new szQuery[512];
   
    formatex(szQuery, charsmax(szQuery), "CREATE TABLE IF NOT EXISTS `%s` (SteamID VARCHAR(40) CHARACTER SET cp1250 COLLATE cp1250_general_ci NOT NULL, user_level INT NOT NULL, user_exp INT NOT NULL, PRIMARY KEY (SteamID))", dbTable);
    hQuery = SQL_PrepareQuery(g_hConnect, szQuery);
   
    if(!SQL_Execute(hQuery))
    {
   
        SQL_QueryError(hQuery, szError, charsmax(szError));
        set_fail_state(szError);
       
    }
    SQL_FreeHandle(hQuery);
}
public ThreadQueryHandler(iState, Handle:hQuery, szError[], iError, iParams[], iParamsSize)
{
    if(iState == 0)
    return;
    log_amx("SQL Error: %d (%s)", iError, szError);
}


public SQL_QueryConnection(iState, Handle:hQuery, szError[], iErrcode, iParams[] , iParamsSize)
{
    switch(iState)
    {
        case TQUERY_CONNECT_FAILED: log_amx ( "[LVL SYSTEM] Load - Could not connect to SQL database. [%d] %s" , iErrcode , szError );
        case TQUERY_QUERY_FAILED: log_amx ( "[LVL SYSTEM] Load Query failed. [%d] %s" , iErrcode , szError );
    }
    new pPlayer = iParams[0];
    if(SQL_NumResults(hQuery) < 1)
    {
        if(equal(g_szSteamID[pPlayer], "ID_PENDING"))
        return PLUGIN_HANDLED;
        g_iUserLevel[pPlayer] = 0
        g_iUserExp[pPlayer] = 0
        format
        (
            g_szQuery, charsmax(g_szQuery),
           
            "INSERT INTO `%s`(`SteamID`, `user_level`, `user_exp`) VALUES ('%s' ,'%d' ,'%d');",
            dbTable, g_szSteamID[pPlayer], 
            g_iUserLevel[pPlayer], g_iUserExp[pPlayer]
        );
        SQL_ThreadQuery(g_hDBTuple, "ThreadQueryHandler", g_szQuery);
        return PLUGIN_HANDLED;
    }
    else
    {
        g_iUserLevel[pPlayer] = SQL_ReadResult(hQuery, 1);
        g_iUserExp[pPlayer] = SQL_ReadResult(hQuery, 2);
    }
    return PLUGIN_HANDLED;
}



public plugin_natives()
{
    register_native("icore_give_user_exp", "icore_give_user_exp", 1);
   
    register_native("icore_get_user_lvl", "icore_get_user_lvl", 1);
    register_native("icore_info_total", "icore_info_total", 1);
    register_native("icore_info_exp", "icore_info_exp", 1);
}
public client_putinserver(id)
{
    new iParams[1]; iParams[0] = id;
    get_user_authid(id, g_szSteamID[id], charsmax(g_szSteamID[]));
    format(g_szQuery, charsmax(g_szQuery), "SELECT * FROM `%s` WHERE (`%s`.`SteamID` = '%s')", dbTable, dbTable, g_szSteamID[id]);
    SQL_ThreadQuery(g_hDBTuple, "SQL_QueryConnection", g_szQuery, iParams, sizeof iParams);
}
public client_disconnect(id)
{
    format(g_szQuery, charsmax(g_szQuery), "UPDATE `%s` SET `user_level` = '%d', `user_exp` = '%d'  WHERE `%s`.`SteamID` = '%s';", dbTable, g_iUserLevel[id], g_iUserExp[id], dbTable, g_szSteamID[id]);
    SQL_ThreadQuery(g_hDBTuple, "ThreadQueryHandler", g_szQuery);
    g_iUserLevel[id] = 0;
    g_iUserExp[id] = 0;
}
public CmdTest(id)
{
    icore_give_user_exp(id, 10, "выдача командой");
}
public icore_give_user_exp(id, iNum, const Message[])
{
    g_iUserExp[id] += iNum;
    InChat(id, "!t[!gLVL!t] !yВам начисленно %d за !g%s", iNum, Message);
    Func_CheckLevel(id);
}
public Func_CheckLevel(id)
{
    new name[32]; get_user_name(id, name, charsmax(name))
    if(g_iUserExp[id] >= 590 || g_iUserLevel[id] == 15) return PLUGIN_HANDLED;
    while(g_iUserExp[id] >= g_szTotalExp[g_iUserLevel[id]])
    {
        g_iUserExp[id] = 0;
        g_iUserLevel[id] += 1;
        new name[32];
        get_user_name(id, name, 31);
        if(g_iUserLevel[id] != 15)
        {
            InChat(0, "!t[!gLVL!t] !yИгрок !g%s !yподнял свой LVL - !g[%d]", name, g_iUserLevel[id]);
            g_iUserLevel[id] = "Легенда зоны";
        }
        else InChat(0, "!t[!gLVL!t] !yИгрок !g%s !yполучил звание - !g'Легенда зоны'", name);
    }
    return PLUGIN_HANDLED;
}

public plugin_end()
{  
    // LVL SYSTEM
    if(g_hDBTuple) SQL_FreeHandle(g_hDBTuple);
    if(g_hConnect) SQL_FreeHandle(g_hConnect);
    return;
}

public icore_info_total(id) return g_szTotalExp[g_iUserLevel[id]];
public icore_info_exp(id) return g_iUserExp[id];
public icore_get_user_lvl(id) return g_iUserLevel[id];
 
Последнее редактирование модератором:
Сообщения
584
Реакции
1,006
Помог
18 раз(а)
Код:
public client_disconnect(id)
{
    format(g_szQuery, charsmax(g_szQuery), "UPDATE `%s` SET `user_level` = '%d', `user_exp` = '%d'  WHERE `%s`.`SteamID` = '%s';", dbTable, g_iUserLevel[id], g_iUserExp[id], dbTable, g_szSteamID[id]);
    SQL_ThreadQuery(g_hDBTuple, "ThreadQueryHandler", g_szQuery);
    g_iUserLevel[id] = 0;
    g_iUserExp[id] = 0;
}
Сохранять надо после авторизации, а не просто при дисконнекте.
Код:
    else
    {
        g_iUserLevel[pPlayer] = SQL_ReadResult(hQuery, 1);
        g_iUserExp[pPlayer] = SQL_ReadResult(hQuery, 2);
    }
    // где-то тут ставить
    g_bAuth[pPlayer] = true;
    return PLUGIN_HANDLED;
}
false поставить перед запросом на загрузку.
В дисконнекте проверить на auth и потом только делать запрос сохранения.
 
Сообщения
32
Реакции
0
Mistrick, Я примерно понял вас. То есть,нужно создать булевую,которая будет говорить есть мы или нет. Когда игрок конектиться,после запроса на получение данных мне нужно поставить true,а при дисконнекте проверять на булевую и после выгрузки мне поставить false?

Код:
public client_disconnect(id)
{
    if(g_bAuth[id])
    {
        format(g_szQuery, charsmax(g_szQuery), "UPDATE `%s` SET `user_level` = '%d', `user_exp` = '%d'  WHERE `%s`.`SteamID` = '%s';", dbTable, g_iUserLevel[id], g_iUserExp[id], dbTable, g_szSteamID[id]);
        SQL_ThreadQuery(g_hDBTuple, "ThreadQueryHandler", g_szQuery);
        g_iUserLevel[id] = 0;
        g_iUserExp[id] = 0;
        g_bAuth[id] = false;
    }
}


public SQL_QueryConnection(iState, Handle:hQuery, szError[], iErrcode, iParams[] , iParamsSize)
{
    switch(iState)
    {
        case TQUERY_CONNECT_FAILED: log_amx ( "[LVL SYSTEM] Load - Could not connect to SQL database. [%d] %s" , iErrcode , szError );
        case TQUERY_QUERY_FAILED: log_amx ( "[LVL SYSTEM] Load Query failed. [%d] %s" , iErrcode , szError );
    }
    new pPlayer = iParams[0];
    if(SQL_NumResults(hQuery) < 1)
    {
        if(equal(g_szSteamID[pPlayer], "ID_PENDING"))
        return PLUGIN_HANDLED;
        g_iUserLevel[pPlayer] = 0
        g_iUserExp[pPlayer] = 0
        format
        (
            g_szQuery, charsmax(g_szQuery),
           
            "INSERT INTO `%s`(`SteamID`, `user_level`, `user_exp`) VALUES ('%s' ,'%d' ,'%d');",
            dbTable, g_szSteamID[pPlayer], 
            g_iUserLevel[pPlayer], g_iUserExp[pPlayer]
        );
        SQL_ThreadQuery(g_hDBTuple, "ThreadQueryHandler", g_szQuery);
        return PLUGIN_HANDLED;
    }
    else
    {
        g_iUserLevel[pPlayer] = SQL_ReadResult(hQuery, 1);
        g_iUserExp[pPlayer] = SQL_ReadResult(hQuery, 2);
    }
    g_bAuth[pPlayer] = true;
    return PLUGIN_HANDLED;
}
И не очень понял вас про "Сохранять надо после авторизации, а не просто при дисконнекте. "
 

Ayk

Сообщения
763
Реакции
478
Помог
19 раз(а)
Ты должен сохранять "статус" игрока: загружены его данные или нет.
Если данные не были загружены то и сохранения не должно быть (ибо перезапишется нулями), а если были то сохранить новые.
 
Сообщения
32
Реакции
0
Hypa_[KZ], не имеет значение. Т.к эта бд не используется
3 Дек 2019
Ayk, Я иногда не понимаю простых вещей введу нехватки опыта. Вот так же и с мускулом. Я сейчас не очень понял,что означает
"сохранять "статус" игрока: загружены его данные или нет"
 

Ayk

Сообщения
763
Реакции
478
Помог
19 раз(а)
AlexaCarra, по сути, это то что ты уже сделал (во втором коде).
Просто добавь g_bAuth[id] = false; до загрузки данных.
 
Сообщения
271
Реакции
348
Помог
15 раз(а)
AlexaCarra, игрок заходит на сервер, отправился запрос в БД на получение его опыта, по какой-то причине запрос прошёл медленно (возможно из-за задержки БД), и игрок вышел до получения запроса. В БД записались нули (либо цифры другого игрока по его id).

Поэтому тут нужно делать как написал Mistrick либо сохранять опыт сразу же при получении его.
 
Сообщения
32
Реакции
0
Ayk, "До загрузи данных" то есть,мне его добавить в коннект? Видимо,я тупой)
Я просто иногда не понимаю,хоть убей,но не пойму ваших понятий. Если я понял всё правильно:
Я делаю g_bAuth[id] = true в загрузке (после коннекта,именно в самой загрузке,внезависимости от ранга,то есть есть ли он в бд или его только создаст),после в дисконекtе я проверяю
Код:
public client_disconnect(id)
{
    if(g_bAuth[id])
    {
        format(g_szQuery, charsmax(g_szQuery), "UPDATE `%s` SET `user_level` = '%d', `user_exp` = '%d'  WHERE `%s`.`SteamID` = '%s';", dbTable, g_iUserLevel[id], g_iUserExp[id], dbTable, g_szSteamID[id]);
        SQL_ThreadQuery(g_hDBTuple, "ThreadQueryHandler", g_szQuery);
        g_iUserLevel[id] = 0;
        g_iUserExp[id] = 0;
        g_bAuth[id] = false;
    }
}
и после обнуляю все переменные хранящие експу,левел и так же булевую.
Я опять таки не очень понимаю ваше выражение "До загрузки данных" куда её ещё то добавлять.если я её обнулю до загрузки данных,то тогда при дисконнекте данные не будут обнуляться,тк g_bAuth[id] = 0(false)
3 Дек 2019
Denzer, Я ж вроде сделал как он. Не мог бы ты прочитать его и ответить?
 
Сообщения
432
Реакции
410
Помог
14 раз(а)
Сообщения
32
Реакции
0
voed, То есть,что получается. Я в путинсервер при получении всех данных включаю булевую,а потом сразу же выключаю,аля "включил на секунду" ?
Код:
public client_putinserver(id)
{
    new iParams[1]; iParams[0] = id;
    get_user_authid(id, g_szSteamID[id], charsmax(g_szSteamID[]));
    format(g_szQuery, charsmax(g_szQuery), "SELECT * FROM `%s` WHERE (`%s`.`SteamID` = '%s')", dbTable, dbTable, g_szSteamID[id]);
    SQL_ThreadQuery(g_hDBTuple, "SQL_QueryConnection", g_szQuery, iParams, sizeof iParams);

   g_bAuth[id] = false;
}

public SQL_QueryConnection(iState, Handle:hQuery, szError[], iErrcode, iParams[] , iParamsSize)
{
    switch(iState)
    {
        case TQUERY_CONNECT_FAILED: log_amx ( "[LVL SYSTEM] Load - Could not connect to SQL database. [%d] %s" , iErrcode , szError );
        case TQUERY_QUERY_FAILED: log_amx ( "[LVL SYSTEM] Load Query failed. [%d] %s" , iErrcode , szError );
    }
    new pPlayer = iParams[0];
    if(SQL_NumResults(hQuery) < 1)
    {
        if(equal(g_szSteamID[pPlayer], "ID_PENDING"))
        return PLUGIN_HANDLED;
        g_iUserLevel[pPlayer] = 0
        g_iUserExp[pPlayer] = 0
        format
        (
            g_szQuery, charsmax(g_szQuery),
           
            "INSERT INTO `%s`(`SteamID`, `user_level`, `user_exp`) VALUES ('%s' ,'%d' ,'%d');",
            dbTable, g_szSteamID[pPlayer], 
            g_iUserLevel[pPlayer], g_iUserExp[pPlayer]
        );
        SQL_ThreadQuery(g_hDBTuple, "ThreadQueryHandler", g_szQuery);
        return PLUGIN_HANDLED;
    }
    else
    {
        g_iUserLevel[pPlayer] = SQL_ReadResult(hQuery, 1);
        g_iUserExp[pPlayer] = SQL_ReadResult(hQuery, 2);
    }
    g_bAuth[pPlayer] = true;
    return PLUGIN_HANDLED;
}
Тогда вопрос,а если дисконнект не всегда срабатывает,а у меня там проверика на g_bAuth[pPlayer], а он по сути уже выключен,так тогда же оно не будет апдейтиться,т.к,повторюсьь, g_bAuth[pPlayer] = false
 
Сообщения
432
Реакции
410
Помог
14 раз(а)
тогда же оно не будет апдейтиться,т.к,повсторюсь, g_bAuth[pPlayer] = false
В SQL_QueryConnection у вас выставляется в true. Эта функция выполняется асинхронно, поэтому после получения данных из БД у вас будет g_bAuth[pPlayer] = true;
Для чистоты логики можно сделать так
Код:
public client_putinserver(id)
{
    g_bAuth[id] = false;
    new iParams[1]; iParams[0] = id;
    get_user_authid(id, g_szSteamID[id], charsmax(g_szSteamID[]));
    format(g_szQuery, charsmax(g_szQuery), "SELECT * FROM `%s` WHERE (`%s`.`SteamID` = '%s')", dbTable, dbTable, g_szSteamID[id]);
    SQL_ThreadQuery(g_hDBTuple, "SQL_QueryConnection", g_szQuery, iParams, sizeof iParams);
}
 
Сообщения
32
Реакции
0
voed, Я понял. Очень благодарю. А есть какие-то ещё такие примеры с мускулом которые сохраняют этот же принцип ?
 

Ayk

Сообщения
763
Реакции
478
Помог
19 раз(а)
AlexaCarra, это уже легко гуглится.
На асинхронный запрос сервер не ждёт ответ; придёт когда придёт.
На синхронный запрос сервер ожидает ответ, отложив почти все дела.
 
Сообщения
432
Реакции
410
Помог
14 раз(а)
AlexaCarra, синхронные запросы намертво вешают сервер, пока не получат ответ от БД
 
Сообщения
333
Реакции
290
Помог
9 раз(а)
C++:
//после получения данных записываем старое значение из БД
g_iUserExpOld[pPlayer] = SQL_ReadResult(hQuery, 2);

//для хранения изменений в процессе используем другую переменную
g_iUserExp[id] += iNum;

//их сумма для работы с нативом
public icore_info_exp(id) return g_iUserExp[id] + g_iUserExpOld[pPlayer];

//в базу для сохранения отправляется только изменение, если оно имеется
... SET `user_exp` = `user_exp` + '%d'..., g_iUserExp[id]

//можно предварительно проверить, были ли изменения, чтобы не отправлять ненужный запрос
if(g_iUserExpOld[pPlayer])
    ... SET `user_exp` = `user_exp` + '%d'..., g_iUserExp[id]
 

Пользователи, просматривающие эту тему

Сейчас на форуме нет ни одного пользователя.
Сверху Снизу