SHOW:
|
|
- or go back to the newest paste.
1 | -------------------------------------------------- | |
2 | -- Сервер для оравы шахтерских лазеров из кросоварпа. | |
3 | -- Ставится в кабине шахтерской платформы | |
4 | -- и подключается сетевыми кабелями к компьютерам, | |
5 | -- стоящим у лазеров. На те компьютеры | |
6 | -- нужно поставить клиентскую программу. | |
7 | -- И то, и то нужно поставить в autostart. | |
8 | -- | |
9 | -- (c) Efrim | |
10 | -- skype: gods_pee | |
11 | -- 05.10.2013 | |
12 | -------------------------------------------------- | |
13 | -- Changelog: | |
14 | -- 1.0: release | |
15 | -- 1.1: saving only IDs of miners instead of full statuses | |
16 | -------------------------------------------------- | |
17 | ||
18 | NETWORK_SIDE = "bottom" -- Сторона, к которой подключен модем | |
19 | DATA_FILE = "miners.dat" -- Файл для сохранения данных | |
20 | TEMP_FILE = "miners.temp" -- Временное хранилище | |
21 | TIMEOUTS_MAX = 3 -- Максимальное количество таймаутов в сетевом общении | |
22 | TIMEOUT = 1 -- Время таймаута | |
23 | REFRESH_PERIOD = 1 -- Период обновления экрана | |
24 | ||
25 | -------------------------------------------------- | |
26 | ||
27 | nTotal = -1 | |
28 | nOnline = -1 | |
29 | nLowEnergy = -1 | |
30 | nMining = -1 | |
31 | nQuarry = -1 | |
32 | nStopped = -1 | |
33 | maxLayer = -1 | |
34 | minLayer = -1 | |
35 | ||
36 | ||
37 | -------------------------------------------------- | |
38 | ||
39 | -- Массив данных о майнерах: | |
40 | -- 1 - ID | |
41 | -- 2 - 'state' | |
42 | -- 3 - 'energy' | |
43 | -- 4 - 'currentLayer' | |
44 | -- 5 - 'mined' | |
45 | -- 6 - 'total' | |
46 | -- 7 - online | |
47 | ||
48 | miners = {} | |
49 | for i = 1, 81 do | |
50 | miners[i] = {} | |
51 | ||
52 | for j = 1, 7 do | |
53 | miners[i][j] = 0 -- Fill the values here | |
54 | end | |
55 | end | |
56 | ||
57 | minersCompact = {} | |
58 | ||
59 | -------------------------------------------------- | |
60 | -- Графическая часть | |
61 | -------------------------------------------------- | |
62 | ||
63 | function DisplayStats() | |
64 | term.clear() | |
65 | term.setCursorPos(1, 1) | |
66 | print("__ Lasers __") | |
67 | print("Online / Total: " .. nOnline .. " / " .. nTotal) | |
68 | print("Stopped / Mining / Quarry: " .. nStopped .. " / " .. nMining .. " / " .. nQuarry) | |
69 | print("Max / Min layer: " .. maxLayer .. " / " .. minLayer) | |
70 | print("With low energy: " .. nLowEnergy) | |
71 | print("") | |
72 | print("Press C to type a command") | |
73 | return 0 | |
74 | end | |
75 | ||
76 | function SubmitCommand() | |
77 | print("") | |
78 | print("Enter command") | |
79 | sleep(1/10) | |
80 | print("> ") | |
81 | local input = read() | |
82 | return input | |
83 | end | |
84 | ||
85 | function ExecuteCommand(command) | |
86 | if command == "help" then | |
87 | PrintHelp() | |
88 | SubmitCommand() | |
89 | elseif command == "reinit" then | |
90 | rednet.broadcast(command) | |
91 | sleep(1/3) | |
92 | rednet.broadcast(command) | |
93 | sleep(1/3) | |
94 | rednet.broadcast(command) | |
95 | sleep(1/3) | |
96 | InitializeNetwork() | |
97 | DisplayStats() | |
98 | else | |
99 | rednet.broadcast(command) | |
100 | DisplayStats() | |
101 | end | |
102 | return 0 | |
103 | end | |
104 | ||
105 | function PrintHelp() | |
106 | print("help") | |
107 | print("start") | |
108 | print("quarry") | |
109 | print("stop") | |
110 | print("restart") | |
111 | print("reinit") | |
112 | print("offset --layers") | |
113 | print("update --pastebin") | |
114 | print("") | |
115 | return 0 | |
116 | end | |
117 | ||
118 | - | if not rednet.isOpen(NETWORK_SIDE) then |
118 | + | |
119 | - | rednet.open(NETWORK_SIDE) |
119 | + | |
120 | -------------------------------------------------- | |
121 | ||
122 | function InitializeNetwork() | |
123 | rednet.open(NETWORK_SIDE) | |
124 | ||
125 | nTotal = 0 | |
126 | local nTimeouts = 0 | |
127 | ||
128 | term.clear() | |
129 | term.setCursorPos(1,1) | |
130 | print("Initializing...") | |
131 | ||
132 | while nTimeouts <= TIMEOUTS_MAX do | |
133 | sleep(1/4) | |
134 | rednet.broadcast("Server is here") | |
135 | ||
136 | local receivedID, receivedMessage, _ = rednet.receive(TIMEOUT) | |
137 | ||
138 | print(receivedID) | |
139 | ||
140 | if receivedID == nil then | |
141 | nTimeouts = nTimeouts + 1 | |
142 | print("Timeout.") | |
143 | else | |
144 | print("Received message.") | |
145 | local _, _, minerIDstr = string.find(receivedMessage, "Miner (%d+) is here") | |
146 | minerID = tonumber(minerIDstr) | |
147 | if receivedID == minerID then | |
148 | AddMiner(minerID) | |
149 | nTimeouts = 0 | |
150 | rednet.send(minerID, "Gotcha") | |
151 | print("Miner " .. nTotal .. " initialized.") | |
152 | end | |
153 | end | |
154 | end | |
155 | ||
156 | print("Initialized total " .. nTotal .. " miners.") | |
157 | ||
158 | SaveMinersTableToFile() | |
159 | ||
160 | return 0 | |
161 | end | |
162 | ||
163 | function AddMiner(minerID) | |
164 | nTotal = nTotal + 1 | |
165 | miners[nTotal][1] = minerID | |
166 | miners[nTotal][7] = 1 | |
167 | ||
168 | minersCompact[nTotal] = minerID | |
169 | ||
170 | return 0 | |
171 | end | |
172 | ||
173 | -------------------------------------------------- | |
174 | -- Общение с имеющимися майнерами | |
175 | -------------------------------------------------- | |
176 | ||
177 | function UpdateMiner(minerN) -- Обновление статуса майнера | |
178 | local timeouts = 0 | |
179 | local minerID = miners[minerN][1] | |
180 | ||
181 | while timeouts <= TIMEOUTS_MAX do | |
182 | CommandMiner(minerN, "statusrequest") | |
183 | local receivedID, receivedMessage, _ = rednet.receive(TIMEOUT) | |
184 | ||
185 | if receivedID == minerID then | |
186 | local state = textutils.unserialize(receivedMessage) | |
187 | ||
188 | miners[minerN][2] = state[1] | |
189 | miners[minerN][3] = state[2] | |
190 | miners[minerN][4] = state[3] | |
191 | miners[minerN][5] = state[4] | |
192 | miners[minerN][6] = state[5] | |
193 | miners[minerN][7] = 1 | |
194 | ||
195 | return 0 | |
196 | end | |
197 | ||
198 | timeouts = timeouts + 1 -- Если дошли до этого места, то таймаут | |
199 | end | |
200 | miners[minerN][7] = 0 -- Если дошли до этого места, то майнер в оффлайне | |
201 | return 1 | |
202 | end | |
203 | ||
204 | function UpdateAllMiners() -- Обновление статусов всех майнеров | |
205 | for i = 1, nTotal do | |
206 | UpdateMiner(i) | |
207 | end | |
208 | ||
209 | return 0 | |
210 | end | |
211 | ||
212 | function CommandMiner(minerN, action) | |
213 | local minerID = miners[minerN][1] | |
214 | ||
215 | rednet.send(minerID, action) | |
216 | ||
217 | return 0 | |
218 | end | |
219 | ||
220 | function CommandAllMiners(action) | |
221 | ||
222 | rednet.broadcast(action) | |
223 | ||
224 | return 0 | |
225 | end | |
226 | ||
227 | -------------------------------------------------- | |
228 | -- Пересчет статистики | |
229 | -------------------------------------------------- | |
230 | ||
231 | function RecalculateStatistics () | |
232 | nOnline = 0 | |
233 | nLowEnergy = 0 | |
234 | nMining = 0 | |
235 | nQuarry = 0 | |
236 | nStopped = 0 | |
237 | maxLayer = 0 | |
238 | minLayer = 256 | |
239 | ||
240 | for i = 1, nTotal do | |
241 | -- nOnline | |
242 | nOnline = nOnline + miners[i][7] | |
243 | -- nLowEnergyTemp | |
244 | if miners[i][3] <= 50000 then | |
245 | nLowEnergy = nLowEnergy + 1 | |
246 | end | |
247 | -- nMiningTemp, nQuarryTemp, nStoppedTemp | |
248 | if miners[i][2] == "not mining" then | |
249 | nStopped = nStopped + 1 | |
250 | elseif miners[i][2] == "mining" then | |
251 | nMining = nMining + 1 | |
252 | elseif miners[i][2] == "mining %(quarry mode%)" then | |
253 | nQuarry = nQuarry + 1 | |
254 | end | |
255 | -- maxLayerTemp | |
256 | maxLayer = math.max(maxLayer, miners[i][4]) | |
257 | minLayer = math.min(minLayer, miners[i][4]) | |
258 | end | |
259 | ||
260 | return 0 | |
261 | end | |
262 | - | file.writeLine(textutils.serialize(miners)) |
262 | + | |
263 | -------------------------------------------------- | |
264 | -- Сохранение и загрузка | |
265 | -------------------------------------------------- | |
266 | ||
267 | function SaveMinersTableToFile() | |
268 | local file = fs.open(TEMP_FILE, "w") | |
269 | file.writeLine(textutils.serialize(minersCompact)) | |
270 | file.writeLine(nTotal) | |
271 | file.close() | |
272 | ||
273 | fs.delete(DATA_FILE) | |
274 | - | miners = textutils.unserialize(file.readLine()) |
274 | + | |
275 | ||
276 | return 0 | |
277 | end | |
278 | ||
279 | function LoadMinersTableFromFile() | |
280 | local file = fs.open(DATA_FILE, "r") | |
281 | minersCompact = textutils.unserialize(file.readLine()) | |
282 | nTotal = tonumber(file.readLine()) | |
283 | ||
284 | for i = 1, nTotal do | |
285 | miners[i][1] = minersCompact[i] | |
286 | - | if not rednet.isOpen(NETWORK_SIDE) then |
286 | + | |
287 | - | print("Opening networking...") |
287 | + | |
288 | - | rednet.open(NETWORK_SIDE) |
288 | + | |
289 | ||
290 | return 0 | |
291 | end | |
292 | ||
293 | -------------------------------------------------- | |
294 | -- Главный луп | |
295 | -------------------------------------------------- | |
296 | ||
297 | function main() | |
298 | rednet.open(NETWORK_SIDE) | |
299 | ||
300 | if fs.exists(DATA_FILE) then | |
301 | print("Loading previous data...") | |
302 | LoadMinersTableFromFile() | |
303 | - | SaveMinersTableToFile() |
303 | + | |
304 | print("Initializing...") | |
305 | InitializeNetwork() | |
306 | end | |
307 | ||
308 | while true do | |
309 | UpdateAllMiners() | |
310 | RecalculateStatistics() | |
311 | DisplayStats() | |
312 | ||
313 | local timeout = os.startTimer(REFRESH_PERIOD) | |
314 | while true do | |
315 | event = {os.pullEvent()} | |
316 | if event[1] == "key" and event[2] == 46 then | |
317 | local command = SubmitCommand() | |
318 | ExecuteCommand(command) | |
319 | timeout = os.startTimer(REFRESH_PERIOD) | |
320 | elseif event[1] == "timer" and event[2] == timeout then | |
321 | break | |
322 | end | |
323 | end | |
324 | end | |
325 | end | |
326 | ||
327 | main() |