462 lines
14 KiB
Lua
462 lines
14 KiB
Lua
local SIZE_SMALL = 20;
|
|
local SIZE_LARGE = 40;
|
|
|
|
local separator = [[
|
|
formspec_version[3]
|
|
box[0.1,%f;10.1,0.01;black]
|
|
]];
|
|
|
|
local function get_material_cost(size, detail)
|
|
local fiber = 0;
|
|
local pigment = 0;
|
|
|
|
if size == SIZE_SMALL then
|
|
fiber = fiber + 20;
|
|
pigment = pigment + 5;
|
|
elseif size == SIZE_LARGE then
|
|
fiber = fiber + 80;
|
|
pigment = pigment + 20;
|
|
end
|
|
|
|
pigment = pigment + (detail * 5);
|
|
|
|
return {
|
|
fiber = math.max(fiber, 0),
|
|
pigment = math.max(pigment, 0),
|
|
};
|
|
end
|
|
|
|
local function get_full_material_cost(meta)
|
|
local cost = get_material_cost(meta:get_int("size") or SIZE_SMALL, meta:get_int("detail") or 0);
|
|
|
|
local stack = meta:get_inventory():get_stack("output", 1);
|
|
if stack:get_name() == "cartographer:map" then
|
|
|
|
local smeta = stack:get_meta();
|
|
|
|
local sub_cost = get_material_cost(smeta:get_int("cartographer:size") or SIZE_SMALL, (smeta:get_int("cartographer:detail") or 1) - 1);
|
|
cost.fiber = math.max(cost.fiber - sub_cost.fiber, 0);
|
|
cost.pigment = math.max(cost.pigment - sub_cost.pigment, 0);
|
|
end
|
|
|
|
return cost;
|
|
end
|
|
|
|
local fs = {};
|
|
|
|
function fs.header(w, h, rank, tab)
|
|
local data = [[
|
|
formspec_version[3]
|
|
size[%f,%f]
|
|
]];
|
|
data = data:format(w, h);
|
|
|
|
if rank < 2 then
|
|
data = data .. "tabheader[0,0;tabs;Materials,Create Map;%d;false;false]";
|
|
data = data:format(tab);
|
|
else
|
|
data = data .. "tabheader[0,0;tabs;Materials,Create Map,Copy Map;%d;false;false]";
|
|
data = data:format(tab);
|
|
end
|
|
|
|
return data;
|
|
end
|
|
|
|
function fs.materials(x, y, rank, meta)
|
|
local fiber = meta:get_int("fiber");
|
|
local pigment = meta:get_int("pigment");
|
|
|
|
local data = [[
|
|
container[%f,%f]
|
|
formspec_version[3]
|
|
label[0,0.25;Fiber x %d]
|
|
label[3,0.25;Pigment x %d]
|
|
]];
|
|
data = data:format(x, y, fiber, pigment);
|
|
|
|
if rank > 1 then
|
|
data = data .. "label[6,0.25;Stuff x %d]";
|
|
data = data:format(0);
|
|
|
|
if rank > 2 then
|
|
data = data .. "label[9,0.25;Things x %d]";
|
|
data = data:format(0);
|
|
end
|
|
end
|
|
|
|
return data .. "container_end[]";
|
|
end
|
|
|
|
function fs.cost(x, y, materials)
|
|
local data = "";
|
|
local i = 0;
|
|
for name,value in pairs(materials) do
|
|
data = data .. "label[" .. tostring(x) .. "," .. tostring(y + (i * 0.25)) .. ";" .. name .. " x " .. tostring(value) .. "]";
|
|
i = i + 1;
|
|
end
|
|
|
|
return data;
|
|
end
|
|
|
|
function fs.convert(x, y, pos)
|
|
local data = [[
|
|
container[%f,%f]
|
|
formspec_version[3]
|
|
list[nodemeta:%d,%d,%d;input;0,0;1,1;]
|
|
button[3.5,0.25;2,0.5;convert;Convert Materials]
|
|
]];
|
|
data = data:format(x, y, pos.x, pos.y, pos.z);
|
|
data = data .. fs.cost(1.25, 0.25, {
|
|
Fiber = 0,
|
|
Pigment = 0,
|
|
}) .. "container_end[]";
|
|
|
|
return data;
|
|
end
|
|
|
|
function fs.craft(x, y, pos, rank, meta)
|
|
local data = [[
|
|
container[%f, %f]
|
|
formspec_version[3]
|
|
list[nodemeta:%d,%d,%d;output;0,1;1,1;]
|
|
button[3.5,1.5;2,0.5;craft;Craft Map]
|
|
]] .. separator:format(0.75);
|
|
data = data:format(x, y, pos.x, pos.y, pos.z);
|
|
|
|
if rank > 2 then
|
|
local size = "s";
|
|
if meta:get_int("size") == SIZE_LARGE then
|
|
size = "l";
|
|
end
|
|
|
|
data = data .. [[
|
|
style[%s;bgcolor=blue]
|
|
button[0,0;0.5,0.5;s;S]
|
|
button[0.5,0;0.5,0.5;l;L]
|
|
]];
|
|
data = data:format(size);
|
|
end
|
|
|
|
local detail = tostring(meta:get_int("detail") + 1);
|
|
data = data .. [[
|
|
style[%s;bgcolor=blue]
|
|
button[1.25,0;0.5,0.5;1;1]
|
|
button[1.75,0;0.5,0.5;2;2]
|
|
]];
|
|
if rank > 1 then
|
|
data = data .. "button[2.25,0;0.5,0.5;3;3]";
|
|
if rank > 2 then
|
|
data = data .. "button[2.75,0;0.5,0.5;4;4]";
|
|
end
|
|
end
|
|
data = data:format(detail) .. fs.cost(3.5, 1, get_full_material_cost(meta)) .. "container_end[]";
|
|
|
|
return data;
|
|
end
|
|
|
|
function fs.copy(x, y, pos)
|
|
local data = [[
|
|
container[%f,%f]
|
|
formspec_version[3]
|
|
list[nodemeta:%d,%d,%d;copy_input;0,0;1,1;]
|
|
list[nodemeta:%d,%d,%d;copy_output;0,1.25;1,1;]
|
|
button[3.5,0.25;2,0.5;copy;Copy Map]
|
|
]];
|
|
data = data:format(x, y, pos.x, pos.y, pos.z, pos.x, pos.y, pos.z);
|
|
data = data .. fs.cost(1.25, 0.25, {
|
|
Fiber = 0,
|
|
Pigment = 0,
|
|
}) .. "container_end[]";
|
|
|
|
return data;
|
|
end
|
|
|
|
function fs.inv(x, y)
|
|
local data = [[
|
|
container[%f, %f]
|
|
formspec_version[3]
|
|
list[current_player;main;0,0;8,4;]
|
|
container_end[]
|
|
]];
|
|
|
|
return data:format(x, y)
|
|
end
|
|
|
|
local player_tables = {};
|
|
|
|
local function table_formspec(player, tab)
|
|
local pos = player_tables[player];
|
|
local meta = minetest.get_meta(pos);
|
|
|
|
local rank = 1;
|
|
local name = minetest.get_node(pos).name;
|
|
if name == "cartographer:standard_table" then
|
|
rank = 2;
|
|
elseif name == "cartographer:advanced_table" then
|
|
rank = 3;
|
|
end
|
|
|
|
if tab == 1 then
|
|
minetest.show_formspec(player, "simple_table",
|
|
fs.header(10.25, 6.75, rank, tab) ..
|
|
fs.materials(0.25, 0, rank, meta) ..
|
|
separator:format(0.4) ..
|
|
fs.convert(0.25, 0.5, pos) ..
|
|
fs.inv(0.25, 1.75)
|
|
);
|
|
elseif tab == 2 then
|
|
minetest.show_formspec(player, "simple_table",
|
|
fs.header(10.25, 8.0, rank, tab) ..
|
|
fs.materials(0.25, 0, rank, meta) ..
|
|
separator:format(0.4) ..
|
|
fs.craft(0.25, 0.5, pos, rank, meta) ..
|
|
fs.inv(0.25, 3)
|
|
);
|
|
elseif tab == 3 then
|
|
minetest.show_formspec(player, "simple_table",
|
|
fs.header(10.25, 8.0, rank, tab) ..
|
|
fs.materials(0.25, 0, rank, meta) ..
|
|
separator:format(0.4) ..
|
|
fs.copy(0.25, 0.5, pos) ..
|
|
fs.inv(0.25, 3)
|
|
);
|
|
end
|
|
end
|
|
|
|
minetest.register_on_player_receive_fields(function(player, name, fields)
|
|
if name == "simple_table" then
|
|
minetest.chat_send_all(name..": ");
|
|
for k,v in pairs(fields) do
|
|
minetest.chat_send_all(tostring(k).." - "..tostring(v));
|
|
end
|
|
|
|
local meta = minetest.get_meta(player_tables[player:get_player_name()]);
|
|
|
|
if fields["convert"] ~= nil then
|
|
local inv = meta:get_inventory();
|
|
local stack = inv:get_stack("input", 1);
|
|
|
|
local fiber = meta:get_int("fiber");
|
|
local pigment = meta:get_int("pigment");
|
|
|
|
local item_name = stack:get_name();
|
|
local item_count = stack:get_count();
|
|
local found_match = false;
|
|
|
|
for name,mats in pairs(_cartographer.materials_by_name) do
|
|
if name == item_name then
|
|
fiber = fiber + ((mats.fiber or 0) * item_count);
|
|
pigment = pigment + ((mats.pigment or 0) * item_count);
|
|
found_match = true;
|
|
break;
|
|
end
|
|
end
|
|
|
|
if not found_match then
|
|
for group,mats in pairs(_cartographer.materials_by_group) do
|
|
if minetest.get_item_group(item_name, group) ~= 0 then
|
|
fiber = fiber + ((mats.fiber or 0) * item_count);
|
|
pigment = pigment + ((mats.pigment or 0) * item_count);
|
|
found_match = true;
|
|
break;
|
|
end
|
|
end
|
|
end
|
|
|
|
if found_match then
|
|
inv:set_stack("input", 1, ItemStack());
|
|
end
|
|
|
|
meta:set_int("fiber", fiber);
|
|
meta:set_int("pigment", pigment);
|
|
|
|
table_formspec(player:get_player_name(), 1)
|
|
elseif fields["craft"] ~= nil then
|
|
local size = meta:get_int("size");
|
|
local detail = meta:get_int("detail");
|
|
local fiber = meta:get_int("fiber");
|
|
local pigment = meta:get_int("pigment");
|
|
|
|
|
|
local inv = meta:get_inventory();
|
|
local stack = inv:get_stack("output", 1);
|
|
|
|
local cost = get_full_material_cost(meta);
|
|
|
|
if stack:is_empty() then
|
|
if fiber >= cost.fiber and pigment >= cost.pigment then
|
|
fiber = fiber - cost.fiber;
|
|
pigment = pigment - cost.pigment;
|
|
meta:set_int("fiber", fiber);
|
|
meta:set_int("pigment", pigment);
|
|
|
|
inv:set_stack("output", 1, cartographer.create_map_item(size, 1 + detail));
|
|
end
|
|
else
|
|
local smeta = stack:get_meta();
|
|
local old_size = smeta:get_int("cartographer:size");
|
|
local old_detail = smeta:get_int("cartographer:detail") - 1;
|
|
if old_detail <= detail and old_size <= size and not (old_detail == detail and old_size == size) and fiber >= cost.fiber and pigment >= cost.pigment then
|
|
fiber = fiber - cost.fiber;
|
|
pigment = pigment - cost.pigment;
|
|
meta:set_int("fiber", fiber);
|
|
meta:set_int("pigment", pigment);
|
|
|
|
smeta:set_int("cartographer:detail", 1 + detail);
|
|
cartographer.resize_map_item(smeta, size);
|
|
|
|
local map = cartographer.get_map(smeta:get_int("cartographer:map_id"));
|
|
if map ~= nil then
|
|
map.detail = 1 + detail;
|
|
end
|
|
inv:set_stack("output", 1, stack);
|
|
end
|
|
end
|
|
|
|
table_formspec(player:get_player_name(), 2)
|
|
elseif fields["copy"] ~= nil then
|
|
local fiber = meta:get_int("fiber");
|
|
local pigment = meta:get_int("pigment");
|
|
|
|
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 size = smeta:get_int("cartographer:size") or SIZE_SMALL;
|
|
local detail = smeta:get_int("cartographer:detail") or 1;
|
|
local cost = get_material_cost(size, detail - 1);
|
|
|
|
if fiber >= cost.fiber and pigment >= cost.pigment then
|
|
fiber = fiber - cost.fiber;
|
|
pigment = pigment - cost.pigment;
|
|
meta:set_int("fiber", fiber);
|
|
meta:set_int("pigment", pigment);
|
|
|
|
inv:set_stack("copy_output", 1, cartographer.copy_map_item(in_stack));
|
|
end
|
|
|
|
end
|
|
|
|
table_formspec(player:get_player_name(), 3)
|
|
elseif fields["s"] ~= nil then
|
|
meta:set_int("size", SIZE_SMALL);
|
|
table_formspec(player:get_player_name(), 2)
|
|
elseif fields["l"] ~= nil then
|
|
meta:set_int("size", SIZE_LARGE);
|
|
table_formspec(player:get_player_name(), 2)
|
|
elseif fields["1"] ~= nil then
|
|
meta:set_int("detail", 0);
|
|
table_formspec(player:get_player_name(), 2)
|
|
elseif fields["2"] ~= nil then
|
|
meta:set_int("detail", 1);
|
|
table_formspec(player:get_player_name(), 2)
|
|
elseif fields["3"] ~= nil then
|
|
meta:set_int("detail", 2);
|
|
table_formspec(player:get_player_name(), 2)
|
|
elseif fields["4"] ~= nil then
|
|
meta:set_int("detail", 3);
|
|
table_formspec(player:get_player_name(), 2)
|
|
elseif fields["tabs"] ~= nil then
|
|
table_formspec(player:get_player_name(), tonumber(fields["tabs"]));
|
|
end
|
|
end
|
|
end);
|
|
|
|
minetest.register_node("cartographer:simple_table", {
|
|
description = "Shabby Cartographer's Table",
|
|
drawtype = "mesh",
|
|
mesh = "cartographer_simple_table.obj",
|
|
tiles = { "cartographer_simple_table.png" },
|
|
paramtype2 = "facedir",
|
|
groups = {
|
|
choppy = 2,
|
|
oddly_breakable_by_hand = 2,
|
|
},
|
|
on_rightclick = function(pos, node, player, itemstack, pointed_thing)
|
|
player_tables[player:get_player_name()] = minetest.get_pointed_thing_position(pointed_thing);
|
|
table_formspec(player:get_player_name(), 1)
|
|
end,
|
|
|
|
after_place_node = function(pos, placer)
|
|
local meta = minetest.get_meta(pos);
|
|
meta:get_inventory():set_size("input", 1);
|
|
meta:get_inventory():set_size("output", 1);
|
|
|
|
meta:set_int("size", SIZE_SMALL);
|
|
meta:set_int("detail", 0);
|
|
|
|
return res;
|
|
end,
|
|
});
|
|
|
|
minetest.register_node("cartographer:standard_table", {
|
|
groups = {
|
|
choppy = 2,
|
|
oddly_breakable_by_hand = 2,
|
|
},
|
|
on_rightclick = function(pos, node, player, itemstack, pointed_thing)
|
|
player_tables[player:get_player_name()] = minetest.get_pointed_thing_position(pointed_thing);
|
|
table_formspec(player:get_player_name(), 1)
|
|
end,
|
|
|
|
after_place_node = function(pos, placer)
|
|
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", SIZE_SMALL);
|
|
meta:set_int("detail", 0);
|
|
|
|
return res;
|
|
end,
|
|
});
|
|
|
|
minetest.register_node("cartographer:advanced_table", {
|
|
groups = {
|
|
choppy = 2,
|
|
oddly_breakable_by_hand = 2,
|
|
},
|
|
on_rightclick = function(pos, node, player, itemstack, pointed_thing)
|
|
player_tables[player:get_player_name()] = minetest.get_pointed_thing_position(pointed_thing);
|
|
table_formspec(player:get_player_name(), 1)
|
|
end,
|
|
|
|
after_place_node = function(pos, placer)
|
|
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", SIZE_SMALL);
|
|
meta:set_int("detail", 0);
|
|
|
|
return res;
|
|
end,
|
|
});
|
|
|
|
function cartographer.register_map_material_name(name, material, value)
|
|
if _cartographer.materials_by_name[name] == nil then
|
|
_cartographer.materials_by_name[name] = {
|
|
[material] = value or 1,
|
|
};
|
|
else
|
|
_cartographer.materials_by_name[name][material] = value;
|
|
end
|
|
end
|
|
|
|
function cartographer.register_map_material_group(name, material, value)
|
|
if _cartographer.materials_by_group[name] == nil then
|
|
_cartographer.materials_by_group[name] = {
|
|
[material] = value or 1,
|
|
};
|
|
else
|
|
_cartographer.materials_by_group[name][material] = value;
|
|
end
|
|
end
|