Pular para o conteúdo principal

Portando para open.mp

· 6 min de leitura
Y_Less

O SA:MP ficou preso no limbo por anos, sem atualizações e com várias gambiarras só para manter as coisas funcionando. O open.mp muda isso — é uma reescrita completa que corrige problemas antigos, melhora o scripting e remove limites antigos, mantendo seu código existente funcionando. Mas o que isso realmente significa para você? Vamos explicar.

aviso

O conteúdo do post a seguir está desatualizado e, em sua maioria, não tem relação com o estado atual do open.mp. O post está publicado aqui para fins de arquivo.

Já estava claro há muito tempo que Kalcor não tinha mais interesse em manter o SA:MP; o que, por si só, tudo bem, mas como ele era a única pessoa com acesso oficial ao código-fonte, isso o transformou em um gargalo para novas atualizações. Tanto YSF quanto fixes.inc foram criados para preencher esse vazio — corrigir bugs e inconsistências no servidor sem ter acesso ao código-fonte; o primeiro como plugin e o segundo como include. Apesar de esforços monumentais para tornar esses (e outros) projetos tão estáveis, abrangentes e fáceis de usar quanto possível, eles naturalmente começaram a atingir seus limites e uma nova geração de correções se tornou necessária. É aí que o open.mp entra.

Fundado nos mesmos princípios, e aproveitando todas as inúmeras melhorias desenvolvidas pela comunidade ao longo de uma década, o open.mp é uma reescrita do zero do servidor SA:MP original, com todas as correções de seus predecessores diretos e muitas outras que eram impraticáveis ou simplesmente impossíveis. É verdade que essa abordagem não veio sem controvérsia — alguns servidores desenvolveram seus próprios métodos privados para lidar com as peculiaridades do SA:MP, independentemente dos esforços da comunidade, mas essas não são técnicas que todo scripter deveria ter que desenvolver por conta própria, e este artigo ajudará na portabilidade de código existente.

Esperamos abordar os principais pontos problemáticos, mas se houver algum que deixarmos passar, fique à vontade para entrar em contato via discord ou github e teremos prazer em corrigir o guia.

A alternativa é desfazer as correções usando uma biblioteca que é a gêmea da fixes.inc: breaks.inc:

https://github.com/pawn-lang/sa-mp-fixes/blob/master/breaks.inc

Então fique à vontade para instalá-la e reverter para todos os comportamentos antigos de forma transparente por meio de hooks.

Tags

Os includes do open.mp adicionam muitas novas tags às funções, embora ainda tentem encontrar um equilíbrio entre upgrades muito necessários e invasividade. Como essas mudanças podem ser muito amplas, escrevemos uma ferramenta para automatizar boa parte disso:

HideMenuForPlayer

Esta função sempre recebeu um parâmetro de ID de menu, mas no SA:MP esse ID não era usado. Então, qualquer que fosse o valor fornecido, o menu atual do jogador era fechado, mesmo que ele não estivesse olhando para aquele que você disse para fechar.

Código antigo poderia ser assim:

gShopMenu = CreateMenu("text", 2, 100.0, 30.0, 7.0);

HideMenuForPlayer(gShopMenu, playerid);

Isso sempre fecharia o menu atual do jogador, independentemente de qual ele estivesse realmente vendo. Agora você precisará lembrar qual menu ele está vendo, ou simplesmente obtê-lo:

gShopMenu = CreateMenu("text", 2, 100.0, 30.0, 7.0);

HideMenuForPlayer(GetPlayerMenu(playerid), playerid);

SetPlayerAttachedObject

Objetos anexados no SA:MP sobreviviam a uma mudança de gamemode, mas no open.mp eles não sobrevivem. Se você quiser que um jogador mantenha seus objetos após um reinício do modo, terá que adicioná-los novamente em OnPlayerConnect:

enum E_ATTACHMENT_DATA
{
E_ATTACHMENT_DATA_MODEL,
E_ATTACHMENT_DATA_BONE,
E_ATTACHMENT_DATA_OFFSET_X,
E_ATTACHMENT_DATA_OFFSET_Y,
E_ATTACHMENT_DATA_OFFSET_Z,
E_ATTACHMENT_DATA_ROT_X,
E_ATTACHMENT_DATA_ROT_Y,
E_ATTACHMENT_DATA_ROT_Z,
E_ATTACHMENT_DATA_SCALE_X,
E_ATTACHMENT_DATA_SCALE_Y,
E_ATTACHMENT_DATA_SCALE_Z,
E_ATTACHMENT_DATA_COLOUR_1,
E_ATTACHMENT_DATA_COLOUR_2,
}

