View difference between Paste ID: wSXdt8uu and qfKhdZGw
SHOW: | | - or go back to the newest paste.
1
local localChannel=666
2
local rest={x=156,y=7,z=263}
3
local drop={x=160,y=6,z=264}
4
5
local chests={
6
	{chest=peripheral.wrap("chest_0"),pos={x=1087,y=65,z=381}},
7
	{chest=peripheral.wrap("chest_1"),pos={x=1087,y=65,z=384}},
8
	{chest=peripheral.wrap("chest_2"),pos={x=1087,y=65,z=387}},
9
	{chest=peripheral.wrap("chest_3"),pos={x=1081,y=65,z=381}},
10
	{chest=peripheral.wrap("chest_4"),pos={x=1081,y=65,z=384}},
11
	{chest=peripheral.wrap("chest_5"),pos={x=1081,y=65,z=387}},
12
}
13
14
local modem=peripheral.wrap("bottom")
15
local wireless=peripheral.wrap("top")
16
17
18
if fs.exists("event")==false then shell.run("pastebin get UKPy4iiE event") end
19
os.loadAPI("event")
20
21
if fs.exists("utils")==false then shell.run("pastebin get dyvydHtK utils") end
22
os.loadAPI("utils")
23
24
if fs.exists("data")==false then shell.run("pastebin get LnvzL7ur data") end
25
if os.loadAPI("data")==false then error("Failed to load data API") end
26
27
local taskQue = {}
28
29
local turtles = {}
30
31
local craftQue = {}
32
33
34
local modems={}
35
modem.open(localChannel)
36
modems["back"]=modem
37
modems["wired"]=modem
38
wireless.open(localChannel)
39
modems["bottom"]=wireless
40
modems["wireless"]=wireless
41
42
local pingLimit = 10
43
local items={}
44
local turtleTimer = os.startTimer(10)
45
46
function indexItems()
47
	items={}
48
	for chestID,chest in pairs(chests) do
49
		for i,stack in pairs(chest.chest.getAllStacks()) do
50
			local data=stack.all()
51
			if items[string.lower(data.display_name)]==nil then
52
				items[string.lower(data.display_name)]={[chestID]=data.qty}
53
			else
54
				if items[string.lower(data.display_name)][chestID]==nil then
55
					items[string.lower(data.display_name)][chestID]=data.qty
56
				else
57
					items[string.lower(data.display_name)][chestID]=items[string.lower(data.display_name)][chestID]+data.qty
58
				end				
59
			end
60
		end
61
	end
62
end
63
indexItems()
64
65
function getItemCount(name)
66
	local item=items[string.lower(name)]
67
	if item==nil then return 0 end
68
	local count=0
69
	for chestID,itemCount in pairs(item) do
70
		count=count+itemCount
71
	end
72
	return count
73
end
74
75
function getItemPosition(name,count)
76
	local item=items[string.lower(name)]
77
	if item==nil then return end
78
	local positions={}
79
	if count==0 then
80
		count=1
81
	end
82
	local remainder=count
83
	for chestID,itemCount in pairs(item) do
84
		remainder=remainder-itemCount
