Русское сообщество по скриптингу

Плагин статистики  [Решено]

Все вопросы по скриптингу для AMXX, помощь в редактировании плагинов.

Модераторы: Subb98, liFe iS GoOD

Правила форума
1. Запрещено материться и оскорблять других участников форума.
2. Запрещен флуд, оффтоп, дабл постинг во всех разделах форума, кроме раздела "Болтовня".
3. Запрещено взламывать сайт/форум или наносить любой вред проекту.
4. Запрещено рекламировать другие ресурсы.
5. Запрещено создавать темы без информативного названия. Название темы должно отображать ее смысл.

В данном разделе форума разрешено создавать темы, касающие только скриптинга для AMX Mod X.

Правила при создании новой темы:
1. При вставке кода плагина необходимо использовать тег [code=php].
2. Любые изображения должны быть загружены, как вложения к вашему сообщению.
3. При описании проблемы или запросе на помощь в редактировании плагина обязательно выкладывайте исходник sma плагина.

Плагин статистики

Сообщение L0L1K » 14 май 2020, 09:59

Была цель написать простой плагин статистики для сервера, который использовал бы минимальное количество запросов к БД и не нагружал сервер. Но получился генератор лагов...
Может кто подскажет, как оптимизировать?
Код: Выделить всё
#include <amxmodx>
#include <amxmisc>
#include <csx>
#include <sqlx>

#define PLUGIN "Lite Stats SQL"
#define VERSION "0.1"
#define AUTHOR "L0L1K"

new Handle:MYSQL_Tuple
new Handle
:MYSQL_Connect

new g_Cvar
[5]

new g_ActiveMysql
new szPlayerRank
[33]
new szPlayerKills[33]
new szPlayerDeaths[33]
new szPlayerShots[33]
new szPlayerHits[33]
new szPlayerHshots[33]
new szPlayerMysql[33]

public plugin_init() 
{
    register_plugin(PLUGIN, VERSION, AUTHOR)

    register_event("30", "ChangeMap", "a")

    g_Cvar[1] = register_cvar("lite_stats_hostname", "") //127.0.0.1
    g_Cvar[2] = register_cvar("lite_stats_username", "")  //root
    g_Cvar[3] = register_cvar("lite_stats_password", "") //password
    g_Cvar[4] = register_cvar("lite_stats_database", "") //testmysql

        set_task(1.0, "MYSQL_Load")
}

public MYSQL_Load()
{
    new szHostname[30], szUsername[30], szPassword[30], szDatabase[30]
    new szError[512], szErr

    get_pcvar_string
(g_Cvar[1], szHostname, charsmax( szHostname ))
    get_pcvar_string(g_Cvar[2], szUsername, charsmax( szUsername ))
    get_pcvar_string(g_Cvar[3], szPassword, charsmax( szPassword ))
    get_pcvar_string(g_Cvar[4], szDatabase, charsmax( szDatabase ))

    MYSQL_Tuple = SQL_MakeDbTuple(szHostname, szUsername, szPassword, szDatabase)
    MYSQL_Connect= SQL_Connect(MYSQL_Tuple, szErr, szError, charsmax( szError ))

    if(MYSQL_Connect == Empty_Handle)
        set_fail_state( szError )

    g_ActiveMysql = true
}

public client_connect(id)
{
    if(!is_user_bot(id) || !is_user_hltv(id))
    {
        set_task(1.0, "CheckPlayer", id)
    }
}

public CheckPlayer(id)
{
    if(!g_ActiveMysql)
    {
        set_task(1.0, "PlayerCheck", id)
    }

    new szError[512]
    new szName[32], szMYSQLName[32]
    new Handle:szSelect

    szSelect 
= SQL_PrepareQuery(MYSQL_Connect, "SELECT * FROM players")

    if(!SQL_Execute(szSelect))
    {
        SQL_QueryError(szSelect, szError, charsmax( szError ))
        set_fail_state( szError )
    }

    get_user_name(id, szName, charsmax( szName ))

    while(SQL_MoreResults(szSelect)) //Получаем данные из mysql
    {
        SQL_ReadResult(szSelect, 1, szMYSQLName, charsmax( szMYSQLName ))
    
        if
(equal(szMYSQLName, szName))
        {
            szPlayerRank[id] = SQL_ReadResult(szSelect, 2)
            szPlayerKills[id] = SQL_ReadResult(szSelect, 3)
            szPlayerDeaths[id] = SQL_ReadResult(szSelect, 4)
            szPlayerShots[id] = SQL_ReadResult(szSelect, 5)
            szPlayerHits[id] = SQL_ReadResult(szSelect, 6)
            szPlayerHshots[id] = SQL_ReadResult(szSelect, 7)
            szPlayerMysql[id] = true

            break
        
}else{
            SQL_NextRow(szSelect)
        }
    }    

    if
(!szPlayerMysql[id])
    {
        new Handle:szInsert
        szInsert 
= SQL_PrepareQuery(MYSQL_Connect, "INSERT INTO `players` (`name`, `rank`, `kills`, `deaths`, `shots`, `hits`, `hs`) VALUES  ('%s', '0', '0', '0', '0', '0', '0');", szName)

        if(!SQL_Execute(szInsert))
        {
            SQL_QueryError(szInsert, szError, charsmax( szError ))
            set_fail_state( szError )
        }
        szPlayerMysql[id] = true
    
}
}

public client_disconnect(id)
{

    new szError[512]
    new szName[32]
    new Handle:szUpdateR
    new Handle
:szUpdateK
    new Handle
:szUpdateD
    new Handle
:szUpdateS
    new Handle
:szUpdateH
    new Handle
:szUpdateHs

    new stats
[8],bodyhits[8],irank
    irank 
= get_user_stats(id,stats,bodyhits)

    get_user_name(id, szName, charsmax( szName ))
    szPlayerRank[id] = irank
    szPlayerKills
[id] = stats[0]
    szPlayerDeaths[id] = stats[1]
    szPlayerShots[id] = stats[4]
    szPlayerHits[id] = stats[5]
    szPlayerHshots[id] = stats[2]

    szUpdateR = SQL_PrepareQuery(MYSQL_Connect, "UPDATE `players` SET `rank` = '%d' WHERE `players`.`name` = '%s';", szPlayerRank[id], szName)
    szUpdateK = SQL_PrepareQuery(MYSQL_Connect, "UPDATE `players` SET `kills` = '%d' WHERE `players`.`name` = '%s';", szPlayerKills[id], szName)
    szUpdateD = SQL_PrepareQuery(MYSQL_Connect, "UPDATE `players` SET `deaths` = '%d' WHERE `players`.`name` = '%s';", szPlayerDeaths[id], szName)
    szUpdateS = SQL_PrepareQuery(MYSQL_Connect, "UPDATE `players` SET `shots` = '%d' WHERE `players`.`name` = '%s';", szPlayerShots[id], szName)
    szUpdateH = SQL_PrepareQuery(MYSQL_Connect, "UPDATE `players` SET `hits` = '%d' WHERE `players`.`name` = '%s';", szPlayerHits[id], szName)
    szUpdateHs = SQL_PrepareQuery(MYSQL_Connect, "UPDATE `players` SET `hs` = '%d' WHERE `players`.`name` = '%s';", szPlayerHshots[id], szName)

    if(!SQL_Execute(szUpdateR) & !SQL_Execute(szUpdateK) & !SQL_Execute(szUpdateD) & !SQL_Execute(szUpdateS) & !SQL_Execute(szUpdateH) & !SQL_Execute(szUpdateHs)) 
    
{
        SQL_QueryError(szUpdateR, szError, charsmax( szError ))
        set_fail_state( szError )
        SQL_QueryError(szUpdateK, szError, charsmax( szError ))
        set_fail_state( szError )
        SQL_QueryError(szUpdateD, szError, charsmax( szError ))
        set_fail_state( szError )
        SQL_QueryError(szUpdateS, szError, charsmax( szError ))
        set_fail_state( szError )
        SQL_QueryError(szUpdateH, szError, charsmax( szError ))
        set_fail_state( szError )
        SQL_QueryError(szUpdateHs, szError, charsmax( szError ))
        set_fail_state( szError )
    }
}
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Аватара пользователя
L0L1K
 
Сообщения: 18
Зарегистрирован: 22 апр 2020, 03:31
Благодарил (а): 3 раз.
Поблагодарили: 1 раз.
Опыт программирования: Около 3 месяцев
Языки программирования: Python
C++

