From 9d43c1c90e47aa66e2022ebb3f35503aa35dfd3f Mon Sep 17 00:00:00 2001 From: Novatux Date: Sun, 25 Jan 2015 10:24:10 +0100 Subject: [PATCH] Huge update (again) --- api.lua | 178 +++++++---------------- computer_memory.lua | 4 +- cptr.lua | 16 +- db.lua | 21 +++ forth.fth | 1 - init.lua | 12 +- screen.lua | 60 ++++++++ t2.lua | 347 ++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 496 insertions(+), 143 deletions(-) create mode 100644 db.lua create mode 100644 screen.lua create mode 100644 t2.lua diff --git a/api.lua b/api.lua index 1027b5c..1b189cd 100644 --- a/api.lua +++ b/api.lua @@ -1,128 +1,78 @@ -local FUEL_EFFICIENCY = 3 -- How many moves can the turtle do with a second of fuel - +local MOVE_COST = 100 +local FUEL_EFFICIENCY = 300 tl = {} -local function getv(dir) - if dir==0 then return {x=0,y=0,z=1} - elseif dir==1 then return {x=1,y=0,z=0} - elseif dir==2 then return {x=0,y=0,z=-1} - elseif dir==3 then return {x=-1,y=0,z=0} end -end -local function turtle_can_go(nname) - return nname == "air" or minetest.registered_nodes[nname].liquidtype ~= "none" +local function tl_move(turtle, cptr, dir) + local info = turtles.get_turtle_info(turtle) + if info.energy < MOVE_COST then + cptr.X = 0 + return + end + local spos = info.spos + local npos = vector.add(spos, dir) + if minetest.get_node(npos).name == "air" then + minetest.set_node(npos, {name = "turtle:turtle2"}) + info.npos = npos + info.moving = true + info.energy = info.energy - MOVE_COST + cptr.X = u16(-1) + cptr.paused = true + else + cptr.X = 0 + end end function tl.forward(turtle, cptr) - local info = get_turtle_info(turtle) - if info.fuel == 0 then - cptr.X = 0 - return - end - local spos = info.spos - local dir = info.dir - local npos = vector.add(spos, getv(dir)) - if turtle_can_go(minetest.get_node(npos).name) then - info.npos = npos - info.moving = true - info.fuel = info.fuel - 1 - cptr.X = u16(-1) - cptr.paused = true - else - cptr.X = 0 - end + local dir = turtles.get_turtle_info(turtle).dir + tl_move(turtle, cptr, minetest.facedir_to_dir(dir)) end function tl.backward(turtle, cptr) - local info = get_turtle_info(turtle) - if info.fuel == 0 then - cptr.X = 0 - return - end - local spos = info.spos - local dir = info.dir - local npos = vector.add(spos, getv((dir+2)%4)) - if turtle_can_go(minetest.get_node(npos).name) then - info.npos = npos - info.moving = true - info.fuel = info.fuel - 1 - cptr.X = u16(-1) - cptr.paused = true - else - cptr.X = 0 - end + local dir = turtles.get_turtle_info(turtle).dir + tl_move(turtle, cptr, vector.multiply(minetest.facedir_to_dir(dir), -1)) end function tl.up(turtle, cptr) - local info = get_turtle_info(turtle) - if info.fuel == 0 then - cptr.X = 0 - return - end - local spos = info.spos - local npos = vector.add(spos, {x=0, y=1, z=0}) - if turtle_can_go(minetest.get_node(npos).name) then - info.npos = npos - info.moving = true - info.fuel = info.fuel - 1 - cptr.X = u16(-1) - cptr.paused = true - else - cptr.X = 0 - end + tl_move(turtle, cptr, {x = 0, y = 1, z = 0}) end function tl.down(turtle, cptr) - local info = get_turtle_info(turtle) - if info.fuel == 0 then - cptr.X = 0 - return - end - local spos = info.spos - local npos = vector.add(spos, {x=0, y=-1, z=0}) - if turtle_can_go(minetest.get_node(npos).name) then - info.npos = npos - info.moving = true - info.fuel = info.fuel - 1 - cptr.X = u16(-1) - cptr.paused = true - else - cptr.X = 0 - end + tl_move(turtle, cptr, {x = 0, y = -1, z = 0}) end function tl.turnleft(turtle, cptr) - local info = get_turtle_info(turtle) - info.ndir = (info.dir+3)%4 - info.rotate = math.pi/2 + local info = turtles.get_turtle_info(turtle) + info.ndir = (info.dir + 3) % 4 + info.rotate = math.pi / 2 info.moving = true cptr.paused = true end function tl.turnright(turtle, cptr) - local info = get_turtle_info(turtle) - info.ndir = (info.dir+1)%4 - info.rotate = -math.pi/2 + local info = turtles.get_turtle_info(turtle) + info.ndir = (info.dir + 1) % 4 + info.rotate = - math.pi / 2 info.moving = true cptr.paused = true end local function write_string_at(cptr, addr, str) - for i=1, string.len(str) do - cptr[u16(addr-1+i)] = string.byte(str, i) + for i = 1, string.len(str) do + cptr[u16(addr - 1 + i)] = string.byte(str, i) end cptr.X = string.len(str) end local function turtle_detect(turtle, cptr, dir) - local info = get_turtle_info(turtle) + local info = turtles.get_turtle_info(turtle) local pos = vector.add(info.spos, dir) local name = minetest.get_node(pos).name write_string_at(cptr, cptr.X, name) end function tl.detect(turtle, cptr) - local info = get_turtle_info(turtle) - turtle_detect(turtle, cptr, getv(info.dir)) + local info = turtles.get_turtle_info(turtle) + turtle_detect(turtle, cptr, minetest.facedir_to_dir(info.dir)) end function tl.detectup(turtle, cptr) @@ -134,27 +84,12 @@ function tl.detectdown(turtle, cptr) end local function turtle_dig(turtle, cptr, dir) - local info = get_turtle_info(turtle) - local dpos = vector.add(info.spos, dir) - local dnode = minetest.get_node(dpos) - if turtle_can_go(dnode.name) or dnode.name == "ignore" then - cptr.X = 0 - return - end - local drops = minetest.get_node_drops(dnode.name, "default:pick_mese") - local _, dropped_item - for _, dropped_item in ipairs(drops) do - local leftover = turtle_invs:add_item(turtle,dropped_item) - minetest.add_item(info.spos,leftover) - end - minetest.remove_node(dpos) - cptr.X = u16(-1) - cptr.paused = true + -- TODO end function tl.dig(turtle, cptr) - local info = get_turtle_info(turtle) - turtle_dig(turtle, cptr, getv(info.dir)) + local info = turtles.get_turtle_info(turtle) + turtle_dig(turtle, cptr, minetest.facedir_to_dir(info.dir)) end function tl.digup(turtle, cptr) @@ -166,28 +101,12 @@ function tl.digdown(turtle, cptr) end local function turtle_place(turtle, cptr, dir, slot) - local info = get_turtle_info(turtle) - local ppos = vector.add(info.spos, dir) - local dnode = minetest.get_node(ppos) - if (not turtle_can_go(dnode.name)) or dnode.name == "ignore" then - cptr.X = 0 - return - end - local stack = turtle_invs:get_stack(turtle, slot) - if stack:is_empty() or minetest.registered_nodes[stack:get_name()] == nil then - cptr.X = 0 - return - end - minetest.set_node(ppos, {name=stack:get_name()}) - stack:take_item() - turtle_invs:set_stack(turtle, slot, stack) - cptr.X = u16(-1) - cptr.paused = true + -- TODO end function tl.place(turtle, cptr, slot) - local info = get_turtle_info(turtle) - turtle_place(turtle, cptr, getv(info.dir), slot) + local info = turtles.get_turtle_info(turtle) + turtle_place(turtle, cptr, minetest.facedir_to_dir(info.dir), slot) end function tl.placeup(turtle, cptr, slot) @@ -200,13 +119,16 @@ end local function stack_set_count(stack, count) stack = stack:to_table() - if stack==nil then return nil end - stack.count=count + if stack == nil then return nil end + stack.count = count return ItemStack(stack) end function tl.refuel(turtle, cptr, slot, nmax) - local info = get_turtle_info(turtle) + -- TODO: update that + local info = turtles.get_turtle_info(turtle) + info.energy = info.energy + 100 * MOVE_COST + --[[local info = get_turtle_info(turtle) local stack = turtle_invs:get_stack(turtle, slot) local fuel, afterfuel = minetest.get_craft_result({method = "fuel", width = 1, items = {stack}}) if fuel.time <= 0 then @@ -235,5 +157,5 @@ function tl.refuel(turtle, cptr, slot, nmax) turtle_invs:set_stack(turtle, slot, stack) end info.fuel = info.fuel+FUEL_EFFICIENCY*count*fuel.time - cptr.X = u16(FUEL_EFFICIENCY*count*fuel.time) + cptr.X = u16(FUEL_EFFICIENCY*count*fuel.time)]] end diff --git a/computer_memory.lua b/computer_memory.lua index 218702a..7234888 100644 --- a/computer_memory.lua +++ b/computer_memory.lua @@ -1,6 +1,6 @@ function create_cptr_memory() - tbl = {} - for i=0, 65535 do tbl[i] = 0 end + local tbl = {} + for i = 0, 65535 do tbl[i] = 0 end tbl[0xff00] = 0x4d tbl[0xff01] = 0x2a tbl[0xff02] = 0xff diff --git a/cptr.lua b/cptr.lua index 17bac03..c8e8438 100644 --- a/cptr.lua +++ b/cptr.lua @@ -10,8 +10,8 @@ local function file_exists(name) return false end -function loadpkg(na) - local modpath = minetest.get_modpath("forth_computer") +local function loadpkg(na) + local modpath = minetest.get_modpath("turtle") local ol = package.cpath local sp if file_exists(modpath.."/INIT.LUA") then @@ -21,7 +21,7 @@ function loadpkg(na) else sp = {modpath.."/?.so.32", modpath.."/?.so.64"} end - for i=1,#sp do + for i=1, #sp do package.cpath = sp[i] e, lib = pcall(require, na) package.cpath = ol @@ -157,13 +157,13 @@ dofile(modpath.."/api.lua") function run_computer(turtle, cptr) if cptr.stopped then return end - cptr.cycles = math.max(MAX_CYCLES,cptr.cycles+CYCLES_PER_STEP) - while 1 do + cptr.cycles = math.max(MAX_CYCLES, cptr.cycles + CYCLES_PER_STEP) + while true do instr = cptr[cptr.PC] local f = ITABLE[instr] if f == nil then return end - cptr.PC = bit32.band(cptr.PC+1, 0xffff) - setfenv(f, {cptr = cptr, turtle=turtle, receive=receive, delete_message=delete_message, set_channel=set_channel, send_message=send_message, u16=u16, u32=u32, s16=s16, s32=s32, read=read, write=write, readC=readC, writeC=writeC, push=push, pop=pop, rpush=rpush, rpop=rpop, bit32=bit32, math=math, tl=tl}) + cptr.PC = u16(cptr.PC + 1) + setfenv(f, {cptr = cptr, turtle = turtle, receive = receive, delete_message = delete_message, set_channel = set_channel, send_message = send_message, u16 = u16, u32 = u32, s16 = s16, s32 = s32, read = read, write = write, readC = readC, writeC = writeC, push = push, pop = pop, rpush = rpush, rpop = rpop, bit32 = bit32, math = math, tl = tl}) f() cptr.cycles = cptr.cycles - 1 if cptr.paused or cptr.cycles <= 0 then @@ -315,7 +315,7 @@ for i, v in pairs(ITABLE_RAW) do end function on_computer_digiline_receive(turtle, channel, msg) - local info = get_turtle_info(turtle) + local info = turtles.get_turtle_info(turtle) local cptr = info.cptr cptr.digiline_events[channel] = msg end diff --git a/db.lua b/db.lua new file mode 100644 index 0000000..f5c8d5b --- /dev/null +++ b/db.lua @@ -0,0 +1,21 @@ +db = {} + +local worldpath = minetest.get_worldpath() .. "/" +function db.read_file(filename) + local file = io.open(worldpath .. filename, "r") + if file == nil then + return {} + end + local contents = file:read("*all") + file:close() + if contents == "" or contents == nil then + return {} + end + return minetest.deserialize(contents) +end + +function db.write_file(filename, data) + local file = io.open(worldpath .. filename, "w") + file:write(minetest.serialize(data)) + file:close() +end diff --git a/forth.fth b/forth.fth index cd8956f..85bf035 100644 --- a/forth.fth +++ b/forth.fth @@ -165,7 +165,6 @@ FORTH : HEX 16 BASE ! ; : DECIMAL 10 BASE ! ; : TUCK SWAP OVER ; -: NIP SWAP DROP ; : ABS DUP 0< IF NEGATE THEN ; : (marker) LATEST ! (here) ! ; : TYPE DUP 0> IF OVER + SWAP ?DO I C@ EMIT LOOP ELSE 2DROP THEN ; diff --git a/init.lua b/init.lua index 6a8d569..cfd35ae 100644 --- a/init.lua +++ b/init.lua @@ -1,6 +1,10 @@ +turtles = {} + local modpath = minetest.get_modpath("turtle") --dofile(modpath.."/turtle.lua") -dofile(modpath.."/computer_memory.lua") -dofile(modpath.."/forth_floppy.lua") -dofile(modpath.."/cptr.lua") -dofile(modpath.."/t.lua") +dofile(modpath .. "/db.lua") +dofile(modpath .. "/computer_memory.lua") +dofile(modpath .. "/forth_floppy.lua") +dofile(modpath .. "/cptr.lua") +dofile(modpath .. "/screen.lua") +dofile(modpath .. "/t2.lua") diff --git a/screen.lua b/screen.lua new file mode 100644 index 0000000..ed861f6 --- /dev/null +++ b/screen.lua @@ -0,0 +1,60 @@ +screen = {} + +local MAX_LINE_LENGTH = 28 +local function lines(str) + local t = {} + local function helper(line) table.insert(t, line) return "" end + helper((str:gsub("(.-)\r?\n", helper))) + return t +end + +local function newline(text, toadd) + local f = lines(text) + table.insert(f, toadd) + return table.concat(f, "\n", 2) +end + +local function add_char(text, char) + local ls = lines(text) + local ll = ls[#ls] + if char == "\n" or char == "\r" then + return newline(text, "") + elseif string.len(ll) >= MAX_LINE_LENGTH then + return newline(text, char) + else + return text .. char + end +end + +local function escape(text) + -- Remove all \0's in the string, that cannot be done using string.gsub as there can't be \0's in a pattern + text2 = "" + for i=1, string.len(text) do + if string.byte(text, i) ~= 0 then text2 = text2 .. string.sub(text, i, i) end + end + return minetest.formspec_escape(text2) +end + +function screen.new() + return "\n\n\n\n\n\n\n\n\n\n" +end + +function screen.add_text(text, toadd) + for i = 1, string.len(toadd) do + text = add_char(text, string.sub(toadd, i, i)) + end + return text +end + +function screen.create_text_formspec(text, basex, basey) + local f = lines(text) + s = "" + i = basey - 0.25 + for _,x in ipairs(f) do + s = s .. "]label[" .. basex .. "," .. tostring(i) .. ";" .. escape(x) + i = i + 0.3 + end + s = s .. "]field[" .. tostring(basex + 0.3) .. "," .. tostring(i + 0.4) .. ";4.4,1;f;;]" + return s:sub(2, -1) +end + diff --git a/t2.lua b/t2.lua new file mode 100644 index 0000000..973e1f0 --- /dev/null +++ b/t2.lua @@ -0,0 +1,347 @@ +local DEBUG = true + +------------------------- +-- Read data from file -- +------------------------- + +local turtle_infos = db.read_file("turtle_infos") +local floppies = db.read_file("floppies") + +minetest.register_on_shutdown(function() + for id, info in pairs(turtle_infos) do + info.turtle = nil + info.playernames = {} + end + db.write_file("turtle_infos", turtle_infos) + db.write_file("floppies", floppies) +end) + +function turtles.get_turtle_info(turtle_id) + if turtle_infos[turtle_id] == nil then + turtle_infos[turtle_id] = {} + end + return turtle_infos[turtle_id] +end + +function turtles.get_turtle_inventory(turtle_id) + local info = turtles.get_turtle_info(turtle_id) + return minetest.get_meta(info.spos):get_inventory() +end + +function turtles.create_turtle_id() + return #turtle_infos + 1 +end + +function turtles.create_floppy_id() + return #floppies + 1 +end + +function turtles.update_formspec(turtle_id) + local info = turtles.get_turtle_info(turtle_id) + local pos = info.spos + local formspec = "size[9,10]".. + screen.create_text_formspec(info.screen, 0, 0).. + "list[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main;4.8,0;4,4;]".. + "image_button[1,4.6;2.5,1;turtle_execute.png;reboot;]".. + "list[nodemeta:"..pos.x..","..pos.y..","..pos.z..";floppy;0,4.6;1,1;]".. + "list[current_player;main;0.5,6;8,4;]" + if info.formspec ~= formspec then + info.formspec = formspec + info.formspec_changed = true + end +end + +local function on_screen_digiline_receive(turtle, channel, msg) + if channel == "screen" then + local info = turtles.get_turtle_info(turtle) + info.screen = screen.add_text(info.screen, msg) + turtles.update_formspec(turtle) + end +end + +local function handle_floppy_meta(stack) + if stack.metadata == "" or stack.metadata == nil then + local id = turtles.create_floppy_id() + stack.metadata = tostring(id) + floppies[id] = string.rep(string.char(0), 16384) + return floppies[id], true + elseif string.len(stack.metadata) >= 1000 then + local id = turtles.create_floppy_id() + floppies[id] = stack.metadata + stack.metadata = tostring(id) + return floppies[id], true + else + if floppies[tonumber(stack.metadata)] == nil then + floppies[tonumber(stack.metadata)] = string.rep(string.char(0), 16384) + end + return floppies[tonumber(stack.metadata)], false + end +end + +local function set_floppy_contents(name, contents) + floppies[tonumber(name)] = contents +end + +function on_disk_digiline_receive(turtle_id, channel, msg) + if channel == "boot" then + if string.len(msg) ~= 1 and string.len(msg) ~= 65 then return end -- Invalid message, it comes probably from the disk itself + local page = string.byte(msg, 1) + if page == nil then return end + local inv = turtles.get_turtle_inventory(turtle_id) + local stack = inv:get_stack("floppy", 1):to_table() + if stack == nil then return end + if stack.name ~= "turtle:floppy" then return end + local floppy_contents, update = handle_floppy_meta(stack) + if update then + inv:set_stack("floppy", 1, ItemStack(stack)) + end + msg = string.sub(msg, 2, -1) + if string.len(msg) == 0 then -- read + turtle_receptor_send(turtle_id, channel, + string.sub(floppy_contents, page * 64 + 1, page * 64 + 64)) + else -- write + floppy_contents = string.sub(floppy_contents, 1, page * 64) .. + msg .. + string.sub(floppy_contents, page * 64 + 65, -1) + set_floppy_contents(stack.metadata, floppy_contents) + end + end +end + +minetest.register_craftitem("turtle:floppy", { + description = "Floppy disk", + inventory_image = "floppy.png", + stack_max = 1, +}) + +local progs = { + ["Empty"] = string.rep(string.char(0), 16536), + ["Forth Boot Disk"] = create_forth_floppy(), +} + +minetest.register_node("turtle:floppy_programmator",{ + description = "Floppy disk programmator", + tiles = {"floppy_programmator_top.png", "floppy_programmator_bottom.png", "floppy_programmator_right.png", + "floppy_programmator_left.png", "floppy_programmator_back.png", "floppy_programmator_front.png"}, + groups = {cracky = 3}, + sounds = default.node_sound_stone_defaults(), + on_construct = function(pos) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + inv:set_size("floppy", 1) + meta:set_int("selected", 1) + local s = "size[8,5.5;]" .. + "dropdown[0,0;5;pselector;" + for key, _ in pairs(progs) do + s = s .. key .. "," + end + s = string.sub(s, 1, -2) + s = s .. ";1]" .. + "button[5,0;2,1;prog;Program]" .. + "list[current_name;floppy;7,0;1,1;]" .. + "list[current_player;main;0,1.5;8,4;]" + meta:set_string("formspec", s) + end, + can_dig = function(pos, player) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + return inv:is_empty("floppy") + end, + allow_metadata_inventory_put = function(pos, listname, index, stack, player) + if stack:get_name() == "turtle:floppy" then return 1 end + return 0 + end, + on_receive_fields = function(pos, formname, fields, sender) + local meta = minetest.get_meta(pos) + if fields.prog then + local inv = meta:get_inventory() + local prog = progs[fields.pselector] + local stack = inv:get_stack("floppy", 1):to_table() + if stack == nil then return end + if stack.name ~= "turtle:floppy" then return end + local contents, update = handle_floppy_meta(stack) + set_floppy_contents(stack.metadata, prog) + if update then + inv:set_stack("floppy", 1, ItemStack(stack)) + end + end + end, +}) + +function turtle_receptor_send(turtle, channel, msg) + on_screen_digiline_receive(turtle, channel, msg) + on_computer_digiline_receive(turtle, channel, msg) + on_disk_digiline_receive(turtle, channel, msg) + --on_turtle_command_receive(turtle, channel, msg) +end + +minetest.register_on_player_receive_fields(function(player, formname, fields) + if formname:sub(1, 7) ~= "turtle:" then return end + local turtle_id = tonumber(formname:sub(8, -1)) + if fields.f ~= nil and fields.f ~= "" then + if string.len(fields.f) > 80 then + fields.f = string.sub(fields.f, 1, 80) + end + turtle_receptor_send(turtle_id, "screen", fields.f) + turtles.update_formspec(turtle_id) + return + end + if fields.reboot then + local info = turtles.get_turtle_info(turtle_id) + info.cptr = create_cptr() + return + end + if fields.quit then + local info = turtles.get_turtle_info(turtle_id) + info.playernames[player:get_player_name()] = nil + end +end) + +minetest.register_node("turtle:turtle", { + description = "Turtle", + drawtype = "airlike", + inventory_image = "turtle_turtle_inv.png", + sunlight_propagates = true, + walkable = false, + pointable = false, + after_place_node = function(pos) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + inv:set_size("floppy", 1) + inv:set_size("main", 8 * 4) + inv:set_size("craft", 3 * 3) + inv:set_size("craft_output", 1) + local id = turtles.create_turtle_id() + meta:set_int("turtle_id", id) + local info = turtles.get_turtle_info(id) + info.spos = vector.new(pos) + info.dir = 0 + info.energy = 0 + info.screen = screen.new() + info.cptr = create_cptr() + info.playernames = {} + turtles.update_formspec(id) + local le = minetest.add_entity(pos, "turtle:turtle"):get_luaentity() + info.turtle = le + le.turtle_id = id + end, +}) + +minetest.register_node("turtle:turtle2", { + description = "turtle:turtle2 (You hacker you)", + groups = {not_in_creative_inventory = 1}, + drawtype = "airlike", + walkable = false, + pointable = false, +}) + +local function done_move(pos, spos, npos) + return vector.dot(vector.subtract(npos, spos), + vector.subtract(npos, pos)) <= 0 +end + +local function done_rotation(yaw, nyaw, rotate_speed) + return (nyaw - yaw + rotate_speed - math.pi / 2) % (2 * math.pi) < math.pi +end + +minetest.register_entity("turtle:turtle", { + physical = true, + collisionbox = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}, + collides_with_objects = false, + visual = "wielditem", -- TODO: change that to a mesh, and add animations + visual_size = {x = 2/3, y = 2/3}, + textures = {"default:wood"}, + on_activate = function(self, staticdata) + local id = tonumber(staticdata) + if id ~= nil then + self.turtle_id = id + if turtle_infos[self.turtle_id] == nil then + minetest.set_node(vector.round(self.object:getpos()), {name = "air"}) + self.object:remove() + return + end + local info = turtles.get_turtle_info(self.turtle_id) + info.turtle = self + end + end, + on_step = function(self, dtime) + if self.turtle_id == nil then return end + local info = turtles.get_turtle_info(self.turtle_id) + if info.rotate then + self.object:setyaw(self.object:getyaw() + info.rotate * dtime) + end + if info.moving then + if info.npos ~= nil then + local pos = self.object:getpos() + local npos = info.npos + local spos = info.spos + if done_move(pos, spos, npos) then + self.object:setpos(npos) + self.object:setvelocity({x = 0, y = 0, z = 0}) + info.spos = npos + info.npos = nil + info.moving = nil + local meta = minetest.get_meta(spos):to_table() + minetest.set_node(spos, {name = "air"}) + minetest.set_node(npos, {name = "turtle:turtle"}) + minetest.get_meta(npos):from_table(meta) + turtles.update_formspec(self.turtle_id) + else + self.object:setvelocity(vector.subtract(npos, spos)) + end + elseif info.ndir ~= nil then + local yaw = self.object:getyaw() + local rotate_speed = info.rotate + local nyaw = info.ndir * math.pi/2 + if done_rotation(yaw, nyaw, rotate_speed) then + self.object:setyaw(nyaw) + info.dir = info.ndir + info.ndir = nil + info.rotate = nil + info.moving = nil + end + end + end + if not info.moving then + run_computer(self.turtle_id, info.cptr) + end + if info.formspec_changed then + for playername, _ in pairs(info.playernames) do + if DEBUG then + print(info.screen) + print("------------------------------------") + end + minetest.show_formspec(playername, "turtle:" .. tostring(self.turtle_id), info.formspec) + end + info.formspec_changed = nil + end + end, + on_rightclick = function(self, clicker) + local info = turtles.get_turtle_info(self.turtle_id) + local name = clicker:get_player_name() + info.playernames[name] = true + minetest.show_formspec(name, "turtle:" .. tostring(self.turtle_id), info.formspec) + end, + on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir) + self.object:remove() + local info = turtles.get_turtle_info(self.turtle_id) + local pos = info.spos + minetest.add_item(pos, "turtle:turtle") + local inv = minetest.get_meta(pos):get_inventory() + + for list, nslots in pairs({["main"] = 8 * 4, ["floppy"] = 1, ["craft"] = 3 * 3}) do + for slot = 1, nslots do + minetest.add_item(pos, inv:get_stack(list, slot)) + end + end + + if info.npos then + minetest.set_node(info.npos, {name = "air"}) + end + minetest.set_node(pos, {name = "air"}) + turtle_infos[self.turtle_id] = nil + end, + get_staticdata = function(self) + return tostring(self.turtle_id) + end, +})