Digilauncher, plus a few tweaks

master
Ciaran Gultnieks 2015-04-20 22:32:09 +01:00
parent c53f472787
commit e7fa4db354
4 changed files with 249 additions and 109 deletions

View File

@ -186,6 +186,7 @@ function cartbase.update(self, dtime)
state.direction = self.direction
state.speed = self.speed
state.railstatus = get_railstatus(state.pos, state.direction, state.speed)
dbg.v3("Railstatus at "..minetest.pos_to_string(state.pos)..", dir="..self.direction..", speed="..self.speed.." : "..dump(state.railstatus))
-- Stop here if we're on an unloaded block. Hopefully it will load and we can just carry on.
if is_unloaded(state.railstatus.railtype) then
if self.speed == 0 then
@ -248,7 +249,7 @@ function cartbase.update(self, dtime)
else
dbg.v3("Hopper/cart at "..minetest.pos_to_string(hpos).." is empty, waiting (for "..math.floor(self.loadwait).."s)")
end
self.wait = 5
self.wait = 1
end
else
self.loadwait = 0
@ -264,7 +265,7 @@ function cartbase.update(self, dtime)
-- Counts as a move, for the purposes of remaining
-- active
self.lastmove = 0
self.wait = 5
self.wait = 1
break
else
if desc == "load" then
@ -274,11 +275,11 @@ function cartbase.update(self, dtime)
dbg.v3("Cart at "..minetest.pos_to_string(hpos).." is full - launching")
else
dbg.v3("Cart at "..minetest.pos_to_string(hpos).." is full")
self.wait = 30
self.wait = 1
end
else
dbg.v3("Hopper at "..minetest.pos_to_string(hpos).." is full, can't"..desc)
self.wait = 30
self.wait = 1
end
end
break
@ -512,6 +513,8 @@ function cartbase.update(self, dtime)
else
-- speed == 0
dbg.v3("Cart stationary at "..minetest.pos_to_string(state.pos))
if state.railstatus.onautolauncher and self.linkedplayer ~= nil then
dbg.v1("Ejecting player from cart")
self.linkedplayer:set_detach()
@ -519,15 +522,19 @@ function cartbase.update(self, dtime)
self.linkedplayer = nil
end
end
-- Set speed/direction from launcher
if state.railstatus.launch then
dbg.v3("Launch cart at "..minetest.pos_to_string(state.pos)..
", direction="..state.railstatus.launch)
cartbase.setdirection(self, state, state.railstatus.launch)
state.speed = LAUNCH_CART_SPEED
elseif state.railstatus.autolaunch and self.linkedplayer ~= nil then
dbg.v3("Autolaunch cart at "..minetest.pos_to_string(state.pos)..
", direction="..state.railstatus.autolaunch)
cartbase.setdirection(self, state, state.railstatus.autolaunch)
state.speed = LAUNCH_CART_SPEED
end
-- Set speed/direction from launcher
if state.railstatus.launch then
cartbase.setdirection(self, state, state.railstatus.launch)
state.speed = LAUNCH_CART_SPEED
elseif state.railstatus.autolaunch and self.linkedplayer ~= nil then
cartbase.setdirection(self, state, state.railstatus.autolaunch)
state.speed = LAUNCH_CART_SPEED
end
-- Set ourselves autonomous if necessary (requires minetest patch)
@ -535,7 +542,7 @@ function cartbase.update(self, dtime)
self.lastmove = 0
end
local autonomous = 0
if self.lastmove < 10 then
if self.lastmove < 10 or state.railstatus.hopper then
autonomous = 1
end
self.object:set_autonomous(autonomous)

View File

@ -3,6 +3,8 @@ local version = "1.0.0"
LAUNCH_CART_SPEED = 2
MAXIMUM_CART_SPEED = 7
railcarts = {}
local railcarts_modpath = minetest.get_modpath("railcarts")
dofile(railcarts_modpath .. "/direction.lua")

View File

