View difference between Paste ID: mzAa07Wn and J3i3TrjU
SHOW: | | - or go back to the newest paste.
1
----------------------------------------------------------------------
2
--                              Master API                          --
3
----------------------------------------------------------------------
4-
4+
5-
-- Version 0.1
5+
-- Version 0.1(481): 1.481-compatible
6-
6+
7
-- Master is an API that controls modules that use my module API.
8
-- Master should have:
9
--  1) fuel chest in the first slot.
10
--  2) stuff chest in the second slot
11
--  3) wireless mining turtle in the third slot
12
--  4) Any number of fuel/stuff chests and wireless mining turtles in its inventory
13
--  5) Note, that Master keeps at least one of each of those items in it's inventory.
14
-- Master's job is to listen to requests and send responses.
15
-- Usage:
16
--  1) For each type of the module you use, make a function which returns a response which will determine what module will do.
17
--     This function recieves the ID of that module as an argument
18
--     Of course, your module should know about that response and have that in its task table.
19
--     You can use master.makeTask(taskName, coordinates, additionalData) function to generate a task response.
20
--     additionalData parameter is optional, and if you don't want to send any coordinates, pass an empty table as coordinates.
21
--     There is a master.makeReturnTask() function added for convinience - it just makes a task that returns module to the Master
22
--  2) Use master.setType(Type, taskFunction) function to associate that function with the type of the module
23
--     you might want to change the state of the module in your taskFunction. Use master.getState(ID) and master.setState(ID, state)
24
--     functions to do that. Initial state of each module is "Waiting"
25
--  4) Set navigation zones for modules using the master.setNavigation(x, z, height) function
26
--     Please notice that x, z are 2D coordinates and height is the height of the plane where all the navigation is done
27-
--  5) Initialize the master by running master.init(filename, ID, mainChannel, moduleCount) function
27+
--  5) Initialize the master by running master.init(filename, ID, moduleCount) function
28
--     Master should have module API on its disk and a script for modules (that's the filename argument)
29-
--     mainChannel is the channel on which master listens, and the moduleCount is the required amount of modules
29+
--     moduleCount is the required amount of modules
30
--     ID is a new ID of the Master
31
--  6) make a stateFunction() that determines whether master should stop the operation. It should return false if it should stop
32
--     and return true if it shouldn't. State function can do other things, such as reinitialization to a new module script and so on
33
--     but it shouldn't take too much time to execute. Use master.reinit(filename, moduleCount) function to change the module script, if you want to.
34
--  7) Run master.operate(stateFunction) to start.
35
 
36
-- Some basic variables:
37
-- MasterID is the unique identifier of master. Default is 100
38
local MasterID = 100
39
 
40-
-- Channel is the channel Master listens.
40+
41-
local channel
41+
42
-- New placed modules will request "Position" to know where they are.
43
local modPosition = {x = 1, y = 0, z = 0, f = 0}
44
 
45
-- naviZones is used by modules to navigate and not interlock themselves
46
local naviZones = {x = 0, z = 0, height = 0}
47
function setNavigation (x, z, height)
48
	naviZones = {x = x, z = z, height = height}
49
end
50-
    naviZones = {x = x, z = z, height = height}
50+
51
--[[
52
*********************************************************************************************
53
*                                    Communication Part                                     *
54
*********************************************************************************************
55
]]--
56
 
57
rednet.open ("right")
58
 
59-
-- We need a modem to communicate.
59+
60-
local modem = peripheral.wrap ("right")
60+
61
-- Message should be a table with fields
62
--  1) Protocol - must be equal to "KuuNet"
63
--  2) ID - that's a sender ID
64
--  3) Master - that must be equal to MasterID variable.
65
--  4) Type - the type of the module. Used to know how to handle its task requests
66
--  Some other fields
67
function isValid (message)
68
	if message ~= nil then
69
		if message.Protocol ~= "KuuNet" then
70
			return false
71-
    if message ~= nil then
71+
		end
72-
        if message.Protocol ~= "KuuNet" then
72+
		if message.ID == nil then
73-
            return false
73+
			return false
74-
        end
74+
		end
