Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
mattyx14 committed Nov 10, 2024
1 parent 0fea509 commit 0aa07d0
Show file tree
Hide file tree
Showing 45 changed files with 260 additions and 327 deletions.
116 changes: 116 additions & 0 deletions docs/python-scripts/convert_monsters_callbacks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
"""
Script for processing Lua files in a project.
This script is designed to modify `.lua` files in the root directory of the project and all of its subdirectories.
The following modifications are made to each `.lua` file:
1. Remove empty callback functions.
2. Remove the 'onAppear' callback function entirely, including its corresponding `end`.
3. Clean up unnecessary blank lines resulting from the removal of callback functions.
Usage:
1. Save this script in the `docs/python-scripts` directory of your project.
2. Open a terminal and navigate to the `docs/python-scripts` directory:
cd path/to/your/project/docs/python-scripts
3. Run the script using Python:
python convert_monsters_callbacks.py
Prerequisites:
- Ensure Python 3 is installed.
- Make sure you have read and write permissions for all `.lua` files in the project directory.
Output:
- The script will print the root directory being processed.
- At the end, it will output the number of files that were modified.
Example:
Root path: /path/to/your/project
Script completed. Modified 5 file(s).
"""

import re
import os

def get_root_path():
"""Get the root path of the project (two levels above the current script directory)."""
return os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))

def process_lua_code(code):
"""Process the Lua code: remove specific callbacks and clean up empty lines.
Args:
code (str): The Lua code to be processed.
Returns:
str: The modified Lua code.
"""
# Remove specific callbacks including 'onAppear' and empty callbacks
code = re.sub(r'\n?mType\.onAppear = function\(.*?\)\n(.*?)\nend\n?', '', code, flags=re.DOTALL)
code = re.sub(r'\n?mType\.\w+ = function\(.*?\) end\n?', '', code)

# Remove extra blank lines created by the removal of callbacks
code = re.sub(r'\n{3,}', '\n\n', code) # Limit multiple blank lines to just two

return code

def process_lua_file(file_path):
"""Process a single Lua file by applying the required modifications.
Args:
file_path (str): The path to the Lua file to be processed.
Returns:
bool: True if the file was modified and saved, False otherwise.
"""
try:
with open(file_path, 'r', encoding='utf-8') as file:
code = file.read()
except Exception as e:
print(f"Error reading file {file_path}: {e}")
return False

original_code = code
modified_code = process_lua_code(code)

if modified_code != original_code:
try:
with open(file_path, 'w', encoding='utf-8') as file:
file.write(modified_code)
return True
except Exception as e:
print(f"Error writing file {file_path}: {e}")
return False

def process_all_lua_files(root_path):
"""Process all Lua files in the root path and its subdirectories.
Args:
root_path (str): The root directory in which to search for Lua files.
Returns:
int: The count of modified Lua files.
"""
modified_files_count = 0

for dirpath, _, filenames in os.walk(root_path):
for filename in filenames:
if filename.endswith(".lua"):
file_path = os.path.join(dirpath, filename)
if process_lua_file(file_path):
modified_files_count += 1

return modified_files_count

def main():
"""Main function to run the script.
This function determines the root path of the project, processes all Lua files
found in the root path and subdirectories, and prints the number of files modified.
"""
root_path = get_root_path()
print(f"Root path: {root_path}")

modified_files_count = process_all_lua_files(root_path)
print(f"Script completed. Modified {modified_files_count} file(s).")

