Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parse packet in lua feature #2978

Closed
wants to merge 15 commits into from
Closed
3 changes: 3 additions & 0 deletions data/creaturescripts/creaturescripts.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,7 @@
<event type="death" name="PlayerDeath" script="playerdeath.lua" />
<event type="death" name="DropLoot" script="droploot.lua" />
<event type="extendedopcode" name="ExtendedOpcode" script="extendedopcode.lua" />
<!--
<event type="parsepacket" recvbyte="130" name="ParsePacket" script="parsepacket.lua" />
-->
</creaturescripts>
9 changes: 9 additions & 0 deletions data/creaturescripts/scripts/parsepacket.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
function onParsePacket(player, recvbyte, msg)
-- structure for parseUseItem packet, recbyte: 130 (0x82)
local pos = msg:getPosition()
local clientId = msg:getU16()
local stackpos = msg:getByte()
local index = msg:getByte()
print(("Player: %s wants to use item at position (%d, %d, %d) with sprite id %d"):format(player:getName(), pos.x, pos.y, pos.z, clientId))
msg:delete()
end
4 changes: 4 additions & 0 deletions data/lib/compat/compat.lua
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,10 @@ do
self:type("extendedopcode")
self:onExtendedOpcode(value)
return
elseif key == "onParsePacket" then
self:type("parsepacket")
self:onParsePacket(value)
return
end
rawset(self, key, value)
end
Expand Down
47 changes: 47 additions & 0 deletions src/creatureevent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "creatureevent.h"
#include "tools.h"
#include "player.h"
#include "pugicast.h"

CreatureEvents::CreatureEvents() :
scriptInterface("CreatureScript Interface")
Expand Down Expand Up @@ -211,11 +212,24 @@ bool CreatureEvent::configureEvent(const pugi::xml_node& node)
type = CREATURE_EVENT_MANACHANGE;
} else if (tmpStr == "extendedopcode") {
type = CREATURE_EVENT_EXTENDED_OPCODE;
} else if (tmpStr == "parsepacket") {
type = CREATURE_EVENT_PARSE_PACKET;
} else {
std::cout << "[Error - CreatureEvent::configureEvent] Invalid type for creature event: " << eventName << std::endl;
return false;
}

if (type == CREATURE_EVENT_PARSE_PACKET) {
// look for recvbyte
pugi::xml_attribute recvbyteAttribute = node.attribute("recvbyte");
if (!recvbyteAttribute) {
std::cout << "[Error - CreatureEvent::configureEvent] Missing recvbyte for parse packet creature event: " << eventName << std::endl;
return false;
}

recvbyte = static_cast<uint8_t>(pugi::cast<uint16_t>(recvbyteAttribute.value()));
}

loaded = true;
return true;
}
Expand Down Expand Up @@ -260,6 +274,9 @@ std::string CreatureEvent::getScriptEventName() const
case CREATURE_EVENT_EXTENDED_OPCODE:
return "onExtendedOpcode";

case CREATURE_EVENT_PARSE_PACKET:
return "onParsePacket";

case CREATURE_EVENT_NONE:
default:
return std::string();
Expand All @@ -272,6 +289,10 @@ void CreatureEvent::copyEvent(CreatureEvent* creatureEvent)
scriptInterface = creatureEvent->scriptInterface;
scripted = creatureEvent->scripted;
loaded = creatureEvent->loaded;

if (type == CREATURE_EVENT_PARSE_PACKET) {
recvbyte = creatureEvent->getRecvbyte();
}
}

void CreatureEvent::clearEvent()
Expand Down Expand Up @@ -603,3 +624,29 @@ void CreatureEvent::executeExtendedOpcode(Player* player, uint8_t opcode, const

scriptInterface->callVoidFunction(3);
}

void CreatureEvent::executeParsePacket(Player* player, uint8_t recvbyte, NetworkMessage& message)
{
//onParsePacket(player, recvbyte, msg)
if (!scriptInterface->reserveScriptEnv()) {
std::cout << "[Error - CreatureEvent::executeParsePacket] Call stack overflow" << std::endl;
return;
}

ScriptEnvironment* env = scriptInterface->getScriptEnv();
env->setScriptId(scriptId, scriptInterface);

lua_State* L = scriptInterface->getLuaState();

scriptInterface->pushFunction(scriptId);

LuaScriptInterface::pushUserdata<Player>(L, player);
LuaScriptInterface::setMetatable(L, -1, "Player");

lua_pushnumber(L, recvbyte);

LuaScriptInterface::pushUserdata<NetworkMessage>(L, &message);
LuaScriptInterface::setWeakMetatable(L, -1, "NetworkMessage");

scriptInterface->callVoidFunction(3);
}
10 changes: 10 additions & 0 deletions src/creatureevent.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "luascript.h"
#include "baseevents.h"
#include "enums.h"
#include "networkmessage.h"

