Fix cart reproduction bugs
parent
6812c99ade
commit
b771ffcc6b
|
@ -149,6 +149,7 @@ History
|
||||||
2020-07-24 V1.08 Adapted to new techage ICTA style
|
2020-07-24 V1.08 Adapted to new techage ICTA style
|
||||||
2020-08-14 V1.09 Hopper support for digtron, protector:chest and default:furnace added
|
2020-08-14 V1.09 Hopper support for digtron, protector:chest and default:furnace added
|
||||||
2020-11-12 V1.10 Make carts more robust against server lag
|
2020-11-12 V1.10 Make carts more robust against server lag
|
||||||
2021-04-10 V2.00 Complete revision to make carts robust against server load/lag,
|
2021-04-10 V2.00 Complete revision to make carts robust against server load/lag,
|
||||||
Speed limit signs and cart terminal added
|
Speed limit signs and cart terminal added
|
||||||
2021-09-02 V2.01 Chat command /stopcart added
|
2021-09-02 V2.01 Chat command /stopcart added
|
||||||
|
2021-10-18 V2.02 Cart reproduction bug fixed
|
||||||
|
|
19
baselib.lua
19
baselib.lua
|
@ -257,9 +257,6 @@ function minecart.add_nodecart(pos, node_name, param2, cargo, owner, userID)
|
||||||
pos2 = minetest.find_node_near(pos, 1, minecart.lRails)
|
pos2 = minetest.find_node_near(pos, 1, minecart.lRails)
|
||||||
if not pos2 or not minecart.is_rail(pos2) then
|
if not pos2 or not minecart.is_rail(pos2) then
|
||||||
pos2 = minetest.find_node_near(pos, 2, minecart.lRails)
|
pos2 = minetest.find_node_near(pos, 2, minecart.lRails)
|
||||||
if not pos2 or not minecart.is_rail(pos2) then
|
|
||||||
pos2 = minetest.find_node_near(pos, 2, {"air"})
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
pos2 = vector.new(pos)
|
pos2 = vector.new(pos)
|
||||||
|
@ -282,8 +279,6 @@ function minecart.add_nodecart(pos, node_name, param2, cargo, owner, userID)
|
||||||
ndef.after_place_node(pos2)
|
ndef.after_place_node(pos2)
|
||||||
end
|
end
|
||||||
return pos2
|
return pos2
|
||||||
else
|
|
||||||
minetest.add_item(pos, ItemStack({name = node_name}))
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -363,10 +358,13 @@ function minecart.entity_to_node(pos, entity)
|
||||||
local dir = minetest.yaw_to_dir(rot.y)
|
local dir = minetest.yaw_to_dir(rot.y)
|
||||||
local facedir = minetest.dir_to_facedir(dir)
|
local facedir = minetest.dir_to_facedir(dir)
|
||||||
minecart.stop_recording(entity, pos)
|
minecart.stop_recording(entity, pos)
|
||||||
entity.object:remove()
|
|
||||||
local pos2 = minecart.add_nodecart(pos, entity.node_name, facedir, entity.cargo, entity.owner, entity.userID)
|
local pos2 = minecart.add_nodecart(pos, entity.node_name, facedir, entity.cargo, entity.owner, entity.userID)
|
||||||
minecart.stop_monitoring(entity.owner, entity.userID, pos2)
|
if pos2 then
|
||||||
minecart.monitoring_remove_cart(entity.owner, entity.userID)
|
minecart.stop_monitoring(entity.owner, entity.userID, pos2)
|
||||||
|
entity.object:remove()
|
||||||
|
else
|
||||||
|
minecart.start_entitycart(entity, pos, facedir)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function minecart.add_node_to_player_inventory(pos, player, node_name)
|
function minecart.add_node_to_player_inventory(pos, player, node_name)
|
||||||
|
@ -389,9 +387,10 @@ function minecart.remove_entity(self, pos, player)
|
||||||
minetest.sound_stop(self.sound_handle)
|
minetest.sound_stop(self.sound_handle)
|
||||||
self.sound_handle = nil
|
self.sound_handle = nil
|
||||||
end
|
end
|
||||||
minecart.add_node_to_player_inventory(pos, player, self.node_name or "minecart:cart")
|
if player then
|
||||||
|
minecart.add_node_to_player_inventory(pos, player, self.node_name or "minecart:cart")
|
||||||
|
end
|
||||||
minecart.stop_monitoring(self.owner, self.userID, pos)
|
minecart.stop_monitoring(self.owner, self.userID, pos)
|
||||||
minecart.stop_recording(self, pos)
|
minecart.stop_recording(self, pos)
|
||||||
minecart.monitoring_remove_cart(self.owner, self.userID)
|
|
||||||
self.object:remove()
|
self.object:remove()
|
||||||
end
|
end
|
||||||
|
|
15
buffer.lua
15
buffer.lua
|
@ -159,13 +159,16 @@ minetest.register_craft({
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_lbm({
|
minetest.register_lbm({
|
||||||
label = "Delete waiting times",
|
label = "Delete metadata",
|
||||||
name = "minecart:del_time",
|
name = "minecart:metadata",
|
||||||
nodenames = {"minecart:buffer"},
|
nodenames = {"minecart:buffer"},
|
||||||
run_at_every_load = false,
|
run_at_every_load = true,
|
||||||
action = function(pos, node)
|
action = function(pos, node)
|
||||||
-- delete old data
|
-- delete old metadata around the buffer (bugfix)
|
||||||
minecart.get_route(pos)
|
local pos1 = {x = pos.x - 2, y = pos.y - 2, z = pos.z - 2}
|
||||||
M(pos):set_string("formspec", formspec(pos))
|
local pos2 = {x = pos.x + 2, y = pos.y + 2, z = pos.z + 2}
|
||||||
|
for _, pos in ipairs(minetest.find_nodes_with_meta(pos1, pos2)) do
|
||||||
|
minecart.del_metadata(pos)
|
||||||
|
end
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
|
@ -186,7 +186,7 @@ local function play_sound(self)
|
||||||
if self.object then
|
if self.object then
|
||||||
self.sound_handle = minetest.sound_play(
|
self.sound_handle = minetest.sound_play(
|
||||||
"carts_cart_moving", {
|
"carts_cart_moving", {
|
||||||
object = self.object,
|
pos = self.object:get_pos(),
|
||||||
gain = (self.curr_speed or 0) / MAX_SPEED,
|
gain = (self.curr_speed or 0) / MAX_SPEED,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
4
init.lua
4
init.lua
|
@ -13,7 +13,7 @@
|
||||||
minecart = {}
|
minecart = {}
|
||||||
|
|
||||||
-- Version for compatibility checks, see readme.md/history
|
-- Version for compatibility checks, see readme.md/history
|
||||||
minecart.version = 2.01
|
minecart.version = 2.02
|
||||||
|
|
||||||
minecart.hopper_enabled = minetest.settings:get_bool("minecart_hopper_enabled") ~= false
|
minecart.hopper_enabled = minetest.settings:get_bool("minecart_hopper_enabled") ~= false
|
||||||
minecart.teleport_enabled = minetest.settings:get_bool("minecart_teleport_enabled") == true
|
minecart.teleport_enabled = minetest.settings:get_bool("minecart_teleport_enabled") == true
|
||||||
|
@ -35,7 +35,7 @@ dofile(MP .. "/api.lua")
|
||||||
dofile(MP .. "/minecart.lua")
|
dofile(MP .. "/minecart.lua")
|
||||||
dofile(MP .. "/buffer.lua")
|
dofile(MP .. "/buffer.lua")
|
||||||
dofile(MP .. "/protection.lua")
|
dofile(MP .. "/protection.lua")
|
||||||
--dofile(MP .. "/tool.lua") # for debugging only
|
--dofile(MP .. "/tool.lua") -- for debugging only
|
||||||
dofile(MP .. "/signs.lua")
|
dofile(MP .. "/signs.lua")
|
||||||
dofile(MP .. "/terminal.lua")
|
dofile(MP .. "/terminal.lua")
|
||||||
dofile(MP .. "/pusher.lua")
|
dofile(MP .. "/pusher.lua")
|
||||||
|
|
|
@ -68,9 +68,6 @@ local function get_checkpoint(cart)
|
||||||
cp = cart.checkpoints[cart.idx]
|
cp = cart.checkpoints[cart.idx]
|
||||||
end
|
end
|
||||||
local pos = H2P(cp[1])
|
local pos = H2P(cp[1])
|
||||||
-- if M(pos):contains("waypoints") then
|
|
||||||
-- print("get_checkpoint", P2S(H2P(cp[1])), P2S(H2P(cp[2])))
|
|
||||||
-- end
|
|
||||||
return cp, cart.idx == #cart.checkpoints
|
return cp, cart.idx == #cart.checkpoints
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -103,21 +100,41 @@ local function get_cart_info(owner, userID, query_pos)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function logging(cart, err)
|
||||||
|
local s = string.format("[Minecart] Cart %s/%u %s!", cart.owner, cart.userID, err)
|
||||||
|
minetest.log("warning", s)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- check cart data
|
||||||
|
local function valid_cart(cart)
|
||||||
|
if cart.objID == nil or cart.objID == 0 then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
if tCartsOnRail[cart.owner] and tCartsOnRail[cart.owner][cart.userID] then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
logging(cart, "with invalid data")
|
||||||
|
local entity = minetest.luaentities[cart.objID]
|
||||||
|
if entity then
|
||||||
|
entity.object:remove()
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
local function monitoring(cycle)
|
local function monitoring(cycle)
|
||||||
local cart = pop(cycle)
|
local cart = pop(cycle)
|
||||||
|
|
||||||
|
-- All running cars
|
||||||
while cart do
|
while cart do
|
||||||
-- All running cars
|
if valid_cart(cart) then
|
||||||
if cart.objID and cart.objID ~= 0 then
|
|
||||||
cart.idx = cart.idx + 1
|
cart.idx = cart.idx + 1
|
||||||
local entity = minetest.luaentities[cart.objID]
|
local entity = minetest.luaentities[cart.objID]
|
||||||
if entity then -- cart entity running
|
if entity then -- cart entity running
|
||||||
local pos = entity.object:get_pos()
|
local pos = entity.object:get_pos()
|
||||||
if pos then
|
if pos then
|
||||||
cart.last_pos = vector.round(pos)
|
cart.last_pos = vector.round(pos)
|
||||||
--print("entity card " .. cart.userID .. " at " .. P2S(cart.last_pos))
|
|
||||||
else
|
else
|
||||||
minetest.log("warning", "[Minecart] entity card without pos!")
|
logging(cart, "without pos")
|
||||||
end
|
end
|
||||||
push(cycle, cart)
|
push(cycle, cart)
|
||||||
elseif cart.checkpoints then
|
elseif cart.checkpoints then
|
||||||
|
@ -130,16 +147,15 @@ local function monitoring(cycle)
|
||||||
end
|
end
|
||||||
push(cycle, cart)
|
push(cycle, cart)
|
||||||
else
|
else
|
||||||
minetest.log("warning", "[Minecart] zombie got lost")
|
logging(cart, "as zombie got lost")
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
local pos = cart.last_pos or cart.pos
|
local pos = cart.last_pos or cart.pos
|
||||||
pos = minecart.add_nodecart(pos, cart.node_name, 0, cart.cargo, cart.owner, cart.userID)
|
pos = minecart.add_nodecart(pos, cart.node_name, 0, cart.cargo, cart.owner, cart.userID)
|
||||||
cart.objID = 0
|
minecart.stop_monitoring(cart.owner, cart.userID, pos)
|
||||||
cart.pos = pos
|
logging(cart, "stopped at " .. P2S(pos))
|
||||||
--print("cart to node", cycle, cart.userID, P2S(pos))
|
|
||||||
end
|
end
|
||||||
elseif cart and not cart.objID and tCartsOnRail[cart.owner] then
|
elseif not cart.objID and tCartsOnRail[cart.owner] then
|
||||||
-- Delete carts marked as "to be deleted"
|
-- Delete carts marked as "to be deleted"
|
||||||
tCartsOnRail[cart.owner][cart.userID] = nil
|
tCartsOnRail[cart.owner][cart.userID] = nil
|
||||||
end
|
end
|
||||||
|
@ -184,6 +200,7 @@ function minecart.stop_monitoring(owner, userID, pos)
|
||||||
--print("stop_monitoring", owner, userID)
|
--print("stop_monitoring", owner, userID)
|
||||||
if tCartsOnRail[owner] and tCartsOnRail[owner][userID] then
|
if tCartsOnRail[owner] and tCartsOnRail[owner][userID] then
|
||||||
tCartsOnRail[owner][userID].pos = pos
|
tCartsOnRail[owner][userID].pos = pos
|
||||||
|
-- Mark as "stopped"
|
||||||
tCartsOnRail[owner][userID].objID = 0
|
tCartsOnRail[owner][userID].objID = 0
|
||||||
minecart.store_carts()
|
minecart.store_carts()
|
||||||
end
|
end
|
||||||
|
@ -192,14 +209,20 @@ end
|
||||||
function minecart.monitoring_remove_cart(owner, userID)
|
function minecart.monitoring_remove_cart(owner, userID)
|
||||||
--print("monitoring_remove_cart", owner, userID)
|
--print("monitoring_remove_cart", owner, userID)
|
||||||
if tCartsOnRail[owner] and tCartsOnRail[owner][userID] then
|
if tCartsOnRail[owner] and tCartsOnRail[owner][userID] then
|
||||||
tCartsOnRail[owner][userID].objID = nil
|
-- Cart stopped?
|
||||||
tCartsOnRail[owner][userID] = nil
|
if tCartsOnRail[owner][userID].objID == 0 then
|
||||||
|
-- Can directly be deleted
|
||||||
|
tCartsOnRail[owner][userID] = nil
|
||||||
|
else -- Cart running
|
||||||
|
-- Mark as "to be deleted" by monitoring
|
||||||
|
tCartsOnRail[owner][userID].objID = nil
|
||||||
|
end
|
||||||
minecart.store_carts()
|
minecart.store_carts()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function minecart.monitoring_valid_cart(owner, userID, pos, node_name)
|
function minecart.monitoring_valid_cart(owner, userID, pos, node_name)
|
||||||
if tCartsOnRail[owner] and tCartsOnRail[owner][userID] then
|
if tCartsOnRail[owner] and tCartsOnRail[owner][userID] and tCartsOnRail[owner][userID].pos then
|
||||||
return vector.equals(tCartsOnRail[owner][userID].pos, pos) and
|
return vector.equals(tCartsOnRail[owner][userID].pos, pos) and
|
||||||
tCartsOnRail[owner][userID].node_name == node_name
|
tCartsOnRail[owner][userID].node_name == node_name
|
||||||
end
|
end
|
||||||
|
@ -245,28 +268,38 @@ minetest.register_chatcommand("mycart", {
|
||||||
|
|
||||||
minetest.register_chatcommand("stopcart", {
|
minetest.register_chatcommand("stopcart", {
|
||||||
params = "<cart-num>",
|
params = "<cart-num>",
|
||||||
description = S("Stop amd return a missing/running cart."),
|
description = S("Stop and return/drop a missing/running cart."),
|
||||||
func = function(owner, param)
|
func = function(owner, param)
|
||||||
local userID = tonumber(param)
|
local userID = tonumber(param)
|
||||||
local player_pos = minetest.get_player_by_name(owner):get_pos()
|
local player_pos = minetest.get_player_by_name(owner):get_pos()
|
||||||
if userID then
|
if userID then
|
||||||
local data = minecart.get_cart_monitoring_data(owner, userID)
|
local data = minecart.get_cart_monitoring_data(owner, userID)
|
||||||
if data then
|
if data and data.objID then
|
||||||
if data.objID and data.objID ~= 0 then
|
local entity = minetest.luaentities[data.objID]
|
||||||
local entity = minetest.luaentities[data.objID]
|
--print("stopcart", userID, data.pos, data.objID, entity)
|
||||||
if entity then -- cart entity running
|
if data.objID == 0 then
|
||||||
minecart.entity_to_node(player_pos, entity)
|
-- Cart as node
|
||||||
|
if data.pos then
|
||||||
|
local meta = M(data.pos)
|
||||||
|
if owner == meta:get_string("owner") and userID == meta:get_int("userID") then
|
||||||
|
minecart.remove_nodecart(data.pos)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
elseif entity then
|
||||||
|
-- Cart as entity
|
||||||
|
minecart.remove_entity(entity, data.pos)
|
||||||
else
|
else
|
||||||
local pos = data.last_pos or data.pos
|
-- Cart as zombie/invalid/corrupted
|
||||||
local cargo, _, _ = minecart.remove_nodecart(pos)
|
-- nothing to do
|
||||||
minecart.add_nodecart(player_pos, data.node_name, 0, cargo, owner, userID)
|
|
||||||
minecart.monitoring_remove_cart(owner, userID)
|
|
||||||
end
|
end
|
||||||
return true, S("Cart") .. " " .. userID .. " " .. S("stopped")
|
minetest.add_item(player_pos, ItemStack({name = data.node_name}))
|
||||||
|
minecart.monitoring_remove_cart(owner, userID)
|
||||||
|
return true, S("Cart") .. " " .. userID .. " " .. S("dropped")
|
||||||
else
|
else
|
||||||
return false, S("Cart") .. " " .. userID .. " " .. S("is not existing!")
|
return false, S("Cart") .. " " .. userID .. " " .. S("is not existing!")
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
|
|
@ -585,6 +585,9 @@ end
|
||||||
-- minecart.get_next_buffer(pos, facedir)
|
-- minecart.get_next_buffer(pos, facedir)
|
||||||
minecart.get_next_buffer = get_next_buffer
|
minecart.get_next_buffer = get_next_buffer
|
||||||
|
|
||||||
|
-- minecart.del_metadata(pos)
|
||||||
|
minecart.del_metadata = del_metadata
|
||||||
|
|
||||||
--minetest.register_lbm({
|
--minetest.register_lbm({
|
||||||
-- label = "Delete waypoints",
|
-- label = "Delete waypoints",
|
||||||
-- name = "minecart:del_meta",
|
-- name = "minecart:del_meta",
|
||||||
|
|
31
storage.lua
31
storage.lua
|
@ -50,30 +50,15 @@ minetest.register_on_mods_loaded(function()
|
||||||
else
|
else
|
||||||
local t = minetest.deserialize(storage:get_string("CartsOnRail")) or {}
|
local t = minetest.deserialize(storage:get_string("CartsOnRail")) or {}
|
||||||
for owner, carts in pairs(t) do
|
for owner, carts in pairs(t) do
|
||||||
minecart.CartsOnRail[owner] = {}
|
minecart.CartsOnRail[owner] = minecart.CartsOnRail[owner] or {}
|
||||||
for userID, cart in pairs(carts) do
|
for userID, cart in pairs(carts) do
|
||||||
print("reload cart", owner, userID, cart.objID)
|
if cart.objID then
|
||||||
minecart.CartsOnRail[owner][userID] = cart
|
minecart.CartsOnRail[owner][userID] = cart
|
||||||
-- mark all entity carts as zombified
|
-- mark all entity carts as zombified
|
||||||
if cart.objID and cart.objID ~= 0 then
|
if cart.objID ~= 0 then
|
||||||
cart.objID = -1
|
cart.objID = -1
|
||||||
minecart.push(1, cart)
|
minecart.push(1, cart)
|
||||||
end
|
end
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
minetest.after(10, function()
|
|
||||||
for owner, carts in pairs(minecart.CartsOnRail) do
|
|
||||||
for userID, cart in pairs(carts) do
|
|
||||||
-- Remove node carts that are not available anymore
|
|
||||||
if cart.pos and (cart.objID == 0 or not cart.objID) then
|
|
||||||
local node = minecart.get_node_lvm(cart.pos)
|
|
||||||
if not minecart.tNodeNames[node.name] then
|
|
||||||
-- Mark as "to be deleted"
|
|
||||||
print("Node cart deleted", owner, userID)
|
|
||||||
minecart.CartsOnRail[owner][userID] = nil
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
3
tool.lua
3
tool.lua
|
@ -78,7 +78,8 @@ local function click_left(itemstack, placer, pointed_thing)
|
||||||
if pointed_thing.type == "node" then
|
if pointed_thing.type == "node" then
|
||||||
local pos = pointed_thing.under
|
local pos = pointed_thing.under
|
||||||
if minecart.is_rail(pos) then
|
if minecart.is_rail(pos) then
|
||||||
test_get_buffer(pos, placer)
|
--test_get_buffer(pos, placer)
|
||||||
|
minecart.delete_waypoint(pos)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue