diff --git a/init.lua b/init.lua index 10bdc2c..a42d53f 100644 --- a/init.lua +++ b/init.lua @@ -1,4 +1,3 @@ -local statedir = minetest.get_worldpath() .. '/' .. minetest.get_current_modname() .. "/" local oldprint=print local function print(...) for k,v in ipairs({...}) do @@ -6,56 +5,76 @@ local function print(...) end end print("Test3D loading.") + +local tInstructions = { +"NOP", +"ADD", +"SUB", +} +--[[ +local statedir = minetest.get_worldpath() .. '/' .. minetest.get_current_modname() .. "/" print("State directory: "..statedir) if not digiline then print("Digilines not found.") return +end +]]-- +local function push(pos,val) + local meta = minetest.get_meta(pos) + local sstack = "" + local stack = string.split(meta:get_string("stack"),"\n") + if #stack > 15 then + print("Stack overflow at "..pos.x..","..pos.y..","..pos.z) + table.remove(stack,1) end + stack[#sstack+1] = tostring(val) + for k,v in ipairs(stack) do + sstack = sstack .. v .. "\n" + end +end +local function pop(pos) + local meta = minetest.get_meta(pos) + local sstack = "" + local stack = string.split(meta:get_string("stack"),"\n") + local n = table.remove(stack,#stack) or 0 + stack[#sstack+1] = tostring(val) + for k,v in ipairs(stack) do + sstack = sstack .. v .. "\n" + end + return tonumber(n) +end local function t21_digiline_receive(pos, node, channel, msg) print(pos,node,channel,msg) + meta = minetest.get_meta(pos) + if meta:get_string("state") == "waiting" and meta:get_string("waitingfor") == channel then + push(pos,msg) + end end print("Created T21 digiline function") -print("Loading/creating states") -_G.test3d = {} -_G.test3d.states={} --- states: ---[[ -{ -mem = {4096 ints} -nodes = int -pc = int -} -]]-- -function _G.test3d.save() - local f = io.open(statedir.."/states.txt","wb") - for k,v in pairs(test3d.states) do - f:write(tostring(k).."\n") - local g=io.open(statedir.."/"..tostring(k)) - for l,m in ipairs(test3d.states[k]) do - g:write(tostring(m).."\n") - end - g:close() - end - f:close() +local function t21_set_infotext(pos) + local meta=minetest.get_meta(pos) + local running="false" + if meta:get_int("test3d_running") == 1 then running="true" end + meta:set_string("infotext","Running: "..running.."\nState: "..meta:get_string("state").."\nPC: "..tostring(meta:get_int("pc")).."\nACC: "..tostring(meta:get_int("acc")).."\nBAK: "..tostring(meta:get_int("bak"))) end -_G.test3d.laststate=0 -_G.test3d.genstate = {} -local statetab={} -os.execute("mkdir "..statedir) -- just in case, 50/50 this kills minetest on some platforms -local f=io.open(statedir.."/states.txt","rb") -local statetab={} -if f ~= nil then - f:close() - for l in io.lines(statedir.."/states.txt") do - print("State: "..l) - end -end -print("Creating T21 formspec") + local function t21_set_meta(pos) - minetest.get_meta(pos):set_string("formspec", "field[channel;Channel;${channel}]\nfield[statename;State;${statename}]") + local meta = minetest.get_meta(pos) + local fspec = "size[8,9]\nlabel[0,0;T21 execution node]\nfield[0.25,1;8,1;channel;Channel prefix;${channel}]\n" + fspec = fspec .. "textarea[0.25,2;8,7.5;program;Program;${program}]\n" + fspec = fspec .. "button_exit[0,8.5;7.9,1;;Done]\n" + meta:set_string("formspec",fspec) + meta:set_string("channel","") + meta:set_string("program","#This is the default program.") + meta:set_string("state","running") -- can be "running", or "waiting" + meta:set_string("waitingfor","") -- address waiting for + meta:set_int("pc",0) + meta:set_int("acc",0) + meta:set_int("bak",0) + t21_set_infotext(pos) + print("Initialized T21 at "..tostring(pos.x)..","..tostring(pos.y)..","..tostring(pos.z)) end -minetest.register_on_shutdown(test3d.save) minetest.register_node("test3d:t21", { description = "T21 Execution Node", tiles = { @@ -73,15 +92,15 @@ minetest.register_node("test3d:t21", { on_construct = t21_set_meta, on_punch = function(pos, _, _, _) local meta=minetest.get_meta(pos) - local cbeep = meta:get_int("test3d_running") --- print("cbeep ",cbeep) - local nbeep=1 - if cbeep==1 then - nbeep=0 + local cstate = meta:get_int("test3d_running") + local nstate=1 + if cstate==1 then + nstate=0 else - nbeep=1 + nstate=1 end - meta:set_int("test3d_running",nbeep) + print("State: "..tostring(cstate).." -> "..tostring(nstate)) + meta:set_int("test3d_running",nstate) end, groups = {snappy=1,choppy=2,oddly_breakable_by_hand=2,flammable=3}, digiline = { @@ -91,11 +110,40 @@ minetest.register_node("test3d:t21", { } }, on_receive_fields = function(pos,_,fields,sender) + if fields.channel == nil or fields.program == nil then return end local meta = minetest.get_meta(pos) - _G.test3d.states[meta:get_string("statename")].nodes=_G.test3d.states[meta:get_string("statename")].nodes-1 -- decrement node counter - meta:set_string("statename",fields.statename) - meta:set_string("channel",fields.channel) -- channel the thing listens for commands on - _G.test3d.states[meta:get_string("statename")].nodes=_G.test3d.states[meta:get_string("statename")].nodes+1 -- increment new node counter + fields.channel = fields.channel or "" + meta:set_string("channel",fields.channel) + print("Channel: "..fields.channel) + local tProgram = {} + local lcounter = 0 + for _,line in ipairs(string.split(fields.program,"\n")) do + if lcounter > 14 then break end -- only 15 real lines will be stored + local ltab = string.split(line," ") + local valid=false + if line:sub(1,1) == "#" then valid=true end + if line:sub(#line,#line) == ":" then valid=true end + for _,ins in ipairs(tInstructions) do + if string.upper(ltab[1]) == ins then + valid = true + end + end + if valid then + lcounter = lcounter + 1 + tProgram[#tProgram+1] = line + print("Valid: "..line) + else + print("Invalid: "..line) + end + end + local sProgram = "" + for _,l in ipairs(tProgram) do + sProgram = sProgram .. l .. "\n" + end + sProgram = sProgram:sub(1,-1) + meta:set_string("program",sProgram) + print("Program:\n"..sProgram) + meta:set_int("pc",1) end }) print("T21 node registered") @@ -105,23 +153,33 @@ minetest.register_abm({ interval=1, chance=1, action = function(pos) + function getDigiline(addr) + digiline:receptor_send(pos,digilines.rules.default,addr,"get") + minetest.get_meta(pos):set_string("state","waiting") + minetest.get_meta(pos):set_string("waitingfor",addr) + end local node = minetest.get_node_or_nil(pos) local meta = minetest.get_meta(pos) - local beepState = meta:get_int("test3d_running") - if beepState == nil then beepState=1 end --- print(beepState) - if beepState == 1 and meta:get_string("statename") ~= nil and meta:get_string("statename") ~= "" then ---[[ minetest.sound_play("default_break_glass",{ - pos=pos, - max_hear_distance=100 - }) -]]-- - print("Running T21 node with instance "..tostring(meta:get_string("statename")).." at position "..tostring(pos.x)..","..tostring(pos.y)..","..tostring(pos.z)) + if meta:get_string("state") == "running" then + local state = meta:get_int("test3d_running") + if state == nil then state=1 end + if state == 1 then + local pc = meta:get_int("pc") + local acc = meta:get_int("acc") + local bak = meta:get_int("bak") + print("Running T21 node with instance at position "..tostring(pos.x)..","..tostring(pos.y)..","..tostring(pos.z).." (PC: "..tostring(pc)..", ACC: "..tostring(acc)..", BAK: "..tostring(bak)..")") + local tProgram = string.split(meta:get_string("program"),"\n") + local tLine = string.split(tProgram[pc]:upper()) + if pc == #tProgram then pc = 0 end + meta:set_int("pc",pc+1) + end end + t21_set_infotext(pos) end, }) print("T21 ABMs registered") +--[[ minetest.register_chatcommand("lua", { -- I'm a terrible person params = "", description = "Execute some Lua code", @@ -131,4 +189,4 @@ minetest.register_chatcommand("lua", { -- I'm a terrible person minetest.chat_send_all(tostring(lstr)) end, }) - +]]--