LUA скрипт [gs] lagrecord

  • Автор темы Автор темы amiiiil
  • Дата начала Дата начала
Пользователь
Пользователь
Статус
Оффлайн
Регистрация
2 Май 2022
Сообщения
460
Реакции
68
ported from salvatore's git [
Пожалуйста, авторизуйтесь для просмотра ссылки.
]


Код:
Expand Collapse Copy
local ffi = require "ffi"
local vector = require "vector"

local function contains(tbl, val)
    for i = 1, #tbl do
        if tbl[i] == val then
            return true
        end
    end

    return false
end

local function to_time(ticks)
    return globals.tickinterval() * ticks
end

local function to_ticks(time)
    return math.floor(time / globals.tickinterval()) + 0.5
end

local sv_maxunlag = cvar.sv_maxunlag

math.clamp = function(v, min, max)
    if v <= min then return min end
    if v >= max then return max end
    return v
end


local host_frameticks = ffi.cast('uint32_t*', ffi.cast("uintptr_t", client.find_signature('engine.dll', "\x03\x05\xCC\xCC\xCC\xCC\x83\xCF\x10")) + 0x2)
local host_currentframetick = ffi.cast('uint32_t*', ffi.cast("uintptr_t", client.find_signature('engine.dll', "\x2B\x05\xCC\xCC\xCC\xCC\x03\x05\xCC\xCC\xCC\xCC\x83\xCF\x10")) + 0x2)

-- Functions
local new_class = function()
    local mt, mt_data, this_mt = { }, { }

    mt.__metatable = false
    mt_data.struct = function(self, name)
        assert(type(name) == 'string', 'invalid class name')
        assert(rawget(self, name) == nil, 'cannot overwrite subclass')

        return function(data)
            assert(type(data) == 'table', 'invalid class data')
            rawset(self, name, setmetatable(data, {
                __metatable = false,
                __index = function(self, key)
                    return
                    rawget(mt, key) or
                            rawget(this_mt, key)
                end
            }))

            return this_mt
        end
    end

    this_mt = setmetatable(mt_data, mt)

    return this_mt
end