@ -2,6 +2,14 @@
local dbg
if moddebug then dbg=moddebug.dbg("railcarts") else dbg={v1=function() end,v2=function() end,v3=function() end} end
local function table_copy(t)
local out = {}
for k, v in pairs(t) do
out[k] = v
end
return out
end
minetest.register_craft({
output = 'node "railcarts:launcher_off" 5',
recipe = {
@ -29,6 +37,15 @@ minetest.register_craft({
}
})
minetest.register_craft({
output = 'node "railcarts:digilauncher" 2',
recipe = {
{"default:cobble", "default:mese_crystal","default:cobble"},
{"default:mese_crystal", "default:chest", "default:mese_crystal"},
{"default:cobble", "default:mese_crystal","default:cobble"},
}
})
minetest.register_craft({
output = 'node "railcarts:launcher_off" 2',
recipe = {
@ -99,6 +116,137 @@ minetest.register_node("railcarts:autolauncher", {
},
})
local digidef = {
description = "Cart Digilauncher",
tiles = {"railcarts_autolauncher.png^pipeworks_tube_connection_stony.png"},
is_ground_content = true,
groups = {cracky=3, tubedevice=1, tubedevice_receiver=1},
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string("formspec",
"size[10,8]"..
"field[8.25,1;2,1;channel;Channel;${channel}]"..
"button_exit[8,2;2,1;save;Save]"..
"list[current_name;main;0,0;8,3;]"..
"list[current_player;main;0,4;8,4;]")
meta:set_string("infotext", "Digilauncher")
local inv = meta:get_inventory()
inv:set_size("main", 24)
end,
can_dig = function(pos,player)
local meta = minetest.get_meta(pos);
local inv = meta:get_inventory()
return inv:is_empty("main")
end,
tube = {
insert_object = function(pos, node, stack, direction)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
return inv:add_item("main", stack)
end,
can_insert = function(pos, node, stack, direction)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
return inv:room_for_item("main", stack)
end,
input_inventory = "main",
connect_sides = {top=1, back=1, left=1, right=1, bottom=1, front=1},
},
on_receive_fields = function(pos, formname, fields, sender)
local meta = minetest.get_meta(pos)
if not fields.save then return end
local meta = minetest.get_meta(pos)
meta:set_string("channel", fields.channel)
end,
digiline =
{
receptor = {},
effector = {
action = function(pos, node, channel, msg)
local meta = minetest.get_meta(pos)
local pchan = meta:get_string("channel")
if channel ~= pchan then return end
if msg == "place" then
railcarts.launcher_place_cart(pos, meta)
elseif msg == "launch" then
node.name = "railcarts:digilauncher_on"
minetest.swap_node(pos, node)
end
end
}
},
}
minetest.register_node("railcarts:digilauncher", digidef)
digiondef = table_copy(digidef)
digiondef.tiles = {"railcarts_launcher_on.png^pipeworks_tube_connection_stony.png"}
digiondef.drop = "railcarts:digilauncher 1"
minetest.register_node("railcarts:digilauncher_on", digiondef)
railcarts.launcher_place_cart = function(pos, meta)
local inv = meta:get_inventory()
tests = {{x=pos.x+1,y=pos.y,z=pos.z},
{x=pos.x-1,y=pos.y,z=pos.z},
{x=pos.x,y=pos.y,z=pos.z+1},
{x=pos.x,y=pos.y,z=pos.z-1},
{x=pos.x,y=pos.y-1,z=pos.z}}
for _, testpos in ipairs(tests) do
if is_rail(minetest.get_node(testpos)) then
-- Check there's not a cart (or anything else, like a mob) in the
-- way
-- TODO: I think the block can be loaded, but the objects not
-- active, in which case this will drop another cart on top of an
-- existing one ad infinitum - needs fixing!
if not railcarts.cart_present(pos, 1) then
-- Get a cart from the autolauncher's inventory
local placecart = nil
for _, carttype in pairs({
"railcarts:cart",
"railcarts:cargo_cart",
"railcarts:boring_cart"}) do
local stack = inv:remove_item("main", ItemStack(carttype))
if not stack:is_empty() then
placecart = carttype
break
end
end
if not placecart then
dbg.v1("Autolauncher at "..minetest.pos_to_string(pos).." is empty")
return
end
dbg.v1("Autolauncher placing "..placecart.." at"..minetest.pos_to_string(testpos))
local object = minetest.add_entity(testpos, placecart.."_ent")
if object then
local ent = object:get_luaentity()
local newdir = xz_to_direction({x=testpos.x-pos.x, z=testpos.z-pos.z})
current_state = {direction=newdir}
cartbase.setdirection(ent, current_state, newdir)
ent.direction = newdir
end
end
end
end
end
railcarts.cart_present = function(pos, radius)
local found = minetest.get_objects_inside_radius(pos, radius)
for _, obj in pairs(found) do
local name = obj:get_entity_name()
if name == "railcarts:cart_ent" then return true end
if name == "railcarts:cargo_cart_ent" then return true end
if name == "railcarts:boring_cart_ent" then return true end
end
return false
end
minetest.register_abm({
nodenames = {"railcarts:autolauncher"},
neighbors = {},
@ -107,57 +255,32 @@ minetest.register_abm({
action =
function(pos, node, active_object_count, active_object_count_wider)
local meta = minetest.get_meta(pos)
-- Checking that the inventory is empty is going to be a lot
-- quicker than seeing if there is somewhere to place a cart,
-- and since there will be a lot of empty (inbound) launchers,
-- we do this first.
local inv = meta:get_inventory()
tests = {{x=pos.x+1,y=pos.y,z=pos.z},
{x=pos.x-1,y=pos.y,z=pos.z},
{x=pos.x,y=pos.y,z=pos.z+1},
{x=pos.x,y=pos.y,z=pos.z-1},
{x=pos.x,y=pos.y-1,z=pos.z}}
for _, testpos in ipairs(tests) do
if is_rail(minetest.get_node(testpos)) then
-- Check there's not a cart (or anything else, like a mob) in the way
-- TODO: I think the block can be loaded, but the objects not active,
-- in which case this will drop another cart on top of an existing
-- one ad infinitum - needs fixing!
already = minetest.get_objects_inside_radius(testpos, 1)
if table.maxn(already) == 0 then
-- Get a cart from the autolauncher's inventory
local stack = inv:remove_item("main", ItemStack("railcarts:cart"))
local placecart = "railcarts:cart_ent"
if stack:is_empty() then
stack = inv:remove_item("main", ItemStack("railcarts:cargo_cart"))
if stack:is_empty() then
stack = inv:remove_item("main", ItemStack("railcarts:boring_cart"))
if stack:is_empty() then
dbg.v1("Autolauncher at "..minetest.pos_to_string(pos).." is empty")
return
end
placecart = "railcarts:boring_cart_ent"
else
placecart = "railcarts:cargo_cart_ent"
end
end
dbg.v1("Autolauncher placing "..placecart.." at"..minetest.pos_to_string(testpos))
local object = minetest.add_entity(testpos, placecart)
if object then
local ent = object:get_luaentity()
local newdir = xz_to_direction({x=testpos.x-pos.x, z=testpos.z-pos.z})
current_state = {direction=newdir}
cartbase.setdirection(ent, current_state, newdir)
ent.direction = newdir
end
end
end
if inv:is_empty("main") then
return
end
railcarts.launcher_place_cart(pos, meta)
end,
})
minetest.register_abm({
nodenames = {"railcarts:digilauncher_on"},
neighbors = {},
interval = 5.0,
chance = 1,
action =
function(pos, node, active_object_count, active_object_count_wider)
local already = minetest.get_objects_inside_radius(pos, 1)
if not railcarts.cart_present(pos, 2) then
node.name = "railcarts:digilauncher"
minetest.swap_node(pos, node)
end
end,
})

106
rail.lua
View File

@ -1,4 +1,4 @@
local dbg
if moddebug then dbg=moddebug.dbg("railcarts") else dbg={v1=function() end,v2=function() end,v3=function() end} end
@ -37,6 +37,12 @@ function is_grabber(node)
if node.name == "railcarts:autolauncher" then
return true
end
if node.name == "railcarts:digilauncher" then
return true
end
if node.name == "railcarts:digilauncher_on" then
return true
end
return false
end
@ -75,6 +81,9 @@ function is_launcher(node)
if node.name == "railcarts:launcher_on" then
return true
end
if node.name == "railcarts:digilauncher_on" then
return true
end
return false
end
@ -237,59 +246,58 @@ function get_railstatus(fppos, direction, speed)
status.hopper = {x=pos.x,y=pos.y+1,z=pos.z}
end
if direction then
if speed > 0 then
-- Check if a player should be ejected
if direction == 1 and is_ejector(surrounds.x_next_above) and is_rail(surrounds.x_next) then
status.eject = true
elseif direction == 3 and is_ejector(surrounds.x_prev_above) and is_rail(surrounds.x_prev) then
status.eject = true
elseif direction == 0 and is_ejector(surrounds.z_next_above) and is_rail(surrounds.z_next) then
status.eject = true
elseif direction == 2 and is_ejector(surrounds.z_prev_above) and is_rail(surrounds.z_prev) then
status.eject = true
end
-- Check for detectors - below the cart, or to the left
local detpos
if is_detector(surrounds.below) then
detpos = {x=pos.x,y=pos.y-1,z=pos.z}
else
if direction == 0 and is_detector(surrounds.x_prev) then
detpos = {x=pos.x-1,y=pos.y,z=pos.z}
elseif direction == 1 and is_detector(surrounds.z_next) then
detpos = {x=pos.x,y=pos.y,z=pos.z+1}
elseif direction == 2 and is_detector(surrounds.x_next) then
detpos = {x=pos.x+1,y=pos.y,z=pos.z}
elseif direction == 1 and is_detector(surrounds.z_prev) then
detpos = {x=pos.x,y=pos.y,z=pos.z-1}
end
end
if detpos then
status.detector = detpos
end
if direction and speed > 0 then
-- Check if a player should be ejected
if direction == 1 and is_ejector(surrounds.x_next_above) and is_rail(surrounds.x_next) then
status.eject = true
elseif direction == 3 and is_ejector(surrounds.x_prev_above) and is_rail(surrounds.x_prev) then
status.eject = true
elseif direction == 0 and is_ejector(surrounds.z_next_above) and is_rail(surrounds.z_next) then
status.eject = true
elseif direction == 2 and is_ejector(surrounds.z_prev_above) and is_rail(surrounds.z_prev) then
status.eject = true
end
if speed == 0 then
-- Check if the cart should be grabbed
if is_grabber(surrounds.x_next_above) then
status.grab = {x=pos.x+1,y=pos.y+1,z=pos.z}
elseif is_grabber(surrounds.x_prev_above) then
status.grab = {x=pos.x-1,y=pos.y+1,z=pos.z}
elseif is_grabber(surrounds.z_prev_above) then
status.grab = {x=pos.x,y=pos.y+1,z=pos.z-1}
elseif is_grabber(surrounds.z_next_above) then
status.grab = {x=pos.x,y=pos.y+1,z=pos.z+1}
elseif is_grabber(surrounds.below) then
status.grab = {x=pos.x,y=pos.y-1,z=pos.z}
-- Check for detectors - below the cart, or to the left
local detpos
if is_detector(surrounds.below) then
detpos = {x=pos.x,y=pos.y-1,z=pos.z}
else
if direction == 0 and is_detector(surrounds.x_prev) then
detpos = {x=pos.x-1,y=pos.y,z=pos.z}
elseif direction == 1 and is_detector(surrounds.z_next) then
detpos = {x=pos.x,y=pos.y,z=pos.z+1}
elseif direction == 2 and is_detector(surrounds.x_next) then
detpos = {x=pos.x+1,y=pos.y,z=pos.z}
elseif direction == 1 and is_detector(surrounds.z_prev) then
detpos = {x=pos.x,y=pos.y,z=pos.z-1}
end
-- Check for being next to a launcher (only stationary carts)
check_launcher(surrounds, status)
end
if detpos then
status.detector = detpos
end
end
end
if speed == 0 then
-- Check if the cart should be grabbed
if is_grabber(surrounds.x_next_above) then
status.grab = {x=pos.x+1,y=pos.y+1,z=pos.z}
elseif is_grabber(surrounds.x_prev_above) then
status.grab = {x=pos.x-1,y=pos.y+1,z=pos.z}
elseif is_grabber(surrounds.z_prev_above) then
status.grab = {x=pos.x,y=pos.y+1,z=pos.z-1}
elseif is_grabber(surrounds.z_next_above) then
status.grab = {x=pos.x,y=pos.y+1,z=pos.z+1}
elseif is_grabber(surrounds.below) then
status.grab = {x=pos.x,y=pos.y-1,z=pos.z}
end
-- Check for being next to a launcher (only stationary carts)
check_launcher(surrounds, status)
end
end
if surrounds.below and surrounds.below.name == "railcarts:autolauncher" then