aboutsummaryrefslogtreecommitdiff
path: root/pseudoload.lua
blob: 532b4291f5dd3eed2c2984f3b5b9d9e0a157e9fe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121

--pseudoload.lua
--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}
--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
				}
			else
				advtrains.trackdb[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

--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_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]
		if dbe then
			return true, dbe.conn1, dbe.conn2, dbe.rely1 or 0, dbe.rely2 or 0, dbe.railheight or 0
		else
			return nil
		end
	end
	local nodename=node.name
	if(not advtrains.is_track_and_drives_on(nodename, advtrains.all_traintypes[traintype].drives_on)) then
		return false
	end
	local conn1, conn2, rely1, rely2, railheight=advtrains.get_track_connections(node.name, node.param2)
	
	--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?
		advtrains.trackdb[rdp.y][rdp.x][rdp.z]={
			conn1=conn1, conn2=conn2,
			rely1=rely1, rely2=rely2,
			railheight=railheight
		}
	end
	
	return true, conn1, conn2, rely1, rely2, railheight
end