75-
        if message.ID == nil then
75+
		if message.Master ~= MasterID then
76-
            return false
76+
			return false
77-
        end
77+
		end
78-
        if message.Master ~= MasterID then
78+
		return true
79-
            return false
79+
	else
80-
        end
80+
		return false
81-
        return true
81+
	end
82-
    else
82+
83-
        return false
83+
84-
    end
84+
85
function listen ()
86
	while true do
87
		local event, sndID, text_msg, senderDistance = os.pullEvent("rednet_message")
88
		local msg = textutils.unserialize (text_msg)
89-
    while true do
89+
		if isValid(msg) then
90-
        local event, modemSide, sndChan, rplyChan, text_msg, senderDistance = os.pullEvent("modem_message")
90+
			return msg
91-
        local msg = textutils.unserialize (text_msg)
91+
		end
92-
        if isValid(msg) then
92+
	end
93-
            return msg
93+
94-
        end
94+
95-
    end
95+
96
function response (ID, message)
97
	message.Protocol = "KuuNet"
98
	message.ID = ID
99-
function response (ID, chan, message)
99+
	message.Master = MasterID
100-
    message.Protocol = "KuuNet"
100+
	rednet.broadcast (textutils.serialize(message))
101-
    message.ID = ID
101+
102-
    message.Master = MasterID
102+
103-
    modem.transmit (chan+1, chan, textutils.serialize(message))
103+
104
*********************************************************************************************
105
*                                   Module Placement Part                                   *
106
*********************************************************************************************
107
]]--
108
-- moduleCount is the number of active modules
109
-- needModules is the number of modules required
110
-- modulesAvailable is the number of available modules
111
local moduleCount = 0
112
local needModules = 0
113
local modAvailable = nil
114
-- This function searches the turtle inventory for same item
115
-- as in the given slot, or selects that slot if there are more than one item
116
function searchItem (slot)
117
	turtle.select (slot)
118
	local found = 0
119
	for i=1,16 do
120-
    turtle.select (slot)
120+
		if i ~= slot then
121-
    local found = 0
121+
			if turtle.getItemCount (i) > 0 then
122-
    for i=1,16 do
122+
				if turtle.compareTo (i) then
123-
        if i ~= slot then
123+
					found = i
124-
            if turtle.getItemCount (i) > 0 then
124+
				end
125-
                if turtle.compareTo (i) then
125+
			end
126-
                    found = i
126+
		end
127-
                end
127+
	end
128-
            end
128+
	if found == 0 then
129-
        end
129+
		if turtle.getItemCount (slot) > 1 then
130-
    end
130+
			found = slot
131-
    if found == 0 then
131+
		else
132-
        if turtle.getItemCount (slot) > 1 then
132+
			turtle.select(1)
133-
            found = slot
133+
			return false
134-
        else
134+
		end
135-
            turtle.select(1)
135+
	end
136-
            return false
136+
	turtle.select (found)
137-
        end
137+
	return true
138-
    end
138+
139-
    turtle.select (found)
139+
140-
    return true
140+
141
	turtle.select (slot)
142
	local count = 0
143
	for i = 1,16 do
144-
    turtle.select (slot)
144+
		if turtle.compareTo(i) then
145-
    local count = 0
145+
			count = count + turtle.getItemCount(i)
146-
    for i = 1,16 do
146+
		end
147-
        if turtle.compareTo(i) then
147+
	end
148-
            count = count + turtle.getItemCount(i)
148+
	return count
149-
        end
149+
150-
    end
150+
151-
    return count
151+
152
-- The counting takes some time, so there is a variable to speed up the process
153
function availableModules ()
154
	if modAvailable == nil then
155
		local minimum = 1024
156
		for i = 1, 3 do
157-
    if modAvailable == nil then
157+
			local quantity = countBySample(i) - 1
158-
        local minimum = 1024
158+
			if minimum > quantity then
159-
        for i = 1, 3 do
159+
				minimum = quantity
160-
            local quantity = countBySample(i) - 1
160+
			end
161-
            if minimum > quantity then
161+
		end
162-
                minimum = quantity
