Add cart entity respawn/destroy to match cart data (partially working)
This commit is contained in:
parent
a0afbff984
commit
92a1c375e9
|
@ -6,11 +6,13 @@ local S = minetest.get_translator(modname)
|
|||
local mcl_log = mcl_util.make_mcl_logger("mcl_logging_minecarts", "Minecarts")
|
||||
|
||||
-- Imports
|
||||
local CART_BLOCK_SIZE = mod.CART_BLOCK_SIZE
|
||||
local table_merge = mcl_util.table_merge
|
||||
local get_cart_data = mod.get_cart_data
|
||||
local save_cart_data = mod.save_cart_data
|
||||
local update_cart_data = mod.update_cart_data
|
||||
local destroy_cart_data = mod.destroy_cart_data
|
||||
local find_carts_by_block_map = mod.find_carts_by_block_map
|
||||
local do_movement,do_detached_movement,handle_cart_enter = dofile(modpath.."/movement.lua")
|
||||
assert(do_movement)
|
||||
assert(do_detached_movement)
|
||||
|
@ -165,9 +167,15 @@ function DEFAULT_CART_DEF:on_step(dtime)
|
|||
self._staticdata = staticdata
|
||||
end
|
||||
|
||||
-- Repair cart_type
|
||||
if not staticdata.cart_type then
|
||||
staticdata.cart_type = self.name
|
||||
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))
|
||||
print("removing cart #"..staticdata.uuid.." with sequence number mismatch")
|
||||
self.object:remove()
|
||||
return
|
||||
end
|
||||
|
||||
-- Regen
|
||||
|
@ -309,6 +317,7 @@ function mcl_minecarts.place_minecart(itemstack, pointed_thing, placer)
|
|||
local uuid = mcl_util.get_uuid(cart)
|
||||
data = make_staticdata( railtype, railpos, cart_dir )
|
||||
data.uuid = uuid
|
||||
data.cart_type = entity_id
|
||||
update_cart_data(data)
|
||||
le._staticdata = data
|
||||
save_cart_data(le._staticdata.uuid)
|
||||
|
@ -447,7 +456,67 @@ if minetest.get_modpath("mcl_wip") then
|
|||
mcl_wip.register_wip_item("mcl_minecarts:command_block_minecart")
|
||||
end
|
||||
|
||||
local function respawn_cart(cart)
|
||||
local cart_type = cart.cart_type or "mcl_minecarts:minecart"
|
||||
local pos = mod.get_cart_position(cart)
|
||||
print("Respawning cart #"..cart.uuid.." at "..tostring(pos))
|
||||
|
||||
-- Update sequence so that old cart entities get removed
|
||||
cart.seq = (cart.seq or 1) + 1
|
||||
save_cart_data(cart.uuid)
|
||||
|
||||
-- Create the new entity
|
||||
local entity = minetest.add_entity(pos, cart_type)
|
||||
local le = entity:get_luaentity()
|
||||
le._seq = cart.seq
|
||||
le._uuid = cart.uuid
|
||||
le._staticdata = cart
|
||||
|
||||
-- We intentionally don't call the normal hooks because this minecart was already there
|
||||
end
|
||||
|
||||
-- Try to respawn cart entities for carts that have moved into range of a player
|
||||
local function try_respawn_carts()
|
||||
-- Build a map of blocks near players
|
||||
local block_map = {}
|
||||
local players = minetest.get_connected_players()
|
||||
for _,player in pairs(players) do
|
||||
local pos = player:get_pos()
|
||||
local min = vector.floor(vector.divide(vector.offset(pos,-CART_BLOCK_SIZE,-CART_BLOCK_SIZE,-CART_BLOCK_SIZE), CART_BLOCK_SIZE))
|
||||
local max = vector.floor(vector.divide(vector.offset(pos, CART_BLOCK_SIZE, CART_BLOCK_SIZE, CART_BLOCK_SIZE), CART_BLOCK_SIZE)) + vector.new(1,1,1)
|
||||
for z = min.z,max.z do
|
||||
for y = min.y,max.y do
|
||||
for x = min.x,min.x do
|
||||
block_map[ vector.to_string(vector.new(x,y,z)) ] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Find all cart data that are in these blocks
|
||||
local carts = find_carts_by_block_map(block_map)
|
||||
|
||||
-- Check to see if any of these don't have an entity
|
||||
for _,cart in pairs(carts) do
|
||||
local le = mcl_util.get_luaentity_from_uuid(cart.uuid)
|
||||
if not le then
|
||||
respawn_cart(cart)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local timer = 0
|
||||
minetest.register_globalstep(function(dtime)
|
||||
timer = timer - dtime
|
||||
if timer <= 0 then
|
||||
local start_time = minetest.get_us_time()
|
||||
try_respawn_carts()
|
||||
local stop_time = minetest.get_us_time()
|
||||
local duration = (stop_time - start_time) / 1e6
|
||||
timer = duration / 50e-6 -- Schedule 50us per second
|
||||
--print("Took "..tostring(duration).." seconds, rescheduling for "..tostring(timer).." seconds in the future")
|
||||
end
|
||||
|
||||
-- TODO: handle periodically updating out-of-range carts
|
||||
end)
|
||||
|
||||
|
|
|
@ -356,4 +356,10 @@ function mcl_minecarts:update_cart_orientation()
|
|||
self.object:set_rotation(rot)
|
||||
end
|
||||
|
||||
function mod.get_cart_position(cart_staticdata)
|
||||
local data = cart_staticdata
|
||||
if not data.connected_at then return end
|
||||
|
||||
return vector.add(data.connected_at, vector.multiply(data.dir or vector.zero(), data.distance or 0))
|
||||
end
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ mod.speed_max = 10
|
|||
mod.check_float_time = 15
|
||||
mod.FRICTION = 0.4
|
||||
mod.MAX_TRAIN_LENGTH = 4
|
||||
mod.CART_BLOCK_SIZE = 64
|
||||
|
||||
for _,filename in pairs({"storage","functions","rails","train","carts"}) do
|
||||
dofile(modpath.."/"..filename..".lua")
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
local storage = minetest.get_mod_storage()
|
||||
local mod = mcl_minecarts
|
||||
|
||||
-- Imports
|
||||
local CART_BLOCK_SIZE = mod.CART_BLOCK_SIZE
|
||||
|
||||
local cart_data = {}
|
||||
local cart_data_fail_cache = {}
|
||||
local cart_ids = storage:get_keys()
|
||||
|
||||
function mod.get_cart_data(uuid)
|
||||
local function get_cart_data(uuid)
|
||||
if cart_data[uuid] then return cart_data[uuid] end
|
||||
if cart_data_fail_cache[uuid] then return nil end
|
||||
|
||||
|
@ -17,6 +21,14 @@ function mod.get_cart_data(uuid)
|
|||
cart_data[uuid] = data
|
||||
return data
|
||||
end
|
||||
mod.get_cart_data = get_cart_data
|
||||
|
||||
-- Preload all cart data into memory
|
||||
for _,id in pairs(cart_ids) do
|
||||
local uuid = string.sub(id,6)
|
||||
get_cart_data(uuid)
|
||||
end
|
||||
|
||||
local function save_cart_data(uuid)
|
||||
if not cart_data[uuid] then return end
|
||||
storage:set_string("cart-"..uuid,minetest.serialize(cart_data[uuid]))
|
||||
|
@ -35,3 +47,17 @@ function mod.destroy_cart_data(uuid)
|
|||
cart_data_fail_cache[uuid] = true
|
||||
end
|
||||
|
||||
function mod.find_carts_by_block_map(block_map)
|
||||
local cart_list = {}
|
||||
for _,data in pairs(cart_data) do
|
||||
if data and data.connected_at then
|
||||
local pos = mod.get_cart_position(data)
|
||||
local block = vector.floor(vector.divide(pos,CART_BLOCK_SIZE))
|
||||
if block_map[vector.to_string(block)] then
|
||||
cart_list[#cart_list + 1] = data
|
||||
end
|
||||
end
|
||||
end
|
||||
return cart_list
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue