· 7 years ago · Sep 02, 2018, 08:56 PM
1-- This is eniallator's Control program.
2-- It works by trying to run commands sent by the remote computer.
3-- The remote program (the program that can run this) is http://pastebin.com/MY9HDL52 and runs like a command line.
4--
5-- ================================================================================
6--
7-- An on going project that im still working on.
8--
9-- ================================================================================
10--
11-- This program can use plugins!
12-- The reason i have made it able to use plugins is so that you can easily install multiple function packs/functions by simply downloading the pastebin into the plugin folder
13-- To create a plugin, follow the plugin template guide here: http://pastebin.com/YmmnaqXP
14--
15-- ================================================================================
16--
17-- To create a new function in this file do the following steps.
18-- In the helpTable table put the following value.
19--
20-- *insert your function name here* = "*insert your function's help here*"
21--
22-- To make your function just add a new key/value to the functionTable on line 66 where the key is how you are going to call your function in the remote command line. For example inputting "testFunc arg1 arg2" would call the function testfunc from the functionTable and in the function argument it would then pass the following arguments: ({"arg1","arg2"},*ID of remote computer thats connected*,*protocol thats being used*).
23--
24-- If you want to send an output to the remote program from your function then use the following rednet code:
25--
26-- rednet.send(connectID, "*insert string you want to send here*", mProt)
27--
28-- If you would like to modify the prefix of the remote's command line then instead of sending a string through to the remote, send the following table:
29--
30-- {"*insert output you want to send here*","*insert prefix you want to send here*"}
31--
32-- If you want people to be able to turn on/off your function then do the following step.
33--
34-- *insert your function name here* = 1
35--
36-- The program will automatically detect if theres a status key/value for your function so thats all you need to do.
37
38version = "1.2.2.1"
39-- Version is used for the updater program i've made here: http://pastebin.com/jSWFQsA1
40
41mProt = "masterRC"
42rednet.open("right")
43-- mProt is the protocol the computer will be using. You can also configure what side the wireless modem is on
44
45pluginFolder = "mControlPlugins"
46-- Where the plugins for the program are read from. Plugins are easily installable functions for the control program
47
48myFunction = "Default mControl program!"
49-- Called when the remote computer lists available computers it can connect with
50
51-- ======================= Default function declaring below =======================
52
53functions = {
54
55status = {upload = 1, download = 1, filelist = 1, redstone = 1},
56-- Easily configure which programs you want running and which ones you don't by simply setting 1 for those you want running and 0 for those you don't want running.
57
58helpTable = {
59 upload = "upload a file to connected computer",
60 download = "download a file from connected computer",
61 filelist = "list files on connected computer",
62 redstone = "control sides of connected computer to emit redstone on"
63 gps = "find me"
64},
65-- Default help messages for each program
66
67functionTable = {
68
69gps = function(findme)
70local x, y, z = gps.locate(5)
71rednet.send(connectID, "X ", x , mProt)
72rednet.send(connectID, "Y ", y , mProt)
73rednet.send(connectID, "Z ", z , mProt)
74end,
75
76help = function()
77
78 rednet.send(connectID,help,mProt)
79end,
80
81upload = function (item)
82 if fs.exists(item[2]) == false then
83
84 rednet.send(connectID, "send", mProt)
85 uselessID, downloadedFile = rednet.receive(mProt)
86 openFile = fs.open(item[2], 'w')
87 openFile.write(downloadedFile)
88 openFile.close()
89 else
90
91 rednet.send(connectID, "File already exists on connected computer.", mProt)
92 end
93 -- Handles the upload function
94end,
95
96download = function (item)
97 if fs.exists(item[1]) == true and fs.isDir(item[1]) == false then
98
99 fileOpen = fs.open(item[1], 'r')
100 stringSend = fileOpen.readAll()
101 fileOpen.close()
102 tableSend = {stringSend, "Successfully downloaded file."}
103 rednet.send(connectID, tableSend, mProt)
104 else
105
106 rednet.send(connectID, "File does not exist on connected computer.", mProt)
107 end
108 -- Handles the download function
109end,
110
111filelist = function ()
112
113 programList = fs.list("")
114 files = ""
115
116 for i=1,#programList do
117 if fs.isDir(programList[i]) == false then
118 if files == "" then
119
120 files = programList[i]
121 else
122
123 files = files .. ", " .. programList[i]
124 end
125 end
126 end
127 -- Handles the fileList function by sending a list of files (not directories) through
128
129 rednet.send(connectID, files, mProt)
130end,
131
132redstone = function(item)
133 if item[1] == "top" or item[1] == "down" or item[1] == "back" or item[1] == "front" or item[1] == "left" or item[1] == "right" then
134 if item[2] == "on" then
135
136 -- First checks to see if item[1] is a valid side then checks if item[2] is a valid state
137 redstone.setOutput(item[1], true)
138 rednet.send(connectID, "Set output " .. item[1] .. " to " .. item[2], mProt)
139 -- Turns the side in item[1] on
140
141 elseif item[2] == "off" then
142
143 redstone.setOutput(item[1], false)
144 rednet.send(connectID, "Set output " .. item[1] .. " to " .. item[2], mProt)
145 -- Turns the side in item[1] off
146 else
147
148 rednet.send(connectID, 'Invalid syntax. Use "redstone [side] [on/off]"', mProt)
149 end
150 else
151
152 rednet.send(connectID, 'Invalid side. Available sides are: top, down, back, front, left, right', mProt)
153 end
154 -- Error messages to catch every combination
155end
156}
157}
158
159-- ============================ Plugin handling below =============================
160
161local args = { ... }
162
163if args[1] then
164
165pluginFolder = args[1] .. "/" .. pluginFolder
166end
167-- Seeing if when running the program you have specified a folder in the arguments
168
169tablesToMerge = {"status", "helpTable", "functionTable"}
170-- Defining what tables are okay to merge with the plugin's table
171
172function mergeTable(mergeTab, tabName)
173for key, value in pairs(mergeTab) do
174 functions[tabName][key:lower()] = value
175end
176end
177-- Function for merging 2 tables
178
179if not fs.exists(pluginFolder) then
180fs.makeDir(pluginFolder)
181end
182-- Checking if the plugin folder is a directory yet or not and if its not then it creates it
183
184pluginFiles = fs.list(pluginFolder)
185
186for i=1,#pluginFiles do
187if not fs.isDir(pluginFolder .. pluginFiles[i]) then
188
189 os.loadAPI(pluginFolder .. "/" .. pluginFiles[i])
190
191 for j=1,#tablesToMerge do
192 if _G[pluginFiles[i]][tablesToMerge[j]] then
193
194 mergeTable(_G[pluginFiles[i]][tablesToMerge[j]], tablesToMerge[j])
195 end
196 end
197end
198end
199-- Merging the existing table with the plugin's table
200
201-- ========================== Help string handling below ==========================
202
203help = "exit - Disconnects from current connected computer\n"
204
205for program, progHelp in pairs(functions.helpTable) do
206if functions.status[program] == 1 then
207 help = help .. program .. " - " .. progHelp .. "\n"
208end
209end
210
211help = help:sub(1,string.len(help) - 1)
212-- Creates the help variable from the programs that are active
213
214-- ====================== Putting everything together below =======================
215
216function progRunning()
217
218local terminate = false
219-- Declaring the terminate variable as false
220
221repeat
222
223 local ID, newMsg = rednet.receive(mProt)
224 -- Getting the connected computer's messages
225
226 if ID == sendID and connected then
227 -- Checking if the computer that sent the message is the connected computer aswell as seeing if the connected variable is still true
228
229 local newMsgIsWord = newMsg ~= ""
230 -- Checking if the incoming message is a word or not
231
232 if newMsgIsWord and newMsg[1]:lower() == "terminate" then
233
234 terminate = true
235 rednet.send(ID, "Terminated " .. funcToRun .. ".", mProt)
236 -- Seeing if the connected computer has sent "terminate" through and setting the terminate variable to true if they have
237 elseif newMsgIsWord and newMsg[1]:lower() == "exit" then
238
239 connected = false
240 rednet.send(ID, "Disconnecting from current computer but continuing to run " .. funcToRun .. ".", mProt)
241 -- Still executing current function even if connected computer has exitted
242
243 elseif newMsgIsWord and newMsg[1]:lower() == "fuel" and turtle then
244
245 rednet.send(ID, "Fuel level currently at: " .. turtle.getFuelLevel(), mProt)
246 -- Sending the current fuel level through to the connected computer
247 else
248
249 local sendMessage = "Currently executing " .. funcToRun .. ". Available commands are -\nterminate: terminate current function\nexit: continue to run function but disconnect."
250 -- Defining the message variable to send
251
252 if turtle and turtle.getFuelLevel() ~= "unlimited" then
253 sendMessage = sendMessage .. "\nfuel: get the fuel level"
254 end
255 -- Adding fuel to the help if the connected computer is a turtle
256
257 rednet.send(ID, sendMessage, mProt)
258 -- Responding to the user if they send a message
259 end
260 end
261
262until terminate
263-- Runs until the terminate variable is true
264end
265-- Function to respond to the connected computer while the local computer is running a function
266
267function callFunc()
268
269functions.functionTable[funcToRun](msg, connectID, mProt)
270end
271-- Function for calling the correct function
272
273while true do
274sendID, msg = rednet.receive(mProt)
275
276 if msg == "list" then
277 rednet.send(sendID, myFunction, mProt)
278 -- Will respond to computers that are running list unless running connect
279
280 elseif msg == "connect" then
281 rednet.send(sendID, {"Connected!",functions.status}, mProt)
282 -- Making the link from the mRemote program to the mControl program
283
284 connected = true
285
286 while connected do
287 invalid = true
288 connectID, msg = rednet.receive(mProt)
289 -- Getting the new message from the connected computer
290
291 if connectID == sendID then
292 -- Comparing the connectID with the sendID to see if its the same id so no other computer can send messages
293 if msg[1] ~= nil then
294
295 msg[1] = msg[1]:lower()
296 end
297
298 if msg[1] == "exit" then
299
300 rednet.send(connectID,"Disconnecting from current computer.",mProt)
301 invalid = false
302 connected = false
303 -- Exits the connect cycle so that it will respond to list and for other computers to connect to it
304 end
305
306 for key,value in pairs(functions.functionTable) do
307 if key == msg[1] then
308
309 invalid = false
310 table.remove(msg,1)
311 funcToRun = key
312 parallel.waitForAny(callFunc,progRunning)
313 end
314 end
315
316 if invalid then
317
318 rednet.send(connectID, 'Invalid command. Type "help" for options.', mProt)
319 -- Default path if msg[1] doesn't get caught by the for loop
320 end
321 end
322 end
323 end
324end