[Plugin] Rui Almeida Tradutor
#1

Primeiramente, todos os crйditos por idealizaзгo e desenvolvimento do projeto a VeNuZ_

Tуpico oficial: [Include] Rui Almeida Tradutor




Introduзгo

Bom, hoje vim aqui compartilhar um cуdigo que eu tive a satisfaзгo de modificar e tentar melhorar na medida do possнvel, pois foi uma ideia que eu achei muito interessante, alйm de destacar dentre as postagens rotineiras que tem ocorrido na board.

A ideia deste projeto й permitir ao dono do servidor, criar especificaзхes de frases usadas com frequкncia para variadas linguagens de acordo com as suas necessidades. Assim, facilitando e aumentando a acessibilidade/usabilidade do seu servidor por parte dos usuбrios que entram no mesmo, sendo americanos ou brasileiros...

O projeto foi desenvolvido primeiramente em include, atravйs de uma include chamada iString, da qual consta na lib IPSI e que se assemelha ao uso da iBits, aonde o desenvolvedor pode manipular strings e caracteres de forma compacta, economizando o peso do GM em um resultado final incrнvel. Pelo fato da include ainda nгo estar totalmente acabada e ter sido localizado algumas limitaзхes de linguagem, eu optei por desenvolver o projeto atravйs de um plug-in, aonde eu poderia usar uma estrutura de arquivamento dinвmica e mais eficaz.




Mйtodos e suas limitaзхes

A include disponibilizada neste tуpico jб contйm uma breve explicaзгo sobre os mйtodos que constam no plugin, porйm estarei citando um pouco aqui, e as devidas limitaзхes.

Por ser um projeto pequeno e sem visгo exponencial de crescimento na nossa board, nгo trabalhei muito os aspectos de melhorias, e tambйm criei algumas limitaзхes no que diz respeito a quantidade de elementos por arquivo e quantidade de arquivos por instвncia.

Lista de mйtodos:
pawn Код:
/*
*   - CreateLangFile, cria um arquivo de linguagem novo, de acordo com o parвmetro nome
*       Nгo hб limites especificados de arquivos para serem criados com linguagens,
*       a criaзгo de dois arquivos com o mesmo nome pode gerar possibilidades de erro
*       e/ou perda de arquivos anteriores, por isso й recomendado cuidado na chamada deste mйtodo.
*
*       s_nome - representa o nome do arquivo de linguagem, de preferencia um nome que seja
*           prуximo ou igual ao nome da linguagem respectiva. (STRING, 24 char)
*/

/*
*   - ChooseLangFile, seleciona um arquivo para ser carregado em memуria, logo
*       todas as tags inseridas neste arquivo poderгo ser acessadas de maneira simples,
*       fбcil e eficiente, atravйs do mйtodo GetLangText.
*
*       s_nome - representa o nome do arquivo de linguagem, de preferencia um nome que seja
*           prуximo ou igual ao nome da linguagem respectiva. (STRING, 24 char)
*/

/*
*   - InsertLangText, inseri uma tag e seu respectivo valor em uma instвncia de arquivo de
*       linguagem que esteja em aberto atravйs do CreateLangFile (OBS: nгo й possнvel abrir
*       dois arquivos de linguagem simultaneamente, o plugin alertarб por erros nesse quesito.),
*
*       s_tag - representa a tag que serб inserida no arquivo de linguagem (STRING, 15 char)
*       s_value - representa a frase traduzida que serб inserida no arquivo de linguagem (STRING, 128 char)
*/

/*
*   - CloseLangFile, fecha um arquivo de linguagem que tenha sido criado atravйs do CreateLangFile
*       Lembrando que arquivos abertos atravйs do mйtodo ChooseLangFile nгo exigem fechamento,
*       pois os mesmos sгo fechados apуs serem carregados em memуria.
*
*       sem parвmetros.
*/

/*
*   - GetLangText, procura o valor de uma tag atrнbuida ao documento de linguagem selecionado pelo
*       mйtodo ChooseLangFile.
*
*       s_tag - representa a tag que serб pesquisada no arquivo de linguagem (STRING, 15 char)
*       s_value - representa a string do arquivo de linguagem que serб passada por referкncia.
*           (STRING, 128 char)
*
*/
Detalhes tйcnicos:

(-) Limitaзхes
(*) Observaзхes

- Foi limitado a quantidade de tags de traduзгo que podem ser inseridas por linguagem a 200 tags, para evitar excesso de elementos carregados em memуria, mantendo a velocidade do plug-in.
- Foi limitado a quantidade de arquivos abertos por instвncia a 1 arquivo, para evitar que pudessem a abertura de muitos arquivos ao mesmo tempo, gerando possнveis erros, crashs e atй mesmo perda de dados.

