From dcfa27df7f7200e16ebf67b45a8436a1c87d490f Mon Sep 17 00:00:00 2001 From: flux <25628292+fluxionary@users.noreply.github.com> Date: Sun, 28 May 2023 15:52:14 -0700 Subject: [PATCH] tree trunk well: compatibility w/ bucket redo --- .luacheckrc | 1 + README.md | 2 + modules/water/init.lua | 2 +- modules/water/well.lua | 173 +++++++++++++++++++++++-------- resources/craftitems.lua | 12 ++- sounds/cottages_fill_glass.1.ogg | Bin 0 -> 12457 bytes sounds/info.txt | 7 ++ 7 files changed, 152 insertions(+), 45 deletions(-) create mode 100644 sounds/cottages_fill_glass.1.ogg create mode 100644 sounds/info.txt diff --git a/.luacheckrc b/.luacheckrc index 820e458..75be1b8 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -660,6 +660,7 @@ stds.cottages = { other_fields = true, }, "broken_tools", + "bucket", "carts", "default", "doors", 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/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..a253c3f 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,128 @@ 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 wielded = puncher:get_wielded_item() local wielded_name = wielded:get_name() - if wielded_name == ci.bucket then - meta:set_string("bucket", wielded_name) - - water.initialize_entity(pos) - - 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) + if minetest.get_item_group(wielded_name, "bucket") == 0 then + return 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() + if not ci.river_water then + return + end + + local pinv = puncher:get_inventory() + 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 - 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", "") - pinv:add_item("main", ci.bucket_filled) + 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..fc293af 100644 --- a/resources/craftitems.lua +++ b/resources/craftitems.lua @@ -28,14 +28,22 @@ if has.default then 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/sounds/cottages_fill_glass.1.ogg b/sounds/cottages_fill_glass.1.ogg new file mode 100644 index 0000000000000000000000000000000000000000..1e44bd28ddbb265b0a26c8b99659288ed49e25d1 GIT binary patch literal 12457 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 P8^jol?+(A