Give furnace minecart minimum velocity when lit, add train separation code, update logging code, add sequence number to entity staticdata to allow respawn/despawn when carts move when the entity is unloaded
This commit is contained in:
parent
602bddf650
commit
2a3ccf63fd
|
@ -73,6 +73,15 @@ function mcl_util.mcl_log(message, module, bypass_default_logger)
|
||||||
minetest.log(selected_module .. " " .. message)
|
minetest.log(selected_module .. " " .. message)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
function mcl_util.make_mcl_logger(label, option)
|
||||||
|
-- Return dummy function if debug option isn't set
|
||||||
|
if not minetest.settings:get_bool(option,false) then return function() end, false end
|
||||||
|
|
||||||
|
local label_text = "["..tostring(label).."]"
|
||||||
|
return function(message)
|
||||||
|
mcl_util.mcl_log(message, label_text, true)
|
||||||
|
end, true
|
||||||
|
end
|
||||||
|
|
||||||
local player_timers = {}
|
local player_timers = {}
|
||||||
|
|
||||||
|
@ -1204,6 +1213,9 @@ end
|
||||||
function mcl_util.get_active_object_id_from_uuid(uuid)
|
function mcl_util.get_active_object_id_from_uuid(uuid)
|
||||||
return uuid_to_aoid_cache[uuid] or scan_active_objects() or uuid_to_aoid_cache[uuid]
|
return uuid_to_aoid_cache[uuid] or scan_active_objects() or uuid_to_aoid_cache[uuid]
|
||||||
end
|
end
|
||||||
|
function mcl_util.get_luaentity_from_uuid(uuid)
|
||||||
|
return minetest.luaentities[ mcl_util.get_active_object_id_from_uuid(uuid) ]
|
||||||
|
end
|
||||||
function mcl_util.get_uuid(obj)
|
function mcl_util.get_uuid(obj)
|
||||||
local le = obj:get_luaentity()
|
local le = obj:get_luaentity()
|
||||||
|
|
||||||
|
|
|
@ -3,13 +3,7 @@ local modpath = minetest.get_modpath(modname)
|
||||||
local mod = mcl_minecarts
|
local mod = mcl_minecarts
|
||||||
local S = minetest.get_translator(modname)
|
local S = minetest.get_translator(modname)
|
||||||
|
|
||||||
local LOGGING_ON = minetest.settings:get_bool("mcl_logging_minecarts", false)
|
local mcl_log = mcl_util.make_mcl_logger("mcl_logging_minecarts", "Minecarts")
|
||||||
local DEBUG = false
|
|
||||||
local function mcl_log(message)
|
|
||||||
if LOGGING_ON then
|
|
||||||
mcl_util.mcl_log(message, "[Minecarts]", true)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Imports
|
-- Imports
|
||||||
local table_merge = mcl_util.table_merge
|
local table_merge = mcl_util.table_merge
|
||||||
|
@ -53,6 +47,7 @@ local function make_staticdata( railtype, connected_at, dir )
|
||||||
velocity = 0,
|
velocity = 0,
|
||||||
dir = vector.new(dir),
|
dir = vector.new(dir),
|
||||||
mass = 1,
|
mass = 1,
|
||||||
|
seq = 1,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -86,8 +81,15 @@ function DEFAULT_CART_DEF:on_activate(staticdata, dtime_s)
|
||||||
if not data.uuid then
|
if not data.uuid then
|
||||||
data.uuid = mcl_util.get_uuid(self.object)
|
data.uuid = mcl_util.get_uuid(self.object)
|
||||||
end
|
end
|
||||||
|
self._seq = data.seq or 1
|
||||||
|
|
||||||
local cd = get_cart_data(data.uuid)
|
local cd = get_cart_data(data.uuid)
|
||||||
if not cd then update_cart_data(data) end
|
if not cd then
|
||||||
|
update_cart_data(data)
|
||||||
|
else
|
||||||
|
if not cd.seq then cd.seq = 1 end
|
||||||
|
data = cd
|
||||||
|
end
|
||||||
|
|
||||||
-- Initialize
|
-- Initialize
|
||||||
if type(data) == "table" then
|
if type(data) == "table" then
|
||||||
|
@ -121,7 +123,7 @@ function DEFAULT_CART_DEF:on_activate(staticdata, dtime_s)
|
||||||
end
|
end
|
||||||
function DEFAULT_CART_DEF:get_staticdata()
|
function DEFAULT_CART_DEF:get_staticdata()
|
||||||
save_cart_data(self._staticdata.uuid)
|
save_cart_data(self._staticdata.uuid)
|
||||||
return minetest.serialize({uuid = self._staticdata.uuid})
|
return minetest.serialize({uuid = self._staticdata.uuid, seq=self._seq})
|
||||||
end
|
end
|
||||||
|
|
||||||
function DEFAULT_CART_DEF:add_node_watch(pos)
|
function DEFAULT_CART_DEF:add_node_watch(pos)
|
||||||
|
@ -147,6 +149,15 @@ function DEFAULT_CART_DEF:remove_node_watch(pos)
|
||||||
end
|
end
|
||||||
staticdata.node_watches = new_watches
|
staticdata.node_watches = new_watches
|
||||||
end
|
end
|
||||||
|
function DEFAULT_CART_DEF:get_cart_position()
|
||||||
|
local staticdata = self._staticdata
|
||||||
|
|
||||||
|
if staticdata.connected_at then
|
||||||
|
return staticdata.connected_at + staticdata.dir * staticdata.distance
|
||||||
|
else
|
||||||
|
return self.object:get_pos()
|
||||||
|
end
|
||||||
|
end
|
||||||
function DEFAULT_CART_DEF:on_step(dtime)
|
function DEFAULT_CART_DEF:on_step(dtime)
|
||||||
local staticdata = self._staticdata
|
local staticdata = self._staticdata
|
||||||
if not staticdata then
|
if not staticdata then
|
||||||
|
@ -154,6 +165,11 @@ function DEFAULT_CART_DEF:on_step(dtime)
|
||||||
self._staticdata = staticdata
|
self._staticdata = staticdata
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if self._seq ~= staticdata.seq then
|
||||||
|
print("TODO: remove cart #"..staticdata.uuid.." with sequence number mismatch")
|
||||||
|
print("self.seq="..tostring(self._seq)..", staticdata.seq="..tostring(staticdata.seq))
|
||||||
|
end
|
||||||
|
|
||||||
-- Regen
|
-- Regen
|
||||||
local hp = self.object:get_hp()
|
local hp = self.object:get_hp()
|
||||||
if hp < MINECART_MAX_HP then
|
if hp < MINECART_MAX_HP then
|
||||||
|
|
|
@ -73,6 +73,10 @@ mcl_minecarts.register_minecart({
|
||||||
|
|
||||||
-- Update furnace stuff
|
-- Update furnace stuff
|
||||||
if (staticdata.fueltime or 0) > 0 then
|
if (staticdata.fueltime or 0) > 0 then
|
||||||
|
if staticdata.velocity < 0.25 then
|
||||||
|
staticdata.velocity = 0.25
|
||||||
|
end
|
||||||
|
|
||||||
staticdata.fueltime = (staticdata.fueltime or dtime) - dtime
|
staticdata.fueltime = (staticdata.fueltime or dtime) - dtime
|
||||||
if staticdata.fueltime <= 0 then
|
if staticdata.fueltime <= 0 then
|
||||||
self.object:set_properties({textures =
|
self.object:set_properties({textures =
|
||||||
|
|
|
@ -5,9 +5,10 @@ local mod = mcl_minecarts
|
||||||
mcl_minecarts.modpath = modpath
|
mcl_minecarts.modpath = modpath
|
||||||
|
|
||||||
-- Constants
|
-- Constants
|
||||||
mcl_minecarts.speed_max = 10
|
mod.speed_max = 10
|
||||||
mcl_minecarts.check_float_time = 15
|
mod.check_float_time = 15
|
||||||
mcl_minecarts.FRICTION = 0.4
|
mod.FRICTION = 0.4
|
||||||
|
mod.MAX_TRAIN_LENGTH = 4
|
||||||
|
|
||||||
for _,filename in pairs({"storage","functions","rails","train","carts"}) do
|
for _,filename in pairs({"storage","functions","rails","train","carts"}) do
|
||||||
dofile(modpath.."/"..filename..".lua")
|
dofile(modpath.."/"..filename..".lua")
|
||||||
|
|
|
@ -4,8 +4,9 @@ local mod = mcl_minecarts
|
||||||
local S = minetest.get_translator(modname)
|
local S = minetest.get_translator(modname)
|
||||||
|
|
||||||
-- Constants
|
-- Constants
|
||||||
local DEBUG = false
|
local mcl_debug,DEBUG = mcl_util.make_mcl_logger("mcl_logging_minecart_debug", "Minecart Debug")
|
||||||
local friction = mcl_minecarts.FRICTION
|
local friction = mcl_minecarts.FRICTION
|
||||||
|
local MAX_TRAIN_LENGTH = mod.MAX_TRAIN_LENGTH
|
||||||
|
|
||||||
-- Imports
|
-- Imports
|
||||||
local train_length = mod.train_length
|
local train_length = mod.train_length
|
||||||
|
@ -131,6 +132,10 @@ local function handle_cart_collision(cart1, prev_pos, next_dir)
|
||||||
|
|
||||||
local meta = minetest.get_meta(vector.add(pos,next_dir))
|
local meta = minetest.get_meta(vector.add(pos,next_dir))
|
||||||
if not cart_uuid then return end
|
if not cart_uuid then return end
|
||||||
|
|
||||||
|
-- Don't collide with the train car in front of you
|
||||||
|
if cart1._staticdata.ahead == cart_uuid then return end
|
||||||
|
|
||||||
minetest.log("action","cart #"..cart1._staticdata.uuid.." collided with cart #"..cart_uuid.." at "..tostring(pos))
|
minetest.log("action","cart #"..cart1._staticdata.uuid.." collided with cart #"..cart_uuid.." at "..tostring(pos))
|
||||||
|
|
||||||
local cart2_aoid = mcl_util.get_active_object_id_from_uuid(cart_uuid)
|
local cart2_aoid = mcl_util.get_active_object_id_from_uuid(cart_uuid)
|
||||||
|
@ -146,8 +151,8 @@ local function handle_cart_collision(cart1, prev_pos, next_dir)
|
||||||
local m1 = cart1_staticdata.mass
|
local m1 = cart1_staticdata.mass
|
||||||
local m2 = cart2_staticdata.mass
|
local m2 = cart2_staticdata.mass
|
||||||
|
|
||||||
print("u1="..tostring(u1)..",u2="..tostring(u2))
|
--print("u1="..tostring(u1)..",u2="..tostring(u2))
|
||||||
if u2 == 0 and u1 < 4 and train_length(cart1) < 3 then
|
if u2 == 0 and u1 < 4 and train_length(cart1) < MAX_TRAIN_LENGTH then
|
||||||
link_cart_ahead(cart1, cart2)
|
link_cart_ahead(cart1, cart2)
|
||||||
cart2_staticdata.dir = mcl_minecarts:get_rail_direction(cart2_staticdata.connected_at, cart1_staticdata.dir)
|
cart2_staticdata.dir = mcl_minecarts:get_rail_direction(cart2_staticdata.connected_at, cart1_staticdata.dir)
|
||||||
cart2_staticdata.velocity = cart1_staticdata.velocity
|
cart2_staticdata.velocity = cart1_staticdata.velocity
|
||||||
|
@ -275,7 +280,7 @@ local function do_movement_step(self, dtime)
|
||||||
end
|
end
|
||||||
|
|
||||||
if DEBUG and ( v_0 > 0 or a ~= 0 ) then
|
if DEBUG and ( v_0 > 0 or a ~= 0 ) then
|
||||||
print( " cart "..tostring(staticdata.uuid)..
|
mcl_debug(" cart "..tostring(staticdata.uuid)..
|
||||||
": a="..tostring(a)..
|
": a="..tostring(a)..
|
||||||
",v_0="..tostring(v_0)..
|
",v_0="..tostring(v_0)..
|
||||||
",x_0="..tostring(x_0)..
|
",x_0="..tostring(x_0)..
|
||||||
|
@ -334,7 +339,7 @@ local function do_movement_step(self, dtime)
|
||||||
staticdata.distance = x_1
|
staticdata.distance = x_1
|
||||||
|
|
||||||
if DEBUG and (1==0) and ( v_0 > 0 or a ~= 0 ) then
|
if DEBUG and (1==0) and ( v_0 > 0 or a ~= 0 ) then
|
||||||
print( "- cart #"..tostring(staticdata.uuid)..
|
mcl_debug( "- cart #"..tostring(staticdata.uuid)..
|
||||||
": a="..tostring(a)..
|
": a="..tostring(a)..
|
||||||
",v_0="..tostring(v_0)..
|
",v_0="..tostring(v_0)..
|
||||||
",v_1="..tostring(v_1)..
|
",v_1="..tostring(v_1)..
|
||||||
|
@ -362,7 +367,7 @@ local function do_movement_step(self, dtime)
|
||||||
-- Get the next direction
|
-- Get the next direction
|
||||||
local next_dir,_ = mcl_minecarts:get_rail_direction(pos, staticdata.dir, nil, nil, staticdata.railtype)
|
local next_dir,_ = mcl_minecarts:get_rail_direction(pos, staticdata.dir, nil, nil, staticdata.railtype)
|
||||||
if DEBUG and next_dir ~= staticdata.dir then
|
if DEBUG and next_dir ~= staticdata.dir then
|
||||||
print( "Changing direction from "..tostring(staticdata.dir).." to "..tostring(next_dir))
|
mcl_debug( "Changing direction from "..tostring(staticdata.dir).." to "..tostring(next_dir))
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Handle cart collisions
|
-- Handle cart collisions
|
||||||
|
@ -376,7 +381,7 @@ local function do_movement_step(self, dtime)
|
||||||
|
|
||||||
-- Handle end of track
|
-- Handle end of track
|
||||||
if next_dir == staticdata.dir * -1 and next_dir.y == 0 then
|
if next_dir == staticdata.dir * -1 and next_dir.y == 0 then
|
||||||
if DEBUG then print("Stopping cart at end of track at "..tostring(pos)) end
|
if DEBUG then mcl_debug("Stopping cart at end of track at "..tostring(pos)) end
|
||||||
staticdata.velocity = 0
|
staticdata.velocity = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -384,7 +389,7 @@ local function do_movement_step(self, dtime)
|
||||||
staticdata.dir = next_dir
|
staticdata.dir = next_dir
|
||||||
elseif stops_in_block and v_1 < (friction/5) and a <= 0 then
|
elseif stops_in_block and v_1 < (friction/5) and a <= 0 then
|
||||||
-- Handle direction flip due to gravity
|
-- Handle direction flip due to gravity
|
||||||
if DEBUG then print("Gravity flipped direction") end
|
if DEBUG then mcl_debug("Gravity flipped direction") end
|
||||||
|
|
||||||
-- Velocity should be zero at this point
|
-- Velocity should be zero at this point
|
||||||
staticdata.velocity = 0
|
staticdata.velocity = 0
|
||||||
|
@ -405,7 +410,7 @@ local function do_movement_step(self, dtime)
|
||||||
|
|
||||||
-- Debug reporting
|
-- Debug reporting
|
||||||
if DEBUG and ( v_0 > 0 or v_1 > 0 ) then
|
if DEBUG and ( v_0 > 0 or v_1 > 0 ) then
|
||||||
print( " cart #"..tostring(staticdata.uuid)..
|
mcl_debug( " cart #"..tostring(staticdata.uuid)..
|
||||||
": a="..tostring(a)..
|
": a="..tostring(a)..
|
||||||
",v_0="..tostring(v_0)..
|
",v_0="..tostring(v_0)..
|
||||||
",v_1="..tostring(v_1)..
|
",v_1="..tostring(v_1)..
|
||||||
|
|
|
@ -4,7 +4,9 @@ local mod = mcl_minecarts
|
||||||
|
|
||||||
-- Imports
|
-- Imports
|
||||||
local get_cart_data = mod.get_cart_data
|
local get_cart_data = mod.get_cart_data
|
||||||
|
local MAX_TRAIN_LENGTH = mod.MAX_TRAIN_LENGTH
|
||||||
|
|
||||||
|
-- Follow .behind to the back end of a train
|
||||||
local function find_back(start)
|
local function find_back(start)
|
||||||
while start.behind do
|
while start.behind do
|
||||||
local nxt = get_cart_data(start.behind)
|
local nxt = get_cart_data(start.behind)
|
||||||
|
@ -14,10 +16,13 @@ local function find_back(start)
|
||||||
return start
|
return start
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Iterate across all the cars in a train
|
||||||
local function train_cars(anchor)
|
local function train_cars(anchor)
|
||||||
local back = find_back(anchor._staticdata)
|
local back = find_back(anchor._staticdata)
|
||||||
|
local limit = MAX_TRAIN_LENGTH
|
||||||
return function()
|
return function()
|
||||||
if not back then return end
|
if not back or limit <= 0 then return end
|
||||||
|
limit = limit - 1
|
||||||
|
|
||||||
local ret = back
|
local ret = back
|
||||||
if back.ahead then
|
if back.ahead then
|
||||||
|
@ -28,26 +33,6 @@ local function train_cars(anchor)
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function mod.update_train(cart)
|
|
||||||
local sum_velocity = 0
|
|
||||||
local count = 0
|
|
||||||
for cart in train_cars(cart) do
|
|
||||||
count = count + 1
|
|
||||||
sum_velocity = sum_velocity + (cart.velocity or 0)
|
|
||||||
end
|
|
||||||
local avg_velocity = sum_velocity / count
|
|
||||||
if count == 0 then return end
|
|
||||||
|
|
||||||
print("Using velocity "..tostring(avg_velocity))
|
|
||||||
|
|
||||||
-- Set the entire train to the average velocity
|
|
||||||
for c in train_cars(cart) do
|
|
||||||
print(tostring(c.behind).."->"..c.uuid.."->"..tostring(c.ahead).." setting cart #"..c.uuid.." velocity to "..tostring(avg_velocity))
|
|
||||||
c.velocity = avg_velocity
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function mod.train_length(cart)
|
function mod.train_length(cart)
|
||||||
local count = 0
|
local count = 0
|
||||||
for cart in train_cars(cart) do
|
for cart in train_cars(cart) do
|
||||||
|
@ -55,6 +40,68 @@ function mod.train_length(cart)
|
||||||
end
|
end
|
||||||
return count
|
return count
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function mod.is_in_same_train(anchor, other)
|
||||||
|
for cart in train_cars(anchor) do
|
||||||
|
if cart.uuid == other.uuid then return true end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function mod.distance_between_cars(car1, car2)
|
||||||
|
if not car1.connected_at then return nil end
|
||||||
|
if not car2.connected_at then return nil end
|
||||||
|
|
||||||
|
if not car1.dir then car1.dir = vector.zero() end
|
||||||
|
if not car2.dir then car2.dir = vector.zero() end
|
||||||
|
|
||||||
|
local pos1 = vector.add(car1.connected_at, vector.multiply(car1.dir, car1.distance))
|
||||||
|
local pos2 = vector.add(car2.connected_at, vector.multiply(car2.dir, car2.distance))
|
||||||
|
|
||||||
|
return vector.distance(pos1, pos2)
|
||||||
|
end
|
||||||
|
local distance_between_cars = mod.distance_between_cars
|
||||||
|
|
||||||
|
function mod.update_train(cart)
|
||||||
|
local staticdata = cart._staticdata
|
||||||
|
|
||||||
|
-- Only update from the back
|
||||||
|
if staticdata.behind or not staticdata.ahead then return end
|
||||||
|
print("\nUpdating train")
|
||||||
|
|
||||||
|
-- Do no special processing if the cart is not part of a train
|
||||||
|
if not staticdata.ahead and not staticdata.behind then return end
|
||||||
|
|
||||||
|
-- Calculate the average velocity of all train cars
|
||||||
|
local sum_velocity = 0
|
||||||
|
for cart in train_cars(cart) do
|
||||||
|
if cart.velocity or 0 > velocity then
|
||||||
|
velocity = cart.velocity
|
||||||
|
end
|
||||||
|
end
|
||||||
|
print("Using velocity "..tostring(velocity))
|
||||||
|
|
||||||
|
-- Set the entire train to the average velocity
|
||||||
|
local behind = nil
|
||||||
|
for c in train_cars(cart) do
|
||||||
|
local e = 0
|
||||||
|
local separation
|
||||||
|
if behind then
|
||||||
|
separation = distance_between_cars(behind, c)
|
||||||
|
local e = 0
|
||||||
|
if separation > 1.25 then
|
||||||
|
velocity = velocity * 0.9
|
||||||
|
elseif separation < 1.15 then
|
||||||
|
velocity = velocity * 1.1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
print(tostring(c.behind).."->"..c.uuid.."->"..tostring(c.ahead).."("..tostring(separation)..") setting cart #"..c.uuid.." velocity to "..tostring(velocity))
|
||||||
|
c.velocity = velocity
|
||||||
|
|
||||||
|
behind = c
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function mod.link_cart_ahead(cart, cart_ahead)
|
function mod.link_cart_ahead(cart, cart_ahead)
|
||||||
local staticdata = cart._staticdata
|
local staticdata = cart._staticdata
|
||||||
local ca_staticdata = cart_ahead._staticdata
|
local ca_staticdata = cart_ahead._staticdata
|
||||||
|
@ -64,9 +111,3 @@ function mod.link_cart_ahead(cart, cart_ahead)
|
||||||
staticdata.ahead = ca_staticdata.uuid
|
staticdata.ahead = ca_staticdata.uuid
|
||||||
ca_staticdata.behind = staticdata.uuid
|
ca_staticdata.behind = staticdata.uuid
|
||||||
end
|
end
|
||||||
function mod.is_in_same_train(anchor, other)
|
|
||||||
for cart in train_cars(anchor) do
|
|
||||||
if cart.uuid == other.uuid then return true end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
Loading…
Reference in New Issue