local insert = function(tbl, new_value)
    local new_tbl = {}

    new_tbl[#new_tbl+1] = new_value

    for _, value in pairs(tbl) do
        if value ~= nil then
            new_tbl[#new_tbl+1] = value
        end
    end

    return new_tbl
end

local evnt do (function()
    local c_list = { }

    local function register_callback(fn)
        assert(type(fn) == 'function', 'callback has to be a function')

        local already_exists = false

        for _, this in pairs(c_list) do
            if this == fn then
                already_exists = true
                break
            end
        end

        if already_exists then
            error('the function callback is already registered', 3)
        end

        table.insert(c_list, fn)
    end

    local function unregister_callback(fn)
        assert(type(fn) == 'function', 'callback has to be a function')

        for index, this in pairs(c_list) do
            if this == fn then
                table.remove(c_list, index)

                return true
            end
        end

        return false
    end

    local function get_list()
        return c_list
    end

    local function fire_callback(...)
        local output = false

        for idx, callback in ipairs(c_list) do
            local success, result = pcall(callback, ...)

            if success == true and result == true then
                output = true
                break
            end
        end

        return output
    end

    evnt = {
        register = register_callback,
        unregister = unregister_callback,
        fire_callback = fire_callback,
        get_list = get_list
    }
end)() end

-- Global Class
local ctx = new_class()
        :struct 'lagrecord' {
    data = { },

    estimated_tickbase = 0,
    local_player_tickbase = 0,



    purge = function(self, player)
        if player == nil then
            self.estimated_tickbase = 0
            self.local_player_tickbase = 0
            self.data = { }

            return
        end

        self.data[player] = { }
    end,

    track_time = function(self, cmd)
        self.estimated_tickbase = entity.get_prop(entity.get_local_player(), "m_nTickBase")

        if cmd.chokedcommands == 0 then
            self.local_player_tickbase = entity.get_prop(entity.get_local_player(), "m_nTickBase")
        end
    end,

    get_server_time = function(self, as_ticks)
        local predicted_server_tick = globals.servertickcount()

        if host_frameticks ~= nil and host_currentframetick ~= nil then
            local delta = host_frameticks[0] - host_currentframetick[0]
            local max_delta_for_tick_rate = math.floor(1 / globals.tickinterval()) / 8

            if delta > 0 and delta < max_delta_for_tick_rate then
                predicted_server_tick = predicted_server_tick + delta
            end
        end

        return as_ticks ~= true and to_time(predicted_server_tick) or predicted_server_tick
    end,

    get_player_time = function(self, player, as_tick)
        assert(player ~= nil, 'invalid player')

        if player == entity.get_local_player() then
            local m_nTickBase = self.local_player_tickbase -- player.m_nTickBase

            return as_tick ~= true and to_time(m_nTickBase) or m_nTickBase
        end

        local simulation_time = entity.get_prop(player, "m_flSimulationTime")

        return as_tick == true and
                to_ticks(simulation_time) or simulation_time
    end,

    get_dead_time = function(self, as_tick)
        local sv_maxunlag = sv_maxunlag:get_float()
        local outgoing_latency = client.latency()

        local dead_time = to_time(self.estimated_tickbase) - outgoing_latency - sv_maxunlag

        return as_tick == true and to_ticks(dead_time) or dead_time
    end,

    verify_records = function(self, userptr, dead_time, is_alive)
        if  userptr == nil or
                userptr.records == nil or userptr.localdata == nil then
            return
        end

        -- make sure we dont keep old records if those become invalid
        local records, localdata = userptr.records, userptr.localdata
        local first_rec_origin = records[1] and records[1].origin
        local allow_updates = localdata.allow_updates

        for idx, this in ipairs(records) do
            local c_idx = idx ~= 1

            if allow_updates == false then
                c_idx = true
            end

            if is_alive == false then
                rawset(records, idx, nil)
            elseif c_idx == true and first_rec_origin then
                if this.simulation_time <= dead_time then
                    -- purge current record if simulation time is too old
                    rawset(records, idx, nil)
                elseif first_rec_origin:distsqr(this.origin) > 4096 then
                    -- purge records if teleport distance is too big
                    for i=2, #records do
                        rawset(records, i, nil)
                    end

                    break
                end
            end
        end
    end,

    on_net_update = function(self, player, tick, dead_time)
        assert(player ~= nil, 'invalid player')

        local index = player
        local origin = vector(entity.get_origin(player))
        local is_alive = entity.is_alive(player)

        self.data[index] = self.data[index] or new_class()
                :struct 'records' { }
                :struct 'localdata' {
            allow_updates = false,
            updated_this_frame = false,
            last_animated_simulation = 0,
            no_entry = vector(),
            cycle = 0
        }

        -- preserve data
        local user = self.data[index]
        local records, localdata = user.records, user.localdata
        local simulation_time = self:get_player_time(player)

        -- set update state to false
        localdata.allow_updates = evnt.fire_callback(player)
        localdata.updated_this_frame = false

        if  localdata.allow_updates == false or
                is_alive == false or entity.is_dormant(player) == true then
            goto verify_records
        end

        do
            local shifted_forwards = records[1] and
                    math.max(0, to_ticks(records[1].simulation_time - simulation_time)) or 0

            if shifted_forwards > 0 and localdata.no_entry.x == 0 then
                localdata.no_entry.y = shifted_forwards
            elseif shifted_forwards <= 0 then
                localdata.no_entry.y = 0
            end

            localdata.cycle = records[1] and math.max(0, tick - records[1].tick - 1) or 0
            localdata.no_entry.x = shifted_forwards
            localdata.last_animated_simulation = simulation_time

            if records[1] and simulation_time <= records[1].simulation_time then
                goto verify_records
            end

            -- STAGE: PLAYER_UPDATE
            localdata.updated_this_frame = true

            rawset(user, 'records', insert(records, {
                tick = tick,

                target = player,
                shifting = to_ticks(simulation_time) - tick - 1,
                elapsed = math.clamp(records[1] and (tick - records[1].tick - 1) or 0, 0, 72),
                choked = math.clamp(records[1] and (to_ticks(simulation_time - records[1].simulation_time) - 1) or 0, 0, 72),

                origin = origin,
                origin_old = records[1] and records[1].origin or origin,
                simulation_time = simulation_time,
                simulation_time_old = records[1] and records[1].simulation_time or simulation_time,

                eye_position = origin + vector(entity.get_prop(player, "m_vecViewOffset")),
                volume = { vector(entity.get_prop(player, "m_vecMins")), vector(entity.get_prop(player, "m_vecMaxs")) }
            }))
        end

        ::verify_records::

        self:verify_records(user, dead_time, is_alive)
    end
}

        :struct 'output' {
    get_player_idx = function(self, ...)
        local va = { ... }

        if #va == 0 then
            local me = entity.get_local_player()

            if me == nil then
                return
            end

            return me
        end

        local va = va[1]
        local va_type = type(va)

        if va == nil or va_type == 'nil' then
            return
        end

        if va_type == 'userdata' and va.get_index then
            return va
        end

        return va
    end,

    get_player_data = function(self, ...)
        local index = self:get_player_idx(...)

        if index == nil then
            return
        end

        local data = self.lagrecord.data[index]

        if data == nil or data.localdata == nil or data.records == nil then
            return
        end

        return data
    end,

    get_all = function(self, ...)
        local data = self:get_player_data(...)

        if data == nil then
            return
        end

        return data.records
    end,

    get_record = function(self, ...)
        local data = self:get_player_data(...)

        if data == nil then
            return
        end

        return data.records[({ ... })[2] or 1]
    end,

    get_snapshot = function(self, ...)
        local data = self:get_player_data(...)

        if data == nil then
            return
        end

        local record_at = ({ ... })[2] or 1
        local record = data.records[record_at]

        if record == nil then
            return
        end

        return {
            id = record_at,
            tick = record.tick,
            updated_this_frame = data.localdata.updated_this_frame,

            origin = {
                angles = record.angles,
                volume = record.volume,
                current = record.origin,
                previous = record.origin_old,
                change = record.origin:distsqr(record.origin_old)
            },

            simulation_time = {
                animated = data.localdata.last_animated_simulation,
                current = record.simulation_time,
                previous = record.simulation_time_old,
                change = record.simulation_time - record.simulation_time_old
            },

            command = {
                elapsed = record.elapsed,
                choke = record.choked,
                cycle = data.localdata.cycle,
                shifting = record.shifting,
                no_entry = data.localdata.no_entry,
            }
        }, record
    end,

    get_server_time = function(self, ...)
        return self.lagrecord:get_server_time(...)
    end
}

-- Callbacks
client.set_event_callback("level_init", function() ctx.lagrecord:purge() end)
client.set_event_callback("setup_command", function(cmd) ctx.lagrecord:track_time(cmd) end)
client.set_event_callback("net_update_end", function()
    local lagrecord = ctx.lagrecord

    local me = entity.get_local_player()
    local tick = lagrecord:get_server_time(true)
    local dead_time = lagrecord:get_dead_time(false)

    if me == nil then
        lagrecord:purge()
        return
    end

    if entity.is_alive(me) == false then
        lagrecord.estimated_tickbase = globals.servertickcount()
    end

    local players = entity.get_players(true, true)


    --entity.get_players(false, true, function(player)
    for i = 1, #players do
        local player = players[i]

        if player == nil or not entity.is_alive(player) then
            goto continue
        end

        lagrecord:on_net_update(player, tick, dead_time)
        ::continue::
    end

end)

return {
    set_update_callback = function(...)
        return evnt.register(...)
    end,

    unset_update_callback = function(...)
        return evnt.unregister(...)
    end,

    get_player_data = function(...)
        return ctx.output:get_player_data(...)
    end,

    get_all = function(...)
        return ctx.output:get_all(...)
    end,

    get_record = function(...)
        return ctx.output:get_record(...)
    end,

    get_snapshot = function(...)
        return ctx.output:get_snapshot(...)
    end,

    get_server_time = function(...)
        return ctx.output:get_server_time(...)
    end
}
 
Зачем это
 
А затем что оно оутдейтед, и у него банально калькуляции чоука нет и многих других правильных реализаций многих моментов а так-же дедтайм уже неправильный без фиксов под изменение тикбазы локального игрока в случае дефенсива и много прям тонны другого
 
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
А затем что оно оутдейтед, и у него банально калькуляции чоука нет и многих других правильных реализаций многих моментов а так-же дедтайм уже неправильный без фиксов под изменение тикбазы локального игрока в случае дефенсива и много прям тонны другого
Код:
Expand Collapse Copy
            -- надеюсь в этом говно чите server_tickcount уже учитывает латенси + задержку когда чел на фейкдаке иначе это пиздец
            local dead_time = math.floor( totime( globals.servertickcount( ) ) - cvar.sv_maxunlag:get_float( ) )

            if toticks( record.sim_time + self:get_lerp_time( ) ) < dead_time then
                return false
            end
 
Код:
Expand Collapse Copy
            -- надеюсь в этом говно чите server_tickcount уже учитывает латенси + задержку когда чел на фейкдаке иначе это пиздец
            local dead_time = math.floor( totime( globals.servertickcount( ) ) - cvar.sv_maxunlag:get_float( ) )

            if toticks( record.sim_time + self:get_lerp_time( ) ) < dead_time then
                return false
            end
а как же учет дельт шифт/аншифт тайма локал плеера (ты наверное замечал как в нормальных читах по типу скита и нла во время того как у тебя елвейс он форсится дефенсив *телепортируется* бектрек, как раз таки это и есть уже фикс под тикбейз) + учет фейк латенси (который туда не залазит по дефолту, и почему-то я сам нахуй нетчаннел через ффи получал и корректировал это дерьмо)
ну и по факту ты сам уже должен понимать что это только лаг рекорды которые если довести до идеала они у тебя только будут, дальше ты сам знаешь что с ними уже можно и посмотреть дифференсы в анимациях и смотреть что как должно быть + я заметил что эзотерик не пофиксил приколы за вальве когда анимации проигрываются только на сервере, для коррекции этой хуйни тебе нужно проигрывать анимации ручками и выполнять еще тонну работы за эзотерика...
 
Последнее редактирование:
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
а как же учет дельт шифт/аншифт тайма локал плеера (ты наверное замечал как в нормальных читах по типу скита и нла во время того как у тебя елвейс он форсится дефенсив *телепортируется* бектрек, как раз таки это и есть уже фикс под тикбейз) + учет фейк латенси (который туда не залазит по дефолту, и почему-то я сам нахуй нетчаннел через ффи получал и корректировал это)
телепортируется он не по причине дефенсива а по причине срабатывания проверки на дедтайм
на счет фейк латенси не знаю что там мне похуй
если эзо не додумался in + out латенси в луа апи сразу добавить то это его проблемы
 
телепортируется он не по причине дефенсива а по причине срабатывания проверки на дедтайм
на счет фейк латенси не знаю что там мне похуй
если эзо не додумался in + out латенси в луа апи сразу добавить то это его проблемы
я выразился по своему на первый момент, второе оно по идее должно быть но чот мне лень было искать
 
ported from salvatore's git [
Пожалуйста, авторизуйтесь для просмотра ссылки.
]


Код:
Expand Collapse Copy
local ffi = require "ffi"
local vector = require "vector"

local function contains(tbl, val)
    for i = 1, #tbl do
        if tbl[i] == val then
            return true
        end
    end

    return false
end

local function to_time(ticks)
    return globals.tickinterval() * ticks
end

local function to_ticks(time)
    return math.floor(time / globals.tickinterval()) + 0.5
end

local sv_maxunlag = cvar.sv_maxunlag

math.clamp = function(v, min, max)
    if v <= min then return min end
    if v >= max then return max end
    return v
end


local host_frameticks = ffi.cast('uint32_t*', ffi.cast("uintptr_t", client.find_signature('engine.dll', "\x03\x05\xCC\xCC\xCC\xCC\x83\xCF\x10")) + 0x2)
local host_currentframetick = ffi.cast('uint32_t*', ffi.cast("uintptr_t", client.find_signature('engine.dll', "\x2B\x05\xCC\xCC\xCC\xCC\x03\x05\xCC\xCC\xCC\xCC\x83\xCF\x10")) + 0x2)

-- Functions
local new_class = function()
    local mt, mt_data, this_mt = { }, { }

    mt.__metatable = false
    mt_data.struct = function(self, name)
        assert(type(name) == 'string', 'invalid class name')
        assert(rawget(self, name) == nil, 'cannot overwrite subclass')

        return function(data)
            assert(type(data) == 'table', 'invalid class data')
            rawset(self, name, setmetatable(data, {
                __metatable = false,
                __index = function(self, key)
                    return
                    rawget(mt, key) or
                            rawget(this_mt, key)
                end
            }))

            return this_mt
        end
    end

    this_mt = setmetatable(mt_data, mt)

    return this_mt
end

local insert = function(tbl, new_value)
    local new_tbl = {}

    new_tbl[#new_tbl+1] = new_value

    for _, value in pairs(tbl) do
        if value ~= nil then
            new_tbl[#new_tbl+1] = value
        end
    end

    return new_tbl
end

local evnt do (function()
    local c_list = { }

    local function register_callback(fn)
        assert(type(fn) == 'function', 'callback has to be a function')

        local already_exists = false

        for _, this in pairs(c_list) do
            if this == fn then
                already_exists = true
                break
            end
        end

        if already_exists then
            error('the function callback is already registered', 3)
        end

        table.insert(c_list, fn)
    end

    local function unregister_callback(fn)
        assert(type(fn) == 'function', 'callback has to be a function')

        for index, this in pairs(c_list) do
            if this == fn then
                table.remove(c_list, index)

                return true
            end
        end

        return false
    end

    local function get_list()
        return c_list
    end

    local function fire_callback(...)
        local output = false

        for idx, callback in ipairs(c_list) do
            local success, result = pcall(callback, ...)

            if success == true and result == true then
                output = true
                break
            end
        end

        return output
    end

    evnt = {
        register = register_callback,
        unregister = unregister_callback,
        fire_callback = fire_callback,
        get_list = get_list
    }
end)() end

-- Global Class
local ctx = new_class()
        :struct 'lagrecord' {
    data = { },

    estimated_tickbase = 0,
    local_player_tickbase = 0,



    purge = function(self, player)
        if player == nil then
            self.estimated_tickbase = 0
            self.local_player_tickbase = 0
            self.data = { }

            return
        end

        self.data[player] = { }
    end,

    track_time = function(self, cmd)
        self.estimated_tickbase = entity.get_prop(entity.get_local_player(), "m_nTickBase")

        if cmd.chokedcommands == 0 then
            self.local_player_tickbase = entity.get_prop(entity.get_local_player(), "m_nTickBase")
        end
    end,

    get_server_time = function(self, as_ticks)
        local predicted_server_tick = globals.servertickcount()

        if host_frameticks ~= nil and host_currentframetick ~= nil then
            local delta = host_frameticks[0] - host_currentframetick[0]
            local max_delta_for_tick_rate = math.floor(1 / globals.tickinterval()) / 8

            if delta > 0 and delta < max_delta_for_tick_rate then
                predicted_server_tick = predicted_server_tick + delta
            end
        end

        return as_ticks ~= true and to_time(predicted_server_tick) or predicted_server_tick
    end,

    get_player_time = function(self, player, as_tick)
        assert(player ~= nil, 'invalid player')

        if player == entity.get_local_player() then
            local m_nTickBase = self.local_player_tickbase -- player.m_nTickBase

            return as_tick ~= true and to_time(m_nTickBase) or m_nTickBase
        end

        local simulation_time = entity.get_prop(player, "m_flSimulationTime")

        return as_tick == true and
                to_ticks(simulation_time) or simulation_time
    end,

    get_dead_time = function(self, as_tick)
        local sv_maxunlag = sv_maxunlag:get_float()
        local outgoing_latency = client.latency()

        local dead_time = to_time(self.estimated_tickbase) - outgoing_latency - sv_maxunlag

        return as_tick == true and to_ticks(dead_time) or dead_time
    end,

    verify_records = function(self, userptr, dead_time, is_alive)
        if  userptr == nil or
                userptr.records == nil or userptr.localdata == nil then
            return
        end

        -- make sure we dont keep old records if those become invalid
        local records, localdata = userptr.records, userptr.localdata
        local first_rec_origin = records[1] and records[1].origin
        local allow_updates = localdata.allow_updates

        for idx, this in ipairs(records) do
            local c_idx = idx ~= 1

            if allow_updates == false then
                c_idx = true
            end

            if is_alive == false then
                rawset(records, idx, nil)
            elseif c_idx == true and first_rec_origin then
                if this.simulation_time <= dead_time then
                    -- purge current record if simulation time is too old
                    rawset(records, idx, nil)
                elseif first_rec_origin:distsqr(this.origin) > 4096 then
                    -- purge records if teleport distance is too big
                    for i=2, #records do
                        rawset(records, i, nil)
                    end

                    break
                end
            end
        end
    end,

    on_net_update = function(self, player, tick, dead_time)
        assert(player ~= nil, 'invalid player')

        local index = player
        local origin = vector(entity.get_origin(player))
        local is_alive = entity.is_alive(player)

        self.data[index] = self.data[index] or new_class()
                :struct 'records' { }
                :struct 'localdata' {
            allow_updates = false,
            updated_this_frame = false,
            last_animated_simulation = 0,
            no_entry = vector(),
            cycle = 0
        }

        -- preserve data
        local user = self.data[index]
        local records, localdata = user.records, user.localdata
        local simulation_time = self:get_player_time(player)

        -- set update state to false
        localdata.allow_updates = evnt.fire_callback(player)
        localdata.updated_this_frame = false

        if  localdata.allow_updates == false or
                is_alive == false or entity.is_dormant(player) == true then
            goto verify_records
        end

        do
            local shifted_forwards = records[1] and
                    math.max(0, to_ticks(records[1].simulation_time - simulation_time)) or 0

            if shifted_forwards > 0 and localdata.no_entry.x == 0 then
                localdata.no_entry.y = shifted_forwards
            elseif shifted_forwards <= 0 then
                localdata.no_entry.y = 0
            end

            localdata.cycle = records[1] and math.max(0, tick - records[1].tick - 1) or 0
            localdata.no_entry.x = shifted_forwards
            localdata.last_animated_simulation = simulation_time

            if records[1] and simulation_time <= records[1].simulation_time then
                goto verify_records
            end

            -- STAGE: PLAYER_UPDATE
            localdata.updated_this_frame = true

            rawset(user, 'records', insert(records, {
                tick = tick,

                target = player,
                shifting = to_ticks(simulation_time) - tick - 1,
                elapsed = math.clamp(records[1] and (tick - records[1].tick - 1) or 0, 0, 72),
                choked = math.clamp(records[1] and (to_ticks(simulation_time - records[1].simulation_time) - 1) or 0, 0, 72),

                origin = origin,
                origin_old = records[1] and records[1].origin or origin,
                simulation_time = simulation_time,
                simulation_time_old = records[1] and records[1].simulation_time or simulation_time,

                eye_position = origin + vector(entity.get_prop(player, "m_vecViewOffset")),
                volume = { vector(entity.get_prop(player, "m_vecMins")), vector(entity.get_prop(player, "m_vecMaxs")) }
            }))
        end

        ::verify_records::

        self:verify_records(user, dead_time, is_alive)
    end
}

        :struct 'output' {
    get_player_idx = function(self, ...)
        local va = { ... }

        if #va == 0 then
            local me = entity.get_local_player()

            if me == nil then
                return
            end

            return me
        end

        local va = va[1]
        local va_type = type(va)

        if va == nil or va_type == 'nil' then
            return
        end

        if va_type == 'userdata' and va.get_index then
            return va
        end

        return va
    end,

    get_player_data = function(self, ...)
        local index = self:get_player_idx(...)

        if index == nil then
            return
        end

        local data = self.lagrecord.data[index]

        if data == nil or data.localdata == nil or data.records == nil then
            return
        end

        return data
    end,

    get_all = function(self, ...)
        local data = self:get_player_data(...)

        if data == nil then
            return
        end

        return data.records
    end,

    get_record = function(self, ...)
        local data = self:get_player_data(...)

        if data == nil then
            return
        end

        return data.records[({ ... })[2] or 1]
    end,

    get_snapshot = function(self, ...)
        local data = self:get_player_data(...)

        if data == nil then
            return
        end

        local record_at = ({ ... })[2] or 1
        local record = data.records[record_at]

        if record == nil then
            return
        end

        return {
            id = record_at,
            tick = record.tick,
            updated_this_frame = data.localdata.updated_this_frame,

            origin = {
                angles = record.angles,
                volume = record.volume,
                current = record.origin,
                previous = record.origin_old,
                change = record.origin:distsqr(record.origin_old)
            },

            simulation_time = {
                animated = data.localdata.last_animated_simulation,
                current = record.simulation_time,
                previous = record.simulation_time_old,
                change = record.simulation_time - record.simulation_time_old
            },

            command = {
                elapsed = record.elapsed,
                choke = record.choked,
                cycle = data.localdata.cycle,
                shifting = record.shifting,
                no_entry = data.localdata.no_entry,
            }
        }, record
    end,

    get_server_time = function(self, ...)
        return self.lagrecord:get_server_time(...)
    end
}

-- Callbacks
client.set_event_callback("level_init", function() ctx.lagrecord:purge() end)
client.set_event_callback("setup_command", function(cmd) ctx.lagrecord:track_time(cmd) end)
client.set_event_callback("net_update_end", function()
    local lagrecord = ctx.lagrecord

    local me = entity.get_local_player()
    local tick = lagrecord:get_server_time(true)
    local dead_time = lagrecord:get_dead_time(false)

    if me == nil then
        lagrecord:purge()
        return
    end

    if entity.is_alive(me) == false then
        lagrecord.estimated_tickbase = globals.servertickcount()
    end

    local players = entity.get_players(true, true)


    --entity.get_players(false, true, function(player)
    for i = 1, #players do
        local player = players[i]

        if player == nil or not entity.is_alive(player) then
            goto continue
        end

        lagrecord:on_net_update(player, tick, dead_time)
        ::continue::
    end

end)

return {
    set_update_callback = function(...)
        return evnt.register(...)
    end,

    unset_update_callback = function(...)
        return evnt.unregister(...)
    end,

    get_player_data = function(...)
        return ctx.output:get_player_data(...)
    end,

    get_all = function(...)
        return ctx.output:get_all(...)
    end,

    get_record = function(...)
        return ctx.output:get_record(...)
    end,

    get_snapshot = function(...)
        return ctx.output:get_snapshot(...)
    end,

    get_server_time = function(...)
        return ctx.output:get_server_time(...)
    end
}
што оно делает
 
Назад
Сверху Снизу