Introdução
O YSI não é apenas uma biblioteca poderosa para escrever modos de jogo e scripts de filtro, mas também possui muitos recursos que podem tornar suas próprias bibliotecas muito melhores. Este tutorial apresentará quatro deles: y_hooks, y_master, y_playerarray e y_groups.
Este tutorial seguirá o desenvolvimento de uma biblioteca muito simples que permite criar um desenho de texto e mostrá-lo apenas a determinados jogadores. Este é um exemplo artificial, mas servirá. O resultado final terá um código como:
Código do peão:O YSI não é apenas uma biblioteca poderosa para escrever modos de jogo e scripts de filtro, mas também possui muitos recursos que podem tornar suas próprias bibliotecas muito melhores. Este tutorial apresentará quatro deles: y_hooks, y_master, y_playerarray e y_groups.
Este tutorial seguirá o desenvolvimento de uma biblioteca muito simples que permite criar um desenho de texto e mostrá-lo apenas a determinados jogadores. Este é um exemplo artificial, mas servirá. O resultado final terá um código como:
- Código:
novo
Grupo : g = Group_Create ( "tds" ) ,
Texto : t = TextDrawCreate ( 20.0 , 20.0 , "Olá" ) ;
Group_SetTextDraw ( g, _ : t, verdadeiro ) ;
Group_SetGlobalTextDraw ( _ : t, false ) ;
TextDrawShow ( t ) ;
Esse código cria um grupo YSI e um desenho de texto, em seguida, define apenas um único grupo para poder ver o desenho de texto e mostra o desenho de texto para todos com permissão para vê-lo (o único grupo).
y_playerarray
y_playerarray cria um array de bits de jogadores para salvar na memória. É um pouco diferente de uma matriz de bits regular, pois o primeiro slot completo é reservado. As razões para isso não são relevantes para este tutorial, mas têm a ver com futuras bibliotecas YSI não lançadas.
Código do peão:y_playerarray
y_playerarray cria um array de bits de jogadores para salvar na memória. É um pouco diferente de uma matriz de bits regular, pois o primeiro slot completo é reservado. As razões para isso não são relevantes para este tutorial, mas têm a ver com futuras bibliotecas YSI não lançadas.
- Código:
#include <a_samp>
#include <YSI\y_playerarray>
- Código:
new
PlayerArray : g_players [ Texto : MAX_TEXT_DRAWS ] < MAX_PLAYERS > ;
Isso declarará uma matriz grande o suficiente para conter dados sobre quem pode ver o que o texto desenha (ou quem tem permissão). Para adicionar um jogador faça:
Código do peão:- Código:
PA + ( g_players [ td ] ,playerid ) ;
Para remover um faça:
Código do peão:- Código:
PA- ( g_players [ td ] , playerid ) ;
y_hooks
O que é y_hooks? É um método para conectar callbacks em sua biblioteca. Quando um novo jogador se conecta ao seu servidor, ele não pode ver nenhum desenho de texto. Isso requer conectar o OnPlayerConnect para redefinir os dados:
Código do peão:O que é y_hooks? É um método para conectar callbacks em sua biblioteca. Quando um novo jogador se conecta ao seu servidor, ele não pode ver nenhum desenho de texto. Isso requer conectar o OnPlayerConnect para redefinir os dados:
- Código:
#include <a_samp>
#include <YSI\y_playerarray>
#include <YSI\y_hooks>
- Código:
new
PlayerArray : g_players [ Texto : MAX_TEXT_DRAWS ] < MAX_PLAYERS > ;
Gancho : TextDraw_OnPlayerConnect ( playerid )
{
for ( new i = 0 ; i != MAX_TEXT_DRAWS; ++ i )
{
PA- ( g_players [ Texto : i ] , playerid );
}
}
Simples. Esse é o tipo de coisa comum às bibliotecas - redefinir um player quando ele se conecta, isso apenas torna um pouco mais fácil.
Código extra
Neste ponto, definirei apenas algum código extra para fazer a biblioteca fazer algo:
Código do peão:Código extra
Neste ponto, definirei apenas algum código extra para fazer a biblioteca fazer algo:
- Código:
#include <a_samp>
#include <YSI\y_playerarray>
#include <YSI\y_hooks>
#include <YSI\y_iterate>
- Código:
new
PlayerArray : g_players [ Texto : MAX_TEXT_DRAWS ] < MAX_PLAYERS > ;
Gancho : TextDraw_OnPlayerConnect ( playerid )
{
for ( new i = 0 ; i != MAX_TEXT_DRAWS; ++ i )
{
PA - ( g_players [ Texto : i ], id do jogador ) ;
}
}
- Código:
stock Text : TextDraw_Create ( Float : x, Float : y, str [ ] )
{
new
Text : td = TextDrawCreate ( x, y, str ) ;
PA_Init ( g_players [ td ] ,falso ) ;
retorno td;
}
- Código:
#define TextDrawCreate TextDraw_Create
- Código:
stock TextDrawShow ( Text : td)
{
foreach ( Jogador, id do jogador )
{
if ( PA = ( g_players [ td ] , id do jogador ) )
{
TextDrawShowForPlayer ( id do jogador, td ) ;
}
}
}
- Código:
stock TextDraw_SetPlayer ( td, playerid, bool : set )
{
if ( set ) PA + ( g_players [ Text : td ], id do jogador ) ;
else PA- ( g_players [ Texto : td ] , playerid ) ; }
No código acima, "TextDraw_Create" está fora da função de criação personalizada que cria um novo desenho de texto e define todos os jogadores como falsos. Em seguida, redefine "TextDrawCreate" para chamar nossa função personalizada. A segunda função percorre todos os jogadores e exibe o desenho de texto apenas para os jogadores selecionados. A função final adiciona ou remove um jogador de um desenho de texto.
y_master
y_master é um sistema de distribuição. O que isso significa é que, se você incluir uma biblioteca usando o sistema mestre YSI em vários scripts, todos eles se comunicarão. Queremos poder adicionar e remover jogadores de desenhos de texto em qualquer script, então precisamos usar o sistema mestre:
Código do peão:y_master
y_master é um sistema de distribuição. O que isso significa é que, se você incluir uma biblioteca usando o sistema mestre YSI em vários scripts, todos eles se comunicarão. Queremos poder adicionar e remover jogadores de desenhos de texto em qualquer script, então precisamos usar o sistema mestre:
- Código:
#include <a_samp>
#include <YSI\y_playerarray>
#include <YSI\y_hooks>
#include <YSI\y_iterate>
#define MASTER 7
#include <YSI\y_master>
- Código:
new
PlayerArray : g_players [ Text : MAX_TEXT_DRAWS ] < MAX_PLAYERS > ;
- Código:
RH : TextDraw_OnPlayerConnect [ i ] ( playerid )
{
for ( novo i = 0 ; i ! = MAX_TEXT_DRAWS; ++ i )
{
PA-( g_players [ Texto : i ] , playerid ) ;
}
}
- Código:
RF @ pt : Text : TextDraw_Create [ ffs ] ( Float : x, Float : y, str [ ] ) < x, y, str >
{
new
Text : td = TextDrawCreate ( x, y, str ) ;
PA_Init ( g_players [ td ] , falso) ;
retorno td;
}
- Código:
#define TextDrawCreate TextDraw_Create
- Código:
RF : TextDrawShow [ i ] ( Text : td )
{
foreach ( Player, playerid )
{
if ( PA = ( g_players [ td ] , playerid ) )
{
TextDrawShowForPlayer ( playerid, td ) ;
}
}
}
- Código:
RF : TextDraw_SetPlayer [ iii] ( td, playerid, bool : set )
{
if ( set ) PA + ( g_players [ Text : td ] , playerid ) ;
else PA- ( g_players [ Texto : td ] , playerid ) ; }
Deve ficar bastante claro olhando para o código acima que não mudou muito - mas muitas mudanças importantes aconteceram.
Código do peão:- Código:
#define MASTER 7
#include <YSI\y_master>
Isso inclui o sistema mestre e define um valor mestre exclusivo para ele. Se você tiver dois scripts em execução e ambos tiverem um streamer de ponto de verificação e um streamer de objeto, você precisa de uma maneira para os streamers cp se comunicarem e os streamers de objeto se comunicarem, mas para não se confundirem entre si. É para isso que serve o ID mestre. Neste caso, estamos usando 7, portanto, todos os scripts que incluem sua biblioteca devem usar 7 para identificar exclusivamente sua biblioteca.
Código do peão:- Código:
RH : TextDraw_OnPlayerConnect [ i ] ( playerid )
Aqui "Hook:" mudou para "RH:" - essa é mais ou menos a única mudança aqui. Como vários scripts incluem sua biblioteca, vários scripts têm todo o código de sua biblioteca. Quando o servidor inicia, todos esses scripts conversam entre si e decidem quem será o responsável, para que todo o código seja feito apenas uma vez. O uso de "RH:" garante que esse gancho seja chamado apenas pelo script responsável.
Código do peão:- Código:
RF @ pt : Text : TextDraw_Create [ ffs ] ( Float : x, Float : y, str [ ] ) < x, y, str >
Esta é a parte mais complexa. "RF" define uma "Função Remota" - como acabei de dizer, vários scripts podem ter o mesmo código, mas apenas um deve ser executado. Isso significa que todos os outros scripts devem encaminhar suas chamadas para o principal e retornar o que ele disser. Um exemplo básico disso é:
Código do peão:- Código:
RF : PrintNumber [ i ] ( n )
{
printf ( "Número: %d" , n ) ;
}
Se todos os seus scripts incluírem que todos podem chamar esta função, mas apenas um script irá executá-la, o que significa que os dados locais podem ser usados. O formato é "RF:FUNCTION_NAME[PARAMETER_TYPES](PARAMETERS}" - os tipos de parâmetro são as letras que apareceriam em CallRemoteFunction (pois é exatamente isso que são). Algumas funções, entretanto, são um pouco mais complicadas, especialmente aquelas com strings. Se
você tem uma string que seus parâmetros contêm "[]" - no entanto, isso não é válido em "CallRemoteFunction", então você precisa usar a versão "parametrizada" de "RF", que é "RF@p":
Código do peão:você tem uma string que seus parâmetros contêm "[]" - no entanto, isso não é válido em "CallRemoteFunction", então você precisa usar a versão "parametrizada" de "RF", que é "RF@p":
- Código:
RF @ p : PrintString [ s ] ( str [ ] ) < str >
{
printf ( "String: %s" , str ) ;
}
Isso adiciona uma parte extra ao final da definição da função com o nome da variável. Todas as outras funções não usam "RF@p", mas poderiam fazer para remover os dados da tag nas variáveis:
Código do peão:- Código:
RF @ p : TextDraw_SetPlayer [ iii ] ( td, playerid, bool : set ) < td, playerid, set >
"RF@t" é uma função que retorna uma tag, como "TextDraw_Create" faz, você também pode misturar modificadores, que é de onde vem "RF@pt" (ou "RF@tp"). O outro modificador principal é "c", que define uma versão mais curta da macro caso o código gerado seja muito longo (geralmente resulta em uma falha do compilador). Portanto, você pode acabar com "RF@pct" para nomes de função muito longos.
y_groups
Se você escrever uma biblioteca personalizada, poderá usar o sistema de grupos para definir os controles de acesso aos seus recursos. O sistema de grupo é, na verdade, um wrapper em torno das permissões normais do player, portanto, você deve fornecer uma função chamada "Library_SetPlayer". O seguinte é uma implementação mínima de uma biblioteca que agora pode usar o sistema de grupos. A biblioteca usa o prefixo "Custom"
Código do peão:y_groups
Se você escrever uma biblioteca personalizada, poderá usar o sistema de grupos para definir os controles de acesso aos seus recursos. O sistema de grupo é, na verdade, um wrapper em torno das permissões normais do player, portanto, você deve fornecer uma função chamada "Library_SetPlayer". O seguinte é uma implementação mínima de uma biblioteca que agora pode usar o sistema de grupos. A biblioteca usa o prefixo "Custom"
- Código:
#include <a_samp>
#include <YSI\y_playerarray>
#include <YSI\y_hooks>
#include <YSI\y_iterate>
- Código:
#define MASTER 7
#include <YSI\y_master>
- Código:
#define _GROUP_MAKE_NAME_INTTEST<%0...%1> % 0TextDraw%1
#define _GROUP_MAKE_LIMIT_INTTEST MAX_TEXT_DRAWS
#include <YSI\y_groups>
- Código:
new
PlayerArray : g_players [ Text : MAX_TEXT_DRAWS ] < MAX_PLAYERS > ;
RH :
for ( new i = 0 ; i != MAX_TEXT_DRAWS; ++ i )
{
PA - ( g_players [ Text : i ] , playerid ) ;
}
}
}
- Código:
RF @ pt : Text : TextDraw_Create [ ffs ] ( Float : x, Float : y, str [ ] ) < x, y, str >
{
novo
Text : td = TextDrawCreate ( x, y, str ) ;
NO_GROUPS ( _ : td )
{
PA_Init ( g_players [ td ] , false ) ;
}
return td;
}
- Código:
#define TextDrawCreate TextDraw_Create
- Código:
RF : TextDrawShow [ i ] ( Text : td )
{
foreach ( Player, playerid )
{
if ( PA= ( g_players [ td ] , playerid ) )
{
TextDrawShowForPlayer ( playerid, td ) ;
}
}
}
- Código:
RF : TextDraw_SetPlayer [ iii ] ( td, playerid, bool : set )
{
if ( set ) PA + ( g_players [ Text : td ] , playerid ) ;
senão PA - (g_players [ Texto : td ] , playerid ) ;
}
- Código:
#undef _GROUP_MAKE_NAME_INTTEST
#undef _GROUP_MAKE_LIMIT_INTTEST
Realmente não mudou muito aqui:
Código do peão:- Código:
#define _GROUP_MAKE_NAME_INTTEST<%0...%1> %0TextDraw%1
#define _GROUP_MAKE_LIMIT_INTTEST MAX_TEXT_DRAWS
#include <YSI\y_groups>
Isso inclui a biblioteca de grupos e define o padrão que as funções devem assumir. Essas três linhas sozinhas definem as seguintes funções:
Código do peão:- Código:
Group_SetTextDraw ( Grupo : grupo, elemento, bool : conjunto ) ;
Group_SetGlobalTextDraw ( elemento, bool : conjunto ) ;
Group_SetTextDrawDefault ( Grupo : grupo, bool : conjunto ) ;
Group_SetGlobalTextDrawDefault ( bool : set ) ;
Observe que não há nenhuma tag "Texto:", mas isso é outro assunto e uma limitação atual da biblioteca de grupos. Agora você pode usar todas as funções de grupo padrão para definir quem pode usar seu sistema.
Código do peão:- Código:
NO_GROUPS ( )
{
for ( new i = 0 ; i != MAX_TEXT_DRAWS; ++ i )
{
PA - ( g_players [ Text : i ] , playerid ) ;
}
}
Dentro do YSI, o sistema de grupos é totalmente opcional. Se você usar este método, o sistema de grupos será incluído inteiramente, mas o padrão "NO_GROUPS" ainda é válido. Você pode apenas remover seu próprio código de inicialização inteiramente aqui - ele só será chamado se os grupos não estiverem definidos, mas estão.
Código do peão:- Código:
NO_GROUPS ( _ : td )
{
PA_Init ( g_players [ td ] , false ) ;
}
O mesmo se aplica aqui - se não houver grupos, use o código de inicialização personalizado, caso contrário, inicialize este novo desenho de texto (em "td") usando o código da biblioteca de grupos.
Observe que o sistema y_groups usa sua função "TextDraw_SetPlayer" para chamar seu código de acesso básico por jogador - por isso é muito importante que essa função exista e tenha esses parâmetros exatos (ou seja, item, playerid, conjunto).
Conclusões
Esta foi uma breve introdução ao uso do YSI para escrever bibliotecas dinâmicas, e usar esses recursos fornece acesso direto a recursos como salvamento automático de grupo na biblioteca do usuário YSI, etc. Este tutorial foi principalmente um exemplo simples construído, mas mostra o básico sem considerar. Qualquer informação adicional é só perguntar aqui ou ler as inclusões relevantes (desafio você a procurar em y_groups e y_master).
Observe que o sistema y_groups usa sua função "TextDraw_SetPlayer" para chamar seu código de acesso básico por jogador - por isso é muito importante que essa função exista e tenha esses parâmetros exatos (ou seja, item, playerid, conjunto).
Conclusões
Esta foi uma breve introdução ao uso do YSI para escrever bibliotecas dinâmicas, e usar esses recursos fornece acesso direto a recursos como salvamento automático de grupo na biblioteca do usuário YSI, etc. Este tutorial foi principalmente um exemplo simples construído, mas mostra o básico sem considerar. Qualquer informação adicional é só perguntar aqui ou ler as inclusões relevantes (desafio você a procurar em y_groups e y_master).
Creditos:Misiur