diff --git a/mods/ITEMS/mcl_loom/README.md b/mods/ITEMS/mcl_loom/README.md index e91bad8fd..3fe89725e 100644 --- a/mods/ITEMS/mcl_loom/README.md +++ b/mods/ITEMS/mcl_loom/README.md @@ -1,6 +1,6 @@ mcl_loom -------- -Looms, by PrairieWind +Looms, by PrairieWind, mirqf, AFCM Adds Looms to MineClone 2/5. Used to add patterns to banners. diff --git a/mods/ITEMS/mcl_loom/init.lua b/mods/ITEMS/mcl_loom/init.lua index 5475980bd..c90f3979a 100644 --- a/mods/ITEMS/mcl_loom/init.lua +++ b/mods/ITEMS/mcl_loom/init.lua @@ -1,5 +1,163 @@ local S = minetest.get_translator(minetest.get_current_modname()) --- Loom Code. Used to craft banner designs easier. Still needs a GUI. https://minecraft.fandom.com/wiki/Loom +local C = minetest.colorize +local F = minetest.formspec_escape + +local pattern_names = { + "border", + "bricks", + "circle", + "cross", + "curly_border", + "diagonal_up_left", + "diagonal_up_right", + "diagonal_right", + "diagonal_left", + "gradient", + "gradient_up", + "half_horizontal_bottom", + "half_horizontal", + "half_vertical", + "half_vertical_right", + "thing", + "rhombus", + "small_stripes", + "square_bottom_left", + "square_bottom_right", + "square_top_left", + "square_top_right", + "straight_cross", + "stripe_bottom", + "stripe_center", + "stripe_downleft", + "stripe_downright", + "stripe_left", + "stripe_middle", + "stripe_right", + "stripe_top", + "triangle_bottom", + "triangle_top", + "triangles_bottom", + "triangles_top", +} + +local function form_patterns_table() + -- Buttons are 3.5 / 4 = 0.875 wide + local formspec = "style_type[item_image_button;noclip=false;content_offset=0]" + for i, item in ipairs(pattern_names) do + local x = ((i - 1) % 4) * 0.875 + local y = (math.floor((i - 1) / 4)) * 0.875 + + formspec = formspec .. + string.format("item_image_button[%f,%f;0.875,0.875;%s;%s;]", x, y, + "mcl_banners:banner_preview_" .. item .. "_red", item) + end + return formspec +end + +local dye_to_colorid_mapping = {} +for colorid, colortab in pairs(mcl_banners.colors) do + dye_to_colorid_mapping[colortab[5]] = colorid +end + +local function add_layer(banner, pattern, color) + local layers = minetest.deserialize(banner:get_meta():get_string("layers")) or {} + table.insert(layers, { pattern = pattern, color = dye_to_colorid_mapping[color:get_name()] }) + banner:get_meta():set_string("layers", minetest.serialize(layers)) + return banner +end + +local function show_loom_formspec(pos, player) + local inv = minetest.get_meta(pos):get_inventory() + + local banner = inv:get_stack("input", 1) + local dye = inv:get_stack("input", 2) + local pattern = inv:get_stack("input", 3) + + local container_content = "" + + if not banner:is_empty() and not dye:is_empty() then + if not pattern:is_empty() then + inv:set_stack("output", 1, add_layer(banner, pattern:get_name():split(":")[2]:split("_")[1], dye)) + local item = pattern:get_name():split(":")[2]:split("_")[1] + container_content = string.format("item_image[0,0;0.875,0.875;%s]", "mcl_banners:banner_preview_" .. item .. "_red") + else + container_content = form_patterns_table() + end + end + + local output = inv:get_stack("output", 1) + local preview = mcl_banners.make_banner_texture(mcl_banners.color_reverse(output:get_name()), minetest.deserialize(output:get_meta():get_string("layers")) or {}) + + local banner_model = "model[9.55,0.7;1.4,2.3;keeper;amc_banner_hanging.b3d;" .. + preview .. ";0,-180;false;false;x=0,y=0;0]" + + local formspec = table.concat({ + "formspec_version[4]", + "size[11.75,10.425]", + "label[0.375,0.375;" .. F(C(mcl_formspec.label_color, S("Loom"))) .. "]", + + -- PLACEHOLDER: "box[0.375,0.75;3.5,3.5;#222222]", + "image[0.375,0.75;3.5,3.5;mcl_loom_inventory.png]", + + -- Banner input slot + mcl_formspec.get_itemslot_bg_v4(1, 1.5, 1, 1), + banner:is_empty() and mcl_formspec.get_itemslot_bg_v4(1, 1.5, 1, 1, 0, "mcl_loom_inventory_banner.png") or "", + "list[nodemeta:" .. pos.x .. "," .. pos.y .. "," .. pos.z .. ";input;1,1.5;1,1;]", + + -- Dye input slot + mcl_formspec.get_itemslot_bg_v4(2.25, 1.5, 1, 1), + dye:is_empty() and mcl_formspec.get_itemslot_bg_v4(2.25, 1.5, 1, 1, 0, "mcl_loom_inventory_dye.png") or "", + "list[nodemeta:" .. pos.x .. "," .. pos.y .. "," .. pos.z .. ";input;2.25,1.5;1,1;1]", + + -- Pattern input slot + mcl_formspec.get_itemslot_bg_v4(1.625, 2.75, 1, 1), + pattern:is_empty() and mcl_formspec.get_itemslot_bg_v4(1.625, 2.75, 1, 1, 0, "mcl_loom_inventory_pattern.png") or + "", + "list[nodemeta:" .. pos.x .. "," .. pos.y .. "," .. pos.z .. ";input;1.625,2.75;1,1;2]", + + -- Container background + "image[4.450,0.7;3.6,3.6;mcl_inventory_background9.png;2]", + + -- Scroll Container with buttons if needed + "scroll_container[4.5,0.75;3.5,3.5;scroll;vertical;0.875]", + container_content, + "scroll_container_end[]", + + -- Scrollbar + -- TODO: style the scrollbar correctly when possible + "scrollbaroptions[min=0;max=" .. + math.max(math.floor(#pattern_names / 4) + 1 - 4, 0) .. ";smallstep=1;largesteps=1]", + "scrollbar[8,0.7;0.75,3.6;vertical;scroll;0]", + + banner_model, + + -- Output slot + mcl_formspec.get_itemslot_bg_v4(9.75, 3.1, 1, 1, 0.2), + "list[nodemeta:" .. pos.x .. "," .. pos.y .. "," .. pos.z .. ";output;9.75,3.1;1,1;]", + + -- Player inventory + "label[0.375,4.7;" .. F(C(mcl_formspec.label_color, S("Inventory"))) .. "]", + mcl_formspec.get_itemslot_bg_v4(0.375, 5.1, 9, 3), + "list[current_player;main;0.375,5.1;9,3;9]", + + mcl_formspec.get_itemslot_bg_v4(0.375, 9.05, 9, 1), + "list[current_player;main;0.375,9.05;9,1;]", + }) + + tt.reload_itemstack_description(inv:get_stack("output", 1)) + minetest.show_formspec(player:get_player_name(), ("mcl_loom:%f_%f_%f"):format(pos.x, pos.y, pos.z), formspec) +end + +minetest.register_on_player_receive_fields(function(player, formname, fields) + if not fields.quit and formname:find("mcl_loom") then + local p = formname:split(":")[2]:split("_") + local pos = vector.new(tonumber(p[1]), tonumber(p[2]), tonumber(p[3])) + local pattern; for k, _ in pairs(fields) do if k ~= "scroll" then pattern = k break end end; if not pattern then return end + local inv = minetest.get_meta(pos):get_inventory(); if not inv then return end + inv:set_stack("output", 1, add_layer(inv:get_stack("input", 1), pattern, inv:get_stack("input", 2))) + show_loom_formspec(pos, player) + end +end) minetest.register_node("mcl_loom:loom", { description = S("Loom"), @@ -12,17 +170,67 @@ minetest.register_node("mcl_loom:loom", { }, paramtype2 = "facedir", groups = { axey = 2, handy = 1, deco_block = 1, material_wood = 1, flammable = 1 }, - sounds = mcl_sounds.node_sound_wood_defaults(), _mcl_blast_resistance = 2.5, - _mcl_hardness = 2.5 + _mcl_hardness = 2.5, + on_construct = function(pos) + local inv = minetest.get_meta(pos):get_inventory() + inv:set_size("input", 3) + inv:set_size("output", 1) + end, + allow_metadata_inventory_put = function(pos, listname, index, stack, player) + if minetest.is_protected(pos, player:get_player_name()) or listname == "output" then + return 0 + else + local name = stack:get_name() + if (index == 1 and not name:find("banner_item")) or (index == 2 and not name:find("mcl_dye")) or (index == 3 and not name:find("pattern")) then return 0 end + return stack:get_count() + end + end, + on_metadata_inventory_put = function(pos, _, _, _, player) + local inv = minetest.get_meta(pos):get_inventory() + if not inv:get_stack("input", 1):is_empty() and not inv:get_stack("input", 2):is_empty() then + show_loom_formspec(pos, player) + end + end, + on_metadata_inventory_take = function(pos, listname, index, stack, player) + local inv = minetest.get_meta(pos):get_inventory() + if listname == "output" then + local count = stack:get_count() + local first = inv:get_stack("input", 1); first:take_item(count); inv:set_stack("input", 1, first) + local second = inv:get_stack("input", 2); second:take_item(count); inv:set_stack("input", 2, second) + else + inv:set_stack("output", 1, "") + end + show_loom_formspec(pos, player) + end, + allow_metadata_inventory_move = function() return 0 end, + on_rightclick = function(pos, node, player, itemstack) + if not player:get_player_control().sneak then show_loom_formspec(pos, player) end + end, + after_dig_node = function(pos, _, oldmetadata, _) + local meta = minetest.get_meta(pos) + local meta2 = meta:to_table() + meta:from_table(oldmetadata) + local inv = meta:get_inventory() + for i = 1, inv:get_size("input") do + local stack = inv:get_stack("input", i) + if not stack:is_empty() then + minetest.add_item(vector.offset(pos, + math.random(0, 10) / 10 - 0.5, + 0, + math.random(0, 10) / 10 - 0.5 + ), stack) + end + end + meta:from_table(meta2) + end, }) - minetest.register_craft({ - output = "mcl_loom:loom", + output = "mcl_functional:loom", recipe = { - { "", "", "" }, + { "", "", "" }, { "mcl_mobitems:string", "mcl_mobitems:string", "" }, - { "group:wood", "group:wood", "" }, + { "group:wood", "group:wood", "" }, } }) diff --git a/mods/ITEMS/mcl_loom/mod.conf b/mods/ITEMS/mcl_loom/mod.conf index e316b201a..ae2483cae 100644 --- a/mods/ITEMS/mcl_loom/mod.conf +++ b/mods/ITEMS/mcl_loom/mod.conf @@ -1,4 +1,4 @@ name = mcl_loom -author = PrairieWind -depends = mcl_core, mcl_sounds, mcl_tools +author = PrairieWind, mirqf, AFCM +depends = mcl_core, mcl_sounds, mcl_tools, mcl_formspec description = Adds the loom villager workstation to MineClone 2/5. Used to add patterns to banners. \ No newline at end of file diff --git a/textures/mcl_loom_inventory.png b/textures/mcl_loom_inventory.png new file mode 100644 index 000000000..6cd4418ce Binary files /dev/null and b/textures/mcl_loom_inventory.png differ diff --git a/textures/mcl_loom_inventory_banner.png b/textures/mcl_loom_inventory_banner.png new file mode 100644 index 000000000..6a32023cd Binary files /dev/null and b/textures/mcl_loom_inventory_banner.png differ diff --git a/textures/mcl_loom_inventory_dye.png b/textures/mcl_loom_inventory_dye.png new file mode 100644 index 000000000..2c2e1e63e Binary files /dev/null and b/textures/mcl_loom_inventory_dye.png differ diff --git a/textures/mcl_loom_inventory_pattern.png b/textures/mcl_loom_inventory_pattern.png new file mode 100644 index 000000000..20e719b33 Binary files /dev/null and b/textures/mcl_loom_inventory_pattern.png differ