mirror of
https://git.minetest.land/VoxeLibre/VoxeLibre.git
synced 2024-08-22 01:47:24 +02:00
Implement offline/out of range minecart movement and fix minecart respawning, remove railtype tracking
This commit is contained in:
parent
a4987f63e9
commit
15c13b7bb3
@ -68,9 +68,8 @@ end
|
|||||||
-- Table for item-to-entity mapping. Keys: itemstring, Values: Corresponding entity ID
|
-- Table for item-to-entity mapping. Keys: itemstring, Values: Corresponding entity ID
|
||||||
local entity_mapping = {}
|
local entity_mapping = {}
|
||||||
|
|
||||||
local function make_staticdata( railtype, connected_at, dir )
|
local function make_staticdata( _, connected_at, dir )
|
||||||
return {
|
return {
|
||||||
railtype = railtype,
|
|
||||||
connected_at = connected_at,
|
connected_at = connected_at,
|
||||||
distance = 0,
|
distance = 0,
|
||||||
velocity = 0,
|
velocity = 0,
|
||||||
@ -122,12 +121,6 @@ function DEFAULT_CART_DEF:on_activate(staticdata, dtime_s)
|
|||||||
|
|
||||||
-- Initialize
|
-- Initialize
|
||||||
if type(data) == "table" then
|
if type(data) == "table" then
|
||||||
-- Migrate old data
|
|
||||||
if data._railtype then
|
|
||||||
data.railtype = data._railtype
|
|
||||||
data._railtype = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Fix up types
|
-- Fix up types
|
||||||
data.dir = vector.new(data.dir)
|
data.dir = vector.new(data.dir)
|
||||||
|
|
||||||
@ -194,11 +187,17 @@ function DEFAULT_CART_DEF:on_step(dtime)
|
|||||||
self._staticdata = staticdata
|
self._staticdata = staticdata
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Update entity position
|
||||||
|
local pos = mod.get_cart_position(staticdata)
|
||||||
|
if pos then self.object:move_to(pos) end
|
||||||
|
|
||||||
-- Repair cart_type
|
-- Repair cart_type
|
||||||
if not staticdata.cart_type then
|
if not staticdata.cart_type then
|
||||||
staticdata.cart_type = self.name
|
staticdata.cart_type = self.name
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Remove superceded entities
|
||||||
if self._seq ~= staticdata.seq then
|
if self._seq ~= staticdata.seq then
|
||||||
print("removing cart #"..staticdata.uuid.." with sequence number mismatch")
|
print("removing cart #"..staticdata.uuid.." with sequence number mismatch")
|
||||||
self.object:remove()
|
self.object:remove()
|
||||||
@ -207,22 +206,11 @@ function DEFAULT_CART_DEF:on_step(dtime)
|
|||||||
|
|
||||||
-- Regen
|
-- Regen
|
||||||
local hp = self.object:get_hp()
|
local hp = self.object:get_hp()
|
||||||
if hp < MINECART_MAX_HP then
|
local time_now = minetest.get_gametime()
|
||||||
if (staticdata.regen_timer or 0) > 0.5 then
|
if hp < MINECART_MAX_HP and staticdata.last_regen <= time_now - 1 then
|
||||||
hp = hp + 1
|
staticdata.last_regen = time_now
|
||||||
staticdata.regen_timer = staticdata.regen_timer - 1
|
hp = hp + 1
|
||||||
end
|
|
||||||
staticdata.regen_timer = (staticdata.regen_timer or 0) + dtime
|
|
||||||
self.object:set_hp(hp)
|
self.object:set_hp(hp)
|
||||||
else
|
|
||||||
staticdata.regen_timer = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Fix railtype field
|
|
||||||
local pos = self.object:get_pos()
|
|
||||||
if staticdata.connected_at and not staticdata.railtype then
|
|
||||||
local node = minetest.get_node(vector.floor(pos)).name
|
|
||||||
staticdata.railtype = minetest.get_item_group(node, "connect_to_raillike")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Cart specific behaviors
|
-- Cart specific behaviors
|
||||||
@ -256,27 +244,12 @@ function DEFAULT_CART_DEF:on_step(dtime)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if staticdata.connected_at then
|
if not staticdata.connected_at then
|
||||||
do_movement(staticdata, dtime)
|
|
||||||
|
|
||||||
-- Update entity
|
|
||||||
local pos = mod.get_cart_position(staticdata)
|
|
||||||
if pos then self.object:move_to(pos) end
|
|
||||||
mod.update_cart_orientation(self)
|
|
||||||
else
|
|
||||||
do_detached_movement(self, dtime)
|
do_detached_movement(self, dtime)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- TODO: move this into mcl_core:cactus _mcl_minecarts_on_enter_side
|
mod.update_cart_orientation(self)
|
||||||
-- Drop minecart if it collides with a cactus node
|
|
||||||
local r = 0.6
|
|
||||||
for _, node_pos in pairs({{r, 0}, {0, r}, {-r, 0}, {0, -r}}) do
|
|
||||||
if minetest.get_node(vector.offset(pos, node_pos[1], 0, node_pos[2])).name == "mcl_core:cactus" then
|
|
||||||
self:on_death()
|
|
||||||
self.object:remove()
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
function DEFAULT_CART_DEF:on_death(killer)
|
function DEFAULT_CART_DEF:on_death(killer)
|
||||||
local staticdata = self._staticdata
|
local staticdata = self._staticdata
|
||||||
@ -325,7 +298,7 @@ function mcl_minecarts.place_minecart(itemstack, pointed_thing, placer)
|
|||||||
local spawn_pos = pointed_thing.above
|
local spawn_pos = pointed_thing.above
|
||||||
local cart_dir = vector.new(1,0,0)
|
local cart_dir = vector.new(1,0,0)
|
||||||
|
|
||||||
local railtype, railpos, node
|
local railpos, node
|
||||||
if mcl_minecarts:is_rail(pointed_thing.under) then
|
if mcl_minecarts:is_rail(pointed_thing.under) then
|
||||||
railpos = pointed_thing.under
|
railpos = pointed_thing.under
|
||||||
elseif mcl_minecarts:is_rail(pointed_thing.above) then
|
elseif mcl_minecarts:is_rail(pointed_thing.above) then
|
||||||
@ -334,8 +307,7 @@ function mcl_minecarts.place_minecart(itemstack, pointed_thing, placer)
|
|||||||
if railpos then
|
if railpos then
|
||||||
spawn_pos = railpos
|
spawn_pos = railpos
|
||||||
node = minetest.get_node(railpos)
|
node = minetest.get_node(railpos)
|
||||||
railtype = minetest.get_item_group(node.name, "connect_to_raillike")
|
cart_dir = mcl_minecarts:get_rail_direction(railpos, vector.new(1,0,0))
|
||||||
cart_dir = mcl_minecarts:get_rail_direction(railpos, vector.new(1,0,0), nil, nil, railtype)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local entity_id = entity_mapping[itemstack:get_name()]
|
local entity_id = entity_mapping[itemstack:get_name()]
|
||||||
@ -343,16 +315,18 @@ function mcl_minecarts.place_minecart(itemstack, pointed_thing, placer)
|
|||||||
|
|
||||||
cart:set_yaw(minetest.dir_to_yaw(cart_dir))
|
cart:set_yaw(minetest.dir_to_yaw(cart_dir))
|
||||||
|
|
||||||
|
-- Setup cart data
|
||||||
|
local uuid = mcl_util.get_uuid(cart)
|
||||||
|
data = make_staticdata( nil, railpos, cart_dir )
|
||||||
|
data.uuid = uuid
|
||||||
|
data.cart_type = entity_id
|
||||||
|
update_cart_data(data)
|
||||||
|
save_cart_data(uuid)
|
||||||
|
|
||||||
-- Update static data
|
-- Update static data
|
||||||
local le = cart:get_luaentity()
|
local le = cart:get_luaentity()
|
||||||
if le then
|
if le then
|
||||||
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
|
le._staticdata = data
|
||||||
save_cart_data(le._staticdata.uuid)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Call placer
|
-- Call placer
|
||||||
@ -361,7 +335,7 @@ function mcl_minecarts.place_minecart(itemstack, pointed_thing, placer)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if railpos then
|
if railpos then
|
||||||
handle_cart_enter(le, railpos)
|
handle_cart_enter(data, railpos)
|
||||||
end
|
end
|
||||||
|
|
||||||
local pname = ""
|
local pname = ""
|
||||||
@ -518,7 +492,7 @@ local function try_respawn_carts()
|
|||||||
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)
|
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 z = min.z,max.z do
|
||||||
for y = min.y,max.y do
|
for y = min.y,max.y do
|
||||||
for x = min.x,min.x do
|
for x = min.x,max.x do
|
||||||
block_map[ vector.to_string(vector.new(x,y,z)) ] = true
|
block_map[ vector.to_string(vector.new(x,y,z)) ] = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -545,10 +519,42 @@ minetest.register_globalstep(function(dtime)
|
|||||||
try_respawn_carts()
|
try_respawn_carts()
|
||||||
local stop_time = minetest.get_us_time()
|
local stop_time = minetest.get_us_time()
|
||||||
local duration = (stop_time - start_time) / 1e6
|
local duration = (stop_time - start_time) / 1e6
|
||||||
timer = duration / 50e-6 -- Schedule 50us per second
|
timer = duration / 250e-6 -- Schedule 50us per second
|
||||||
|
if timer > 5 then timer = 5 end
|
||||||
--print("Took "..tostring(duration).." seconds, rescheduling for "..tostring(timer).." seconds in the future")
|
--print("Took "..tostring(duration).." seconds, rescheduling for "..tostring(timer).." seconds in the future")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- TODO: handle periodically updating out-of-range carts
|
-- Handle periodically updating out-of-range carts
|
||||||
|
-- TODO: change how often cart positions are updated based on velocity
|
||||||
|
for uuid,staticdata in mod.carts() do
|
||||||
|
local pos = mod.get_cart_position(staticdata)
|
||||||
|
local le = mcl_util.get_luaentity_from_uuid(staticdata.uuid)
|
||||||
|
--[[
|
||||||
|
print("cart# "..uuid..
|
||||||
|
",velocity="..tostring(staticdata.velocity)..
|
||||||
|
",pos="..tostring(pos)..
|
||||||
|
",le="..tostring(le)..
|
||||||
|
",connected_at="..tostring(staticdata.connected_at)
|
||||||
|
)]]
|
||||||
|
|
||||||
|
--- Non-entity code
|
||||||
|
if staticdata.connected_at then
|
||||||
|
do_movement(staticdata, dtime)
|
||||||
|
|
||||||
|
-- TODO: move this into mcl_core:cactus _mcl_minecarts_on_enter_side
|
||||||
|
-- Drop minecart if it collides with a cactus node
|
||||||
|
local pos = mod.get_cart_position(staticdata)
|
||||||
|
if pos then
|
||||||
|
local r = 0.6
|
||||||
|
for _, node_pos in pairs({{r, 0}, {0, r}, {-r, 0}, {0, -r}}) do
|
||||||
|
if minetest.get_node(vector.offset(pos, node_pos[1], 0, node_pos[2])).name == "mcl_core:cactus" then
|
||||||
|
self:on_death()
|
||||||
|
self.object:remove()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
@ -372,7 +372,7 @@ function mod.reverse_cart_direction(staticdata)
|
|||||||
staticdata.distance = 1 - (staticdata.distance or 0)
|
staticdata.distance = 1 - (staticdata.distance or 0)
|
||||||
|
|
||||||
-- recalculate direction
|
-- recalculate direction
|
||||||
local next_dir,_ = mod:get_rail_direction(staticdata.connected_at, next_dir, nil, nil, staticdata.railtype)
|
local next_dir,_ = mod:get_rail_direction(staticdata.connected_at, next_dir)
|
||||||
staticdata.dir = next_dir
|
staticdata.dir = next_dir
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -7,8 +7,8 @@ local S = minetest.get_translator(modname)
|
|||||||
local mcl_debug,DEBUG = mcl_util.make_mcl_logger("mcl_logging_minecart_debug", "Minecart Debug")
|
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
|
local MAX_TRAIN_LENGTH = mod.MAX_TRAIN_LENGTH
|
||||||
DEBUG = true
|
--DEBUG = false
|
||||||
mcl_debug = function(msg) print(msg) end
|
--mcl_debug = function(msg) print(msg) end
|
||||||
|
|
||||||
-- Imports
|
-- Imports
|
||||||
local train_length = mod.train_length
|
local train_length = mod.train_length
|
||||||
@ -30,13 +30,9 @@ end
|
|||||||
mod.detach_minecart = detach_minecart
|
mod.detach_minecart = detach_minecart
|
||||||
|
|
||||||
local function try_detach_minecart(staticdata)
|
local function try_detach_minecart(staticdata)
|
||||||
if not staticdata then return end
|
if not staticdata or not staticdata.connected_at then return end
|
||||||
|
if not mod:is_rail(staticdata.connected_at) then
|
||||||
-- Don't try to detach if alread detached
|
print("Detaching minecart"..tostring(staticdata.uuid))
|
||||||
if not staticdata.connected_at then return end
|
|
||||||
|
|
||||||
local node = minetest.get_node(staticdata.connected_at)
|
|
||||||
if minetest.get_item_group(node.name, "rail") == 0 then
|
|
||||||
detach_minecart(staticdata)
|
detach_minecart(staticdata)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -77,10 +73,10 @@ local function handle_cart_enter_exit(staticdata, pos, next_dir, event)
|
|||||||
-- Handle cart-specific behaviors
|
-- Handle cart-specific behaviors
|
||||||
if luaentity then
|
if luaentity then
|
||||||
local hook = luaentity["_mcl_minecarts_"..event]
|
local hook = luaentity["_mcl_minecarts_"..event]
|
||||||
|
if hook then hook(self, pos) end
|
||||||
else
|
else
|
||||||
minetest.log("warning", "TODO: chanve _mcl_minecarts_"..event.." calling so it is not dependent on the existence of a luaentity")
|
--minetest.log("warning", "TODO: change _mcl_minecarts_"..event.." calling so it is not dependent on the existence of a luaentity")
|
||||||
end
|
end
|
||||||
if hook then hook(self, pos) end
|
|
||||||
end
|
end
|
||||||
local function set_metadata_cart_status(pos, uuid, state)
|
local function set_metadata_cart_status(pos, uuid, state)
|
||||||
local meta = minetest.get_meta(pos)
|
local meta = minetest.get_meta(pos)
|
||||||
@ -117,6 +113,8 @@ local function handle_cart_node_watches(staticdata, dtime)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function handle_cart_collision(cart1_staticdata, prev_pos, next_dir)
|
local function handle_cart_collision(cart1_staticdata, prev_pos, next_dir)
|
||||||
|
if not cart1_staticdata then return end
|
||||||
|
|
||||||
-- Look ahead one block
|
-- Look ahead one block
|
||||||
local pos = vector.add(prev_pos, next_dir)
|
local pos = vector.add(prev_pos, next_dir)
|
||||||
|
|
||||||
@ -387,7 +385,7 @@ local function do_movement_step(staticdata, dtime)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Handle cart collisions
|
-- Handle cart collisions
|
||||||
handle_cart_collision(self, pos, next_dir)
|
handle_cart_collision(staticdata, pos, next_dir)
|
||||||
|
|
||||||
-- Leave the old node
|
-- Leave the old node
|
||||||
handle_cart_leave(staticdata, old_pos, next_dir )
|
handle_cart_leave(staticdata, old_pos, next_dir )
|
||||||
|
@ -54,6 +54,10 @@ function mod.destroy_cart_data(uuid)
|
|||||||
cart_data_fail_cache[uuid] = true
|
cart_data_fail_cache[uuid] = true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function mod.carts()
|
||||||
|
return pairs(cart_data)
|
||||||
|
end
|
||||||
|
|
||||||
function mod.find_carts_by_block_map(block_map)
|
function mod.find_carts_by_block_map(block_map)
|
||||||
local cart_list = {}
|
local cart_list = {}
|
||||||
for _,data in pairs(cart_data) do
|
for _,data in pairs(cart_data) do
|
||||||
@ -68,3 +72,8 @@ function mod.find_carts_by_block_map(block_map)
|
|||||||
return cart_list
|
return cart_list
|
||||||
end
|
end
|
||||||
|
|
||||||
|
minetest.register_on_shutdown(function()
|
||||||
|
for uuid,_ in pairs(cart_data) do
|
||||||
|
save_cart_data(uuid)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
Loading…
Reference in New Issue
Block a user