Data Storage

From GMod Wiki

Jump to: navigation, search

Flood this page with links, tutorials, wiki pages and overall categories regarding how to save and load things!

Mess.pngThis page has been deemed a mess. It may contain unnecessary information or be poorly organized. You can discuss changes on this article's talk page.

Contents

File based storage

Using text files to store data is a simple and effective way of storing data. You are free in your implementation, but this article aims to give some suggestions on how to store data. You use the standard file library, on both the server and client, to read and write files and then use string operations to write or extract the data you want.

A benefit of using this method is you have absolute freedom and it doesn't require any extra libraries.

Delimiter-seperated values

The most common and simplest method to load text files is to 'explode' the string. Exploding a string means you split a string up in chunks by a delimiter. In Lua the function to do this is string.explode and a table is returned.

Example

Let's assume we want to store everyone who has ever been to our server. We want to keep track of player names, steam id and their total playing time.

In the following example, ';' is the delimiter between values and a new row is indicated by a new line. This means that each player is on its own line. The data is formatted like so where total playing time is in seconds:

Steam ID;Player name;Total playing time
Steam ID;Player name;Total playing time
Steam ID;Player name;Total playing time

and with some values filled:

STEAM_0:1:14884029;Manadar;60
STEAM_0:0:11956651;Overv;240

Put this file into garrysmod\data\playerdata.txt

Now let's try to read the values from our file in Lua.

print("\n\n\nReading playerdata.txt ...")
 
textdata = file.Read("playerdata.txt")
print("playerdata.txt is read. Data: \n" .. textdata)
print("")
 
print("Seperating lines ...")
lines = string.Explode("\n", textdata)
print("Lines split. The lines are:")
PrintTable( lines )
 
// Now let's loop through all the lines so we can split those too
for i, line in ipairs(lines) do
	// line is the current line, and i is the current line number
 
	data = string.Explode(";", line)
 
	playersteam = data[1]
	playername = data[2]
	playertotaltime = data[3]
 
	print(playername .. " (" .. playersteam .. ") has played on this server " .. playertotaltime .. " seconds")
end
print("\n\n")

Output:

Reading playerdata.txt ...
playerdata.txt is read. Data: 
STEAM_0:1:14884029;Manadar;60
STEAM_0:0:11956651;Overv;240

Seperating lines ...
Lines split. The lines are:
1	=	STEAM_0:1:14884029;Manadar;60
2	=	STEAM_0:0:11956651;Overv;240
Parsing player data ...
Manadar (STEAM_0:1:14884029) has played on this server 60 seconds
Overv (STEAM_0:0:11956651) has played on this server 240 seconds

As you can see. We've successfully split each succeeding line and put the data in separate variables, ready to be passed to another function or whatever you want to do with it.

Putting the data in a text file is a lot easier. You make a new table and put your values in and then use the string.Implode function. Like so:

function file.AppendLine(filename, addme)
	data = file.Read(filename)
	if ( data ) then
		file.Write(filename, data .. "\n" .. tostring(addme))
	else
		file.Write(filename, tostring(addme))
	end
end
 
 
print("Getting local player data ...")
ply = LocalPlayer()
print(ply)
 
values = { ply:GetName(), ply:GetName(), 0 } // create a new table with our required values
 
print("Building data string ... ")
data = string.Implode(";", values)
 
print("Data string: " .. data)
 
file.AppendLine("playerdata.txt", data)

Output:

Getting local player data ...
Player [1][Manadar]
Building data string ... 
Data string: STEAM_0:1:14884029;Manadar;0

and our playerdata.txt now contains:

STEAM_0:1:14884029;Manadar;60
STEAM_0:0:11956651;Overv;240
STEAM_0:1:14884029;Manadar;0

Great success!

Note: Alternatively, if you want to store A LOT of data about you can choose to store the data of one player, one row in our example, in a separate file. This way you won't have to split each line or have to rewrite the entire file every time you make a change resulting in a performance boost.

TODO (Deco Da Man): Fill this in with links

Disadvantages

This implementation relies on its data not having a ; in the values. If someone joined our server with a name HiThar;;lol our example would fail horribly because one row now contains 5 values instead of the expected 3. To overcome this problem, see this serialization chapter just below this one.

Serialization

The example above only works for simple data types, but if you try to store things such as tables in tables or vectors you'll run into problems quickly. That is why there is serialization. Serialization is turning any object or variable into a sequence of bits so that it can be restored to its previous state. After the serialization we can store the bits into a file and read from the file to restore it. In Gmod the recommended method to serialize your variables is using GLON. GLON provides you with a complete layer of abstraction so you can store and restore any variables of any Gmod type you desire.

TODO (Deco Da Man): Fill this in with an example (like the above ones)

Note: Util.TableToKeyValues and Util.KeyValuesToTable are deprecated. Use GLON instead.

Relational database

Relational databases is what modern applications use to store their data. There are a great deal of benefits for using relational database, but the learning curve is much more steep than with using file based storage.

There are a number of database storage options for GMod. There is the SQLite module, built into GMod If SQLite does not suit your needs because you want to use a SQL server, you can use one of the (My)SQL modules available.

SQL

All of the relational databases listed below use SQL as their data definition language and data manipulation language. There are some minor changes between the different instances but using a quick reference guide those are easy to solve.

TODO (Deco Da Man): Fill this in with an example (like the above ones)

One of the most difficult things to learn here is to design a good database. You want to use primary keys and foreign keys where they are required, or you'll find yourself writing more queries than is necessary.

TODO (Deco Da Man): Fill this in with links

SQLite

Garry's Mod comes with a built-in SQLite library. You can use it both from server and client, and saves to the cl.db and sv.db files (I bet you can't guess which one is which!). SQLite is a small but powerful database and is often compatible with MySQL. The SQLite interface is available via the built-in sql library.

TODO (Deco Da Man): Fill this in with an example (like the above ones)

There are many tutorials for SQLite, and uncountable numbers of tutorials for SQL to be found on the internet. For SQL tutorials, see this great resource: Here are a few: General tutorials for SQL: http://www.w3schools.com/sql/default.asp Documentation for SQLite: http://www.sqlite.org/docs.html Language Specifications for SQLite: http://theopensourcery.com/sqlitedocs.htm

MySQL

Coming soon

TCP and UDP Connections

TCP or UDP connections can be used to communicate directly with another application or server. More detail will follow. Coming soon

Personal tools
Namespaces
Variants
Actions
Navigation
Lua Scripting
Functions
Hooks
Toolbox