LogUtils

This bundle is marked as pending. It has not been reviewed by a staff member yet.
LogUtils v1.0.1 by Tomotz

This library provides a log file for the game.

Features beyond what FileIO offers:
- Log is saved to a memory buffer, allowing you to write to the file over and over again without losing the old data.
- Writing lines to the log only when the game is in replay to reduce performance impact
- Maximum log length - when reached, will open a new log file (and memory buffer) to avoid long writes
- Adds the player id to the log name to allow multiple logs from a single game on the same computer (for map testing)

Interface:
LogWrite(line)
Appends a line to the current log file (also flushes everything in the memory buffer to the file)
LogWriteNoFlush(line)
Appends a line to the memory buffer without writing it to the file.
This should only be used if you know you will eventually use a LogWrite to flush this line
LogWriteNoFlushReplay(line)
LogWriteReplay(line)
These functions are the same as the ones above, except they will only write the line when a replay of the game is played.
Note that the normal variants of these functions will write in both replay and normal modes.
These functions should be used when you worry about game performace impact. If you write many/very long lines to
the log, it might hurt performance

Installation instructions:
Copy the code to your map.

Credits:
TriggerHappy GameStatus (Replay Detection) [vJASS] - GameStatus (Replay Detection)
* A big block of code was taken from there to allow detecting that the game is run in replay mode.
Requires:
FileIO (lua) by Trokkin - [Lua] - FileIO (Lua-optimized)
TotalInitialization by Bribe - [Lua] - Total Initialization

Updated:
27 Dec 2024