*Apуs a criaзгo de um arquivo de linguagem e toda sua inserзгo de tags traduzidas, й necessбrio o fechamento do mesmo.
*Apуs a seleзгo de um arquivo de linguagem pelo ChooseLangFile nгo hб necessidade de fechar o arquivo, pois o mesmo й fechado automaticamente apуs todos os elementos traduzidos serem carregados em memуria




Exemplo de aplicaзхes

Ex1. (Teste para aprendizagem)
pawn Код:
/*
*   - Exemplo utilizando a include Rui Almeida Tradutor
*/


#include <a_samp>
#include <lang>

main()
{
    print("\n----------------------------------");
    print(" Blank Gamemode by your Willian Luigi");
    print("----------------------------------\n");
}

public OnGameModeInit()
{
    // Don't use these lines if it's a filterscript
    SetGameModeText("Blank Script");
    AddPlayerClass(0, 1958.3783, 1343.1572, 15.3746, 269.1425, 0, 0, 0, 0, 0, 0);
   

    //Cria um arquivo de linguagem inglкs
    CreateLangFile("ENG");

    InsertLangText("hello", "Hey welcome to my sv bitche.");

    //fecha a instвncia do arquivo de linguagem aberto.
    CloseLangFile();
   
    CreateLangFile("BR");

    InsertLangText("hello", "Olб, seja bem-vindo ao servidor.");

    //fecha a instвncia do arquivo de linguagem aberto.
    CloseLangFile();
   
    new str[128];
   
    //Carrega o arquivo de linguagem na memуria, todas as tags atй entгo inseridas nele poderгo ser
    //acessadas.
    ChooseLangFile("ENG");
   
    //busca a tag hello inserida no arquivo de linguagem.
    GetLangText("hello", str);

    print(str);
   
    //Carrega o arquivo de linguagem na memуria, todas as tags atй entгo inseridas nele poderгo ser
    //acessadas.
    ChooseLangFile("BR");
   
    //busca a tag hello inserida no arquivo de linguagem.
    GetLangText("hello", str);

    print(str);
   
    return 1;
}
Ex2. (Aplicaзгo em GameMode)
pawn Код:
/*
*   - Exemplo utilizando a include Rui Almeida Tradutor
*/


#include <a_samp>
#include <lang>

main()
{
    print("\n----------------------------------");
    print(" Blank Gamemode by your Willian Luigi");
    print("----------------------------------\n");
}
public OnGameModeInit()
{
    // Don't use these lines if it's a filterscript
    SetGameModeText("Blank Script");
    AddPlayerClass(0, 1958.3783, 1343.1572, 15.3746, 269.1425, 0, 0, 0, 0, 0, 0);
   
   
    CreateLangFile("ENG");

    InsertLangText("hello", "Hey, welcome to my server.");
    InsertLangText("bye", "Bye bye, I hope u get back.");
    InsertLangText("dead", "Oh, you die.");
    InsertLangText("kill", "Uoooouw, u've killed someone.");
    InsertLangText("chat_say", "%s say: %s");

    CloseLangFile();
   
    CreateLangFile("BR");

    InsertLangText("hello", "Olб, seja bem-vindo ao meu servidor.");
    InsertLangText("bye", "Atй mais, espero que vocк volte.");
    InsertLangText("dead", "Oh, vocк morreu.");
    InsertLangText("kill", "OOOOOWWWS, vocк matou alguйm.");
    InsertLangText("chat_say", "%s diz: %s");

    CloseLangFile();
   
    return 1;
}

public OnPlayerConnect(playerid)
{

    SendClientMessage(playerid, -1, "Select your language using /BR - Brazilians or /ENG - Americans");

    return 1;
}

public OnPlayerDisconnect(playerid, reason)
{

    new bye[128];
    GetLangText("bye", bye);
    SendClientMessage(playerid, -1, bye);

    return 1;
}

public OnPlayerDeath(playerid, killerid, reason)
{
    new death[128];
    GetLangText("dead", death);
    SendClientMessage(playerid, -1, death);
    return 1;
}

public OnPlayerText(playerid, text[])
{

    new chat_say[128];
    GetLangText("chat_say", chat_say);
   
    new formatted_string[128];
    new pname[MAX_PLAYER_NAME];
    GetPlayerName(playerid, pname, sizeof(pname));
    format(formatted_string, 128, chat_say, pname, text);
    SendClientMessageToAll(-1, formatted_string);
    return 0;
}

