Bom galera, como todo mundo sabe eu não curto a versão liberada pelo Open Tibia Server Team ( mais conhecido como CVS ), então a um tempo, eu resolvi começar um protocolo próprio, porém isso me trouxe problemas e perca de tempo....
Então eu parei, e deixei o projeto descontinuado, então para não ficar ocupando espaço aqui no meu computador, eu resolvi posta-los para vocês aprenderem e verem como eu fiz, quem sabe até continuar certo?
O que tem o "Protocolo" :
- Versão 7.1 ( prefiri pois não utiliza Criptografia para enviar dados, e sei lá, axo mais romântico )
- Char List;
- GameWorld Connect.
O que NÃO tem :
- Poder "andar" no servidor;
- Database ( quer dizer, sempre o mesmo char );
- Ações básicas.
Agora vocês me perguntam....
Então, já que não tem nada, porque você liberou?
Sei lá, pra vocês terem um conhecimento básico de como mecher com WinSocket...
são somente 2 arquivos :
main.cpp
#include "NetworkMessage.h"#include "main.h"int main() { // Inicializa o Winsock. WSADATA wsaData; int iResult = WSAStartup( MAKEWORD(2,2), &wsaData ); if ( iResult != NO_ERROR ) std::cout << "Error at WSAStartup()\n" << std::endl; // Cria um novo Socket SOCKET m_socket; m_socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); char Host[128]; hostent *HostEntry = NULL; if(gethostname(Host, 128) == 0){ HostEntry = gethostbyname(Host); if(HostEntry){ unsigned char** addr = (unsigned char**)HostEntry->h_addr_list; // Equivaleria ao IP do config.lua addr = (unsigned char**)HostEntry->h_addr_list; addr++; HosterIP = addr[0][0]+(addr[0][1] << 8) + (addr[0][2] << 16) + (addr[0][3] << 24); } } // Configura o novo Socket sockaddr_in service; service.sin_family = AF_INET; service.sin_port = htons(7171); service.sin_addr.s_addr = INADDR_ANY; if ( bind( m_socket, (SOCKADDR*) &service, sizeof(service) ) == SOCKET_ERROR ) { std::cout << "bind() failed.\n" << std::endl; closesocket(m_socket); return 0; } // Tenta ler o Socket if ( listen( m_socket, 1 ) == SOCKET_ERROR ) std::cout << "Error listening on socket.\n" << std::endl; // Aceita Conexões while (true) { // Aceita um novo Socket SOCKET s = accept( m_socket, NULL, NULL ); if(s > 0) // o Socket é válido ClientConect(s); } WSACleanup(); return 0;}int ClientConect(SOCKET s){ NetworkMessage msg; if(!msg.ReadFromSocket(s)) // O Socket enviado num tá correto... MANDEO PARA O INFERNO! return 0; unsigned short ProtocolID = msg.GetU16(); msg.Reset(); // Muda a posição de escrita pra 2 (depois dos 2 bytes da length) if(ProtocolID == 0x0201) // O CVS me deu uma ajudinha aqui :X { msg.AddByte(0x14); std::stringstream motd; motd << "1"; motd << "\n"; motd << "Mensagem"; msg.AddString(motd.str()); msg.AddByte(0x64); // Box da lista de chars msg.AddByte(1); // Número de Chars msg.AddString("Kyo"); msg.AddString("OpenTibia"); msg.AddU32(HosterIP); msg.AddU16(7171); msg.AddU16(999); // Premmy Days /* // Como mandar uma mensagem de erro... msg.AddByte(0x0A); // mensagem de erro ( "Sorry" ) msg.AddString("Conexão Correta."); */ } else if(ProtocolID == 0x020A) // GameWorld Connect { msg.AddByte(0x0A); msg.AddU32(10);//id msg.AddByte(0x32); msg.AddByte(0x00); // Adding the Player to the Map msg.AddByte(0x64); // Position Code msg.AddU16(50); msg.AddU16(50); msg.AddByte(7); for (int x = 0; x < 18; x++) for (int y = 0; y < 14; y++) { msg.AddU16(102); // ID do chão if ((x == 8) && (y == 6)) // Posição do Player { msg.AddByte(0x61); msg.AddByte(0x00); msg.AddU32(0); // ? msg.AddU32(10); // ID do player msg.AddString("Kyo"); // Nome do Player msg.AddByte(50); // Porcentagem de vida msg.AddByte(2); // Direção msg.AddByte(128); // Looktype msg.AddByte(114); msg.AddByte(114); msg.AddByte(114); msg.AddByte(114); msg.AddByte(0x00); // Luz ? msg.AddByte(0xDC); // Luz ? msg.AddU16(300); // Velocidade } if ((x != 18) || (y != 14)) { msg.AddByte(0); msg.AddByte(0xFF); } } // Multi-lvl bytes msg.AddByte(0xFF); msg.AddByte(0xFF); msg.AddByte(0xFF); msg.AddByte(0xFF); msg.AddByte(0xFF); msg.AddByte(0xFF); msg.AddByte(0xFF); msg.AddByte(0xFF); msg.AddByte(0xFF); msg.AddByte(0xFF); msg.AddByte(0xFF); msg.AddByte(0xFF); // World Light Level msg.AddByte(0xE4); // TODO Light level msg.AddByte(0xFF); // TODO Light Color // Status msg.AddByte(0xA0); msg.AddU16(1000); msg.AddU16(1000); msg.AddU16(300); msg.AddU32(100); msg.AddByte(1); msg.AddU16(1000); msg.AddU16(1000); msg.AddByte(100); // Player Light Level msg.AddByte(0x82); //Light Code msg.AddByte(0x6F); //Light Level msg.AddByte(0xd7); //Light Color // Player Inventory msg.AddByte(0xA1); // Skills msg.AddByte(10); msg.AddByte(10); msg.AddByte(10); msg.AddByte(10); msg.AddByte(10); msg.AddByte(10); msg.AddByte(10); msg.WriteToSocket(s); msg.Reset(); // Muda a posição de escrita pra 2 (depois dos 2 bytes da length) } else { // Retorna o Protocolo que foi enviado em Hex std::cout << "Unknow Protocol connect where ID = "; for (int i=2*sizeof(ProtocolID) - 1; i>=0; i--) { std::cout << "0123456789ABCDEF"[((ProtocolID >> i*4) & 0xF)]; } std::cout << std::endl; } // Envia o Socket para o Cliente msg.WriteToSocket(s);}
main.h
#ifndef _MAIN_H_#define _MAIN_H_#include "winsock2.h"#include <iostream>#include <sstream>int HosterIP;int ClientConect(SOCKET s);#endif
E o "NetworkMessage.cpp" e "NetworkMessage.h" vocês podem usar o do CVS team, ou podem aprimora-lo que nem eu fiz ( ty Vitor por tem me ajudado
)
Caso alguem pergunte, a única coisa que vai precisar pra compilar é colocar no "Linker" isso : -lwsock32
Kyo~*