added trackdb and unloaded wagons handling

master
orwell96 2016-05-29 21:33:09 +02:00
parent 2c864564d2
commit 62f5e05c09
10 changed files with 399 additions and 273 deletions

View File

@ -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!")
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")
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
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

View File

@ -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!")
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")
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
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

View File

@ -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]))
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))
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
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[y][x][z]={
conn1=conn1, conn2=conn2,
rely1=rely1, rely2=rely2,
railheight=railheight
}
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

View File

@ -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]))
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))
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
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[y][x][z]={
conn1=conn1, conn2=conn2,
rely1=rely1, rely2=rely2,
railheight=railheight
}
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,

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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)