diff --git a/src/otclient/core/game.cpp b/src/otclient/core/game.cpp index 18b05694..69e94cf3 100644 --- a/src/otclient/core/game.cpp +++ b/src/otclient/core/game.cpp @@ -974,6 +974,20 @@ void Game::requestQuestLine(int questId) m_protocolGame->sendRequestQuestLine(questId); } +void Game::equipItem(const ItemPtr& item) +{ + if(!canPerformGameAction()) + return; + m_protocolGame->sendEquipItem(item->getId(), item->getCountOrSubType()); +} + +void Game::mount(bool mount) +{ + if(!canPerformGameAction()) + return; + m_protocolGame->sendMount(mount); +} + bool Game::checkBotProtection() { #ifdef BOT_PROTECTION diff --git a/src/otclient/core/game.h b/src/otclient/core/game.h index 13cebb4c..f577dbf4 100644 --- a/src/otclient/core/game.h +++ b/src/otclient/core/game.h @@ -220,6 +220,15 @@ public: void requestQuestLog(); void requestQuestLine(int questId); + // 870 only + void equipItem(const ItemPtr& item); + void mount(bool mount); + + // 910 only + //void requestItemInfo(); + //void reportRuleViolation2(); + // TODO: market related + bool canPerformGameAction(); bool canReportBugs() { return m_canReportBugs; } bool checkBotProtection(); diff --git a/src/otclient/luafunctions.cpp b/src/otclient/luafunctions.cpp index cfd7edc0..1db624d6 100644 --- a/src/otclient/luafunctions.cpp +++ b/src/otclient/luafunctions.cpp @@ -146,6 +146,8 @@ void OTClient::registerLuaFunctions() g_lua.bindClassStaticFunction("g_game", "editList", std::bind(&Game::editList, &g_game, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); g_lua.bindClassStaticFunction("g_game", "requestQuestLog", std::bind(&Game::requestQuestLog, &g_game)); g_lua.bindClassStaticFunction("g_game", "requestQuestLine", std::bind(&Game::requestQuestLine, &g_game, std::placeholders::_1)); + g_lua.bindClassStaticFunction("g_game", "equipItem", std::bind(&Game::equipItem, &g_game, std::placeholders::_1)); + g_lua.bindClassStaticFunction("g_game", "mount", std::bind(&Game::mount, &g_game, std::placeholders::_1)); g_lua.bindClassStaticFunction("g_game", "canPerformGameAction", std::bind(&Game::canPerformGameAction, &g_game)); g_lua.bindClassStaticFunction("g_game", "canReportBugs", std::bind(&Game::canReportBugs, &g_game)); g_lua.bindClassStaticFunction("g_game", "checkBotProtection", std::bind(&Game::checkBotProtection, &g_game)); diff --git a/src/otclient/net/protocolcodes.h b/src/otclient/net/protocolcodes.h index 148e3b4c..2610a2e5 100644 --- a/src/otclient/net/protocolcodes.h +++ b/src/otclient/net/protocolcodes.h @@ -81,7 +81,7 @@ namespace Proto { LoginServerCharacterList = 100 }; - enum GameServerOpts { + enum GameServerOpcodes { GameServerInitGame = 10, GameServerGMActions = 11, GameServerLoginError = 20, @@ -96,6 +96,18 @@ namespace Proto { #endif GameServerChallange = 31, GameServerDeath = 40, + + // all in game opcodes must be equal or greater than 50 + GameServerFirstGameOpcode = 50, + + // NOTE: add any custom opcodes in this range + // 50 - 97 + + // otclient ONLY + GameServerExtendedP2POpcode = 98, + GameServerExtendedOpcode = 99, + + // original tibia ONLY GameServerFullMap = 100, GameServerMapTopRow = 101, GameServerMapRightRow = 102, @@ -134,13 +146,14 @@ namespace Proto { GameServerCreatureUnpass = 146, GameServerEditText = 150, GameServerEditList = 151, - GameServerPlayerDataBasic = 159, + GameServerPlayerDataBasic = 159, // 910 GameServerPlayerData = 160, GameServerPlayerSkills = 161, GameServerPlayerState = 162, GameServerClearTarget = 163, GameServerSpellDelay = 164, // 870 GameServerSpellGroupDelay = 165, // 870 + GameServerMultiUseDelay = 166, // 870 GameServerTalk = 170, GameServerChannels = 171, GameServerOpenChannel = 172, @@ -153,7 +166,7 @@ namespace Proto { GameServerCloseChannel = 179, GameServerTextMessage = 180, GameServerCancelWalk = 181, - GameServerWait = 182, + GameServerWalkWait = 182, GameServerFloorChangeUp = 190, GameServerFloorChangeDown = 191, GameServerChooseOutfit = 200, @@ -164,25 +177,33 @@ namespace Proto { GameServerAutomapFlag = 221, GameServerQuestLog = 240, GameServerQuestLine = 241, - GameServerChannelEvent = 243, - GameServerObjectInfo = 244, // 910 + GameServerChannelEvent = 243, // 910 + GameServerItemInfo = 244, // 910 GameServerPlayerInventory = 245, // 910 GameServerMarketEnter = 246, // 944 GameServerMarketLeave = 247, // 944 - GameServerMarketBrowseItem = 248, // 944 - GameServerMarketAcceptOffer = 249, // 944 - GameServerMarketOwnOffers = 250, // 944 - GameServerMarketCancelOffer = 251, // 944 - GameServerMarketBrowseOwnHistory = 252, // 944 - GameServerMarketMarketDetail = 253, // 944 - GameServerExtendedOpcode = 254 // otclient only + GameServerMarketDetail = 248, // 944 + GameServerMarketBrowse = 249, // 944 }; - enum ClientOpts { + enum ClientOpcodes { ClientEnterAccount = 1, ClientEnterGame = 10, ClientLeaveGame = 20, - ClientPingResponse = 30, + ClientPing = 29, + ClientPingBack = 30, + + // all in game opcodes must be equal or greater than 50 + ClientFirstGameOpcode = 50, + + // NOTE: add any custom opcodes in this range + // 50 - 97 + + // otclient ONLY + ClientExtendedP2POpcode = 98, + ClientExtendedOpcode = 99, + + // original tibia ONLY ClientAutoWalk = 100, ClientWalkNorth = 101, ClientWalkEast = 102, @@ -197,7 +218,7 @@ namespace Proto { ClientTurnEast = 112, ClientTurnSouth = 113, ClientTurnWest = 114, - ClientEquipObject = 119, // 910 + ClientEquipItem = 119, // 910 ClientMove = 120, ClientInspectNpcTrade = 121, ClientBuyItem = 122, @@ -247,14 +268,13 @@ namespace Proto { ClientDebugReport = 232, ClientRequestQuestLog = 240, ClientRequestQuestLine = 241, - ClientRuleViolationReport = 242, // 910 - ClientGetObjectInfo = 243, // 910 + ClientNewRuleViolation = 242, // 910 + ClientRequestItemInfo = 243, // 910 ClientMarketLeave = 244, // 944 ClientMarketBrowse = 245, // 944 - ClientMarketCreateOffer = 246, // 944 - ClientMarketCancelOffer = 247, // 944 - ClientMarketAcceptOffer = 248, // 944 - ClientExtendedOpcode = 254 // otclient only + ClientMarketCreate = 246, // 944 + ClientMarketCancel = 247, // 944 + ClientMarketAccept = 248, // 944 }; enum ServerSpeakType { @@ -274,7 +294,7 @@ namespace Proto { ServerSpeakChannelRed, ServerSpeakPrivateRedFrom, // new ServerSpeakPrivateRedTo, // new - // 16 - 33 ?? + // 16 - 33 ServerSpeakMonsterSay = 34, ServerSpeakMonsterYell, @@ -324,9 +344,9 @@ namespace Proto { ServerSpeakPrivateRedTo, ServerSpeakPrivateRedFrom = ServerSpeakPrivateRedTo, ServerSpeakChannelOrange, - // 16 ?? + // 16 ServerSpeakChannelRed2 = 17, - // 18 ?? + // 18 ServerSpeakMonsterSay = 19, ServerSpeakMonsterYell #elif PROTOCOL>=810 @@ -344,9 +364,9 @@ namespace Proto { ServerSpeakPrivateRedTo, ServerSpeakPrivateRedFrom = ServerSpeakPrivateRedTo, ServerSpeakChannelOrange, - // 13 ?? + // 13 ServerSpeakChannelRed2 = 14, - // 15 ?? + // 15 ServerSpeakMonsterSay = 16, ServerSpeakMonsterYell, @@ -359,11 +379,11 @@ namespace Proto { enum MessageTypes { #if PROTOCOL>=910 - // 1-3 ?? + // 1-3 MessageConsoleBlue = 4, // old - // 5-11 ?? + // 5-11 MessageConsoleRed = 12, // old - // 13-15 ?? + // 13-15 MessageStatusDefault = 16, // old MessageWarning, // old MessageEventAdvance, // old diff --git a/src/otclient/net/protocolgame.h b/src/otclient/net/protocolgame.h index 293baffa..e0c409fb 100644 --- a/src/otclient/net/protocolgame.h +++ b/src/otclient/net/protocolgame.h @@ -38,7 +38,8 @@ public: void onError(const boost::system::error_code& error); void sendLogout(); - void sendPingResponse(); + void sendPing(); + void sendPingBack(); void sendAutoWalk(const std::vector& path); void sendWalkNorth(); void sendWalkEast(); @@ -53,6 +54,7 @@ public: void sendTurnEast(); void sendTurnSouth(); void sendTurnWest(); + void sendEquipItem(int itemId, int countOrSubType); void sendMove(const Position& fromPos, int itemId, int stackpos, const Position& toPos, int count); void sendInspectNpcTrade(int itemId, int count); void sendBuyItem(int itemId, int subType, int amount, bool ignoreCapacity, bool buyWithBackpack); @@ -93,6 +95,7 @@ public: void sendRefreshContainer(); void sendRequestOutfit(); void sendChangeOutfit(const Outfit& outfit); + void sendMount(bool mount); void sendAddVip(const std::string& name); void sendRemoveVip(uint playerId); void sendBugReport(const std::string& comment); @@ -100,6 +103,15 @@ public: void sendDebugReport(const std::string& a, const std::string& b, const std::string& c, const std::string& d); void sendRequestQuestLog(); void sendRequestQuestLine(int questId); + void sendNewNewRuleViolation(int reason, int action, const std::string& characterName, const std::string& comment, const std::string& translation); + void sendRequestItemInfo(int itemId, int index); + /* + void sendMarketLeave(); + void sendMarketBrowse(); + void sendMarketCreate(); + void sendMarketCancel(); + void sendMarketAccept(); + */ void sendExtendedOpcode(uint8 opcode, const std::string& buffer); private: @@ -114,6 +126,7 @@ private: void parseLoginAdvice(InputMessage& msg); void parseLoginWait(InputMessage& msg); void parsePing(InputMessage& msg); + void parsePingBack(InputMessage& msg); void parseChallange(InputMessage& msg); void parseDeath(InputMessage& msg); void parseMapDescription(InputMessage& msg); @@ -141,6 +154,7 @@ private: void parseAnimatedText(InputMessage& msg); void parseDistanceMissile(InputMessage& msg); void parseCreatureMark(InputMessage& msg); + void parseTrappers(InputMessage& msg); void parseCreatureHealth(InputMessage& msg); void parseCreatureLight(InputMessage& msg); void parseCreatureOutfit(InputMessage& msg); @@ -158,6 +172,7 @@ private: void parsePlayerCancelAttack(InputMessage& msg); void parseSpellDelay(InputMessage& msg); void parseSpellGroupDelay(InputMessage& msg); + void parseMultiUseDelay(InputMessage& msg); void parseCreatureSpeak(InputMessage& msg); void parseChannelList(InputMessage& msg); void parseOpenChannel(InputMessage& msg); @@ -173,6 +188,7 @@ private: void parseCloseTrade(InputMessage&); void parseTextMessage(InputMessage& msg); void parseCancelWalk(InputMessage& msg); + void parseWalkWait(InputMessage& msg); void parseFloorChangeUp(InputMessage& msg); void parseFloorChangeDown(InputMessage& msg); void parseOpenOutfitWindow(InputMessage& msg); @@ -184,7 +200,7 @@ private: void parseQuestLog(InputMessage& msg); void parseQuestLine(InputMessage& msg); void parseChannelEvent(InputMessage& msg); - void parseObjectInfo(InputMessage& msg); + void parseItemInfo(InputMessage& msg); void parsePlayerInventory(InputMessage& msg); void parseExtendedOpcode(InputMessage& msg); diff --git a/src/otclient/net/protocolgameparse.cpp b/src/otclient/net/protocolgameparse.cpp index 21f28bcd..be932ee0 100644 --- a/src/otclient/net/protocolgameparse.cpp +++ b/src/otclient/net/protocolgameparse.cpp @@ -42,8 +42,8 @@ void ProtocolGame::parseMessage(InputMessage& msg) while(!msg.eof()) { opcode = msg.getU8(); - if(!m_gameInitialized && opcode >= Proto::GameServerFullMap) - logWarning("first game network opcode is not GameServerInitGame"); + if(!m_gameInitialized && opcode >= Proto::GameServerFirstGameOpcode) + logWarning("received a game opcode from the server, but the game is not initialized yet, this is a server side bug"); switch(opcode) { case Proto::GameServerInitGame: @@ -65,7 +65,7 @@ void ProtocolGame::parseMessage(InputMessage& msg) parsePing(msg); break; case Proto::GameServerPingBack: - // nothing todo + parsePingBack(msg); break; case Proto::GameServerChallange: parseChallange(msg); @@ -157,6 +157,9 @@ void ProtocolGame::parseMessage(InputMessage& msg) case Proto::GameServerMarkCreature: parseCreatureMark(msg); break; + case Proto::GameServerTrappers: + parseTrappers(msg); + break; case Proto::GameServerCreatureHealth: parseCreatureHealth(msg); break; @@ -232,6 +235,9 @@ void ProtocolGame::parseMessage(InputMessage& msg) case Proto::GameServerCancelWalk: parseCancelWalk(msg); break; + case Proto::GameServerWalkWait: + parseWalkWait(msg); + break; case Proto::GameServerFloorChangeUp: parseFloorChangeUp(msg); break; @@ -262,47 +268,40 @@ void ProtocolGame::parseMessage(InputMessage& msg) case Proto::GameServerQuestLine: parseQuestLine(msg); break; -#if PROTOCOL>=870 + // PROTOCOL>=870 case Proto::GameServerSpellDelay: parseSpellDelay(msg); break; case Proto::GameServerSpellGroupDelay: parseSpellGroupDelay(msg); break; -#endif -#if PROTOCOL>=910 + case Proto::GameServerMultiUseDelay: + parseMultiUseDelay(msg); + break; + // PROTOCOL>=910 case Proto::GameServerPlayerDataBasic: parsePlayerInfo(msg); break; case Proto::GameServerChannelEvent: parseChannelEvent(msg); break; - case Proto::GameServerObjectInfo: - parseObjectInfo(msg); + case Proto::GameServerItemInfo: + parseItemInfo(msg); break; case Proto::GameServerPlayerInventory: parsePlayerInventory(msg); break; -#endif -#if PROTOCOL>=944 + // PROTOCOL>=944 + /* case Proto::GameServerMarketEnter: case Proto::GameServerMarketLeave: - case Proto::GameServerMarketBrowseItem: - case Proto::GameServerMarketAcceptOffer: - case Proto::GameServerMarketOwnOffers: - case Proto::GameServerMarketCancelOffer: - case Proto::GameServerMarketBrowseOwnHistory: - case Proto::GameServerMarketMarketDetail: - //TODO - break; -#endif - // additional opcode used by otclient only + case Proto::GameServerMarketDetail: + case Proto::GameServerMarketBrowse: + */ + // otclient ONLY case Proto::GameServerExtendedOpcode: parseExtendedOpcode(msg); break; - // not handled yet - //case Proto::GameServerTrappers - //case Proto::GameServerWait: default: Fw::throwException("unknown opcode"); break; @@ -358,7 +357,12 @@ void ProtocolGame::parseLoginWait(InputMessage& msg) void ProtocolGame::parsePing(InputMessage& msg) { g_game.processPing(); - sendPingResponse(); + sendPingBack(); +} + +void ProtocolGame::parsePingBack(InputMessage& msg) +{ + // nothing to do } void ProtocolGame::parseChallange(InputMessage& msg) @@ -688,6 +692,23 @@ void ProtocolGame::parseCreatureMark(InputMessage& msg) logTraceError("could not get creature"); } +void ProtocolGame::parseTrappers(InputMessage& msg) +{ + int numTrappers = msg.getU8(); + + if(numTrappers > 8) + logTraceError("too many trappers"); + + for(int i=0;i +/* + ClientEquipObject + ClientRefreshContainer + ClientMount + ClientRuleViolationReport + ClientGetItemInfo + ClientMarketLeave + ClientMarketBrowse + ClientMarketCreate + ClientMarketCancel + ClientMarketAccept + ClientExtendedOpcode = 254 // otclient only + */ void ProtocolGame::sendLoginPacket(uint challangeTimestamp, uint8 challangeRandom) { OutputMessage msg; @@ -83,10 +96,17 @@ void ProtocolGame::sendLogout() send(msg); } -void ProtocolGame::sendPingResponse() +void ProtocolGame::sendPing() +{ + OutputMessage msg; + msg.addU8(Proto::ClientPing); + send(msg); +} + +void ProtocolGame::sendPingBack() { OutputMessage msg; - msg.addU8(Proto::ClientPingResponse); + msg.addU8(Proto::ClientPingBack); send(msg); } @@ -222,6 +242,15 @@ void ProtocolGame::sendTurnWest() send(msg); } +void ProtocolGame::sendEquipItem(int itemId, int countOrSubType) +{ + OutputMessage msg; + msg.addU8(Proto::ClientEquipItem); + msg.addU16(itemId); + msg.addU8(countOrSubType); + send(msg); +} + void ProtocolGame::sendMove(const Position& fromPos, int thingId, int stackpos, const Position& toPos, int count) { OutputMessage msg; @@ -587,14 +616,20 @@ void ProtocolGame::sendChangeOutfit(const Outfit& outfit) { OutputMessage msg; msg.addU8(Proto::ClientChangeOutfit); - msg.addU16(outfit.getId()); msg.addU8(outfit.getHead()); msg.addU8(outfit.getBody()); msg.addU8(outfit.getLegs()); msg.addU8(outfit.getFeet()); msg.addU8(outfit.getAddons()); + send(msg); +} +void ProtocolGame::sendMount(bool mount) +{ + OutputMessage msg; + msg.addU8(Proto::ClientMount); + msg.addU8(mount); send(msg); } @@ -662,6 +697,28 @@ void ProtocolGame::sendRequestQuestLine(int questId) send(msg); } +void ProtocolGame::sendNewNewRuleViolation(int reason, int action, const std::string& characterName, const std::string& comment, const std::string& translation) +{ + OutputMessage msg; + msg.addU8(Proto::ClientNewRuleViolation); + msg.addU8(reason); + msg.addU8(action); + msg.addString(characterName); + msg.addString(comment); + msg.addString(translation); + send(msg); +} + +void ProtocolGame::sendRequestItemInfo(int itemId, int index) +{ + OutputMessage msg; + msg.addU8(Proto::ClientRequestItemInfo); + msg.addU8(1); // count, 1 for just one item + msg.addU16(itemId); + msg.addU8(index); + send(msg); +} + void ProtocolGame::sendExtendedOpcode(uint8 opcode, const std::string& buffer) { OutputMessage msg;