This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Joe3000's profile picture

Saving And Running Functions That Are In A Table.... Inside A Function... Inside A Table?

Started by Joe3000, 24 July 2013 - 12:34 AM
Joe3000 #1
Posted 24 July 2013 - 02:34 AM
So, here is the brief explanation: I want to save the "blocks" that are made in the run program (which are saved to the map program), and then when i open the run program again, it has the same blocks. So this would work when randomly generating new world, and that every time you logged on it wouldnt be a new world… I must admit that I have no idea what i am doing when it comes to saving this table, so any ideas would help :D/> thank you

The run program:

tem = fs.open("temp", "a")
map = fs.open("map", "r")
main = fs.open("main", "r")
tem.write("l,h = term.getSize() \n")
p = 0
length = 0
while true do
line = main.readLine(length)
if line == nil then break end
tem.write(line.. "\n")
if length == 4 then
while true do
line2 = map.readLine(p)
if line2 == nil then break end
tem.write(line2.."\n")
p = p + 1
end
end
length = length + 1
end
shell.run("temp")
tem.close()
map.close()
main.close()

the map program (this is a random one i generated earlier):

blocks = {
table: 68742d
table: 1a3513c
table: 12a55a6
table: 5d4162
table: 6fa0b5
table: a002b1
table: 110bd0b
table: 1eb27fa
table: 18dceab
table: fb6a7b
table: be922
table: 1f6ef9f
table: edd8bc
table: 1304e4e
table: 64e484
table: 1d6c372
table: b99636
table: 34e6e3
table: 1226c45
table: f255c7
table: 1ddbced
table: 9e98ac
table: 3953e8
table: 1b3c442
table: 119dc64
table: d44892
table: e8a10f
table: a6138a
table: 14cfca5
table: 15edf5c
table: 19a43fb
table: e549e7
table: 156e454
table: 1a87fe7
table: 1653029
table: 3ceb07
table: 16a40b2
table: bd66d7
table: aae1f3
table: d82739
table: f71ae6
table: 1071776
table: 95709d
table: 1145cf3
table: 1e25e47
table: 9bb04a
table: 152d5de
table: 1570667
table: 655c0f
table: 7eea52
table: 49e93e
table: 700250
table: 1a81203
table: 136922b
table: 1b647b9
table: 1ee463
table: 243322
table: 9918f3
table: 134fada
table: 1410709
table: 34f715
table: 14987e8
table: 79b7fc
table: 11e0ceb
table: 1e22114
table: e9cef7
table: 12f0f7
table: 189f687
table: 98293e
table: 1bbb315
table: 1ea6729
table: 1ae5f1
table: 1ee3c8d
}


and finally, the main program:

running = true
timer = os.startTimer(.01)
max = l
min = 1
map = fs.open("map", "w")
function spawnBlock(p1, p2)
block = {
xpos = p1;
ypos = p2;
real = true;
made = true;
–col = math.random(100);

update = function(self)
if self.real == true and self.made == true then
if self.xpos >= min or self.xpos <= max then
if self.xpos > l/2 then
table.insert(blocks, spawnBlock(self.xpos + 1, self.ypos + math.random(-1, 1)))
elseif self.xpos < l/2 then
table.insert(blocks, spawnBlock(self.xpos - 1, self.ypos + math.random(-1, 1)))
elseif self.xpos == l/2 then
table.insert(blocks, spawnBlock(self.xpos + 1, self.ypos + math.random(-1, 1)))
table.insert(blocks, spawnBlock(self.xpos - 1, self.ypos + math.random(-1, 1)))
end
end
self.made = false
end
end;

draw = function(self)
if self.real == true then
term.setBackgroundColour(colours.white)
term.setCursorPos(self.xpos, self.ypos)
term.write(" ")
end
end;
}
return block
end
function updateGame()
id, p1, p2, p3 = os.pullEvent()
if id == "timer" then
if p1 == timer then
for i = 1, #blocks do
blocks:update()
end
timer = os.startTimer(.01)
end
elseif id == "key" then
if p1 == keys.q then
running = false
end
end
end
function drawGame()
term.setBackgroundColour(colours.black)
term.clear()
for i,v in pairs(blocks) do
v:draw()
end
end
function gameLoop()
while running do
updateGame()
drawGame()
end
term.setCursorPos(1,1)
end
table.insert(blocks, spawnBlock(l/2, h - 5))
gameLoop()
map.write("blocks = {\n")
for i = 1,#blocks do
map.write(tostring(blocks).."\n")
end
map.write("}")
map.close()
fs.delete("temp")
immibis #2
Posted 24 July 2013 - 03:20 AM
"table: XXXXXX" isn't actually a table. Look into textutils.serialize.
Joe3000 #3
Posted 24 July 2013 - 02:14 PM
textutils says I cant serialize a type that is a function, is there any way around this?
LBPHacker #4
Posted 24 July 2013 - 04:30 PM
local serializeFunciton = function(func)
    local dump = string.dump(func)
    local result = ""
    for byte in dump:gmatch(".") do result = result .. "\\" .. tostring(string.byte(byte)) end
    return result
