mirror of
https://github.com/mehah/otclient
synced 2026-08-15 16:29:06 -04:00
feat: Cam system by kondra (#1116)
This commit is contained in:
parent
ea464b491c
commit
4694714921
21 changed files with 1046 additions and 4 deletions
|
|
@ -468,6 +468,7 @@ Beyond of it's flexibility with scripts, otclient comes with tons of other featu
|
|||
- Placeholder
|
||||
- UIGraph
|
||||
- keybinds
|
||||
- Cam system
|
||||
|
||||
## <a name="themobileproject"><img height="32" src="https://raw.githubusercontent.com/github/explore/80688e429a7d4ef2fca1e82350fe8e3517d3494d/topics/android/android.png" alt="Android"> The Mobile Project </a>
|
||||
The Mobile Project
|
||||
|
|
|
|||
3
meta.lua
3
meta.lua
|
|
@ -710,8 +710,9 @@ g_game = {}
|
|||
---@param characterName string
|
||||
---@param authenticatorToken string
|
||||
---@param sessionKey string
|
||||
---@param recordTo string
|
||||
function g_game.loginWorld(account, password, worldName, worldHost, worldPort, characterName, authenticatorToken,
|
||||
sessionKey)
|
||||
sessionKey, recordTo)
|
||||
end
|
||||
|
||||
function g_game.cancelLogin() end
|
||||
|
|
|
|||
4
records/.gitignore
vendored
Normal file
4
records/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
*
|
||||
!.gitignore
|
||||
!README.md
|
||||
!test1098.cam
|
||||
28
records/README.md
Normal file
28
records/README.md
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# Record On Client
|
||||
|
||||
`modules/client_entergame/characterlist.lua`
|
||||
https://github.com/mehah/otclient/blob/5bf0e87ff4393d300c02e9185f18e8cea9f52a90/modules/client_entergame/characterlist.lua#L48
|
||||
Add an argument to the function `g_game.loginWorld` , which represents the name and extension.
|
||||
|
||||
Ex: `os.time() .. '.cam'`
|
||||
```diff
|
||||
- g_game.loginWorld(G.account, G.password, charInfo.worldName, charInfo.worldHost, charInfo.worldPort, charInfo.characterName, G.authenticatorToken, G.sessionKey)
|
||||
+ g_game.loginWorld(G.account, G.password, charInfo.worldName, charInfo.worldHost, charInfo.worldPort, charInfo.characterName, G.authenticatorToken, G.sessionKey, os.time() .. '.cam')
|
||||
```
|
||||
|
||||
# Record On TFS by gesior
|
||||
1) Add these changes https://github.com/gesior/tmp-cams-system
|
||||
2) the server will create the .cam file
|
||||
3) move the created file from the tfs/records folder to the OTC/records folder
|
||||
|
||||
# Play Record
|
||||
In terminal :
|
||||
```lua
|
||||
g_game.setClientVersion(1098)
|
||||
g_game.setProtocolVersion(g_game.getClientProtocolVersion(1098))
|
||||
```
|
||||
|
||||
```lua
|
||||
g_game.playRecord("test1098.cam")
|
||||
EnterGame.hide()
|
||||
```
|
||||
641
records/test1098.cam
Normal file
641
records/test1098.cam
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -300,6 +300,8 @@ set(SOURCE_FILES
|
|||
framework/util/crypt.cpp
|
||||
framework/proxy/proxy.cpp
|
||||
framework/proxy/proxy_client.cpp
|
||||
framework/net/packet_player.cpp
|
||||
framework/net/packet_recorder.cpp
|
||||
|
||||
client/animatedtext.cpp
|
||||
client/animator.cpp
|
||||
|
|
|
|||
|
|
@ -34,6 +34,9 @@
|
|||
#include "framework/core/graphicalapplication.h"
|
||||
#include "tile.h"
|
||||
|
||||
#include <framework/net/packet_player.h>
|
||||
#include <framework/net/packet_recorder.h>
|
||||
|
||||
Game g_game;
|
||||
|
||||
void Game::init()
|
||||
|
|
@ -590,7 +593,7 @@ void Game::processWalkCancel(const Otc::Direction direction)
|
|||
m_localPlayer->cancelWalk(direction);
|
||||
}
|
||||
|
||||
void Game::loginWorld(const std::string_view account, const std::string_view password, const std::string_view worldName, const std::string_view worldHost, const int worldPort, const std::string_view characterName, const std::string_view authenticatorToken, const std::string_view sessionKey)
|
||||
void Game::loginWorld(const std::string_view account, const std::string_view password, const std::string_view worldName, const std::string_view worldHost, const int worldPort, const std::string_view characterName, const std::string_view authenticatorToken, const std::string_view sessionKey, const std::string_view& recordTo)
|
||||
{
|
||||
if (m_protocolGame || isOnline())
|
||||
throw Exception("Unable to login into a world while already online or logging.");
|
||||
|
|
@ -606,11 +609,38 @@ void Game::loginWorld(const std::string_view account, const std::string_view pas
|
|||
m_localPlayer->setName(characterName);
|
||||
|
||||
m_protocolGame = std::make_shared<ProtocolGame>();
|
||||
if (!recordTo.empty()) {
|
||||
m_protocolGame->setRecorder(std::make_shared<PacketRecorder>(recordTo));
|
||||
}
|
||||
m_protocolGame->login(account, password, worldHost, static_cast<uint16_t>(worldPort), characterName, authenticatorToken, sessionKey);
|
||||
m_characterName = characterName;
|
||||
m_worldName = worldName;
|
||||
}
|
||||
|
||||
void Game::playRecord(const std::string_view& file)
|
||||
{
|
||||
if (m_protocolGame || isOnline())
|
||||
throw Exception("Unable to login into a world while already online or logging.");
|
||||
|
||||
if (m_protocolVersion == 0)
|
||||
throw Exception("Must set a valid game protocol version before logging.");
|
||||
|
||||
auto packetPlayer = std::make_shared<PacketPlayer>(file);
|
||||
if (!packetPlayer)
|
||||
throw Exception("Invalid record file.");
|
||||
|
||||
// reset the new game state
|
||||
resetGameStates();
|
||||
|
||||
m_localPlayer = std::make_shared<LocalPlayer>();
|
||||
m_localPlayer->setName("Player");
|
||||
|
||||
m_protocolGame = std::make_shared<ProtocolGame>();
|
||||
m_protocolGame->playRecord(packetPlayer);
|
||||
m_characterName = "Player";
|
||||
m_worldName = "Record";
|
||||
}
|
||||
|
||||
void Game::cancelLogin()
|
||||
{
|
||||
enableBotCall();
|
||||
|
|
|
|||
|
|
@ -545,7 +545,8 @@ protected:
|
|||
|
||||
public:
|
||||
// login related
|
||||
void loginWorld(std::string_view account, std::string_view password, std::string_view worldName, std::string_view worldHost, int worldPort, std::string_view characterName, std::string_view authenticatorToken, std::string_view sessionKey);
|
||||
void loginWorld(std::string_view account, std::string_view password, std::string_view worldName, std::string_view worldHost, int worldPort, std::string_view characterName, std::string_view authenticatorToken, std::string_view sessionKey, const std::string_view& recordTo);
|
||||
void playRecord(const std::string_view& file);
|
||||
void cancelLogin();
|
||||
void forceLogout();
|
||||
void safeLogout();
|
||||
|
|
|
|||
|
|
@ -225,6 +225,7 @@ void Client::registerLuaFunctions()
|
|||
|
||||
g_lua.registerSingletonClass("g_game");
|
||||
g_lua.bindSingletonFunction("g_game", "loginWorld", &Game::loginWorld, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "playRecord", &Game::playRecord, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "cancelLogin", &Game::cancelLogin, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "forceLogout", &Game::forceLogout, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "safeLogout", &Game::safeLogout, &g_game);
|
||||
|
|
|
|||
|
|
@ -24,6 +24,9 @@
|
|||
#include "framework/net/inputmessage.h"
|
||||
#include "game.h"
|
||||
|
||||
#include <framework/net/packet_player.h>
|
||||
#include <framework/net/packet_recorder.h>
|
||||
|
||||
void ProtocolGame::login(const std::string_view accountName, const std::string_view accountPassword, const std::string_view host, uint16_t port,
|
||||
const std::string_view characterName, const std::string_view authenticatorToken, const std::string_view sessionKey)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -375,6 +375,7 @@ private:
|
|||
bool m_gameInitialized{ false };
|
||||
bool m_mapKnown{ false };
|
||||
bool m_firstRecv{ true };
|
||||
bool m_record {false};
|
||||
|
||||
std::string m_accountName;
|
||||
std::string m_accountPassword;
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@ class Connection;
|
|||
class Protocol;
|
||||
class ProtocolHttp;
|
||||
class Server;
|
||||
class PacketPlayer;
|
||||
class PacketRecorder;
|
||||
|
||||
using InputMessagePtr = std::shared_ptr<InputMessage>;
|
||||
using OutputMessagePtr = std::shared_ptr<OutputMessage>;
|
||||
|
|
@ -46,3 +48,5 @@ using ConnectionPtr = std::shared_ptr<Connection>;
|
|||
using ProtocolPtr = std::shared_ptr<Protocol>;
|
||||
using ProtocolHttpPtr = std::shared_ptr<ProtocolHttp>;
|
||||
using ServerPtr = std::shared_ptr<Server>;
|
||||
using PacketPlayerPtr = std::shared_ptr<PacketPlayer>;
|
||||
using PacketRecorderPtr = std::shared_ptr<PacketRecorder>;
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ public:
|
|||
|
||||
void setBuffer(const std::string& buffer);
|
||||
std::string_view getBuffer() { return std::string_view{ (char*)m_buffer + m_headerPos, m_messageSize }; }
|
||||
std::string getBodyBuffer() { return std::string((char*)m_buffer + MAX_HEADER_SIZE, m_messageSize - getHeaderSize()); }
|
||||
|
||||
void skipBytes(const uint16_t bytes) { m_readPos += bytes; }
|
||||
void setReadPos(const uint16_t readPos) { m_readPos = readPos; }
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ protected:
|
|||
void writeMessageSize();
|
||||
|
||||
friend class Protocol;
|
||||
friend class PacketPlayer;
|
||||
|
||||
private:
|
||||
bool canWrite(int bytes) const;
|
||||
|
|
|
|||
106
src/framework/net/packet_player.cpp
Normal file
106
src/framework/net/packet_player.cpp
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2024 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <framework/global.h>
|
||||
#include <framework/core/clock.h>
|
||||
#include <filesystem>
|
||||
|
||||
#include "packet_player.h"
|
||||
|
||||
PacketPlayer::~PacketPlayer()
|
||||
{
|
||||
if (m_event)
|
||||
m_event->cancel();
|
||||
}
|
||||
|
||||
PacketPlayer::PacketPlayer(const std::string_view& file)
|
||||
{
|
||||
static uint32_t sessionId = 1;
|
||||
#ifdef ANDROID
|
||||
std::ifstream f(std::string("records/") + file);
|
||||
#else
|
||||
std::ifstream f(std::filesystem::path("records") / file);
|
||||
#endif
|
||||
if (!f.is_open())
|
||||
return;
|
||||
std::string type, packetHex;
|
||||
ticks_t time;
|
||||
while (f >> type >> time >> packetHex) {
|
||||
// Convert hex string to binary data manually
|
||||
std::string packetStr;
|
||||
for (size_t i = 0; i < packetHex.length(); i += 2) {
|
||||
std::string byteString = packetHex.substr(i, 2);
|
||||
char byte = (char)strtol(byteString.c_str(), nullptr, 16);
|
||||
packetStr.push_back(byte);
|
||||
}
|
||||
auto packet = std::make_shared<std::vector<uint8_t>>(packetStr.begin(), packetStr.end());
|
||||
if (type == "<") {
|
||||
m_input.push_back(std::make_pair(time, packet));
|
||||
} else if (type == ">") {
|
||||
m_output.push_back(std::make_pair(time, packet));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PacketPlayer::start(std::function<void(std::shared_ptr<std::vector<uint8_t>>)> recvCallback,
|
||||
std::function<void(std::error_code)> disconnectCallback)
|
||||
{
|
||||
m_start = g_clock.millis();
|
||||
m_recvCallback = recvCallback;
|
||||
m_disconnectCallback = disconnectCallback;
|
||||
m_event = g_dispatcher.scheduleEvent(std::bind(&PacketPlayer::process, this), 50);
|
||||
}
|
||||
|
||||
void PacketPlayer::stop()
|
||||
{
|
||||
if (m_event)
|
||||
m_event->cancel();
|
||||
m_event = nullptr;
|
||||
}
|
||||
|
||||
void PacketPlayer::onOutputPacket(const OutputMessagePtr& packet)
|
||||
{
|
||||
if (packet->getBuffer()[0] == 0x14) { // logout
|
||||
m_disconnectCallback(asio::error::eof);
|
||||
stop();
|
||||
}
|
||||
}
|
||||
|
||||
void PacketPlayer::process()
|
||||
{
|
||||
ticks_t nextPacket = 1;
|
||||
while (!m_input.empty()) {
|
||||
auto& packet = m_input.front();
|
||||
nextPacket = (packet.first + m_start) - g_clock.millis();
|
||||
if (nextPacket > 1)
|
||||
break;
|
||||
m_recvCallback(packet.second);
|
||||
m_input.pop_front();
|
||||
}
|
||||
|
||||
if (!m_input.empty() && nextPacket > 1) {
|
||||
m_event = g_dispatcher.scheduleEvent(std::bind(&PacketPlayer::process, this), nextPacket);
|
||||
} else {
|
||||
m_disconnectCallback(asio::error::eof);
|
||||
stop();
|
||||
}
|
||||
}
|
||||
48
src/framework/net/packet_player.h
Normal file
48
src/framework/net/packet_player.h
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2024 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <deque>
|
||||
#include <framework/core/eventdispatcher.h>
|
||||
#include <framework/net/outputmessage.h>
|
||||
|
||||
class PacketPlayer : public LuaObject {
|
||||
public:
|
||||
PacketPlayer(const std::string_view& file);
|
||||
virtual ~PacketPlayer();
|
||||
|
||||
void start(std::function<void(std::shared_ptr<std::vector<uint8_t>>)> recvCallback, std::function<void(std::error_code)> disconnectCallback);
|
||||
void stop();
|
||||
|
||||
void onOutputPacket(const OutputMessagePtr& packet);
|
||||
|
||||
private:
|
||||
void process();
|
||||
|
||||
ticks_t m_start;
|
||||
ScheduledEventPtr m_event;
|
||||
std::deque<std::pair<ticks_t, std::shared_ptr<std::vector<uint8_t>>>> m_input;
|
||||
std::deque<std::pair<ticks_t, std::shared_ptr<std::vector<uint8_t>>>> m_output;
|
||||
std::function<void(std::shared_ptr<std::vector<uint8_t>>)> m_recvCallback;
|
||||
std::function<void(std::error_code)> m_disconnectCallback;
|
||||
};
|
||||
69
src/framework/net/packet_recorder.cpp
Normal file
69
src/framework/net/packet_recorder.cpp
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2024 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <framework/global.h>
|
||||
#include <framework/core/clock.h>
|
||||
#include <framework/core/resourcemanager.h>
|
||||
|
||||
#include "packet_recorder.h"
|
||||
|
||||
PacketRecorder::PacketRecorder(const std::string_view& file)
|
||||
{
|
||||
m_start = g_clock.millis();
|
||||
#ifdef ANDROID
|
||||
g_resources.makeDir("records");
|
||||
m_stream = std::ofstream(std::string("records/") + file);
|
||||
#else
|
||||
std::error_code ec;
|
||||
std::filesystem::create_directory("records", ec);
|
||||
m_stream = std::ofstream(std::filesystem::path("records") / file);
|
||||
#endif
|
||||
}
|
||||
|
||||
PacketRecorder::~PacketRecorder()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void PacketRecorder::addInputPacket(const InputMessagePtr& packet)
|
||||
{
|
||||
m_stream << "< " << (g_clock.millis() - m_start) << " ";
|
||||
for (auto& buffer : packet->getBodyBuffer()) {
|
||||
m_stream << std::setfill('0') << std::setw(2) << std::hex << (uint16_t)(uint8_t)buffer;
|
||||
}
|
||||
m_stream << std::dec << "\n";
|
||||
}
|
||||
|
||||
void PacketRecorder::addOutputPacket(const OutputMessagePtr& packet)
|
||||
{
|
||||
if (m_firstOutput) {
|
||||
// skip packet with login and password
|
||||
m_firstOutput = false;
|
||||
return;
|
||||
}
|
||||
|
||||
m_stream << "> " << (g_clock.millis() - m_start) << " ";
|
||||
for (auto& buffer : packet->getBuffer()) {
|
||||
m_stream << std::setfill('0') << std::setw(2) << std::hex << (uint16_t)(uint8_t)buffer;
|
||||
}
|
||||
m_stream << std::dec << "\n";
|
||||
}
|
||||
40
src/framework/net/packet_recorder.h
Normal file
40
src/framework/net/packet_recorder.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2024 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <framework/net/inputmessage.h>
|
||||
#include <framework/net/outputmessage.h>
|
||||
|
||||
class PacketRecorder : public LuaObject {
|
||||
public:
|
||||
PacketRecorder(const std::string_view& file);
|
||||
virtual ~PacketRecorder();
|
||||
|
||||
void addInputPacket(const InputMessagePtr& packet);
|
||||
void addOutputPacket(const OutputMessagePtr& packet);
|
||||
|
||||
private:
|
||||
ticks_t m_start;
|
||||
std::ofstream m_stream;
|
||||
bool m_firstOutput = true;
|
||||
};
|
||||
|
|
@ -33,6 +33,8 @@
|
|||
#else
|
||||
#include "connection.h"
|
||||
#endif
|
||||
#include <framework/net/packet_player.h>
|
||||
#include <framework/net/packet_recorder.h>
|
||||
|
||||
extern asio::io_service g_ioService;
|
||||
|
||||
|
|
@ -109,6 +111,16 @@ bool Protocol::isConnecting()
|
|||
|
||||
void Protocol::send(const OutputMessagePtr& outputMessage)
|
||||
{
|
||||
if (m_player) {
|
||||
m_player->onOutputPacket(outputMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_recorder) {
|
||||
m_recorder->addOutputPacket(outputMessage);
|
||||
}
|
||||
|
||||
|
||||
// encrypt
|
||||
if (m_xteaEncryptionEnabled)
|
||||
xteaEncrypt(outputMessage);
|
||||
|
|
@ -227,6 +239,9 @@ void Protocol::internalRecvData(const uint8_t* buffer, const uint16_t size)
|
|||
m_inputMessage->setMessageSize(m_inputMessage->getHeaderSize() + totalSize);
|
||||
}
|
||||
|
||||
if (m_recorder) {
|
||||
m_recorder->addInputPacket(m_inputMessage);
|
||||
}
|
||||
onRecv(m_inputMessage);
|
||||
}
|
||||
|
||||
|
|
@ -355,4 +370,39 @@ void Protocol::onLocalDisconnected(std::error_code ec)
|
|||
m_disconnected = true;
|
||||
onError(ec);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void Protocol::onPlayerPacket(const std::shared_ptr<std::vector<uint8_t>>& packet)
|
||||
{
|
||||
if (m_disconnected)
|
||||
return;
|
||||
auto self(asProtocol());
|
||||
post(g_ioService, [&, packet] {
|
||||
if (m_disconnected)
|
||||
return;
|
||||
m_inputMessage->reset();
|
||||
|
||||
m_inputMessage->setHeaderSize(0);
|
||||
m_inputMessage->fillBuffer(packet->data(), packet->size());
|
||||
m_inputMessage->setMessageSize(packet->size());
|
||||
onRecv(m_inputMessage);
|
||||
});
|
||||
}
|
||||
|
||||
void Protocol::playRecord(PacketPlayerPtr player)
|
||||
{
|
||||
m_disconnected = false;
|
||||
m_player = player;
|
||||
m_player->start([capture0 = asProtocol()](auto&& PH1) {
|
||||
capture0->onPlayerPacket(std::forward<decltype(PH1)>(PH1));
|
||||
},
|
||||
[capture0 = asProtocol()](auto&& PH1) {
|
||||
capture0->onLocalDisconnected(std::forward<decltype(PH1)>(PH1));
|
||||
});
|
||||
return onConnect();
|
||||
}
|
||||
|
||||
void Protocol::setRecorder(PacketRecorderPtr recorder)
|
||||
{
|
||||
m_recorder = recorder;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,9 @@ public:
|
|||
#endif
|
||||
void disconnect();
|
||||
|
||||
void setRecorder(PacketRecorderPtr recorder);
|
||||
void playRecord(PacketPlayerPtr player);
|
||||
|
||||
bool isConnected();
|
||||
bool isConnecting();
|
||||
ticks_t getElapsedTicksSinceLastRead() const { return m_connection ? m_connection->getElapsedTicksSinceLastRead() : -1; }
|
||||
|
|
@ -80,6 +83,7 @@ protected:
|
|||
virtual void onSend() {};
|
||||
|
||||
void onProxyPacket(const std::shared_ptr<std::vector<uint8_t>>& packet);
|
||||
void onPlayerPacket(const std::shared_ptr<std::vector<uint8_t>>& packet);
|
||||
void onLocalDisconnected(std::error_code ec);
|
||||
bool m_disconnected = false;
|
||||
uint32_t m_proxy = 0;
|
||||
|
|
@ -87,6 +91,8 @@ protected:
|
|||
std::array<uint32_t, 4> m_xteaKey{};
|
||||
uint32_t m_packetNumber{ 0 };
|
||||
|
||||
PacketPlayerPtr m_player;
|
||||
PacketRecorderPtr m_recorder;
|
||||
private:
|
||||
void internalRecvHeader(const uint8_t* buffer, uint16_t size);
|
||||
void internalRecvData(const uint8_t* buffer, uint16_t size);
|
||||
|
|
|
|||
|
|
@ -397,6 +397,8 @@
|
|||
<ClCompile Include="..\src\framework\net\httplogin.cpp" />
|
||||
<ClCompile Include="..\src\framework\net\inputmessage.cpp" />
|
||||
<ClCompile Include="..\src\framework\net\outputmessage.cpp" />
|
||||
<ClCompile Include="..\src\framework\net\packet_player.cpp" />
|
||||
<ClCompile Include="..\src\framework\net\packet_recorder.cpp" />
|
||||
<ClCompile Include="..\src\framework\net\protocol.cpp" />
|
||||
<ClCompile Include="..\src\framework\net\protocolhttp.cpp" />
|
||||
<ClCompile Include="..\src\framework\net\server.cpp" />
|
||||
|
|
@ -563,6 +565,8 @@
|
|||
<ClInclude Include="..\src\framework\net\httplogin.h" />
|
||||
<ClInclude Include="..\src\framework\net\inputmessage.h" />
|
||||
<ClInclude Include="..\src\framework\net\outputmessage.h" />
|
||||
<ClInclude Include="..\src\framework\net\packet_player.h" />
|
||||
<ClInclude Include="..\src\framework\net\packet_recorder.h" />
|
||||
<ClInclude Include="..\src\framework\net\protocol.h" />
|
||||
<ClInclude Include="..\src\framework\net\protocolhttp.h" />
|
||||
<ClInclude Include="..\src\framework\net\server.h" />
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue