Tabela de Classificação
Conteúdo Mais Visto
Exibindo conteúdo com a maior reputação em 3em todas áreas
-
3 pontos
[OTClient] Entendendo as funções Opcodes
Raulcdj and 2 outros deu reputação para Gengo for uma resposta no tópico
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: -
1 ponto
Problema com Atributo de % de dano Magico 7.6
Luan MF deu reputação para Majesty for uma resposta no tópico
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. -
1 ponto
Extended Opcodes
Raulcdj deu reputação para Majesty for uma resposta no tópico
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 -
1 ponto
Como usar opcode
TEKADON deu reputação para Gengo for uma resposta no tópico
O numero que vc está utilizando no opcodes que vc está testando, já deve estar em uso, tente um outro numero. -
1 ponto
Como usar opcode
TEKADON deu reputação para Gengo for uma resposta no tópico
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. -
1 ponto
[Windows][Codeblocks] Compilando Sources OTClient
Nother deu reputação para Majesty for uma resposta no tópico
[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)