~fgaz/minetest-extruder

12223b8c40ad9937dfb7be03c3af0025a065ad2a — Francesco Gazzetta 1 year, 3 months ago f248c03
Add extrusion amount setting

* add settings formspec
3 files changed, 61 insertions(+), 13 deletions(-)

M .luacheckrc
M init.lua
M mod.conf
M .luacheckrc => .luacheckrc +3 -0
@@ 6,6 6,8 @@ local used_minetest_fields = {
  register_privilege = {},
  check_player_privs = {},
  chat_send_player = {},
  show_formspec = {},
  register_on_player_receive_fields = {},
}

stds.minetest = {


@@ 19,6 21,7 @@ stds.minetest = {
		to_string = {},
		from_string = {},
		add = {},
        subtract = {},
		direction = {},
	  },
	},

M init.lua => init.lua +57 -12
@@ 58,16 58,25 @@ local function visit(pos, direction)
  return visited
end

local function extrude(surface, direction, remove)
local function extrude(surface, direction, meta, remove)
  local amount = math.max(1, meta:get_int("amount"))

  -- TODO use VoxelManip (and accumulate two of the bounding coordinates in visit()?)
  -- or at least bulk_set_node
  for pos_str,node in pairs(surface) do
    if node then
      local pos = vector.from_string(pos_str)
      if remove then
        minetest.remove_node(pos)
      else
        minetest.set_node(vector.add(pos, direction), node)
      if not remove then pos = vector.add(pos, direction) end
      for _ = 1, amount do
        if remove then
          minetest.remove_node(pos)
          pos = vector.subtract(pos, direction)
        else
          -- MAYBE check that it's air, do not overwrite other nodes
          -- or add a setting
          minetest.set_node(pos, node)
          pos = vector.add(pos, direction)
        end
      end
    end
  end


@@ 83,26 92,62 @@ local function check_privs_with_msg(player_or_name)
  return true
end

local function use(placer, pointed_thing, remove)
local function use(placer, pointed_thing, meta, remove)
  if placer == nil or pointed_thing == nil or pointed_thing.type ~= "node" then return end
  if not check_privs_with_msg(placer) then return end
  local direction = vector.direction(pointed_thing.under, pointed_thing.above)
  local surface = visit(pointed_thing.under, direction)
  -- TODO ask for confirmation if surface is too big (block limit field/checkbox in formspec?)
  -- confirmation can be "click again" (store previous above and under)
  extrude(surface, direction, remove)
  extrude(surface, direction, meta, remove)
end

local settings_formspec = [[
  formspec_version[3]
  size[4,3]
  button_exit[0.5,1.8;3,0.8;confirm;Confirm]
  field[0.5,0.6;3,0.8;amount;Extrusion amount;%d]
]]

minetest.register_tool(modname .. ":extruder", {
  description = "Extruder tool\nClick to extrude a surface, right click to adjust options",
  inventory_image = "extruder.png",
  stack_max = 1,
  liquids_pointable = true,

  on_use = function(_, placer, pointed_thing) use(placer, pointed_thing, true) end,
  on_place = function(_, placer, pointed_thing) use(placer, pointed_thing, false) end,
  on_use = function(itemstack, placer, pointed_thing)
    use(placer, pointed_thing, itemstack:get_meta(), true)
  end,
  on_place = function(itemstack, placer, pointed_thing)
    use(placer, pointed_thing, itemstack:get_meta(), false)
  end,

  -- TODO add formspec with "amount" field and "go/select through vertices" checkbox
  --on_secondary_use = function(itemstack, placer, pointed_thing)
  --end,
  -- TODO add "go/select through vertices" checkbox
  -- TODO add "only extrude/select nodes of the same type"
  on_secondary_use = function(itemstack, placer, _)
    local amount = math.max(1, itemstack:get_meta():get_int("amount"))
    minetest.show_formspec(placer:get_player_name(), modname .. ":settings",
      string.format(settings_formspec, amount)
    )
  end,
})

minetest.register_on_player_receive_fields(function(player, formname, fields)
  if formname ~= (modname .. ":settings") then return end

  local inventory = player:get_inventory()
  local wield_index = player:get_wield_index()
  local itemstack = inventory:get_stack("main", wield_index)
  if (not itemstack) or (itemstack:get_name() ~= (modname .. ":extruder")) then return end

  local amount = tonumber(fields.amount)
  if (not amount) or (amount < 1) then amount = 1 end
  local amount_str = amount == 1 and "" or tostring(amount)
  itemstack:get_meta():set_int("amount", amount)

  itemstack:get_meta():set_string("count_meta", table.concat({
    amount_str,
  }, ""))

  inventory:set_stack("main", wield_index, itemstack)
end)

M mod.conf => mod.conf +1 -1
@@ 2,5 2,5 @@ name = extruder
title = Extruder Tool
description = Adds an extruder tool that can extend continuous surfaces towards the node face that was clicked
depends =
# Formspec v2, get_modpath()
# Formspec v3, get_modpath()
min_minetest_version = 5.2.0