class CreatureEvent;
using CreatureEvent_ptr = std::unique_ptr<CreatureEvent>;
Expand All @@ -41,6 +42,7 @@ enum CreatureEventType_t {
CREATURE_EVENT_HEALTHCHANGE,
CREATURE_EVENT_MANACHANGE,
CREATURE_EVENT_EXTENDED_OPCODE, // otclient additional network opcodes
CREATURE_EVENT_PARSE_PACKET,
};

class CreatureEvent final : public Event
Expand Down Expand Up @@ -68,6 +70,12 @@ class CreatureEvent final : public Event
void setLoaded(bool b) {
loaded = b;
}
void setRecvbyte(uint8_t recvbyte) {
this->recvbyte = recvbyte;
}
uint8_t getRecvbyte() {
return recvbyte;
}

void clearEvent();
void copyEvent(CreatureEvent* creatureEvent);
Expand All @@ -85,6 +93,7 @@ class CreatureEvent final : public Event
void executeHealthChange(Creature* creature, Creature* attacker, CombatDamage& damage);
void executeManaChange(Creature* creature, Creature* attacker, CombatDamage& damage);
void executeExtendedOpcode(Player* player, uint8_t opcode, const std::string& buffer);
void executeParsePacket(Player* player, uint8_t recvbyte, NetworkMessage& message);
//

private:
Expand All @@ -93,6 +102,7 @@ class CreatureEvent final : public Event
std::string eventName;
CreatureEventType_t type;
bool loaded;
uint8_t recvbyte; // only for parse packet creaturescript
};

class CreatureEvents final : public BaseEvents
Expand Down
19 changes: 19 additions & 0 deletions src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5492,6 +5492,25 @@ void Game::playerAnswerModalWindow(uint32_t playerId, uint32_t modalWindowId, ui
}
}

void Game::playerExecuteParsePacketEvent(uint32_t playerId, uint8_t recvbyte, NetworkMessage& message)
{
Player* player = getPlayerByID(playerId);
if (!player) {
return;
nekiro marked this conversation as resolved.
Show resolved Hide resolved
}

for (CreatureEvent* creatureEvent : player->eventsList) {
if (!creatureEvent->isLoaded()) {
continue;
}

if (creatureEvent->getEventType() == CREATURE_EVENT_PARSE_PACKET && creatureEvent->getRecvbyte() == recvbyte) {
creatureEvent->executeParsePacket(player, recvbyte, message);
return;
}
}
}

