<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.multitheftauto.com/wiki/Modules/FileSystem/file/readByte?action=history&amp;feed=atom</id>
	<title>Modules/FileSystem/file/readByte - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.multitheftauto.com/wiki/Modules/FileSystem/file/readByte?action=history&amp;feed=atom"/>
	<link rel="alternate" type="text/html" href="https://wiki.multitheftauto.com/index.php?title=Modules/FileSystem/file/readByte&amp;action=history"/>
	<updated>2026-04-06T12:00:30Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.39.3</generator>
	<entry>
		<id>https://wiki.multitheftauto.com/index.php?title=Modules/FileSystem/file/readByte&amp;diff=73733&amp;oldid=prev</id>
		<title>Danilo at 02:58, 23 January 2022</title>
		<link rel="alternate" type="text/html" href="https://wiki.multitheftauto.com/index.php?title=Modules/FileSystem/file/readByte&amp;diff=73733&amp;oldid=prev"/>
		<updated>2022-01-23T02:58:59Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 02:58, 23 January 2022&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l1&quot;&gt;Line 1:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 1:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&amp;lt;pageclass class=&quot;#3cc882&quot; subcaption=&quot;File function&quot;&gt;&amp;lt;/pageclass&gt;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;__NOTOC__&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;__NOTOC__&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;This function attempts to read a signed byte (native type) from a file and returns it. The amount of bytes read should be one.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;This function attempts to read a signed byte (native type) from a file and returns it. The amount of bytes read should be one.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Danilo</name></author>
	</entry>
	<entry>
		<id>https://wiki.multitheftauto.com/index.php?title=Modules/FileSystem/file/readByte&amp;diff=73649&amp;oldid=prev</id>
		<title>Danilo: Created page with &quot;__NOTOC__ This function attempts to read a signed byte (native type) from a file and returns it. The amount of bytes read should be one.  ==Syntax== &lt;syntaxhighlight lang=&quot;lua&quot;&gt; signed_byte file:readByte () &lt;/syntaxhighlight&gt;  ==Returns== Returns the signed byte if it was successfully read from the file, '''false''' otherwise.  ==Example== &lt;section name=&quot;Server&quot; class=&quot;server&quot; show=&quot;true&quot;&gt; This snippet writes a snapshot of server-side player information into a file. This...&quot;</title>
		<link rel="alternate" type="text/html" href="https://wiki.multitheftauto.com/index.php?title=Modules/FileSystem/file/readByte&amp;diff=73649&amp;oldid=prev"/>
		<updated>2022-01-19T03:28:28Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;__NOTOC__ This function attempts to read a signed byte (native type) from a file and returns it. The amount of bytes read should be one.  ==Syntax== &amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt; signed_byte file:readByte () &amp;lt;/syntaxhighlight&amp;gt;  ==Returns== Returns the signed byte if it was successfully read from the file, &amp;#039;&amp;#039;&amp;#039;false&amp;#039;&amp;#039;&amp;#039; otherwise.  ==Example== &amp;lt;section name=&amp;quot;Server&amp;quot; class=&amp;quot;server&amp;quot; show=&amp;quot;true&amp;quot;&amp;gt; This snippet writes a snapshot of server-side player information into a file. This...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;__NOTOC__&lt;br /&gt;
This function attempts to read a signed byte (native type) from a file and returns it. The amount of bytes read should be one.&lt;br /&gt;
&lt;br /&gt;
==Syntax==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
signed_byte file:readByte ()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Returns==&lt;br /&gt;
Returns the signed byte if it was successfully read from the file, '''false''' otherwise.&lt;br /&gt;
&lt;br /&gt;
==Example==&lt;br /&gt;
&amp;lt;section name=&amp;quot;Server&amp;quot; class=&amp;quot;server&amp;quot; show=&amp;quot;true&amp;quot;&amp;gt;&lt;br /&gt;
This snippet writes a snapshot of server-side player information into a file. This is a system that keeps persistent player data on a server based on the nickname. It should be expanded to manage the lifetime of player information, so the database does not grow too big. This is theoretical code and should be used as basis.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
-- Create the filesystem interface.&lt;br /&gt;
local fsys = createFilesystemInterface();&lt;br /&gt;
&lt;br /&gt;
if not ( fsys ) then&lt;br /&gt;
    outputDebugString( &amp;quot;could not acquire filesystem interface handle&amp;quot; );&lt;br /&gt;
    return false;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Get a file translator to this resource.&lt;br /&gt;
