diff --git a/init.lua b/init.lua index 94d7504..762e47d 100644 --- a/init.lua +++ b/init.lua @@ -1,21 +1,5 @@ ---[[ - -Copyright (C) 2016 Aftermoth, Zolan Davis - -This program is free software; you can redistribute it and/or modify it -under the terms of the GNU Lesser General Public License as published -by the Free Software Foundation; either version 2.1 of the License, -or (at your option) version 3 of the License. - -http://www.gnu.org/licenses/lgpl-2.1.html - - ---]] - -- ======== FYI ======== -minetest.register_alias("nudger", "nudger:nudger") - minetest.register_craft({ output = "nudger:nudger", recipe = { @@ -24,6 +8,24 @@ minetest.register_craft({ } }) +nudger = {} +local transforms = {} + +nudger.register_transforms = function(prefix, suffixes, cost, callback) +--[[ + prefix = string. First common part of node names. Longer is better. Can be ''. + suffixes = table of strings. Remainders of node names with prefix removed. Can include ''. + cost = integer. How many rotations worth of tool wear should one transform cost for this group. + callback = function, called with (pos). In case other adjustments are needed after transforming. Can be nil. +--]] + local l, n = string.len(prefix), 0 + for i,j in ipairs(transforms) do + if string.len(j[1]) <= l then break end + n=i + end + table.insert(transforms,n+1,{prefix, suffixes, cost, callback}) +end + -- ======== Chat ======== local menu0 = { @@ -36,23 +38,23 @@ local menu0 = { } local menu1 = { - "Reverse rotations.", - "Store a node's rotation.", - "Equip stored rotation.", + "Reverse directions.", + "Store orientation.", + "Equip orientation.", + "Transform.", "Toggle chat level.", - "Buy nudgiquin for 20% tool wear.", + "Get sixel node for 20% tool wear.", "", - "", - - "Nudge to stored rotation.", +-- submenu + "Nudge to orientation.", "Store ...", } -- ======== Helpers ======== -local function say(msg, plr) - minetest.chat_send_player(plr:get_player_name(), msg) +local function say(msg, plr, sh) + if sh ~= 1 then minetest.chat_send_player(plr and plr:get_player_name() or "singleplayer", msg) end end local function edit_ok(pos, plr) @@ -64,30 +66,32 @@ local function edit_ok(pos, plr) end local function node_ok(pos, plr) - local node = minetest.get_node_or_nil(pos) + local node = minetest.get_node(pos) local ndef = minetest.registered_nodes[node.name] if not ndef or not (ndef.paramtype2 == "facedir") or node.param2 == nil or (ndef.drawtype == "nodebox" and not (ndef.node_box.type == "fixed")) then - say("Target can't be nudged.", plr) + if plr then say("Target can't be nudged.", plr) end return end return node end +local function is_sixel(pos) + return minetest.get_node(pos).name:sub(1,12) == "nudger:sixel" +end local function tool_use(istk, cost, pos) - if not pos or minetest.get_node_or_nil(pos).name ~= "nudger:nudgiquin" then - local wear = tonumber(istk:get_wear()) + 327*cost - if wear > 65535 then istk:clear() + if not pos or not is_sixel(pos) then + local wear = tonumber(istk:get_wear()) + 257*cost + if wear > 65534 then istk:clear() else istk:set_wear(wear) end end - return istk end --- ======== Rotation ======== +-- ======== Actions ======== --- == Choose axis of rotation == +-- Choose axis of rotation local function face(ptd) local a, u = ptd.above.x, ptd.under.x @@ -128,7 +132,7 @@ local function choose_axis(plr, ptd, mode) end --- == Do rotation == +-- == Rotate == local map = { { -- x @@ -151,7 +155,7 @@ local map = { local function rotate(istk, plr, ptd, mode, sgn) local pos = ptd.under local node = node_ok(pos, plr) - if not node then return istk end + if not node then return end local p = (node.param2)%24 local q, r = math.floor(p/4), p%4 local a, s = choose_axis(plr,ptd,mode) @@ -166,143 +170,160 @@ local function rotate(istk, plr, ptd, mode, sgn) end node.param2 = p minetest.swap_node(pos, node) - return tool_use(istk, 1, pos), p + tool_use(istk, 1, pos) + return p end --- == Store / Apply == +-- == Store / Apply Orientation == -local function store(istk, pos, plr) - local node = node_ok(pos, plr) - if not node then return istk end - return tool_use(istk, 4, pos), node.param2 +local function store(istk, pos) + local node = node_ok(pos) + if not node then return 0 end + tool_use(istk, 8, pos) + return node.param2 end local function apply(istk, pos, plr, p2) local node = node_ok(pos, plr) - if not node then return istk end + if not node then return end node.param2 = p2 minetest.swap_node(pos, node) - return tool_use(istk, 1, pos), p2 + tool_use(istk, 1, pos) + return p2 +end + +-- == Transform == + +local function transform(istk,pos,plr) + local node = minetest.get_node(pos) + local name = node.name + for i,j in ipairs(transforms) do + if string.match(name,'^'..j[1]) then + s = string.sub(name, string.len(j[1])+1) + jj = j[2] + for k,t in ipairs(jj) do + if t == s then + node.name=j[1]..jj[k%#jj+1] + minetest.swap_node(pos,node) + if j[4] then j[4](pos) end + tool_use(istk,j[3]) + return + end + end + end + end + say("Target can't transform.",plr) +end + + +-- ======== Sixel ======== + +local function sixel(istk,plr) + if tonumber(istk:get_wear()) > 52428 then + say("Sorry, this nudger is too damaged.",plr) + else + tool_use(istk,51,nil) + local inv = plr:get_inventory() + local stk = inv:add_item("main",ItemStack("nudger:sixel")) + if not stk:is_empty() then + minetest.item_drop(stk,plr,plr:get_pos()) + end + say("Sixel can be nudged without tool damage,",plr) + say(" and reports its param2 with 'More chat.'",plr) + end end -- ======== Interface ======== -local function shop(istk,plr) - if tonumber(istk:get_wear()) > 52428 then - say("Sorry, this nudger is too damaged.",plr) - else - tool_use(istk,40,nil) - local inv = plr:get_inventory() - local stk = inv:add_item("main",ItemStack("nudger:nudgiquin")) - if not stk:is_empty() then - minetest.item_drop(stk,plr,plr:get_pos()) - end - say("Nudgiquin can be nudged without tool damage.",plr) - say("It will also report its param2 with 'More chat.'",plr) - end -end - -local function reset(istk, plr) - say("Shift+click to cycle options.", plr) - say("Right click to switch menus.", plr) - istk:set_name("nudger:nudger0") - return 0 -end - -local function do_on_use(istk, plr, ptd) +local function do_on_use(istk, plr, ptd, rt) local m = tonumber(istk:get_metadata()) - if not m then m = reset(istk, plr) end --- unpack metadata - local p2 = math.floor(m/120) - local sh = math.floor((m%120)/60) - local mm = math.floor((m%60)/6) - local rm = m%6 - local sr, dr = math.floor(rm/3), rm%3 --- menu options - if plr:get_player_control().sneak then - if mm == 0 then - rm = 3*sr + (dr + 1)%3 - elseif mm < 6 then - mm = mm%5 + 1 - elseif mm < 10 then - mm = 17 - mm - end - - if mm == 0 then - if sh==0 then say(menu0[rm + 1], plr) end - istk:set_name("nudger:nudger"..rm) - else - say(menu1[mm], plr) - if mm == 2 or mm == 9 then istk:set_name("nudger:nudger6") - elseif mm == 3 then istk:set_name("nudger:nudger") - elseif mm == 8 then istk:set_name("nudger:nudger7") - end - end --- menu actions - else - local once = true - if mm == 1 then - rm = 3*(1 - sr) + dr - if sh==0 then say("Reversed.", plr) end - elseif mm == 4 then - sh = 1 - sh - say(((sh==0 and "More") or "Less").." chat.", plr) - elseif mm == 5 then - shop(istk,plr) - else - once = false - end - - local pos = (ptd.type == "node" and ptd.under) or false - - local qp2 - if pos and not once then - if mm == 0 then - if edit_ok(pos, plr) then - istk, qp2 = rotate(istk, plr, ptd, dr, 1-2*sr) - end - elseif mm == 2 or mm == 3 or mm == 9 then - if mm == 2 or mm == 9 then - istk, qp2 = store(istk, pos, plr) - if qp2 then p2 = qp2 end - if sh==0 then say("Stored.", plr) end - end - mm = 8 - istk:set_name("nudger:nudger7") - say(menu1[8], plr) - elseif mm == 8 then - if edit_ok(pos, plr) then - istk, qp2 = apply(istk, pos, plr, p2) - end - end - end - if qp2 and sh==0 and minetest.get_node_or_nil(pos).name == "nudger:nudgiquin" then say("nq: "..qp2, plr) end - if once then - mm = 0 - istk:set_name("nudger:nudger"..rm) - end - end - istk:set_metadata(120*p2 + 60*sh + 6*mm + rm) - return istk -end - -local function do_on_place(istk, plr) - local m = tonumber(istk:get_metadata()) - if not m then m = reset(istk, plr) - else - local mh = math.floor(m/60) - local sh = mh%2 + if m then + -- unpack metadata + local p2 = math.floor(m/120) + local sh = math.floor((m%120)/60) local mm = math.floor((m%60)/6) local rm = m%6 - mm = (mm == 0 and 1) or 0 - if mm == 1 then - if sh==0 then say(menu1[1], plr) end - istk:set_name("nudger:nudger") + local sr, dr = math.floor(rm/3), rm%3 + -- Switch menus + if rt then + mm = (mm == 0 and 1) or 0 + if mm == 1 then + say(menu1[1], plr, sh) + istk:set_name("nudger:nudger") + else + istk:set_name("nudger:nudger"..rm) + end + -- Cycle menu options + elseif plr:get_player_control().sneak then + if mm == 0 then + rm = 3*sr + (dr + 1)%3 + elseif mm < 7 then + mm = mm%6 + 1 + elseif mm < 10 then + mm = 17 - mm + end + -- show correct tool + if mm == 0 then + say(menu0[rm + 1], plr, sh) + istk:set_name("nudger:nudger"..rm) + else + say(menu1[mm], plr) + if mm == 3 or mm == 5 then istk:set_name("nudger:nudger") + elseif mm == 2 or mm == 9 then istk:set_name("nudger:nudger6") + elseif mm == 4 then istk:set_name("nudger:nudger8") + elseif mm == 8 then istk:set_name("nudger:nudger7") + end + end + -- Apply menu actions else - istk:set_name("nudger:nudger"..rm) + local once = true + if mm == 1 then + rm = 3*(1 - sr) + dr + say("Reversed.", plr, sh) + elseif mm == 5 then + sh = 1 - sh + say(((sh==0 and "More") or "Less").." chat.", plr) + elseif mm == 6 then + sixel(istk,plr) + else + local pos = ptd.type == "node" and ptd.under + if pos then + if mm == 2 or mm == 3 or mm == 9 then + if mm ~= 3 then + p2 = store(istk, pos) + say(p2.." Stored.", plr, sh) + end + if mm ~= 9 then say(" * storage submenu *", plr, sh) end + mm = 8 + istk:set_name("nudger:nudger7") + say(menu1[8], plr) + elseif edit_ok(pos, plr) then + local qp2 + if mm == 0 then + qp2 = rotate(istk, plr, ptd, dr, 1-2*sr) + elseif mm == 4 then + transform(istk,pos,plr) + elseif mm == 8 then + qp2 = apply(istk, pos, plr, p2) + end + if qp2 and is_sixel(pos) then + say("sixel: "..qp2, plr, sh) + end + end + end + once = false + end + if once then + mm = 0 + istk:set_name("nudger:nudger"..rm) + end end - m = 60*mh + 6*mm + rm + m = 120*p2 + 60*sh + 6*mm + rm + else m = 0 + say("Shift click to cycle menu options.", plr) + say("Right click to switch menus.", plr) + istk:set_name("nudger:nudger0") end istk:set_metadata(m) return istk @@ -311,6 +332,8 @@ end -- ======== Registration ======== +-- * Tools * + minetest.register_tool("nudger:nudger", { description = "Nudger", inventory_image = "nudger.png", @@ -318,11 +341,11 @@ minetest.register_tool("nudger:nudger", { return do_on_use(istk, plr, ptd) end, on_place = function(istk, plr, ptd) - return do_on_place(istk, plr) + return do_on_use(istk, plr, ptd, 1) end, }) -local adj={"+cw","lf","dn","-cw","rt","up","copy","paste"} +local adj={"+cw","lf","dn","-cw","rt","up","store","apply"} for i = 0, 7 do minetest.register_tool("nudger:nudger"..i, { @@ -333,19 +356,60 @@ for i = 0, 7 do on_use = function(istk, plr, ptd) return do_on_use(istk, plr, ptd) end, - on_place = function(istk, plr, ptd) - return do_on_place(istk, plr) - end, + on_place = function(istk, plr, ptd) + return do_on_use(istk, plr, ptd, 1) + end, }) end -minetest.register_node("nudger:nudgiquin", { - - description = "Nudgiquin", - drop = "nudger:nudgiquin", - tiles = {"nq_up.png","nq_dn.png","nq_rt.png","nq_lf.png","nq_fc.png","nq_bk.png"}, +minetest.register_tool("nudger:nudger8", { + description = "Gerund", + inventory_image = "nudger.png^[transform1", + on_use = function(istk, plr, ptd) + return do_on_use(istk, plr, ptd) + end, + on_place = function(istk, plr, ptd) + return do_on_use(istk, plr, ptd, 1) + end, +}) + +-- * Nodes * + +minetest.register_node("nudger:sixel", { + description = "Sixel", + drop = "nudger:sixel", + tiles = {"sixel_tp.png","sixel_bt.png","sixel_rt.png","sixel_lf.png","sixel_ft.png","sixel_bk.png"}, + paramtype = "light", paramtype2 = "facedir", is_ground_content = false, sunlight_propagates = true, groups = {dig_immediate=3}, }) + +minetest.register_node("nudger:sixel_t", { + description = "Sixel t", + drop = "nudger:sixel", + tiles = {"sixel_t2.png","sixel_t2.png","sixel_t1.png","sixel_t3.png","sixel_t1.png","sixel_t3.png",}, + paramtype = "light", + paramtype2 = "facedir", + is_ground_content = false, + sunlight_propagates = true, + groups = {dig_immediate=3,not_in_creative_inventory=1}, + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-0.5, -0.5, -0.5, 0.5, -0.3, -0.3}, + {-0.3, -0.3, -0.5, -0.1, 0.5, -0.3}, + {-0.5, -0.3, -0.5, -0.3, -0.1, 0.5}, + }, + }, +}) + +-- * Transforms * + +local function example(pos) + say('Sixel transformed at '..pos.x..','..pos.y..','..pos.z) +end + +nudger.register_transforms('nudger:sixel', {'','_t'}, 0, example)