Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
sanjiv
Citizen
Posts: 85
Joined: Mon Feb 27, 2012 5:11 am

The Burrito wrote: then it saves like this:

Code: Select all

for i,v in ipairs(things) do
love.filesystem.write( filename, "makeThing("..v.x..","..v.y..","..v.a..","..v.d..")\n")
end
This is from memory so it's probably wrong (don't have access to my code right now). I prefer to generate readable files so they're fairly easy to edit by hand if need be. To load rather than parsing the file back into a table it runs like any other lua file. This means I can use this as a way to inject custom code into specific maps and stuff like that.
This is what most closely seems to fit my intent,

but I haven't been using "love.filesystem.write" correctly. A literal example would help. To avoid confusion, might an example be given using the following details?

file to store and load info from
boxList.txt --or should this be a .lua file?

info
listOfBoxes={
{a1,b1,c1,d1},
{a2,b2,c2,d2},
{a3,b3,c3,d3}
}

how info will be used in game
drawBoxes(listOfBoxes) --some function that will draw 3 boxes using the 3 lists in listOfBoxes
updateBoxes(listOfBoxes) --some other funtion might make them move or something

Roland_Yonaba
Inner party member
Posts: 1563
Joined: Tue Jun 21, 2011 6:08 pm
Contact:

sanjiv wrote: but I haven't been using "love.filesystem.write" correctly. A literal example would help. To avoid confusion, might an example be given using the following details?
file to store and load info from
boxList.txt --or should this be a .lua file?
info
listOfBoxes={
{a1,b1,c1,d1},
{a2,b2,c2,d2},
{a3,b3,c3,d3}
}
how info will be used in game
drawBoxes(listOfBoxes) --some function that will draw 3 boxes using the 3 lists in listOfBoxes
updateBoxes(listOfBoxes) --some other funtion might make them move or something
Well, love.filesystem.write actually writes contents into a file...But it is done through a protected way. Remember, love.filesystem can access to specific places and only them.
To have it working properly, first set the folder using love.filesystem.setIdentity. You can call this function in love.load callback.

Code: Select all

