• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

[TFS 1.3] [8.6] Server Freeze/Lag when player die

ivvanek

New Member
Joined
Mar 24, 2009
Messages
113
Reaction score
3
I have realized that droploot.lua and PlayerDeath.lua makes my server freeze for 3 seconds when player die.

Disabled in xml file:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<creaturescripts>
    <event type="login" name="PlayerLogin" script="login.lua" />
    <event type="logout" name="PlayerLogout" script="logout.lua" />
    <event type="login" name="FirstItems" script="firstitems.lua" />
<!--    <event type="login" name="OfflineTraining" script="offlinetraining.lua" /> -->
    <event type="login" name="RegenerateStamina" script="regeneratestamina.lua" />
<!--    <event type="death" name="PlayerDeath" script="playerdeath.lua" /> -->
<!--    <event type="death" name="DropLoot" script="droploot.lua" /> -->
    <event type="extendedopcode" name="ExtendedOpcode" script="extendedopcode.lua" />
</creaturescripts>

droploot.lua
Code:
function onDeath(player, corpse, killer, mostDamage, unjustified, mostDamage_unjustified)
    if player:hasFlag(PlayerFlag_NotGenerateLoot) or player:getVocation():getId() == VOCATION_NONE then
        return true
    end

    local amulet = player:getSlotItem(CONST_SLOT_NECKLACE)
    if amulet and amulet.itemid == ITEM_AMULETOFLOSS and not table.contains({SKULL_RED, SKULL_BLACK}, player:getSkull()) then
        local isPlayer = false
        if killer then
            if killer:isPlayer() then
                isPlayer = true
            else
                local master = killer:getMaster()
                if master and master:isPlayer() then
                    isPlayer = true
                end
            end
        end

        if not isPlayer or not player:hasBlessing(6) then
            player:removeItem(ITEM_AMULETOFLOSS, 1, -1, false)
        end
    else
        for i = CONST_SLOT_HEAD, CONST_SLOT_AMMO do
            local item = player:getSlotItem(i)
            if item then
                if table.contains({SKULL_RED, SKULL_BLACK}, player:getSkull()) or math.random(item:isContainer() and 100 or 1000) <= player:getLossPercent() then
                    if not item:moveTo(corpse) then
                        item:remove()
                    end
                end
            end
        end
    end

    if not player:getSlotItem(CONST_SLOT_BACKPACK) then
        player:addItem(ITEM_BAG, 1, false, CONST_SLOT_BACKPACK)
    end
    return true
end

playerdeath.lua
Code:
local deathListEnabled = true
local maxDeathRecords = 5

function onDeath(player, corpse, killer, mostDamageKiller, unjustified, mostDamageUnjustified)
    local playerId = player:getId()
    if nextUseStaminaTime[playerId] then
        nextUseStaminaTime[playerId] = nil
    end

    player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You are dead.")
    if not deathListEnabled then
        return
    end

    local byPlayer = 0
    local killerName
    if killer then
        if killer:isPlayer() then
            byPlayer = 1
        else
            local master = killer:getMaster()
            if master and master ~= killer and master:isPlayer() then
                killer = master
                byPlayer = 1
            end
        end
        killerName = killer:getName()
    else
        killerName = "field item"
    end

    local byPlayerMostDamage = 0
    local mostDamageKillerName
    if mostDamageKiller then
        if mostDamageKiller:isPlayer() then
            byPlayerMostDamage = 1
        else
            local master = mostDamageKiller:getMaster()
            if master and master ~= mostDamageKiller and master:isPlayer() then
                mostDamageKiller = master
                byPlayerMostDamage = 1
            end
        end
        mostDamageName = mostDamageKiller:getName()
    else
        mostDamageName = "field item"
    end

    local playerGuid = player:getGuid()
    db.query("INSERT INTO `player_deaths` (`player_id`, `time`, `level`, `killed_by`, `is_player`, `mostdamage_by`, `mostdamage_is_player`, `unjustified`, `mostdamage_unjustified`) VALUES (" .. playerGuid .. ", " .. os.time() .. ", " .. player:getLevel() .. ", " .. db.escapeString(killerName) .. ", " .. byPlayer .. ", " .. db.escapeString(mostDamageName) .. ", " .. byPlayerMostDamage .. ", " .. (unjustified and 1 or 0) .. ", " .. (mostDamageUnjustified and 1 or 0) .. ")")
    local resultId = db.storeQuery("SELECT `player_id` FROM `player_deaths` WHERE `player_id` = " .. playerGuid)

    local deathRecords = 0
    local tmpResultId = resultId
    while tmpResultId ~= false do
        tmpResultId = result.next(resultId)
        deathRecords = deathRecords + 1
    end

    if resultId ~= false then
        result.free(resultId)
    end

    local limit = deathRecords - maxDeathRecords
    if limit > 0 then
        db.asyncQuery("DELETE FROM `player_deaths` WHERE `player_id` = " .. playerGuid .. " ORDER BY `time` LIMIT " .. limit)
    end

    if byPlayer == 1 then
        local targetGuild = player:getGuild()
        targetGuild = targetGuild and targetGuild:getId() or 0
        if targetGuild ~= 0 then
            local killerGuild = killer:getGuild()
            killerGuild = killerGuild and killerGuild:getId() or 0
            if killerGuild ~= 0 and targetGuild ~= killerGuild and isInWar(playerId, killer:getId()) then
                local warId = false
                resultId = db.storeQuery("SELECT `id` FROM `guild_wars` WHERE `status` = 1 AND ((`guild1` = " .. killerGuild .. " AND `guild2` = " .. targetGuild .. ") OR (`guild1` = " .. targetGuild .. " AND `guild2` = " .. killerGuild .. "))")
                if resultId ~= false then
                    warId = result.getNumber(resultId, "id")
                    result.free(resultId)
                end

                if warId ~= false then
                    db.asyncQuery("INSERT INTO `guildwar_kills` (`killer`, `target`, `killerguild`, `targetguild`, `time`, `warid`) VALUES (" .. db.escapeString(killerName) .. ", " .. db.escapeString(player:getName()) .. ", " .. killerGuild .. ", " .. targetGuild .. ", " .. os.time() .. ", " .. warId .. ")")
                end
            end
        end
    end