Lua:
if Debug and Debug.beginFile then Debug.beginFile("LogUtils") end
--[[
LogUtils v1.0.1 by Tomotz
This library provides a log file for the game.
Features beyond what FileIO offers:
 - Log is saved to a memory buffer, allowing you to write to the file over and over again without losing the old data.
 - Writing lines to the log only when the game is in replay to reduce performance impact
 - Maximum log length - when reached, will open a new log file (and memory buffer) to avoid long writes
 - Adds the player id to the log name to allow multiple logs from a single game on the same computer (for map testing)
Interface:
    LogWrite(line)
        Appends a line to the current log file (also flushes everything in the memory buffer to the file)
    LogWriteNoFlush(line)
        Appends a line to the memory buffer without writing it to the file.
        This should only be used if you know you will eventually use a LogWrite to flush this line
    LogWriteNoFlushReplay(line)
    LogWriteReplay(line)
        These functions are the same as the ones above, except they will only write the line when a replay of the game is played.
        Note that the normal variants of these functions will write in both replay and normal modes.
        These functions should be used when you worry about game performace impact. If you write many/very long lines to
        the log, it might hurt performance
Installation instructions:
Copy the code to your map.
Credits:
TriggerHappy GameStatus (Replay Detection) https://www.hiveworkshop.com/threads/gamestatus-replay-detection.293176/
 * A big block of code was taken from there to allow detecting that the game is run in replay mode.
Requires:
FileIO (lua) by Trokkin - https://www.hiveworkshop.com/threads/fileio-lua-optimized.347049/
TotalInitialization by Bribe - https://www.hiveworkshop.com/threads/total-initialization.317099/
Updated: 24 Dec 2024
--]]
do
    LIBRARY_LogUtils   = true
    local SCOPE_PREFIX = "LogUtils_" ---@type string requires TotalInitialization, FileIO
    -- Configurations:

    -- Base name for the log files.
    -- The logs are saved to Documents\Warcraft III\CustomMapData
    -- the relative path where the log files are kept. Should end with \\
    local RAW_LOG_PATH    = "Savegames\\TestMap\\"
    -- Raw name for the log file. Will append the player index to the start on any mode, and "replay" to the end on replay mode.
    -- Will also add the log index (in case there are multiple log files in the same run) and .txt to the end
    local RAW_LOG_NAME    = "last_game_log"
    -- The maximum length of the memory buffer. If too long, writes to the log file can take a long time
    -- (as the whole buffer is flushed on every write) and hinder performances
    local MAX_BUFF_LEN    = 50000 ---@type integer -- Theoretically, FileIO supports 999999
    -- Maximum number of log files that will be created in a single game (will stop logging if threshold was reached)
    local MAX_FILES       = 10 ---@type integer
    -- Same as MAX_FILES, but for replay logs
    local MAX_FILESREPLAY = 50 ---@type integer
    -- If true, will try writing the map name to the long on init (using TRIGSTR_001)
    local WRITE_MAP_NAME  = true ---@type boolean
    -- Useful globals that tells you if the game is offline (single player I think), online or replay.
    -- The first 3 are constants and should not be changed
    GAME_STATUS_OFFLINE   = 0 ---@type integer
    GAME_STATUS_ONLINE    = 1 ---@type integer
    GAME_STATUS_REPLAY    = 2 ---@type integer
    GameStatus            = 0 ---@type integer -- one of GAME_STATUS_OFFLINE, GAME_STATUS_ONLINE, GAME_STATUS_REPLAY
    -- Local variables for internal use
    local LogFileName ---@type string
    local WriteBuffer     = "\n" ---@type string
    local FileIdx         = 0 ---@type integer
    local IsFlashed       = true ---@type boolean
    ---@param text string
    local function WriteAndFlush(text)
        if (FileIdx < MAX_FILES) or ((GameStatus == GAME_STATUS_REPLAY) and (FileIdx < MAX_FILESREPLAY)) then
            FileIO.Save(LogFileName, text)
        end
    end
    local function CreateNewLogFile()
        LogFileName = RAW_LOG_PATH .. GetPlayerId(GetLocalPlayer()) .. "_" .. RAW_LOG_NAME .. "_"
        if GameStatus == GAME_STATUS_REPLAY then
            LogFileName = LogFileName .. "replay_"
        end
        LogFileName = LogFileName .. tostring(FileIdx) .. ".txt"
        FileIdx = FileIdx + 1
        WriteAndFlush("\nLog file is empty")
    end
    -- sets GameStatus variable which decides if game is online, offline or replay
    local function SetGameStatus()
        local firstPlayer ---@type player
        local u ---@type unit
        local selected ---@type boolean
        -- find an actual player
        firstPlayer = Player(0)
        while not ((GetPlayerController(firstPlayer) == MAP_CONTROL_USER and GetPlayerSlotState(firstPlayer) == PLAYER_SLOT_STATE_PLAYING)) do
            firstPlayer = Player(GetPlayerId(firstPlayer) + 1)
        end
        -- force the player to select a dummy unit
        u = CreateUnit(firstPlayer, FourCC('hfoo'), 0, 0, 0)
        SelectUnit(u, true)
        selected = IsUnitSelected(u, firstPlayer)
        RemoveUnit(u)
        if (selected) then
            -- detect if replay or offline game
            if (ReloadGameCachesFromDisk()) then
                GameStatus = GAME_STATUS_OFFLINE
            else
                GameStatus = GAME_STATUS_REPLAY
            end
        else
            -- if the unit wasn't selected instantly, the game is online
            GameStatus = GAME_STATUS_ONLINE
        end
    end
    local function init()
        SetGameStatus()
        CreateNewLogFile()
        -- write map name to log
        if WRITE_MAP_NAME then
            LogWrite(GetLocalizedString("TRIGSTR_001"))
        end
    end
    -- Writes a line to the WriteBuffer to be logged
    ---@param line string
    function LogWriteNoFlush(line)
        local full_line = line .. "\n" ---@type string
        if StringLength(WriteBuffer) + StringLength(full_line) > MAX_BUFF_LEN then
            if not IsFlashed then
                WriteAndFlush(WriteBuffer)
            end
            CreateNewLogFile()
            WriteBuffer = full_line
        else
            WriteBuffer = WriteBuffer .. full_line
        end
        IsFlashed = false
    end
    -- Writes a line to the WriteBuffer to be logged only in replay mode
    ---@param line string
    function LogWriteNoFlushReplay(line)
        if GameStatus == GAME_STATUS_REPLAY then
            LogWriteNoFlush(line)
        end
    end
    -- Writes a line to the current log
    ---@param line string
    function LogWrite(line)
        LogWriteNoFlush(line)
        WriteAndFlush(WriteBuffer)
        IsFlashed = true
    end
    -- Writes a line to the log only in replay mode
    ---@param line string
    function LogWriteReplay(line)
        if GameStatus == GAME_STATUS_REPLAY then
            LogWrite(line)
        end
    end
    OnInit(init)
end
if Debug and Debug.endFile then Debug.endFile() end

Change Log:
1.0.1: Fixed bug with log names for multiplayer.
Previews
Contents

TestMap (Map)

Top