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
|
||||
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)
|
||||
nvm.start_level = nvm.start_level or 0
|
||||
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 facedir = minetest.get_node(pos).param2
|
||||
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)
|
||||
nvm.level = 1
|
||||
@ -203,14 +210,13 @@ local function quarry_task(pos, crd, nvm)
|
||||
for zoffs = 1, nvm.hole_diameter do
|
||||
for xoffs = 1, nvm.hole_diameter do
|
||||
local qpos = get_quarry_pos(pos1, xoffs, zoffs)
|
||||
local item_name = peek_node(qpos)
|
||||
if item_name then
|
||||
if add_to_inv(pos, item_name) then
|
||||
minetest.remove_node(qpos)
|
||||
crd.State:keep_running(pos, nvm, COUNTDOWN_TICKS)
|
||||
else
|
||||
crd.State:blocked(pos, nvm, S("inventory full"))
|
||||
end
|
||||
local dig_state = techage.dig_like_player(qpos, fake_player, add_to_inv)
|
||||
|
||||
if dig_state == techage.dig_states.INV_FULL then
|
||||
crd.State:blocked(pos, nvm, S("inventory full"))
|
||||
coroutine.yield()
|
||||
elseif dig_state == techage.dig_states.DUG then
|
||||
crd.State:keep_running(pos, nvm, COUNTDOWN_TICKS)
|
||||
coroutine.yield()
|
||||
end
|
||||
end
|
||||
@ -229,7 +235,10 @@ local function keep_running(pos, elapsed)
|
||||
|
||||
local nvm = techage.get_nvm(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
|
||||
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
|
||||
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)
|
||||
-- To keep it simple, return only the item with the lowest rarity
|
||||
if drop.items then
|
||||
|
@ -141,7 +141,7 @@ techage.register_consumer("digtron_battery", S("Digtron Battery"), { act = tiles
|
||||
end
|
||||
end,
|
||||
preserve_metadata = function(pos, oldnode, oldmetadata, drops)
|
||||
metadata = M(pos):to_table()
|
||||
local metadata = M(pos):to_table()
|
||||
if metadata.inventory then
|
||||
local total = count_coal(metadata)
|
||||
local meta = drops[1]:get_meta()
|
||||
|
@ -15,7 +15,6 @@
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
local logic = techage.logic
|
||||
local BATTERY_CAPACITY = 10000000
|
||||
|
||||
local function calc_percent(content)
|
||||
@ -36,73 +35,69 @@ local function on_timer(pos, elapsed)
|
||||
return true
|
||||
end
|
||||
|
||||
local function register_battery(ext, percent, nici)
|
||||
minetest.register_node("techage:ta4_battery"..ext, {
|
||||
description = S("Battery").." "..ext,
|
||||
inventory_image = 'techage_battery_inventory.png',
|
||||
wield_image = 'techage_battery_inventory.png',
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_smartline.png",
|
||||
"techage_smartline.png",
|
||||
"techage_smartline.png",
|
||||
"techage_smartline.png",
|
||||
"techage_smartline.png",
|
||||
"techage_smartline.png^techage_battery_green.png",
|
||||
minetest.register_alias("techage:ta4_battery75", "techage:ta4_battery")
|
||||
minetest.register_alias("techage:ta4_battery50", "techage:ta4_battery")
|
||||
minetest.register_alias("techage:ta4_battery25", "techage:ta4_battery")
|
||||
|
||||
minetest.register_node("techage:ta4_battery", {
|
||||
description = S("Battery"),
|
||||
inventory_image = 'techage_battery_inventory.png',
|
||||
wield_image = 'techage_battery_inventory.png',
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_smartline.png",
|
||||
"techage_smartline.png",
|
||||
"techage_smartline.png",
|
||||
"techage_smartline.png",
|
||||
"techage_smartline.png",
|
||||
"techage_smartline.png^techage_battery_green.png",
|
||||
},
|
||||
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{ -6/32, -6/32, 14/32, 6/32, 6/32, 16/32},
|
||||
},
|
||||
},
|
||||
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{ -6/32, -6/32, 14/32, 6/32, 6/32, 16/32},
|
||||
},
|
||||
},
|
||||
|
||||
after_place_node = function(pos, placer)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_int("content", BATTERY_CAPACITY * percent)
|
||||
local node = minetest.get_node(pos)
|
||||
node.name = "techage:ta4_battery"
|
||||
minetest.swap_node(pos, node)
|
||||
on_timer(pos, 1)
|
||||
minetest.get_node_timer(pos):start(30)
|
||||
end,
|
||||
|
||||
on_timer = on_timer,
|
||||
|
||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
||||
local percent = calc_percent(tonumber(oldmetadata.fields.content))
|
||||
local stack
|
||||
if percent > 95 then
|
||||
stack = ItemStack("techage:ta4_battery")
|
||||
elseif percent > 75 then
|
||||
stack = ItemStack("techage:ta4_battery75")
|
||||
elseif percent > 50 then
|
||||
stack = ItemStack("techage:ta4_battery50")
|
||||
elseif percent > 25 then
|
||||
stack = ItemStack("techage:ta4_battery25")
|
||||
else
|
||||
return
|
||||
after_place_node = function(pos, placer, itemstack)
|
||||
local content = BATTERY_CAPACITY
|
||||
if itemstack then
|
||||
local stack_meta = itemstack:get_meta()
|
||||
if stack_meta then
|
||||
-- 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
|
||||
local inv = minetest.get_inventory({type="player", name=digger:get_player_name()})
|
||||
inv:add_item("main", stack)
|
||||
end,
|
||||
end
|
||||
M(pos):set_int("content", content)
|
||||
on_timer(pos, 1)
|
||||
minetest.get_node_timer(pos):start(30)
|
||||
end,
|
||||
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
paramtype2 = "facedir",
|
||||
groups = {choppy=1, cracky=1, crumbly=1, not_in_creative_inventory=nici},
|
||||
drop = "",
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
})
|
||||
end
|
||||
on_timer = on_timer,
|
||||
|
||||
register_battery("", 1.0, 0)
|
||||
register_battery("75", 0.75, 1)
|
||||
register_battery("50", 0.5, 1)
|
||||
register_battery("25", 0.25, 1)
|
||||
preserve_metadata = function(pos, oldnode, oldmetadata, drops)
|
||||
local content = M(pos):get_int("content")
|
||||
|
||||
local meta = drops[1]:get_meta()
|
||||
meta:set_int("content", content)
|
||||
local percent = calc_percent(content)
|
||||
local text = S("Digtron Battery").." ("..percent.." %)"
|
||||
meta:set_string("description", text)
|
||||
end,
|
||||
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
paramtype2 = "facedir",
|
||||
groups = {choppy=1, cracky=1, crumbly=1, not_in_creative_inventory=nici},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
})
|
||||
|
||||
minetest.register_node("techage:ta4_battery_empty", {
|
||||
description = S("Battery"),
|
||||
@ -159,8 +154,7 @@ else
|
||||
})
|
||||
end
|
||||
|
||||
techage.register_node({"techage:ta4_battery", "techage:ta4_battery25",
|
||||
"techage:ta4_battery50", "techage:ta4_battery75"},
|
||||
techage.register_node({"techage:ta4_battery"},
|
||||
{
|
||||
on_node_load = function(pos)
|
||||
minetest.get_node_timer(pos):start(30)
|
||||
|
1
init.lua
1
init.lua
@ -66,6 +66,7 @@ end
|
||||
-- Basis features
|
||||
local MP = minetest.get_modpath("techage")
|
||||
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/gravel_lib.lua") -- ore probability
|
||||
dofile(MP.."/basis/node_states.lua") -- state model
|
||||
|
@ -120,19 +120,15 @@ local function get_capa(itemstack)
|
||||
return 0
|
||||
end
|
||||
|
||||
local function set_capa(pos, oldnode, digger, capa)
|
||||
local node = ItemStack(oldnode.name)
|
||||
local meta = node:get_meta()
|
||||
local function set_capa(pos, oldnode, oldmetadata, drops)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local capa = nvm.capa
|
||||
local meta = drops[1]:get_meta()
|
||||
capa = techage.power.percent(PWR_CAPA, capa)
|
||||
capa = (math.floor((capa or 0) / 5)) * 5
|
||||
meta:set_int("capa", capa)
|
||||
local text = S("TA3 Accu Box").." ("..capa.." %)"
|
||||
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
|
||||
|
||||
local function after_place_node(pos, placer, itemstack)
|
||||
@ -149,9 +145,7 @@ local function after_place_node(pos, placer, itemstack)
|
||||
end
|
||||
|
||||
local function after_dig_node(pos, oldnode, oldmetadata, digger)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
Cable:after_dig_node(pos)
|
||||
set_capa(pos, oldnode, digger, nvm.capa)
|
||||
techage.del_mem(pos)
|
||||
end
|
||||
|
||||
@ -188,13 +182,12 @@ minetest.register_node("techage:ta3_akku", {
|
||||
after_dig_node = after_dig_node,
|
||||
tubelib2_on_update2 = tubelib2_on_update2,
|
||||
networks = net_def,
|
||||
|
||||
drop = "", -- don't remove, item will be added via 'set_capa'
|
||||
paramtype2 = "facedir",
|
||||
groups = {cracky=2, crumbly=2, choppy=2},
|
||||
on_rotate = screwdriver.disallow,
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
preserve_metadata = set_capa,
|
||||
})
|
||||
|
||||
Cable:add_secondary_node_names({"techage:ta3_akku"})
|
||||
|
Loading…
Reference in New Issue
Block a user