Re: Плагин статистики

Сообщение RevCrew » 14 май 2020, 11:09

L0L1K, вау, да это реально генератор лагов. Желательно плагин переписать на асинхронные запросы. А вообще, вы не смотрели в сторону других плагинов с Mysql? как там все сделано?
Аватара пользователя
RevCrew
Скриптер
 
Сообщения: 1648
Зарегистрирован: 15 июл 2013, 20:45
Благодарил (а): 273 раз.
Поблагодарили: 357 раз.
Языки программирования: Unkown

Re: Плагин статистики

Сообщение L0L1K » 14 май 2020, 14:55

RevCrew писал(а):L0L1K, вау, да это реально генератор лагов. Желательно плагин переписать на асинхронные запросы. А вообще, вы не смотрели в сторону других плагинов с Mysql? как там все сделано?


Нет, не изучал)
То есть нужно посмотреть про асинхронные запросы? А ещё какие будут советы?

Добавлено спустя 1 минуту 45 секунд:
Или какой плагин взять для примера, чтобы посмотреть как всё устроено?
Аватара пользователя
L0L1K
 
Сообщения: 18
Зарегистрирован: 22 апр 2020, 03:31
Благодарил (а): 3 раз.
Поблагодарили: 1 раз.
Опыт программирования: Около 3 месяцев
Языки программирования: Python
C++

Re: Плагин статистики  [Решено]

Сообщение RevCrew » 15 май 2020, 11:13

L0L1K, плагинов много, нужно просто найти. Прочитай про SQL_ThreadQuery.
Давай начнем с функции CheckPlayer. Тебе нужна таблица players с полями player_id и player_ip. То есть загружать нужно по айпи и стиму, а не по нику, т.к ник менять можно на любой

Код: Выделить всё
if(is_user_bot(id) || is_user_hltv(id))
        return;

new query[512], Data[1]; Data[0] = id;

formatex(query, charsmax(query), "\
        SELECT * FROM `players`\
        WHERE (`player_id` = '%s' OR `player_ip` = '%s')"
, authid, ip\
        )
    SQL_ThreadQuery(MYSQL_Tuple , "QueryLoadPlayer", query, Data, 1)

public QueryLoadPlayer(FailState,Handle:Query,Error[],Errcode,Data[],DataSize)
{
    if(FailState)
    {
        return SQL_Error(Query, Error, Errcode, FailState);
    }
    
    new id 
= Data[0];
    
    if
(SQL_NumResults(Query) <= 0) {
// Эта функция вносит игрока в базу данных, (запрос Insert)
        Sql_InsertNewPlayer(id)
        return SQL_FreeHandle(Query);
    }

// тут нужно загружать твои данные, в моем случае это выглядит так, у тебя по другому будет
g_player_stats[id][PS_EXP] = SQL_ReadResult(Query, SQL_FieldNameToNum(Query,"exp"));
    return SQL_FreeHandle(Query);
}
Аватара пользователя
RevCrew
Скриптер
 
Сообщения: 1648
Зарегистрирован: 15 июл 2013, 20:45
Благодарил (а): 273 раз.
Поблагодарили: 357 раз.
Языки программирования: Unkown

Re: Плагин статистики

Сообщение L0L1K » 22 май 2020, 01:54

Спасибо, потихоньку разбираюсь)
Аватара пользователя
L0L1K
 
Сообщения: 18
Зарегистрирован: 22 апр 2020, 03:31
Благодарил (а): 3 раз.
Поблагодарили: 1 раз.
Опыт программирования: Около 3 месяцев
Языки программирования: Python
C++

Re: Плагин статистики

Сообщение L0L1K » 22 май 2020, 18:47

RevCrew писал(а):L0L1K, плагинов много, нужно просто найти. Прочитай про SQL_ThreadQuery.
Давай начнем с функции CheckPlayer. Тебе нужна таблица players с полями player_id и player_ip. То есть загружать нужно по айпи и стиму, а не по нику, т.к ник менять можно на любой

Код: Выделить всё
if(is_user_bot(id) || is_user_hltv(id))
        return;

new query[512], Data[1]; Data[0] = id;