end

How to fix?

EDIT:
I have disabled everything in creaturescripts.xml and still i have freeze 3 seconds when player die. Which next step i have to do to find the problem?

Code:
<?xml version="1.0" encoding="UTF-8"?>
<creaturescripts>
<!--    <event type="login" name="PlayerLogin" script="login.lua" /> -->
<!--    <event type="logout" name="PlayerLogout" script="logout.lua" /> -->
<!--    <event type="login" name="FirstItems" script="firstitems.lua" /> -->
<!--    <event type="login" name="OfflineTraining" script="offlinetraining.lua" /> -->
<!--    <event type="login" name="RegenerateStamina" script="regeneratestamina.lua" /> -->
<!--    <event type="death" name="PlayerDeath" script="playerdeath.lua" /> -->
<!--    <event type="death" name="DropLoot" script="droploot.lua" /> -->
<!--    <event type="extendedopcode" name="ExtendedOpcode" script="extendedopcode.lua" /> -->
</creaturescripts>
 
Last edited:
i installed everything from zero, recompilled files of engine, new database, changing Acc Makers from myAAC to ZnoteAAC and everytime i have the same problem. When player die and server is freezing for 2-3 seconds, after freeze his body going to the ground, after dead 3 seconds freeze, body on ground and lag is gone.
Whats going on? maybe the engine from @Nekiro has bug?
 
Bump.
I was using mariadb and thinking this is the issue, then reinstalled again my vps and installed mysql 5.7 server and the same problem, when players die i have lag on server.
Any ideas?
 
Fixed, it was problem with operation system, i installed debian 9, 10, ubuntu 16.04 and i had the same problem. Probably it is problem with the database complability or connection or loop problem, dunno. I reinstalled system to debian 8 jessie and works good with mysql.
 
Fixed, it was problem with operation system, i installed debian 9, 10, ubuntu 16.04 and i had the same problem. Probably it is problem with the database complability or connection or loop problem, dunno. I reinstalled system to debian 8 jessie and works good with mysql.
lib version maybe (debian 8 have old libs)
 
I am very disappointed but the problem back... i was wrong with the solved problem because it doesnt lag/freeze every time. Sometimes it lag for 2-3 seconds, sometimes for 1 seconds, sometimes for 0.1 second, thats very weird. I am very tired about this issue... any ideas?
 
I was using mariadb
Try creating a new database - but use Aria instead of InnoDB as table engine.
Replace ENGINE=InnoDB with ENGINE=Aria in your schemas (server and znote) and in the scripts in the migrations folder.

Edit: tell us how long it takes to import your schemas to the database when using InnoDB as engine, and how long it takes using Aria, please.
Edit #2: I don't know if there are negative implications by changing the table engine, but I haven't had any problems in my server since I did it.
Edit #3: the freeze on death - isn't it actually caused by the logout? Try logging out and check if it also freezes the server for a few seconds.
Edit #4: I noticed that you posted several threads about having freezes when certain events happen - this might fix them all.
 
Last edited:
Back
Top