• 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.X] Globalevent save all players 5 minute interval

highsanta

Advanced OT User
Joined
Dec 20, 2023
Messages
424
Solutions
3
Reaction score
180
Lua:
function onThink(interval)
    local players = Game.getPlayers()
    for i = 1, #players do
        local player = players[i]
        if player:save() then
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Your data has been successfully saved.")
        else
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Failed to save your data.")
        end
    end
    Game.broadcastMessage("All player data has been successfully saved.", MESSAGE_STATUS_CONSOLE_BLUE)
    return true
end
XML:
<globalevent name="test" interval="300000" script="save.lua"/>
 
Revscript version:
Lua:
local savePlayers = GlobalEvent("SavePlayers")

function savePlayers.onThink(interval)
    for _, player in ipairs(Game.getPlayers()) do
        if player:save() then
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Your data has been successfully saved.")
        else
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Failed to save your data.")
        end
    end
    return true
end

savePlayers:interval(300000)
savePlayers:register()

Here is a version that will only save 10 players in each iteration, so it will avoid lag. It should at least reduce the lag compared to the previous method

Warning: although this method does not cause lag, it adds the possibility that players can clone items, although the possibility is low, random things can happen.
Lua:
local function savePlayer(player)
    if not player:save() then
        player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Failed to save your data.")
        return
    end

    player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Your data has been successfully saved.")
end

local function savePlayersCoroutine()
    local index = 0
    local playersId = {}
    for _, player in ipairs(Game.getPlayers()) do
        index = index + 1
        playersId[index] = player:getId()
    end

    local batchSize = 10
    return coroutine.create(function()
        for i, playerId in ipairs(playersId) do
            local player = Player(playerId)
            if player then savePlayer(player) end
            if i % batchSize == 0 then coroutine.yield() end
        end
    end)
end

local savePlayersCo = nil

local savePlayersBatch = GlobalEvent("SavePlayersBatch")

function savePlayersBatch.onThink(interval)
    savePlayersCo = savePlayersCo or savePlayersCoroutine()
    coroutine.resume(savePlayersCo)
    if coroutine.status(savePlayersCo) == "dead" then savePlayersCo = nil end
    return true
end

savePlayersBatch:interval(1000 * 60)
savePlayersBatch:register()
 
Last edited:
This can cause huge lags

jet lag GIF
 
This can cause huge lags

jet lag GIF
Yup i was going to say the same thing. Especially anyone running default serialization/deserialization of items (1 db row per item). All them deletes, reinserts, and foreign key checks firing for every item. It can be disastrous

And then to do this every 5 minutes... very bad for a server that has a lot of people online.

< 50 people online = no problem
500+ online = noticable lag due to sync lock
1000+ online = full annihilation
 
Lua:
function onThink(player, interval)

local lastSAVE = 4444
local nextSAVE = 4445
local tempomin = 1 * 60   --em segundos
local tempomax = 5 * 60

        local aleatorio = math.random(tempomin, tempomax)

    if not player or not player:isPlayer() then
        return true
    end

        if player:getStorageValue(lastSAVE) <= 0 then
           player:setStorageValue(lastSAVE, os.time())
           player:save()
        end

        if player:getStorageValue(nextSAVE) <= 0 then
           player:setStorageValue(nextSAVE, os.time() + aleatorio)
        end

 return true
end
my autosave on creaturescripts.. (remember to register onlogin)
on this case, i'm using 1~5 min, if u got more than 500 player, maybe use about 5~10min, the saves rare will be at the same time.
 
Last edited:
Lua:
function onThink(player, interval)

local lastSAVE = 4444
local nextSAVE = 4445
local tempomin = 1 * 60   --em segundos
local tempomax = 5 * 60

        local aleatorio = math.random(tempomin, tempomax)

    if not player or not player:isPlayer() or player:isFakePlayer() then
        return true
    end

        if player:getStorageValue(lastSAVE) <= 0 then
           player:setStorageValue(lastSAVE, os.time())
           player:save()
        end

        if player:getStorageValue(nextSAVE) <= 0 then
           player:setStorageValue(nextSAVE, os.time() + aleatorio)
        end

       if os.time() > player:getStorageValue(nextSAVE) then
                   player:setStorageValue(nextSAVE, os.time() + 7)
            else
              player:save()
             player:setStorageValue(nextSAVE, os.time() + aleatorio)
       end

 return true
end
my autosave on creaturescripts.. (remember to register onlogin)
on this case, i'm using 1~5 min, if u got more than 500 player, maybe use about 5~10min, the saves rare will be at the same time.
ok so, i need to ask....
what is the method isFakePlayer() for xD
 

I don't have a server to check it, but saving players into .txt/binary files or in the server's memory and then pushing it into the database sounds way faster.
I remember that on the old server, we had problems (lags) saving players even once an hour (global map + 200 players~ + saving map items), doing it the standard way until the devs [nekiro] completely rewrote that[saving player data] part.
 
Definitely it will not cause lags, it will cause desynchronizations potentially causing item cloning (in case of crash between the saves)
you will eat ze memory leaks and you will be happy
Reset Germany GIF by PEEKASSO
 
Definitely it will not cause lags, it will cause desynchronizations potentially causing item cloning (in case of crash between the saves)
Yes, you are right, thanks for capturing the problem.

Now that I think about it, the player:save() method should not even exist, as soon as we use it in some script there is the possibility that any player can clone items, just by completing the mission, the command, the action or anything that can trigger a player:save()

The only way to make it safe is to call it for all players at the same time.
 
Yes, you are right, thanks for capturing the problem.

Now that I think about it, the player:save() method should not even exist, as soon as we use it in some script there is the possibility that any player can clone items, just by completing the mission, the command, the action or anything that can trigger a player:save()

The only way to make it safe is to call it for all players at the same time.
Yeah, the concept of saving player on logout is super bad to begin with, same as any single player save
 
ok so, i need to ask....
what is the method isFakePlayer() for xD
from the sabreheaven database (which I still don't understand what it's for.)



I had forgotten to remove it and I also forgot to remove some logic, so the script is functional but there are other unnecessary things. I do globalsave every hour, then I use another function to not save the players at that exact moment.

still testing antiroll backs and these saves.
 
Back
Top