love.filesystem.setIdentity("MyGame")
This will create a folder named "MyGame" in you user folder. Depending on the OS, that folder will have different pathes:
Windows XP: C:\Documents and Settings\user\Application Data\Love\ or %appdata%\Love\MyGame
Windows Vista and 7: C:\Users\user\AppData\Roaming\LOVE\MyGame or %appdata%\Love\MyGame
Linux: $XDG_DATA_HOME/love/MyGame or ~/.local/share/love/MyGame mac: /Users/user/Library/Application Support/LOVE/MyGame The you can write/read anything inside this folder using love.filesystem.write or love.filesystem.read. Now, concerning data output , i'd rather recommend to tweak a bit TheBurrito's code. Simply iterates using ipairs. Code: Select all local function save(myTable) local str = "{" for k,v in ipairs(myTable) do if type(v)=="table" then str = str..save(v)..',' else str = str..v.."," end end return str.."}" end This assumes that keys in table are alwaysnumeric ... It seems to be the case. Although it would have be simple to use TSerial library. You would have get the same results no matter what the input table was. Using it should be quite simple.File extension doesn't matter, Lua will just execute the piece of code inside. But I'll prefer saving data a way one can load it back using return, instead of setting it as var in the global environment. It is more safe, to me...So Code: Select all  function love.load() love.filesystem.setIdentity("myGame/") --bla bla bla end function love.draw() -- bla bla bla --saving love.filesystem.write('data.txt', 'return '..save(listOfBoxes),'all') ---bla bla bla -- loading back local listOfBoxes = love.filesystem.load('data.txt')() --- bla bla bla end  PS: Ima party member now... Walkin' on the street with my new lafreak bartbes Sex machine Posts: 4946 Joined: Fri Aug 29, 2008 10:35 am Location: The Netherlands Contact: ### Re: Saving and Loading Tables (in text files?) The Burrito wrote: then it saves like this: Code: Select all for i,v in ipairs(things) do love.filesystem.write( filename, "makeThing("..v.x..","..v.y..","..v.a..","..v.d..")\n") end I'd like to note this doesn't work, because love.filesystem.write doesn't append, it replaces, so you'll be overwriting your previous lines with every new one. Use newFile and friends instead. The Burrito Party member Posts: 153 Joined: Mon Sep 21, 2009 12:14 am Contact: ### Re: Saving and Loading Tables (in text files?) bartbes wrote:I'd like to note this doesn't work, because love.filesystem.write doesn't append You're right, should've waited until I could looks at my stuff. Here's some of my actual code: Code: Select all function mapSave(map) mapfile = love.filesystem.newFile(map) mapfile:open('w') for i,v in ipairs(background) do mapfile:write("makeBG('"..v.file.."',"..v.x..","..v.y..","..v.s..")\n") end ... function makeBG(img, x,y, s) local t = {} t.img = love.graphics.newImage(img) t.file = img t.x = x t.y = y t.s = s or 1 table.insert(background, t) end  Where "map" is the file name and then love.filesystem.load to load the created file. The various table to string methods are probably going to be more straight forward, being able to read and edit it by hand really stops being all that useful once everything in your editor actually works. sanjiv Citizen Posts: 85 Joined: Mon Feb 27, 2012 5:11 am ### Re: Saving and Loading Tables (in text files?) Roland_Yonaba wrote: Well, love.filesystem.write actually writes contents into a file...But it is done through a protected way. Remember, love.filesystem can access to specific places and only them. To have it working properly, first set the folder using love.filesystem.setIdentity. You can call this function in love.load callback. Code: Select all love.filesystem.setIdentity("MyGame") This will create a folder named "MyGame" in you user folder. Depending on the OS, that folder will have different pathes: Windows XP: C:\Documents and Settings\user\Application Data\Love\ or %appdata%\Love\MyGame Windows Vista and 7: C:\Users\user\AppData\Roaming\LOVE\MyGame or %appdata%\Love\MyGame Linux:$XDG_DATA_HOME/love/MyGame or ~/.local/share/love/MyGame
mac: /Users/user/Library/Application Support/LOVE/MyGame
The you can write/read anything inside this folder using love.filesystem.write or love.filesystem.read.
The most intuitive thing would be to place this directory in the same place as main.lua, so everything for the game is contained in the same folder. Is that possible, or do too many things break as you move the folder around, or turn it into a .LOVE file?

(speaking as a newb, it'd be really nice if that was the default setting)

sanjiv
Citizen
Posts: 85
Joined: Mon Feb 27, 2012 5:11 am

I'm looking at " love.filesystem.setSource ", but "getSource seems conspicuously missing. It seems like that'd be exactly what I need to find the current location of my game folder with the main.lua in it. I assume there are good reasons why there is no love.filesystem.getSource? Or can I hope for something like that in future iterations of LOVE?

No biggie. If I want the level editor to work for future collaborators, I guess I'll just put everything on the C drive, and get them to do the same.

Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

sanjiv wrote:The most intuitive thing would be to place this directory in the same place as main.lua, so everything for the game is contained in the same folder. Is that possible, or do too many things break as you move the folder around, or turn it into a .LOVE file?
The problem with that is that you might not have the rights to write to that place, so then you would need to be administrator to run your game, which is a very bad idea.

There is no getSource because it makes no sense: the root of the virtual filesystem is the combination of the .love and the write directory..

Bannana97
Citizen
Posts: 77
Joined: Wed May 16, 2012 2:49 pm

I made a nice XML save/load for tables because I am making a game using them and I had to make everything saveable.
It's pretty easy to do, so I encourage you to do the same.

Centauri Soldier
Prole
Posts: 42
Joined: Mon May 21, 2012 6:38 am

Long time coder (of lua, not LOVE) but first this is my first post on the LOVE forums. I hope the forum is as friendly as I've read it is.

Well, I figured for my first post, I'd start with a contribution, so here ya go.

I whipped up a table to string function some time ago that is quite good. It will not convert user data but it will convert everything else. Once you have the string, you can save it to a text file.

Code: Select all

--[[
Code by Centauri Soldier
www.AMSPublic.com
[email protected]

You are free to redistribute this
code and use it wherever and however
remains present and unchanged.

]]

local tEscapeChars = {
[1] = {
Char = "\\",
RelacementChar = "\\\\",
},
[2] = {
Char = "\a",
RelacementChar = "\\a",
},
[3] = {
Char = "\b",
RelacementChar = "\\b",
},
[4] = {
Char = "\f",
RelacementChar = "\\f",
},
[5] = {
Char = "\r\n",
RelacementChar = "\\r\\n",
},
[6] = {
Char = "\t",
RelacementChar = "\\t",
},
[7] = {
Char = "\v",
RelacementChar = "\\v",
},
[8] = {
Char = "\"",
RelacementChar = "\\\"",
},
[9] = {
Char = "\'",
RelacementChar = "\\'",
},
--[[ This version is for use with
pure lua as oppossed to AMS lua.
[10] = {
Char = "%[",
RelacementChar = "%%[",
},
[11] = {
Char = "%]",
RelacementChar = "%%]",
},
]]
[10] = {
Char = "%[",
RelacementChar = "\$", }, [11] = { Char = "%]", RelacementChar = "\$",
},
};

function GetFunctionName(fFunc)

if type(fFunc) == "function" then

for vIndex, vItem in pairs(getfenv(fFunc)) do

if vIndex ~= "_G" then
local sItemType = type(vItem);

if sItemType == "function" then

if vItem == fFunc then
return vIndex
end

elseif sItemType == "table" then

for vIndex2, vItem2 in pairs(vItem)	do
local sItemType2 = type(vItem2);

if sItemType2 == "function" then

if vItem2 == fFunc then
return vIndex.."."..vIndex2
end

elseif sItemType2 == "table" then

for vIndex3, vItem3 in pairs(vItem2) do
local sItemType3 = type(vItem3);

if sItemType3 == "function" then

if vItem3 == fFunc then
return vIndex.."."..vIndex2.."."..vIndex3
end

end

end

end

end

end

end

end

end

return ""
end

--[[
The number(argument #2) tells
the function how many indents
we want from the start. This
is required but can be 0.
]]
function TableToString(tInput, nCount)
local sRet = "";

local sTab = "";

for x = 1, nCount do
sTab = sTab.."\t";
end

local sIndexTab = sTab.."\t";

nCount = nCount + 1;

if type(tInput) == "table" then
sRet = sRet.."{\r\n";

for vIndex, vItem in pairs(tInput) do
local sIndexType = type(vIndex);
local sItemType = type(vItem);
local sIndex = "";

--write the index to string
if sIndexType == "number" then
sRet = sRet..sTab.."["..vIndex.."] = ";

elseif sIndexType == "string" then

if string.find(vIndex, '%W', 1) then
sIndex = sIndexTab.."[\""..vIndex.."\"] = ";
else
sIndex = sIndexTab..vIndex.." = ";
end

end

--write the	item to string
if sItemType == "number" then
sRet = sRet..sIndex..vItem..",\r\n"

elseif sItemType == "string" then

for nIndex, tChar in pairs(tEscapeChars) do
vItem = string.gsub(vItem, tChar.Char, tChar.RelacementChar);
end

sRet = sRet..sIndex.."\""..vItem.."\",\r\n";

elseif sItemType == "boolean" then

if vItem then
sRet = sRet..sIndex.."true,\r\n";
else
sRet = sRet..sIndex.."false,\r\n";
end

elseif sItemType == "nil" then
sRet = sRet..sIndex.."nil,\r\n"

elseif sItemType == "function" then
sRet = sRet..sIndex..GetFunctionName(vItem, getfenv(vItem), "")..",\r\n";

elseif sItemType == "userdata" then
--do the userdata stuff here...

elseif sItemType == "table" then
sRet = sRet..sIndex..TableToString(vItem, nCount)..",\r\n";

end

end

end

sRet = sRet..sTab.."}"

return sRet
end

sanjiv
Citizen
Posts: 85
Joined: Mon Feb 27, 2012 5:11 am