formatex(query, charsmax(query), "\
        SELECT * FROM `players`\
        WHERE (`player_id` = '%s' OR `player_ip` = '%s')"
, authid, ip\
        )
    SQL_ThreadQuery(MYSQL_Tuple , "QueryLoadPlayer", query, Data, 1)

public QueryLoadPlayer(FailState,Handle:Query,Error[],Errcode,Data[],DataSize)
{
    if(FailState)
    {
        return SQL_Error(Query, Error, Errcode, FailState);
    }
    
    new id 
= Data[0];
    
    if
(SQL_NumResults(Query) <= 0) {
// Эта функция вносит игрока в базу данных, (запрос Insert)
        Sql_InsertNewPlayer(id)
        return SQL_FreeHandle(Query);
    }

// тут нужно загружать твои данные, в моем случае это выглядит так, у тебя по другому будет
g_player_stats[id][PS_EXP] = SQL_ReadResult(Query, SQL_FieldNameToNum(Query,"exp"));
    return SQL_FreeHandle(Query);
}
 


lite_stats.sma(87) : error 017: undefined symbol "SQL_Error"
lite_stats.sma(94) : error 017: undefined symbol "Sql_InsertNewPlayer"

при компиляции
Аватара пользователя
L0L1K
 
Сообщения: 18
Зарегистрирован: 22 апр 2020, 03:31
Благодарил (а): 3 раз.
Поблагодарили: 1 раз.
Опыт программирования: Около 3 месяцев
Языки программирования: Python
C++

Re: Плагин статистики

Сообщение Baton4ik48 » 22 май 2020, 19:54

L0L1K писал(а):
RevCrew писал(а):L0L1K, плагинов много, нужно просто найти. Прочитай про SQL_ThreadQuery.
Давай начнем с функции CheckPlayer. Тебе нужна таблица players с полями player_id и player_ip. То есть загружать нужно по айпи и стиму, а не по нику, т.к ник менять можно на любой

Код: Выделить всё
if(is_user_bot(id) || is_user_hltv(id))
        return;

new query[512], Data[1]; Data[0] = id;

formatex(query, charsmax(query), "\
        SELECT * FROM `players`\
        WHERE (`player_id` = '%s' OR `player_ip` = '%s')"
, authid, ip\
        )
    SQL_ThreadQuery(MYSQL_Tuple , "QueryLoadPlayer", query, Data, 1)

public QueryLoadPlayer(FailState,Handle:Query,Error[],Errcode,Data[],DataSize)
{
    if(FailState)
    {
        return SQL_Error(Query, Error, Errcode, FailState);
    }
    
    new id 
= Data[0];
    
    if
(SQL_NumResults(Query) <= 0) {
// Эта функция вносит игрока в базу данных, (запрос Insert)
        Sql_InsertNewPlayer(id)
        return SQL_FreeHandle(Query);
    }

// тут нужно загружать твои данные, в моем случае это выглядит так, у тебя по другому будет
g_player_stats[id][PS_EXP] = SQL_ReadResult(Query, SQL_FieldNameToNum(Query,"exp"));
    return SQL_FreeHandle(Query);
}


lite_stats.sma(87) : error 017: undefined symbol "SQL_Error"
lite_stats.sma(94) : error 017: undefined symbol "Sql_InsertNewPlayer"

при компиляции



весь код скинь посмотреть, походу не дописал в начале
Аватара пользователя
Baton4ik48
 
Сообщения: 23
Зарегистрирован: 01 май 2012, 20:06
Благодарил (а): 4 раз.
Поблагодарили: 0 раз.
Опыт программирования: Меньше месяца

Re: Плагин статистики

Сообщение RevCrew » 22 май 2020, 22:18

L0L1K, я скинул не готовый вариант, вам нужно переписать все это под себя

Добавлено спустя 44 секунды:
Рекомендую разобраться с каждой строчкой что я прислал, если будут вопросы, пишите
Аватара пользователя
RevCrew
Скриптер
 
Сообщения: 1648
Зарегистрирован: 15 июл 2013, 20:45
Благодарил (а): 273 раз.
Поблагодарили: 357 раз.
Языки программирования: Unkown

Re: Плагин статистики

Сообщение L0L1K » 23 май 2020, 12:31