end

local unserializeFunction = function(str, name)
    local dump = loadstring("return \"" .. str .. "\"")()
    return loadstring(dump, name or "unserialized")
end
Be aware that if the unserialized function contains an error, the line number in the error message will be -1.
PixelToast #5
Posted 24 July 2013 - 04:42 PM
i have my own advanced serialization / unserialization functions:
Spoiler

function serializeImpl(t,TF) -- converts anything into a string
local sType = type(t)
if sType == "table" then
  local result = "{"
  local aset=1
  local comma=false
  for k,v in pairs(t) do
   comma=true
   if k==aset then
	result = result..serializeImpl(v,TF)..","
	aset=aset+1
   else
	local tmp=serializeImpl(k,TF)
	local tmp2=serializeImpl(v,TF)
	if type(k)=="string" then
	 if pcall(loadstring,"{"..k.."="..tmp2.."}") and not string.find(k,",") then
	  result=result..k.."="..tmp2..","
	 else
	  result=result.."["..tmp.."]="..tmp2..","
	 end
	else
	 result=result.."["..tmp.."]="..tmp2..","
	end
   end
  end
  if comma then
   result=string.sub(result,1,-2)
  end
  result = result.."}"
  return result
elseif sType == "string" then
  return string.gsub(string.format("%q",t),"\\\n","\\n") -- improved from textutils
elseif sType == "number" or sType == "boolean" or sType == "nil" then
  return tostring(t)
elseif sType == "function" and not TF then -- function i added
  local status,data=pcall(string.dump,t) -- convert the function into a string
  if status then
   return 'func('..string.format("%q",data)..')' -- format it so it dosent screw up syntax
  else
   error()
  end
elseif sType == "function" and TF then
  return tostring(t)
else
  error()
end
end

function split(T,func) -- splits a table
if func then
  T=func(T) -- advanced function
end
local Out={}
if type(T)=="table" then
  for k,v in pairs(T) do
   Out[split(k)]=split(v) -- set the values for the new table
  end
else
  Out=T
end
return Out
end
function serialize(t,TF) -- TODO: combine with serializeImpl
t=split(t)
return serializeImpl(t,TF)
end

function unserialize(s,tf) -- converts a string back into its original form
if type(s)~="string" then
  error("String exepcted. got "..type(s),2)
end
local func, e = loadstring( "return "..s, "serialize" )
local funcs={} -- a table to store all the functions generated by f() (for securety)
if not func then
  error("Invalid string.")
end
setfenv( func, { -- make sure nothing can be called within the function
  func=function(S) -- puts function requests into the funcs table
   local new={}
   funcs[new]=S
   return new
  end,
})
return split(func(),function(val) -- apply functions if any
  if funcs[val] then
   return loadstring(funcs[val])
  else
   return val
  end
end)
end
i can make it non recursive if you want :P/>
Joe3000 #6
Posted 24 July 2013 - 05:00 PM
Oh, god… I might be getting in over me head here…. I have no idea what any of what both you guys wrote is or how it works XD im sorry