diff --git a/mods/ENTITIES/mcl_minecarts/carts.lua b/mods/ENTITIES/mcl_minecarts/carts.lua index 828a275d5..e2e105285 100644 --- a/mods/ENTITIES/mcl_minecarts/carts.lua +++ b/mods/ENTITIES/mcl_minecarts/carts.lua @@ -68,9 +68,8 @@ end -- Table for item-to-entity mapping. Keys: itemstring, Values: Corresponding entity ID local entity_mapping = {} -local function make_staticdata( railtype, connected_at, dir ) +local function make_staticdata( _, connected_at, dir ) return { - railtype = railtype, connected_at = connected_at, distance = 0, velocity = 0, @@ -122,12 +121,6 @@ function DEFAULT_CART_DEF:on_activate(staticdata, dtime_s) -- Initialize if type(data) == "table" then - -- Migrate old data - if data._railtype then - data.railtype = data._railtype - data._railtype = nil - end - -- Fix up types data.dir = vector.new(data.dir) @@ -194,11 +187,17 @@ function DEFAULT_CART_DEF:on_step(dtime) self._staticdata = staticdata end + + -- Update entity position + local pos = mod.get_cart_position(staticdata) + if pos then self.object:move_to(pos) end + -- Repair cart_type if not staticdata.cart_type then staticdata.cart_type = self.name end + -- Remove superceded entities if self._seq ~= staticdata.seq then print("removing cart #"..staticdata.uuid.." with sequence number mismatch") self.object:remove() @@ -207,22 +206,11 @@ function DEFAULT_CART_DEF:on_step(dtime) -- Regen local hp = self.object:get_hp() - if hp < MINECART_MAX_HP then - if (staticdata.regen_timer or 0) > 0.5 then - hp = hp + 1 - staticdata.regen_timer = staticdata.regen_timer - 1 - end - staticdata.regen_timer = (staticdata.regen_timer or 0) + dtime + local time_now = minetest.get_gametime() + if hp < MINECART_MAX_HP and staticdata.last_regen <= time_now - 1 then + staticdata.last_regen = time_now + hp = hp + 1 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 -- Cart specific behaviors @@ -256,27 +244,12 @@ function DEFAULT_CART_DEF:on_step(dtime) end end - if 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 + if not staticdata.connected_at then do_detached_movement(self, dtime) end - -- TODO: move this into mcl_core:cactus _mcl_minecarts_on_enter_side - -- 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 + mod.update_cart_orientation(self) + end function DEFAULT_CART_DEF:on_death(killer) local staticdata = self._staticdata @@ -325,7 +298,7 @@ function mcl_minecarts.place_minecart(itemstack, pointed_thing, placer) local spawn_pos = pointed_thing.above local cart_dir = vector.new(1,0,0) - local railtype, railpos, node + local railpos, node if mcl_minecarts:is_rail(pointed_thing.under) then railpos = pointed_thing.under 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 spawn_pos = 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), nil, nil, railtype) + cart_dir = mcl_minecarts:get_rail_direction(railpos, vector.new(1,0,0)) end 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)) + -- 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 local le = cart:get_luaentity() 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 - save_cart_data(le._staticdata.uuid) end -- Call placer @@ -361,7 +335,7 @@ function mcl_minecarts.place_minecart(itemstack, pointed_thing, placer) end if railpos then - handle_cart_enter(le, railpos) + handle_cart_enter(data, railpos) end 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) for z = min.z,max.z 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 end end @@ -545,10 +519,42 @@ minetest.register_globalstep(function(dtime) 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 + 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") 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) diff --git a/mods/ENTITIES/mcl_minecarts/functions.lua b/mods/ENTITIES/mcl_minecarts/functions.lua index a3b256022..40d5cd2d3 100644 --- a/mods/ENTITIES/mcl_minecarts/functions.lua +++ b/mods/ENTITIES/mcl_minecarts/functions.lua @@ -372,7 +372,7 @@ function mod.reverse_cart_direction(staticdata) staticdata.distance = 1 - (staticdata.distance or 0) -- 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 end diff --git a/mods/ENTITIES/mcl_minecarts/movement.lua b/mods/ENTITIES/mcl_minecarts/movement.lua index bccbb5d83..b7b389102 100644 --- a/mods/ENTITIES/mcl_minecarts/movement.lua +++ b/mods/ENTITIES/mcl_minecarts/movement.lua @@ -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 friction = mcl_minecarts.FRICTION local MAX_TRAIN_LENGTH = mod.MAX_TRAIN_LENGTH -DEBUG = true -mcl_debug = function(msg) print(msg) end +--DEBUG = false +--mcl_debug = function(msg) print(msg) end -- Imports local train_length = mod.train_length @@ -30,13 +30,9 @@ end mod.detach_minecart = detach_minecart local function try_detach_minecart(staticdata) - if not staticdata then return end - - -- Don't try to detach if alread detached - 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 + if not staticdata or not staticdata.connected_at then return end + if not mod:is_rail(staticdata.connected_at) then + print("Detaching minecart"..tostring(staticdata.uuid)) detach_minecart(staticdata) end end @@ -77,10 +73,10 @@ local function handle_cart_enter_exit(staticdata, pos, next_dir, event) -- Handle cart-specific behaviors if luaentity then local hook = luaentity["_mcl_minecarts_"..event] + if hook then hook(self, pos) end 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 - if hook then hook(self, pos) end end local function set_metadata_cart_status(pos, uuid, state) local meta = minetest.get_meta(pos) @@ -117,6 +113,8 @@ local function handle_cart_node_watches(staticdata, dtime) end local function handle_cart_collision(cart1_staticdata, prev_pos, next_dir) + if not cart1_staticdata then return end + -- Look ahead one block local pos = vector.add(prev_pos, next_dir) @@ -387,7 +385,7 @@ local function do_movement_step(staticdata, dtime) end -- Handle cart collisions - handle_cart_collision(self, pos, next_dir) + handle_cart_collision(staticdata, pos, next_dir) -- Leave the old node handle_cart_leave(staticdata, old_pos, next_dir ) diff --git a/mods/ENTITIES/mcl_minecarts/storage.lua b/mods/ENTITIES/mcl_minecarts/storage.lua index b31433c1d..c68942778 100644 --- a/mods/ENTITIES/mcl_minecarts/storage.lua +++ b/mods/ENTITIES/mcl_minecarts/storage.lua @@ -54,6 +54,10 @@ function mod.destroy_cart_data(uuid) cart_data_fail_cache[uuid] = true end +function mod.carts() + return pairs(cart_data) +end + function mod.find_carts_by_block_map(block_map) local cart_list = {} for _,data in pairs(cart_data) do @@ -68,3 +72,8 @@ function mod.find_carts_by_block_map(block_map) return cart_list end +minetest.register_on_shutdown(function() + for uuid,_ in pairs(cart_data) do + save_cart_data(uuid) + end +end)