Код: Выделить всё
#include <amxmodx>
#include <amxmisc>
#include <csx>
#include <sqlx>

#define PLUGIN "Lite Stats SQL"
#define VERSION "0.1"
#define AUTHOR "L0L1K"

new Handle:MYSQL_Tuple
new Handle
:MYSQL_Connect

new g_Cvar
[5]

new g_ActiveMysql


public plugin_init
() 
{
    register_plugin(PLUGIN, VERSION, AUTHOR)


    g_Cvar[1] = register_cvar("lite_stats_hostname", "db.ds-host.ru") //127.0.0.1
    g_Cvar[2] = register_cvar("lite_stats_username", "w13098_stats")  //root
    g_Cvar[3] = register_cvar("lite_stats_password", "L0l!k123") //password
    g_Cvar[4] = register_cvar("lite_stats_database", "w13098_stats") //testmysql

        set_task(1.0, "MYSQL_Load")
}

public MYSQL_Load()
{
    new szHostname[30], szUsername[30], szPassword[30], szDatabase[30]
    new szError[512], szErr

    get_pcvar_string
(g_Cvar[1], szHostname, charsmax( szHostname ))
    get_pcvar_string(g_Cvar[2], szUsername, charsmax( szUsername ))
    get_pcvar_string(g_Cvar[3], szPassword, charsmax( szPassword ))
    get_pcvar_string(g_Cvar[4], szDatabase, charsmax( szDatabase ))

    MYSQL_Tuple = SQL_MakeDbTuple(szHostname, szUsername, szPassword, szDatabase)
    MYSQL_Connect= SQL_Connect(MYSQL_Tuple, szErr, szError, charsmax( szError ))

    if(MYSQL_Connect == Empty_Handle)
        set_fail_state( szError )

    g_ActiveMysql = true
}

public client_connect(id)
{
    if(!is_user_bot(id) || !is_user_hltv(id))
    {
        set_task(1.0, "CheckPlayer", id)
    }
}

public CheckPlayer(id)
{
    if(!g_ActiveMysql)
    {
        set_task(1.0, "PlayerCheck", id)
    }


    new query[512], Data[1]; Data[0] = id;

    formatex(query, charsmax(query), "\
        SELECT * FROM `players`\
        WHERE (`player_id` = '%s')"
, id\
        )
    SQL_ThreadQuery(MYSQL_Tuple , "QueryLoadPlayer", query, Data, 1)
}

public QueryLoadPlayer(FailState,Handle:Query,Error[],Errcode,Data[],DataSize)
{
    if(FailState)
    {
        return SQL_Error(Query, Error, Errcode, FailState);
    }
    
    new id 
= Data[0];
    
    if
(SQL_NumResults(Query) <= 0) {
// Эта функция вносит игрока в базу данных, (запрос Insert)
        SQL_InsertNewPlayer(id)
        return SQL_FreeHandle(Query);
    }
    new stats[8],bodyhits[8],irank
    irank 
= get_user_stats(id,stats,bodyhits)

// тут нужно загружать твои данные, в моем случае это выглядит так, у тебя по другому будет
    irank = SQL_ReadResult(Query, SQL_FieldNameToNum(Query,"rank"));
        return SQL_FreeHandle(Query);
}


извиняюсь, что торможу)
Аватара пользователя
L0L1K
 
Сообщения: 18
Зарегистрирован: 22 апр 2020, 03:31
Благодарил (а): 3 раз.
Поблагодарили: 1 раз.
Опыт программирования: Около 3 месяцев
Языки программирования: Python
C++

Re: Плагин статистики

Сообщение RevCrew » 23 май 2020, 14:18

L0L1K, структуру таблицы скинь

и
Код: Выделить всё
formatex(querycharsmax(query), "\
        SELECT * FROM `players`\
        WHERE (`player_id` = '%s')"
id\
        ) 

нужно по стим айди или айпи проверять.
Аватара пользователя
RevCrew
Скриптер
 
Сообщения: 1648
Зарегистрирован: 15 июл 2013, 20:45
Благодарил (а): 273 раз.
Поблагодарили: 357 раз.
Языки программирования: Unkown

След.

Вернуться в Скриптинг

Кто сейчас на конференции

Сейчас этот форум просматривают: Bing [Bot] и гости: 13