View difference between Paste ID: 5mB8Y4mw and rSqGVmDX
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()