public OnPlayerConnect(playerid)
{
for (new i = 0; i != MAX_OBJECT_ATTACHMENT_SLOTS; ++i)
{
SetPlayerAttachedObject(
playerid,
i,
gAttachementData[playerid][E_ATTACHMENT_DATA_MODEL],
gAttachementData[playerid][E_ATTACHMENT_DATA_BONE],
gAttachementData[playerid][E_ATTACHMENT_DATA_OFFSET_X],
gAttachementData[playerid][E_ATTACHMENT_DATA_OFFSET_Y],
gAttachementData[playerid][E_ATTACHMENT_DATA_OFFSET_Z],
gAttachementData[playerid][E_ATTACHMENT_DATA_ROT_X],
gAttachementData[playerid][E_ATTACHMENT_DATA_ROT_Y],
gAttachementData[playerid][E_ATTACHMENT_DATA_ROT_Z],
gAttachementData[playerid][E_ATTACHMENT_DATA_SCALE_X],
gAttachementData[playerid][E_ATTACHMENT_DATA_SCALE_Y],
gAttachementData[playerid][E_ATTACHMENT_DATA_SCALE_Z],
gAttachementData[playerid][E_ATTACHMENT_DATA_COLOUR_1],
gAttachementData[playerid][E_ATTACHMENT_DATA_COLOUR_2]
);
}
}

Dinheiro ao morrer

Quando um jogador morre em San Andreas, $100 são deduzidos dele automaticamente para cobrir as contas do hospital. Esse recurso permanece no SA:MP, mas foi removido do open.mp para permitir que scripts gerenciem todo o próprio dinheiro. Vários scripts já tentam corrigir isso adicionando $100 a um jogador depois da morte, ou ao nascer. Se esse for o seu script, simplesmente remova a correção adicional, embora o código no open.mp tente levar em conta scripts que fazem isso. Se seu script dependia desse recurso, basta adicionar o seguinte código em OnPlayerDeath:

GivePlayerMoney(playerid, -100);

Game texts

O SA:MP tem seis estilos diferentes de game text, mas vários deles são basicamente inutilizáveis. Um fica aparecendo e desaparecendo constantemente, um desaparece após um tempo definido independentemente do tempo que você colocou, e um nunca desaparece independentemente do tempo selecionado. No entanto, descobriu-se que todos esses estilos de game text podem ser reproduzidos com precisão1 usando text draws. Assim, fixes.inc e, posteriormente, open.mp fizeram isso. A aparência dos game texts é a mesma de antes, com a vantagem de que todos os estilos são utilizáveis, e a desvantagem de que eles não fazem mais fade in e fade out.

FadingGameTextForPlayer(playerid, const format[], time, style)
{
if (style > 6)
{
// Não há versão com fade desses estilos.
GameTextForPlayer(playerid, format, time, style)
}
else
{
// Envia uma mensagem bruta via Pawn.RakNet
}
}

Tamanhos dos pools

GetPlayerPoolSize, GetActorPoolSize e GetVehiclePoolSize eram um tanto sem sentido quando foram introduzidas pela primeira vez; retornavam o maior ID conectado, que não tem relação com o número de jogadores conectados, e chegaram muito depois de métodos de loop muito melhores já existirem. Ser meio bobo não é, por si só, motivo para remover as funções, mas infelizmente elas também estão quebradas e retornam dados incorretos quando não há jogadores conectados. Não há como corrigir esses valores de retorno de uma forma que seja ao mesmo tempo retrocompatível e correta daqui para frente (acredite, tentamos). Diante desses fatos, optamos por simplesmente remover as funções. Use apenas um loop normal ou foreach:

foreach (new i : Player)
{
}

Alguns scripts travaram quando essa mudança foi introduzida, mas apenas ao usar a seguinte forma de loop:

for (new i = 0; i != GetPlayerPoolSize(); ++i)
{
}

Embora, como o maior valor é um jogador real quando há pessoas online, esse código esteja errado de qualquer forma — ele deixa uma pessoa de fora.

Grafias

O SA:MP é muito inconsistente nas grafias usadas no código — algumas coisas usam inglês britânico, outras usam americano:

  • Bumper - Britânico
  • Hood - Americano
  • Armour - Britânico
  • Stereo - Americano

Unificamos isso e adotamos as grafias britânicas. Então, por exemplo:

TextDrawBoxColor(Text:textid, boxColor);

Agora é:

TextDrawBoxColour(Text:textid, boxColour);

A ferramenta de upgrade cuidará automaticamente da maioria desses casos.

Footnotes

  1. Com uma exceção notável: o novo estilo de game text de relógio. Por algum motivo desconhecido, a cor do relógio é diferente para pessoas diferentes, o que levou a muita discussão sobre a melhor forma de replicar esse estilo até que a discrepância fosse encontrada. Tivemos que escolher uma das duas por consistência.