void Game::addPlayer(Player* player)
{
const std::string& lowercase_name = asLowerCaseString(player->getName());
Expand Down
1 change: 1 addition & 0 deletions src/game.h
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,7 @@ class Game
void playerReportBug(uint32_t playerId, const std::string& message, const Position& position, uint8_t category);
void playerDebugAssert(uint32_t playerId, const std::string& assertLine, const std::string& date, const std::string& description, const std::string& comment);
void playerAnswerModalWindow(uint32_t playerId, uint32_t modalWindowId, uint8_t button, uint8_t choice);
void playerExecuteParsePacketEvent(uint32_t playerId, uint8_t recvbyte, NetworkMessage& message);
void playerReportRuleViolation(uint32_t playerId, const std::string& targetName, uint8_t reportType, uint8_t reportReason, const std::string& comment, const std::string& translation);

bool internalStartTrade(Player* player, Player* tradePartner, Item* tradeItem);
Expand Down
17 changes: 17 additions & 0 deletions src/luascript.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3108,6 +3108,7 @@ void LuaScriptInterface::registerFunctions()
// CreatureEvent
registerClass("CreatureEvent", "", LuaScriptInterface::luaCreateCreatureEvent);
registerMethod("CreatureEvent", "type", LuaScriptInterface::luaCreatureEventType);
registerMethod("CreatureEvent", "recvbyte", LuaScriptInterface::luaCreatureEventRecvbyte);
registerMethod("CreatureEvent", "register", LuaScriptInterface::luaCreatureEventRegister);
registerMethod("CreatureEvent", "onLogin", LuaScriptInterface::luaCreatureEventOnCallback);
registerMethod("CreatureEvent", "onLogout", LuaScriptInterface::luaCreatureEventOnCallback);
Expand All @@ -3121,6 +3122,7 @@ void LuaScriptInterface::registerFunctions()
registerMethod("CreatureEvent", "onHealthChange", LuaScriptInterface::luaCreatureEventOnCallback);
registerMethod("CreatureEvent", "onManaChange", LuaScriptInterface::luaCreatureEventOnCallback);
registerMethod("CreatureEvent", "onExtendedOpcode", LuaScriptInterface::luaCreatureEventOnCallback);
registerMethod("CreatureEvent", "onParsePacket", LuaScriptInterface::luaCreatureEventOnCallback);

// MoveEvent
registerClass("MoveEvent", "", LuaScriptInterface::luaCreateMoveEvent);
Expand Down Expand Up @@ -16118,6 +16120,8 @@ int LuaScriptInterface::luaCreatureEventType(lua_State* L)
creature->setEventType(CREATURE_EVENT_MANACHANGE);
} else if (tmpStr == "extendedopcode") {
creature->setEventType(CREATURE_EVENT_EXTENDED_OPCODE);
} else if (tmpStr == "parsepacket") {
creature->setEventType(CREATURE_EVENT_PARSE_PACKET);
} else {
std::cout << "[Error - CreatureEvent::configureLuaEvent] Invalid type for creature event: " << typeName << std::endl;
pushBoolean(L, false);
Expand All @@ -16130,6 +16134,19 @@ int LuaScriptInterface::luaCreatureEventType(lua_State* L)
return 1;
}

int LuaScriptInterface::luaCreatureEventRecvbyte(lua_State* L)
{
// creatureevent:recvbyte(byte)
CreatureEvent* creature = getUserdata<CreatureEvent>(L, 1);
if (creature && creature->getEventType() == CREATURE_EVENT_PARSE_PACKET) {
creature->setRecvbyte(getNumber<uint8_t>(L, 2));
pushBoolean(L, true);
} else {
lua_pushnil(L);
}
return 1;
}

int LuaScriptInterface::luaCreatureEventRegister(lua_State* L)
{
// creatureevent:register()
Expand Down
1 change: 1 addition & 0 deletions src/luascript.h
Original file line number Diff line number Diff line change
Expand Up @@ -1491,6 +1491,7 @@ class LuaScriptInterface
// CreatureEvents
static int luaCreateCreatureEvent(lua_State* L);
static int luaCreatureEventType(lua_State* L);
static int luaCreatureEventRecvbyte(lua_State* L);
static int luaCreatureEventRegister(lua_State* L);
static int luaCreatureEventOnCallback(lua_State* L);

Expand Down
4 changes: 4 additions & 0 deletions src/networkmessage.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ class NetworkMessage
enum { MAX_PROTOCOL_BODY_LENGTH = MAX_BODY_LENGTH - 10 };

NetworkMessage() = default;
NetworkMessage(const NetworkMessage& other) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't make sense if you don't really plan to make a copy, I see that you modified PR to not make copies, so why this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

future proof

Copy link
Contributor

@MillhioreBT MillhioreBT Dec 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although if you ask me, I think that you should allow us to have the freedom of being able to write several events with the same byte, and make a copy of the message for each event that is called, each one decides whether to do more than one event, why put limitations?

then we can do the following:
image

info = other.info;
memcpy(&buffer, &other.buffer, sizeof(other.buffer) / sizeof(other.buffer[0]));
}

void reset() {
info = {};
Expand Down
5 changes: 5 additions & 0 deletions src/protocolgame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,11 @@ void ProtocolGame::parsePacket(NetworkMessage& msg)
}
}

if (player->hasEventRegistered(CREATURE_EVENT_PARSE_PACKET)) {
addGameTask(&Game::playerExecuteParsePacketEvent, player->getID(), recvbyte, msg);
return;
Copy link
Contributor

@MillhioreBT MillhioreBT Dec 10, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is serious? or a joke? XD
the return; <<<

player:registerEvent("parsepacket") >>> the player will stop doing things, the (all)-packet's are simply never parsed in the sources

}

switch (recvbyte) {
case 0x14: g_dispatcher.addTask(createTask(std::bind(&ProtocolGame::logout, getThis(), true, false))); break;
case 0x1D: addGameTask(&Game::playerReceivePingBack, player->getID()); break;
Expand Down