public OnPlayerCommandText(playerid, cmdtext[])
{
    if (strcmp("/BR", cmdtext) == 0)
    {
        ChooseLangFile("BR");
        return 1;
    }
   
    if (strcmp("/ENG", cmdtext) == 0)
    {
        ChooseLangFile("ENG");
        return 1;
    }
    return 0;
}
Esse segundo exemplo, visa um ambiente de servidor real, aonde ocorreria essa comunicaзгo das duas partes, tanto se o player fosse BR, quanto se fosse ENG.




Include/Plug-in source

Ainda nгo tive oportunidade para fazer um upload completo dos pacotes dos projetos utilizados, entгo por enquanto estarei postando apenas os cуdigos fonte aqui.

Include (lang.inc)
pawn Код:
/*
*
*
*       Rui Almeida Tradutor - VeNuZ_
*
*   -LOG:
*   Data de inicio: 15/12/2014
*   Ultima atualizaзгo: 15/12/2014
*
*
*   - CODE.ME, 2013.1 - Willian Luigi
*
*
*/


//definiзгo para constar que sу podem ser inseridas 200 tags em cada linguagem.
#define MAX_TAGS (200)

/*
*   - CreateLangFile, cria um arquivo de linguagem novo, de acordo com o parвmetro nome
*       Nгo hб limites especificados de arquivos para serem criados com linguagens,
*       a criaзгo de dois arquivos com o mesmo nome pode gerar possibilidades de erro
*       e/ou perda de arquivos anteriores, por isso й recomendado cuidado na chamada deste mйtodo.
*
*       s_nome - representa o nome do arquivo de linguagem, de preferencia um nome que seja
*           prуximo ou igual ao nome da linguagem respectiva. (STRING, 24 char)
*/

native CreateLangFile(s_nome[]);

/*
*   - ChooseLangFile, seleciona um arquivo para ser carregado em memуria, logo
*       todas as tags inseridas neste arquivo poderгo ser acessadas de maneira simples,
*       fбcil e eficiente, atravйs do mйtodo GetLangText.
*
*       s_nome - representa o nome do arquivo de linguagem, de preferencia um nome que seja
*           prуximo ou igual ao nome da linguagem respectiva. (STRING, 24 char)
*/

native ChooseLangFile(s_nome[]);

/*
*   - InsertLangText, inseri uma tag e seu respectivo valor em uma instвncia de arquivo de
*       linguagem que esteja em aberto atravйs do CreateLangFile (OBS: nгo й possнvel abrir
*       dois arquivos de linguagem simultaneamente, o plugin alertarб por erros nesse quesito.),
*
*       s_tag - representa a tag que serб inserida no arquivo de linguagem (STRING, 15 char)
*       s_value - representa a frase traduzida que serб inserida no arquivo de linguagem (STRING, 128 char)
*/

native InsertLangText(s_tag[], s_value[]);

/*
*   - CloseLangFile, fecha um arquivo de linguagem que tenha sido criado atravйs do CreateLangFile
*       Lembrando que arquivos abertos atravйs do mйtodo ChooseLangFile nгo exigem fechamento,
*       pois os mesmos sгo fechados apуs serem carregados em memуria.
*
*       sem parвmetros.
*/

native CloseLangFile();

/*
*   - GetLangText, procura o valor de uma tag atrнbuida ao documento de linguagem selecionado pelo
*       mйtodo ChooseLangFile.
*
*       s_tag - representa a tag que serб pesquisada no arquivo de linguagem (STRING, 15 char)
*       s_value - representa a string do arquivo de linguagem que serб passada por referкncia.
*           (STRING, 128 char)
*
*/

native GetLangText(s_tag[], s_value[]);

forward IsValidLangFile(s_nome[]);
public IsValidLangFile(s_nome[])
{
    new n[15 + 30];
    format(n, sizeof(n), "translatedmsgs/%s.dat", s_nome);
    return fexist(n);
}
Plug-in (lang.dll)
pawn Код:
/*
*
*
*       Rui Almeida Tradutor - VeNuZ_
*
*   -LOG:
*   Data de inicio: 15/12/2014
*   Ultima atualizaзгo: 15/12/2014
*
*
*   - CODE.ME, 2013.1 - Willian Luigi
*
*
*/


#define _CRT_SECURE_NO_WARNINGS
#include <Windows.h>
#include <string>

#include "SDK\amx\amx.h"
#include "SDK\plugincommon.h"

typedef void (*logprintf_t)(char* format, ...);

#define PATTERN_LOCATION "scriptfiles/translatedmsgs/"

