Quarry: Improve digging behaviour
Quarry now digs nodes like a player. Additionally, some possible causes for crashes are fixed. E.g. the `inv` in the `after_dig_node` callbacks were not guaranteed to exist. Please note that TA4 batteries that were dug before this change are considered as full.
This commit is contained in:
parent
21d73a307f
commit
0375cb1480
@ -157,23 +157,6 @@ local function mark_area(pos1, pos2, owner)
|
|||||||
pos1.y = pos1.y - 0.2
|
pos1.y = pos1.y - 0.2
|
||||||
end
|
end
|
||||||
|
|
||||||
local function peek_node(qpos)
|
|
||||||
local node = techage.get_node_lvm(qpos)
|
|
||||||
local ndef = minetest.registered_nodes[node.name]
|
|
||||||
if techage.can_node_dig(node, ndef) then
|
|
||||||
return techage.dropped_node(node, ndef)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function add_to_inv(pos, item_name)
|
|
||||||
local inv = M(pos):get_inventory()
|
|
||||||
if inv:room_for_item("main", item_name) then
|
|
||||||
inv:add_item("main", item_name)
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
local function quarry_task(pos, crd, nvm)
|
local function quarry_task(pos, crd, nvm)
|
||||||
nvm.start_level = nvm.start_level or 0
|
nvm.start_level = nvm.start_level or 0
|
||||||
nvm.quarry_depth = nvm.quarry_depth or 1
|
nvm.quarry_depth = nvm.quarry_depth or 1
|
||||||
@ -182,6 +165,30 @@ local function quarry_task(pos, crd, nvm)
|
|||||||
local y_last = y_first - nvm.quarry_depth + 1
|
local y_last = y_first - nvm.quarry_depth + 1
|
||||||
local facedir = minetest.get_node(pos).param2
|
local facedir = minetest.get_node(pos).param2
|
||||||
local owner = M(pos):get_string("owner")
|
local owner = M(pos):get_string("owner")
|
||||||
|
local fake_player = techage.Fake_player:new()
|
||||||
|
fake_player.get_pos = function (...)
|
||||||
|
return pos
|
||||||
|
end
|
||||||
|
fake_player.get_inventory = function(...)
|
||||||
|
return M(pos):get_inventory()
|
||||||
|
end
|
||||||
|
|
||||||
|
local add_to_inv = function(itemstacks)
|
||||||
|
local at_least_one_added = false
|
||||||
|
local inv = M(pos):get_inventory()
|
||||||
|
if #itemstacks == 0 then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
for _,stack in ipairs(itemstacks) do
|
||||||
|
if inv:room_for_item("main", stack) then
|
||||||
|
inv:add_item("main", stack)
|
||||||
|
at_least_one_added = true
|
||||||
|
elseif at_least_one_added then
|
||||||
|
minetest.add_item({x=pos.x,y=pos.y+1,z=pos.z}, stack)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return at_least_one_added
|
||||||
|
end
|
||||||
|
|
||||||
local pos1, pos2 = get_corner_positions(pos, facedir, nvm.hole_diameter)
|
local pos1, pos2 = get_corner_positions(pos, facedir, nvm.hole_diameter)
|
||||||
nvm.level = 1
|
nvm.level = 1
|
||||||
@ -203,14 +210,13 @@ local function quarry_task(pos, crd, nvm)
|
|||||||
for zoffs = 1, nvm.hole_diameter do
|
for zoffs = 1, nvm.hole_diameter do
|
||||||
for xoffs = 1, nvm.hole_diameter do
|
for xoffs = 1, nvm.hole_diameter do
|
||||||
local qpos = get_quarry_pos(pos1, xoffs, zoffs)
|
local qpos = get_quarry_pos(pos1, xoffs, zoffs)
|
||||||
local item_name = peek_node(qpos)
|
local dig_state = techage.dig_like_player(qpos, fake_player, add_to_inv)
|
||||||
if item_name then
|
|
||||||
if add_to_inv(pos, item_name) then
|
if dig_state == techage.dig_states.INV_FULL then
|
||||||
minetest.remove_node(qpos)
|
|
||||||
crd.State:keep_running(pos, nvm, COUNTDOWN_TICKS)
|
|
||||||
else
|
|
||||||
crd.State:blocked(pos, nvm, S("inventory full"))
|
crd.State:blocked(pos, nvm, S("inventory full"))
|
||||||
end
|
coroutine.yield()
|
||||||
|
elseif dig_state == techage.dig_states.DUG then
|
||||||
|
crd.State:keep_running(pos, nvm, COUNTDOWN_TICKS)
|
||||||
coroutine.yield()
|
coroutine.yield()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -229,7 +235,10 @@ local function keep_running(pos, elapsed)
|
|||||||
|
|
||||||
local nvm = techage.get_nvm(pos)
|
local nvm = techage.get_nvm(pos)
|
||||||
local crd = CRD(pos)
|
local crd = CRD(pos)
|
||||||
coroutine.resume(mem.co, pos, crd, nvm)
|
local _, err = coroutine.resume(mem.co, pos, crd, nvm)
|
||||||
|
if err then
|
||||||
|
minetest.log("error", "[TA4 Quarry Coroutine Error]" .. err)
|
||||||
|
end
|
||||||
|
|
||||||
if techage.is_activeformspec(pos) then
|
if techage.is_activeformspec(pos) then
|
||||||
M(pos):set_string("formspec", formspec(crd.State, pos, nvm))
|
M(pos):set_string("formspec", formspec(crd.State, pos, nvm))
|
||||||
|
118
basis/fake_player.lua
Normal file
118
basis/fake_player.lua
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
--[[
|
||||||
|
|
||||||
|
TechAge
|
||||||
|
=======
|
||||||
|
|
||||||
|
Copyright (C) 2019-2020 Joachim Stolberg
|
||||||
|
Copyright (C) 2020 Thomas S.
|
||||||
|
|
||||||
|
GPL v3
|
||||||
|
See LICENSE.txt for more information
|
||||||
|
|
||||||
|
Fake Player
|
||||||
|
|
||||||
|
]]--
|
||||||
|
|
||||||
|
-- Map method names to their return values
|
||||||
|
local methods = {
|
||||||
|
get_pos = { x = 0, y = 0, z = 0 },
|
||||||
|
set_pos = nil,
|
||||||
|
moveto = nil,
|
||||||
|
punch = nil,
|
||||||
|
right_click = nil,
|
||||||
|
get_hp = 20,
|
||||||
|
set_hp = nil,
|
||||||
|
get_inventory = nil,
|
||||||
|
get_wield_list = "",
|
||||||
|
get_wield_index = 0,
|
||||||
|
get_wielded_item = ItemStack(),
|
||||||
|
set_wielded_item = true,
|
||||||
|
set_armor_groups = nil,
|
||||||
|
get_armor_groups = {},
|
||||||
|
set_animation = nil,
|
||||||
|
get_animation = {},
|
||||||
|
set_animation_frame_speed = nil,
|
||||||
|
set_attach = nil,
|
||||||
|
get_attach = nil,
|
||||||
|
set_detach = nil,
|
||||||
|
get_bone_position = {},
|
||||||
|
set_properties = nil,
|
||||||
|
get_properties = {},
|
||||||
|
is_player = false,
|
||||||
|
get_nametag_attributes = {},
|
||||||
|
set_nametag_attributes = nil,
|
||||||
|
get_player_name = "",
|
||||||
|
get_player_velocity = nil,
|
||||||
|
add_player_velocity = nil,
|
||||||
|
get_look_dir = vector.new(0, 0, 1),
|
||||||
|
get_look_vertical = 0,
|
||||||
|
get_look_horizontal = 0,
|
||||||
|
set_look_vertical = nil,
|
||||||
|
set_look_horizontal = nil,
|
||||||
|
get_look_pitch = 0,
|
||||||
|
get_look_yaw = 0,
|
||||||
|
set_look_pitch = nil,
|
||||||
|
set_look_yaw = nil,
|
||||||
|
get_breath = 10,
|
||||||
|
set_breath = nil,
|
||||||
|
set_fov = nil,
|
||||||
|
get_fov = 0,
|
||||||
|
set_attribute = nil,
|
||||||
|
get_attribute = nil,
|
||||||
|
get_meta = nil,
|
||||||
|
set_inventory_formspec = nil,
|
||||||
|
get_inventory_formspec = "",
|
||||||
|
set_formspec_prepend = nil,
|
||||||
|
get_formspec_prepend = "",
|
||||||
|
get_player_control = {},
|
||||||
|
get_player_control_bits = 0,
|
||||||
|
set_physics_override = nil,
|
||||||
|
get_physics_override = {},
|
||||||
|
hud_add = 0,
|
||||||
|
hud_remove = nil,
|
||||||
|
hud_change = nil,
|
||||||
|
hud_get = {},
|
||||||
|
hud_set_flags = nil,
|
||||||
|
hud_get_flags = {},
|
||||||
|
hud_set_hotbar_itemcount = nil,
|
||||||
|
hud_get_hotbar_itemcount = 8,
|
||||||
|
hud_set_hotbar_image = nil,
|
||||||
|
hud_get_hotbar_image = "",
|
||||||
|
hud_set_hotbar_selected_image = nil,
|
||||||
|
hud_get_hotbar_selected_image = "",
|
||||||
|
set_sky = nil,
|
||||||
|
get_sky = {},
|
||||||
|
get_sky_color = {},
|
||||||
|
set_sun = nil,
|
||||||
|
get_sun = {},
|
||||||
|
set_moon = nil,
|
||||||
|
get_moon = {},
|
||||||
|
set_stars = nil,
|
||||||
|
get_stars = {},
|
||||||
|
set_clouds = nil,
|
||||||
|
get_clouds = {},
|
||||||
|
override_day_night_ratio = nil,
|
||||||
|
get_day_night_ratio = nil,
|
||||||
|
set_local_animation = nil,
|
||||||
|
get_local_animation = {},
|
||||||
|
set_eye_offset = nil,
|
||||||
|
get_eye_offset = {},
|
||||||
|
send_mapblock = nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
techage.Fake_player = {}
|
||||||
|
techage.Fake_player.__index = techage.Fake_player
|
||||||
|
|
||||||
|
function techage.Fake_player:new()
|
||||||
|
local fake_player = {}
|
||||||
|
setmetatable(fake_player, techage.Fake_player)
|
||||||
|
return fake_player
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
for method_name, return_value in pairs(methods) do
|
||||||
|
techage.Fake_player[method_name] = function(self, ...)
|
||||||
|
return return_value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -142,6 +142,43 @@ function techage.can_node_dig(node, ndef)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
techage.dig_states = {
|
||||||
|
NOT_DIGGABLE = 1,
|
||||||
|
INV_FULL = 2,
|
||||||
|
DUG = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Digs a node like a player would by utilizing a fake player object.
|
||||||
|
-- add_to_inv(itemstacks) is a method that should try to add the dropped stacks to an appropriate inventory.
|
||||||
|
-- The node will only be dug, if add_to_inv(itemstacks) returns true.
|
||||||
|
function techage.dig_like_player(pos, fake_player, add_to_inv)
|
||||||
|
local node = techage.get_node_lvm(pos)
|
||||||
|
local ndef = minetest.registered_nodes[node.name]
|
||||||
|
if not ndef or ndef.diggable == false or (ndef.can_dig and not ndef.can_dig(pos, fake_player)) then
|
||||||
|
return techage.dig_states.NOT_DIGGABLE
|
||||||
|
end
|
||||||
|
local drop_as_strings = minetest.get_node_drops(node)
|
||||||
|
local drop_as_stacks = {}
|
||||||
|
for _,itemstring in ipairs(drop_as_strings) do
|
||||||
|
drop_as_stacks[#drop_as_stacks+1] = ItemStack(itemstring)
|
||||||
|
end
|
||||||
|
local meta = M(pos)
|
||||||
|
if ndef.preserve_metadata then
|
||||||
|
ndef.preserve_metadata(pos, node, meta, drop_as_stacks)
|
||||||
|
end
|
||||||
|
|
||||||
|
if add_to_inv(drop_as_stacks) then
|
||||||
|
local oldmeta = meta:to_table()
|
||||||
|
minetest.remove_node(pos)
|
||||||
|
|
||||||
|
if ndef.after_dig_node then
|
||||||
|
ndef.after_dig_node(pos, node, oldmeta, fake_player)
|
||||||
|
end
|
||||||
|
return techage.dig_states.DUG
|
||||||
|
end
|
||||||
|
return techage.dig_states.INV_FULL
|
||||||
|
end
|
||||||
|
|
||||||
local function handle_drop(drop)
|
local function handle_drop(drop)
|
||||||
-- To keep it simple, return only the item with the lowest rarity
|
-- To keep it simple, return only the item with the lowest rarity
|
||||||
if drop.items then
|
if drop.items then
|
||||||
|
@ -141,7 +141,7 @@ techage.register_consumer("digtron_battery", S("Digtron Battery"), { act = tiles
|
|||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
preserve_metadata = function(pos, oldnode, oldmetadata, drops)
|
preserve_metadata = function(pos, oldnode, oldmetadata, drops)
|
||||||
metadata = M(pos):to_table()
|
local metadata = M(pos):to_table()
|
||||||
if metadata.inventory then
|
if metadata.inventory then
|
||||||
local total = count_coal(metadata)
|
local total = count_coal(metadata)
|
||||||
local meta = drops[1]:get_meta()
|
local meta = drops[1]:get_meta()
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
-- for lazy programmers
|
-- for lazy programmers
|
||||||
local M = minetest.get_meta
|
local M = minetest.get_meta
|
||||||
local S = techage.S
|
local S = techage.S
|
||||||
local logic = techage.logic
|
|
||||||
local BATTERY_CAPACITY = 10000000
|
local BATTERY_CAPACITY = 10000000
|
||||||
|
|
||||||
local function calc_percent(content)
|
local function calc_percent(content)
|
||||||
@ -36,9 +35,12 @@ local function on_timer(pos, elapsed)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
local function register_battery(ext, percent, nici)
|
minetest.register_alias("techage:ta4_battery75", "techage:ta4_battery")
|
||||||
minetest.register_node("techage:ta4_battery"..ext, {
|
minetest.register_alias("techage:ta4_battery50", "techage:ta4_battery")
|
||||||
description = S("Battery").." "..ext,
|
minetest.register_alias("techage:ta4_battery25", "techage:ta4_battery")
|
||||||
|
|
||||||
|
minetest.register_node("techage:ta4_battery", {
|
||||||
|
description = S("Battery"),
|
||||||
inventory_image = 'techage_battery_inventory.png',
|
inventory_image = 'techage_battery_inventory.png',
|
||||||
wield_image = 'techage_battery_inventory.png',
|
wield_image = 'techage_battery_inventory.png',
|
||||||
tiles = {
|
tiles = {
|
||||||
@ -59,50 +61,43 @@ local function register_battery(ext, percent, nici)
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
after_place_node = function(pos, placer)
|
after_place_node = function(pos, placer, itemstack)
|
||||||
local meta = minetest.get_meta(pos)
|
local content = BATTERY_CAPACITY
|
||||||
meta:set_int("content", BATTERY_CAPACITY * percent)
|
if itemstack then
|
||||||
local node = minetest.get_node(pos)
|
local stack_meta = itemstack:get_meta()
|
||||||
node.name = "techage:ta4_battery"
|
if stack_meta then
|
||||||
minetest.swap_node(pos, node)
|
-- This ensures that dug batteries of the old system are considered full.
|
||||||
|
local string_content = stack_meta:get_string("content")
|
||||||
|
if string_content ~= "" then
|
||||||
|
-- Batteries dug in the new system are handled correctly.
|
||||||
|
content = techage.in_range(stack_meta:get_int("content"), 0, BATTERY_CAPACITY)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
M(pos):set_int("content", content)
|
||||||
on_timer(pos, 1)
|
on_timer(pos, 1)
|
||||||
minetest.get_node_timer(pos):start(30)
|
minetest.get_node_timer(pos):start(30)
|
||||||
end,
|
end,
|
||||||
|
|
||||||
on_timer = on_timer,
|
on_timer = on_timer,
|
||||||
|
|
||||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
preserve_metadata = function(pos, oldnode, oldmetadata, drops)
|
||||||
local percent = calc_percent(tonumber(oldmetadata.fields.content))
|
local content = M(pos):get_int("content")
|
||||||
local stack
|
|
||||||
if percent > 95 then
|
local meta = drops[1]:get_meta()
|
||||||
stack = ItemStack("techage:ta4_battery")
|
meta:set_int("content", content)
|
||||||
elseif percent > 75 then
|
local percent = calc_percent(content)
|
||||||
stack = ItemStack("techage:ta4_battery75")
|
local text = S("Digtron Battery").." ("..percent.." %)"
|
||||||
elseif percent > 50 then
|
meta:set_string("description", text)
|
||||||
stack = ItemStack("techage:ta4_battery50")
|
|
||||||
elseif percent > 25 then
|
|
||||||
stack = ItemStack("techage:ta4_battery25")
|
|
||||||
else
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local inv = minetest.get_inventory({type="player", name=digger:get_player_name()})
|
|
||||||
inv:add_item("main", stack)
|
|
||||||
end,
|
end,
|
||||||
|
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
sunlight_propagates = true,
|
sunlight_propagates = true,
|
||||||
paramtype2 = "facedir",
|
paramtype2 = "facedir",
|
||||||
groups = {choppy=1, cracky=1, crumbly=1, not_in_creative_inventory=nici},
|
groups = {choppy=1, cracky=1, crumbly=1, not_in_creative_inventory=nici},
|
||||||
drop = "",
|
|
||||||
is_ground_content = false,
|
is_ground_content = false,
|
||||||
sounds = default.node_sound_stone_defaults(),
|
sounds = default.node_sound_stone_defaults(),
|
||||||
})
|
})
|
||||||
end
|
|
||||||
|
|
||||||
register_battery("", 1.0, 0)
|
|
||||||
register_battery("75", 0.75, 1)
|
|
||||||
register_battery("50", 0.5, 1)
|
|
||||||
register_battery("25", 0.25, 1)
|
|
||||||
|
|
||||||
minetest.register_node("techage:ta4_battery_empty", {
|
minetest.register_node("techage:ta4_battery_empty", {
|
||||||
description = S("Battery"),
|
description = S("Battery"),
|
||||||
@ -159,8 +154,7 @@ else
|
|||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
techage.register_node({"techage:ta4_battery", "techage:ta4_battery25",
|
techage.register_node({"techage:ta4_battery"},
|
||||||
"techage:ta4_battery50", "techage:ta4_battery75"},
|
|
||||||
{
|
{
|
||||||
on_node_load = function(pos)
|
on_node_load = function(pos)
|
||||||
minetest.get_node_timer(pos):start(30)
|
minetest.get_node_timer(pos):start(30)
|
||||||
|
1
init.lua
1
init.lua
@ -66,6 +66,7 @@ end
|
|||||||
-- Basis features
|
-- Basis features
|
||||||
local MP = minetest.get_modpath("techage")
|
local MP = minetest.get_modpath("techage")
|
||||||
dofile(MP.."/basis/lib.lua") -- helper functions
|
dofile(MP.."/basis/lib.lua") -- helper functions
|
||||||
|
dofile(MP.."/basis/fake_player.lua") -- dummy player object
|
||||||
dofile(MP.."/basis/node_store.lua")
|
dofile(MP.."/basis/node_store.lua")
|
||||||
dofile(MP.."/basis/gravel_lib.lua") -- ore probability
|
dofile(MP.."/basis/gravel_lib.lua") -- ore probability
|
||||||
dofile(MP.."/basis/node_states.lua") -- state model
|
dofile(MP.."/basis/node_states.lua") -- state model
|
||||||
|
@ -120,19 +120,15 @@ local function get_capa(itemstack)
|
|||||||
return 0
|
return 0
|
||||||
end
|
end
|
||||||
|
|
||||||
local function set_capa(pos, oldnode, digger, capa)
|
local function set_capa(pos, oldnode, oldmetadata, drops)
|
||||||
local node = ItemStack(oldnode.name)
|
local nvm = techage.get_nvm(pos)
|
||||||
local meta = node:get_meta()
|
local capa = nvm.capa
|
||||||
|
local meta = drops[1]:get_meta()
|
||||||
capa = techage.power.percent(PWR_CAPA, capa)
|
capa = techage.power.percent(PWR_CAPA, capa)
|
||||||
capa = (math.floor((capa or 0) / 5)) * 5
|
capa = (math.floor((capa or 0) / 5)) * 5
|
||||||
meta:set_int("capa", capa)
|
meta:set_int("capa", capa)
|
||||||
local text = S("TA3 Accu Box").." ("..capa.." %)"
|
local text = S("TA3 Accu Box").." ("..capa.." %)"
|
||||||
meta:set_string("description", text)
|
meta:set_string("description", text)
|
||||||
local inv = minetest.get_inventory({type="player", name=digger:get_player_name()})
|
|
||||||
local left_over = inv:add_item("main", node)
|
|
||||||
if left_over:get_count() > 0 then
|
|
||||||
minetest.add_item(pos, node)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function after_place_node(pos, placer, itemstack)
|
local function after_place_node(pos, placer, itemstack)
|
||||||
@ -149,9 +145,7 @@ local function after_place_node(pos, placer, itemstack)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function after_dig_node(pos, oldnode, oldmetadata, digger)
|
local function after_dig_node(pos, oldnode, oldmetadata, digger)
|
||||||
local nvm = techage.get_nvm(pos)
|
|
||||||
Cable:after_dig_node(pos)
|
Cable:after_dig_node(pos)
|
||||||
set_capa(pos, oldnode, digger, nvm.capa)
|
|
||||||
techage.del_mem(pos)
|
techage.del_mem(pos)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -188,13 +182,12 @@ minetest.register_node("techage:ta3_akku", {
|
|||||||
after_dig_node = after_dig_node,
|
after_dig_node = after_dig_node,
|
||||||
tubelib2_on_update2 = tubelib2_on_update2,
|
tubelib2_on_update2 = tubelib2_on_update2,
|
||||||
networks = net_def,
|
networks = net_def,
|
||||||
|
|
||||||
drop = "", -- don't remove, item will be added via 'set_capa'
|
|
||||||
paramtype2 = "facedir",
|
paramtype2 = "facedir",
|
||||||
groups = {cracky=2, crumbly=2, choppy=2},
|
groups = {cracky=2, crumbly=2, choppy=2},
|
||||||
on_rotate = screwdriver.disallow,
|
on_rotate = screwdriver.disallow,
|
||||||
is_ground_content = false,
|
is_ground_content = false,
|
||||||
sounds = default.node_sound_wood_defaults(),
|
sounds = default.node_sound_wood_defaults(),
|
||||||
|
preserve_metadata = set_capa,
|
||||||
})
|
})
|
||||||
|
|
||||||
Cable:add_secondary_node_names({"techage:ta3_akku"})
|
Cable:add_secondary_node_names({"techage:ta3_akku"})
|
||||||
|
Loading…
Reference in New Issue
Block a user