mirror of
https://github.com/luanti-org/minetest_game.git
synced 2025-05-21 06:43:17 -04:00
419 lines
12 KiB
Lua
419 lines
12 KiB
Lua
|
|
----------------
|
|
-- Lookup tables
|
|
----------------
|
|
|
|
-- Contains which mortar you get when you put a rapeseed into a mortar
|
|
local put_seed_into_mortar = {
|
|
["farming:mortar"] = "farming:mortar_with_1_rapeseed",
|
|
["farming:mortar_with_1_rapeseed"] = "farming:mortar_with_2_rapeseed",
|
|
["farming:mortar_with_2_rapeseed"] = "farming:mortar_with_3_rapeseed",
|
|
}
|
|
-- Contains which mortar you get when you take oil from a mortar with a bottle
|
|
local take_oil_from_mortar = {
|
|
["farming:mortar_with_1_rapeseed_oil"] = "farming:mortar",
|
|
["farming:mortar_with_2_rapeseed_oil"] = "farming:mortar_with_1_rapeseed_oil",
|
|
["farming:mortar_with_3_rapeseed_oil"] = "farming:mortar_with_2_rapeseed_oil",
|
|
}
|
|
|
|
-- Conatins what will be in the mortar after the player used the pestle often enough
|
|
-- How often the pestle has to be used is calculated in get_num_poundings
|
|
local pound_with_pestle = {
|
|
["farming:mortar_with_1_rapeseed"] = {
|
|
after = "farming:mortar_with_1_rapeseed_oil",
|
|
base_min = 1,
|
|
base_max = 2,
|
|
prob = 0.5,
|
|
},
|
|
["farming:mortar_with_2_rapeseed"] = {
|
|
after = "farming:mortar_with_2_rapeseed_oil",
|
|
base_min = 2,
|
|
base_max = 3,
|
|
prob = 0.3,
|
|
},
|
|
["farming:mortar_with_3_rapeseed"] = {
|
|
after = "farming:mortar_with_3_rapeseed_oil",
|
|
base_min = 3,
|
|
base_max = 4,
|
|
prob = 0.2,
|
|
},
|
|
}
|
|
|
|
-- Returns for an entry in pound_with_pestle, how often the player has to use the
|
|
-- pestle
|
|
local function get_num_poundings(entry)
|
|
local ret = math.random(entry.base_min, entry.base_max)
|
|
-- todo: make this more efficient
|
|
while math.random() > entry.prob do
|
|
ret = ret + 1
|
|
end
|
|
return ret
|
|
end
|
|
|
|
|
|
----------------------------------
|
|
-- Tables that are used at runtime
|
|
----------------------------------
|
|
|
|
-- Contains for hashed node positions how many step pounding uses are still needed
|
|
local pending_poundings = {}
|
|
|
|
|
|
---------------------------------
|
|
-- Basic helpers for registration
|
|
---------------------------------
|
|
|
|
local function get_mortar_nodebox(fill_num)
|
|
-- the mortar's sides are 2/16 high
|
|
-- we do not want the mortar to be filled completely => 1.8 / 16
|
|
-- there can be up to 3 seeds or layers oil in the mortar => / 3
|
|
local fill_offset = fill_num * (1.8 / 16 / 3)
|
|
return {
|
|
type = "fixed",
|
|
fixed = {
|
|
{-3/16, -0.5, -3/16, 3/16, -7/16 + fill_offset, 3/16}, -- ground plate + filling
|
|
{-1/4, -7/16, -3/16, -3/16, -5/16, 3/16}, -- 4 sides
|
|
{-3/16, -7/16, -1/4, 3/16, -5/16, -3/16},
|
|
{3/16, -7/16, -3/16, 1/4, -5/16, 3/16},
|
|
{-3/16, -7/16, 3/16, 3/16, -5/16, 1/4}
|
|
},
|
|
}
|
|
end
|
|
|
|
local mortar_box_simple = {
|
|
type = "fixed",
|
|
fixed = {-1/4, -0.5, -1/4, 1/4, -5/16, 1/4},
|
|
}
|
|
|
|
local function mortar_on_flood(pos)
|
|
-- drop the mortar as item
|
|
pos = vector.new(pos)
|
|
pos.y = pos.y - 0.3
|
|
minetest.add_item(pos, "farming:mortar")
|
|
end
|
|
|
|
local function poundable_mortar_on_destruct(pos)
|
|
-- remove the entry in pending_poundings
|
|
local pos_hash = minetest.hash_node_position(pos)
|
|
pending_poundings[pos_hash] = nil
|
|
end
|
|
|
|
|
|
----------------------------------------------
|
|
-- Function for using the pestle on the mortar
|
|
----------------------------------------------
|
|
|
|
local function pestle_on_use(itemstack, user, pointed_thing)
|
|
if pointed_thing.type ~= "node" then
|
|
return
|
|
end
|
|
|
|
local pos = pointed_thing.under
|
|
local node = minetest.get_node(pos)
|
|
-- find out if the node is a mortar and get its pounding target
|
|
local target = pound_with_pestle[node.name]
|
|
if not target then
|
|
return
|
|
end
|
|
|
|
-- check for protection
|
|
local user_name = user and minetest.is_player(user) and
|
|
user:get_player_name() or ""
|
|
if minetest.is_protected(pos, user_name) then
|
|
return
|
|
end
|
|
|
|
-- get how often the player still has to use the pestle
|
|
local pos_hash = minetest.hash_node_position(pos)
|
|
local remaining_hits = pending_poundings[pos_hash]
|
|
-- if not found, generate new amount from specs
|
|
remaining_hits = remaining_hits or get_num_poundings(target)
|
|
remaining_hits = remaining_hits - 1
|
|
if remaining_hits == 0 then
|
|
-- replace with target node
|
|
node.name = target.after
|
|
minetest.swap_node(pos, node)
|
|
-- clean up
|
|
pending_poundings[pos_hash] = nil
|
|
else
|
|
-- write back
|
|
pending_poundings[pos_hash] = remaining_hits
|
|
end
|
|
|
|
minetest.sound_play({name = "default_hard_footstep", gain = 1.0},
|
|
{pos = pos}, true)
|
|
-- add tool wear
|
|
if not minetest.global_exists("creative") or
|
|
not creative.is_enabled_for(user_name) then
|
|
itemstack:add_wear(1024)
|
|
if itemstack:is_empty() then
|
|
-- item broke
|
|
minetest.sound_play("default_tool_breaks", {pos = pos, gain = 0.5},
|
|
true)
|
|
end
|
|
end
|
|
return itemstack
|
|
end
|
|
|
|
|
|
--------------------------
|
|
-- Mortar and Pestle Items
|
|
--------------------------
|
|
|
|
-- the empty mortar
|
|
minetest.register_node("farming:mortar", {
|
|
description = "Mortar",
|
|
groups = {cracky = 3},
|
|
stack_max = 16,
|
|
drawtype = "nodebox",
|
|
tiles = {"default_clay.png"},
|
|
paramtype = "light",
|
|
paramtype2 = "none",
|
|
is_ground_content = false,
|
|
floodable = true,
|
|
node_box = get_mortar_nodebox(0),
|
|
selection_box = mortar_box_simple,
|
|
collision_box = mortar_box_simple,
|
|
sounds = default.node_sound_stone_defaults(),
|
|
on_flood = mortar_on_flood,
|
|
})
|
|
|
|
-- filled mortars
|
|
for _, item in ipairs({"rapeseed", "rapeseed_oil"}) do
|
|
local top_tile, on_destruct
|
|
|
|
if item == "rapeseed" then
|
|
top_tile = "farming_rapeseed_in_mortar.png"
|
|
on_destruct = poundable_mortar_on_destruct
|
|
else
|
|
top_tile = "(farming_rapeseed_oil.png^[mask:farming_mortar_mask.png)"
|
|
end
|
|
top_tile = "default_clay.png^" .. top_tile
|
|
|
|
for fillstate = 1, 3 do
|
|
minetest.register_node(string.format("farming:mortar_with_%i_%s", fillstate,
|
|
item), {
|
|
groups = {cracky = 3, not_in_creative_inventory = 1},
|
|
drawtype = "nodebox",
|
|
tiles = {top_tile, "default_clay.png"},
|
|
paramtype = "light",
|
|
paramtype2 = "none",
|
|
is_ground_content = false,
|
|
floodable = true,
|
|
node_box = get_mortar_nodebox(fillstate),
|
|
selection_box = mortar_box_simple,
|
|
collision_box = mortar_box_simple,
|
|
sounds = default.node_sound_stone_defaults(),
|
|
drop = "farming:mortar",
|
|
on_flood = mortar_on_flood,
|
|
on_destruct = on_destruct,
|
|
})
|
|
end
|
|
end
|
|
|
|
minetest.register_tool("farming:pestle", {
|
|
description = "Pestle",
|
|
groups = {},
|
|
inventory_image = "farming_pestle.png",
|
|
wield_image = "farming_pestle.png^[transformR270",
|
|
stack_max = 1,
|
|
range = 2.0,
|
|
sound = {breaks = "default_tool_breaks"},
|
|
tool_capabilities = {
|
|
full_punch_interval = 1.0,
|
|
max_drop_level = 0,
|
|
groupcaps = {},
|
|
damage_groups = {},
|
|
},
|
|
on_use = pestle_on_use,
|
|
})
|
|
|
|
|
|
------------------------------------------
|
|
-- Overrides for seed and glass bottle
|
|
-- (for putting into / taking from mortar)
|
|
------------------------------------------
|
|
|
|
-- implement putting seeds into the mortar
|
|
local old_rapeseed_on_place = minetest.registered_items["farming:rapeseed"].on_place
|
|
minetest.override_item("farming:rapeseed", {
|
|
node_placement_prediction = "", -- deactivate prediction (it looks bad)
|
|
|
|
on_place = function(itemstack, placer, pointed_thing)
|
|
if pointed_thing.type ~= "node" then
|
|
return old_rapeseed_on_place(itemstack, placer, pointed_thing)
|
|
end
|
|
|
|
-- do protection checks and check if mortar is clicked
|
|
local pos = pointed_thing.under
|
|
local node = minetest.get_node(pos)
|
|
local new_node_name = put_seed_into_mortar[node.name]
|
|
|
|
local placer_name = placer and minetest.is_player(placer) and
|
|
placer:get_player_name() or ""
|
|
|
|
if minetest.is_protected(pos, placer_name) or not new_node_name then
|
|
return old_rapeseed_on_place(itemstack, placer, pointed_thing)
|
|
end
|
|
|
|
-- replace the node
|
|
node.name = new_node_name
|
|
minetest.swap_node(pos, node)
|
|
|
|
-- clear pending_poundings (the player has to start over)
|
|
pending_poundings[minetest.hash_node_position(pos)] = nil
|
|
|
|
-- remove the seed from inventory
|
|
if not minetest.global_exists("creative") or
|
|
not creative.is_enabled_for(placer_name) then
|
|
itemstack:take_item()
|
|
end
|
|
return itemstack
|
|
end,
|
|
})
|
|
|
|
-- implement taking oil from the mortar with glass bottle
|
|
local old_glass_bottle_on_use = minetest.registered_items["vessels:glass_bottle"].on_use
|
|
or function(itemstack, user, pointed_thing)
|
|
-- default behaviour when leftclicking with item
|
|
if pointed_thing.type == "object" then
|
|
pointed_thing.ref:punch(user, 1.0, {full_punch_interval = 1.0}, nil)
|
|
return user:get_wielded_item()
|
|
elseif pointed_thing.type == "node" then
|
|
local node = minetest.get_node(pointed_thing.under)
|
|
local node_def = minetest.registered_nodes[node.name]
|
|
if node_def then
|
|
node_def.on_punch(pointed_thing.under, node, user, pointed_thing)
|
|
end
|
|
return user:get_wielded_item()
|
|
end
|
|
end
|
|
minetest.override_item("vessels:glass_bottle", {
|
|
on_use = function(itemstack, user, pointed_thing)
|
|
if pointed_thing.type ~= "node" then
|
|
return old_glass_bottle_on_use(itemstack, user, pointed_thing)
|
|
end
|
|
|
|
-- do protection checks and check if mortar is clicked
|
|
local pos = pointed_thing.under
|
|
local node = minetest.get_node(pos)
|
|
local new_node_name = take_oil_from_mortar[node.name]
|
|
|
|
local user_is_player = user and minetest.is_player(user)
|
|
local user_name = user_is_player and user:get_player_name() or ""
|
|
|
|
if minetest.is_protected(pos, user_name) or not new_node_name then
|
|
return old_glass_bottle_on_use(itemstack, user, pointed_thing)
|
|
end
|
|
|
|
-- replace the node
|
|
node.name = new_node_name
|
|
minetest.swap_node(pos, node)
|
|
|
|
-- fill the bottle
|
|
local creative_enabled = minetest.global_exists("creative") and
|
|
creative.is_enabled_for(user_name)
|
|
local item_count = itemstack:get_count()
|
|
-- try to replace
|
|
if item_count == 1 and not creative_enabled then
|
|
itemstack:set_name("farming:glass_bottle_with_rapeseed_oil")
|
|
return itemstack
|
|
end
|
|
-- do not take in creative
|
|
if not creative_enabled then
|
|
itemstack:take_item()
|
|
end
|
|
-- add full bottle to inventory or drop it
|
|
local full_bottle = ItemStack("farming:glass_bottle_with_rapeseed_oil")
|
|
if user_is_player then
|
|
local inv = user:get_inventory()
|
|
if inv then
|
|
full_bottle = inv:add_item("main", full_bottle)
|
|
end
|
|
end
|
|
if not full_bottle:is_empty() then
|
|
-- no space => drop full bottle
|
|
minetest.add_item(pos, full_bottle)
|
|
end
|
|
return itemstack
|
|
end,
|
|
})
|
|
|
|
|
|
-------------
|
|
-- Craftitems
|
|
-------------
|
|
|
|
minetest.register_craftitem("farming:raw_mortar", {
|
|
description = "Raw Mortar",
|
|
groups = {},
|
|
inventory_image = "farming_raw_mortar.png",
|
|
stack_max = 16,
|
|
})
|
|
|
|
minetest.register_craftitem("farming:raw_pestle", {
|
|
description = "Raw Pestle",
|
|
groups = {},
|
|
inventory_image = "farming_raw_pestle.png",
|
|
stack_max = 1,
|
|
})
|
|
|
|
minetest.register_craftitem("farming:glass_bottle_with_rapeseed_oil", {
|
|
description = "Bottle with Rapeseed Oil",
|
|
groups = {},
|
|
inventory_image = "farming_rapeseed_oil.png^[mask:vessels_glass_bottle_liquidmask.png"
|
|
.. "^vessels_glass_bottle.png",
|
|
on_use = minetest.item_eat(3, "vessels:glass_bottle"),
|
|
})
|
|
|
|
|
|
-----------
|
|
-- Crafting
|
|
-----------
|
|
|
|
minetest.register_craft({
|
|
output = "farming:raw_mortar",
|
|
recipe = {
|
|
{"default:clay_lump", "", "default:clay_lump"},
|
|
{"", "default:clay_lump", ""},
|
|
},
|
|
})
|
|
|
|
minetest.register_craft({
|
|
type = "cooking",
|
|
output = "farming:mortar",
|
|
recipe = "farming:raw_mortar",
|
|
cooktime = 3,
|
|
})
|
|
|
|
minetest.register_craft({
|
|
output = "farming:raw_pestle",
|
|
recipe = {
|
|
{"default:clay_lump"},
|
|
{"default:clay_lump"},
|
|
},
|
|
})
|
|
|
|
minetest.register_craft({
|
|
type = "cooking",
|
|
output = "farming:pestle",
|
|
recipe = "farming:raw_pestle",
|
|
cooktime = 3,
|
|
})
|
|
|
|
minetest.register_craft({
|
|
type = "fuel",
|
|
recipe = "farming:glass_bottle_with_rapeseed_oil",
|
|
burntime = 13,
|
|
replacements = {{"farming:glass_bottle_with_rapeseed_oil", "vessels:glass_bottle"}},
|
|
})
|
|
|
|
minetest.register_craft({
|
|
output = "default:torch 4",
|
|
recipe = {
|
|
{"farming:glass_bottle_with_rapeseed_oil"},
|
|
{"farming:cotton"},
|
|
{"group:stick"},
|
|
},
|
|
replacements = {{"farming:glass_bottle_with_rapeseed_oil", "vessels:glass_bottle"}},
|
|
})
|