85
		positions[#positions+1]={pos=chests[chestID].pos,count=itemCount}
86
		if remainder<=0 then
87
			return positions
88
		end
89
	end
90
	return positions
91
end
92
93
function getIdleTurtle()
94
	for id,turtle in pairs(turtles) do
95
		if turtle.status=="idle" then
96
			return turtle
97
		end
98
	end
99
	return nil
100
end
101
102
function statusUpdate(channel,turtle,previous,new)
103
	--print("Que:\n"..textutils.serialise(taskQue))
104
	event.handleCCEvents(0.05)
105
	if new=="idle" then
106
		turtle.task=nil
107
		if #taskQue==0 then 
108
			if #craftQue == 0 then return end
109
			indexItems()
110
			for i,queEntry in ipairs(craftQue) do
111
				if craftItem(queEntry.item,queEntry.count,true) == true then
112
					craftItem(queEntry.item,queEntry.count,nil,queEntry.final)
113
					craftQue[i]=nil
114
					for j=i+1,#craftQue do
115
						craftQue[j-i]=craftQue[j]
116
					end
117
					craftQue[#craftQue]=nil
118
					return
119
				end
120
			end
121
			return
122
		end
123
		modems["wireless"].transmit(channel,localChannel,taskQue[1])
124
		turtle.task=taskQue[1]
125
		turtle.status="working"
126
		for id,data in ipairs(taskQue) do
127
			taskQue[id-1]=data
128
		end
129
		taskQue[0]=nil
130
		taskQue[#taskQue]=nil
131
	end
132
end
133
event.addHandler("onTurtleStatusChange",statusUpdate)
134
135
function turtleTimed(turtle,channel)
136
	local command = turtle.task
137
	if command == nil then return end
138
	local turtle=getIdleTurtle()
139
	if turtle==nil then
140
		taskQue[#taskQue+1]=command
141
	else
142
		modems["wireless"].transmit(turtle.channel,localChannel,command)
143
		turtle.task=command
144
		turtle.status="working"
145
	end
146
end
147
event.addHandler("onTurtleTimeout",turtleTimed)
148
149
function createRecipe(targetItem,recipeString)
150
	data.set(targetItem,recipeString)
151
end
152
153
function checkTurtleConnectionTimer(timer)
154
	if timer ~= turtleTimer then return end
155
	for channel,turtle in pairs(turtles) do
156
		if turtle.lastMessage < os.clock() - 20 then
157
			turtle.missed = turtle.missed + 1
158
			if turtle.missed > pingLimit then
159
				print("Turtle " .. channel .. " has timed out")
160
				event.trigger("onTurtleTimeout",turtle,channel)
161
				turtles[channel] = nil
162
				checkTurtleConnectionTimer(timer)
163
				break
164
			end
165
		else
166
			turtle.missed = 0
167
		end
168
	end	
169
	--[[
170
	for channel,turtle in pairs(turtles) do
171
		if turtle.timer == timer then
172
			ping(channel)
173
			if turtle.pingTimer == nil then
174
				turtle.missed = 0
175
				turtle.pingTimer = os.startTimer(10)
176
			end
177
		elseif turtle.pingTimer == timer  and turtle.missed == pingLimit then
178
			--print("Turtle " .. channel .. " has timed out")
179
			event.trigger("onTurtleTimeout",turtle,channel)
180
			turtles[channel] = nil
181
			return
182
		elseif turtle.pingTimer == timer and turtle.missed then
183
			turtle.pingTimer = os.startTimer(10)
184
			turtle.missed = turtle.missed + 1
185
		end
186
	end
187
	]]
188
	turtleTimer = os.startTimer(10)
189
end
190
event.addHandler("timer",checkTurtleConnectionTimer)
191
192
function craftItem(itemName,count,check,final)
193
	indexItems()
194
	local hasSubs = false
195
	local recipe = data.get(itemName,"db/recipes")
196
	if recipe==nil or recipe=="nil" then return end		
197
	local command = "craft|"..count.."|"
198
	if final == nil or final == false then
199
		command = "innerCraft|"..count.."|"
200
	end
201
	print(itemName .." : " .. count)
202
	for i=1,9 do
203
		local item = utils.split(recipe,";",i)
204
		local positions = getItemPosition(item,count)
205
		local itemFound = false
206
		if item~=nil and positions ~=nil then
207
			local remainder=count
208
			for chestID,data in pairs(positions) do
209
				local count=data.count
210
				if count>=remainder then
211
					command = command .. item ..";".. data.pos.x ..",".. data.pos.y ..",".. data.pos.z .. ";"..i.."|"
212
					itemFound = true
213
					break
214
				end
215
			end
216
			if itemFound == false then
217
				if data.get(item,"db/recipes")~=nil then
218
					if check == nil then
219
						craftItem(item,count,nil,false)
220
					end
221
					hasSubs = true
222
				end
223
			end
224
		elseif positions == nil and item ~= nil and item ~= ""  then
225
			print("item not found in system "..tostring(item).." Recipe: "..tostring(not ( data.get(item,"db/recipes") == nil ) ) )
226
			if data.get(item,"db/recipes")~=nil then
227
				if check == nil then
228
					craftItem(item,count,nil,false)
229
				elseif check ~= false then
230
					return false
231
				end
232
				hasSubs = true
233
			else
234
				print("Not enough items")
235
			end
236
		end	
237
	end
238
	
239
	if hasSubs == true then
240
		craftQue[#craftQue+1] = { item = itemName, count = count, final = final }
241
	end
242
	
243
	if check == true and hasSubs == false then
244
		return true
245
	elseif check == true then
246
		return false
247
	end
248
	local turtle = getIdleTurtle()
249
	if turtle==nil then
250
		craftQue[#craftQue+1] = { item = itemName, count = count, final = final }
251
		--taskQue[#taskQue+1]=command
252
	else
253
		modems["wireless"].transmit(turtle.channel,localChannel,command)
254
		turtle.task=command
255
		turtle.status="working"
256
	end
257
	print(textutils.serialise(craftQue))
258
end
259
260
function ping(channel)
261
	modems.wireless.transmit(channel,localChannel,"ping")
262
end
263
264
local messageHandles={
265
	["ping"]=function(replyChannel,message)
266
		if turtles[replyChannel]==nil then return end
267
		event.trigger("onPing",replyChannel)
268
		return "pong"
269
	end,
270
	
271
	["pong"]=function(replyChannel,message)
272
		if turtles[replyChannel]==nil then return end
273
		event.trigger("onPong",replyChannel)
274
	end,
275
	
276
	["getItemCount"]=function(replyChannel,message)
277
		indexItems()
278
		local itemName=utils.split(message,"|",2)
279
		return "returnItemCount|"..getItemCount(itemName)
280
	end,
281
	
282
	["requestItemList"]=function(replyChannel,message)
283
		indexItems()
284
		local itemString=""
285
		for itemname,chests in pairs(items) do
286
			itemString=itemString..itemname..","..getItemCount(itemname)..";"
287
		end
288
		return "returnItemList|"..itemString
289
	end,
290
	
291
	["requestTurtles"]=function(replyChannel,message)
292
		local turtleString=""
293
		for channel,turtle in pairs(turtles) do
294
			turtleString=turtleString..channel..","..turtle.status..","..tostring(turtle.task)..";"
295
		end
296
		return "returnTurtles|"..turtleString
297
	end,
298
	
299
	["requestQue"]=function(replyChannel,message)
300
		local queString=""
301
		for _,queCommand in pairs(taskQue) do
302
			queString=queString..string.gsub(queCommand,"|",";").."|"
303
		end
304
		return "returnQue|"..queString
305
	end,
306
	
307
	["requestItem"]=function(replyChannel,message)
308
		indexItems()
309
		local itemName=utils.split(message,"|",2)
310
		local count=tonumber(utils.split(message,"|",3))
311
		--print("Item request: "..itemName.."x"..count)
312
		local positions=getItemPosition(itemName,count)
313
		local remainder=count
314
		if positions==nil then return end
315
		for chestID,data in pairs(positions) do
316
			----print(chestID)
317
			local count=data.count
318
			if count>remainder then
319
				count=remainder
320
			end
321
			remainder=remainder-count
322
			local command="get|"..itemName.."|"..count.."|"..data.pos.x..","..data.pos.y..","..data.pos.z
323
			--print("Command: "..command)
324
			local turtle=getIdleTurtle()
325
			if turtle==nil then
326
				taskQue[#taskQue+1]=command
327
			else
328
				modems["wireless"].transmit(turtle.channel,localChannel,command)
329
				turtle.task=command
330
				turtle.status="working"
331
			end
332
			if remainder<=0 then
333
				return
334
			end
335
		end
336
	end,
337
	
338
	["addRecipe"]=function(replyChannel,message)
339
		local item = utils.split(message,"|",2)
340
		local recipe = utils.split(message,"|",3)
341
		data.set(item,recipe,"db/recipes")
342
		--print("Adding recipe: "..recipe)
343
	end,
344
	
345
	["requestRecipes"]=function(replyChannel,message)
346
		local returnString = "returnRecipes|"
347
		for id,_ in pairs(data.getAll("db/recipes")) do
348
			returnString = returnString .. id .. ";"
349
		end
350
		return returnString
351
	end,
352
	
353
	["requestCraft"]=function(replyChannel,message)
354
		local itemName=utils.split(message,"|",2)
355
		local count=tonumber(utils.split(message,"|",3))
356
		craftItem(itemName,count,nil,true)
357
	end,
358
	
359
	["getItemPosition"]=function(replyChannel,message)
360
		indexItems()
361
		local itemName=utils.split(message,"|",2)
362
		local posString=""
363
		local positions=getItemPosition(itemName)
364
		if positions==nil then return end
365
		for _,pos in pairs(positions) do
366
			posString=posString..x..","..y..","..z.."|"
367
		end
368
		return posString
369
	end,
370
	
371
	["sendToTurtles"]=function(replyChannel,message)
372
		local turtleChannel=utils.split(message,"|",2)
373
		local message=utils.split(message,"|",3)
374
		local turtle=turtles[replyChannel]
375
		turtle.task=message
376
		turtle.status="working"
377
		
378
	end,
379
	
380
	["indexItems"]=function(replyChannel,message)
381
		indexItems()
382
		return "confirmed"
383
	end,
384
	
385
	["assign"]=function(replyChannel)
386
		if turtles[replyChannel]==nil then
387
			turtles[replyChannel]={
388
				channel=replyChannel,
389
				status="idle",
390
				lastMessage = os.clock()
391
			}
392
			event.trigger("onTurtleAssign",replyChannel,turtles[replyChannel],"confirmed")
393
			event.trigger("onTurtleStatusChange",replyChannel,turtles[replyChannel],false,"idle")
394
			return "confirmed"
395
		else
396
			event.trigger("onTurtleAssign",replyChannel,turtles[replyChannel],"denied")
397
			return "denied"
398
		end
399
	end,
400
	
401
	["status"]=function(replyChannel,message)
402
		if turtles[replyChannel]==nil then
403
			return "denied"
404
		end
405
		local previous=turtles[replyChannel].status
406
		local status=utils.split(message,"|",2)
407
		turtles[replyChannel].status=status
408
		event.trigger("onTurtleStatusChange",replyChannel,turtles[replyChannel],previous,status)
409
	end,
410
	
411
	["requestDropoff"]=function(replyChannel,message)
412
		return "returnDropoff|"..drop.x..","..drop.y..","..drop.z
413
	end,
414
	
415
	["requestRestPos"]=function(replyChannel,message)
416
		return "returnHomePos|"..rest.x..","..rest.y..","..rest.z
417
	end,
418
}
419
420
421
function handleMessages(side,channel,replyChannel,message)
422
	--print(replyChannel.." : "..message)
423
	if turtles[replyChannel] ~= nil then
424
		turtles[replyChannel].lastMessage = os.clock()
425
	end
426
	local messageType=utils.split(message,"|",1)
427
	if messageHandles[messageType]==nil then return end
428
	local returnMessage=messageHandles[messageType](replyChannel,message)
429
	event.handleCCEvents(0.10)
430
	if returnMessage==nil then return end
431
	--print(replyChannel .. " : " .. returnMessage)
432
	modems[side].transmit(replyChannel,localChannel,returnMessage)
433
end
434
event.addHandler("modem_message",handleMessages)
435
436
while true do
437
	event.handleCCEvents()
438
end
439
440
print("ENDED GRACEFULLY")