railcarts/boringcart.lua
2014-04-29 07:57:32 +01:00

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"},
},
})