337 lines
11 KiB
Lua
337 lines
11 KiB
Lua
|
|
local dbg
|
|
if moddebug then dbg=moddebug.dbg("railcarts") else dbg={v1=function() end,v2=function() end,v3=function() end} end
|
|
|
|
boringcart = {}
|
|
|
|
-- TODO - a list of things that are 'safe' to dig. This is not in anyway
|
|
-- complete, and not an acceptable way to do this in any case.
|
|
local safediglist = {
|
|
"default:stone",
|
|
"default:gravel",
|
|
"default:clay",
|
|
"default:dirt",
|
|
"default:dirt_with_grass",
|
|
"default:dirt_with_snow",
|
|
"default:desert_stone",
|
|
"default:desert_sand",
|
|
"default:sand",
|
|
"default:stone_with_coal",
|
|
"default:stone_with_iron",
|
|
"default:stone_with_copper",
|
|
"default:stone_with_mese",
|
|
"default:stone_with_gold",
|
|
"default:stone_with_diamond",
|
|
"default:tree",
|
|
"default:leaves",
|
|
}
|
|
|
|
-- A table that indexes players against the last boring cart they right
|
|
-- clicked, so we can know which cart to apply changes to when form
|
|
-- fields are clicked. This seems mighty messy, but I don't see a better
|
|
-- way of doing it.
|
|
-- A hidden form field could work (if such a thing was possible) but in
|
|
-- any case, that would allow a client to subvert the contents and apply
|
|
-- changes to a different cart!
|
|
boringcart.lastcartformbyplayer = {}
|
|
|
|
minetest.register_on_player_receive_fields(
|
|
function(player, formname, fields)
|
|
if formname ~= "railcarts:boring_cart" then return end
|
|
if fields.quit then return end
|
|
|
|
local playername = player:get_player_name()
|
|
dbg.v3("Recieved boring cart form submit from "..playername.." with "..dump(fields))
|
|
local cart = boringcart.lastcartformbyplayer[playername]
|
|
if not cart then return end
|
|
|
|
if fields.dig then
|
|
if fields.dig == "true" then
|
|
cart.dig = true
|
|
else
|
|
cart.dig = false
|
|
end
|
|
end
|
|
|
|
if fields.safedig then
|
|
if fields.safedig == "true" then
|
|
cart.safedig = true
|
|
else
|
|
cart.safedig = false
|
|
end
|
|
end
|
|
|
|
if fields.bridge then
|
|
if fields.bridge == "true" then
|
|
cart.bridge = true
|
|
else
|
|
cart.bridge = false
|
|
end
|
|
end
|
|
|
|
if fields.lay then
|
|
if fields.lay == "true" then
|
|
cart.lay = true
|
|
else
|
|
cart.lay = false
|
|
end
|
|
end
|
|
|
|
if fields.slope then
|
|
if fields.slope == "Level" then
|
|
cart.digslope = 2
|
|
elseif fields.slope == "Up" then
|
|
cart.digslope = 1
|
|
elseif fields.slope == "Down" then
|
|
cart.digslope = 3
|
|
end
|
|
end
|
|
dbg.v1(playername.." set boring cart parameters dig:"..tostring(cart.dig)..
|
|
",safedig:"..tostring(cart.safedig)..
|
|
",bridge:"..tostring(cart.bridge)..",lay:"..
|
|
tostring(cart.lay)..",slope:"..cart.digslope)
|
|
|
|
boringcart.show_form(cart, player)
|
|
|
|
end
|
|
)
|
|
|
|
|
|
function boringcart.show_form(self, player)
|
|
local playername = player:get_player_name()
|
|
boringcart.lastcartformbyplayer[playername] = self
|
|
minetest.show_formspec(playername, "railcarts:boring_cart",
|
|
"size[10,12;]"..
|
|
"label[0,0;Boring cart cargo:]" ..
|
|
"list[detached:" .. self.inventoryname .. ";main;0,1;4,3;]"..
|
|
"label[6,0;Boring cart materials:]" ..
|
|
"list[detached:" .. self.inventoryname .. ";materials;6,1;4,3;]"..
|
|
"list[current_player;main;1,8;8,4;]"..
|
|
"checkbox[0,4;dig;Dig;"..tostring(self.dig).."]"..
|
|
"checkbox[2,4;bridge;Bridge;"..tostring(self.bridge).."]"..
|
|
"checkbox[4,4;lay;Lay;"..tostring(self.lay).."]"..
|
|
"checkbox[6,4;safedig;Safe;"..tostring(self.safedig).."]"..
|
|
"dropdown[0,5;3;slope;Up,Level,Down;"..self.digslope.."]")
|
|
end
|
|
|
|
function boringcart.on_end_of_rails(self, current_state, axis, oaxis, xz)
|
|
|
|
local laypos = vector.new(current_state.pos)
|
|
laypos[axis] = laypos [axis] + xz[axis]
|
|
|
|
-- Have we got a mese pick? Without one, there will be no digging.
|
|
local has_mesepick = self.inventory:contains_item("materials", "default:pick_mese 1")
|
|
|
|
if self.digslope == 3 then
|
|
laypos.y = laypos.y - 1
|
|
elseif self.digslope == 1 then
|
|
laypos.y = laypos.y + 1
|
|
end
|
|
laynode = minetest.get_node(laypos)
|
|
|
|
local laybelowpos = vector.new(laypos)
|
|
laybelowpos.y = laybelowpos.y -1
|
|
lbnode = minetest.get_node(laybelowpos)
|
|
|
|
local digposl
|
|
|
|
if self.dig and has_mesepick then
|
|
digposl = {}
|
|
|
|
-- If digging and bridging are enabled, we can avoid laying rails on
|
|
-- stuff that might fall
|
|
if self.dig and self.bridge then
|
|
if minetest.get_item_group(lbnode.name, "falling_node") ~= 0 then
|
|
table.insert(digposl, laybelowpos)
|
|
end
|
|
end
|
|
|
|
local nn
|
|
|
|
nn = vector.new(laypos)
|
|
table.insert(digposl, nn)
|
|
nn = vector.new(nn)
|
|
nn.y = nn.y + 1
|
|
table.insert(digposl, nn)
|
|
nn = vector.new(nn)
|
|
nn.y = nn.y + 1
|
|
table.insert(digposl, nn)
|
|
|
|
nn = vector.new(laypos)
|
|
nn[oaxis] = nn[oaxis] - 1
|
|
table.insert(digposl, nn)
|
|
nn = vector.new(nn)
|
|
nn.y = nn.y + 1
|
|
table.insert(digposl, nn)
|
|
nn = vector.new(nn)
|
|
nn.y = nn.y + 1
|
|
table.insert(digposl, nn)
|
|
|
|
nn = vector.new(laypos)
|
|
nn[oaxis] = nn[oaxis] + 1
|
|
table.insert(digposl, nn)
|
|
nn = vector.new(nn)
|
|
nn.y = nn.y + 1
|
|
table.insert(digposl, nn)
|
|
nn = vector.new(nn)
|
|
nn.y = nn.y + 1
|
|
table.insert(digposl, nn)
|
|
|
|
if self.digslope == 3 then
|
|
-- Extra space above on downslopes
|
|
nn = vector.new(laypos)
|
|
nn.y = nn.y + 3
|
|
table.insert(digposl, nn)
|
|
nn = vector.new(nn)
|
|
nn[oaxis] = nn[oaxis] + 1
|
|
table.insert(digposl, nn)
|
|
nn = vector.new(nn)
|
|
nn[oaxis] = nn[oaxis] - 2
|
|
table.insert(digposl, nn)
|
|
elseif self.digslope == 1 then
|
|
-- Extra space above current pos on upslopes
|
|
nn = vector.new(current_state.pos)
|
|
nn.y = nn.y + 3
|
|
table.insert(digposl, nn)
|
|
nn = vector.new(nn)
|
|
nn[oaxis] = nn[oaxis] + 1
|
|
table.insert(digposl, nn)
|
|
nn = vector.new(nn)
|
|
nn[oaxis] = nn[oaxis] - 2
|
|
table.insert(digposl, nn)
|
|
end
|
|
|
|
end
|
|
|
|
if digposl then
|
|
|
|
for _, digpos in ipairs(digposl) do
|
|
dignode = minetest.get_node(digpos)
|
|
if dignode.name ~= "air" then
|
|
|
|
if self.safedig then
|
|
local safe = false
|
|
for _, checkname in ipairs(safediglist) do
|
|
if dignode.name == checkname then
|
|
safe = true
|
|
break
|
|
end
|
|
end
|
|
if not safe then
|
|
dbg.v1("Boring cart blocked by unsafe dig node "..dignode.name.. " at "..minetest.pos_to_string(digpos))
|
|
return false
|
|
end
|
|
end
|
|
|
|
minetest.set_node(digpos, {name="air"})
|
|
|
|
-- TODO api docs say get_node_drops will be removed - why and to be replaced by what?
|
|
-- TODO also, can we calculate the right tool wear here?
|
|
local itemstacks = minetest.get_node_drops(dignode.name, "default:pick_mese")
|
|
local full = false
|
|
for _, item in ipairs(itemstacks) do
|
|
if self.inventory:room_for_item("main", item) then
|
|
self.inventory:add_item("main", item)
|
|
else
|
|
minetest.item_drop(item, "", digpos)
|
|
full = true
|
|
end
|
|
end
|
|
dbg.v2("Boring cart dug "..dignode.name.. " at "..minetest.pos_to_string(digpos))
|
|
if full then
|
|
dbg.v2("Boring cart full at "..minetest.pos_to_string(digpos))
|
|
return false
|
|
end
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
|
|
if laynode.name ~= "air" then
|
|
dbg.v2("Boring cart blocked by "..laynode.name.. " at "..minetest.pos_to_string(laypos))
|
|
return false
|
|
end
|
|
|
|
if minetest.registered_nodes[lbnode.name].walkable then
|
|
if not self.lay then
|
|
dbg.v2("Boring cart at end of rails, ready to lay, but disabled at "..minetest.pos_to_string(laypos))
|
|
return false
|
|
end
|
|
if self.inventory:remove_item("materials", "default:rail 1"):get_count() == 1 then
|
|
minetest.place_node(laypos, {name="default:rail"})
|
|
dbg.v2("Cart laid rail at "..minetest.pos_to_string(laypos))
|
|
return true
|
|
else
|
|
dbg.v2("Boring cart out of rails at "..minetest.pos_to_string(laypos))
|
|
return false
|
|
end
|
|
end
|
|
|
|
if lbnode.name == "air" then
|
|
if self.bridge then
|
|
if self.inventory:remove_item("materials", "default:wood 1"):get_count() == 1 then
|
|
dbg.v2("Cart laid bridge at "..minetest.pos_to_string(laypos))
|
|
minetest.place_node(laypos, {name="default:wood"})
|
|
return true
|
|
else
|
|
dbg.v2("Boring cart needs to bridge but has no wood at "..minetest.pos_to_string(laypos))
|
|
return false
|
|
end
|
|
else
|
|
dbg.v2("Boring cart cannot lay track on "..lbnode.name.." at "..minetest.pos_to_string(laypos))
|
|
return false
|
|
end
|
|
end
|
|
|
|
dbg.v2("Boring cart doesn't know what to do with "..lbnode.name.." below and in front")
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
minetest.register_entity("railcarts:boring_cart_ent", {
|
|
physical = true,
|
|
collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
|
|
visual = "mesh",
|
|
textures = { "railcarts_tex_boringcart.png" },
|
|
mesh= "railcarts_transport_cart.x",
|
|
visual_size = {x=1,y=1,z=1},
|
|
groups = { immortal=1, },
|
|
|
|
carttype = "boring",
|
|
getitem = "railcarts:boring_cart",
|
|
|
|
on_step = cartbase.on_step_handler,
|
|
on_punch = cartbase.on_punch_handler,
|
|
on_activate = cartbase.on_activate_handler,
|
|
get_staticdata = cartbase.get_staticdata_handler,
|
|
on_end_of_rails = boringcart.on_end_of_rails,
|
|
|
|
on_rightclick = function(self, clicker)
|
|
boringcart.show_form(self, clicker)
|
|
return true
|
|
end
|
|
|
|
})
|
|
|
|
minetest.register_craftitem("railcarts:boring_cart", {
|
|
description = "Boring Cart",
|
|
image = minetest.inventorycube("railcarts_inv_transportcart_top.png",
|
|
"railcarts_inv_cart_side.png",
|
|
"railcarts_inv_cart_side.png"),
|
|
|
|
on_place = function(item, placer, pointed_thing)
|
|
return cartbase.place_cart(item, pointed_thing, "railcarts:boring_cart_ent")
|
|
end
|
|
})
|
|
|
|
minetest.register_craft({
|
|
output = "railcarts:boring_cart",
|
|
recipe = {
|
|
{"", "", ""},
|
|
{"default:steel_ingot", "default:mese_crystal", "default:steel_ingot"},
|
|
{"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
|
|
},
|
|
})
|
|
|