if not digiline then print("Digilines not found.") return end local oldprint=print local function print(...) for k,v in ipairs({...}) do oldprint("[Test3D:T400] "..tostring(v)) end end print("Test3D loading.") local tInstructions = { "NOP", "ADD", "SUB", "PEEK", "POKE", } 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 t400_digiline_receive(pos, node, channel, msg) print(pos,node,channel,msg) meta = minetest.get_meta(pos) if meta:get_string("waitingfor") == channel then if meta:get_string("state") == "waitingstack" then push(pos,msg) if meta:get_string("state") == "waitingins" then meta:set_int("ci",tonumber(msg)) end end end print("Created T400 digiline function") local function t400_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 local function t400_set_meta(pos) local meta = minetest.get_meta(pos) local fspec = "size[8,9]\nlabel[0,0;T400 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("state","running") -- can be "running", "waitingstack" or "waitingins" meta:set_string("waitingfor","") -- address waiting for meta:set_string("stack","") -- internal stack meta:set_int("ci",0) -- current instruction meta:set_int("pc",0) -- program counter t400_set_infotext(pos) print("Initialized T400 at "..tostring(pos.x)..","..tostring(pos.y)..","..tostring(pos.z)) end minetest.register_node("test3d:t400", { description = "T400 Execution Node", tiles = { { image="t400.png", animation={ type = "vertical_frames", aspect_w=16, aspect_h=16, length=18, length=1.8, }, }, }, on_construct = t400_set_meta, on_punch = function(pos, _, _, _) local meta=minetest.get_meta(pos) local cstate = meta:get_int("test3d_running") local nstate=1 if cstate==1 then nstate=0 else nstate=1 end 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 = { receptor = {}, effector = { action = t400_digiline_receive } }, on_receive_fields = function(pos,_,fields,sender) if fields.channel == nil or fields.program == nil then return end local meta = minetest.get_meta(pos) 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",0) end }) print("T400 node registered") minetest.register_abm({ nodenames={"test3d:t400"}, 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) 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 T400 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 t400_set_infotext(pos) end, }) print("T400 ABMs registered") --[[ minetest.register_chatcommand("lua", { -- I'm a terrible person params = "", description = "Execute some Lua code", privs = {talk = true}, func = function( _ , text) e,lstr = pcall(loadstring(text)) minetest.chat_send_all(tostring(lstr)) end, }) ]]--