-
Notifications
You must be signed in to change notification settings - Fork 1
/
map.lua
207 lines (183 loc) · 4.23 KB
/
map.lua
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
local Area = require("area")
local Util = require "util"
local serpent = require("serpent")
local format = string.format
local info = Util.info
local Map = {}
Map.__index = Map
local function expand_tilde(path)
if path:find("^~") ~= nil then
return format("%s%s", os.getenv("HOME"), path:sub(2))
else
return path
end
end
function Map.new(name)
local ret = setmetatable({}, Map)
ret.name = name
ret.currentArea = nil
ret.currentRoom = nil
ret.areas = {}
ret.save_location = nil
return ret
end
function Map:add_area(name)
if not self.areas[name] then
self.areas[name] = Area.new(name)
self.currentArea = self.areas[name]
self.currentRoom = self.currentArea:get_room()
return self.areas[name]
end
return nil
end
function Map:replace_area(name)
if self.areas[name] then
self.areas[name] = Area.new(name)
self.currentArea = self.areas[name]
self.currentRoom = self.currentArea:get_room()
return self.areas[name]
end
return nil
end
function Map:rename_area(old_name, new_name)
self.areas[new_name] = self.areas[old_name]
self.areas[old_name] = nil
for _,area in pairs(self.areas) do
area:rename_area(old_name, new_name)
end
end
function Map:track(dir)
if not self.currentArea then
return false
end
local exit = self.currentArea:track(dir)
if exit then
self.currentArea = self.areas[exit.area]
self.currentArea:set_pos(table.unpack(exit.pos))
self.currentRoom = self.currentArea:get_room()
return exit
else
self.currentArea = nil
self.currentRoom = nil
return nil
end
end
function Map:set_position(id)
self.currentArea = nil
self.currentRoom = nil
for _,area in pairs(self.areas) do
local room = area:find_room(id)
if room then
self.currentArea = area
self.currentRoom = room
self.currentArea:set_pos(table.unpack(room.pos))
return true
end
end
return false
end
function Map:find_room(id)
for name,area in pairs(self.areas) do
local room = area:find_room(id)
if room then
return room, name
end
end
return nil
end
function Map:get_area()
return self.currentArea
end
function Map:get_room()
return self.currentRoom
end
function Map:move(dir)
if self.currentArea then
self.currentRoom = self.currentArea:move(dir)
end
return self.currentRoom
end
function Map:unmove()
if self.currentArea then
self.currentRoom = self.currentArea:unmove()
end
return self.currentRoom
end
function Map:go_back()
if self.currentArea then
self.currentRoom = self.currentArea:go_back()
end
return self.currentRoom
end
function Map:drop_last_exit()
if self.currentArea then
self.currentArea:drop_last_exit()
end
end
local function table_len(obj)
local count = 0
for _,_ in pairs(obj) do count = count + 1 end
return count
end
function Map:save(path, suffix)
tasks.spawn(function ()
suffix = suffix or ""
local area_count = table_len(self.areas)
local obj = {}
local data_to_save = false
path = expand_tilde(path)
local fname = format("%s.map_%s%s.lua", path, self.name, suffix)
info("MAP", format("Saving to '%s'", fname))
if area_count > 10 then
info("MAP", format("Saving %d areas", area_count))
end
for _,area in pairs(self.areas) do
local name = area.name
if area_count <= 10 then
info("MAP", "Saving area '" .. name .. "'")
end
obj[name] = area:save()
data_to_save = true
end
if not data_to_save then
print("[**] Nothing to save")
return
end
local file = io.open(fname, "w")
io.output(file)
io.write(serpent.block(obj))
io.output(nil)
file:close()
end)
end
function Map:load(path, suffix)
self.areas = {}
suffix = suffix or ""
path = expand_tilde(path)
local fname = format("%s.map_%s%s.lua", path, self.name, suffix)
info("MAP", format("Loading from '%s'", fname))
local ok, obj = false, {}
local file = io.open(fname, "r")
if file then
ok, obj = serpent.load(file:read("*a"))
file:close()
end
if ok then
local area_count = table_len(obj)
for name,area in pairs(obj) do
if area_count < 10 then
info("MAP", format("Loading area '%s'", name))
end
self.areas[name] = Area.load(area)
end
info("MAP", format("Loaded %d areas", area_count))
end
return ok
end
function Map:print()
if self.currentArea then
return self.currentArea:print()
end
return { "", cformat("<red>-- No map available<reset>") }
end
return Map