diff --git a/.luacheckrc b/.luacheckrc index 542b27e..75be1b8 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -659,7 +659,8 @@ stds.cottages = { }, other_fields = true, }, - + "broken_tools", + "bucket", "carts", "default", "doors", @@ -669,6 +670,7 @@ stds.cottages = { "player_monoids", "stairs", "stamina", + "staminoid", "unified_inventory", }, } diff --git a/README.md b/README.md index 56fd62b..64303d6 100644 --- a/README.md +++ b/README.md @@ -54,3 +54,5 @@ CC-by-sa 2.0/de. cottages_slate.png Textures not provided but used (need to be supplied by a default mod): default_wood.png default_tree.png default_dirt.png default_grass_side.png default_chest_top.png default_chest_side.png default_chest_front.png default_stick.png farming_wheat.png + +* cottages_fill_glass.1.ogg (C) ezwa 2009 cc0 https://opengameart.org/content/6-short-water-splashes diff --git a/api/register_machine.lua b/api/register_machine.lua index b4ca658..1108ffb 100644 --- a/api/register_machine.lua +++ b/api/register_machine.lua @@ -82,6 +82,7 @@ function api.register_machine(name, def) is_ground_content = false, groups = def.groups, sounds = def.sounds, + drop = def.drop, after_place_node = function(pos, placer, itemstack) local meta = minetest.get_meta(pos) diff --git a/init.lua b/init.lua index 5133fb0..232a9f0 100644 --- a/init.lua +++ b/init.lua @@ -12,6 +12,7 @@ cottages = { has = { anvil = minetest.get_modpath("anvil"), + broken_tools = minetest.get_modpath("broken_tools"), bucket = minetest.get_modpath("bucket"), default = minetest.get_modpath("default"), doors = minetest.get_modpath("doors"), @@ -25,6 +26,7 @@ cottages = { stairs = minetest.get_modpath("stairs"), stairsplus = minetest.get_modpath("stairsplus"), stamina = minetest.get_modpath("stamina") and minetest.global_exists("stamina") and stamina.exhaust_player, + staminoid = minetest.get_modpath("staminoid"), technic = minetest.get_modpath("technic"), unified_inventory = minetest.get_modpath("unified_inventory"), wool = minetest.get_modpath("wool"), diff --git a/mod.conf b/mod.conf index f738a08..06eae37 100644 --- a/mod.conf +++ b/mod.conf @@ -5,4 +5,26 @@ author = Sokomine description = Contains nodes for building medieval houses. url = https://github.com/sokomine/cottages version = 2023-02-08 -optional_depends = anvil, bucket, default, doors, env_sounds, ethereal, farming, moreblocks, node_entity_queue, player_api, player_monoids, stairs, stairsplus, stamina, technic, unified_inventory, wool, workbench +optional_depends = """ +anvil, +broken_tools, +bucket, +default, +doors, +env_sounds, +ethereal, +farming, +moreblocks, +node_entity_queue, +player_api, +player_monoids, +stairs, +stairsplus, +stairsplus_legacy, +stamina, +staminoid, +technic, +unified_inventory, +wool, +workbench +""" diff --git a/modules/anvil/anvil.lua b/modules/anvil/anvil.lua index b290744..67291a4 100644 --- a/modules/anvil/anvil.lua +++ b/modules/anvil/anvil.lua @@ -4,6 +4,7 @@ local FS = function(...) return F(S(...)) end local anvil = cottages.anvil +local ci = cottages.craftitems local add_entity = minetest.add_entity local get_node = minetest.get_node @@ -17,8 +18,9 @@ local v_sub = vector.subtract local get_safe_short_description = cottages.util.get_safe_short_description local resolve_item = cottages.util.resolve_item +local exhaust_player = cottages.util.exhaust_player -local has_stamina = cottages.has.stamina +local has_broken_tools = cottages.has.broken_tools local repair_amount = cottages.settings.anvil.repair_amount local hammer_wear = cottages.settings.anvil.hammer_wear @@ -28,6 +30,7 @@ local hud_timeout = cottages.settings.anvil.hud_timeout local stamina_use = cottages.settings.anvil.stamina local tool_entity_enabled = cottages.settings.anvil.tool_entity_enabled local tool_entity_displacement = cottages.settings.anvil.tool_entity_displacement +local destroy_when_dug = cottages.settings.anvil.destroy_when_dug local hud_info_by_puncher_name = {} @@ -185,6 +188,11 @@ function anvil.use_anvil(pos, puncher) -- do the actual repair tool:add_wear(-repair_amount) + + if has_broken_tools then + broken_tools.fix_tool(tool) + end + inv:set_stack("input", 1, tool) -- damage the hammer slightly @@ -193,9 +201,7 @@ function anvil.use_anvil(pos, puncher) update_hud(puncher, tool) - if has_stamina then - stamina.exhaust_player(puncher, stamina_use, "cottages:anvil") - end + exhaust_player(puncher, stamina_use, "cottages:anvil") else -- tell the player when the job is done, but only once if meta:get_int("informed") > 0 then @@ -204,7 +210,7 @@ function anvil.use_anvil(pos, puncher) meta:set_int("informed", 1) - local tool_desc = tool:get_short_description() or tool:get_description() + local tool_desc = get_safe_short_description(tool) minetest.chat_send_player(puncher_name, S("Your @1 has been repaired successfully.", tool_desc)) end end @@ -440,6 +446,18 @@ function anvil.preserve_metadata(pos, oldnode, oldmeta, drops) return drops end +local drop + +if destroy_when_dug then + drop = { + items = { + { + items = { ci.steel .. " 7" }, + }, + }, + } +end + cottages.api.register_machine("cottages:anvil", { description = S("anvil"), drawtype = "nodebox", @@ -456,6 +474,7 @@ cottages.api.register_machine("cottages:anvil", { tiles = { "cottages_stone.png^[colorize:#000:192" }, groups = { cracky = 2 }, sounds = cottages.sounds.metal, + drop = drop, inv_info = { input = 1, diff --git a/modules/anvil/crafts.lua b/modules/anvil/crafts.lua index ce3c6d1..4cf1e98 100644 --- a/modules/anvil/crafts.lua +++ b/modules/anvil/crafts.lua @@ -1,16 +1,18 @@ local S = cottages.S local ci = cottages.craftitems -if ci.steel then +if ci.steelblock then minetest.register_craft({ output = "cottages:anvil", recipe = { - { ci.steel, ci.steel, ci.steel }, - { "", ci.steel, "" }, - { ci.steel, ci.steel, ci.steel }, + { ci.steelblock, ci.steelblock, ci.steelblock }, + { "", ci.steelblock, "" }, + { ci.steelblock, ci.steelblock, ci.steelblock }, }, }) +end +if ci.steel then minetest.register_craft({ output = "cottages:hammer", recipe = { diff --git a/modules/barrel/crafts.lua b/modules/barrel/crafts.lua index 89308df..15de35f 100644 --- a/modules/barrel/crafts.lua +++ b/modules/barrel/crafts.lua @@ -4,9 +4,9 @@ if ci.wood and ci.steel then minetest.register_craft({ output = "cottages:barrel", recipe = { - { ci.wood, ci.wood, ci.wood }, - { ci.steel, "", ci.steel }, - { ci.wood, ci.wood, ci.wood }, + { ci.wood, ci.steel, ci.wood }, + { ci.wood, "", ci.wood }, + { ci.wood, ci.steel, ci.wood }, }, }) diff --git a/modules/doorlike/api.lua b/modules/doorlike/api.lua index b40748b..f715f24 100644 --- a/modules/doorlike/api.lua +++ b/modules/doorlike/api.lua @@ -1,8 +1,10 @@ local S = cottages.S +local exhaust_player = cottages.util.exhaust_player + local api = cottages.doorlike + local stamina_use = cottages.settings.doorlike.stamina -local has_stamina = cottages.has.stamina -- propagate shutting/closing of window shutters to window shutters below/above this one local offsets = { @@ -43,16 +45,12 @@ end function api.shutter_open(pos, puncher) api.shutter_operate(pos, "cottages:window_shutter_closed", "cottages:window_shutter_open") - if has_stamina then - stamina.exhaust_player(puncher, stamina_use, "cottages:shutter") - end + exhaust_player(puncher, stamina_use, "cottages:shutter") end function api.shutter_close(pos, puncher) api.shutter_operate(pos, "cottages:window_shutter_open", "cottages:window_shutter_closed") - if has_stamina then - stamina.exhaust_player(puncher, stamina_use, "cottages:shutter") - end + exhaust_player(puncher, stamina_use, "cottages:shutter") end function api.is_night() @@ -141,9 +139,7 @@ function api.register_hatch(nodename, description, texture, receipe_item, def) fixed = { -0.5, -0.55, -0.5, 0.5, -0.45, 0.5 }, }, on_rightclick = function(pos, node, puncher) - if has_stamina then - stamina.exhaust_player(puncher, stamina_use, nodename) - end + exhaust_player(puncher, stamina_use, nodename) minetest.swap_node(pos, { name = node.name, param2 = new_facedirs[node.param2 + 1] }) end, diff --git a/modules/historic/crafts.lua b/modules/historic/crafts.lua index 1ef7523..6327c6a 100644 --- a/modules/historic/crafts.lua +++ b/modules/historic/crafts.lua @@ -33,9 +33,9 @@ if ci.stick and ci.glass then minetest.register_craft({ output = "cottages:glass_pane 4", recipe = { - { ci.stick, ci.stick, ci.stick }, + { "", ci.stick, "" }, { ci.stick, ci.glass, ci.stick }, - { ci.stick, ci.stick, ci.stick }, + { "", ci.stick, "" }, }, }) end diff --git a/modules/mining/crafts.lua b/modules/mining/crafts.lua index b81b29d..9cb4009 100644 --- a/modules/mining/crafts.lua +++ b/modules/mining/crafts.lua @@ -4,7 +4,9 @@ if ci.cotton then minetest.register_craft({ output = "cottages:rope", recipe = { - { ci.cotton, ci.cotton, ci.cotton }, + { ci.cotton, "", "" }, + { "", ci.cotton, "" }, + { "", "", ci.cotton }, }, }) end diff --git a/modules/mining/nodes.lua b/modules/mining/nodes.lua index d9917e1..ed91f55 100644 --- a/modules/mining/nodes.lua +++ b/modules/mining/nodes.lua @@ -52,7 +52,7 @@ else wield_image = "default_ladder_wood.png", drawtype = "raillike", tiles = { - "default_ladder_wood.png^carts_rail_straight.png^cottages_rope.png", + "default_ladder_wood.png^cottages_rope.png", }, paramtype = "light", paramtype2 = "wallmounted", diff --git a/modules/pitchfork/tool.lua b/modules/pitchfork/tool.lua index bac05f4..f922a0f 100644 --- a/modules/pitchfork/tool.lua +++ b/modules/pitchfork/tool.lua @@ -1,6 +1,6 @@ local S = cottages.S -local has_stamina = cottages.has.stamina +local exhaust_player = cottages.util.exhaust_player local stamina_use = cottages.settings.pitchfork.stamina minetest.register_node("cottages:pitchfork", { @@ -91,9 +91,7 @@ local function override_on_dig(node_name, replacement) minetest.swap_node(pos, { name = replacement }) minetest.swap_node(pos_above, { name = "cottages:hay_mat", param2 = math.random(2, 25) }) - if has_stamina then - stamina.exhaust_player(digger, stamina_use, "cottages:pitchfork") - end + exhaust_player(digger, stamina_use, "cottages:pitchfork") return true end, diff --git a/modules/straw/quern.lua b/modules/straw/quern.lua index 0bb8975..b4c110d 100644 --- a/modules/straw/quern.lua +++ b/modules/straw/quern.lua @@ -7,8 +7,8 @@ local FS = function(...) end local get_safe_short_description = cottages.util.get_safe_short_description +local exhaust_player = cottages.util.exhaust_player -local has_stamina = cottages.has.stamina local stamina_use = cottages.settings.straw.quern_stamina local quern_min_per_turn = cottages.settings.straw.quern_min_per_turn local quern_max_per_turn = cottages.settings.straw.quern_max_per_turn @@ -125,9 +125,7 @@ function straw.use_quern(pos, player) minetest.sound_play({ name = cottages.sounds.use_quern }, { pos = pos, gain = 1, pitch = 0.25 }, true) - if has_stamina then - stamina.exhaust_player(player, stamina_use, "cottages:quern") - end + exhaust_player(player, stamina_use, "cottages:quern") return true end diff --git a/modules/straw/threshing.lua b/modules/straw/threshing.lua index f8ce2bc..c678762 100644 --- a/modules/straw/threshing.lua +++ b/modules/straw/threshing.lua @@ -7,8 +7,8 @@ local FS = function(...) end local get_safe_short_description = cottages.util.get_safe_short_description +local exhaust_player = cottages.util.exhaust_player -local has_stamina = cottages.has.stamina local stamina_use = cottages.settings.straw.threshing_stamina local threshing_min_per_punch = cottages.settings.straw.threshing_min_per_punch local threshing_max_per_punch = cottages.settings.straw.threshing_max_per_punch @@ -166,9 +166,7 @@ function straw.use_threshing(pos, player) minetest.sound_play({ name = cottages.sounds.use_thresher }, { pos = particle_pos, gain = 1, pitch = 0.5 }, true) - if has_stamina then - stamina.exhaust_player(player, stamina_use, "cottages:quern") - end + exhaust_player(player, stamina_use, "cottages:threshing") return true end diff --git a/modules/water/init.lua b/modules/water/init.lua index 7bb7f98..12c540c 100644 --- a/modules/water/init.lua +++ b/modules/water/init.lua @@ -1,4 +1,4 @@ -if not (cottages.craftitems.bucket and cottages.craftitems.bucket_filled) then +if not cottages.has.bucket then return end diff --git a/modules/water/well.lua b/modules/water/well.lua index 8d99dd7..311542d 100644 --- a/modules/water/well.lua +++ b/modules/water/well.lua @@ -1,3 +1,4 @@ +local f = string.format local F = minetest.formspec_escape local S = cottages.S local FS = function(...) @@ -14,7 +15,21 @@ local settings = cottages.settings.water local sound_handles_by_pos = {} local particlespawner_ids_by_pos = {} -local well_fill_time = cottages.settings.water.well_fill_time +water.registered_fillables = {} +water.registered_filleds = {} + +function water.register_fillable(empty, filled, fill_time) + assert(minetest.registered_items[empty], f("item %s does not exist", empty)) + assert(minetest.registered_items[filled], f("item %s does not exist", filled)) + assert(not fill_time or fill_time >= 0, f("fill time must be greater than or equal to 0")) + local def = { + empty = empty, + filled = filled, + fill_time = fill_time or settings.well_fill_time, + } + water.register_fillable[empty] = def + water.registered_filleds[filled] = def +end function water.get_well_fs_parts(pos) return { @@ -37,54 +52,168 @@ function water.get_well_info(pos) return S("Tree trunk well") end -function water.use_well(pos, puncher) - local player_name = puncher:get_player_name() - local meta = minetest.get_meta(pos) +if bucket.fork == "flux" then + -- bucket redo + function water.use_well(pos, puncher) + if not minetest.is_player(puncher) then + return + end - local pinv = puncher:get_inventory() - local bucket = meta:get("bucket") - - local entity_pos = vector.add(pos, vector.new(0, 1 / 4, 0)) - - if not bucket then + local player_name = puncher:get_player_name() + local spos = minetest.pos_to_string(pos) + local pinv = puncher:get_inventory() local wielded = puncher:get_wielded_item() local wielded_name = wielded:get_name() - if wielded_name == ci.bucket then - meta:set_string("bucket", wielded_name) + local fillable = water.registered_fillables[wielded_name] + local entity_pos = vector.add(pos, vector.new(0, 1 / 4, 0)) - water.initialize_entity(pos) + if fillable then + if fillable.fill_time == 0 then + local removed = pinv:remove_item("main", wielded_name) + if removed:is_empty() then + cottages.log( + "error", + "well @ %s: failed to remove %s's wielded item %s", + spos, + player_name, + removed:to_string() + ) + else + local remainder = pinv:add_item("main", fillable.filled) + if not remainder:is_empty() then + if not minetest.add_item(pos, remainder) then + cottages.log( + "error", + "well @ %s: somehow lost %s's %s", + spos, + player_name, + remainder:to_string() + ) + end + end - pinv:remove_item("main", "bucket:bucket_empty") - - local timer = minetest.get_node_timer(pos) - timer:start(well_fill_time) - - water.add_filling_effects(pos) - elseif wielded_name == ci.bucket_filled then - -- empty a bucket - pinv:remove_item("main", ci.bucket_filled) - pinv:add_item("main", ci.bucket) - - minetest.sound_play({ name = s.water_empty }, { pos = entity_pos, gain = 0.5, pitch = 2.0 }, true) - end - elseif bucket == ci.bucket then - minetest.chat_send_player(player_name, S("Please wait until your bucket has been filled.")) - local timer = minetest.get_node_timer(pos) - if not timer:is_started() then - timer:start(well_fill_time) - water.add_filling_effects(pos) - end - elseif bucket == ci.bucket_filled then - meta:set_string("bucket", "") - - for _, obj in ipairs(minetest.get_objects_inside_radius(entity_pos, 0.1)) do - local ent = obj:get_luaentity() - if ent and ent.name == "cottages:bucket_entity" then - obj:remove() + minetest.sound_play( + { name = "cottages_fill_glass" }, + { pos = entity_pos, loop = false, gain = 0.5, pitch = 2.0 }, + true + ) + return + end end end - pinv:add_item("main", ci.bucket_filled) + if minetest.get_item_group(wielded_name, "bucket") == 0 then + return + end + + if not ci.river_water then + return + end + + pinv:add_item("main", ci.river_water) + + minetest.sound_play( + { name = "cottages_fill_glass" }, + { pos = pos, loop = false, gain = 0.5, pitch = 1.0 }, + true + ) + end +else + function water.use_well(pos, puncher) + local spos = minetest.pos_to_string(pos) + local player_name = puncher:get_player_name() + local node_meta = minetest.get_meta(pos) + + local pinv = puncher:get_inventory() + local current_bucket = node_meta:get("bucket") + + local entity_pos = vector.add(pos, vector.new(0, 1 / 4, 0)) + + if not current_bucket then + local wielded = puncher:get_wielded_item() + local wielded_name = wielded:get_name() + local fillable = water.registered_fillables[wielded_name] + local filled = water.registered_filleds[wielded_name] + if fillable then + if fillable.fill_time == 0 then + local removed = pinv:remove_item("main", wielded_name) + if removed:is_empty() then + cottages.log( + "error", + "well @ %s: failed to remove %s's wielded item %s", + spos, + player_name, + removed:to_string() + ) + else + local remainder = pinv:add_item("main", fillable.filled) + if not remainder:is_empty() then + if not minetest.add_item(pos, remainder) then + cottages.log( + "error", + "well @ %s: somehow lost %s's %s", + spos, + player_name, + remainder:to_string() + ) + end + end + + minetest.sound_play( + { name = "cottages_fill_glass" }, + { pos = entity_pos, loop = false, gain = 0.5, pitch = 2.0 }, + true + ) + end + else + local removed = pinv:remove_item("main", wielded_name) + local remainder = node_meta:set_string("bucket", removed) + if not remainder:is_empty() then + if not minetest.add_item(pos, remainder) then + cottages.log( + "error", + "well @ %s: somehow lost %s's %s", + spos, + player_name, + remainder:to_string() + ) + end + end + + water.initialize_entity(pos) + + local timer = minetest.get_node_timer(pos) + timer:start(fillable.fill_time) + + water.add_filling_effects(pos) + end + elseif filled then + -- empty a bucket + -- TODO error checking and logging + pinv:remove_item("main", filled.filled) + pinv:add_item("main", filled.empty) + + minetest.sound_play({ name = s.water_empty }, { pos = entity_pos, gain = 0.5, pitch = 2.0 }, true) + end + elseif current_bucket then + minetest.chat_send_player(player_name, S("Please wait until your bucket has been filled.")) + local timer = minetest.get_node_timer(pos) + if not timer:is_started() then + timer:start(settings.well_fill_time) + water.add_filling_effects(pos) + end + elseif current_bucket == ci.bucket_filled then + node_meta:set_string("bucket", "") + + for _, obj in ipairs(minetest.get_objects_inside_radius(entity_pos, 0.1)) do + local ent = obj:get_luaentity() + if ent and ent.name == "cottages:bucket_entity" then + obj:remove() + end + end + + pinv:add_item("main", ci.bucket_filled) + end end end diff --git a/resources/craftitems.lua b/resources/craftitems.lua index f43a53b..8c49475 100644 --- a/resources/craftitems.lua +++ b/resources/craftitems.lua @@ -24,18 +24,27 @@ if has.default then ci.rail = resolve_item("default:rail") ci.sand = resolve_item("default:sand") ci.steel = resolve_item("default:steel_ingot") + ci.steelblock = resolve_item("default:steelblock") ci.stone = resolve_item("default:stone") end if has.bucket then - ci.bucket = resolve_item("bucket:bucket_empty") - ci.bucket_filled = resolve_item("bucket:bucket_river_water") + if bucket.fork == "flux" then + ci.bucket = resolve_item("bucket:bucket_steel") + else + ci.bucket = resolve_item("bucket:bucket_empty") + ci.bucket_filled = resolve_item("bucket:bucket_river_water") + end end if has.carts then ci.rail = resolve_item("carts:rail") end +if has.default then + ci.river_water = resolve_item("default:river_water_source") +end + if has.doors then ci.door = resolve_item("doors:door_wood") end diff --git a/settingtypes.txt b/settingtypes.txt index 03945ba..4508a23 100644 --- a/settingtypes.txt +++ b/settingtypes.txt @@ -11,7 +11,7 @@ cottages.anvil.hammer_wear (hammer wear) int 100 0 65536 cottages.anvil.repair_amount (anvil repair amount) int 4369 0 65535 # amount of stamina to consume per hammer strike -cottages.anvil.stamina (anvil stamina usage) int 40 0 +cottages.anvil.stamina (anvil stamina usage) int 80 0 # if false, right-click the anvil to place a tool on it cottages.anvil.formspec_enabled (enable anvil formspec) bool true @@ -28,6 +28,9 @@ cottages.anvil.tool_entity_enabled (tool entity enabled) bool false # how far above the anvil to put the entity cottages.anvil.tool_entity_displacement (tool entity displacement) float .125 +# if true, the anvil is destroyed when dug, though it does drop some iron. +cottages.anvil.destroy_when_dug (destroy anvil when dug) bool true + ############################################################################### # provides a barrel which can be used to store liquids, and a couple decorative variants. diff --git a/sounds/cottages_fill_glass.1.ogg b/sounds/cottages_fill_glass.1.ogg new file mode 100644 index 0000000..1e44bd2 Binary files /dev/null and b/sounds/cottages_fill_glass.1.ogg differ diff --git a/sounds/info.txt b/sounds/info.txt new file mode 100644 index 0000000..6e83bca --- /dev/null +++ b/sounds/info.txt @@ -0,0 +1,7 @@ +Sounds used from http://www.pdsounds.org/sounds/emptying_syringe_in_water_slow and http://www.pdsounds.org/sounds/emptying_syringe_in_water_fast + +No license aka public domain/cc0/wtfpl/do-what-you-want :) + +Cut by qubodup + +Hosted by opengameart.org diff --git a/util.lua b/util.lua index b9d88f3..756e764 100644 --- a/util.lua +++ b/util.lua @@ -314,4 +314,15 @@ else end end +local has_stamina = cottages.has.stamina +local has_staminoid = cottages.has.staminoid + +function util.exhaust_player(player, amount, reason) + if has_stamina then + stamina.exhaust_player(player, amount, reason) + elseif has_staminoid then + staminoid.exhaust(player, amount / 10, reason) + end +end + cottages.util = util