//Definiзхes de valores mбximos utilizados pela include
#define MAX_STRING_DISPLAY  128 //O valor mбximo de caracteres que sгo mostrados na tela de conversaзгo
#define MAX_LANG_NAME       24  //O valor mбximo de caracteres para se usar no nome das linguagens
#define MAX_TAG             15  //O valor mбximo de caracteres para se usar na TAG

struct LangStruct
{
    char L_TEXT[MAX_STRING_DISPLAY];
    char L_TAG[MAX_TAG];
};

LangStruct lang_selected[200];
FILE *file;

logprintf_t logprintf;
extern void *pAMXFunctions;


//Mйtodos utilizados para criaзгo de arquivos da linguagem

int _ERROR(int _err)
{
    switch (_err)
    {
        case 1:
        {
            logprintf("[ERRO .1] - Nгo foi possнvel criar o arquivo.");
            break;
        }
        case 2:
        {
            logprintf("[ERRO .2] - Algum arquivo de linguagem nгo foi fechado corretamente.");     
            break;
        }
        case 3:
        {
            logprintf("[ERRO .3] - Nгo hб nenhum arquivo de linguagem aberto.");
            break;
        }
        case 4:
        {
            logprintf("[ERRO .4] - Arquivo de linguagem inexistente.");
            break;
        }
    }

    return (0);
}

cell AMX_NATIVE_CALL CreateLangFile(AMX* amx, cell* params)
{

    if (file != NULL)
    {
        return (_ERROR(2));
    }

    cell *addr;
    char file_name[27 + MAX_LANG_NAME], tmp[MAX_LANG_NAME];
    int szFile;

    amx_GetAddr(amx, params[1], &addr);
    amx_StrLen(addr, &szFile);
    amx_GetString(tmp, addr, 0, szFile + 1);
    sprintf(file_name, "%s%s.dat", PATTERN_LOCATION, tmp);

    file = fopen(file_name, "ab+");

    if (file == NULL)
    {
        return (_ERROR(1));
    }

    return (1);
}

cell AMX_NATIVE_CALL InsertLangText(AMX* amx, cell* params)
{
    if (file == NULL)
    {
        return (_ERROR(3));
    }

    cell *addr[2] = {NULL, NULL};
    int szLang_text, szLang_tag;

    LangStruct _l;

    amx_GetAddr(amx, params[1], &addr[0]);
    amx_GetAddr(amx, params[2], &addr[1]);
    amx_StrLen(addr[0], &szLang_tag);
    amx_StrLen(addr[1], &szLang_text);
    amx_GetString(_l.L_TAG, addr[0], 0, szLang_tag + 1);
    amx_GetString(_l.L_TEXT, addr[1], 0, szLang_text + 1);

    fwrite(&_l, sizeof(LangStruct), 1, file);

    return (1);
}

cell AMX_NATIVE_CALL CloseLangFile(AMX* amx, cell* params)
{
    if (file == NULL)
    {
        return (_ERROR(3));
    }

    fclose(file);
    file = NULL;

    return (1);
}

cell AMX_NATIVE_CALL ChooseLangFile(AMX* amx, cell* params)
{
    if (file != NULL)
    {
        return (_ERROR(2));
    }

    char file_name[27 + MAX_LANG_NAME], tmp[MAX_LANG_NAME];
    int szFile;
    cell *addr;
    FILE *ftmp;
   
    amx_GetAddr(amx, params[1], &addr);
    amx_StrLen(addr, &szFile);
    amx_GetString(tmp, addr, 0, szFile + 1);
    sprintf(file_name, "%s%s.dat", PATTERN_LOCATION, tmp);
    ftmp = fopen(file_name, "rb");

    if (ftmp == NULL)
    {
        return (_ERROR(4));
    }

    int i = 0;
    do
    {  
        fread(&lang_selected[i], sizeof(LangStruct), 1, ftmp);
       
        i++;
    } while(!feof(ftmp));

    fclose(ftmp);
    return (1);
}

cell AMX_NATIVE_CALL GetLangText(AMX* amx, cell* params)
{
    cell *addr[2] = {NULL, NULL};
    char tag[MAX_TAG];
    int szTag;

    amx_GetAddr(amx, params[1], &addr[0]);
    amx_GetAddr(amx, params[2], &addr[1]);
    amx_StrLen(addr[0], &szTag);
    amx_GetString(tag, addr[0], 0, szTag + 1);

    for (int i = 0; i < sizeof(lang_selected); ++i)
    {
        if (!strcmp(lang_selected[i].L_TAG, tag))
        {
            amx_SetString(addr[1], lang_selected[i].L_TEXT, 0, 0, strlen(lang_selected[i].L_TEXT) + 1);
            break;
        }
    }

    return (1);
}

