· 6 years ago · Oct 06, 2019, 04:10 PM
1--PeachMaster's MTC and Digital Interlocking System: A system for MTC and W-MTC, but this one is for standard MTC
2--Hi! you are not supposted to access this file. get out debil cyka blyat
3--...unless you know what you're doing. I mean, why are you doing this? This file isn't really for editing.
4--You get what you get and you don't throw a fit. That's what my kindergarden teacher said.
5
6-- Menu API provided by cyanisaac and ProjectB, licensed under the MIT license.
7--JSON API provided by ElvishJerricco.
8--Initalize all the things!
9--Initalize signalblocks
10--TrainControl 1.1
11--Use one channel instead of multiple for signal communications
12local sbraw = fs.open("signalDatabase", "r")
13local cdraw = fs.open("computerdatabase", "r")
14local sraw = fs.open("system", "r")
15local craw = fs.open("config", "r")
16os.loadAPI("menu")
17local signalBlocks = textutils.unserialise(sbraw.readAll())
18local system = sraw.readAll()
19local computerDatabase = textutils.unserialise(cdraw.readAll())
20local config
21local clientsDoneInSelfTest = {}
22local radio = peripheral.find("pdmInstructionRadio")
23local sendQueue
24sbraw.close()
25sraw.close()
26cdraw.close()
27local modem = peripheral.find("modem")
28if modem == nil then
29error("TrainControl cannot continue because a modem has not been found.")
30end
31
32if fs.exists("menu") == false then
33print("Downloading menu API..stand by..")
34shell.run("pastebin get UK4ATXvH menu")
35sleep(1)
36end
37
38if fs.exists("json") == false then
39 print("Downloading JSON API..stand by..")
40shell.run("pastebin get 4nRg9CHU json")
41sleep(1)
42end
43
44if fs.exists("encrypt") == false then
45 print("Downloading encryption API...stand by..")
46 shell.run("pastebin get WRTfH0yx encrypt")
47 sleep(1)
48end
49
50
51
52
53os.loadAPI("menu")
54os.loadAPI("json")
55os.loadAPI("encrypt")
56
57
58--Oh yeah, don't forget about the main functions.
59
60local function setup()
61 local madeConfig = {}
62 term.clear()
63 term.setCursorPos(1,1)
64 print("Please set a name for this system for identification (ex. railroad/divison name): ")
65 local systemName = read()
66 madeConfig["SystemName"] = systemName
67 menu.doInfoScreen("Welcome to TrainControl!", "Hi, Welcome! This will help you set up the program to get your trains running safely.")
68 local theMenu = {"Modem using Rednet (most recommended)", "Bundled Redstone", "Redstone (least recommended, don't use it)"}
69 madeConfig["SignalConnectionType"] = menu.doMenu("TrainControl Setup | Signal Connection Type", theMenu)
70 theMenu = {"MTC", "W-MTC", "Don't use it"}
71 madeConfig["UseMTC"] = menu.doMenu("TrainControl Setup | MTC Type", theMenu)
72
73 while true do
74 term.clear()
75 term.setCursorPos(1,1)
76
77 print("Please define a channel for Modem communications. It doesn't really matter which one you choose, as long as it's not being used for something else.")
78 local ModemChannel = read()
79 local hmm = tonumber(ModemChannel)
80 if hmm ~= nil then
81
82 if hmm > 65535 then
83
84 print("That was not a valid channel. Channels cannot as be higher than 65535.")
85 else
86 madeConfig["ModemChannel"] = hmm
87 break
88 end
89
90 else
91 print("That was not a valid channel. Channels must be numbers and as high as 65535.")
92 end
93end
94
95 term.clear()
96 term.setCursorPos(1,1)
97 print("Please define a channel for Terminal communications. It doesn't really matter which one you choose, as long as it's not being used for something else.")
98 local terminalChannel = read()
99 madeConfig["TerminalChannel"] = terminalChannel
100
101 term.clear()
102 term.setCursorPos(1,1)
103
104
105
106 menu.doInfoScreen("Setup Complete!", "TrainControl will start after you press ENTER.")
107 print(textutils.serialise(madeConfig))
108 config = madeConfig
109 local writeConfig = fs.open("config", "w")
110 writeConfig.write(textutils.serialise(config))
111 writeConfig.close()
112 sleep(2)
113
114
115end
116
117local function getSomethingFromTable(theTable, thingWanted) -- A workaround to crappy CC/Lua. >:(
118 for k, v in pairs(theTable) do
119 if k == thingWanted then
120 return v
121 end
122 end
123end
124
125local function saveTableFile(path, watchuwant) -- Quicker way to do things w o a h
126 local handle = fs.open(path, "w")
127 handle.write(textutils.serialise(whatchuwant))
128 handle.close()
129end
130
131local function loadTableFile(path) -- Quiciker way to do things w o a h
132 local handle = fs.open(path, "r")
133 local thing = textutils.unserialise(handle.readAll())
134 handle.close()
135 return thing
136end
137
138
139local function doEncrypt(thing1)
140
141 -- local ok = encrypt.encrypt(thing1, "kgkg499tgi34ikg39koowklfow0o349")
142 --return ok
143 return thing1
144end
145
146local function doDecrypt(thing)
147 -- local ok = encrypt.decrypt(thing, "kgkg499tgi34ikg39koowklfow0o349")
148 -- return ok
149 return thing
150end
151
152
153local function controlSignals()
154 --Signal status meanings:
155 --1 = Unoccupied, green
156 --2 = Unoccupied, yellow (train in next block so use caution)
157 --3 = Occupied, train is in it.
158
159 --Reload the signaldatabase, just in case anything was changed.
160 signalDatabase = loadTableFile("signalDatabase")
161 if config.SignalConnectionType == 1 then
162
163 --Connection type is Modem based, so do everything modem related here.
164 local event, side, sendChannel, replyChannel, message, distance = os.pullEvent()
165
166 if event == "modem_message" then
167 local response = doDecrypt(message)
168
169 if response.funct == "blockOccupied" then
170 signalBlocks[response.source].status = 3
171
172 if getSomethingFromTable(signalBlocks[response.source], "prev") ~= "none" then
173 local previousSignal = getSomethingFromTable(signalBlocks[response.source], "prev")
174
175 if getSomethingFromTable(signalBlocks[response.source], "prev").status ~= 3 then signalBlocks[previousSignal].status = 2 end
176 print("Sending a signal update to the previous signal.")
177 modem.transmit(config["ModemChannel"], config["ModemChannel"], doEncrypt({funct = "updateSignalStatus", signalStatus = getSomethingFromTable(signalBlocks, previousSignal).status, to = getSomethingFromTable(signalBlocks, previousSignal).name}))
178 end
179
180 print(response.source.." is occupied. ")
181
182 end
183 if response.funct == "blockReleased" then
184 print(response.source)
185 signalBlocks[response.source].status = 1
186 print(response.source.." is released.")
187
188 if getSomethingFromTable(signalBlocks[response.source], "prev") ~= "none" then
189 local previousSignal = getSomethingFromTable(signalBlocks[response.source], "prev")
190 if getSomethingFromTable(signalBlocks[response.source], "prev").status ~= 3 then signalBlocks[previousSignal].status = 1 end
191 print("Sending signalupdate to the previous signal.")
192 modem.transmit(config["ModemChannel"], config["ModemChannel"], doEncrypt({funct = "updateSignalStatus", signalStatus = getSomethingFromTable(signalBlocks, previousSignal).status, to = getSomethingFromTable(signalBlocks, previousSignal).name}))
193 end
194
195 end
196 if getSomethingFromTable(signalBlocks[response.source], "next") ~= "none" and signalBlocks[response.source].occupiedBy ~= nil and config["UseMTC"] == 2 then
197 local nextSignal = getSomethingFromTable(signalBlocks[response.source], "next")
198 print("Sending a signal update for W-MTC to the previous signal. ")
199 modem.transmit(config["ModemChannel"], config["ModemChannel"], doEncrypt({funct = "updateSignalStatus", signalStatus = getSomethingFromTable(signalBlocks, nextSignal).status, to = getSomethingFromTable(signalBlocks, previousSignal).name, isWMTCOkay = true}))
200 else
201 modem.transmit(config["ModemChannel"], config["ModemChannel"], doEncrypt({funct = "updateSignalStatus", signalStatus = getSomethingFromTable(signalBlocks, nextSignal).status, to = getSomethingFromTable(signalBlocks, previousSignal).name, isWMTCOkay = false}))
202 end
203
204 if response.funct == "switchOccupied" then
205 print(response.source.. " is occupied!")
206 signalBlocks[response.source].status = 1
207
208
209 end
210
211 if response.funct == "switchReleased" then
212 print(response.source.. "is released!")
213 signalBlocks[response.source].status = 0
214 end
215
216 if response.funct == "setSwitchStatus" then
217 --owo
218 modem.transmit(getSomethingFromTable(tonumber(config["ModemChannel"]), tonumber(config["ModemChannel"]), encrypt(textutils.serialise({funct = "updateSwitchStatus", switchStatus = response.switchStatus})))
219 end
220
221 --Alright, we got that, now send it to the signals.
222 if response.source ~= "Terminal" then
223 modem.transmit(config["ModemChannel"], config["ModemChannel"], doEncrypt({funct = "updateSignalStatus", signalStatus = getSomethingFromTable(signalBlocks, response.source).status, to = getSomethingFromTable(signalBlocks, response.source).name, isWMTCOkay = getSomethingFromTable(signalBlocks, response.source).isWMTCOkay}))
224 end
225 if config["UseMTC"] == 2 then
226 --Alright..W-MTC on..generate a MTC data packet.
227 local speedLimit1
228 local nextSpeedLimit1
229 local speedChange1
230 local changeX
231 local changeY
232 local changeZ
233 local endSoon1
234 local xStopPoint
235 local yStopPoint
236 local zStopPoint
237 local mtcStats
238 local nextSignal = getSomethingFromTable(signalBlocks[response.source], "next")
239 if getSomethingFromTable(signalBlocks[nextSignal], "status") == 3 then
240 speedLimit = getSomethingFromTable(signalBlocks[response.source], "yellowSpeedLimit")
241 endSoon = true
242 xStopPoint = getSomethingFromTable(signalBlocks[nextSignal], "positionX")
243 yStopPoint = getSomethingFromTable(signalBlocks[nextSignal], "positionY")
244 zStopPoint = getSomethingFromTable(signalBlocks[nextSignal], "positionZ")
245 end
246 if getSomethingFromTable(signalBlocks[nextSignal], "status") == 2 then
247 nextSpeedLimit = getSomethingFromTable(signalBlocks[response.source], "yellowSpeedLimit")
248 speedChange = true
249 changeX = getSomethingFromTable(signalBlocks[nextSignal], "positionX")
250 changeY = getSomethingFromTable(signalBlocks[nextSignal], "positionY")
251 changeZ = getSomethingFromTable(signalBlocks[nextSignal], "positionZ")
252 end
253
254 --Alright..generate the JSON.
255 local send = {speedLimit = speedLimit1, nextSpeedLimit = nextSpeedLimit1, speedChange = speedChange1, endSoon = endSoon1}
256
257 if endSoon1 then
258 send["xStopPoint"] = xStopPoint
259 send["yStopPoint"] = yStopPoint
260 send["zStopPoint"] = zStopPoint
261 end
262
263 if getSomethingFromTable(signalBlocks[response.source], "next") == "none" then
264 mtcStat = 2
265 send["mtcStatus"] = mtcStat
266 end
267
268 if speedChange1 then
269 send["nextSpeedLimitChangeX"] = changeX
270 send["nextSpeedLimitChangeY"] = changeY
271 send["nextSpeedLimitChangeZ"] = changeZ
272 end
273 --Is it done? Okay, print it just in case.
274 print(textutils.serialise(send))
275 --Okay, it's finally done, put it into the queue.
276 if signalBlocks[response.source].occupiedBy ~= nil then
277
278 signalBlocks[response.source].sendTo = {funct = "sendToTrain", sendTo = signalBlocks[response.source].occupiedBy, send1 = send}
279 end
280 end
281 --Also, finally, save it to the file so it can be used later.
282 -- saveTableFile("signaldatabase", signalDatabase)
283 if response.funct == "radio_message" then
284 --Okay, it came from a train. Let's check it out.
285 local response1 = response.message
286 print(textutils.serialise(response1))
287 if response1.funct == "attemptConnection" then
288 --Attempting..alright..welcome!
289 --Give temp data, actual limits will be sent on the next update
290 local send = {funct = "startlevel2", speedLimit = 60, nextSpeedLimit = 0, speedChange = false, stationStopSoon = false, mtcStatus = 1 }
291
292 end
293
294 if response1.funct == "update" then
295 --Great, an update! There may have been something you have missed, so I'm going to send it to you.
296 signalBlocks[response.signalBlock].occupiedBy = response.sendChannel
297
298 if signalBlocks[response.signalBlock].sendTo ~= nil then
299 modem.transmit(signalBlock[response.signalBlock].wirelessRadioChannel, modem["ModemChannel"], signalBlocks[response.source].sendTo)
300 end
301
302 end
303
304 if response1.funct == "disconnect" then
305
306 end
307
308 end
309
310 end
311
312--No? it's not a modem message? Then maybe it's something else.
313
314
315end
316end
317
318local function starts_with(str, start)
319 return str:sub(1, #start) == start
320 end
321
322 local function ends_with(str, ending)
323 return ending == "" or str:sub(-#ending) == ending
324 end
325
326local function powerUpSelfTest()
327
328
329--Okay, host the system via rednet.
330
331--...test for all of them.
332if config.SignalConnectionType == 1 then
333 --rednet.send(72, {71, "test", "test!!!"})
334
335 for key,value in pairs( computerDatabase ) do
336 local send = doEncrypt({funct = "attemptConnection", to = key})
337 print("Attempting connection to "..key)
338 modem.transmit(tonumber(config["ModemChannel"]), tonumber(config["ModemChannel"]), send)
339
340 --Wait for a response, but also there's a timeout.
341 local timeout = os.startTimer(15)
342 while true do
343 local event = {os.pullEvent()}
344 if event[1] == "modem_message" then
345 --Decode the response.
346 local response = doDecrypt(event[5])
347 if response.funct == "ok" then
348 print("Connection to "..response.source.."is okay.")
349 table.insert(clientsDoneInSelfTest, response.source)
350 break
351 end
352 elseif event[1] == "timer" and event[2] == timeout then
353 print("Connection to "..key.." aborted because it took too long.")
354
355 return false
356 end
357
358 end
359
360 end
361
362end
363 return true
364end
365
366
367
368
369
370
371
372---..initalized? Great! now print stuff.
373term.setCursorPos(1,1)
374print(fs.exists("config") )
375if fs.exists("config") then
376local craw = fs.open("config", "r")
377local theconfig = textutils.unserialise(craw.readAll())
378config = theconfig
379craw.close()
380else
381setup()
382end
383term.clear()
384term.setTextColor(colors.green)
385textutils.slowPrint("PeachMaster's MTC and Digital Interlocking System", 15)
386print("This copy is for: "..getSomethingFromTable(config, "SystemName"))
387term.setTextColor(colors.white)
388modem.open(tonumber(config["ModemChannel"]))
389modem.open(tonumber(config["TerminalChannel"]))
390if powerUpSelfTest() then
391 print("Power Up Self Test completed succesfully!")
392 while true do
393 controlSignals()
394 end
395
396else
397
398end