Ir para conteúdo

Tabela de Classificação


Conteúdo Mais Visto

Exibindo conteúdo com a maior reputação em 3em todas áreas

  1. 3 pontos
    Gengo

    [OTClient] Entendendo as funções Opcodes

    Eai, galera, blz! Hoje vim trazer um tutorial sobre Opcodes, sei que hoje em dia tem muitos tutorias falando sobre isso, porém é sempre bom dar uma atualizada, afinal um tutorial nunca será "igual" a o outro e quanto mais tutorias sobre o assunto, melhor o entendimento. Primeiro vamos conhecer o que é esse tal de Opcodes, uma breve explicação que vemos por ai. O que são Opcodes? R: Opcodes é a comunicação entre o cliente e o servidor. Na source do servidor muitos poderiam utilizar sockets, que são pacotes de informação, diretamente sem usar funcionalidades do jogo como meio de comunicação, já o Opcode utiliza-se recursos in-game para fazer essa comunicação. Vamos analisar o código do módulo acima? Vamos ver qual é a funcionalidade dessas funções e o que ela espera nos seus respectivos parâmetros. Vamos por etapa: 1 - ProtocolGame.registerExtendedOpcode(Opcode, function(protocol, opcode, buffer) end) Essa função tem a funcionalidade de registrar um Opcode, como vemos o nome já é autoexplicativo. Parâmetros: Opcodes É um numero(Identificador) qualquer que vai do 0 ao 255, no caso desse módulo foi utilizado o numero 110. Function: Esse segundo parâmetro é uma função que fica esperando uma resposta do servidor, vemos que o eperado é que servidor nos envie um buffer qualquer, neste caso esperamos que seja enviado o nome do player. 2 - ProtocolGame.unregisterExtendedOpcode(Opcode) Essa função tem a funcionalidade de desregistrar um Opcode, como vemos o nome já é autoexplicativo. Parâmetro: Opcode: É o mesmo numero(Identificador) que utilizamos para registrar, assim a propria função saberá qual Opcode deve ser desfeita, digamos assim. 3- g_game.getProtocolGame():sendExtendedOpcode(Opcode, '') Essa função tem o intuito de solicitar/executar uma ação no servidor, nesse caso do módulo de exemplo, essa ação fará com que o otClient solicite ao servidor uma responsta no qual foi designada a ser feito, me retornar o nome do player. Parâmetros: Opcode: É o mesmo numero(Identificador) que utilizamos para registrar. buffer: Dados que poderam ser enviados ao servidor. Exemplo: Enviar uma pos, e verificar se contem uma creatura, nesse exemplo não foi enviado nada. Também temos na parte do servidor e é algo simples que dê para entender. Essa função espera que o client solicite/execute uma ação para o servidor possa processar e se preciso retornar algo que é esperado. Parâmetros: cid: Cid identificar do player, não vem ao caso explicar com o maior detalhe. opcode: É o mesmo numero(Identificador) que utilizamos para registrar na parte do client, assim o servidor sabe qual ação deve ser executada. buffer: Dados que o client enviou para o servidor. Podemos analisar com calma essa função, obersevem cada detalhe que é utilizado podemos ver que se a opcode for a mesma opcode registrada no client que nesse caso é o 110, solicitamos ao servidor que nos envie o nome da creatura que executou a ação, atraves da função: doSendPlayerExtendedOpcode doSendPlayerExtendedOpcode(cid, Opcode, buffer) Essa função tem o intuito de enviar informações para o client, e ao executar essa função, podemos perceber que lá quando registramos o Opcode ProtocolGame.registerExtendedOpcode na parte do módulo, o segundo parâmetro é executado. Parâmetros: cid: Cid identificar do player, não vem ao caso explicar com o maior detalhe. opcode: É o mesmo numero(Identificador) que utilizamos para registrar na parte do client, assim o servidor sabe qual ação deve ser executada. buffer: Dados que o servidor envia para client, nesse caso foi enviado o nome da creatura. Então vamos reforçar o tutorial e vermos o que aprendemos, vamos-lá. 1º Vemos que para registrar um Opcode, utilizamos a função: ProtocolGame.registerExtendedOpcode(Opcodes, function(protocol, opcode, buffer) end) na maioria das vezes utilizamos dentro da função init. 2º Vemos que precisamos também desregistrar a Opcode, e utilizamos a função: ProtocolGame.unregisterExtendedOpcode(Opcodes), mais utilizado na função do módulo em terminate. 3º Vemos que podemos fazer com que o client solicite uma ação ao servidor utilizando a função: g_game.getProtocolGame():sendExtendedOpcode(Opcodes, Buffer). 4º Vemos também que na parte do servidor, a função: onExtendedOpcode(cid, opcode, buffer) espera que o client solicite/execute algo que possa ser processado e se preciso enviar alguma responsta esperada com a função: doSendPlayerExtendedOpcode(cid, Opcodes, Buffer) Bom, espero que dê para entender com o exemplo e uma breve explicação de cada função. Desculpem-me de qualquer erro, se falei algo errado ou se precisava dizer algo a mais; podem me chamar no privado que estarei lendo e aceitando qualquer tipo de sugestão ou alteração, afinal estamos todos aqui para aprender e o importante é que todos entendam como tudo funciona, aprendam e pratiquem. Download do módulo:
  2. 1 ponto
    Majesty

    Problema com Atributo de % de dano Magico 7.6

    data/movements/movements.xml, adicione as tags: <movevent type="Equip" itemid="2656" slot="armor" event="function" value="onEquipItem"/> <movevent type="DeEquip" itemid="2656" slot="armor" event="function" value="onDeEquipItem"/> 2656 - id da blue robe.
  3. 1 ponto
    Majesty

    Extended Opcodes

    Adaptação para sources de servidores 8.54+ Códigos: protocolgame.h Embaixo de void AddShopItem(NetworkMessage_ptr msg, const ShopInfo item); Adicione void parseExtendedOpcode(NetworkMessage& msg);void sendExtendedOpcode(uint8_t opcode, const std::string& buffer); protocolgame.cpp Embaixo de uint32_t key[4] = {msg.GetU32(), msg.GetU32(), msg.GetU32(), msg.GetU32()};enableXTEAEncryption();setXTEAKey(key); Adicione // notifies to otclient that this server can receive extended game protocol opcodesif(operatingSystem >= CLIENTOS_OTCLIENT_LINUX)sendExtendedOpcode(0x00, std::string()); Embaixo de void ProtocolGame::AddShopItem(NetworkMessage_ptr msg, const ShopInfo item){const ItemType& it = Item::items[item.itemId];msg->AddU16(it.clientId);if(it.isSplash() || it.isFluidContainer())msg->AddByte(fluidMap[item.subType % 8]);else if(it.stackable || it.charges)msg->AddByte(item.subType);elsemsg->AddByte(0x01);msg->AddString(item.itemName);msg->AddU32(uint32_t(it.weight * 100));msg->AddU32(item.buyPrice);msg->AddU32(item.sellPrice);} Adicione void ProtocolGame::parseExtendedOpcode(NetworkMessage& msg){uint8_t opcode = msg.GetByte();std::string buffer = msg.GetString();// process additional opcodes via lua script eventaddGameTask(&Game::parsePlayerExtendedOpcode, player->getID(), opcode, buffer);}void ProtocolGame::sendExtendedOpcode(uint8_t opcode, const std::string& buffer){// extended opcodes can only be send to players using otclient, cipsoft's tibia can't understand themNetworkMessage_ptr msg = getOutputBuffer();if(msg){TRACK_MESSAGE(msg);msg->AddByte(0x32);msg->AddByte(opcode);msg->AddString(buffer);}} Embaixo de case 0x1E: // keep alive / ping responseparseReceivePing(msg);break; Adicione case 0x32: // otclient extended opcodeparseExtendedOpcode(msg);break; enums.h Embaixo de enum GuildLevel_t{GUILDLEVEL_NONE = 0,GUILDLEVEL_MEMBER,GUILDLEVEL_VICE,GUILDLEVEL_LEADER}; Substitua o OperatingSystem por este enum OperatingSystem_t{CLIENTOS_LINUX = 0x01,CLIENTOS_WINDOWS = 0x02,CLIENTOS_OTCLIENT_LINUX = 0x0A,CLIENTOS_OTCLIENT_WINDOWS = 0x0B,CLIENTOS_OTCLIENT_MAC = 0x0C,};/ player.h Embaixo de void sendCreatureShield(const Creature* creature) Adicione void sendExtendedOpcode(uint8_t opcode, const std::string& buffer){if(client) client->sendExtendedOpcode(opcode, buffer);} luascript.cpp Embaixo de void LuaScriptInterface::registerFunctions(){ Adicione //doSendPlayerExtendedOpcode(cid, opcode, buffer)lua_register(m_luaState, "doSendPlayerExtendedOpcode", LuaScriptInterface::luaDoSendPlayerExtendedOpcode); Embaixo de SHIFT_OPERATOR(int32_t, LeftShift, <<)SHIFT_OPERATOR(int32_t, RightShift, >>)SHIFT_OPERATOR(uint32_t, ULeftShift, <<)SHIFT_OPERATOR(uint32_t, URightShift, >>)#undef SHIFT_OPERATOR Adicione int32_t LuaScriptInterface::luaDoSendPlayerExtendedOpcode(lua_State* L){//doSendPlayerExtendedOpcode(cid, opcode, buffer)std::string buffer = popString(L);int opcode = popNumber(L);ScriptEnviroment* env = getEnv();if(Player* player = env->getPlayerByUID(popNumber(L))) {player->sendExtendedOpcode(opcode, buffer);lua_pushboolean(L, true);}lua_pushboolean(L, false);return 1;} luascript.h Embaixo de virtual void registerFunctions(); Adicione static int32_t luaDoSendPlayerExtendedOpcode(lua_State* L); creatureevent.h Substitua CREATURE_EVENT_PREPAREDEATH Por isso CREATURE_EVENT_PREPAREDEATH,CREATURE_EVENT_EXTENDED_OPCODE // otclient additional network opcodes Embaixo de uint32_t executePrepareDeath(Creature* creature, DeathList deathList); Adicione uint32_t executeExtendedOpcode(Creature* creature, uint8_t opcode, const std::string& buffer); creatureevent.cpp Embaixo de else if(tmpStr == "death")m_type = CREATURE_EVENT_DEATH; Adicione else if(tmpStr == "extendedopcode")m_type = CREATURE_EVENT_EXTENDED_OPCODE; Embaixo de case CREATURE_EVENT_DEATH:return "onDeath"; Adicione case CREATURE_EVENT_EXTENDED_OPCODE:return "onExtendedOpcode"; Embaixo de case CREATURE_EVENT_DEATH:return "cid, corpse, deathList"; Adicione case CREATURE_EVENT_EXTENDED_OPCODE:return "cid, opcode, buffer"; Embaixo de std::cout << "[Error - CreatureEvent::executeFollow] Call stack overflow." << std::endl;return 0;}} Adicione uint32_t CreatureEvent::executeExtendedOpcode(Creature* creature, uint8_t opcode, const std::string& buffer){//onExtendedOpcode(cid, opcode, buffer)if(m_interface->reserveEnv()){ScriptEnviroment* env = m_interface->getEnv();if(m_scripted == EVENT_SCRIPT_BUFFER){env->setRealPos(creature->getPosition());std::stringstream scriptstream;scriptstream << "local cid = " << env->addThing(creature) << std::endl;scriptstream << "local opcode = " << (int)opcode << std::endl;scriptstream << "local buffer = " << buffer.c_str() << std::endl;scriptstream << m_scriptData;bool result = true;if(m_interface->loadBuffer(scriptstream.str())){lua_State* L = m_interface->getState();result = m_interface->getGlobalBool(L, "_result", true);}m_interface->releaseEnv();return result;}else{#ifdef __DEBUG_LUASCRIPTS__char desc[35];sprintf(desc, "%s", player->getName().c_str());env->setEvent(desc);#endifenv->setScriptId(m_scriptId, m_interface);env->setRealPos(creature->getPosition());lua_State* L = m_interface->getState();m_interface->pushFunction(m_scriptId);lua_pushnumber(L, env->addThing(creature));lua_pushnumber(L, opcode);lua_pushlstring(L, buffer.c_str(), buffer.length());bool result = m_interface->callFunction(3);m_interface->releaseEnv();return result;}}else{std::cout << "[Error - CreatureEvent::executeRemoved] Call stack overflow." << std::endl;return 0;}} game.h Embaixo de int32_t getLightHour() {return lightHour;}void startDecay(Item* item); Adicione void parsePlayerExtendedOpcode(uint32_t playerId, uint8_t opcode, const std::string& buffer); game.cpp Embaixo de player->sendTextMessage(MSG_INFO_DESCR, buffer);} Adicione void Game::parsePlayerExtendedOpcode(uint32_t playerId, uint8_t opcode, const std::string& buffer){Player* player = getPlayerByID(playerId);if(!player || player->isRemoved())return;CreatureEventList extendedOpcodeEvents = player->getCreatureEvents(CREATURE_EVENT_EXTENDED_OPCODE);for(CreatureEventList::iterator it = extendedOpcodeEvents.begin(); it != extendedOpcodeEvents.end(); ++it)(*it)->executeExtendedOpcode(player, opcode, buffer);} /creaturescripts/creaturescrips.xml <event type="extendedopcode" name="ExtendedOpcode" event="script" value="extendedopcode.lua"/> /creaturescripts/extendedopcode.lua OPCODE_LANGUAGE = 1function onExtendedOpcode(cid, opcode, buffer)if opcode == OPCODE_LANGUAGE then-- otclient languageif buffer == 'en' or buffer == 'pt' then-- example, setting player language, because otclient is multi-language...--doCreatureSetStorage(cid, CREATURE_STORAGE_LANGUAGE, buffer)endelse-- other opcodes can be ignored, and the server will just work fine...endend Exemplo de aplicação, getPlayerVocation em extended opcode: No cliente: 1- Vá em otclient/modules/gamelib/game.lua e adicione: function getPlayerVocation() local protocol = g_game.getProtocolGame() protocol:sendExtendedOpcode(25,5) end 2- No seu script adicione isto: ProtocolGame.registerExtendedOpcode(26, function(protocol, opcode, buffer) vocation = buffer print(vocation) end ) No servidor: 1- Em creaturescripts/script/extendedopcode.lua adicione isto: function onExtendedOpcode(cid, opcode, buffer) if opcode == 25 then doSendPlayerExtendedOpcode(cid, 26, getPlayerVocation(cid)) end return true end Créditos : MaXwEllDeN 100% por adaptar o código
  4. 1 ponto
    Gengo

    Como usar opcode

    O numero que vc está utilizando no opcodes que vc está testando, já deve estar em uso, tente um outro numero.
  5. 1 ponto
    Gengo

    Como usar opcode

    Bom vamos lá, creio que essa parte que você mostrou seu código, esteja errado. No primeiro parâmetro da função de registrar você informou o numero da opcodes que você vai utilizar, até ai tudo bem! No segundo parâmetro você informou o numero 5 e na verdade seria uma função a ser informada, exemplo que você poderia fazer.
  6. 1 ponto
    Majesty

    [Windows][Codeblocks] Compilando Sources OTClient

    [Windows][Codeblocks] Compilando Sources OTClient Tutorial explicando como compilar as Sources do OTClient com o Codeblocks. 1 - Downloads Necessários: - CMake: (32-bit download, 64-bit download) - Codeblocks: http://www.mediafire.com/file/ame2qs65s8ub9o2/codeblocks-17.12-setup.exe/file - MingW: http://www.mediafire.com/file/9bb8gl42p1q8e5c/MingW.rar/file - Edubart OTClient Sources: https://github.com/edubart/otclient/tree/17738dfdeaaaee8e2954c6091b6f9563ae3766c1 - OTLand OTClient Sources: https://github.com/otland/otclient/tree/53fcda286b224bf1a52d7e5ed64a51ccbee3e5cd 1.1 - Download Não Necessário: - Libs OTClient para MingW32: http://www.mediafire.com/file/7ymdqmzerpch7gd/otclient-libs-mingw32.rar/file Obs: Libs OTClient já estão incluídas com o MingW! - Link de download no tópico apenas para conhecimento sobre as libs utilizadas. 2 - Instalação: - Faça a instalação do CMake (C:\Program Files\CMake). - Faça a instalação do Codeblocks (C:\Program Files (x86)\CodeBlocks). - Descompacte o MingW na unidade C:\. - Após descompactar o MingW, deverá ficar assim C:\MingW. Exemplo: - Descompacte as sources do OTClient na unidade C:\. Exemplo: C:\otclient-master. - Dentro da pasta C:\otclient-master, crie uma pasta chamada otclient-cmake. - A pasta otclient-cmake será utilizada para a criação do projeto do OTClient no CMake. 2.1 - Diretório Path: - Utilize a Tecla do logotipo do Windows + Pause para acessar as Propriedades do Sistema. - Acesse Configurações avançadas do sistema. - Na aba Avançado, clique em Variáveis de Ambiente. - Em variáveis de usuário, edite a váriavel Path e adicione o caminho abaixo: C:\Program Files\CMake\bin;C:\MinGW\bin;C:\MinGW\lib;C:\MinGW\include; 3 - CMake: - Encontre e abra o cmake-gui.exe em C:\Program Files\CMake\bin. Para facilitar a utilização, envie um atalho para a Área de Trabalho. - Antes de utilizar o CMake, acesse no menu Options > Warning Messages... > Supress Warnings > Marque as opções Developer Warnings e Deprecated Warnings. - Como configurar o projeto do OTClient no CMake: - Escolha o diretório das sources do OTClient. - Escolha o diretório que vai ser salvo o projeto do OTClient no CMake. - Clique no botão Configure escolha a opção Codeblocks - MingW Makefiles para ser o gerador do projeto. Ficando assim: - Espere ele gerar o projeto. - Feito isso, você deve configurar o CMake para compilar o OTClient (modo Release | OpenGL ou Directx9) - Isso deve ser feito uma vez para OpenGL e depois para Directx9. - OTClient CMake com modo Release e OpenGL: - CMAKE_BUILD_TYPE - Release + OPENGLES - OFF - OTClient CMake com modo Release e Directx9: - CMAKE_BUILD_TYPE - Release + OPENGLES - 2.0 - Feito isso, com a opção escolhida (Release + OpenGL ou Release + Directx9), clique no botão Generate. - O projeto otclient.cbp será salvo dentro da pasta C:\otclient-master\otclient-cmake. - OTClient pronto para ser compilado. 4 - Codeblocks: - Abra o Codeblocks. - Antes de abrir o projeto do OTClient, no menu selecione Settings > Compiler > Toolchain executables, verifique as configurações e deixe assim: - Diretório do Compilador: C:\MingW - Compilador C: gcc.exe - Compilador C++: g++.exe - Bibliotecas Dinâmicas: g++.exe - Bibliotecas Estáticas: ar.exe - Debugger: GDB/CDB debugger : Default - Compilador de Recursos: windres.exe - Programa make: mingw32-make.exe Imagem: - Depois, abra o projeto do OTClient com o comando Ctrl + O e abra o arquivo otclient.cbp: - Feito isso, para compilar o OTClient clique na opção Build: - O resultado final deverá ser esse: - OTClient compilado no Codeblocks com sucesso! - Como utilizar o OTClient: - Copie o otclient.exe da pasta otclient-cmake e cole na pasta otclient-master. - Copie as DLLs libwinpthread-1.dll, libEGL.dll e libGLESv2.dll da pasta C:\MingW\bin e cole na pasta otclient-master. - Copie o Tibia.spr e Tibia.dat da versão desejada em data/things/versão (no lugar de versão crie a pasta com o número, exemplos: 760, 860, 1098, etc). - Abra o otclient.exe. 5 - Créditos: Edubart (Sources OTClient) Majesty (Downloads Mediafire + Tutorial CMake e Codeblocks)
Esta tabela de classificação está definida como São Paulo/GMT-03:00
×