Digilauncher, plus a few tweaks
This commit is contained in:
parent
c53f472787
commit
e7fa4db354
33
cartbase.lua
33
cartbase.lua
@ -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)
|
||||
|
2
init.lua
2
init.lua
@ -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")
|
||||
|
217
launchers.lua
217
launchers.lua
@ -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
106
rail.lua
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user