added trackdb and unloaded wagons handling
parent
2c864564d2
commit
62f5e05c09
46
helpers.lua
46
helpers.lua
|
@ -58,22 +58,18 @@ rely1, rely2 tell to which height the connections are pointed to. 1 means it wil
|
|||
|
||||
]]
|
||||
|
||||
function advtrains.conway(midreal, prev, drives_on)--in order prev,mid,return
|
||||
function advtrains.conway(midreal, prev, traintype)--in order prev,mid,return
|
||||
local mid=advtrains.round_vector_floor_y(midreal)
|
||||
if(not advtrains.is_track_and_drives_on(minetest.get_node(mid).name, drives_on)) then
|
||||
--print("[advtrains]in conway: no rail, returning!")
|
||||
local drives_on=advtrains.all_traintypes[traintype].drives_on
|
||||
|
||||
if not advtrains.get_rail_info_at(advtrains.round_vector_floor_y(prev), traintype) then
|
||||
return nil
|
||||
end
|
||||
if(not prev or not advtrains.is_track_and_drives_on(minetest.get_node(advtrains.round_vector_floor_y(prev)).name, drives_on)) then
|
||||
--print("[advtrains]in conway: no prev rail, there should be an initial path!, returning!")
|
||||
return nil
|
||||
end
|
||||
local midnode=minetest.get_node_or_nil(mid)
|
||||
if not midnode then --print("[advtrains][conway] midnode is ignore")
|
||||
return nil
|
||||
end
|
||||
|
||||
local middir1, middir2, midrely1, midrely2=advtrains.get_track_connections(midnode.name, midnode.param2)
|
||||
local midnode_ok, middir1, middir2, midrely1, midrely2=advtrains.get_rail_info_at(advtrains.round_vector_floor_y(mid), traintype)
|
||||
if not midnode_ok then
|
||||
return nil
|
||||
end
|
||||
|
||||
local next, chkdir, chkrely, y_offset
|
||||
y_offset=0
|
||||
|
@ -110,29 +106,21 @@ function advtrains.conway(midreal, prev, drives_on)--in order prev,mid,return
|
|||
print("[advtrains]in conway: no next rail(nil), returning!")
|
||||
return nil
|
||||
end
|
||||
local nextnode=minetest.get_node_or_nil(advtrains.round_vector_floor_y(next))
|
||||
if not nextnode then print("[advtrains][conway] nextnode is ignore")
|
||||
return nil
|
||||
end
|
||||
|
||||
local nextnode_ok, nextdir1, nextdir2, nextrely1, nextrely2, nextrailheight=advtrains.get_rail_info_at(advtrains.round_vector_floor_y(mid), traintype)
|
||||
|
||||
--is it a rail?
|
||||
if(not advtrains.is_track_and_drives_on(nextnode.name, drives_on)) then
|
||||
if(not nextnode_ok) then
|
||||
print("[advtrains]in conway: next "..minetest.pos_to_string(next).." not a rail, trying one node below!")
|
||||
next.y=next.y-1
|
||||
y_offset=y_offset-1
|
||||
|
||||
nextnode=minetest.get_node_or_nil(advtrains.round_vector_floor_y(next))
|
||||
if not nextnode then --print("[advtrains][conway] nextnode is ignore")
|
||||
return nil
|
||||
end
|
||||
if(not advtrains.is_track_and_drives_on(nextnode.name, drives_on)) then
|
||||
nextnode_ok, nextdir1, nextdir2, nextrely1, nextrely2, nextrailheight=advtrains.get_rail_info_at(advtrains.round_vector_floor_y(mid), traintype)
|
||||
if(not nextnode_ok) then
|
||||
print("[advtrains]in conway: one below "..minetest.pos_to_string(next).." is not a rail either, returning!")
|
||||
return nil
|
||||
end
|
||||
end
|
||||
--print("[advtrains]trying to find if rail connects: "..(next and minetest.pos_to_string(next) or "nil").."(chkdir is "..(chkdir or "nil")..", y-offset "..y_offset..")")
|
||||
|
||||
local nextdir1, nextdir2, nextrely1, nextrely2, nextrailheight=advtrains.get_track_connections(nextnode.name, nextnode.param2)
|
||||
|
||||
--is this next rail connecting to the mid?
|
||||
if not ( (((nextdir1+4)%8)==chkdir and nextrely1==chkrely-y_offset) or (((nextdir2+4)%8)==chkdir and nextrely2==chkrely-y_offset) ) then
|
||||
|
@ -140,9 +128,13 @@ function advtrains.conway(midreal, prev, drives_on)--in order prev,mid,return
|
|||
next.y=next.y-1
|
||||
y_offset=y_offset-1
|
||||
|
||||
nextdir1, nextdir2, nextrely1, nextrely2, nextrailheight=advtrains.get_track_connections(nextnode.name, nextnode.param2)
|
||||
nextnode_ok, nextdir1, nextdir2, nextrely1, nextrely2, nextrailheight=advtrains.get_rail_info_at(advtrains.round_vector_floor_y(mid), traintype)
|
||||
if(not nextnode_ok) then
|
||||
print("[advtrains]in conway: (at connecting if check again) one below "..minetest.pos_to_string(next).." is not a rail either, returning!")
|
||||
return nil
|
||||
end
|
||||
if not ( (((nextdir1+4)%8)==chkdir and nextrely1==chkrely) or (((nextdir2+4)%8)==chkdir and nextrely2==chkrely) ) then
|
||||
print("[advtrains]in conway: next "..minetest.pos_to_string(next).." rail not connecting, returning!")
|
||||
print("[advtrains]in conway: one below "..minetest.pos_to_string(next).." rail not connecting, returning!")
|
||||
--print("[advtrains] in order mid1,2,next1,2,chkdir "..middir1.." "..middir2.." "..nextdir1.." "..nextdir2.." "..chkdir)
|
||||
return nil
|
||||
end
|
||||
|
|
50
helpers.lua~
50
helpers.lua~
|
@ -58,22 +58,18 @@ rely1, rely2 tell to which height the connections are pointed to. 1 means it wil
|
|||
|
||||
]]
|
||||
|
||||
function advtrains.conway(midreal, prev, drives_on)--in order prev,mid,return
|
||||
function advtrains.conway(midreal, prev, traintype)--in order prev,mid,return
|
||||
local mid=advtrains.round_vector_floor_y(midreal)
|
||||
if(not advtrains.is_track_and_drives_on(minetest.get_node(mid).name, drives_on)) then
|
||||
--print("[advtrains]in conway: no rail, returning!")
|
||||
local drives_on=advtrains.all_traintypes[traintype].drives_on
|
||||
|
||||
if not advtrains.get_rail_info_at(advtrains.round_vector_floor_y(prev), traintype) then
|
||||
return nil
|
||||
end
|
||||
if(not prev or not advtrains.is_track_and_drives_on(minetest.get_node(advtrains.round_vector_floor_y(prev)).name, drives_on)) then
|
||||
--print("[advtrains]in conway: no prev rail, there should be an initial path!, returning!")
|
||||
return nil
|
||||
end
|
||||
local midnode=minetest.get_node_or_nil(mid)
|
||||
if not midnode then --print("[advtrains][conway] midnode is ignore")
|
||||
return nil
|
||||
end
|
||||
|
||||
local middir1, middir2, midrely1, midrely2=advtrains.get_track_connections(midnode.name, midnode.param2)
|
||||
local midnode_ok, middir1, middir2, midrely1, midrely2=advtrains.get_rail_info_at(advtrains.round_vector_floor_y(mid), traintype)
|
||||
if not midnode_ok then
|
||||
return nil
|
||||
end
|
||||
|
||||
local next, chkdir, chkrely, y_offset
|
||||
y_offset=0
|
||||
|
@ -110,29 +106,21 @@ function advtrains.conway(midreal, prev, drives_on)--in order prev,mid,return
|
|||
print("[advtrains]in conway: no next rail(nil), returning!")
|
||||
return nil
|
||||
end
|
||||
local nextnode=minetest.get_node_or_nil(advtrains.round_vector_floor_y(next))
|
||||
if not nextnode then print("[advtrains][conway] nextnode is ignore")
|
||||
return nil
|
||||
end
|
||||
|
||||
local nextnode_ok, nextdir1, nextdir2, nextrely1, nextrely2, nextrailheight=advtrains.get_rail_info_at(advtrains.round_vector_floor_y(mid), traintype)
|
||||
|
||||
--is it a rail?
|
||||
if(not advtrains.is_track_and_drives_on(nextnode.name, drives_on)) then
|
||||
if(not nextnode_ok) then
|
||||
print("[advtrains]in conway: next "..minetest.pos_to_string(next).." not a rail, trying one node below!")
|
||||
next.y=next.y-1
|
||||
y_offset=y_offset-1
|
||||
|
||||
nextnode=minetest.get_node_or_nil(advtrains.round_vector_floor_y(next))
|
||||
if not nextnode then --print("[advtrains][conway] nextnode is ignore")
|
||||
return nil
|
||||
end
|
||||
if(not advtrains.is_track_and_drives_on(nextnode.name, drives_on)) then
|
||||
nextnode_ok, nextdir1, nextdir2, nextrely1, nextrely2, nextrailheight=advtrains.get_rail_info_at(advtrains.round_vector_floor_y(mid), traintype)
|
||||
if(not nextnode_ok) then
|
||||
print("[advtrains]in conway: one below "..minetest.pos_to_string(next).." is not a rail either, returning!")
|
||||
return nil
|
||||
end
|
||||
end
|
||||
--print("[advtrains]trying to find if rail connects: "..(next and minetest.pos_to_string(next) or "nil").."(chkdir is "..(chkdir or "nil")..", y-offset "..y_offset..")")
|
||||
|
||||
local nextdir1, nextdir2, nextrely1, nextrely2, nextrailheight=advtrains.get_track_connections(nextnode.name, nextnode.param2)
|
||||
|
||||
--is this next rail connecting to the mid?
|
||||
if not ( (((nextdir1+4)%8)==chkdir and nextrely1==chkrely-y_offset) or (((nextdir2+4)%8)==chkdir and nextrely2==chkrely-y_offset) ) then
|
||||
|
@ -140,8 +128,8 @@ function advtrains.conway(midreal, prev, drives_on)--in order prev,mid,return
|
|||
next.y=next.y-1
|
||||
y_offset=y_offset-1
|
||||
|
||||
nextdir1, nextdir2, nextrely1, nextrely2, nextrailheight=advtrains.get_track_connections(nextnode.name, nextnode.param2)
|
||||
if not ( (((nextdir1+4)%8)==chkdir and nextrely1==chkrely) or (((nextdir2+4)%8)==chkdir and nextrely2==chkrely) ) then
|
||||
nextnode_ok, nextdir1, nextdir2, nextrely1, nextrely2, nextrailheight=advtrains.get_rail_info_at(advtrains.round_vector_floor_y(mid), traintype)
|
||||
if not nextnode_ok or not ( (((nextdir1+4)%8)==chkdir and nextrely1==chkrely) or (((nextdir2+4)%8)==chkdir and nextrely2==chkrely) ) then
|
||||
print("[advtrains]in conway: next "..minetest.pos_to_string(next).." rail not connecting, returning!")
|
||||
--print("[advtrains] in order mid1,2,next1,2,chkdir "..middir1.." "..middir2.." "..nextdir1.." "..nextdir2.." "..chkdir)
|
||||
return nil
|
||||
|
@ -199,17 +187,17 @@ function advtrains.merge_tables(a, ...)
|
|||
end
|
||||
function advtrains.yaw_from_3_positions(prev, curr, next)
|
||||
local pts=minetest.pos_to_string
|
||||
print("p3 "..pts(prev)..pts(curr)..pts(next))
|
||||
--print("p3 "..pts(prev)..pts(curr)..pts(next))
|
||||
local prev2curr=math.atan2((curr.x-prev.x), (prev.z-curr.z))
|
||||
local curr2next=math.atan2((next.x-curr.x), (curr.z-next.z))
|
||||
print("y3 "..(prev2curr*360/(2*math.pi)).." "..(curr2next*360/(2*math.pi)))
|
||||
--print("y3 "..(prev2curr*360/(2*math.pi)).." "..(curr2next*360/(2*math.pi)))
|
||||
return prev2curr+(advtrains.minAngleDiffRad(prev2curr, curr2next)/2)
|
||||
end
|
||||
function advtrains.get_wagon_yaw(front, first, second, back, pct)
|
||||
local pts=minetest.pos_to_string
|
||||
print("p "..pts(front)..pts(first)..pts(second)..pts(back))
|
||||
--print("p "..pts(front)..pts(first)..pts(second)..pts(back))
|
||||
local y2=advtrains.yaw_from_3_positions(second, first, front)
|
||||
local y1=advtrains.yaw_from_3_positions(back, second, first)
|
||||
print("y "..(y1*360/(2*math.pi)).." "..(y2*360/(2*math.pi)))
|
||||
--print("y "..(y1*360/(2*math.pi)).." "..(y2*360/(2*math.pi)))
|
||||
return y1+advtrains.minAngleDiffRad(y1, y2)*pct
|
||||
end
|
||||
|
|
149
pseudoload.lua
149
pseudoload.lua
|
@ -3,84 +3,92 @@
|
|||
--responsible for keeping up a database of all rail nodes existant in the world, regardless of whether the mapchunk is loaded.
|
||||
|
||||
advtrains.trackdb={}
|
||||
--trackdb[y][x][z]={conn1, conn2, rely1, rely2, railheight}
|
||||
--trackdb[tt][y][x][z]={conn1, conn2, rely1, rely2, railheight}
|
||||
--serialization format:
|
||||
--(2byte x)(2byte y)(2byte z)(4bits conn1, 4bits conn2)[(plain rely1)|(plain rely2)|(plain railheight)]\n
|
||||
--[] may be missing if 0,0,0
|
||||
|
||||
--load initially
|
||||
advtrains.pl_fpath=minetest.get_worldpath().."/advtrains_trackdb"
|
||||
local file, err = io.open(advtrains.pl_fpath, "r")
|
||||
if not file then
|
||||
local er=err or "Unknown Error"
|
||||
print("[advtrains]Failed loading advtrains trackdb save file "..er)
|
||||
else
|
||||
--custom format to save memory
|
||||
while true do
|
||||
local xbytes=file:read(2)
|
||||
if not xbytes then
|
||||
break --eof reached
|
||||
end
|
||||
local ybytes=file:read(2)
|
||||
local zbytes=file:read(2)
|
||||
local x=(string.byte(xbytes[1])-128)*256+(string.byte(xbytes[2]))
|
||||
local y=(string.byte(ybytes[1])-128)*256+(string.byte(ybytes[2]))
|
||||
local z=(string.byte(zbytes[1])-128)*256+(string.byte(zbytes[2]))
|
||||
|
||||
local conn1=string.byte(file:read(1))
|
||||
local conn1=string.byte(file:read(1))
|
||||
|
||||
if not advtrains.trackdb[y] then advtrains.trackdb[y]={} end
|
||||
if not advtrains.trackdb[y][x] then advtrains.trackdb[y][x]={} end
|
||||
|
||||
local rest=file.read("*l")
|
||||
if rest~="" then
|
||||
local rely1, rely2, railheight=string.match(rest, "([^|]+)|([^|]+)|([^|]+)")
|
||||
if rely1 and rely2 and railheight then
|
||||
advtrains.trackdb[y][x][z]={
|
||||
conn1=conn1, conn2=conn2,
|
||||
rely1=rely1, rely2=rely2,
|
||||
railheight=railheight
|
||||
}
|
||||
for tt, _ in pairs(advtrains.all_traintypes) do
|
||||
local pl_fpath=minetest.get_worldpath().."/advtrains_trackdb_"..tt
|
||||
advtrains.trackdb[tt]={}
|
||||
local file, err = io.open(pl_fpath, "r")
|
||||
if not file then
|
||||
local er=err or "Unknown Error"
|
||||
print("[advtrains]Failed loading advtrains trackdb save file "..er)
|
||||
else
|
||||
--custom format to save memory
|
||||
while true do
|
||||
local xbytes=file:read(2)
|
||||
if not xbytes then
|
||||
break --eof reached
|
||||
end
|
||||
local ybytes=file:read(2)
|
||||
local zbytes=file:read(2)
|
||||
local x=(string.byte(xbytes[1])-128)*256+(string.byte(xbytes[2]))
|
||||
local y=(string.byte(ybytes[1])-128)*256+(string.byte(ybytes[2]))
|
||||
local z=(string.byte(zbytes[1])-128)*256+(string.byte(zbytes[2]))
|
||||
|
||||
local conn1=string.byte(file:read(1))
|
||||
local conn1=string.byte(file:read(1))
|
||||
|
||||
if not advtrains.trackdb[tt][y] then advtrains.trackdb[tt][y]={} end
|
||||
if not advtrains.trackdb[tt][y][x] then advtrains.trackdb[tt][y][x]={} end
|
||||
|
||||
local rest=file.read("*l")
|
||||
if rest~="" then
|
||||
local rely1, rely2, railheight=string.match(rest, "([^|]+)|([^|]+)|([^|]+)")
|
||||
if rely1 and rely2 and railheight then
|
||||
advtrains.trackdb[tt][y][x][z]={
|
||||
conn1=conn1, conn2=conn2,
|
||||
rely1=rely1, rely2=rely2,
|
||||
railheight=railheight
|
||||
}
|
||||
else
|
||||
advtrains.trackdb[tt][y][x][z]={
|
||||
conn1=conn1, conn2=conn2
|
||||
}
|
||||
end
|
||||
else
|
||||
advtrains.trackdb[y][x][z]={
|
||||
advtrains.trackdb[tt][y][x][z]={
|
||||
conn1=conn1, conn2=conn2
|
||||
}
|
||||
end
|
||||
else
|
||||
advtrains.trackdb[y][x][z]={
|
||||
conn1=conn1, conn2=conn2
|
||||
}
|
||||
end
|
||||
end
|
||||
file:close()
|
||||
end
|
||||
function advtrains.save_trackdb()
|
||||
local file, err = io.open(advtrains.pl_fpath, "w")
|
||||
if not file then
|
||||
local er=err or "Unknown Error"
|
||||
print("[advtrains]Failed saving advtrains trackdb save file "..er)
|
||||
else
|
||||
--custom format to save memory
|
||||
for x,txl in pairs(advtrains.trackdb) do
|
||||
for y,tyl in pairs(txl) do
|
||||
for z,rail in pairs(tyl) do
|
||||
file:write(string.char(math.floor(x/256)+128)..string.char((x%256)))
|
||||
file:write(string.char(math.floor(y/256)+128)..string.char((y%256)))
|
||||
file:write(string.char(math.floor(z/256)+128)..string.char((z%256)))
|
||||
file:write(string.char(rail.conn1))
|
||||
file:write(string.char(rail.conn2))
|
||||
if (rail.rely1 and rail.rely1~=0) or (rail.rely2 and rail.rely2~=0) or (rail.railheight and rail.railheight~=0) then
|
||||
file:write(rail.rely1.."|"..rail.rely2.."|"..rail.railheight)
|
||||
end
|
||||
file:write("\n")
|
||||
end
|
||||
end
|
||||
end
|
||||
file:close()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function advtrains.save_trackdb()
|
||||
for tt, _ in pairs(advtrains.all_traintypes) do
|
||||
local pl_fpath=minetest.get_worldpath().."/advtrains_trackdb_"..tt
|
||||
local file, err = io.open(pl_fpath, "w")
|
||||
if not file then
|
||||
local er=err or "Unknown Error"
|
||||
print("[advtrains]Failed saving advtrains trackdb save file "..er)
|
||||
else
|
||||
--custom format to save memory
|
||||
for x,txl in pairs(advtrains.trackdb[tt]) do
|
||||
for y,tyl in pairs(txl) do
|
||||
for z,rail in pairs(tyl) do
|
||||
file:write(string.char(math.floor(x/256)+128)..string.char((x%256)))
|
||||
file:write(string.char(math.floor(y/256)+128)..string.char((y%256)))
|
||||
file:write(string.char(math.floor(z/256)+128)..string.char((z%256)))
|
||||
file:write(string.char(rail.conn1))
|
||||
file:write(string.char(rail.conn2))
|
||||
if (rail.rely1 and rail.rely1~=0) or (rail.rely2 and rail.rely2~=0) or (rail.railheight and rail.railheight~=0) then
|
||||
file:write(rail.rely1.."|"..rail.rely2.."|"..rail.railheight)
|
||||
end
|
||||
file:write("\n")
|
||||
end
|
||||
end
|
||||
end
|
||||
file:close()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--get_node with pseudoload.
|
||||
--returns:
|
||||
--true, conn1, conn2, rely1, rely2, railheight in case everything's right.
|
||||
|
@ -92,7 +100,7 @@ function advtrains.get_rail_info_at(pos, traintype)
|
|||
if not node then
|
||||
--try raildb
|
||||
local rdp=vector.round(rdp)
|
||||
local dbe=advtrains.trackdb[rdp.y][rdp.x][rdp.z]
|
||||
local dbe=advtrains.trackdb[traintype][rdp.y][rdp.x][rdp.z]
|
||||
if dbe then
|
||||
return true, dbe.conn1, dbe.conn2, dbe.rely1 or 0, dbe.rely2 or 0, dbe.railheight or 0
|
||||
else
|
||||
|
@ -107,7 +115,7 @@ function advtrains.get_rail_info_at(pos, traintype)
|
|||
|
||||
--already in trackdb?
|
||||
local rdp=vector.round(rdp)
|
||||
if not advtrains.trackdb[rdp.y][rdp.x][rdp.z] then--TODO is this write prevention here really needed?
|
||||
if not advtrains.trackdb[traintype][rdp.y][rdp.x][rdp.z] then--TODO is this necessary?
|
||||
advtrains.trackdb[rdp.y][rdp.x][rdp.z]={
|
||||
conn1=conn1, conn2=conn2,
|
||||
rely1=rely1, rely2=rely2,
|
||||
|
@ -117,5 +125,12 @@ function advtrains.get_rail_info_at(pos, traintype)
|
|||
|
||||
return true, conn1, conn2, rely1, rely2, railheight
|
||||
end
|
||||
|
||||
function advtrains.reset_trackdb_position(pos)
|
||||
local rdp=vector.round(pos)
|
||||
for tt, _ in pairs(advtrains.all_traintypes) do
|
||||
advtrains.trackdb[tt][rdp.y][rdp.x][rdp.z]=nil
|
||||
advtrains.get_rail_info_at(pos, tt)--to restore it.
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
|
142
pseudoload.lua~
142
pseudoload.lua~
|
@ -3,96 +3,104 @@
|
|||
--responsible for keeping up a database of all rail nodes existant in the world, regardless of whether the mapchunk is loaded.
|
||||
|
||||
advtrains.trackdb={}
|
||||
--trackdb[y][x][z]={conn1, conn2, rely1, rely2, railheight}
|
||||
--trackdb[tt][y][x][z]={conn1, conn2, rely1, rely2, railheight}
|
||||
--serialization format:
|
||||
--(2byte x)(2byte y)(2byte z)(4bits conn1, 4bits conn2)[(plain rely1)|(plain rely2)|(plain railheight)]\n
|
||||
--[] may be missing if 0,0,0
|
||||
|
||||
--load initially
|
||||
advtrains.pl_fpath=minetest.get_worldpath().."/advtrains_trackdb"
|
||||
local file, err = io.open(advtrains.pl_fpath, "r")
|
||||
if not file then
|
||||
local er=err or "Unknown Error"
|
||||
print("[advtrains]Failed loading advtrains trackdb save file "..er)
|
||||
else
|
||||
--custom format to save memory
|
||||
while true do
|
||||
local xbytes=file:read(2)
|
||||
if not xbytes then
|
||||
break --eof reached
|
||||
end
|
||||
local ybytes=file:read(2)
|
||||
local zbytes=file:read(2)
|
||||
local x=(string.byte(xbytes[1])-128)*256+(string.byte(xbytes[2]))
|
||||
local y=(string.byte(ybytes[1])-128)*256+(string.byte(ybytes[2]))
|
||||
local z=(string.byte(zbytes[1])-128)*256+(string.byte(zbytes[2]))
|
||||
|
||||
local conn1=string.byte(file:read(1))
|
||||
local conn1=string.byte(file:read(1))
|
||||
|
||||
if not advtrains.trackdb[y] then advtrains.trackdb[y]={} end
|
||||
if not advtrains.trackdb[y][x] then advtrains.trackdb[y][x]={} end
|
||||
|
||||
local rest=file.read("*l")
|
||||
if rest~="" then
|
||||
local rely1, rely2, railheight=string.match(rest, "([^|]+)|([^|]+)|([^|]+)")
|
||||
if rely1 and rely2 and railheight then
|
||||
advtrains.trackdb[y][x][z]={
|
||||
conn1=conn1, conn2=conn2,
|
||||
rely1=rely1, rely2=rely2,
|
||||
railheight=railheight
|
||||
}
|
||||
for tt, _ in pairs(advtrains.all_traintypes) do
|
||||
local pl_fpath=minetest.get_worldpath().."/advtrains_trackdb_"..tt
|
||||
advtrains.trackdb[tt]={}
|
||||
local file, err = io.open(pl_fpath, "r")
|
||||
if not file then
|
||||
local er=err or "Unknown Error"
|
||||
print("[advtrains]Failed loading advtrains trackdb save file "..er)
|
||||
else
|
||||
--custom format to save memory
|
||||
while true do
|
||||
local xbytes=file:read(2)
|
||||
if not xbytes then
|
||||
break --eof reached
|
||||
end
|
||||
local ybytes=file:read(2)
|
||||
local zbytes=file:read(2)
|
||||
local x=(string.byte(xbytes[1])-128)*256+(string.byte(xbytes[2]))
|
||||
local y=(string.byte(ybytes[1])-128)*256+(string.byte(ybytes[2]))
|
||||
local z=(string.byte(zbytes[1])-128)*256+(string.byte(zbytes[2]))
|
||||
|
||||
local conn1=string.byte(file:read(1))
|
||||
local conn1=string.byte(file:read(1))
|
||||
|
||||
if not advtrains.trackdb[tt][y] then advtrains.trackdb[tt][y]={} end
|
||||
if not advtrains.trackdb[tt][y][x] then advtrains.trackdb[tt][y][x]={} end
|
||||
|
||||
local rest=file.read("*l")
|
||||
if rest~="" then
|
||||
local rely1, rely2, railheight=string.match(rest, "([^|]+)|([^|]+)|([^|]+)")
|
||||
if rely1 and rely2 and railheight then
|
||||
advtrains.trackdb[tt][y][x][z]={
|
||||
conn1=conn1, conn2=conn2,
|
||||
rely1=rely1, rely2=rely2,
|
||||
railheight=railheight
|
||||
}
|
||||
else
|
||||
advtrains.trackdb[tt][y][x][z]={
|
||||
conn1=conn1, conn2=conn2
|
||||
}
|
||||
end
|
||||
else
|
||||
advtrains.trackdb[y][x][z]={
|
||||
advtrains.trackdb[tt][y][x][z]={
|
||||
conn1=conn1, conn2=conn2
|
||||
}
|
||||
end
|
||||
else
|
||||
advtrains.trackdb[y][x][z]={
|
||||
conn1=conn1, conn2=conn2
|
||||
}
|
||||
end
|
||||
end
|
||||
file:close()
|
||||
end
|
||||
function advtrains.save_trackdb()
|
||||
local file, err = io.open(advtrains.pl_fpath, "w")
|
||||
if not file then
|
||||
local er=err or "Unknown Error"
|
||||
print("[advtrains]Failed saving advtrains trackdb save file "..er)
|
||||
else
|
||||
--custom format to save memory
|
||||
for x,txl in pairs(advtrains.trackdb) do
|
||||
for y,tyl in pairs(txl) do
|
||||
for z,rail in pairs(tyl) do
|
||||
file:write(string.char(math.floor(x/256)+128)..string.char((x%256)))
|
||||
file:write(string.char(math.floor(y/256)+128)..string.char((y%256)))
|
||||
file:write(string.char(math.floor(z/256)+128)..string.char((z%256)))
|
||||
file:write(string.char(rail.conn1))
|
||||
file:write(string.char(rail.conn2))
|
||||
if (rail.rely1 and rail.rely1~=0) or (rail.rely2 and rail.rely2~=0) or (rail.railheight and rail.railheight~=0) then
|
||||
file:write(rail.rely1.."|"..rail.rely2.."|"..rail.railheight)
|
||||
end
|
||||
file:write("\n")
|
||||
end
|
||||
end
|
||||
end
|
||||
file:close()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function advtrains.save_trackdb()
|
||||
for tt, _ in pairs(advtrains.all_traintypes) do
|
||||
local pl_fpath=minetest.get_worldpath().."/advtrains_trackdb_"..tt
|
||||
local file, err = io.open(pl_fpath, "w")
|
||||
if not file then
|
||||
local er=err or "Unknown Error"
|
||||
print("[advtrains]Failed saving advtrains trackdb save file "..er)
|
||||
else
|
||||
--custom format to save memory
|
||||
for x,txl in pairs(advtrains.trackdb[tt]) do
|
||||
for y,tyl in pairs(txl) do
|
||||
for z,rail in pairs(tyl) do
|
||||
file:write(string.char(math.floor(x/256)+128)..string.char((x%256)))
|
||||
file:write(string.char(math.floor(y/256)+128)..string.char((y%256)))
|
||||
file:write(string.char(math.floor(z/256)+128)..string.char((z%256)))
|
||||
file:write(string.char(rail.conn1))
|
||||
file:write(string.char(rail.conn2))
|
||||
if (rail.rely1 and rail.rely1~=0) or (rail.rely2 and rail.rely2~=0) or (rail.railheight and rail.railheight~=0) then
|
||||
file:write(rail.rely1.."|"..rail.rely2.."|"..rail.railheight)
|
||||
end
|
||||
file:write("\n")
|
||||
end
|
||||
end
|
||||
end
|
||||
file:close()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--get_node with pseudoload.
|
||||
--returns:
|
||||
--true, conn1, conn2, rely1, rely2, railheight in case everything's right.
|
||||
--false if it's not a rail or the train does not drive on this rail, but it is loaded or
|
||||
--nil if the node is neither loaded nor in trackdb
|
||||
--the distraction between false and nil will be needed only in special cases.(train initpos)
|
||||
function advtrains.get_rail_at(pos, traintype)
|
||||
function advtrains.get_rail_info_at(pos, traintype)
|
||||
local node=minetest.get_node_or_nil(pos)
|
||||
if not node then
|
||||
--try raildb
|
||||
local rdp=vector.round(rdp)
|
||||
local dbe=advtrains.trackdb[rdp.y][rdp.x][rdp.z]
|
||||
local dbe=advtrains.trackdb[traintype][rdp.y][rdp.x][rdp.z]
|
||||
if dbe then
|
||||
return true, dbe.conn1, dbe.conn2, dbe.rely1 or 0, dbe.rely2 or 0, dbe.railheight or 0
|
||||
else
|
||||
|
@ -107,7 +115,7 @@ function advtrains.get_rail_at(pos, traintype)
|
|||
|
||||
--already in trackdb?
|
||||
local rdp=vector.round(rdp)
|
||||
if not advtrains.trackdb[rdp.y][rdp.x][rdp.z] then--TODO is this write prevention here really needed?
|
||||
if not advtrains.trackdb[traintype][rdp.y][rdp.x][rdp.z] then--TODO is this necessary?
|
||||
advtrains.trackdb[rdp.y][rdp.x][rdp.z]={
|
||||
conn1=conn1, conn2=conn2,
|
||||
rely1=rely1, rely2=rely2,
|
||||
|
|
|
@ -31,6 +31,7 @@ function advtrains.register_tracks(tracktype, def)
|
|||
if advtrains.is_train_at_pos(pos) then return end
|
||||
advtrains.invalidate_all_paths()
|
||||
minetest.set_node(pos, {name=def.nodename_prefix.."_"..suffix_target, param2=node.param2})
|
||||
advtrains.reset_trackdb_position(pos)
|
||||
end
|
||||
end
|
||||
local function make_overdef(img_suffix, conn1, conn2, switchfunc)
|
||||
|
@ -70,8 +71,12 @@ function advtrains.register_tracks(tracktype, def)
|
|||
can_dig=function(pos)
|
||||
return not advtrains.is_train_at_pos(pos)
|
||||
end,
|
||||
after_dig_node=function()
|
||||
after_dig_node=function(pos)
|
||||
advtrains.invalidate_all_paths()
|
||||
advtrains.reset_trackdb_position(pos)
|
||||
end
|
||||
after_place_node=function(pos)
|
||||
advtrains.reset_trackdb_position(pos)
|
||||
end
|
||||
}
|
||||
minetest.register_node(def.nodename_prefix.."_st", advtrains.merge_tables(common_def, make_overdef("st", 0, 4), def.straight or {}))
|
||||
|
@ -136,7 +141,7 @@ end
|
|||
|
||||
function advtrains.get_track_connections(name, param2)
|
||||
local nodedef=minetest.registered_nodes[name]
|
||||
if not nodedef then print("[advtrains] get_track_connections couldn't find nodedef for nodename "..(name or "nil")) return 0,4 end
|
||||
if not nodedef then print("[advtrains] get_track_connections couldn't find nodedef for nodename "..(name or "nil")) return 0, 4, 0, 0, 0 end
|
||||
local noderot=param2
|
||||
if not param2 then noderot=0 end
|
||||
if noderot > 3 then print("[advtrains] get_track_connections: rail has invaild param2 of "..noderot) noderot=0 end
|
||||
|
|
12
tracks.lua~
12
tracks.lua~
|
@ -31,6 +31,7 @@ function advtrains.register_tracks(tracktype, def)
|
|||
if advtrains.is_train_at_pos(pos) then return end
|
||||
advtrains.invalidate_all_paths()
|
||||
minetest.set_node(pos, {name=def.nodename_prefix.."_"..suffix_target, param2=node.param2})
|
||||
advtrains.reset_trackdb_position(pos)
|
||||
end
|
||||
end
|
||||
local function make_overdef(img_suffix, conn1, conn2, switchfunc)
|
||||
|
@ -70,8 +71,9 @@ function advtrains.register_tracks(tracktype, def)
|
|||
can_dig=function(pos)
|
||||
return not advtrains.is_train_at_pos(pos)
|
||||
end,
|
||||
after_dig_node=function()
|
||||
after_dig_node=function(pos)
|
||||
advtrains.invalidate_all_paths()
|
||||
advtrains.reset_trackdb_position(pos)
|
||||
end
|
||||
}
|
||||
minetest.register_node(def.nodename_prefix.."_st", advtrains.merge_tables(common_def, make_overdef("st", 0, 4), def.straight or {}))
|
||||
|
@ -101,13 +103,15 @@ function advtrains.register_tracks(tracktype, def)
|
|||
rely1=0,
|
||||
rely2=0.5,
|
||||
railheight=0.25,
|
||||
}, def.straight or {}))
|
||||
description = def.description.." (vertical track lower node)",
|
||||
}, def.vert1 or {}))
|
||||
minetest.register_node(def.nodename_prefix.."_vert2", advtrains.merge_tables(common_def, make_overdef("vert2", 0, 4), {
|
||||
mesh = "trackvertical2.b3d",
|
||||
rely1=0.5,
|
||||
rely2=1,
|
||||
railheight=0.75,
|
||||
},def.straight45 or {}))
|
||||
description = def.description.." (vertical track lower node)",
|
||||
},def.vert2 or {}))
|
||||
|
||||
advtrains.register_track_placer(def.nodename_prefix, def.texture_prefix, def.description)
|
||||
table.insert(advtrains.all_tracktypes, tracktype)
|
||||
|
@ -134,7 +138,7 @@ end
|
|||
|
||||
function advtrains.get_track_connections(name, param2)
|
||||
local nodedef=minetest.registered_nodes[name]
|
||||
if not nodedef then print("[advtrains] get_track_connections couldn't find nodedef for nodename "..(name or "nil")) return 0,4 end
|
||||
if not nodedef then print("[advtrains] get_track_connections couldn't find nodedef for nodename "..(name or "nil")) return 0, 4, 0, 0, 0 end
|
||||
local noderot=param2
|
||||
if not param2 then noderot=0 end
|
||||
if noderot > 3 then print("[advtrains] get_track_connections: rail has invaild param2 of "..noderot) noderot=0 end
|
||||
|
|
128
trainlogic.lua
128
trainlogic.lua
|
@ -32,6 +32,18 @@ else
|
|||
end
|
||||
file:close()
|
||||
end
|
||||
advtrains.fpath_ws=minetest.get_worldpath().."/advtrains_wagon_save"
|
||||
local file, err = io.open(advtrains.fpath_ws, "r")
|
||||
if not file then
|
||||
local er=err or "Unknown Error"
|
||||
print("[advtrains]Failed loading advtrains save file "..er)
|
||||
else
|
||||
local tbl = minetest.deserialize(file:read("*a"))
|
||||
if type(tbl) == "table" then
|
||||
advtrains.wagon_save=tbl
|
||||
end
|
||||
file:close()
|
||||
end
|
||||
|
||||
|
||||
advtrains.save = function()
|
||||
|
@ -48,6 +60,25 @@ advtrains.save = function()
|
|||
end
|
||||
file:write(datastr)
|
||||
file:close()
|
||||
|
||||
-- update wagon saves
|
||||
for _,wagon in pairs(minetest.luaentities) do
|
||||
if wagon.is_wagon and wagon.initialized then
|
||||
advtrains.wagon_save[wagon.unique_id]=advtrains.merge_tables(wagon)--so, will only copy non_metatable elements
|
||||
end
|
||||
end
|
||||
|
||||
datastr = minetest.serialize(advtrains.wagon_save)
|
||||
if not datastr then
|
||||
minetest.log("error", "[advtrains] Failed to serialize train data!")
|
||||
return
|
||||
end
|
||||
file, err = io.open(advtrains.fpath_ws, "w")
|
||||
if err then
|
||||
return err
|
||||
end
|
||||
file:write(datastr)
|
||||
file:close()
|
||||
end
|
||||
minetest.register_on_shutdown(advtrains.save)
|
||||
|
||||
|
@ -136,6 +167,45 @@ function advtrains.train_step(id, train, dtime)
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
--check for any trainpart entities if they have been unloaded. do this only if both front and end positions are loaded, to ensure train entities will be placed inside loaded area, and only every second.
|
||||
train.check_trainpartload=train.check_trainpartload-dtime
|
||||
if train.check_trainpartload<=0 and posfront and posback and minetest.get_node_or_nil(posfront) and minetest.get_node_or_nil(posback) then
|
||||
--it is better to iterate luaentites only once
|
||||
local found_uids={}
|
||||
for _,wagon in pairs(minetest.luaentities) do
|
||||
if wagon.is_wagon and wagon.initialized and wagon.train_id==id then
|
||||
if found_uids[wagon.unique_id] then
|
||||
--duplicate found, delete it
|
||||
wagon.object and wagon.object:remove()
|
||||
else
|
||||
found_uids[wagon.unique_id]=true
|
||||
end
|
||||
end
|
||||
end
|
||||
--now iterate trainparts and check. then cross them out to see if there are wagons over for any reason
|
||||
for pit, w_id in ipairs(train.trainparts) do
|
||||
if found_uids[w_id] then
|
||||
found_uids[w_id]=nil
|
||||
elseif advtrains.wagon_save[w_id] then
|
||||
--spawn a new and initialize it with the properties from wagon_save
|
||||
local le=minetest.env:add_entity(posfront, "advtrains:"..sysname):get_luaentity()
|
||||
for k,v in pairs(advtrains.wagon_save[w_id]) do
|
||||
le[k]=v
|
||||
end
|
||||
else
|
||||
--what the hell...
|
||||
local le=minetest.env:add_entity(posfront, "advtrains:"..sysname):get_luaentity()
|
||||
le.unique_id=w_id
|
||||
le.train_id=id
|
||||
le.pos_in_trainparts=pit
|
||||
advtrains.update_trainpart_properties(id, train)
|
||||
end
|
||||
end
|
||||
train.check_trainpartload=1
|
||||
end
|
||||
|
||||
|
||||
--handle collided_with_env
|
||||
if train.recently_collided_with_env then
|
||||
train.tarvelocity=0
|
||||
|
@ -229,41 +299,35 @@ function advtrains.pathpredict(id, train)
|
|||
return false
|
||||
end
|
||||
|
||||
local node=minetest.get_node_or_nil(advtrains.round_vector_floor_y(train.last_pos))
|
||||
if not node then
|
||||
--print("pathpredict:last_pos node "..minetest.pos_to_string(advtrains.round_vector_floor_y(train.last_pos)).." is nil. block probably not loaded")
|
||||
return nil
|
||||
end
|
||||
local nodename=node.name
|
||||
local node_ok=advtrains.get_rail_info_at(advtrains.round_vector_floor_y(train.last_pos), train.traintype)
|
||||
|
||||
if(not advtrains.is_track_and_drives_on(nodename, advtrains.all_traintypes[train.traintype].drives_on)) then
|
||||
advtrains.dumppath(train.path)
|
||||
print("at index "..train.index)
|
||||
if node_ok==nil then
|
||||
--block not loaded, do nothing
|
||||
return nil
|
||||
elseif node_ok==false then
|
||||
print("[advtrains]no track here, (fail) removing train.")
|
||||
advtrains.trains[id]=nil
|
||||
return false
|
||||
end
|
||||
|
||||
if not train.last_pos_prev then
|
||||
--no chance to recover
|
||||
print("[advtrains]train hasn't saved last-pos_prev, removing train.")
|
||||
advtrains.trains[id]=nil
|
||||
return false
|
||||
end
|
||||
local prevnode=minetest.get_node_or_nil(advtrains.round_vector_floor_y(train.last_pos_prev))
|
||||
if not prevnode then
|
||||
--print("pathpredict:last_pos_prev node "..minetest.pos_to_string(advtrains.round_vector_floor_y(train.last_pos_prev)).." is nil. block probably not loaded")
|
||||
return nil
|
||||
end
|
||||
local prevnodename=prevnode.name
|
||||
|
||||
if(not advtrains.is_track_and_drives_on(prevnodename, advtrains.all_traintypes[train.traintype].drives_on)) then
|
||||
local prevnode_ok=advtrains.get_rail_info_at(advtrains.round_vector_floor_y(train.last_pos_prev), train.traintype)
|
||||
|
||||
if prevnode_ok==nil then
|
||||
--block not loaded, do nothing
|
||||
return nil
|
||||
elseif prevnode_ok==false then
|
||||
print("[advtrains]no track at prev, (fail) removing train.")
|
||||
advtrains.trains[id]=nil
|
||||
return false
|
||||
end
|
||||
|
||||
local conn1, conn2=advtrains.get_track_connections(nodename, node.param2)
|
||||
|
||||
train.index=(train.restore_add_index or 0)+(train.savedpos_off_track_index_offset or 0)
|
||||
--restore_add_index is set by save() to prevent trains hopping to next round index. should be between -0.5 and 0.5
|
||||
--savedpos_off_track_index_offset is set if train went off track. see below.
|
||||
|
@ -277,7 +341,7 @@ function advtrains.pathpredict(id, train)
|
|||
local maxn=advtrains.maxN(train.path)
|
||||
while (maxn-train.index) < 2 do--pregenerate
|
||||
--print("[advtrains]maxn conway for ",maxn,minetest.pos_to_string(path[maxn]),maxn-1,minetest.pos_to_string(path[maxn-1]))
|
||||
local conway=advtrains.conway(train.path[maxn], train.path[maxn-1], advtrains.all_traintypes[train.traintype].drives_on)
|
||||
local conway=advtrains.conway(train.path[maxn], train.path[maxn-1], train.traintype)
|
||||
if conway then
|
||||
train.path[maxn+1]=conway
|
||||
train.max_index_on_track=maxn
|
||||
|
@ -294,7 +358,7 @@ function advtrains.pathpredict(id, train)
|
|||
local minn=advtrains.minN(train.path)
|
||||
while (train.index-minn) < (train.trainlen or 0) + 2 do --post_generate. has to be at least trainlen.
|
||||
--print("[advtrains]minn conway for ",minn,minetest.pos_to_string(path[minn]),minn+1,minetest.pos_to_string(path[minn+1]))
|
||||
local conway=advtrains.conway(train.path[minn], train.path[minn+1], advtrains.all_traintypes[train.traintype].drives_on)
|
||||
local conway=advtrains.conway(train.path[minn], train.path[minn+1], train.traintype)
|
||||
if conway then
|
||||
train.path[minn-1]=conway
|
||||
train.min_index_on_track=minn
|
||||
|
@ -384,30 +448,20 @@ function advtrains.split_train_at_wagon(wagon)
|
|||
print("split_train: pos_for_new_train not set")
|
||||
return false
|
||||
end
|
||||
local node=minetest.get_node_or_nil(advtrains.round_vector_floor_y(pos_for_new_train))
|
||||
if not node then
|
||||
print("split_train: pos_for_new_train node "..minetest.pos_to_string(advtrains.round_vector_floor_y(pos_for_new_train)).." is nil. block probably not loaded")
|
||||
return nil
|
||||
end
|
||||
local nodename=node.name
|
||||
|
||||
if(not advtrains.is_track_and_drives_on(nodename, advtrains.all_traintypes[train.traintype].drives_on)) then
|
||||
print("split_train: pos_for_new_train "..minetest.pos_to_string(advtrains.round_vector_floor_y(pos_for_new_train_prev)).." is not a rail")
|
||||
local node_ok=advtrains.get_rail_info_at(advtrains.round_vector_floor_y(pos_for_new_train), train.traintype)
|
||||
if not node_ok then
|
||||
print("split_train: pos_for_new_train "..minetest.pos_to_string(advtrains.round_vector_floor_y(pos_for_new_train_prev)).." not loaded or is not a rail")
|
||||
return false
|
||||
end
|
||||
|
||||
if not train.last_pos_prev then
|
||||
print("split_train: pos_for_new_train_prev not set")
|
||||
return false
|
||||
end
|
||||
local prevnode=minetest.get_node_or_nil(advtrains.round_vector_floor_y(pos_for_new_train_prev))
|
||||
if not node then
|
||||
print("split_train: pos_for_new_train_prev node "..minetest.pos_to_string(advtrains.round_vector_floor_y(pos_for_new_train_prev)).." is nil. block probably not loaded")
|
||||
return false
|
||||
end
|
||||
local prevnodename=prevnode.name
|
||||
|
||||
if(not advtrains.is_track_and_drives_on(prevnodename, advtrains.all_traintypes[train.traintype].drives_on)) then
|
||||
print("split_train: pos_for_new_train_prev "..minetest.pos_to_string(advtrains.round_vector_floor_y(pos_for_new_train_prev)).." is not a rail")
|
||||
local prevnode_ok=advtrains.get_rail_info_at(advtrains.round_vector_floor_y(pos_for_new_train), train.traintype)
|
||||
if not prevnode_ok then
|
||||
print("split_train: pos_for_new_train_prev "..minetest.pos_to_string(advtrains.round_vector_floor_y(pos_for_new_train_prev)).." not loaded or is not a rail")
|
||||
return false
|
||||
end
|
||||
|
||||
|
|
128
trainlogic.lua~
128
trainlogic.lua~
|
@ -32,6 +32,18 @@ else
|
|||
end
|
||||
file:close()
|
||||
end
|
||||
advtrains.fpath_ws=minetest.get_worldpath().."/advtrains_wagon_save"
|
||||
local file, err = io.open(advtrains.fpath_ws, "r")
|
||||
if not file then
|
||||
local er=err or "Unknown Error"
|
||||
print("[advtrains]Failed loading advtrains save file "..er)
|
||||
else
|
||||
local tbl = minetest.deserialize(file:read("*a"))
|
||||
if type(tbl) == "table" then
|
||||
advtrains.wagon_save=tbl
|
||||
end
|
||||
file:close()
|
||||
end
|
||||
|
||||
|
||||
advtrains.save = function()
|
||||
|
@ -48,6 +60,25 @@ advtrains.save = function()
|
|||
end
|
||||
file:write(datastr)
|
||||
file:close()
|
||||
|
||||
-- update wagon saves
|
||||
for _,wagon in pairs(minetest.luaentities) do
|
||||
if wagon.is_wagon and wagon.initialized then
|
||||
advtrains.wagon_save[wagon.unique_id]=advtrains.merge_tables(wagon)--so, will only copy non_metatable elements
|
||||
end
|
||||
end
|
||||
|
||||
datastr = minetest.serialize(advtrains.wagon_save)
|
||||
if not datastr then
|
||||
minetest.log("error", "[advtrains] Failed to serialize train data!")
|
||||
return
|
||||
end
|
||||
file, err = io.open(advtrains.fpath_ws, "w")
|
||||
if err then
|
||||
return err
|
||||
end
|
||||
file:write(datastr)
|
||||
file:close()
|
||||
end
|
||||
minetest.register_on_shutdown(advtrains.save)
|
||||
|
||||
|
@ -136,6 +167,44 @@ function advtrains.train_step(id, train, dtime)
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
--check for any trainpart entities if they have been unloaded. do this only if both front and end positions are loaded, to ensure train entities will be placed inside loaded area, and only every second.
|
||||
train.check_trainpartload=train.check_trainpartload-dtime
|
||||
if train.check_trainpartload<=0 and posfront and posback and minetest.get_node_or_nil(posfront) and minetest.get_node_or_nil(posback) then
|
||||
--it is better to iterate luaentites only once
|
||||
local found_uids={}
|
||||
for _,wagon in pairs(minetest.luaentities) do
|
||||
if wagon.is_wagon and wagon.initialized and wagon.train_id==id then
|
||||
if found_uids[wagon.unique_id] then
|
||||
--duplicate found, delete it
|
||||
wagon.object and wagon.object:remove()
|
||||
else
|
||||
found_uids[wagon.unique_id]=true
|
||||
end
|
||||
end
|
||||
end
|
||||
--now iterate trainparts and check. then cross them out to see if there are wagons over for any reason
|
||||
for pit, w_id in ipairs(train.trainparts) do
|
||||
if found_uids[w_id] then
|
||||
found_uids[w_id]=nil
|
||||
elseif advtrains.wagon_save[w_id] then
|
||||
--spawn a new and initialize it with the properties from wagon_save
|
||||
local le=minetest.env:add_entity(posfront, "advtrains:"..sysname):get_luaentity()
|
||||
for k,v in pairs(advtrains.wagon_save[w_id]) do
|
||||
le[k]=v
|
||||
end
|
||||
else
|
||||
--what the hell...
|
||||
local le=minetest.env:add_entity(posfront, "advtrains:"..sysname):get_luaentity()
|
||||
le.train_id=id
|
||||
le.pos_in_trainparts=pit
|
||||
--update trainpart properties when train stepped...
|
||||
end
|
||||
end
|
||||
train.check_trainpartload=1
|
||||
end
|
||||
|
||||
|
||||
--handle collided_with_env
|
||||
if train.recently_collided_with_env then
|
||||
train.tarvelocity=0
|
||||
|
@ -228,41 +297,36 @@ function advtrains.pathpredict(id, train)
|
|||
advtrains.train[id]=nil
|
||||
return false
|
||||
end
|
||||
local node=minetest.get_node_or_nil(advtrains.round_vector_floor_y(train.last_pos))
|
||||
if not node then
|
||||
--print("pathpredict:last_pos node "..minetest.pos_to_string(advtrains.round_vector_floor_y(train.last_pos)).." is nil. block probably not loaded")
|
||||
return nil
|
||||
end
|
||||
local nodename=node.name
|
||||
|
||||
if(not advtrains.is_track_and_drives_on(nodename, advtrains.all_traintypes[train.traintype].drives_on)) then
|
||||
advtrains.dumppath(train.path)
|
||||
print("at index "..train.index)
|
||||
local node_ok=advtrains.get_rail_info_at(advtrains.round_vector_floor_y(train.last_pos), train.traintype)
|
||||
|
||||
if node_ok==nil then
|
||||
--block not loaded, do nothing
|
||||
return nil
|
||||
elseif node_ok==false then
|
||||
print("[advtrains]no track here, (fail) removing train.")
|
||||
advtrains.trains[id]=nil
|
||||
return false
|
||||
end
|
||||
|
||||
if not train.last_pos_prev then
|
||||
--no chance to recover
|
||||
print("[advtrains]train hasn't saved last-pos_prev, removing train.")
|
||||
advtrains.trains[id]=nil
|
||||
return false
|
||||
end
|
||||
local prevnode=minetest.get_node_or_nil(advtrains.round_vector_floor_y(train.last_pos_prev))
|
||||
if not prevnode then
|
||||
--print("pathpredict:last_pos_prev node "..minetest.pos_to_string(advtrains.round_vector_floor_y(train.last_pos_prev)).." is nil. block probably not loaded")
|
||||
return nil
|
||||
end
|
||||
local prevnodename=prevnode.name
|
||||
|
||||
if(not advtrains.is_track_and_drives_on(prevnodename, advtrains.all_traintypes[train.traintype].drives_on)) then
|
||||
local prevnode_ok=advtrains.get_rail_info_at(advtrains.round_vector_floor_y(train.last_pos_prev), train.traintype)
|
||||
|
||||
if prevnode_ok==nil then
|
||||
--block not loaded, do nothing
|
||||
return nil
|
||||
elseif prevnode_ok==false then
|
||||
print("[advtrains]no track at prev, (fail) removing train.")
|
||||
advtrains.trains[id]=nil
|
||||
return false
|
||||
end
|
||||
|
||||
local conn1, conn2=advtrains.get_track_connections(nodename, node.param2)
|
||||
|
||||
train.index=(train.restore_add_index or 0)+(train.savedpos_off_track_index_offset or 0)
|
||||
--restore_add_index is set by save() to prevent trains hopping to next round index. should be between -0.5 and 0.5
|
||||
--savedpos_off_track_index_offset is set if train went off track. see below.
|
||||
|
@ -276,7 +340,7 @@ function advtrains.pathpredict(id, train)
|
|||
local maxn=advtrains.maxN(train.path)
|
||||
while (maxn-train.index) < 2 do--pregenerate
|
||||
--print("[advtrains]maxn conway for ",maxn,minetest.pos_to_string(path[maxn]),maxn-1,minetest.pos_to_string(path[maxn-1]))
|
||||
local conway=advtrains.conway(train.path[maxn], train.path[maxn-1], advtrains.all_traintypes[train.traintype].drives_on)
|
||||
local conway=advtrains.conway(train.path[maxn], train.path[maxn-1], train.traintype)
|
||||
if conway then
|
||||
train.path[maxn+1]=conway
|
||||
train.max_index_on_track=maxn
|
||||
|
@ -293,7 +357,7 @@ function advtrains.pathpredict(id, train)
|
|||
local minn=advtrains.minN(train.path)
|
||||
while (train.index-minn) < (train.trainlen or 0) + 2 do --post_generate. has to be at least trainlen.
|
||||
--print("[advtrains]minn conway for ",minn,minetest.pos_to_string(path[minn]),minn+1,minetest.pos_to_string(path[minn+1]))
|
||||
local conway=advtrains.conway(train.path[minn], train.path[minn+1], advtrains.all_traintypes[train.traintype].drives_on)
|
||||
local conway=advtrains.conway(train.path[minn], train.path[minn+1], train.traintype)
|
||||
if conway then
|
||||
train.path[minn-1]=conway
|
||||
train.min_index_on_track=minn
|
||||
|
@ -383,30 +447,20 @@ function advtrains.split_train_at_wagon(wagon)
|
|||
print("split_train: pos_for_new_train not set")
|
||||
return false
|
||||
end
|
||||
local node=minetest.get_node_or_nil(advtrains.round_vector_floor_y(pos_for_new_train))
|
||||
if not node then
|
||||
print("split_train: pos_for_new_train node "..minetest.pos_to_string(advtrains.round_vector_floor_y(pos_for_new_train)).." is nil. block probably not loaded")
|
||||
return nil
|
||||
end
|
||||
local nodename=node.name
|
||||
|
||||
if(not advtrains.is_track_and_drives_on(nodename, advtrains.all_traintypes[train.traintype].drives_on)) then
|
||||
print("split_train: pos_for_new_train "..minetest.pos_to_string(advtrains.round_vector_floor_y(pos_for_new_train_prev)).." is not a rail")
|
||||
local node_ok=advtrains.get_rail_info_at(advtrains.round_vector_floor_y(pos_for_new_train), train.traintype)
|
||||
if not node_ok then
|
||||
print("split_train: pos_for_new_train "..minetest.pos_to_string(advtrains.round_vector_floor_y(pos_for_new_train_prev)).." not loaded or is not a rail")
|
||||
return false
|
||||
end
|
||||
|
||||
if not train.last_pos_prev then
|
||||
print("split_train: pos_for_new_train_prev not set")
|
||||
return false
|
||||
end
|
||||
local prevnode=minetest.get_node_or_nil(advtrains.round_vector_floor_y(pos_for_new_train_prev))
|
||||
if not node then
|
||||
print("split_train: pos_for_new_train_prev node "..minetest.pos_to_string(advtrains.round_vector_floor_y(pos_for_new_train_prev)).." is nil. block probably not loaded")
|
||||
return false
|
||||
end
|
||||
local prevnodename=prevnode.name
|
||||
|
||||
if(not advtrains.is_track_and_drives_on(prevnodename, advtrains.all_traintypes[train.traintype].drives_on)) then
|
||||
print("split_train: pos_for_new_train_prev "..minetest.pos_to_string(advtrains.round_vector_floor_y(pos_for_new_train_prev)).." is not a rail")
|
||||
local prevnode_ok=advtrains.get_rail_info_at(advtrains.round_vector_floor_y(pos_for_new_train), train.traintype)
|
||||
if not prevnode_ok then
|
||||
print("split_train: pos_for_new_train_prev "..minetest.pos_to_string(advtrains.round_vector_floor_y(pos_for_new_train_prev)).." not loaded or is not a rail")
|
||||
return false
|
||||
end
|
||||
|
||||
|
|
|
@ -89,6 +89,8 @@ function wagon:on_activate(staticdata, dtime_s)
|
|||
end
|
||||
|
||||
function wagon:get_staticdata()
|
||||
--save to table before being unloaded
|
||||
advtrains.wagon_save[self.unique_id]=advtrains.merge_tables(self)
|
||||
return minetest.serialize({
|
||||
unique_id=self.unique_id,
|
||||
train_id=self.train_id,
|
||||
|
|
|
@ -60,6 +60,7 @@ function wagon:on_activate(staticdata, dtime_s)
|
|||
if tmp then
|
||||
self.unique_id=tmp.unique_id
|
||||
self.train_id=tmp.train_id
|
||||
self.wagon_flipped=tmp.wagon_flipped
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -88,9 +89,12 @@ function wagon:on_activate(staticdata, dtime_s)
|
|||
end
|
||||
|
||||
function wagon:get_staticdata()
|
||||
--save to table before being unloaded
|
||||
advtrains.wagon_save[self.unique_id]=advtrains.merge_tables(self)
|
||||
return minetest.serialize({
|
||||
unique_id=self.unique_id,
|
||||
train_id=self.train_id,
|
||||
wagon_flipped=self.wagon_flipped,
|
||||
})
|
||||
end
|
||||
|
||||
|
@ -177,7 +181,7 @@ function wagon:on_step(dtime)
|
|||
return
|
||||
end
|
||||
|
||||
local pos_in_train_left=self.pos_in_train+0
|
||||
local pos_in_train_left=(self.pos_in_train or 0)+0 --pos_in_train may be not set if this was emergency-instantiated by train_step when it found out that an object is missing but no wagon_save was found.
|
||||
local index=gp.index
|
||||
if pos_in_train_left>(index-math.floor(index))*(gp.path_dist[math.floor(index)] or 1) then
|
||||
pos_in_train_left=pos_in_train_left - (index-math.floor(index))*(gp.path_dist[math.floor(index)] or 1)
|
||||
|
|
Loading…
Reference in New Issue