162+
		modAvailable = minimum
163-
            end
163+
	end
164-
        end
164+
	return modAvailable
165-
        modAvailable = minimum
165+
166-
    end
166+
167-
    return modAvailable
167+
168
	searchItem (3)   -- search for a module
169
	if turtle.place () then  -- put it down
170
		searchItem (1)
171-
    searchItem (3)   -- search for a module
171+
		turtle.drop (1)  -- Add a fuel chest
172-
    if turtle.place () then  -- put it down
172+
		searchItem (2)
173-
        searchItem (1)
173+
		turtle.drop (1)  -- And a stuff chest
174-
        turtle.drop (1)  -- Add a fuel chest
174+
		turtle.select (1)-- select first slot to make things look good :)
175-
        searchItem (2)
175+
		peripheral.call ("front", "turnOn")    -- Turn on the module    
176-
        turtle.drop (1)  -- And a stuff chest
176+
		modAvailable = modAvailable - 1
177-
        turtle.select (1)-- select first slot to make things look good :)
177+
	end
178-
        peripheral.call ("front", "turnOn")    -- Turn on the module    
178+
179-
        modAvailable = modAvailable - 1
179+
180-
    end
180+
181
*********************************************************************************************
182
*                                       Operation Part                                      *
183
*********************************************************************************************
184
]]--
185
 
186
-- This is a table that contains all the states of the modules.
187
-- Indexes of that table are ID's and values are tables with following fields
188
--  1) Type - type of the module. Each Type has it's own task table
189
--  2) State - the state of the module. List of states is unique for each module type, but there are some common states: "Waiting" and "Returning"
190
tStates = {}
191
 
192
-- There is a function that searches for a free ID. Let's limit the maximun number of IDs to 1024
193
function freeID ()
194-
194+
	for i = 1, 1024 do
195
		if tStates [i] == nil then
196
			return i
197-
    for i = 1, 1024 do
197+
		end
198-
        if tStates [i] == nil then
198+
	end
199-
            return i
199+
200-
        end
200+
201-
    end
201+
202
tTasks = {}
203
 
204
-- Here is the table used to handle the requests.
205
tRequests = {
206
	-- "Master" is the request sent by new modules. We should assign a new ID to it and remember that ID in tStates table
207
	Master = function (request)
208
		local ID = freeID ()
209-
    -- "Master" is the request sent by new modules. We should assign a new ID to it and remember that ID in tStates table
209+
		response (request.ID, {NewID = ID})
210-
    Master = function (request)
210+
		tStates[ID] = {State = "Waiting", Type = request.Type}
211-
        local ID = freeID ()
211+
		moduleCount = moduleCount + 1
212-
        response (request.ID, channel, {NewID = ID})
212+
	end,
213-
        tStates[ID] = {State = "Waiting", Type = request.Type}
213+
	-- Task is the request used to reques the next thing module should do
214-
        moduleCount = moduleCount + 1
214+
	-- It uses the tTasks table. There is a function for each module type which returns a response
215-
    end,
215+
	-- Response may contain coordinate of the next place and id should contain "Task" field
216-
    -- Task is the request used to reques the next thing module should do
216+
	-- This function may do something else, change the state of module and so on.
217-
    -- It uses the tTasks table. There is a function for each module type which returns a response
217+
	-- To associate it with the module, sender ID is passed to that function
218-
    -- Response may contain coordinate of the next place and id should contain "Task" field
218+
	-- tTasks table should be filled by user of this API
219-
    -- This function may do something else, change the state of module and so on.
219+
	Task = function (request)
220-
    -- To associate it with the module, sender ID is passed to that function
220+
		response (request.ID, tTasks[request.Type](request.ID))
221-
    -- tTasks table should be filled by user of this API
221+
	end,
222-
    Task = function (request)
222+
	-- "Returned" is the request sent by module that has returned to Master and waiting there until Master collects it
223-
        response (request.ID, channel, tTasks[request.Type](request.ID))
223+
	Returned = function (request)
224-
    end,
224+
		while turtle.suck () do end -- Get all the items that module had
225-
    -- "Returned" is the request sent by module that has returned to Master and waiting there until Master collects it
225+
		turtle.dig ()               -- And get the module back
226-
    Returned = function (request)
226+
		tStates[request.ID] = nil -- delete that module from our state table
227-
        while turtle.suck () do end -- Get all the items that module had
227+
		moduleCount = moduleCount - 1 -- and decrease the counter
228-
        turtle.dig ()               -- And get the module back
228+
		modAvailable = modAvailable + 1
229-
        tStates[request.ID] = nil -- delete that module from our state table
229+
	end
230-
        moduleCount = moduleCount - 1 -- and decrease the counter
230+
231-
        modAvailable = modAvailable + 1
231+
232-
    end
232+
-- This is the variable used to determine whether the master should place modules
233
local isPlacing = false
234
 
235-
-- This is the variable used to determine whether the master should place modules 
235+
236
-- It automatically stops placing modules when there is enough modules
237
function moduleManager ()
238
	while true do
239
		if isPlacing then
240
			if moduleCount == needModules or availableModules() == 0 then
241-
    while true do
241+
				isPlacing = false
242-
        if isPlacing then
242+
			else
243-
            if moduleCount == needModules or availableModules() == 0 then
243+
				addModule ()
244-
                isPlacing = false
244+
			end
245-
            else
245+
		end
246-
                addModule ()
246+
		sleep (6)
247-
            end
247+
	end
248-
        end
248+
249-
        sleep (6)
249+
250-
    end
250+
251
-- stateFunction is the function used to determine when master should stop.
252
-- Master stops when there are to active modules and stateFunction returns false.
253
-- State function can do other things, such as reinitialization to a new module script and so on, but it shouldn't take too much time to execute
254
function operate (stateFunction)
255
	local server = function ()
256
		while stateFunction() or moduleCount > 0 do
257
			local request = listen ()
258-
    local server = function ()
258+
			tRequests[request.Request](request) -- Just execute the request handler.
259-
        while stateFunction() or moduleCount > 0 do
259+
		end
260-
            local request = listen ()
260+
	end
261-
            tRequests[request.Request](request) -- Just execute the request handler.
261+
	parallel.waitForAny (server, moduleManager)
262-
        end
262+
	rednet.close ("right")
263-
    end
263+
264-
    parallel.waitForAny (server, moduleManager)
264+
265-
    modem.closeAll ()
265+
266
*********************************************************************************************
267
*                                    Initialization Part                                    *
268
*********************************************************************************************
269
]]--
270
 
271
-- Some basic movement and refueling
272
-- Refuel assumes that Master has a bunch of fuel chests in slot 1 and slot 16 is empty
273
function refuel (amount)
274
	if turtle.getFuelLevel () > amount then
275
		return true
276
	else
277-
    if turtle.getFuelLevel () > amount then
277+
		turtle.select (1)
278-
        return true
278+
		turtle.placeUp ()
279-
    else
279+
		turtle.select (16)
280-
        turtle.select (1)
280+
			turtle.suckUp ()
281-
        turtle.placeUp ()
281+
			while turtle.refuel (1) do
282-
        turtle.select (16)
282+
				if turtle.getFuelLevel() >= amount then
283-
            turtle.suckUp ()
283+
					turtle.dropUp ()
284-
            while turtle.refuel (1) do
284+
					turtle.select (1)
285-
                if turtle.getFuelLevel() >= amount then
285+
					turtle.digUp ()
286-
                    turtle.dropUp ()
286+
					return true
287-
                    turtle.select (1)
287+
				end
288-
                    turtle.digUp ()
288+
				if turtle.getItemCount (1) == 0 then
289-
                    return true
289+
					turtle.suckUp ()
290-
                end
290+
				end
291-
                if turtle.getItemCount (1) == 0 then
291+
			end
292-
                    turtle.suckUp ()
292+
		end
293-
                end
293+
	turtle.dropUp ()
294-
            end
294+
	turtle.select (1)
295-
        end
295+
	turtle.digUp ()
296-
    turtle.dropUp ()
296+
	return false
297-
    turtle.select (1)
297+
298-
    turtle.digUp ()
298+
299-
    return false
299+
300
	forward = turtle.forward,
301
	back = turtle.back
302
}
303-
    forward = turtle.forward,
303+
304-
    back = turtle.back
304+
	refuel (1)
305
	while not tMoves[direction]() do
306
		print "Movement obstructed. Waiting"
307-
    refuel (1)
307+
		sleep (1)
308-
    while not tMoves[direction]() do
308+
	end
309-
        print "Movement obstructed. Waiting"
309+
310-
        sleep (1)
310+
311-
    end
311+
312
function setType (Type, taskFunction)
313
	tTasks[Type] = taskFunction
314
end
315
 
316-
    tTasks[Type] = taskFunction
316+
317
-- Filename is the name of module's script. It will be copied on the disk drive
318
function init (filename, ID, moduleCount)
319
	-- Set the ID of the Master
320
	MasterID = ID
321-
function init (filename, ID, mainChannel, moduleCount)
321+
322-
    -- Set the ID of the Master
322+
	-- Next, we need to know the position of the master.
323-
    MasterID = ID
323+
	-- If gps is not found, use relative coordinates
324-
    -- Set the main channel and listen on said channel
324+
	local gpsPresent = true
325-
    channel = mainChannel
325+
	local x, y, z = gps.locate(5)
326-
    modem.open (channel)
326+
	if x == nil then
327-
    
327+
		x, y, z = 0, 0, 0
328-
    -- Next, we need to know the position of the master.
328+
		gpsPresent = false
329-
    -- If gps is not found, use relative coordinates
329+
	end
330-
    modem.open(gps.CHANNEL_GPS)
330+
331-
    local gpsPresent = true
331+
	-- Now we need to move forward to copy files on disk and determine our f
332-
    local x, y, z = gps.locate(5)
332+
	forceMove ("forward")
333-
    if x == nil then
333+
	local newX, newZ = 1, 0 -- if there is no gps, assume that master is facing positive x
334-
        x, y, z = 0, 0, 0
334+
	if gpsPresent then
335-
        gpsPresent = false
335+
		newX, __, newZ = gps.locate (5)
336-
    end
336+
	end
337
	-- Determine f by the difference of coordinates.
338-
    -- Now we need to move forward to copy files on disk and determine our f
338+
	local xDiff = newX - x
339-
    forceMove ("forward")
339+
	local zDiff = newZ - z
340-
    local newX, newZ = 1, 0 -- if there is no gps, assume that master is facing positive x
340+
	if xDiff ~= 0 then
341-
    if gpsPresent then
341+
		if xDiff > 0 then
342-
        newX, __, newZ = gps.locate (5)
342+
			f = 0     -- Positive x
343-
    end
343+
		else
344-
    modem.close(gps.CHANNEL_GPS)
344+
			f = 2     -- Negative x
345-
    -- Determine f by the difference of coordinates.
345+
		end
346-
    local xDiff = newX - x
346+
	else
347-
    local zDiff = newZ - z
347+
		if zDiff > 0 then
348-
    if xDiff ~= 0 then
348+
			f = 1     -- Positive z
349-
        if xDiff > 0 then
349+
		else
350-
            f = 0     -- Positive x
350+
			f = 3     -- Negative z
351-
        else
351+
		end
352-
            f = 2     -- Negative x
352+
	end
353-
        end
353+
	-- And set the position and modPosition variables.
354-
    else
354+
	Position = {x = x, y = y, z = z, f = f}
355-
        if zDiff > 0 then
355+
	modPosition = {x = newX, y = y, z = newZ, f = f}
356-
            f = 1     -- Positive z
356+
357-
        else
357+
	-- Copy all the required files on the disk
358-
            f = 3     -- Negative z
358+
	if fs.exists ("/disk/module") then
359-
        end
359+
		fs.delete ("/disk/module")
360-
    end
360+
	end
361-
    -- And set the position and modPosition variables.
361+
	fs.copy ("module", "/disk/module")
362-
    Position = {x = x, y = y, z = z, f = f}
362+
	if fs.exists ("/disk/"..filename) then
363-
    modPosition = {x = newX, y = y, z = newZ, f = f}
363+
		fs.delete ("/disk/"..filename)
364
	end
365-
    -- Copy all the required files on the disk
365+
	fs.copy (filename, "/disk/"..filename)
366-
    if fs.exists ("/disk/module") then
366+
	-- Make a startup file for modules
367-
        fs.delete ("/disk/module")
367+
	local file = fs.open ("/disk/startup", "w")
368-
    end
368+
	file.writeLine ("shell.run(\"copy\", \"/disk/module\", \"/module\")")
369-
    fs.copy ("module", "/disk/module")
369+
	file.writeLine ("shell.run(\"copy\", \"/disk/"..filename.."\", \"/startup\")")
370-
    if fs.exists ("/disk/"..filename) then
370+
	file.writeLine ("shell.run(\"startup\")")
371-
        fs.delete ("/disk/"..filename)
371+
	file.close()
372-
    end
372+
373-
    fs.copy (filename, "/disk/"..filename)
373+
	-- Now, make a file with the data modules need
374-
    -- Make a startup file for modules
374+
	file = fs.open ("/disk/initdata", "w")
375-
    local file = fs.open ("/disk/startup", "w")
375+
	-- Communication data: master ID and communication channel
376-
    file.writeLine ("shell.run(\"copy\", \"/disk/module\", \"/module\")")
376+
	file.writeLine (textutils.serialize ({MasterID = MasterID, channel = channel}) )
377-
    file.writeLine ("shell.run(\"copy\", \"/disk/"..filename.."\", \"/startup\")")
377+
	-- Location data:
378-
    file.writeLine ("shell.run(\"startup\")")
378+
	file.writeLine (textutils.serialize (modPosition))
379-
    file.close()
379+
	-- Navigation data:
380-
    
380+
	file.writeLine (textutils.serialize (naviZones))
381-
    -- Now, make a file with the data modules need
381+
	file.close()
382-
    file = fs.open ("/disk/initdata", "w")
382+
383-
    -- Communication data: master ID and communication channel
383+
	-- And go back to initial location
384-
    file.writeLine (textutils.serialize ({MasterID = MasterID, channel = channel}) )
384+
	forceMove ("back")
385-
    -- Location data:
385+
386-
    file.writeLine (textutils.serialize (modPosition))
386+
	-- Set the amount of modules needed. I use "+" because one can run init again to add a different type of module to the operation
387-
    -- Navigation data:
387+
	needModules = needModules + moduleCount
388-
    file.writeLine (textutils.serialize (naviZones))
388+
	-- And start placing them
389-
    file.close()
389+
	isPlacing = true
390-
    
390+
391-
    -- And go back to initial location
391+
392-
    forceMove ("back")
392+
393
--[[
394-
    -- Set the amount of modules needed. I use "+" because one can run init again to add a different type of module to the operation
394+
395-
    needModules = needModules + moduleCount
395+
396-
    -- And start placing them
396+
397-
    isPlacing = true
397+
398
 
399-
399+
400-
400+
401
	-- return position is two block away of Master. So, let's calculate it.
402
	local tShifts = {
403
		[0] = { 1,  0},
404
		[1] = { 0,  1},
405
		[2] = {-1,  0},
406
		[3] = { 0, -1},
407
	}
408
	local xShift, zShift = unpack (tShifts[modPosition.f])
409-
    -- return position is two block away of Master. So, let's calculate it.
409+
	returnX = modPosition.x + xShift
410-
    local tShifts = {
410+
	returnZ = modPosition.z + zShift
411-
        [0] = { 1,  0},
411+
	return {   Task = "Return",
412-
        [1] = { 0,  1},
412+
		x = returnX,
413-
        [2] = {-1,  0},
413+
		y = modPosition.y,
414-
        [3] = { 0, -1},
414+
		z = returnZ,
415-
    }
415+
		f = (modPosition.f+2)%4, -- basically, reverse direction
416-
    local xShift, zShift = unpack (tShifts[modPosition.f])
416+
	}
417-
    returnX = modPosition.x + xShift
417+
418-
    returnZ = modPosition.z + zShift
418+
419-
    return {   Task = "Return",
419+
420-
        x = returnX,
420+
421-
        y = modPosition.y,
421+
422-
        z = returnZ,
422+
	local newTask = {Task = taskName}
423-
        f = (modPosition.f+2)%4, -- basically, reverse direction
423+
	for key, value in pairs (coordinates) do  
424-
    }
424+
		newTask[key] = value
425
	end
426-
426+
	if additionalData ~= nil then
427
		for key, value in pairs (additionalData) do  
428
			newTask[key] = value
429
		end
430-
    local newTask = {Task = taskName}
430+
	end
431-
    for key, value in pairs (coordinates) do  
431+
	return newTask
432-
        newTask[key] = value
432+
433-
    end
433+
434-
    if additionalData ~= nil then
434+
435-
        for key, value in pairs (additionalData) do  
435+
	return tStates[ID].State
436-
            newTask[key] = value
436+
437-
        end
437+
438-
    end
438+
439-
    return newTask
439+
	tStates[ID].State = newState
440
end
441-
441+
442
-- reinit function is just a simplified init, that doesn't update channel, MasterID and Master's position. Use it to change the modules script
443-
    return tStates[ID].State
443+
444
	forceMove ("forward")
445-
445+
	-- Copy all the required files on the disk
446
	if fs.exists ("/disk/module") then
447-
    tStates[ID].State = newState
447+
		fs.delete ("/disk/module")
448
	end
449
	fs.copy ("module", "/disk/module")
450
	if fs.exists ("/disk/"..filename) then
451
		fs.delete ("/disk/"..filename)
452-
    forceMove ("forward")
452+
	end
453-
    -- Copy all the required files on the disk
453+
	fs.copy (filename, "/disk/"..filename)
454-
    if fs.exists ("/disk/module") then
454+
	-- Make a startup file for modules
455-
        fs.delete ("/disk/module")
455+
	local file = fs.open ("/disk/startup", "w")
456-
    end
456+
	file.writeLine ("shell.run(\"copy\", \"/disk/module\", \"/module\")")
457-
    fs.copy ("module", "/disk/module")
457+
	file.writeLine ("shell.run(\"copy\", \"/disk/"..filename.."\", \"/startup\")")
458-
    if fs.exists ("/disk/"..filename) then
458+
	file.writeLine ("shell.run(\"startup\")")
459-
        fs.delete ("/disk/"..filename)
459+
	file.close()
460-
    end
460+
461-
    fs.copy (filename, "/disk/"..filename)
461+
	-- Now, make a file with the data modules need
462-
    -- Make a startup file for modules
462+
	file = fs.open ("/disk/initdata", "w")
463-
    local file = fs.open ("/disk/startup", "w")
463+
	-- Communication data: master ID
464-
    file.writeLine ("shell.run(\"copy\", \"/disk/module\", \"/module\")")
464+
	file.writeLine (textutils.serialize ({MasterID = MasterID}) )
465-
    file.writeLine ("shell.run(\"copy\", \"/disk/"..filename.."\", \"/startup\")")
465+
	-- Location data:
466-
    file.writeLine ("shell.run(\"startup\")")
466+
	file.writeLine (textutils.serialize (modPosition))
467-
    file.close()
467+
	-- Navigation data:
468-
    
468+
	file.writeLine (textutils.serialize (naviZones))
469-
    -- Now, make a file with the data modules need
469+
	file.close()
470-
    file = fs.open ("/disk/initdata", "w")
470+
471-
    -- Communication data: master ID and communication channel
471+
	-- And go back to initial location
472-
    file.writeLine (textutils.serialize ({MasterID = MasterID, channel = channel}) )
472+
	forceMove ("back")
473-
    -- Location data:
473+
474-
    file.writeLine (textutils.serialize (modPosition))
474+
	-- Set the amount of modules needed. I use "+" because one can run init again to add a different type of module to the operation
475-
    -- Navigation data:
475+
	needModules = needModules + moduleCount
476-
    file.writeLine (textutils.serialize (naviZones))
476+
	-- And start placing them
477-
    file.close()
477+
	isPlacing = true
478-
    
478+