Skip to content

Commit

Permalink
Merge branch 'main' into improve-save-stash
Browse files Browse the repository at this point in the history
  • Loading branch information
Luan Luciano authored Jun 17, 2024
2 parents 30f0aa9 + 4af5b2d commit 5788ccb
Show file tree
Hide file tree
Showing 14 changed files with 209 additions and 130 deletions.
32 changes: 22 additions & 10 deletions data/libs/functions/boss_lever.lua
Original file line number Diff line number Diff line change
Expand Up @@ -174,24 +174,36 @@ function BossLever:onUse(player)
end

if creature:getLevel() < self.requiredLevel then
creature:sendTextMessage(MESSAGE_EVENT_ADVANCE, "All the players need to be level " .. self.requiredLevel .. " or higher.")
local message = "All players need to be level " .. self.requiredLevel .. " or higher."
creature:sendTextMessage(MESSAGE_EVENT_ADVANCE, message)
player:sendTextMessage(MESSAGE_EVENT_ADVANCE, message)
return false
end

if self:lastEncounterTime(creature) > os.time() then
local info = lever:getInfoPositions()
for _, v in pairs(info) do
local newPlayer = v.creature
if newPlayer then
local timeLeft = self:lastEncounterTime(newPlayer) - os.time()
newPlayer:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You or a member in your team have to wait " .. getTimeInWords(timeLeft) .. " to face " .. self.name .. " again!")
if self:lastEncounterTime(newPlayer) > os.time() then
newPlayer:getPosition():sendMagicEffect(CONST_ME_POFF)
if creature:getGroup():getId() < GROUP_TYPE_GOD and self:lastEncounterTime(creature) > os.time() then
local infoPositions = lever:getInfoPositions()
for _, posInfo in pairs(infoPositions) do
local currentPlayer = posInfo.creature
if currentPlayer then
local lastEncounter = self:lastEncounterTime(currentPlayer)
local currentTime = os.time()
if lastEncounter and currentTime < lastEncounter then
local timeLeft = lastEncounter - currentTime
local timeMessage = getTimeInWords(timeLeft) .. " to face " .. monsterName .. " again!"
local message = "You have to wait " .. timeMessage

if currentPlayer ~= player then
player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "A member in your team has to wait " .. timeMessage)
end

currentPlayer:sendTextMessage(MESSAGE_EVENT_ADVANCE, message)
currentPlayer:getPosition():sendMagicEffect(CONST_ME_POFF)
end
end
end
return false
end

self.onUseExtra(creature)
return true
end)
Expand Down
17 changes: 11 additions & 6 deletions data/modules/scripts/gamestore/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,11 @@ function onRecvbyte(player, msg, byte)
return player:sendCancelMessage("Store don't have offers for rookgaard citizen.")
end

if player:isUIExhausted(250) then
player:sendCancelMessage("You are exhausted.")
return
end

if byte == GameStore.RecivedPackets.C_StoreEvent then
elseif byte == GameStore.RecivedPackets.C_TransferCoins then
parseTransferableCoins(player:getId(), msg)
Expand All @@ -262,12 +267,6 @@ function onRecvbyte(player, msg, byte)
parseRequestTransactionHistory(player:getId(), msg)
end

if player:isUIExhausted(250) then
player:sendCancelMessage("You are exhausted.")
return false
end

player:updateUIExhausted()
return true
end

Expand Down Expand Up @@ -306,6 +305,7 @@ function parseTransferableCoins(playerId, msg)
GameStore.insertHistory(accountId, GameStore.HistoryTypes.HISTORY_TYPE_NONE, player:getName() .. " transferred you this amount.", amount, GameStore.CoinType.Transferable)
GameStore.insertHistory(player:getAccountId(), GameStore.HistoryTypes.HISTORY_TYPE_NONE, "You transferred this amount to " .. reciver, -1 * amount, GameStore.CoinType.Transferable)
openStore(playerId)
player:updateUIExhausted()
end

function parseOpenStore(playerId, msg)
Expand Down Expand Up @@ -396,6 +396,7 @@ function parseRequestStoreOffers(playerId, msg)

