cartographer/table.lua

1033 lines
32 KiB
Lua
Raw Permalink Normal View History

2020-06-13 08:54:13 -04:00
-- Arguments
-- gui: The GUI API
-- gui_skin: The GUI skin
-- audio: The audio playback API
-- maps: The map API
-- materials: The material API
-- map_item: The map item API
2020-06-13 16:21:34 -04:00
-- settings: The mod settings
local gui, gui_skin, audio, maps, materials, map_item, settings = ...
local SCALE_SMALL = 1
local SCALE_MEDIUM = 2
local SCALE_LARGE = 4
local SCALE_HUGE = 8
-- Get the material cost for the given map scale and detail level
2020-06-13 08:54:13 -04:00
--
-- scale: The map scale
-- detail: The detail level
2020-06-13 08:54:13 -04:00
--
-- Returns a table with material costs
local function get_material_cost(scale, detail)
local paper = scale * 4
local pigment = detail * 5
2020-02-16 12:55:07 -05:00
if scale == SCALE_SMALL then
pigment = pigment + 5
elseif scale == SCALE_MEDIUM then
pigment = pigment + 10
elseif scale == SCALE_LARGE then
pigment = pigment + 15
elseif scale == SCALE_HUGE then
pigment = pigment + 20
2020-02-16 12:55:07 -05:00
end
return {
2020-03-07 10:26:24 -05:00
paper = math.max(paper, 0),
2020-02-16 12:55:07 -05:00
pigment = math.max(pigment, 0),
}
2020-02-16 12:55:07 -05:00
end
-- Get the material cost of the craft settings from the given table metadata
2020-06-13 08:54:13 -04:00
--
-- meta: The metadata to read
--
-- Returns a table with the material costs, and a boolean indicating if the
-- costs were positive or negative before clamping.
local function get_craft_material_cost(meta)
local cost = get_material_cost(meta:get_int("scale") or SCALE_SMALL, meta:get_int("detail") or 0)
local stack = meta:get_inventory():get_stack("output", 1)
local is_positive = true
2020-02-16 12:55:07 -05:00
if stack:get_name() == "cartographer:map" then
local smeta = stack:get_meta()
2020-06-07 18:09:58 -04:00
local sub_cost = get_material_cost(smeta:get_int("cartographer:scale") or SCALE_SMALL,
(smeta:get_int("cartographer:detail") or 1) - 1)
is_positive = cost.paper >= sub_cost.paper and cost.pigment >= sub_cost.pigment
cost.paper = math.max(cost.paper - sub_cost.paper, 0)
cost.pigment = math.max(cost.pigment - sub_cost.pigment, 0)
2020-02-16 12:55:07 -05:00
end
return cost, is_positive
end
-- Check if the given table metadata has enough materials to cover the given
-- cost table.
2020-06-13 08:54:13 -04:00
--
-- cost: A table of material costs
-- meta: The metadata
--
-- Returns true if the table's materials can cover the cost
local function can_afford(cost, meta)
return cost.paper + cost.pigment > 0
and cost.paper <= meta:get_int("paper")
and cost.pigment <= meta:get_int("pigment")
2020-02-16 12:55:07 -05:00
end
-- Get the material cost of the copy settings from the given table metadata
2020-06-13 08:54:13 -04:00
--
-- meta: The metadata to read
--
-- Returns a table with the material costs
local function get_copy_material_cost(meta)
local inv = meta:get_inventory()
local in_stack = inv:get_stack("copy_input", 1)
local out_stack = inv:get_stack("copy_output", 1)
if out_stack:is_empty() and in_stack:get_name() == "cartographer:map" then
local smeta = in_stack:get_meta()
local scale = smeta:get_int("cartographer:scale") or SCALE_SMALL
local detail = smeta:get_int("cartographer:detail") or 1
return get_material_cost(scale, detail - 1)
end
return {
paper = 0,
pigment = 0,
}
end
local fs = {}
2020-02-16 12:55:07 -05:00
-- Draw a 1px thick horizontal separator formspec element
2020-06-13 08:54:13 -04:00
--
-- y: The y position of the separator
-- width: The wisth of the separator
-- skin: A 9-slice background skin table
--
-- Returns a formspec string
function fs.separator(y, width, skin)
2020-06-07 18:09:58 -04:00
return gui.bg9 {
x = 0,
2020-06-07 18:09:58 -04:00
y = y,
w = width,
2020-06-07 18:09:58 -04:00
h = 0.01,
skin = skin,
}
2020-02-16 12:55:07 -05:00
end
-- Draw all the essential formspec data (size, background, styles, tabs)
2020-06-13 08:54:13 -04:00
--
-- w: The width of the formspec
-- h: The height of the formspec
-- rank: An into defining the 'rank' of the table being displayed
-- tab: An int defining the index of the selected tab
-- skin: A formspec skin table
--
-- Returns a formspec string
function fs.header(w, h, rank, tab, skin)
local tabs_x = skin.background.margin_x + skin.inner_background.margin_x
local tabs_y = skin.background.margin_y - skin.tab.height
2020-06-07 18:09:58 -04:00
local data = {
gui.formspec {
w = w,
h = h,
bg = skin.background,
},
gui.bg9 {
x = skin.background.margin_x,
y = skin.background.margin_y,
2020-06-07 18:09:58 -04:00
w = w - skin.background.margin_x * 2,
h = h - skin.background.margin_y * 2,
2020-06-07 18:09:58 -04:00
skin = skin.inner_background,
},
gui.style_type {
selector = "button",
properties = {
noclip = true,
border = false,
bgimg = skin.tab.texture .. ".png",
bgimg_hovered = skin.tab.hovered_texture .. ".png",
bgimg_pressed = skin.tab.pressed_texture .. ".png",
bgimg_middle = skin.tab.radius,
padding = skin.tab.padding or -skin.tab.radius,
2020-06-07 18:09:58 -04:00
textcolor = skin.tab.font_color,
}
},
gui.style {
selector = "tab" .. tostring(tab),
properties = {
bgimg = skin.tab.selected_texture .. ".png",
bgimg_hovered = skin.tab.selected_texture .. ".png",
bgimg_pressed = skin.tab.selected_texture .. ".png",
}
},
gui.button {
x = tabs_x,
y = tabs_y,
2020-06-07 18:09:58 -04:00
w = skin.tab.width,
h = skin.tab.height,
2020-06-07 18:09:58 -04:00
id = "tab1",
text = "Materials"
},
gui.button {
x = tabs_x + skin.tab.width,
y = tabs_y,
2020-06-07 18:09:58 -04:00
w = skin.tab.width,
h = skin.tab.height,
2020-06-07 18:09:58 -04:00
id = "tab2",
text = "Create Map"
},
}
if rank >= 2 then
2020-06-07 18:09:58 -04:00
table.insert(data, gui.button {
x = tabs_x + skin.tab.width * 2,
y = tabs_y,
2020-06-07 18:09:58 -04:00
w = skin.tab.width,
h = skin.tab.height,
2020-06-07 18:09:58 -04:00
id = "tab3",
text = "Copy Map"
})
end
2020-02-16 12:55:07 -05:00
2020-06-07 18:09:58 -04:00
table.insert(data, gui.style_type {
selector = "button",
properties = {
bgimg = skin.button.texture .. ".png",
bgimg_hovered = skin.button.hovered_texture .. ".png",
bgimg_pressed = skin.button.pressed_texture .. ".png",
bgimg_middle = skin.button.radius,
padding = skin.button.padding or -skin.button.radius,
2020-06-07 18:09:58 -04:00
textcolor = skin.button.font_color,
},
})
2020-06-07 18:09:58 -04:00
table.insert(data, gui.style {
selector = "disabled_button",
properties = {
bgimg = "",
bgimg_hovered = "",
bgimg_pressed = "",
textcolor = skin.button.disabled_font_color,
},
})
2020-06-07 18:09:58 -04:00
return table.concat(data)
end
2020-02-16 12:55:07 -05:00
-- Draw material counters from a table's metadata
2020-06-13 08:54:13 -04:00
--
-- x: The x position of the labels
-- y: The y position of the labels
-- meta: A metadata object containing the material quantities
-- skin: A formspec skin table
--
-- Returns a formspec string
function fs.materials(x, y, meta, skin)
local indicator_w = skin.material_indicator.width
local indicator_h = skin.material_indicator.height
local indicator_spacing = skin.material_indicator.spacing
local margin_x = skin.label.margin_x
local margin_y = skin.label.margin_y
local inner_h = indicator_h - (margin_y * 2)
2020-06-07 18:09:58 -04:00
return gui.container {
x = x,
y = y,
w = indicator_w,
h = indicator_h,
bg = skin.label,
2020-06-07 18:09:58 -04:00
gui.image {
x = margin_x,
y = margin_y,
2020-06-07 18:09:58 -04:00
w = inner_h,
h = inner_h,
2020-06-07 18:09:58 -04:00
image = skin.paper_texture .. ".png",
},
gui.label {
x = margin_x + inner_h + margin_y, -- y because the previous element uses the inner height
y = margin_y + inner_h * 0.5,
2020-06-07 18:09:58 -04:00
textcolor = skin.label.font_color,
text = string.format("× %d", meta:get_int("paper")),
2020-06-07 18:09:58 -04:00
},
} .. gui.container {
x = x + indicator_w + indicator_spacing,
y = y,
w = indicator_w,
h = indicator_h,
bg = skin.label,
2020-06-07 18:09:58 -04:00
gui.image {
x = margin_x,
y = margin_y,
2020-06-07 18:09:58 -04:00
w = inner_h,
h = inner_h,
2020-06-07 18:09:58 -04:00
image = skin.pigment_texture .. ".png",
},
gui.label {
x = margin_x + inner_h + margin_y, -- See previous label
y = margin_y + inner_h * 0.5,
2020-06-07 18:09:58 -04:00
textcolor = skin.label.font_color,
text = string.format("× %d", meta:get_int("pigment")),
2020-06-07 18:09:58 -04:00
},
}
2020-02-16 12:55:07 -05:00
end
2020-04-03 19:35:59 -04:00
-- Draw a label with material costs from a table
2020-06-13 08:54:13 -04:00
--
2020-04-03 19:35:59 -04:00
-- x: The x position of the interface
-- y: The y position of the interface
2020-04-23 07:13:23 -04:00
-- cost: A table of material costs, with string keys for the material
2020-06-07 18:09:58 -04:00
-- names and integer values
2020-04-03 19:35:59 -04:00
-- skin: A formspec skin table
--
-- Returns a formspec string
2020-04-23 07:13:23 -04:00
function fs.cost(x, y, cost, skin)
local indicator_w = skin.material_indicator.width
local indicator_h = skin.material_indicator.height
local margin_x = skin.label.margin_x
local margin_y = skin.label.margin_y
local inner_h = indicator_h - (margin_y * 2)
2020-06-07 18:09:58 -04:00
local data = {
gui.bg9 {
x = x,
y = y,
w = indicator_w,
h = indicator_h * 2,
2020-04-03 19:35:59 -04:00
2020-06-07 18:09:58 -04:00
skin = skin.label,
},
}
local i = 0
2020-04-23 07:13:23 -04:00
for name,value in pairs(cost) do
local texture = ""
2020-04-23 07:13:23 -04:00
if name == "paper" then
texture = skin.paper_texture .. ".png"
2020-04-23 07:13:23 -04:00
elseif name == "pigment" then
texture = skin.pigment_texture .. ".png"
2020-04-23 07:13:23 -04:00
end
2020-06-07 18:09:58 -04:00
table.insert(data, gui.image {
x = x + margin_x,
y = y + (i * inner_h),
w = inner_h,
h = inner_h,
2020-06-07 18:09:58 -04:00
image = texture,
})
2020-06-07 18:09:58 -04:00
table.insert(data, gui.label {
x = x + margin_x + inner_h,
y = y + ((i + 0.5) * inner_h),
2020-06-07 18:09:58 -04:00
textcolor = skin.label.font_color,
text = string.format("× %d", value),
})
2020-06-07 18:09:58 -04:00
i = i + 1
2020-02-16 12:55:07 -05:00
end
return table.concat(data)
2020-02-16 12:55:07 -05:00
end
-- Draw the material conversion tab UI
2020-06-13 08:54:13 -04:00
--
-- x: The x position of the interface
-- y: The y position of the interface
-- pos: The table position (for displaying the inventory)
-- skin: A formspec skin table
--
-- Returns a formspec string
function fs.convert(x, y, pos, skin)
local meta = minetest.get_meta(pos)
local value = materials.get_stack_value(meta:get_inventory():get_stack("input", 1))
local button_w = skin.button.width
local button_h = skin.button.height
local inv_w = skin.slot.width
local inv_h = skin.slot.height
local indicator_w = skin.material_indicator.width
local indicator_h = skin.material_indicator.height * 2
local indicator_spacing = skin.material_indicator.spacing
2020-06-07 18:09:58 -04:00
return gui.container {
x = x,
y = y,
gui.inventory {
x = 0,
y = 0,
w = inv_w,
h = inv_h,
2020-06-07 18:09:58 -04:00
location = string.format("nodemeta:%d,%d,%d", pos.x, pos.y, pos.z),
id = "input",
bg = skin.slot,
tooltip = "Place items here to convert\nthem into mapmaking materials",
},
fs.cost(inv_w + indicator_spacing, (inv_h - indicator_h) * 0.5, value, skin),
2020-06-07 18:09:58 -04:00
gui.button {
x = inv_w + indicator_w + indicator_spacing * 2,
y = (inv_h - button_h) * 0.5,
w = button_w,
h = button_h,
2020-06-07 18:09:58 -04:00
id = "convert",
text = "Convert Materials",
disabled = value.paper + value.pigment <= 0,
},
}
2020-02-16 12:55:07 -05:00
end
-- Draw the map crafting tab UI
2020-06-13 08:54:13 -04:00
--
-- x: The x position of the interface
-- y: The y position of the interface
-- pos: The table position (for displaying the inventory)
2020-06-13 08:54:13 -04:00
-- rank: The 'rank' of the table
-- meta: A metadata object containing the table settings and material
-- quantities
-- skin: A formspec skin table
--
-- Returns a formspec string
function fs.craft(x, y, pos, rank, meta, skin)
local cost, is_positive = get_craft_material_cost(meta)
local stack = meta:get_inventory():get_stack("output", 1)
local button_w = skin.button.width
local button_h = skin.button.height
local inv_w = skin.slot.width
local inv_h = skin.slot.height
local indicator_w = skin.material_indicator.width
local indicator_h = skin.material_indicator.height * 2
local indicator_spacing = skin.material_indicator.spacing
local radio = skin.radio
2020-06-07 18:09:58 -04:00
local data = {
x = x,
y = y,
gui.container {
2020-06-07 18:09:58 -04:00
x = 0,
y = radio.height + radio.margin_y * 2,
gui.inventory {
x = 0,
y = 0,
w = inv_w,
h = inv_h,
location = string.format("nodemeta:%d,%d,%d", pos.x, pos.y, pos.z),
id = "output",
bg = skin.slot,
tooltip = "Place a map here to upgrade it,\nor leave empty to craft",
},
2020-06-07 18:09:58 -04:00
fs.cost(inv_w + indicator_spacing, (inv_h - indicator_h) * 0.5, cost, skin),
gui.button {
x = inv_w + indicator_w + indicator_spacing * 2,
y = (inv_h - button_h) * 0.5,
w = button_w,
h = button_h,
id = "craft",
text = stack:get_name() == "cartographer:map" and "Upgrade Map" or "Craft Map",
disabled = not (is_positive and can_afford(cost, meta)),
},
2020-06-07 18:09:58 -04:00
},
gui.style {
selector = string.format("%dx,%d", meta:get_int("scale"), meta:get_int("detail") + 1),
properties = {
bgimg = skin.button.selected_texture .. ".png",
bgimg_hovered = skin.button.selected_texture .. ".png",
bgimg_pressed = skin.button.selected_texture .. ".png",
},
},
gui.label {
x = 0,
y = 0,
text = "Detail Level",
textcolor = skin.label.font_color,
},
}
2020-06-07 18:09:58 -04:00
table.insert(data, gui.button {
x = 0,
y = radio.margin_y,
w = radio.width,
h = radio.height,
2020-06-07 18:09:58 -04:00
id = "1",
text = "1",
})
2020-06-07 18:09:58 -04:00
table.insert(data, gui.button {
x = radio.width,
y = radio.margin_y,
w = radio.width,
h = radio.height,
2020-06-07 18:09:58 -04:00
id = "2",
text = "2",
})
2020-02-16 12:55:07 -05:00
if rank > 1 then
2020-06-07 18:09:58 -04:00
table.insert(data, gui.button {
x = radio.width * 2,
y = radio.margin_y,
w = radio.width,
h = radio.height,
2020-06-07 18:09:58 -04:00
id = "3",
text = "3",
})
2020-02-16 12:55:07 -05:00
if rank > 2 then
2020-06-07 18:09:58 -04:00
table.insert(data, gui.button {
x = radio.width * 3,
y = radio.margin_y,
w = radio.width,
h = radio.height,
2020-06-07 18:09:58 -04:00
id = "4",
text = "4",
})
2020-02-16 12:55:07 -05:00
end
end
if rank > 1 then
table.insert(data, gui.button {
x = radio.margin_x + radio.width * 4,
y = radio.margin_y,
w = radio.width,
h = radio.height,
id = "1x",
text = "1×",
})
table.insert(data, gui.button {
x = radio.margin_x + radio.width * 5,
y = radio.margin_y,
w = radio.width,
h = radio.height,
id = "2x",
text = "2×",
})
if rank > 2 then
table.insert(data, gui.button {
x = radio.margin_x + radio.width * 6,
y = radio.margin_y,
w = radio.width,
h = radio.height,
id = "4x",
text = "4×",
})
table.insert(data, gui.button {
x = radio.margin_x + radio.width * 7,
y = radio.margin_y,
w = radio.width,
h = radio.height,
id = "8x",
text = "8×",
})
end
end
return gui.container(data)
2020-02-16 12:55:07 -05:00
end
-- Draw the map copying tab UI
2020-06-13 08:54:13 -04:00
--
-- x: The x position of the interface
-- y: The y position of the interface
-- width: The width to fill
-- pos: The table position (for displaying the inventory)
-- skin: A formspec skin table
--
-- Returns a formspec string
function fs.copy(x, y, width, pos, skin)
local meta = minetest.get_meta(pos)
local costs = get_copy_material_cost(meta)
local button_w = skin.button.width
local button_h = skin.button.height
local inv_w = skin.slot.width
local inv_h = skin.slot.height
local indicator_w = skin.material_indicator.width
local indicator_h = skin.material_indicator.height * 2
local indicator_spacing = skin.material_indicator.spacing
2020-06-07 18:09:58 -04:00
return gui.container {
x = x,
y = y,
gui.inventory {
x = 0,
y = 0,
w = inv_h,
h = inv_w,
2020-06-07 18:09:58 -04:00
location = string.format("nodemeta:%d,%d,%d", pos.x, pos.y, pos.z),
id = "copy_input",
bg = skin.slot,
},
gui.inventory {
x = width - inv_w,
2020-06-07 18:09:58 -04:00
y = 0,
w = inv_w,
h = inv_h,
2020-06-07 18:09:58 -04:00
location = string.format("nodemeta:%d,%d,%d", pos.x, pos.y, pos.z),
id = "copy_output",
bg = skin.slot,
},
fs.cost(inv_w + indicator_spacing, (inv_h - indicator_h) * 0.5, costs, skin),
2020-06-07 18:09:58 -04:00
gui.button {
x = inv_w + indicator_w + indicator_spacing * 2,
y = (inv_h - button_h) * 0.5,
w = button_w,
h = button_h,
2020-06-07 18:09:58 -04:00
id = "copy",
text = "Copy Map",
disabled = not can_afford(costs, meta),
},
}
2020-02-16 12:55:07 -05:00
end
-- Draw the player's inventory
2020-06-13 08:54:13 -04:00
--
-- x: The x position of the inventory
-- y: The y position of the inventory
-- skin: A formspec skin table
--
-- Returns a formspec string
function fs.inv(x, y, skin)
2020-06-07 18:09:58 -04:00
return gui.inventory {
x = x,
y = y,
w = gui_skin.player_inv_columns,
h = gui_skin.player_inv_rows,
2020-06-07 18:09:58 -04:00
location = "current_player",
id = "main",
bg = skin.slot,
}
2020-02-16 12:55:07 -05:00
end
local player_tables = {}
2020-02-16 12:55:07 -05:00
-- Show the table formspec to the specified player
-- The player must be recorded in player_tables in order to receive
-- a formspec.
--
-- player: The player's name
local function table_formspec(player)
local data = player_tables[player]
local pos = data.pos
if not pos then
return
end
local meta = minetest.get_meta(pos)
2020-02-16 12:55:07 -05:00
local rank = 1
local skin = gui_skin.table_skins.simple_table
local name = minetest.get_node(pos).name
2020-02-16 12:55:07 -05:00
if name == "cartographer:standard_table" then
rank = 2
skin = gui_skin.table_skins.standard_table
2020-02-16 12:55:07 -05:00
elseif name == "cartographer:advanced_table" then
rank = 3
skin = gui_skin.table_skins.advanced_table
end
local outer_x = skin.background.margin_x
local outer_y = skin.background.margin_y
local inner_x = skin.inner_background.margin_x
local inner_y = skin.inner_background.margin_y
local inv_width = skin.slot.width * gui_skin.player_inv_columns
+ (skin.slot.column_margin * (gui_skin.player_inv_columns - 1))
local inv_height = skin.slot.height * gui_skin.player_inv_rows
+ (skin.slot.row_margin * (gui_skin.player_inv_rows - 1))
local inner_width = inv_width + inner_x * 2
local width = inner_width + outer_x * 2
local sep_height = skin.material_indicator.spacing
local ind_h = skin.material_indicator.height + skin.material_indicator.spacing * 0.5
2020-02-16 12:55:07 -05:00
if data.tab == 1 then
local convert_height = skin.slot.height + sep_height
local form_height = (outer_y * 2) + (inner_y * 2) + convert_height + ind_h + sep_height * 2 + inv_height
2020-06-13 12:24:04 -04:00
minetest.show_formspec(player, "cartographer:table",
fs.header(width, form_height, rank, data.tab, skin) ..
gui.container {
x = outer_x,
y = outer_y + inner_y,
fs.materials(inner_x, 0, meta, skin),
fs.separator(ind_h, inner_width, skin.separator),
fs.convert(inner_x, ind_h + sep_height, pos, skin),
fs.separator(ind_h + sep_height + convert_height, inner_width, skin.separator),
fs.inv(inner_x, ind_h + sep_height * 2 + convert_height, skin),
})
elseif data.tab == 2 then
local radio_height = skin.radio.height
local radio_margin_y = skin.radio.margin_y
local craft_height = radio_height + radio_margin_y * 2 + skin.slot.height + sep_height
local form_height = (outer_y * 2) + (inner_y * 2) + craft_height + ind_h + sep_height * 2 + inv_height
2020-06-13 12:24:04 -04:00
minetest.show_formspec(player, "cartographer:table",
fs.header(width, form_height, rank, data.tab, skin) ..
gui.container {
x = outer_x,
y = outer_y + inner_y,
fs.materials(inner_x, 0, meta, skin),
fs.separator(ind_h, inner_width, skin.separator),
fs.craft(inner_x, ind_h + sep_height, pos, rank, meta, skin),
fs.separator(ind_h + craft_height + sep_height, inner_width, skin.separator),
fs.inv(inner_x, ind_h + craft_height + sep_height * 2, skin),
})
elseif data.tab == 3 then
local copy_height = skin.slot.height + sep_height
local form_height = (outer_y * 2) + (inner_y * 2) + copy_height + ind_h + sep_height * 2 + inv_height
2020-06-13 12:24:04 -04:00
minetest.show_formspec(player, "cartographer:table",
fs.header(width, form_height, rank, data.tab, skin) ..
gui.container {
x = outer_x,
y = outer_y + inner_y,
fs.materials(inner_x, 0, meta, skin),
fs.separator(ind_h, inner_width, skin.separator),
fs.copy(inner_x, ind_h + sep_height, inv_width, pos, skin),
fs.separator(ind_h + copy_height + sep_height, inner_width, skin.separator),
fs.inv(inner_x, ind_h + copy_height + sep_height * 2, skin),
})
2020-02-16 12:55:07 -05:00
end
end
-- Called when a player sends input to the server from a formspec
-- This callback handles player input in the table formspec
2020-06-13 08:54:13 -04:00
--
-- player: The player who sent the input
-- name: The formspec name
-- fields: A table containing the input
2020-02-16 12:55:07 -05:00
minetest.register_on_player_receive_fields(function(player, name, fields)
2020-06-13 12:24:04 -04:00
if name == "cartographer:table" then
local meta = minetest.get_meta(player_tables[player:get_player_name()].pos)
2020-02-16 12:55:07 -05:00
local rank = 1
local node_name = minetest.get_node(player_tables[player:get_player_name()].pos).name
2020-06-13 12:25:54 -04:00
if node_name == "cartographer:standard_table" then
rank = 2
2020-06-13 12:25:54 -04:00
elseif node_name == "cartographer:advanced_table" then
rank = 3
2020-06-13 12:24:04 -04:00
end
if fields["convert"] then
local inv = meta:get_inventory()
local stack = inv:get_stack("input", 1)
2020-02-16 12:55:07 -05:00
local value = materials.get_stack_value(stack)
2020-02-16 12:55:07 -05:00
if value.paper + value.pigment > 0 then
meta:set_int("paper", meta:get_int("paper") + value.paper)
meta:set_int("pigment", meta:get_int("pigment") + value.pigment)
inv:set_stack("input", 1, ItemStack(nil))
end
elseif fields["craft"] then
local size = meta:get_int("size")
local detail = meta:get_int("detail")
local scale = meta:get_int("scale")
local cost, is_positive = get_craft_material_cost(meta)
2020-02-16 12:55:07 -05:00
if is_positive and can_afford(cost, meta) then
meta:set_int("paper", meta:get_int("paper") - cost.paper)
meta:set_int("pigment", meta:get_int("pigment") - cost.pigment)
2020-02-16 12:55:07 -05:00
local inv = meta:get_inventory()
local stack = inv:get_stack("output", 1)
2020-02-16 12:55:07 -05:00
if stack:is_empty() then
inv:set_stack("output", 1, map_item.create(size, 1 + detail, scale))
else
local smeta = stack:get_meta()
smeta:set_int("cartographer:detail", 1 + detail)
map_item.resize(smeta, size)
map_item.rescale(smeta, scale)
2020-02-16 12:55:07 -05:00
local map = maps.get(smeta:get_int("cartographer:map_id"))
if map then
map.detail = 1 + detail
2020-02-16 12:55:07 -05:00
end
inv:set_stack("output", 1, stack)
2020-02-16 12:55:07 -05:00
end
audio.play_feedback("cartographer_write", player)
2020-02-16 12:55:07 -05:00
end
2020-06-13 12:24:04 -04:00
elseif fields["copy"] and rank >= 2 then
local cost = get_copy_material_cost(meta)
if can_afford(cost, meta) then
meta:set_int("paper", meta:get_int("paper") - cost.paper)
meta:set_int("pigment", meta:get_int("pigment") - cost.pigment)
2020-02-16 12:55:07 -05:00
audio.play_feedback("cartographer_write", player)
2020-02-16 12:55:07 -05:00
local inv = meta:get_inventory()
inv:set_stack("copy_output", 1, map_item.copy(inv:get_stack("copy_input", 1)))
2020-02-16 12:55:07 -05:00
end
elseif fields["1"] then
meta:set_int("detail", 0)
elseif fields["2"] then
meta:set_int("detail", 1)
2020-06-13 12:24:04 -04:00
elseif fields["3"] and rank > 1 then
meta:set_int("detail", 2)
2020-06-13 12:24:04 -04:00
elseif fields["4"] and rank > 2 then
meta:set_int("detail", 3)
2020-06-13 12:24:04 -04:00
elseif fields["1x"] and rank > 1 then
meta:set_int("scale", SCALE_SMALL)
2020-06-13 12:24:04 -04:00
elseif fields["2x"] and rank > 1 then
meta:set_int("scale", SCALE_MEDIUM)
2020-06-13 12:24:04 -04:00
elseif fields["4x"] and rank > 2 then
meta:set_int("scale", SCALE_LARGE)
2020-06-13 12:24:04 -04:00
elseif fields["8x"] and rank > 2 then
meta:set_int("scale", SCALE_HUGE)
elseif fields["tab1"] then
player_tables[player:get_player_name()].tab = 1
audio.play_feedback("cartographer_turn_page", player)
elseif fields["tab2"] then
player_tables[player:get_player_name()].tab = 2
audio.play_feedback("cartographer_turn_page", player)
2020-06-13 12:24:04 -04:00
elseif fields["tab3"] and rank >= 2 then
player_tables[player:get_player_name()].tab = 3
audio.play_feedback("cartographer_turn_page", player)
end
if not fields["quit"] then
table_formspec(player:get_player_name())
2020-02-16 12:55:07 -05:00
end
end
end)
2020-02-16 12:55:07 -05:00
-- Called after a table is placed. Sets up the table's inventory and metadata.
2020-06-13 08:54:13 -04:00
--
-- pos: The node's position
local function setup_table_node(pos)
local meta = minetest.get_meta(pos)
meta:get_inventory():set_size("input", 1)
meta:get_inventory():set_size("output", 1)
meta:get_inventory():set_size("copy_input", 1)
meta:get_inventory():set_size("copy_output", 1)
meta:set_int("size", settings.default_size)
meta:set_int("scale", SCALE_SMALL)
meta:set_int("detail", 0)
end
-- Called when the player tries to put an item into one of the table's
-- inventories.
2020-06-13 08:54:13 -04:00
--
-- listname: The name of the inventory the item is being placed in.
-- stack: The itemstack
--
-- Returns 0 if the place is invalid otherwise, returns the number of items
-- that can be placed.
local function table_can_put(_, listname, _, stack, _)
if listname == "copy_output" then
return 0
end
if stack:get_name() ~= "cartographer:map" and (listname == "output" or listname == "copy_input") then
return 0
end
return stack:get_count()
end
-- Called when the player tries to move an item between two of the table's
-- inventories.
2020-06-13 08:54:13 -04:00
--
-- to_list: The name of the inventory the item is being placed in.
-- count: The number of items being moved
--
-- Returns 0 if the move is invalid otherwise, returns the number of items
-- that can be moved.
local function table_can_move(_, _, _, to_list, _, count, _)
if to_list == "copy_output" then
return 0
end
return count
end
-- Called when a change occurs in a table's inventory
2020-06-13 08:54:13 -04:00
--
-- pos: The node's position
-- listname: The name of the changed inventory list
local function table_on_items_changed(pos, listname, _, _, _)
for player, data in pairs(player_tables) do
if vector.equals(pos, data.pos) and (
(data.tab == 1 and listname == "input")
or (data.tab == 2 and listname == "output")
or (data.tab == 3 and listname == "copy_input")) then
table_formspec(player)
end
end
end
2020-06-13 08:54:13 -04:00
-- The table node definitions
2020-02-16 12:55:07 -05:00
minetest.register_node("cartographer:simple_table", {
description = "Shabby Cartographer's Table",
drawtype = "mesh",
mesh = gui_skin.table_skins.simple_table.node_mesh,
tiles = { gui_skin.table_skins.simple_table.node_texture },
2020-02-16 12:55:07 -05:00
paramtype2 = "facedir",
groups = {
choppy = 2,
oddly_breakable_by_hand = 2,
},
2020-03-29 20:34:48 -04:00
selection_box = {
type = "fixed",
fixed = {
{-0.5, -0.5, -0.375, 0.5, 0.6875, 0.375},
},
},
collision_box = {
type = "fixed",
fixed = {
{-0.5, -0.5, -0.375, 0.5, 0.6875, 0.375},
},
},
on_rightclick = function(_, _, player, _, pointed_thing)
player_tables[player:get_player_name()] = {
pos = minetest.get_pointed_thing_position(pointed_thing),
tab = 1,
}
audio.play_feedback("cartographer_open_map", player)
table_formspec(player:get_player_name())
2020-02-16 12:55:07 -05:00
end,
after_place_node = setup_table_node,
allow_metadata_inventory_move = table_can_move,
allow_metadata_inventory_put = table_can_put,
on_metadata_inventory_put = table_on_items_changed,
on_metadata_inventory_take = table_on_items_changed,
})
2020-02-16 12:55:07 -05:00
minetest.register_node("cartographer:standard_table", {
2020-02-25 20:23:09 -05:00
description = "Simple Cartographer's Table",
drawtype = "mesh",
mesh = gui_skin.table_skins.standard_table.node_mesh,
tiles = { gui_skin.table_skins.standard_table.node_texture },
2020-02-25 20:23:09 -05:00
paramtype2 = "facedir",
2020-02-16 12:55:07 -05:00
groups = {
choppy = 2,
oddly_breakable_by_hand = 2,
},
2020-03-29 20:34:48 -04:00
selection_box = {
type = "fixed",
fixed = {
{-0.5, -0.5, -0.375, 0.5, 0.6875, 0.375},
},
},
collision_box = {
type = "fixed",
fixed = {
{-0.5, -0.5, -0.375, 0.5, 0.6875, 0.375},
},
},
on_rightclick = function(_, _, player, _, pointed_thing)
player_tables[player:get_player_name()] = {
pos = minetest.get_pointed_thing_position(pointed_thing),
tab = 1,
}
audio.play_feedback("cartographer_open_map", player)
table_formspec(player:get_player_name())
2020-02-16 12:55:07 -05:00
end,
after_place_node = setup_table_node,
allow_metadata_inventory_move = table_can_move,
allow_metadata_inventory_put = table_can_put,
on_metadata_inventory_put = table_on_items_changed,
on_metadata_inventory_take = table_on_items_changed,
})
2020-02-16 12:55:07 -05:00
minetest.register_node("cartographer:advanced_table", {
description = "Advanced Cartographer's Table",
2020-03-29 20:34:48 -04:00
drawtype = "mesh",
mesh = gui_skin.table_skins.advanced_table.node_mesh,
tiles = { gui_skin.table_skins.advanced_table.node_texture },
paramtype2 = "facedir",
2020-02-16 12:55:07 -05:00
groups = {
choppy = 2,
oddly_breakable_by_hand = 2,
},
2020-03-29 20:34:48 -04:00
selection_box = {
type = "fixed",
fixed = {
{-0.5, -0.5, -0.375, 0.5, 0.6875, 0.375},
},
},
collision_box = {
type = "fixed",
fixed = {
{-0.5, -0.5, -0.375, 0.5, 0.6875, 0.375},
},
},
on_rightclick = function(_, _, player, _, pointed_thing)
player_tables[player:get_player_name()] = {
pos = minetest.get_pointed_thing_position(pointed_thing),
tab = 1,
}
audio.play_feedback("cartographer_open_map", player)
table_formspec(player:get_player_name())
2020-02-16 12:55:07 -05:00
end,
after_place_node = setup_table_node,
allow_metadata_inventory_move = table_can_move,
allow_metadata_inventory_put = table_can_put,
on_metadata_inventory_put = table_on_items_changed,
on_metadata_inventory_take = table_on_items_changed,
})