PLUGIN_EXPORT unsigned int PLUGIN_CALL Supports()
{
    return SUPPORTS_VERSION | SUPPORTS_AMX_NATIVES | SUPPORTS_PROCESS_TICK;
}

PLUGIN_EXPORT bool PLUGIN_CALL Load(void **ppData)
{
    pAMXFunctions = ppData[PLUGIN_DATA_AMX_EXPORTS];
    logprintf = (logprintf_t) ppData[PLUGIN_DATA_LOGPRINTF];

    logprintf("\n==============================\n");
    logprintf(" * Rui Almeida Tradutor loaded.\n");
    logprintf(" © - 2014 Willian Luigi");
    logprintf("\n==============================\n");
    return true;
}

PLUGIN_EXPORT void PLUGIN_CALL Unload()
{
    logprintf("\n==============================\n");
    logprintf(" * Rui Almeida Tradutor unloaded.\n");
    logprintf(" © - 2014 Willian Luigi");
    logprintf("\n==============================\n");
}

AMX_NATIVE_INFO PluginNatives[] =
{
    {"CreateLangFile", CreateLangFile},
    {"ChooseLangFile", ChooseLangFile},
    {"InsertLangText", InsertLangText},
    {"GetLangText", GetLangText},
    {"CloseLangFile", CloseLangFile},
    {0, 0}
};

PLUGIN_EXPORT int PLUGIN_CALL AmxLoad( AMX *amx )
{
    return amx_Register(amx, PluginNatives, -1);
}


PLUGIN_EXPORT int PLUGIN_CALL AmxUnload( AMX *amx )
{
    return AMX_ERR_NONE;
}



Conclusгo

Para os usuбrios, lembrando que й necessбrio criar uma pasta dentro de scriptfiles, nome: "translatedmsgs"

Link para download do plugin: lang.dll




Crйditos

VeNuZ_, como citado no comeзo.
Willian_Luigi, desenvolvimento do plug-in.
Reply
#2

Muito bom capivara, й isso aн!


Код:
REP[Willian_Luigi] += 2;
Reply
#3

Vocкs que desenvolveram o plugin?

Se sim, parapenis, caso nгo, parapenis igual!!

Curti bastante! booa
Reply
#4

Poderia ter feito tambem o IsValidLangFile.

De qualquer forma agora esta muito melhor, parabйns e bom trabalho.
Reply
#5

Bom trabalho!
sу 2 coisas a apontar:
nгo precisas do SUPPORTS_PROCESS_TICK no PLUGIN_CALL Supports
Nгo precisas da callback Unload()
Reply
#6

Quote:
Originally Posted by PT
Посмотреть сообщение
Poderia ter feito tambem o IsValidLangFile.
Se o problema todo era esse, jб pode usar, implementei especialmente para vocк.

Abraзos.
Reply
#7

Ai que delicia gosti XisDe
Reply
#8

Bacana e ъtil...mas uma dъvida, quando o mesmo й criado apуs o servidor ser executado, tudo que foi criado atй entгo й deletado quando o servidor fecha? Caso nгo for, nгo seria necessбrio cria-lo toda vez que o servidor ser executado...bastaria checar pela nova funзгo implementada IsValidLangFile se todos os arquivos usados existem, logo, se nгo existirem, cria-los.

Novamente parabйns aos dois, ambos reputados.

@OFF De volta no fуrum entгo й estudante? Hehe abзs.
Reply
#9

Quote:
Originally Posted by Bruno13
Посмотреть сообщение
Bacana e ъtil...mas uma dъvida, quando o mesmo й criado apуs o servidor ser executado, tudo que foi criado atй entгo й deletado quando o servidor fecha? Caso nгo for, nгo seria necessбrio cria-lo toda vez que o servidor ser executado...bastaria checar pela nova funзгo implementada IsValidLangFile se todos os arquivos usados existem, logo, se nгo existirem, cria-los.

@OFF De volta no fуrum entгo й estudante? Hehe abзs.
Os arquivos nгo sгo deletados ao fechar o servidor, o fato de eu usar aquela implementaзгo, foi pra exemplificar como utilizar as funзхes tanto para criaзгo e escolha de arquivos de linguagem.


Mas em uma implementaзгo real para o seu servidor, vocк executa estб parte apenas uma vez e depois verifica se jб existe, exatamente como vocк falou...


De volta aos poucos, hehe..
Reply
#10

Parabйns wilian, achei bastante interessante o plugin.

+Rep para vocк.

@Edit

Nгo tou conseguindo te dar rep. ._.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)