if __name__ == "__main__":
main()
2 changes: 1 addition & 1 deletion schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ CREATE TABLE IF NOT EXISTS `players` (
`posx` int(11) NOT NULL DEFAULT '0',
`posy` int(11) NOT NULL DEFAULT '0',
`posz` int(11) NOT NULL DEFAULT '0',
`conditions` blob NOT NULL,
`conditions` mediumblob NOT NULL,
`cap` int(11) NOT NULL DEFAULT '0',
`sex` int(11) NOT NULL DEFAULT '0',
`pronoun` int(11) NOT NULL DEFAULT '0',
Expand Down
1 change: 1 addition & 0 deletions src/creatures/combat/combat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "lua/callbacks/events_callbacks.hpp"
#include "lua/creature/events.hpp"
#include "map/spectators.hpp"
#include "creatures/players/player.hpp"

int32_t Combat::getLevelFormula(const std::shared_ptr<Player> &player, const std::shared_ptr<Spell> &wheelSpell, const CombatDamage &damage) const {
if (!player) {
Expand Down
32 changes: 25 additions & 7 deletions src/creatures/creature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -270,18 +270,17 @@ void Creature::addEventWalk(bool firstStep) {
return;
}

g_dispatcher().context().tryAddEvent([ticks, self = getCreature()]() {
safeCall([this, ticks]() {
// Take first step right away, but still queue the next
if (ticks == 1) {
g_game().checkCreatureWalk(self->getID());
g_game().checkCreatureWalk(getID());
}

self->eventWalk = g_dispatcher().scheduleEvent(
eventWalk = g_dispatcher().scheduleEvent(
static_cast<uint32_t>(ticks),
[creatureId = self->getID()] { g_game().checkCreatureWalk(creatureId); }, "Game::checkCreatureWalk"
[creatureId = getID()] { g_game().checkCreatureWalk(creatureId); }, "Game::checkCreatureWalk"
);
},
"addEventWalk");
});
}

void Creature::stopEventWalk() {
Expand Down Expand Up @@ -1082,7 +1081,7 @@ void Creature::getPathSearchParams(const std::shared_ptr<Creature> &, FindPathPa

void Creature::goToFollowCreature_async(std::function<void()> &&onComplete) {
if (!hasAsyncTaskFlag(Pathfinder) && onComplete) {
g_dispatcher().context().addEvent(std::move(onComplete), "goToFollowCreature_async");
g_dispatcher().addEvent(std::move(onComplete), "goToFollowCreature_async");
}

setAsyncTaskFlag(Pathfinder, true);
Expand Down Expand Up @@ -1592,6 +1591,10 @@ LightInfo Creature::getCreatureLight() const {
return internalLight;
}

uint16_t Creature::getSpeed() const {
return std::clamp(baseSpeed + varSpeed, 0, static_cast<int>(std::numeric_limits<uint16_t>::max()));
}

void Creature::setSpeed(int32_t varSpeedDelta) {
// Prevents creatures from not exceeding the maximum allowed speed
if (getSpeed() >= PLAYER_MAX_SPEED) {
Expand Down Expand Up @@ -2002,3 +2005,18 @@ void Creature::sendAsyncTasks() {
},
TaskGroup::WalkParallel);
}

void Creature::safeCall(std::function<void(void)> &&action) const {
if (g_dispatcher().context().isAsync()) {
g_dispatcher().addEvent([weak_self = std::weak_ptr<const Creature>(static_self_cast<Creature>()), action = std::move(action)] {
if (const auto self = weak_self.lock()) {
if (!self->isInternalRemoved) {
action();
}
}
},
g_dispatcher().context().getName());
} else if (!isInternalRemoved) {
action();
}
}
7 changes: 4 additions & 3 deletions src/creatures/creature.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,9 +194,7 @@ class Creature : virtual public Thing, public SharedObject {
virtual uint16_t getStepSpeed() const {
return getSpeed();
}
uint16_t getSpeed() const {
return static_cast<uint16_t>(baseSpeed + varSpeed);
}
uint16_t getSpeed() const;
void setSpeed(int32_t varSpeedDelta);

void setBaseSpeed(uint16_t newBaseSpeed) {
Expand Down Expand Up @@ -848,6 +846,9 @@ class Creature : virtual public Thing, public SharedObject {

virtual void onExecuteAsyncTasks() {};

// This method maintains safety in asynchronous calls, avoiding competition between threads.
void safeCall(std::function<void(void)> &&action) const;

private:
bool canFollowMaster() const;
bool isLostSummon();
Expand Down
1 change: 0 additions & 1 deletion src/creatures/monsters/monster.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ class Monster final : public Creature {
const std::string &getTypeName() const override;
const std::string &getNameDescription() const override;
void setNameDescription(std::string_view nameDescription);
;
std::string getDescription(int32_t) override;

CreatureType_t getType() const override;
Expand Down
2 changes: 0 additions & 2 deletions src/creatures/monsters/spawns/spawn_monster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -232,9 +232,7 @@ bool SpawnMonster::spawnMonster(uint32_t spawnMonsterId, spawnBlock_t &sb, const

spawnedMonsterMap[spawnMonsterId] = monster;
sb.lastSpawn = OTSYS_TIME();
g_events().eventMonsterOnSpawn(monster, sb.pos);
monster->onSpawn();
g_callbacks().executeCallback(EventCallback_t::monsterOnSpawn, &EventCallback::monsterOnSpawn, monster, sb.pos);
return true;
}

Expand Down
3 changes: 0 additions & 3 deletions src/creatures/npcs/spawns/spawn_npc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -202,9 +202,6 @@ bool SpawnNpc::spawnNpc(uint32_t spawnId, const std::shared_ptr<NpcType> &npcTyp

spawnedNpcMap.insert(spawned_pair(spawnId, npc));
spawnNpcMap[spawnId].lastSpawnNpc = OTSYS_TIME();

g_events().eventNpcOnSpawn(npc, pos);
g_callbacks().executeCallback(EventCallback_t::npcOnSpawn, &EventCallback::npcOnSpawn, npc, pos);
return true;
}

Expand Down
20 changes: 6 additions & 14 deletions src/creatures/players/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include "creatures/players/player.hpp"

#include "account/account.hpp"
#include "config/configmanager.hpp"
#include "core.hpp"
#include "creatures/appearance/mounts/mounts.hpp"
Expand Down Expand Up @@ -1773,8 +1774,8 @@ std::shared_ptr<DepotLocker> Player::getDepotLocker(uint32_t depotId) {
depotLocker->internalAddThing(marketItem);
depotLocker->internalAddThing(inbox);
if (createSupplyStash) {
const auto &supplyStash = Item::CreateItem(ITEM_SUPPLY_STASH);
depotLocker->internalAddThing(supplyStash);
const auto &supplyStashPtr = Item::CreateItem(ITEM_SUPPLY_STASH);
depotLocker->internalAddThing(supplyStashPtr);
}
const auto &depotChest = Item::CreateItemAsContainer(ITEM_DEPOT, static_cast<uint16_t>(g_configManager().getNumber(DEPOT_BOXES)));
for (uint32_t i = g_configManager().getNumber(DEPOT_BOXES); i > 0; i--) {
Expand Down Expand Up @@ -3783,14 +3784,9 @@ void Player::addInFightTicks(bool pzlock /*= false*/) {

updateImbuementTrackerStats();

// this method can be called asynchronously.
g_dispatcher().context().tryAddEvent([self = std::weak_ptr<Player>(getPlayer())] {
if (const auto &player = self.lock()) {
const auto &condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_INFIGHT, g_configManager().getNumber(PZ_LOCKED), 0);
player->addCondition(condition);
}
},
"Player::addInFightTicks");
safeCall([this] {
addCondition(Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_INFIGHT, g_configManager().getNumber(PZ_LOCKED), 0));
});
}

void Player::setDailyReward(uint8_t reward) {
Expand Down Expand Up @@ -8718,10 +8714,6 @@ bool Player::saySpell(SpeakClasses type, const std::string &text, bool isGhostMo
}

tmpPlayer->onCreatureSay(static_self_cast<Player>(), type, text);
if (static_self_cast<Player>() != tmpPlayer) {
g_events().eventCreatureOnHear(tmpPlayer, getPlayer(), text, type);
g_callbacks().executeCallback(EventCallback_t::creatureOnHear, &EventCallback::creatureOnHear, tmpPlayer, getPlayer(), text, type);
}
}
return true;
}
Expand Down
1 change: 1 addition & 0 deletions src/creatures/players/vip/player_vip.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include "creatures/players/vip/player_vip.hpp"

#include "account/account.hpp"
#include "creatures/players/grouping/groups.hpp"
#include "creatures/players/player.hpp"
#include "io/iologindata.hpp"
Expand Down
15 changes: 4 additions & 11 deletions src/game/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2907,9 +2907,7 @@ ReturnValue Game::internalTeleport(const std::shared_ptr<Thing> &thing, const Po
return ret;
}

g_dispatcher().addWalkEvent([=] {
g_game().map.moveCreature(creature, toTile, !pushMove);
});
map.moveCreature(creature, toTile, !pushMove);

return RETURNVALUE_NOERROR;
} else if (const auto &item = thing->getItem()) {
Expand Down Expand Up @@ -6397,10 +6395,6 @@ bool Game::internalCreatureSay(const std::shared_ptr<Creature> &creature, SpeakC
// event method
for (const auto &spectator : spectators) {
spectator->onCreatureSay(creature, type, text);
if (creature != spectator) {
g_events().eventCreatureOnHear(spectator, creature, text, type);
g_callbacks().executeCallback(EventCallback_t::creatureOnHear, &EventCallback::creatureOnHear, spectator, creature, text, type);
}
}
return true;
}
Expand Down Expand Up @@ -6440,10 +6434,9 @@ void Game::addCreatureCheck(const std::shared_ptr<Creature> &creature) {

creature->inCheckCreaturesVector.store(true);

g_dispatcher().context().tryAddEvent([creature] {
creature->safeCall([this, creature] {
checkCreatureLists[uniform_random(0, EVENT_CREATURECOUNT - 1)].emplace_back(creature);
},
"addCreatureCheck");
});
}

void Game::removeCreatureCheck(const std::shared_ptr<Creature> &creature) {
Expand All @@ -6457,7 +6450,7 @@ void Game::checkCreatures() {
metrics::method_latency measure(__METHOD_NAME__);
static size_t index = 0;

std::erase_if(checkCreatureLists[index], [this](const std::shared_ptr<Creature> &creature) {
std::erase_if(checkCreatureLists[index], [this](const std::shared_ptr<Creature> creature) {
if (creature->creatureCheck && creature->isAlive()) {
creature->onThink(EVENT_CREATURE_THINK_INTERVAL);
creature->onAttacking(EVENT_CREATURE_THINK_INTERVAL);
Expand Down
8 changes: 4 additions & 4 deletions src/game/movement/teleport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,11 @@ void Teleport::addThing(int32_t, const std::shared_ptr<Thing> &thing) {
g_game().internalCreatureTurn(creature, origPos.x > destPos.x ? DIRECTION_WEST : DIRECTION_EAST);
g_dispatcher().addWalkEvent([=] {
g_game().map.moveCreature(creature, destTile);
if (effect != CONST_ME_NONE) {
g_game().addMagicEffect(origPos, effect);
g_game().addMagicEffect(destTile->getPosition(), effect);
}
});
if (effect != CONST_ME_NONE) {
g_game().addMagicEffect(origPos, effect);
g_game().addMagicEffect(destTile->getPosition(), effect);
}
} else if (const auto &item = thing->getItem()) {
if (effect != CONST_ME_NONE) {
g_game().addMagicEffect(destTile->getPosition(), effect);
Expand Down
16 changes: 0 additions & 16 deletions src/game/scheduling/dispatcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,22 +251,6 @@ void Dispatcher::stopEvent(uint64_t eventId) {
}
}

void DispatcherContext::addEvent(std::function<void(void)> &&f, std::string_view context) const {
g_dispatcher().addEvent(std::move(f), context);
}

void DispatcherContext::tryAddEvent(std::function<void(void)> &&f, std::string_view context) const {
if (!f) {
return;
}

if (isAsync()) {
g_dispatcher().addEvent(std::move(f), context);
} else {
f();
}
}

bool DispatcherContext::isOn() {
return OTSYS_TIME() != 0;
}
6 changes: 0 additions & 6 deletions src/game/scheduling/dispatcher.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,6 @@ struct DispatcherContext {
return type;
}

// postpone the event
void addEvent(std::function<void(void)> &&f, std::string_view context) const;

// if the context is async, the event will be postponed, if not, it will be executed immediately.
void tryAddEvent(std::function<void(void)> &&f, std::string_view context) const;

private:
void reset() {
group = TaskGroup::ThreadPool;
Expand Down
Loading

0 comments on commit 0aa07d0

Please sign in to comment.