local resRoot = fsys.createTranslator( &amp;quot;mods/deathmatch/resources/playerManager/&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
-- Keep track of player information.&lt;br /&gt;
local playerData = {};&lt;br /&gt;
&lt;br /&gt;
local function createPlayerInfo( nickname )&lt;br /&gt;
    local info = {&lt;br /&gt;
        nickname = nickname,&lt;br /&gt;
        weapons = {},&lt;br /&gt;
        player = false&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    function info.setPlayer( player )&lt;br /&gt;
        if ( player ) then&lt;br /&gt;
            local weapons = info.weapons;&lt;br /&gt;
&lt;br /&gt;
            for m=1,12 do&lt;br /&gt;
                local weapInfo = weapons[m];&lt;br /&gt;
&lt;br /&gt;
                if ( weapInfo ) then&lt;br /&gt;
                    -- Update the players weapon information.&lt;br /&gt;
                    setPlayerWeapon( m, weapInfo.weaponType );&lt;br /&gt;
                    setPlayerAmmoInClip( m, weapInfo.currentAmmo );&lt;br /&gt;
                    setPlayerTotalAmmo( m, weapInfo.maxAmmo );&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        -- Save the player object.&lt;br /&gt;
        info.player = player;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    function info.saveState()&lt;br /&gt;
        local weapons = info.weapons;&lt;br /&gt;
        local player = info.player;&lt;br /&gt;
&lt;br /&gt;
        if ( player ) then return; end;&lt;br /&gt;
&lt;br /&gt;
        for m=1,12 do&lt;br /&gt;
            weapons[m] = {&lt;br /&gt;
                weaponType = getPlayerWeapon( player ),&lt;br /&gt;
                currentAmmo = getPlayerAmmoInClip( player ),&lt;br /&gt;
                maxAmmo = getPlayerTotalAmmo( player )&lt;br /&gt;
            };&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return info;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Utilities for writing and reading short strings.&lt;br /&gt;
-- Here our byte functions come into play.&lt;br /&gt;
local function readSmallString( theFile )&lt;br /&gt;
    theFile:read( theFile:readUByte() );&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function writeSmallString( theFile, string )&lt;br /&gt;
    theFile:writeUByte( #string );&lt;br /&gt;
    theFile:write( string );&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Create player information from persistent storage.&lt;br /&gt;
local storageFile = false;&lt;br /&gt;
&lt;br /&gt;
if ( resRoot:exists( &amp;quot;player.dat&amp;quot; ) ) then&lt;br /&gt;
    -- Load player information.&lt;br /&gt;
    storageFile = resRoot:open( &amp;quot;player.dat&amp;quot;, &amp;quot;rb+&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
    -- Make sure we could open the file correctly.&lt;br /&gt;
    if ( storageFile ) then&lt;br /&gt;
        -- Read the header.&lt;br /&gt;
        local numPlayerEntries = storageFile:readInt();&lt;br /&gt;
&lt;br /&gt;
        -- Process each player entry.&lt;br /&gt;
        local n = 1;&lt;br /&gt;
&lt;br /&gt;
        while ( n &amp;lt;= numPlayerEntries ) do&lt;br /&gt;
            local nickname = readSmallString( storageFile );&lt;br /&gt;
            local weapons = {};&lt;br /&gt;
&lt;br /&gt;
            for m=1,12 do&lt;br /&gt;
                local info = {&lt;br /&gt;
                    weaponType = theFile:readUByte(),&lt;br /&gt;
                    currentAmmo = theFile:readUShort(),&lt;br /&gt;
                    totalAmmo = theFile:readUShort()&lt;br /&gt;
                };&lt;br /&gt;
                table.insert( weapons, info );&lt;br /&gt;
            end&lt;br /&gt;
&lt;br /&gt;
            -- Create and store the player information.&lt;br /&gt;
            local playerInfo = createPlayerInfo( nickname );&lt;br /&gt;
            playerInfo.weapons = weapons;&lt;br /&gt;
&lt;br /&gt;
            table.insert( playerData, playerInfo );&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
else&lt;br /&gt;
    storageFile = resRoot:open( &amp;quot;player.dat&amp;quot;, &amp;quot;wb&amp;quot; );&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function getPlayerInfo( player, createNew )&lt;br /&gt;
    if ( createNew == nil ) then createNew = true; end&lt;br /&gt;
&lt;br /&gt;
    -- Attempt to get by player handle.&lt;br /&gt;
    for m,n in ipairs(playerData) do&lt;br /&gt;
        if ( n.player == player ) then&lt;br /&gt;
            return n;&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Attempt to get by player nick.&lt;br /&gt;
    local nickname = getPlayerName( player );&lt;br /&gt;
&lt;br /&gt;
    for m,n in ipairs(playerData) do&lt;br /&gt;
        if ( n.nickname == nickname ) then&lt;br /&gt;
            n.setPlayer( player );&lt;br /&gt;
            return n;&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if ( createNew ) then&lt;br /&gt;
        -- We found nothing, so lets create a new player info.&lt;br /&gt;
        local newInfo = createPlayerInfo( nickname );&lt;br /&gt;
        newInfo.setPlayer( player );&lt;br /&gt;
        return newInfo;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return false;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
addEventHandler( &amp;quot;onPlayerJoin&amp;quot;, root,&lt;br /&gt;
    function()&lt;br /&gt;
        -- Cache the player information.&lt;br /&gt;
        getPlayerInfo( source );&lt;br /&gt;
    end&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
addEventHandler( &amp;quot;onPlayerQuit&amp;quot;, root,&lt;br /&gt;
    function()&lt;br /&gt;
        -- Make sure we do not have a player information attached to the quit player anymore.&lt;br /&gt;
        local info = getPlayerInfo( source, false );&lt;br /&gt;
&lt;br /&gt;
        if not ( info ) then return; end;&lt;br /&gt;
&lt;br /&gt;
        info.saveStatus();&lt;br /&gt;
        info.setPlayer( false );&lt;br /&gt;
    end&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
addEventHandler( &amp;quot;onResourceStop&amp;quot;, resourceRoot,&lt;br /&gt;
    function()&lt;br /&gt;
        -- Store the player information to disk.&lt;br /&gt;
        if ( storageFile ) then&lt;br /&gt;
            -- Write the number of playerData entries.&lt;br /&gt;
            storageFile:writeInt( #playerData );&lt;br /&gt;
&lt;br /&gt;
            for m,n in ipairs( playerData ) do&lt;br /&gt;
                -- Make sure the info is up to date.&lt;br /&gt;
                n.saveState();&lt;br /&gt;
&lt;br /&gt;
                -- Write player header.&lt;br /&gt;
                writeSmallString( storageFile, getPlayerName( n.nickname ) );&lt;br /&gt;
&lt;br /&gt;
                -- Now write the player information.&lt;br /&gt;
                for m,n in ipairs( n.weapons ) do&lt;br /&gt;
                    theFile:writeUByte( n.weaponType );&lt;br /&gt;
                    theFile:writeUShort( n.currentAmmo );&lt;br /&gt;
                    theFile:writeUShort( n.maxAmmo );&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
&lt;br /&gt;
            -- Clean up the file handle.&lt;br /&gt;
            storageFile:destroy();&lt;br /&gt;
&lt;br /&gt;
            -- We are finished saving. Tell the server owner.&lt;br /&gt;
            outputDebugString( &amp;quot;wrote persistent player storage.&amp;quot; );&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;/section&amp;gt;&lt;br /&gt;
{{:Modules/FileSystem/file/functions}}&lt;/div&gt;</summary>
		<author><name>Danilo</name></author>
	</entry>
</feed>