Olá a todos, eu sempre acompanho o SAMPVOICE e sua equipe e sempre tentei adiciona-lo ao 0.3.dl, porém, o problema vem sempre através da parte do client, no caso os arquivos da pasta não se conectam no servidor, dando o erro de que o jogador não está com a versão correta do plugin.
Alguém poderia me ajudar?
(Já vi vários 0.3.DL por ai com o sampvoice, porém, nunca divulgaram)
Citar:- Sincronização de dados;
- Funções Get*;
- Mundos virtuais e processo de "streaming";
- Pool interna de processamento de RPCs.
- Dessincronização.
• Sincronização de dados.
Citar:Todos os dados como posição, arma atual e velocidade vem em pacotes. Ou mais precisamente no caso de UDP, datagramas. Cada datagrama contém uma ou mais mensagens, podendo ser vida, posição atual, entre outros.
Cada pacote é identificado pelos seus primeiros 8 bits (1 byte), que nesse caso é o seu identificador numérico. Existem diferentes tipos de pacotes contendo diferentes mensagens/dados em si, sendo:
ID_PLAYER_SYNC (ID: 207) - Um pacote com este identificador numérico é responsável por atualizações a pé, dos jogadores. Este pacote sempre será enviado APENAS se o jogador estiver a pé, e é enviado a cada um segundo se o jogador não estiver se movendo. A sua estrutura de dados é a seguinte:
lrKey - Seta para esquerda/direita (←→) - Se a tecla atual for seta para esquerda, então lrKey se iguala a KEY_LEFT, caso contrário KEY_RIGHT. 0 se nenhum dos casos.
udKey - Seta para cima/baixo (↑↓) - Se a tecla atual for seta para cima, então lrKey se iguala a KEY_UP, caso contrário KEY_DOWN. 0 se nenhum dos casos.
keys - Um mapa (bitmask) com as teclas pressionadas.
position[3] - Posição atual (X, Y, Z).
quaternion[4] - Quaterniões de rotação (W, X, Y, Z).
health - Vida atual do jogador.
armour - Colete atual do jogador.
weaponId - Arma atual do jogador.
additionalKey - Tecla adicional.
specialAction - Ação especial.
velocity[3] - Velocidade nos eixos X, Y e Z.
surfingOffsets[3] - Offsets de surfing em um veículo - 0.0 em todas as offsets se o jogador não estiver surfando um veículo.
surfingVehicleId - O ID do veículo que o jogador está surfando (0 se nenhum).
animationId - ID da animação atual.
animationFlags - Flags da animação atual.
ID_VEHICLE_SYNC (ID: 200) - Um pacote com este identificador numérico é responsável por atualizações do jogador dentro de um veículo (como motorista). A sua estrutura de dados é a seguinte:
vehicleId - ID de veículo atual.
lrKey - Seta para esquerda/direita (←→) - Se a tecla atual for seta para esquerda, então lrKey se iguala a KEY_LEFT, caso contrário KEY_RIGHT. 0 se nenhum dos casos.
udKey - Seta para cima/baixo (↑↓) - Se a tecla atual for seta para cima, então lrKey se iguala a KEY_UP, caso contrário KEY_DOWN. 0 se nenhum dos casos.
keys - Um mapa (bitmask) com as teclas pressionadas.
quaternion[4] - Quaterniões de rotação do veículo (W, X, Y, Z).
position[3] - Posição atual (X, Y, Z)
velocity[3] - Velocidade nos eixos X, Y e Z.
vehicleHealth - Vida atual do veículo.
playerHealth - Vida do jogador.
armour - Colete do jogador.
weaponId - Arma atual do jogador.
additionalKey - Tecla adicional.
sirenState - Estado da sirene do veículo.
landingGearState - Estado do trem de pouso (dado também utilizado por veículos como empilhadeira para representar o estado do garfo/forquilha).
trailerId - ID de trailer anexado ao veículo (0 se nenhum).
trainSpeed - Velocidade do trem (dado utilizado por trens).
ID_PASSENGER_SYNC (ID: 211) - Um pacote com este identificador numérico é responsável por atualizações do jogador dentro de um veículo (como passageiro). A sua estrutura de dados é a seguinte:
vehicleId - ID de veículo atual. seatId - Número do assento atual. driveBy - 0 se o jogador não estiver em modo de drive-by, caso contrário 1. weaponId - ID de arma atual. additionalKey - Tecla adicional. playerHealth - Vida do jogador. playerArmour - Colete do jogador.
lrKey - Seta para esquerda/direita (←→) - Se a tecla atual for seta para esquerda, então lrKey se iguala a KEY_LEFT, caso contrário KEY_RIGHT. 0 se nenhum dos casos.
udKey - Seta para cima/baixo (↑↓) - Se a tecla atual for seta para cima, então lrKey se iguala a KEY_UP, caso contrário KEY_DOWN. 0 se nenhum dos casos.
keys - Um mapa (bitmask) com as teclas pressionadas.
position[3] - Posição atual do jogador (X, Y, Z).
ID_AIM_SYNC (ID: 203) - Um pacote com este identificador numérico é responsável por atualizações relacionadas com a câmera/mira do jogador. A sua estrutura de dados é a seguinte:
ID_BULLET_SYNC (ID: 206) - Um pacote com este identificador numérico é responsável por atualizações de tiros/balas disparados por um jogador. A sua estrutura de dados é a seguinte:
hitId - ID do veículo, objeto ou jogador que levou o tiro.
origin[3] - Origem da bala.
hitPos[3] - Posição de acerto.
offsets[3] - offsets da bala.
weaponId - ID da arma que a bala pertence.
ID_TRAILER_SYNC (ID: 210) - Um pacote com este identificador numérico é responsável por atualizações de trailers anexados a veículos sendo utilizados por jogadores. A sua estrutura de dados é a seguinte:
trailerId - ID do trailer anexado.
position[3] - Posição atual (X, Y, Z).
quaternion[4] - Quaterniões de rotação do trailer (W, X, Y, Z).
velocity[3] - Velocidade nos eixos X, Y e Z.
angularVelocity[3] - Velocidade angular.
ID_WEAPONS_UPDATE (ID: 204) - Um pacote com este identificador numérico é responsável por atualizações de balas e armas em todas as slots. A sua estrutura de dados é a seguinte:
slot[12] - Slot.
arma0[12] - ID da arma.
balas0[12] - Quantidade de balas.
ID_RCON_COMMAND (ID: 201) - Um pacote com este identificador numérico é responsável por mandar tentativas de comandos rcon para o servidor. Todos os comandos rcons são mandados por esse pacote, até mesmo tentativas de login. A sua estrutura de dados é a seguinte:
text_length - UINT32 com a quantidade de células do texto do comando.
cmdtext - Texto do comando.
• Funções Get*.
Citar:Funções Get* (como GetPlayerWeapon) retornam valores que o servidor já tem, sem nenhuma operação I/O. Esses valores são contidos nos dados dos pacotes de sincronização que jogadores enviam para o servidor. Assim que recebidos os dados, os valores são escritos em variáveis nas estruturas internas do servidor em CPlayerPool, assim, a função retornará o valor já presente em uma das variáveis nas estruturas internas.
Após um pacote de sincronização chegar no servidor e ter seus dados escritos nas estruturas internas, a callback OnPlayerUpdate é chamada. O valor retornado na callback OnPlayerUpdate determina se os dados recebidos pelo servidor vão ser transmitidos com outros jogadores ou não, nesse caso retornando 1 permite que os dados sejam transmitidos com outros jogadores após terem sidos salvos nas estruturas internas do servidor, e retornando 0 impedirá a transmissão desses dados.
• Mundos virtuais e processo de "streaming".
Citar:O servidor controla aquilo que será transmitido com o cliente. Outros jogadores só vão ser criados se você estiver a uma certa distância de suas posições atuais e se o mundo virtual for o mesmo, resultando no processo de stream-in com outros clientes.
No processo de stream-in com jogadores, o servidor manda a chamada de procedimento remoto (RPC - Remote Procedure Call) WorldPlayerAdd para seu cliente, criando os outros jogadores em seu cliente e então permitindo que você receba dados de sincronização desses outros clientes. O mesmo serve para veículos e objetos, o processo de stream-in ocorre quando você chega na distância necessária (geralmente uma distância menor que 200.0 no plano X, Y - O valor pode variar, depende de como você definiu stream_distance em server.cfg, mas por padrão é 200.0) e se estiver no mesmo mundo virtual.
Chegando a uma distância superior à stream_distance, os jogadores/veículos/objetos sofrem stream-out, em que são removidos do seu cliente, logo esses jogadores não terão dados de sincronização mandados para você.
O cliente não controla aquilo que será transmitido consigo mesmo, o servidor é responsável por isso baseado em fatores como posição e mundo virtual. O cliente pode chegar ao ponto de modificar a posição resultando no servidor em fazer o processo de stream-in/out, mas, o cliente nunca poderá alterar o mundo virtual, que é totalmente controlado pelo servidor.
No momento que o mundo virtual muda, todo jogador/objeto/carro que está próximo de você e dentro da distância de streaming e não pertencer ao seu mundo virtual, sofrerá o processo de stream-out, e aquilo que ainda não foi transmitido não será. Você estará limitado a outros jogadores/veículos/objetos que estejam no seu mesmo mundo virtual.
• Pool interna de processamento de RPCs.
Citar:Chamadas de procedimento remoto (RPCs - Remote Procedure Calls) tem o objetivo de executar funções internas no cliente. Quando você muda a ação especial de um jogador com a função SetPlayerSpecialAction, o RPC 88 é mandado para o cliente, tendo o ID da ação especial como parâmetro, e logo uma função interna é chamada no cliente e a ação especial muda de acordo com a providenciada na chamada de procedimento remoto.
Antes de uma chamada de procedimento remoto ser enviada, o servidor verifica se o cliente está mandando atualizações para se certificar que não esteja AFK. Se o cliente estiver AFK, os RPCs são colocados em uma pool de processamento interna, e assim que o cliente voltar, os RPCs são removidos da pool e processados, chegando no cliente.
Vamos considerar o seguinte exemplo:
- O servidor manda uma chamada de procedimento remoto para mudar a ação especial do cliente.
- O cliente está pausado, resultando na adição do RPC, na pool interna de processamento.
- O cliente volta, então o RPC é processado e removido da pool de processamento, chegando no cliente.
- O cliente manda a nova ação especial no pacote de sincronização a pé.
- Os dados do pacote são escritos nas variáveis das estruturas internas do servidor.
- OnPlayerUpdate é chamada, e se ela retornar 1, a atualização será transmitida para jogadores dentro da área de streaming.
- GetPlayerSpecialAction retornará o novo ID de ação especial mantido em uma variável em CPlayerPool->CPlayer[id_do_jogador].
• Dessincronização.
Citar:A dessincronização, também conhecida como "relógio travado" por algumas pessoas, é uma grande causa de falsos-positivos em relação a verificações de anti-cheat.
Um jogador sofrendo dessincronização, ainda manda pacotes de atualização para o servidor e recebe eles, mas não vai reagir a alguns RPCs mandados pelo servidor, como 145 (SetPlayerAmmo) com o intuito de atualizar/mudar alguma informação do cliente.
Como o cliente acaba não reagindo a certos RPCs, o mesmo não passará pelo processo de stream in/out que é feito com RPCs, resultando jogadores/veículos/objetos em não serem removidos, mas vão parar de mandar dados de sincronização, resultando em que o jogador dessincronizado veja todos como se estivessem pausados/AFK.
Fazer a detecção de um jogador dessincronizado não é complicado, leve em consideração que ele ainda manda atualizações para o servidor, logo a callback OnPlayerUpdate continua sendo chamada. Você pode fazer a detecção tentando mudar a munição na slot 0 utilizando SetPlayerAmmo, já que os jogadores não vão perceber a mudança de munição em punhos (id 0) ou soco inglês (id 1), e verificar se há alguma diferença de valores com a última atualização.
Este é um tutorial simples e rápido para você compreender algumas coisas básicas sobre declaração de vars/arrays em Pawn (1) e como economizar memória com isso (2).
Vou passar rápido no tópico 1 (declaração de vars/arrays em Pawn) e me estender no tópico 2.
Coisas que você precisa saber para entender este tópico:
- Basicamente, todas as variáveis declaradas em Pawn (seja new, seja static) alocarão 32 bits (4 bytes ou 4B) p/cell.
- Cells são representadas por colchetes var[0] e bytes por chaves var{0}.
- Todo caractere da table ASCII (inclusive os especiais) compreendem nos decimais que vão de 0 a 255
- 8 bits podem armazenar um número de 0 a 255.
Logo podemos concluir que: 8 bits (1B) são suficientes para armazenar qualquer caractere (inclusive os especiais).
Sendo assim, a maneira mais eficiente de armazenar uma mensagem dentro de uma string não é inserindo um caractere por cell (4B), e sim um caractere por byte, ou seja, 4 caracteres por cell.
Como faremos isso?
Fácil, use ' ! ' antes de declarar uma String.
Ao invés de:
Código PHP:
new String[16] = "Tutorial Maroto";
Use:
Código PHP:
new String[4] = !"Tutorial Maroto";
Isso faz com que você economize 12 Bytes de um total de 16 (75%). Imagine fazer isso para um servidor inteiro, a memória cai muito.
Enfim, tudo tem seus prós e contras. O nome desse tipo de string, de acordo com Pawn, é packed strings (mensagens compactadas), em que, realmente, alocam uma quantia menor de memória, mas não é possível que você use a função 'format' com elas, o que ferra tudo, porque são muito poucas as strings em um servidor que não passem por um format.vou mostrar uma alternativa.
Existe um comando que por aí em GameModes chamado /Cores, que basicamente faz com que uma dialog MSGBOX apareça na tela do player com as 256 cores de veículos, cada cor com seu respectivo número, tipo isso:
Mas pensa bem, se você for armazenar as 3072 caracteres que tem aí dentro (não é um palpite, têm exatos 3072 caracteres), você teria que fazer algo mais ou menos assim:
Código PHP:
if(!strcmp(cmd, "/cores", true)) { new color_list[3072];
Sim, declarar uma string de 3072 cells, quero dizer 12.288bytes, exatos 12 KILOBYTES.
Será se conseguimos diminuir para 3 KB? diminuir em 75%? Não exatamente, mas conseguimos diminuir muito a memória alocada, e é agora que começa o tutorial.
Já que são 3072 caracteres, precisamos de apenas 768 cells (3072/4). Começamos por aí.
Além disso, vamos ter que criar outra array para armazenar a string que será formatada (usaremos 14 cells).
Por último, usaremos uma função.
Código PHP:
if(!strcmp(cmd, "/Cores", true)) { new Result[768]; // Os 3072 caracteres do resultado final new String[14]; // Os 14 caracteres que serão formatados a cada looping for(new i; i != 256; ++i) { // 256 cores format(String, 14, "{%06x}%03i%s", (VehicleColors[i] >>> 8), i, (((i+1) % 16) ? (" ") : ("\n"))); // Não precisa entender isso, apenas que fique claro que estamos usando format strpack(String, String); // compactando as 14 cells em 14 bytes (que fique claro que a array String NÃO diminuiu de tamanho, apenas a informação foi compactada) strpackcat(Result, String); // juntando a array Result com a array String (formatada e depois compactada) } // Depois do processo ter terminado, a array Result estará prontinha para uso ShowPlayerDialog(playerid, DIALOG_NOANS, DIALOG_STYLE_MSGBOX, "Cores", Result, "Ok", ""); return 1; }
a stock strpackcat (que basicamente concatena 2 packed strings, como se fosse strcat só que de packed strings):
Código PHP:
stock strpackcat(dest[], const source[], maxlength=sizeof(dest)) { if(dest{3}) { if(!dest{0}) { print("JBScript [strpackcat] ERROR: The destiny string must be already packed before using this function."); return 0; } } if(source{3}) { if(!source{0}) { print("JBScript [strpackcat] ERROR: The source string must be already packed before using this function."); return 0; } } new dl = strlen(dest), sl = strlen(source); maxlength *= 4; if(maxlength < dl) { print("JBScript [strpackcat] ERROR: The maxlength is lesser then destiny string length."); return 0; } if(maxlength < sl+dl) { sl = maxlength-dl; } for(new i; i != sl; ++i) { dest{dl+i} = source{i}; } return 1; }
Bom, o tutorial é basicamente isso, não tão útil até porque nem sempre criamos uma array assim tão grande. É mais usado nesses casos (raros) mesmo.
Algumas coisas eu não falei durante o tutorial pois não é o foco (já que devem existir outros tutoriais sobre os detalhes que eu deixei de falar, como o uso de 'char', que basicamente retorna o número de cells que são necessárias para armazenar x caracteres, etc).
Como vejo muitas dificuldades nas diferenças entre SetTimer e SetTimerEx, venho aqui trazer um tutorial simples para vocês.
1. De certeza você já ouviu falar daquela expressão: "SetTimer é para todos os jogadores e SetTimerEx é para cada um." Isso está meio que errado. Não é pra isso que foi criado o SetTimer e SetTimerEx.
2. Usamos SetTimer e SetTimerEx quando queremos chamar uma função com atraso, ou seja, por um determinado tempo depois.
3.SetTimer: Sem parametros. SetTimerEx: Com parâmetros.
Explicação:
SetTimer:
Código PHP:
SetTimer(NomeFuncao, Tempo, Repetição);
NomeFuncao: Será o nome de sua função pública. Tempo: O tempo de duração que você quer chamar ela. Repetição: true = repetir sempre, false = apenas uma vez.
NomeFuncao: Será o nome de sua função pública. Tempo: O tempo de duração que você quer chamar ela. Repetição: true = repetir sempre, false = apenas uma vez. formato: tipos de valores. {Float,_}:... : parâmetros (seguindo o formato definido anteriormente).
Até agora, se você é iniciante, você provavelmente está pensando: Eu não entendi nada! Enfim, para isso estou aqui, vou explicar na sua experiência dia-dia.
Vamos imaginar na sua casa: O Microondas, você coloca algo apenas para esquentar, programa ele pra 1 minuto e a contagem começa a descer até chegar ao 0... ( porém o SetTimer(Ex) é incrementando(subindo), e não descendo.
Outro exemplo: você está brincando de esconde-esconde e tem que contar até 10. Quando chegar ao 10, você já pode procurar eles..
Isso é o SetTimer(Ex). Você faz um SetTimer que 'conte' até 10, e quando chegar no 10, irá executar a função de procurar eles.
Agora digamos que você tenha roubado e parou de contar antes dos 10 segundos. Nesse caso, utilizamos o KillTimer parando o SetTimer(Ex)!
Esse é o conceito de SetTimer(Ex)... Ele vai até onde você mandar! Vamos a uns exemplos práticos para entendermos melhor!
Diminuindo tempo pensando em milissegundos.
O tempo do SetTimer(Ex) é feito em milissegundos. Ou Seja:
Código PHP:
1 segundo = 1000 60 segundos = 60000 // [...]
Se você precisa de 2 minutos e 27 segundos por exemplo, sem gerador ou algo do tipo você teria que bater muita cabeça até conseguir. Para facilitar seu trabalho, iniciante, você bota isso no topo do seu GM/FS. Não me lembro do criador do code, mas vou deixar aqui os créditos pro Y_Less. Se alguem souber de quem criou isso, coloca nos comentários
É claro que você não usaria pra dias, semanas, meses, anos, década e muito menos seculos. Para isso usamos GetTimer, mas fica pra outra explicação.
Agora sim! Com esse código definido, fica muito mais fácil trabalharmos! Vamos ver na prática.
Como ficaria o exemplo: "Você está brincando de esconde-esconde e tem que contar até 10. Quando chegar ao 10, você já pode procurar eles.." na prática?
SetTimer
Código PHP:
SetTimer("Contando", segundos(10), false); // Veja como ficou mais fácil definir o tempo. Mas você também pode optar pelo normal: SetTimer("Contando", 10000, false); // Ele cria uma função contando 10 segundos sem repetição!
// Como SetTimer não tem parametro, nunca passamos valor para ela. Sempre utilizaremos ( ).
forward Contando(); public Contando()// Quando completar os 10 segundos, funciona a callback. { print("Contei até 10 segundos ! Agora posso começar a procurar!"); return true; }
Outro exemplo muito conhecido, o sistema de payday:
Código PHP:
public OnGameModeInit() { SetTimer("PayDay", horas(1), true); /* Criamos um Timer com o nome da função PayDay Ele irá contar até 1 hora. / true = ele irá se repetir depois de terminar. ( voltará a funcionar sozinho ).*/ return true; }
forward PayDay(); public PayDay() // Quando completar as 1 hora, funciona a Callback: { for(new i; i < MAX_PLAYERS; ++i) // Loop - Todos os Players { // Mensagem para todos os players. SendClientMessage(i, -1, "Você recebeu o PayDay!"); } return true; }
Realmente, SetTimer poderia ser para todos os players(usando loop). Mas não é isso o conceito dela. Ela vai muito além disso, como utilizar pra sistema de salvamentos ou outras coisas.
Código PHP:
for(new i; i < MAX_PLAYERS; ++i) { SendClientMessage(i, -1, "Você recebeu o PayDay!"); }
Para quem não entendeu isso, procure por tutoriais de Loop. MAX_PLAYERS definido por padrão é 500... Ou seja vai pegar 500 números que são os slots. Até aqui tudo bem. Mas porque trocou no meu SendClientMessage playerid por i ?
playerid = ID DO PLAYER! LEMBREM-SE DISSO!
O Loop, portanto, vai dar 500 voltas... e vai mandar para todos os ID's.
O ID 0 que é o Fulano com Nick A...
Pro ID 1 que é o Fulano com Nick B...
Assim vai até os 500 players(slots).
SetTimerEx
Existem vários exemplos. Mais vou dar apenas dois. Esse, é um simples bloqueio de comando. Depois de usar, ele permitirá que você utilize o comando de novo só depois de 15 segundos.
Código PHP:
new bool:BloquearComando[MAX_PLAYERS char];
get_cmd_noparams(bloquearcomando) // ICMD ( mesma coisa que /bloquearcomando ) { if(BloquearComando{playerid} == true) return SendClientMessage(playerid, -1, "Você já utilizou o comando! Aguarde 15 segundos para utlizar de novo.");
BloquearComando{playerid} = true; SetTimerEx("BloqComando", segundos(15), false, "i", playerid); // Ele irá criar uma função de 15 segundos e não vai ficar se repetindo. // Como eu falei no meu BIZU: playerid carrega o ID do Player. Ele vai levar o ID do player para a função. SendClientMessage(playerid, -1, "Você Utilizou o Comando: /BloquearComando"); return true; }
forward BloqComando(playerid); public BloqComando(playerid) // playerid CARREGA O ID DO PLAYER ! { BloquearComando{playerid} = false; SendClientMessage(playerid, -1, "Já se passou 15 segundos! Agora você já pode utilizar o comando!"); return true; }
Agora que tal um sistema de carregar suas informações simples?
Código PHP:
get_cmd_noparams(minhasinfo) // ICMD ( mesma coisa que /minhasinfo ) { new Idade = 18; new Float:PontosNaEscola = 9.0; // playerid = seu ID SetTimerEx("CarregInfo", 5000, true, "iif", playerid, Idade, PontosNaEscola); return true; }
Temporizadores não são 100% precisos e sim 75%;
Uso de muitos temporizadores aumentará o uso de Memória/CPU.
Lembrando daqueles "i", "iif", etc.. Sugiro ver melhor os tutoriais de Format.
Código:
i Integer.
d Integer.
a Array. The next parameter must be an integer ("i") with the array's size. [CURRENTLY UNUSABLE]
s String. [CURRENTLY UNUSABLE]
f Float.
b Boolean (true/false).
Olá users, estou enfrentando um problema um tanto quanto inexplicável.
Quando adiciono a linha abaixo em OnGameModeInit, o samp-server carrega algumas funções e logo em seguida fecha:
Código PHP:
LimitGlobalChatRadius(100.0);
Esse problema só ocorre quando eu adiciono o código citado, se eu o remover, o servidor abre normalmente.
O final do log, é apresentado os veículos carregados, e uma mensagem de conexão antes de fechar:
Código PHP:
Number of vehicle models: 41 [connection] 127.0.0.1:60310 requests connection cookie.
Citar:Em teoria da informação, a distância Levenshtein ou distância de edição entre dois "strings" (duas sequências de caracteres) é dada pelo número mínimo de operações necessárias para transformar um string no outro. Entendemos por "operações" a inserção, deleção ou substituição de um carácter. O nome advém do cientista russoVladimir Levenshtein, que considerou esta distância já em 1965. É muito útil para aplicações que precisam determinar quão semelhantes dois strings são, como é por exemplo o caso com os verificadores ortográficos.
Essa include se utiliza da distância de Levenshtein para adivinhar o comando que o player gostaria de ter digitado.
Como utilizar:
Código:
public OnPlayerCommandPerformed(playerid, cmdtext[], success) {
if (!success) {
new
guessCmd[32];
Creditos:
- Por: Kirima pela include guess-command.inc
- Southclaws pela Função da Distância de Levenshtein
- Y_Less por y_commands
- Zeex por amx_assembly
Olá, mais um projeto recuperado do antigo Fórum. Créditos ao bruxo00.
doxIT!
Este simples filterscript serve para os administradores do servidor terem mais informações sobre os jogadores. Recorrendo ao comando /dox <playerid> o administrador tem acesso a:
Código PHP:
DNS Reverso Username da Internet Cidade País Código do País Internet Server Provider Latitude Longitude TimeZone Organização Região Nome da Região Código Postal Se está a usar ou não VPN
Este Filterscript é extremamente fácil de adaptar a qualquer gamemode.
A API de verificar se o IP é VPN tem um limite de acessos por dia. Hoje já excedi esse limite por isso é que aparece que o meu IP está banido.
A versão antiga requeria hospedar um .php. Esta versão não é preciso usar nenhum .php, todo o scrapping é feito diretamente no filterscript.
COMO FUNCIONA A DETEÇÃO DE VPN
Citando diretamente a API:
Código:
Given an IP address, the system will return a probabilistic value (between a value of 0 and 1) of how likely the IP is a VPN / proxy / hosting / bad IP. A value of 1 means that IP is explicitly banned (a web host, VPN, or TOR node) by our dynamic lists. Otherwise, the output will return a real number value between 0 and 1, of how likely the IP is bad / VPN / proxy, which is inferred through machine learning & probability theory techniques using dynamic checks with large datasets. Billions of new records are parsed each month to ensure the datasets have the latest information and old records automatically expire. The system is designed to be efficient, fast, simple, and accurate.
Inserido por: Levi.M - 24/02/2021 09:37 - Fórum: Includes
- Sem Respostas
Mais um sistema recuperado da Fórum SA-MP. Créditos ao ipsBruno.
Bini 4
Após algumas semanas de desenvolvimento da nova versão de Bini. Finalmente consigo acaba-la.
A nova versão de Bini não conta com muitas alterações, exceto a engine de manipulação de arquivos na memória. Desta vez utiliza memória cache mais avançada usando Setproperty e Getproperty!
Por mais que não seja necessário o uso de INI_Save. Aconselha o USO DA MESMA, pois em caso de crashs ou eventuais bugs no seu servidor decorrente em outros fatores, alguns arquivos podem ser perdidos !!
Velocidade
Com esta nova engine, a velocidade foi bastante aprimorada. O que já era rápido ficou mais rápido ainda.
Código PHP:
[00:57:47] Bini -> write 3304 ms - read 32 ms - read/write 3336 ms [00:57:47] Dof2 -> write 3557 ms - read 258 ms - read/write 3815 ms
A função write apesar de ser mais rápida que todos os outros sistemas de arquivos ainda precisa de alguns ajustes de velocidade e estabilidade, então eventuais atualizações estão para surgir
printf("Bini -> write %d ms - read %d ms - read/write %d ms", bin[0], bin[1], bin[2]); printf("Dof2 -> write %d ms - read %d ms - read/write %d ms", dof[0], dof[1], dof[2]); return true; }
public OnFilterScriptExit() { DOF2_Exit(); INI_Exit(); return true; }
Usando
Para usar Bini é bastante simples! Basta fazer o seguinte:
Escrevendo:
Números
Código PHP:
INI_WriteInt("arquivo.ini", "key", valor);
Textos
Código PHP:
INI_WriteString("arquivo.ini", "key", "valor");
Lendo valores:
Números
Código PHP:
INI_ReadInt("arquivo.ini", "key");
Textos
Código PHP:
INI_ReadString("arquivo.ini", "key");
deixe
Código PHP:
public OnFilterScriptExit() { INI_Exit(); return true; }
**Importante
- Se você tem arquivos escritos por DOF2 ou Y_Ini este sistema não será compatível pois meu sistema usa o método formal para escrita de escrita em arquivos ini, sem espaço entre as keys
Com está velocidade é permitido que você possa colocar em até 50 escritas/leituras em OnPlayerUpdate. Salve em bini.inc por favor.
Arquivo não salvando
Caso for um único arquivo, veja se o servidor não está sendo fechado corretamente. Quando você não fecha por RCON EXIT o OnGameModeExit/FilterScriptExit não são chamados e logo INI_Exit também não é !!
Caso for vários arquivos tente aumentar o valor max_lines_file para acima de 999
Exemplo:
Código PHP:
#define max_lines_file 5000
Servidor crashando
Certifique-se se antes de usar algum arquivo INI_Open/INI_READ o arquivo existe. Use
Código PHP:
if(fexist(#arquivo.ini)) // o arquivo existe
Ocupando muito AMX
Nem sempre o que ocupa muito amx é lento. Bini usa um sistema avançado de cache, onde tudo é registrado no amx em tempo real. Mas é tudo registrado no AMX, não ocupa nada de memória do seu computador. Só ocupará memória se de alguma forma outros fatores externos a Bini ultrapassarem isto.