· last year · Jun 25, 2024, 12:50 AM
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("back")
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},
64-- Default help messages for each program
65
66functionTable = {
67
68help = function()
69
70 rednet.send(connectID,help,mProt)
71end,
72
73upload = function (item)
74 if fs.exists(item[2]) == false then
75
76 rednet.send(connectID, "send", mProt)
77 uselessID, downloadedFile = rednet.receive(mProt)
78 openFile = fs.open(item[2], 'w')
79 openFile.write(downloadedFile)
80 openFile.close()
81 else
82
83 rednet.send(connectID, "File already exists on connected computer.", mProt)
84 end
85 -- Handles the upload function
86end,
87
88download = function (item)
89 if fs.exists(item[1]) == true and fs.isDir(item[1]) == false then
90
91 fileOpen = fs.open(item[1], 'r')
92 stringSend = fileOpen.readAll()
93 fileOpen.close()
94 tableSend = {stringSend, "Successfully downloaded file."}
95 rednet.send(connectID, tableSend, mProt)
96 else
97
98 rednet.send(connectID, "File does not exist on connected computer.", mProt)
99 end
100 -- Handles the download function
101end,
102
103filelist = function ()
104
105 programList = fs.list("")
106 files = ""
107
108 for i=1,#programList do
109 if fs.isDir(programList[i]) == false then
110 if files == "" then
111
112 files = programList[i]
113 else
114
115 files = files .. ", " .. programList[i]
116 end
117 end
118 end
119 -- Handles the fileList function by sending a list of files (not directories) through
120
121 rednet.send(connectID, files, mProt)
122end,
123
124redstone = function(item)
125 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
126 if item[2] == "on" then
127
128 -- First checks to see if item[1] is a valid side then checks if item[2] is a valid state
129 redstone.setOutput(item[1], true)
130 rednet.send(connectID, "Set output " .. item[1] .. " to " .. item[2], mProt)
131 -- Turns the side in item[1] on
132
133 elseif item[2] == "off" then
134
135 redstone.setOutput(item[1], false)
136 rednet.send(connectID, "Set output " .. item[1] .. " to " .. item[2], mProt)
137 -- Turns the side in item[1] off
138 else
139
140 rednet.send(connectID, 'Invalid syntax. Use "redstone [side] [on/off]"', mProt)
141 end
142 else
143
144 rednet.send(connectID, 'Invalid side. Available sides are: top, down, back, front, left, right', mProt)
145 end
146 -- Error messages to catch every combination
147end
148}
149}
150
151-- ============================ Plugin handling below =============================
152
153local args = { ... }
154
155if args[1] then
156
157pluginFolder = args[1] .. "/" .. pluginFolder
158end
159-- Seeing if when running the program you have specified a folder in the arguments
160
161tablesToMerge = {"status", "helpTable", "functionTable"}
162-- Defining what tables are okay to merge with the plugin's table
163
164function mergeTable(mergeTab, tabName)
165for key, value in pairs(mergeTab) do
166 functions[tabName][key:lower()] = value
167end
168end
169-- Function for merging 2 tables
170
171if not fs.exists(pluginFolder) then
172fs.makeDir(pluginFolder)
173end
174-- Checking if the plugin folder is a directory yet or not and if its not then it creates it
175
176pluginFiles = fs.list(pluginFolder)
177
178for i=1,#pluginFiles do
179if not fs.isDir(pluginFolder .. pluginFiles[i]) then
180
181 os.loadAPI(pluginFolder .. "/" .. pluginFiles[i])
182
183 for j=1,#tablesToMerge do
184 if _G[pluginFiles[i]][tablesToMerge[j]] then
185
186 mergeTable(_G[pluginFiles[i]][tablesToMerge[j]], tablesToMerge[j])
187 end
188 end
189end
190end
191-- Merging the existing table with the plugin's table
192
193-- ========================== Help string handling below ==========================
194
195help = "exit - Disconnects from current connected computer\n"
196
197for program, progHelp in pairs(functions.helpTable) do
198if functions.status[program] == 1 then
199 help = help .. program .. " - " .. progHelp .. "\n"
200end
201end
202
203help = help:sub(1,string.len(help) - 1)
204-- Creates the help variable from the programs that are active
205
206-- ====================== Putting everything together below =======================
207
208function progRunning()
209
210local terminate = false
211-- Declaring the terminate variable as false
212
213repeat
214
215 local ID, newMsg = rednet.receive(mProt)
216 -- Getting the connected computer's messages
217
218 if ID == sendID and connected then
219 -- Checking if the computer that sent the message is the connected computer aswell as seeing if the connected variable is still true
220
221 local newMsgIsWord = newMsg ~= ""
222 -- Checking if the incoming message is a word or not
223
224 if newMsgIsWord and newMsg[1]:lower() == "terminate" then
225
226 terminate = true
227 rednet.send(ID, "Terminated " .. funcToRun .. ".", mProt)
228 -- Seeing if the connected computer has sent "terminate" through and setting the terminate variable to true if they have
229 elseif newMsgIsWord and newMsg[1]:lower() == "exit" then
230
231 connected = false
232 rednet.send(ID, "Disconnecting from current computer but continuing to run " .. funcToRun .. ".", mProt)
233 -- Still executing current function even if connected computer has exitted
234
235 elseif newMsgIsWord and newMsg[1]:lower() == "fuel" and turtle then
236
237 rednet.send(ID, "Fuel level currently at: " .. turtle.getFuelLevel(), mProt)
238 -- Sending the current fuel level through to the connected computer
239 else
240
241 local sendMessage = "Currently executing " .. funcToRun .. ". Available commands are -\nterminate: terminate current function\nexit: continue to run function but disconnect."
242 -- Defining the message variable to send
243
244 if turtle and turtle.getFuelLevel() ~= "unlimited" then
245 sendMessage = sendMessage .. "\nfuel: get the fuel level"
246 end
247 -- Adding fuel to the help if the connected computer is a turtle
248
249 rednet.send(ID, sendMessage, mProt)
250 -- Responding to the user if they send a message
251 end
252 end
253
254until terminate
255-- Runs until the terminate variable is true
256end
257-- Function to respond to the connected computer while the local computer is running a function
258
259function callFunc()
260
261functions.functionTable[funcToRun](msg, connectID, mProt)
262end
263-- Function for calling the correct function
264
265while true do
266sendID, msg = rednet.receive(mProt)
267
268 if msg == "list" then
269 rednet.send(sendID, myFunction, mProt)
270 -- Will respond to computers that are running list unless running connect
271
272 elseif msg == "connect" then
273 rednet.send(sendID, {"Connected!",functions.status}, mProt)
274 -- Making the link from the mRemote program to the mControl program
275
276 connected = true
277
278 while connected do
279 invalid = true
280 connectID, msg = rednet.receive(mProt)
281 -- Getting the new message from the connected computer
282
283 if connectID == sendID then
284 -- Comparing the connectID with the sendID to see if its the same id so no other computer can send messages
285 if msg[1] ~= nil then
286
287 msg[1] = msg[1]:lower()
288 end
289
290 if msg[1] == "exit" then
291
292 rednet.send(connectID,"Disconnecting from current computer.",mProt)
293 invalid = false
294 connected = false
295 -- Exits the connect cycle so that it will respond to list and for other computers to connect to it
296 end
297
298 for key,value in pairs(functions.functionTable) do
299 if key == msg[1] then
300
301 invalid = false
302 table.remove(msg,1)
303 funcToRun = key
304 parallel.waitForAny(callFunc,progRunning)
305 end
306 end
307
308 if invalid then
309
310 rednet.send(connectID, 'Invalid command. Type "help" for options.', mProt)
311 -- Default path if msg[1] doesn't get caught by the for loop
312 end
313 end
314 end
315 end
316end