addPlayerEvent(sendShowStoreOffers, 250, playerId, searchResultsCategory)
end
player:updateUIExhausted()
end

function parseBuyStoreOffer(playerId, msg)
Expand Down Expand Up @@ -532,6 +533,8 @@ function parseBuyStoreOffer(playerId, msg)
sendUpdatedStoreBalances(playerId)
return addPlayerEvent(sendStorePurchaseSuccessful, 650, playerId, message)
end

player:updateUIExhausted()
return true
end

Expand All @@ -540,11 +543,13 @@ function parseOpenTransactionHistory(playerId, msg)
local page = 1
GameStore.DefaultValues.DEFAULT_VALUE_ENTRIES_PER_PAGE = msg:getByte()
sendStoreTransactionHistory(playerId, page, GameStore.DefaultValues.DEFAULT_VALUE_ENTRIES_PER_PAGE)
player:updateUIExhausted()
end

function parseRequestTransactionHistory(playerId, msg)
local page = msg:getU32()
sendStoreTransactionHistory(playerId, page + 1, GameStore.DefaultValues.DEFAULT_VALUE_ENTRIES_PER_PAGE)
player:updateUIExhausted()
end

local function getCategoriesRook()
Expand Down
6 changes: 5 additions & 1 deletion src/creatures/monsters/monster.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,11 @@ class Monster final : public Creature {
void dropLoot(std::shared_ptr<Container> corpse, std::shared_ptr<Creature> lastHitCreature) override;
void getPathSearchParams(const std::shared_ptr<Creature> &creature, FindPathParams &fpp) override;
bool useCacheMap() const override {
return !randomStepping;
// return !randomStepping;
// As the map cache is done synchronously for each movement that a monster makes, it is better to disable it,
// as the pathfinder, which is one of the resources that uses this cache the most,
// is multithreding and thus the processing cost is divided between the threads.
return false;
}

friend class MonsterFunctions;
Expand Down
36 changes: 22 additions & 14 deletions src/creatures/players/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1717,13 +1717,7 @@ void Player::onCreatureAppear(std::shared_ptr<Creature> creature, bool isLogin)
Creature::onCreatureAppear(creature, isLogin);

if (isLogin && creature == getPlayer()) {
for (int32_t slot = CONST_SLOT_FIRST; slot <= CONST_SLOT_LAST; ++slot) {
std::shared_ptr<Item> item = inventory[slot];
if (item) {
item->startDecaying();
g_moveEvents().onPlayerEquip(getPlayer(), item, static_cast<Slots_t>(slot), false);
}
}
onEquipInventory();

// Refresh bosstiary tracker onLogin
refreshCyclopediaMonsterTracker(true);
Expand Down Expand Up @@ -1864,14 +1858,9 @@ void Player::onRemoveCreature(std::shared_ptr<Creature> creature, bool isLogout)
Creature::onRemoveCreature(creature, isLogout);

if (auto player = getPlayer(); player == creature) {
for (uint8_t slot = CONST_SLOT_FIRST; slot <= CONST_SLOT_LAST; ++slot) {
const auto item = inventory[slot];
if (item) {
g_moveEvents().onPlayerDeEquip(getPlayer(), item, static_cast<Slots_t>(slot));
}
}

if (isLogout) {
onDeEquipInventory();

if (m_party) {
m_party->leaveParty(player);
}
Expand Down Expand Up @@ -2013,6 +2002,25 @@ void Player::onCreatureMove(const std::shared_ptr<Creature> &creature, const std
}
}

void Player::onEquipInventory() {
for (int32_t slot = CONST_SLOT_FIRST; slot <= CONST_SLOT_LAST; ++slot) {
std::shared_ptr<Item> item = inventory[slot];
if (item) {
item->startDecaying();
g_moveEvents().onPlayerEquip(getPlayer(), item, static_cast<Slots_t>(slot), false);
}
}
}

void Player::onDeEquipInventory() {
for (int32_t slot = CONST_SLOT_FIRST; slot <= CONST_SLOT_LAST; ++slot) {
std::shared_ptr<Item> item = inventory[slot];
if (item) {
g_moveEvents().onPlayerDeEquip(getPlayer(), item, static_cast<Slots_t>(slot));
}
}
}

// container
void Player::onAddContainerItem(std::shared_ptr<Item> item) {
checkTradeState(item);
Expand Down
23 changes: 10 additions & 13 deletions src/creatures/players/player.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1317,6 +1317,9 @@ class Player final : public Creature, public Cylinder, public Bankable {
void onRemoveCreature(std::shared_ptr<Creature> creature, bool isLogout) override;
void onCreatureMove(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Tile> &newTile, const Position &newPos, const std::shared_ptr<Tile> &oldTile, const Position &oldPos, bool teleport) override;

void onEquipInventory();
void onDeEquipInventory();

void onAttackedCreatureDisappear(bool isLogout) override;
void onFollowCreatureDisappear(bool isLogout) override;

Expand Down Expand Up @@ -2562,27 +2565,21 @@ class Player final : public Creature, public Cylinder, public Bankable {
}

bool checkAutoLoot(bool isBoss) const {
const bool autoLoot = g_configManager().getBoolean(AUTOLOOT, __FUNCTION__);
if (!autoLoot) {
if (!g_configManager().getBoolean(AUTOLOOT, __FUNCTION__)) {
return false;
}
if (g_configManager().getBoolean(VIP_SYSTEM_ENABLED, __FUNCTION__) && g_configManager().getBoolean(VIP_AUTOLOOT_VIP_ONLY, __FUNCTION__) && !isVip()) {
return false;
}

auto featureKV = kv()->scoped("features")->get("autoloot");
if (featureKV.has_value()) {
auto value = featureKV->getNumber();
if (value == 2) {
return true;
} else if (value == 1) {
return !isBoss;
} else if (value == 0) {
return false;
}
auto value = featureKV.has_value() ? featureKV->getNumber() : 0;
if (value == 2) {
return true;
} else if (value == 1) {
return !isBoss;
}

return true;
return false;
}

QuickLootFilter_t getQuickLootFilter() const {
Expand Down
14 changes: 0 additions & 14 deletions src/game/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6255,7 +6255,6 @@ void Game::checkCreatureWalk(uint32_t creatureId) {
const auto &creature = getCreatureByID(creatureId);
if (creature && creature->getHealth() > 0) {
creature->onCreatureWalk();
cleanup();
}
}

Expand Down Expand Up @@ -6318,7 +6317,6 @@ void Game::checkCreatures() {
--end;
}
}
cleanup();

index = (index + 1) % EVENT_CREATURECOUNT;
}
Expand Down Expand Up @@ -7967,8 +7965,6 @@ void Game::shutdown() {
map.spawnsNpc.clear();
raids.clear();

cleanup();

if (serviceManager) {
serviceManager->stop();
}
Expand All @@ -7980,16 +7976,6 @@ void Game::shutdown() {
g_logger().info("Done!");
}

void Game::cleanup() {
for (auto it = browseFields.begin(); it != browseFields.end();) {
if (it->second.expired()) {
it = browseFields.erase(it);
} else {
++it;
}
}
}

void Game::addBestiaryList(uint16_t raceid, std::string name) {
auto it = BestiaryList.find(raceid);
if (it != BestiaryList.end()) {
Expand Down
1 change: 0 additions & 1 deletion src/game/game.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,6 @@ class Game {

void updatePlayerHelpers(std::shared_ptr<Player> player);

void cleanup();
void shutdown();
void dieSafely(const std::string &errorMsg);
void addBestiaryList(uint16_t raceid, std::string name);
Expand Down
55 changes: 38 additions & 17 deletions src/game/scheduling/dispatcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,30 +56,51 @@ void Dispatcher::executeSerialEvents(std::vector<Task> &tasks) {
}

void Dispatcher::executeParallelEvents(std::vector<Task> &tasks, const uint8_t groupId) {
std::atomic_uint_fast64_t totalTaskSize = tasks.size();
std::atomic_bool isTasksCompleted = false;
asyncWait(tasks.size(), [groupId, &tasks](size_t i) {
dispacherContext.type = DispatcherType::AsyncEvent;
dispacherContext.group = static_cast<TaskGroup>(groupId);
tasks[i].execute();

for (const auto &task : tasks) {
threadPool.detach_task([groupId, &task, &isTasksCompleted, &totalTaskSize] {
dispacherContext.type = DispatcherType::AsyncEvent;
dispacherContext.group = static_cast<TaskGroup>(groupId);
dispacherContext.taskName = task.getContext();
dispacherContext.reset();
});

task.execute();
tasks.clear();
}

dispacherContext.reset();
void Dispatcher::asyncWait(size_t requestSize, std::function<void(size_t i)> &&f) {
if (requestSize == 0) {
return;
}

totalTaskSize.fetch_sub(1);
if (totalTaskSize.load() == 0) {
isTasksCompleted.store(true);
isTasksCompleted.notify_one();
}
});
// This prevents an async call from running inside another async call.
if (asyncWaitDisabled) {
for (uint_fast64_t i = 0; i < requestSize; ++i) {
f(i);
}
return;
}

isTasksCompleted.wait(false);
const auto &partitions = generatePartition(requestSize);
const auto pSize = partitions.size();

tasks.clear();
BS::multi_future<void> retFuture;

if (pSize > 1) {
asyncWaitDisabled = true;
const auto min = partitions[1].first;
const auto max = partitions[partitions.size() - 1].second;
retFuture = threadPool.submit_loop(min, max, [&f](const unsigned int i) { f(i); });
}

const auto &[min, max] = partitions[0];
for (uint_fast64_t i = min; i < max; ++i) {
f(i);
}

if (pSize > 1) {
retFuture.wait();
asyncWaitDisabled = false;
}
}

void Dispatcher::executeEvents(const TaskGroup startGroup) {
Expand Down
19 changes: 19 additions & 0 deletions src/game/scheduling/dispatcher.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ class Dispatcher {
}

void asyncEvent(std::function<void(void)> &&f, TaskGroup group = TaskGroup::GenericParallel);
void asyncWait(size_t size, std::function<void(size_t i)> &&f);

uint64_t asyncCycleEvent(uint32_t delay, std::function<void(void)> &&f, TaskGroup group = TaskGroup::GenericParallel) {
return scheduleEvent(
Expand Down Expand Up @@ -173,6 +174,22 @@ class Dispatcher {
}
}

std::vector<std::pair<uint64_t, uint64_t>> generatePartition(size_t size) const {
if (size == 0) {
return {};
}

std::vector<std::pair<uint64_t, uint64_t>> list;
list.reserve(threadPool.get_thread_count());

const auto size_per_block = std::ceil(size / static_cast<float>(threadPool.get_thread_count()));
for (uint_fast64_t i = 0; i < size; i += size_per_block) {
list.emplace_back(i, std::min<uint64_t>(size, i + size_per_block));
}

return list;
}

uint_fast64_t dispatcherCycle = 0;

ThreadPool &threadPool;
Expand Down Expand Up @@ -200,6 +217,8 @@ class Dispatcher {
phmap::btree_multiset<std::shared_ptr<Task>, Task::Compare> scheduledTasks;
phmap::parallel_flat_hash_map_m<uint64_t, std::shared_ptr<Task>> scheduledTasksRef;

bool asyncWaitDisabled = false;

friend class CanaryServer;
};

Expand Down
4 changes: 4 additions & 0 deletions src/items/containers/container.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ std::shared_ptr<Container> Container::create(std::shared_ptr<Tile> tile) {

Container::~Container() {
if (getID() == ITEM_BROWSEFIELD) {
if (getParent() && getParent()->getTile()) {
g_game().browseFields.erase(getParent()->getTile());
}

for (std::shared_ptr<Item> item : itemlist) {
item->setParent(getParent());
}
Expand Down
Loading

0 comments on commit 5788ccb

Please sign in to comment.