SHOW:
|
|
- or go back to the newest paste.
1 | - | -- Made By Orwell |
1 | + | --made by me |
2 | - | -- version 0.2 - 3 june 2012 |
2 | + | --setup() made by orwell |
3 | - | --local type |
3 | + | |
4 | local tArgs = { ... } | |
5 | if #tArgs < 1 then | |
6 | error("Usage: blueprint <gunzipped schematic file>") | |
7 | end | |
8 | ||
9 | if not fs.exists("textutilsFIX") then | |
10 | shell.run("pastebin get 3wguFBXn textutilsFIX") | |
11 | end | |
12 | ||
13 | os.loadAPI("textutilsFIX") | |
14 | ||
15 | local filename = tArgs[1] | |
16 | ||
17 | if not fs.exists(filename) then | |
18 | error("File does not exist.") | |
19 | end | |
20 | - | block_id[5] = "Wooden Plank" |
20 | + | |
21 | function save(name,table) | |
22 | local h = fs.open(name,"w") | |
23 | table = textutils.serialize(table) | |
24 | h.write(table) | |
25 | h.close() | |
26 | end | |
27 | ||
28 | function saveIns(name,table) | |
29 | local h = fs.open(name,"w") | |
30 | h.writeLine(name.." = {}") | |
31 | for i,coord in pairs(table) do | |
32 | - | block_id[17] = "Log" |
32 | + | h.writeLine(name.."["..i.."] = {"..table.concat(coord,",").."}") |
33 | h.flush() | |
34 | end | |
35 | h.close() | |
36 | end | |
37 | ||
38 | function saveBlueprint(reference,slots,instructions,uniqueblocks) | |
39 | local fname = filename:gsub("%.(.*)","")..".blueprint" | |
40 | local h = fs.open(fname,"w") | |
41 | h.writeLine("reference ="..textutils.serialize(reference)..";") | |
42 | h.writeLine("slots = "..textutils.serialize(slots)..";") | |
43 | h.writeLine("uniqueblocks = "..textutils.serialize(uniqueblocks)..";") | |
44 | h.writeLine("instructions = "..textutilsFIX.serialize(instructions)..";") | |
45 | h.close() | |
46 | return fname | |
47 | end | |
48 | ||
49 | local block_id = {} | |
50 | ||
51 | block_id[0] = "Air" | |
52 | block_id[1] = "Stone" | |
53 | block_id[2] = "Grass" | |
54 | block_id[3] = "Dirt" | |
55 | block_id[4] = "Cobblestone" | |
56 | block_id[5] = "Wood Planks" | |
57 | block_id[6] = "Sapling" | |
58 | block_id[7] = "Bedrock" | |
59 | block_id[8] = "Water" | |
60 | block_id[9] = "Stationary water" | |
61 | block_id[10] = "Lava" | |
62 | block_id[11] = "Stationary lava" | |
63 | block_id[12] = "Sand" | |
64 | block_id[13] = "Gravel" | |
65 | block_id[14] = "Gold Ore" | |
66 | block_id[15] = "Iron (Ore)" | |
67 | block_id[16] = "Coal Ore" | |
68 | block_id[17] = "Wood" | |
69 | block_id[18] = "Leaves" | |
70 | block_id[19] = "Sponge" | |
71 | block_id[20] = "Glass" | |
72 | block_id[21] = "Lapis Lazuli (Ore)" | |
73 | block_id[22] = "Lapis Lazuli (Block)" | |
74 | block_id[23] = "Dispenser" | |
75 | block_id[24] = "Sandstone" | |
76 | block_id[25] = "Note Block Tile entity" | |
77 | block_id[26] = "Bed" | |
78 | block_id[27] = "Powered Rail " | |
79 | block_id[28] = "Detector Rail " | |
80 | block_id[29] = "Sticky Piston" | |
81 | block_id[30] = "Cobweb" | |
82 | block_id[31] = "Tall Grass" | |
83 | block_id[32] = "Dead Bush" | |
84 | block_id[33] = "Piston" | |
85 | block_id[34] = "Piston Extension" | |
86 | block_id[35] = "Wool" | |
87 | block_id[36] = "Block moved by Piston" | |
88 | block_id[37] = "Dandelionandelion" | |
89 | block_id[38] = "Rose" | |
90 | block_id[39] = "Brown Mushroom" | |
91 | block_id[40] = "Red Mushroom" | |
92 | block_id[41] = "Block of Gold" | |
93 | block_id[42] = "Block of Iron" | |
94 | block_id[43] = "Double Slabs" | |
95 | block_id[44] = "Slabs" | |
96 | block_id[45] = "Brick Block" | |
97 | block_id[46] = "TNT" | |
98 | block_id[47] = "Bookshelf" | |
99 | block_id[48] = "Moss Stone" | |
100 | block_id[49] = "Obsidian" | |
101 | block_id[50] = "Torch" | |
102 | block_id[51] = "Fire" | |
103 | block_id[52] = "Monster Spawner" | |
104 | block_id[53] = "Wooden Stairs" | |
105 | block_id[54] = "Chest" | |
106 | block_id[55] = "Redstone (Wire)" | |
107 | block_id[56] = "Diamond (Ore)" | |
108 | block_id[57] = "Block of Diamond" | |
109 | block_id[58] = "Crafting Table" | |
110 | - | block_id[95] = "Locked Chest" |
110 | + | |
111 | block_id[60] = "Farland" | |
112 | block_id[61] = "Furnace" | |
113 | - | block_id[98] = "Stone Brick" |
113 | + | |
114 | block_id[63] = "Sign Post" | |
115 | block_id[64] = "Wooden Door" | |
116 | block_id[65] = "Ladders" | |
117 | block_id[66] = "Rails" | |
118 | block_id[67] = "Cobblestone Stairs" | |
119 | block_id[68] = "Wall Sign" | |
120 | block_id[69] = "Lever" | |
121 | block_id[70] = "Stone Pressure Plate" | |
122 | block_id[71] = "Iron Door" | |
123 | block_id[72] = "Wooden Pressure Plates" | |
124 | block_id[73] = "Redstone Ore" | |
125 | block_id[74] = "Glowing Redstone Ore" | |
126 | block_id[75] = "Redstone Torch" | |
127 | block_id[76] = "Redstone Torch" | |
128 | block_id[77] = "Stone Button " | |
129 | block_id[78] = "Snow" | |
130 | block_id[79] = "Ice" | |
131 | block_id[80] = "Snow Block" | |
132 | block_id[81] = "Cactus" | |
133 | block_id[82] = "Clay (Block)" | |
134 | block_id[83] = "Sugar Cane" | |
135 | block_id[84] = "Jukebox" | |
136 | block_id[85] = "Fence" | |
137 | block_id[86] = "Pumpkin" | |
138 | block_id[87] = "Netherrack" | |
139 | block_id[88] = "Soul Sand" | |
140 | block_id[89] = "Glowstone" | |
141 | block_id[90] = "Portal" | |
142 | block_id[91] = "Jack-O-Lantern" | |
143 | block_id[92] = "Cake Block" | |
144 | block_id[93] = "Redstone Repeater" | |
145 | block_id[94] = "Redstone Repeater" | |
146 | block_id[95] = "Stained Glass" | |
147 | block_id[96] = "Trapdoors" | |
148 | block_id[97] = "Hidden Silverfish" | |
149 | block_id[98] = "Stone Bricks" | |
150 | block_id[99] = "Huge brown and red mushroom" | |
151 | block_id[100] = "Huge brown and red mushroom" | |
152 | block_id[101] = "Iron Bars" | |
153 | block_id[102] = "Glass Pane" | |
154 | block_id[103] = "Melon" | |
155 | block_id[104] = "Pumpkin Stem" | |
156 | block_id[105] = "Melon Stem" | |
157 | block_id[106] = "Vines" | |
158 | block_id[107] = "Fence Gate" | |
159 | block_id[108] = "Brick Stairs" | |
160 | block_id[109] = "Stone Brick Stairs" | |
161 | block_id[110] = "Mycelium" | |
162 | block_id[111] = "Lily Pad" | |
163 | block_id[112] = "Nether Brick" | |
164 | - | --[[ |
164 | + | |
165 | block_id[114] = "Nether Brick Stairs" | |
166 | - | if #tArgs ~= 1 then |
166 | + | |
167 | - | print("Usage: build <gunzipped schematic file>") |
167 | + | |
168 | - | return |
168 | + | |
169 | block_id[118] = "Cauldron" | |
170 | block_id[119] = "End Portal" | |
171 | block_id[120] = "End Portal Frame" | |
172 | block_id[121] = "End Stone " | |
173 | block_id[126] = "Wood Slabs" | |
174 | - | print("File does not exist.") |
174 | + | block_id[128] = "Sandstone Stairs" |
175 | - | return |
175 | + | block_id[134] = "Spruce Wood Stairs" |
176 | block_id[135] = "Birch Wood Stairs" | |
177 | - | ]]-- |
177 | + | block_id[136] = "Jungle Wood Stairs" |
178 | block_id[156] = "Quartz Stairs" | |
179 | block_id[159] = "Stained Clay" | |
180 | block_id[160] = "Stained Glass Pane" | |
181 | block_id[163] = "Acacia Wood Stairs" | |
182 | block_id[164] = "Dark Oak Wood Stairs" | |
183 | block_id[171] = "Carpet" | |
184 | block_id[172] = "Hardened Clay" | |
185 | block_id[256] = "Iron Ingotron Shovel" | |
186 | block_id[257] = "Iron Pickaxe" | |
187 | block_id[258] = "Iron Axe" | |
188 | block_id[259] = "Flint and Steel" | |
189 | - | return "UNKNOWN" |
189 | + | |
190 | block_id[261] = "Bow" | |
191 | block_id[262] = "Arrow" | |
192 | - | if(id == 35) then |
192 | + | |
193 | - | str = woolColors[blockData] .. " " .. block_id[id] |
193 | + | |
194 | local woolColors = {} | |
195 | woolColors[0] = "White" | |
196 | woolColors[1] = "Orange" | |
197 | woolColors[2] = "Magenta" | |
198 | woolColors[3] = "Light Blue" | |
199 | woolColors[4] = "Yellow" | |
200 | woolColors[5] = "Lime" | |
201 | woolColors[6] = "Pink" | |
202 | woolColors[7] = "Gray" | |
203 | woolColors[8] = "Light Gray" | |
204 | woolColors[9] = "Cyan" | |
205 | woolColors[10] = "Purple" | |
206 | woolColors[11] = "Blue" | |
207 | woolColors[12] = "Brown" | |
208 | woolColors[13] = "Green" | |
209 | woolColors[14] = "Red" | |
210 | woolColors[15] = "Black" | |
211 | ||
212 | local woodTypes = {} | |
213 | woodTypes[0] = "Oak" | |
214 | woodTypes[1] = "Spruce" | |
215 | woodTypes[2] = "Birch" | |
216 | woodTypes[3] = "Jungle" | |
217 | woodTypes[4] = "Acacia" | |
218 | woodTypes[5] = "Dark Oak" | |
219 | ||
220 | local stairOrientation = {} | |
221 | stairOrientation[0] = "East" | |
222 | stairOrientation[1] = "West" | |
223 | stairOrientation[2] = "South" | |
224 | stairOrientation[3] = "North" | |
225 | stairOrientation[4] = "East Inverted" | |
226 | stairOrientation[5] = "West Inverted" | |
227 | stairOrientation[6] = "South Inverted" | |
228 | stairOrientation[7] = "North Inverted" | |
229 | ||
230 | local nonWoodenSlabs = { | |
231 | [0] = "Stone", | |
232 | [1] = "Sandstone", | |
233 | [2] = "Wooden", | |
234 | [3] = "Cobblestone", | |
235 | [4] = "Bricks", | |
236 | [5] = "Stone Bricks", | |
237 | [6] = "Nether Brick", | |
238 | [7] = "Quartz", | |
239 | [8] = "Inverted Stone", | |
240 | [9] = "Inverted Sandstone", | |
241 | [10] = "Inverted Wooden", | |
242 | [11] = "Inverted Cobblestone", | |
243 | [12] = "Inverted Bricks", | |
244 | [13] = "Inverted Stone Bricks", | |
245 | - | |
245 | + | [14] = "Inverted Nether Brick", |
246 | [15] = "Inverted Quartz", | |
247 | } | |
248 | ||
249 | ||
250 | ||
251 | ||
252 | local length = 0 | |
253 | local height = 0 | |
254 | local width = 0 | |
255 | local blocks = {} | |
256 | local data = {} | |
257 | ||
258 | function getBlockName(id, blockData) | |
259 | blockData = blockData or nil | |
260 | local str = nil | |
261 | if(block_id[id] == nil) then | |
262 | return tostring(id)..", "..tostring(blockData) | |
263 | else | |
264 | if(blockData) then | |
265 | if(id == 35) or (id == 159) or (id == 95) or (id == 160) or (id == 171) then | |
266 | str = tostring(woolColors[blockData]) .. " " .. tostring(block_id[id]) | |
267 | return str | |
268 | elseif id == 5 or id==17 or id==126 then | |
269 | str = tostring(woodTypes[blockData]).." "..tostring(block_id[id]) | |
270 | return str | |
271 | elseif id == 44 or id == 43 then | |
272 | str = tostring(nonWoodenSlabs[blockData]).." "..tostring(block_id[id]) | |
273 | return str | |
274 | end | |
275 | end | |
276 | return block_id[id] | |
277 | end | |
278 | end | |
279 | ||
280 | function getBlockId(x,y,z) | |
281 | return blocks[y + z*width + x*length*width + 1] | |
282 | end | |
283 | ||
284 | function getData(x,y,z) | |
285 | return data[y + z*width + x*length*width + 1] | |
286 | end | |
287 | ||
288 | function readbytes(h, n) | |
289 | for i=1,n do | |
290 | h.read() | |
291 | end | |
292 | end | |
293 | ||
294 | function readname(h) | |
295 | local n1 = h.read() | |
296 | local n2 = h.read() | |
297 | ||
298 | if(n1 == nil or n2 == nil) then | |
299 | return "" | |
300 | end | |
301 | ||
302 | local n = n1*256 + n2 | |
303 | ||
304 | local str = "" | |
305 | for i=1,n do | |
306 | local c = h.read() | |
307 | if c == nil then | |
308 | return | |
309 | end | |
310 | str = str .. string.char(c) | |
311 | end | |
312 | return str | |
313 | end | |
314 | ||
315 | function parse(a, h, containsName) | |
316 | local containsName = containsName or true | |
317 | local i,i1,i2,i3,i4 | |
318 | if a==0 then | |
319 | return | |
320 | end | |
321 | if containsName then | |
322 | name = readname(h) | |
323 | end | |
324 | ||
325 | if a==1 then | |
326 | readbytes(h,1) | |
327 | elseif a==2 then | |
328 | i1 = h.read() | |
329 | i2 = h.read() | |
330 | i = i1*256 + i2 | |
331 | if(name=="Height") then | |
332 | height = i | |
333 | elseif (name=="Length") then | |
334 | length = i | |
335 | elseif (name=="Width") then | |
336 | width = i | |
337 | - | a = 0 |
337 | + | |
338 | elseif a==3 then | |
339 | readbytes(h,4) | |
340 | elseif a==4 then | |
341 | readbytes(h,8) | |
342 | elseif a==5 then | |
343 | readbytes(h,4) | |
344 | elseif a==6 then | |
345 | readbytes(h,8) | |
346 | elseif a==7 then | |
347 | i1 = h.read() | |
348 | i2 = h.read() | |
349 | i3 = h.read() | |
350 | i4 = h.read() | |
351 | i = i1*256*256*256 + i2*256*256 + i3*256 + i4 | |
352 | if name == "Blocks" then | |
353 | for i=1,i do | |
354 | table.insert(blocks, h.read()) | |
355 | end | |
356 | elseif name == "Data" then | |
357 | for i=1,i do | |
358 | table.insert(data, h.read()) | |
359 | end | |
360 | else | |
361 | readbytes(h,i) | |
362 | end | |
363 | elseif a==8 then | |
364 | - | |
364 | + | |
365 | - | |
365 | + | |
366 | i = i1*256 + i2 | |
367 | readbytes(h,i) | |
368 | elseif a==9 then | |
369 | --readbytes(h,5) | |
370 | local type = h.read() | |
371 | i1 = h.read() | |
372 | i2 = h.read() | |
373 | i3 = h.read() | |
374 | i4 = h.read() | |
375 | i = i1*256*256*256 + i2*256*256 + i3*256 + i4 | |
376 | for j=1,i do | |
377 | parse(h.read(), h, false) | |
378 | end | |
379 | end | |
380 | end | |
381 | ||
382 | function forward() | |
383 | - | print(" -" .. getBlockName(v.blockID, v.data) .. ": " .. v.amount) |
383 | + | |
384 | turtle.dig() | |
385 | end | |
386 | end | |
387 | ||
388 | - | print("Give the numbers of all slots containing the specified block type:") |
388 | + | |
389 | while not turtle.up() do | |
390 | turtle.digUp() | |
391 | end | |
392 | end | |
393 | - | print(" -in which slots is " .. getBlockName(block.blockID, blockData) .. "?") |
393 | + | |
394 | function down() | |
395 | while not turtle.down() do | |
396 | turtle.digDown() | |
397 | end | |
398 | - | write(" ") |
398 | + | |
399 | - | str = read() |
399 | + | |
400 | - | for i = 1, #str do |
400 | + | |
401 | - | local c = str:sub(i,i) |
401 | + | |
402 | - | n = tonumber(c) |
402 | + | |
403 | - | if(n) then |
403 | + | |
404 | - | if(n>0 and n<10) then |
404 | + | |
405 | - | table.insert(slots[block.blockID][blockData], n) |
405 | + | |
406 | - | end |
406 | + | local function setColor(color) |
407 | - | end |
407 | + | if term.isColor() then |
408 | term.setTextColor(color) | |
409 | end | |
410 | end | |
411 | ||
412 | local function show_selected_slot(n) | |
413 | - | save("blocks",blocks) |
413 | + | local w,h = term.getCursorPos() |
414 | - | save("data",data) |
414 | + | local itemData = turtle.getItemDetail(newSelect) |
415 | - | save("uniqueblocks",uniqueblocks) |
415 | + | if itemData then |
416 | term.clearLine() | |
417 | term.setCursorPos(1,h) | |
418 | write(" "..itemData.name..", "..itemData.damage) | |
419 | - | setup(...) |
419 | + | else |
420 | term.clearLine() | |
421 | term.setCursorPos(1,h) | |
422 | write(" ") | |
423 | end | |
424 | return itemData | |
425 | end | |
426 | ||
427 | function setup(filename) | |
428 | --input file | |
429 | --returns blocks,data | |
430 | --requires parse, getBlockName | |
431 | ||
432 | if not fs.exists(filename) then | |
433 | error("File "..tostring(filename).." does not exist.") | |
434 | end | |
435 | h = fs.open(filename, "rb") | |
436 | ||
437 | local a = 0 | |
438 | while (a ~= nil) do | |
439 | a = h.read() | |
440 | parse(a, h) | |
441 | end | |
442 | ||
443 | write("length: " .. length) | |
444 | write(" width: " .. width) | |
445 | write(" height: " .. height .. "\n") | |
446 | ||
447 | uniqueblocks={} | |
448 | for i,v in ipairs(blocks) do | |
449 | found = false | |
450 | for j,w in ipairs(uniqueblocks) do | |
451 | ||
452 | --[[if (w.blockID==v and (w.data==data[i] or w.blockID ~= 35)) then | |
453 | found = true | |
454 | w.amount = w.amount + 1 | |
455 | break | |
456 | end]]-- | |
457 | ||
458 | --for now, data is only accounted for when the block is whool | |
459 | if (w.blockID==v) and (w.data==data[i]) then | |
460 | found = true | |
461 | w.amount = w.amount + 1 | |
462 | break | |
463 | end | |
464 | end | |
465 | ||
466 | if found==false then | |
467 | uniqueblocks[#uniqueblocks+1] = {} | |
468 | uniqueblocks[#uniqueblocks].blockID = v | |
469 | uniqueblocks[#uniqueblocks].data = data[i] | |
470 | uniqueblocks[#uniqueblocks].amount = 1 | |
471 | end | |
472 | end | |
473 | ||
474 | if fs.exists("slots") then | |
475 | print("slots file discovered...") | |
476 | print("skipping setup") | |
477 | h.close() | |
478 | return | |
479 | end | |
480 | ||
481 | print("number of block types: " .. #uniqueblocks) | |
482 | for i,v in ipairs(uniqueblocks) do | |
483 | if (i%9)==0 then | |
484 | read() | |
485 | end | |
486 | local stacks = math.ceil( (v.amount/64) ) | |
487 | setColor(colors.white) | |
488 | write(" -" .. getBlockName(v.blockID, v.data)) | |
489 | setColor(colors.lightGray) | |
490 | write("("..v.blockID..","..v.data..")") | |
491 | setColor(colors.white) | |
492 | write(": ") | |
493 | ||
494 | if v.amount > 64 then | |
495 | setColor(colors.magenta) | |
496 | print(stacks.." stacks") | |
497 | else | |
498 | setColor(colors.cyan) | |
499 | print(v.amount) | |
500 | end | |
501 | end | |
502 | setColor(colors.white) | |
503 | read() | |
504 | ||
505 | print("Use arrowKeys and enter to select slots containing which block the turtle will use for the specified blockType") | |
506 | print("select an empty block or press x to skip(not use) the specified blockType ie air") | |
507 | ||
508 | slots={} | |
509 | for i,block in ipairs(uniqueblocks) do | |
510 | local n = nil | |
511 | blockData = block.data | |
512 | setColor(colors.green) | |
513 | print(" -in which slots is " .. getBlockName(block.blockID, blockData).."("..block.blockID..","..blockData .. ") ?") | |
514 | setColor(colors.white) | |
515 | if not slots[block.blockID] then | |
516 | slots[block.blockID] = {} | |
517 | end | |
518 | slots[block.blockID][blockData] = {} | |
519 | show_selected_slot(turtle.getSelectedSlot()) | |
520 | --input none | |
521 | --output(n) | |
522 | ||
523 | --(oldWay) | |
524 | if tArgs[2] == "sim" or tArgs[2] == "simulate" then | |
525 | write(" ") | |
526 | str = read() | |
527 | n = tonumber(str) | |
528 | else | |
529 | n = numberSelector() | |
530 | end | |
531 | ||
532 | - | function blueprint() |
532 | + | local itemData = show_selected_slot(n) |
533 | if(n and itemData) then | |
534 | - | local x,y,z = 0,0,0 |
534 | + | print() |
535 | slots[block.blockID][blockData] = {itemData.name,itemData.damage} | |
536 | - | while true do |
536 | + | |
537 | local w,h = term.getCursorPos() | |
538 | term.clearLine() | |
539 | term.setCursorPos(1,h) | |
540 | print(" SKIPPING") | |
541 | slots[block.blockID][blockData] = {} | |
542 | end | |
543 | end | |
544 | ||
545 | - | x,y,z = iterate(x,y,z,0,0,0,height-1,width-1,length-1) |
545 | + | |
546 | save("slots",slots) | |
547 | end | |
548 | ||
549 | function numberSelector() | |
550 | ||
551 | - | function createInstructions(startx,starty,startz,height,width,length,nTurtles,placeMode) |
551 | + | local function selectNext(newSelect) |
552 | if newSelect >= 1 and newSelect <= 16 then | |
553 | - | local x,y,z = startx,starty,startz |
553 | + | turtle.select(newSelect) |
554 | - | instructions = {} |
554 | + | show_selected_slot(newSelect) |
555 | - | nTurtles = nTurtles or 1 |
555 | + | |
556 | - | --startx,starty,startz = startx,starty,startz or 0,0,0 |
556 | + | |
557 | - | placeMode = placeMode or "horizontal" |
557 | + | |
558 | - | local oTurtles = {} |
558 | + | local function ifKey(events,nKey,fn,...) |
559 | if events[1] == "key" and events[2] == tonumber(nKey) then | |
560 | - | --if horizontal |
560 | + | fn(...) |
561 | - | for i = 1,nTurtles do |
561 | + | |
562 | - | oTurtles[i] = {} |
562 | + | |
563 | - | if i == tonumber(nTurtles) then |
563 | + | |
564 | - | oTurtles[tonumber(nTurtles)].responsibleLength = math.floor(x/nTurtles) + (x - (math.floor(x/nTurtles)*nTurtles)) |
564 | + | local bRunning = true |
565 | local bNothing = false | |
566 | - | oTurtles[i].responsibleLength = math.floor(x/nTurtles) |
566 | + | while bRunning do |
567 | local events = { os.pullEvent("key") } | |
568 | - | oTurtles[i].startHeight = startx |
568 | + | local newSelect |
569 | - | if i == 1 then |
569 | + | local selected = turtle.getSelectedSlot() |
570 | - | oTurtles[i].startWidth = starty |
570 | + | |
571 | ifKey(events,203,function() newSelect = selected - 1 ; selectNext(newSelect) ; end) | |
572 | - | oTurtles[i].startWidth = oTurtles[i-1].startWidth + oTurtles[i].responsibleLength |
572 | + | ifKey(events,205,function() newSelect = selected + 1 ; selectNext(newSelect) ; end) |
573 | ifKey(events,200,function() newSelect = selected - 4 ; selectNext(newSelect) ; end) | |
574 | - | oTurtles[i].startLength = startz |
574 | + | ifKey(events,208,function() newSelect = selected + 4 ; selectNext(newSelect) ; end) |
575 | - | oTurtles[i].finalHeight = height-1 |
575 | + | ifKey(events,28,function() bRunning = false ; end) |
576 | - | oTurtles[i].finalWidth = oTurtles[i].startWidth + oTurtles[i].responsibleLength - 1 |
576 | + | ifKey(events,45,function() bNothing = true ; bRunning = false ; end) |
577 | - | oTurtles[i].finalLength = length-1 |
577 | + | ifKey(events,15,function() bNothing = true ; bRunning = false; end) |
578 | - | instructions[i] = {} |
578 | + | |
579 | for i = 2,13 do | |
580 | ifKey(events,i,function() selectNext(i-1) end) | |
581 | end | |
582 | for i = 26,27 do | |
583 | - | for i = 1,nTurtles do |
583 | + | ifKey(events,i,function() selectNext(i-13) end) |
584 | - | x,y,z = startx,starty,startz |
584 | + | |
585 | - | |
585 | + | for i = 39,40 do |
586 | - | |
586 | + | ifKey(events,i,function() selectNext(i-24) end) |
587 | - | while true do |
587 | + | |
588 | - | local n = #instructions[i]+1 |
588 | + | |
589 | - | instructions[i][n]={} |
589 | + | if bNothing then |
590 | - | instructions[i][n].x,instructions[1][n].y,instructions[1][n].z = x,y,z |
590 | + | return nil |
591 | - | instructions[i][n].placeMode = placeMode |
591 | + | |
592 | - | instructions[i][n].id = getBlockId(x,y,z) |
592 | + | return turtle.getSelectedSlot() |
593 | - | instructions[i][n].data = getData(x,y,z) |
593 | + | |
594 | - | x,y,z = iterate(x,y,z, |
594 | + | |
595 | - | oTurtles[i].startHeight, oTurtles[i].startWidth, oTurtles[i].startLength, |
595 | + | |
596 | - | oTurtles[i].finalHeight, oTurtles[i].finalWidth, oTurtles[i].finalLength |
596 | + | |
597 | - | ) |
597 | + | |
598 | - | --attach methods here |
598 | + | |
599 | --finds the location to place the next block | |
600 | - | |
600 | + | |
601 | - | |
601 | + | |
602 | --makes the turtle build faster by having to travel less | |
603 | blockID2 = getBlockId(x,y,z) -- temporary variable | |
604 | blockData2 = getData(x,y,z) -- temporary variable | |
605 | if slots[blockID2] then | |
606 | - | local ins = blueprint() |
606 | + | |
607 | - | save("instructions",ins) |
607 | + | |
608 | if slot_2nd then | |
609 | - | --[[ |
609 | + | |
610 | - | print("Press key to start building...") |
610 | + | |
611 | - | read() |
611 | + | |
612 | end | |
613 | - | up() |
613 | + | |
614 | - | n = 1 |
614 | + | |
615 | - | turtle.select(n) |
615 | + | |
616 | end | |
617 | - | for x=1,height do |
617 | + | |
618 | - | for y=1,width do |
618 | + | |
619 | - | for z=1,length do |
619 | + | |
620 | - | blockID = getBlockId(x-1,y-1,z-1) |
620 | + | |
621 | - | blockData = getData(x-1,y-1,z-1) |
621 | + | |
622 | - | forward() |
622 | + | |
623 | - | turtle.digDown() |
623 | + | |
624 | - | slot_lst = slots[blockID][blockData] |
624 | + | |
625 | - | if(slot_lst ~= nil) then |
625 | + | |
626 | - | if(#slot_lst > 0) then |
626 | + | |
627 | - | local found=false |
627 | + | |
628 | - | for i,v in ipairs(slot_lst) do |
628 | + | |
629 | - | if(turtle.getItemCount(v) > 0) then |
629 | + | |
630 | - | found=true |
630 | + | |
631 | - | turtle.select(v) |
631 | + | |
632 | - | break |
632 | + | |
633 | end | |
634 | - | end |
634 | + | |
635 | - | if not found then |
635 | + | |
636 | - | print("Not enough " .. getBlockName(blockID, blockData) .. ". Please refill...") |
636 | + | |
637 | - | read() |
637 | + | |
638 | - | end |
638 | + | |
639 | - | place() |
639 | + | |
640 | local height = finalx | |
641 | local width = finaly | |
642 | local length = finalz | |
643 | - | turtle.turnLeft() |
643 | + | |
644 | - | forward() |
644 | + | |
645 | - | turtle.turnLeft() |
645 | + | |
646 | - | for i=1,length do |
646 | + | |
647 | - | forward() |
647 | + | |
648 | if x < height then | |
649 | - | turtle.turnRight() |
649 | + | |
650 | - | turtle.turnRight() |
650 | + | |
651 | --x,y,z = "max","max","max" | |
652 | - | turtle.turnRight() |
652 | + | |
653 | - | for i=1,width do |
653 | + | |
654 | - | forward() |
654 | + | |
655 | if y <= starty then | |
656 | - | turtle.turnLeft() |
656 | + | |
657 | - | up() |
657 | + | |
658 | elseif x == height then | |
659 | x = "max" | |
660 | - | for i=1,height+1 do |
660 | + | |
661 | - | down() |
661 | + | |
662 | - | end]] |
662 | + | |
663 | else | |
664 | y=y-1 | |
665 | end | |
666 | end | |
667 | return x,y,z | |
668 | end | |
669 | ||
670 | function iterate(x,y,z,startx,starty,startz,finalx,finaly,finalz) | |
671 | ||
672 | local height = finalx | |
673 | local width = finaly | |
674 | local length = finalz | |
675 | ||
676 | ||
677 | local oddx,oddy = check(x,y,z,startx,starty,startz) | |
678 | if z == length and oddy then | |
679 | x,y,z = Yiterate(x,y,z,startx,starty,startz,finalx,finaly,finalz) | |
680 | elseif z == startz and oddy then | |
681 | z = z + 1 | |
682 | elseif z == startz and (not oddy) then | |
683 | x,y,z = Yiterate(x,y,z,startx,starty,startz,finalx,finaly,finalz) | |
684 | elseif z==length and (not oddy) then | |
685 | z = z - 1 | |
686 | ||
687 | elseif z < length then | |
688 | if oddy then | |
689 | z = z + 1 | |
690 | else | |
691 | z = z - 1 | |
692 | end | |
693 | end | |
694 | return x,y,z | |
695 | end | |
696 | ||
697 | -- [[ TSP_algorithm API ]] -- | |
698 | ||
699 | local w,h = term.getSize() | |
700 | ||
701 | local function calculateDistance(tNode1,tNode2) | |
702 | local turnCost = 0 | |
703 | local deltaY,deltaZ | |
704 | local y1 = tNode1[2] | |
705 | local z1 = tNode1[3] | |
706 | local y2 = tNode2[2] | |
707 | local z2 = tNode2[3] | |
708 | ||
709 | deltaZ = z2-z1 | |
710 | deltaY = y2-y1 | |
711 | ||
712 | if deltaZ == 0 or deltaY == 0 then | |
713 | turnCost = 0 | |
714 | else | |
715 | turnCost = 1 | |
716 | end | |
717 | ||
718 | return math.abs(deltaZ) + math.abs(deltaY) + turnCost | |
719 | --return math.sqrt( (z2-z1)^2 + (y2-y1)^2 ) | |
720 | end | |
721 | ||
722 | local function twoOptSwap(route, i, k) | |
723 | local new_route = {} | |
724 | for c = 1,i-1 do | |
725 | table.insert(new_route,route[c]) | |
726 | end | |
727 | for c = k,i,-1 do | |
728 | table.insert(new_route,route[c]) | |
729 | end | |
730 | for c = k+1,#route do | |
731 | table.insert(new_route,route[c]) | |
732 | end | |
733 | return new_route | |
734 | end | |
735 | ||
736 | local function calculateTotalDistance(route) | |
737 | local total = 0 | |
738 | for i = 1,#route-1 do | |
739 | total = total + calculateDistance(route[i],route[i+1]) | |
740 | end | |
741 | return total | |
742 | end | |
743 | ||
744 | local function display(route,distance) | |
745 | local l,h = term.getSize() | |
746 | shell.run("clear") | |
747 | ||
748 | for i = 1,#route-1 do | |
749 | paintutils.drawLine(route[i][2],route[i][3],route[i+1][2],route[i+1][3],colors.lime) | |
750 | end | |
751 | for i,coord in pairs(route) do | |
752 | term.setBackgroundColor(colors.yellow) | |
753 | term.setTextColor(colors.magenta) | |
754 | term.setCursorPos(coord[2],coord[3]) | |
755 | term.write(string.char(i+64)) | |
756 | end | |
757 | term.setBackgroundColor(colors.black) | |
758 | term.setTextColor(colors.white) | |
759 | term.setCursorPos(1,h) | |
760 | term.write(distance) | |
761 | end | |
762 | ||
763 | local route = {} | |
764 | route[1] = {1,28,3} | |
765 | route[2] = {1,36,13} | |
766 | route[3] = {1,20,8} | |
767 | route[4] = {1,8,8} | |
768 | route[5] = {1,44,5} | |
769 | route[6] = {1,32,13} | |
770 | route[7] = {1,20,17} | |
771 | --route[8] = {1,28,3} | |
772 | ||
773 | function tsp_algorithm(existing_route) | |
774 | local improve = 0 | |
775 | while improve < 3 do | |
776 | local best_distance = calculateTotalDistance(existing_route) | |
777 | for i = 2,#existing_route-1 do | |
778 | for k = i + 1, #existing_route do | |
779 | new_route = twoOptSwap(existing_route, i, k) | |
780 | new_distance = calculateTotalDistance(new_route) | |
781 | if new_distance < best_distance then | |
782 | improve = 0 | |
783 | existing_route = new_route | |
784 | best_distance = calculateTotalDistance(existing_route) | |
785 | display(existing_route,best_distance) | |
786 | sleep(0) | |
787 | end | |
788 | end | |
789 | end | |
790 | improve = improve + 1 | |
791 | end | |
792 | return existing_route, best_distance | |
793 | end | |
794 | ||
795 | -- [[ schematic --> blueprint ]] -- | |
796 | ||
797 | --turtles[i].instructions[n] = {x,y,z,id,data} | |
798 | --i = multiturtle ie 1,2,3,4 ; n = step ie 1 - 256 (no air) | |
799 | ||
800 | --fn splits 16x16 grid between 4 turtles returning startx,y,z and endx,y,z of 4 4x4 grids | |
801 | --fn takes each 4x4 grid and turns them into instructions[n] = {x,y,z,id,data} | |
802 | --fn for master turtle to setup all slave turtles with the instructions[n] table and goto/find/place functions | |
803 | ||
804 | function blueprint(startx,starty,startz,finalx,finaly,finalz) | |
805 | --uses iterator to make instructions[n] table | |
806 | local x,y,z = startx,starty,startz | |
807 | local instructions = {} | |
808 | local nTimes = (finalx+1-startx)*(finaly+1-starty)*(finalz+1-startz) | |
809 | for i=1,nTimes do | |
810 | if x == "max" then | |
811 | break | |
812 | end | |
813 | local id = getBlockId(x,y,z) | |
814 | local data = getData(x,y,z) | |
815 | if id > 0 then | |
816 | table.insert(instructions,{x,y,z,id,data}) | |
817 | end | |
818 | x,y,z = iterate(x,y,z,startx,starty,startz,finalx,finaly,finalz) | |
819 | end | |
820 | return instructions | |
821 | end | |
822 | ||
823 | function improveBlueprint(instructions,startx,starty,startz,finalx,finaly,finalz) | |
824 | local function instructions2layers(instructions) | |
825 | local layers = {} | |
826 | for x = startx,finalx do | |
827 | layers[x] = {} | |
828 | for n=1,#instructions do | |
829 | if instructions[n][1] == x then | |
830 | table.insert(layers[x],{unpack(instructions[n],1,3)}) | |
831 | end | |
832 | end | |
833 | end | |
834 | return layers | |
835 | end | |
836 | local function organize(layers) | |
837 | local startingPosition = {startx,starty,startz} | |
838 | for x = startx,finalx do | |
839 | table.insert(layers[x],1,startingPosition) | |
840 | layers[x] = tsp_algorithm(layers[x]) | |
841 | startingPosition = layers[x][#layers[x]] | |
842 | end | |
843 | return layers | |
844 | end | |
845 | ||
846 | local function layers2instructions(layers) | |
847 | local instructions = {} | |
848 | --organizedlayers only | |
849 | for x = startx,finalx do | |
850 | for i = 2,#layers[x] do | |
851 | table.insert(instructions,layers[x][i]) | |
852 | end | |
853 | end | |
854 | return instructions | |
855 | end | |
856 | ||
857 | local function add_id_and_data(instructions) | |
858 | for n = 1,#instructions do | |
859 | instructions[n][4] = getBlockId(unpack(instructions[n],1,3)) | |
860 | instructions[n][5] = getData(unpack(instructions[n],1,3)) | |
861 | end | |
862 | return instructions | |
863 | end | |
864 | ||
865 | local layers = instructions2layers(instructions) | |
866 | layers = organize(layers) | |
867 | local new_instructions = layers2instructions(layers) | |
868 | new_instructions = add_id_and_data(new_instructions) | |
869 | return new_instructions | |
870 | end | |
871 | ||
872 | function simulateIns(instructions) | |
873 | local lastx = 0 | |
874 | shell.run("clr") | |
875 | for n = 1,#instructions do | |
876 | if lastx~=instructions[n][1] then | |
877 | term.setBackgroundColor(colors.black) | |
878 | shell.run("clr") | |
879 | end | |
880 | term.setCursorPos(instructions[n][2]+1,instructions[n][3]+1) | |
881 | term.setBackgroundColor(2^instructions[n][5]) | |
882 | term.write(" ") | |
883 | lastx = instructions[n][1] | |
884 | sleep(0) | |
885 | end | |
886 | end | |
887 | ||
888 | function orientation_check(reference,slots) | |
889 | for id,table in pairs(slots) do | |
890 | for data,table2 in pairs(table) do | |
891 | if table2 and table2[1] then | |
892 | if (table2[1]:find("stairs") or table2[1]:find("chest") or table2[1]:find("furnace")) then | |
893 | for n = 1,5 do | |
894 | term.scroll(1) | |
895 | sleep(0) | |
896 | end | |
897 | print("orientation required") | |
898 | print("what direction is the turtle facing?") | |
899 | local r | |
900 | while true do | |
901 | write(" ") | |
902 | if term.isColor() then | |
903 | term.setTextColor(colors.yellow) | |
904 | end | |
905 | r = read() | |
906 | term.setTextColor(colors.white) | |
907 | if r ~= "south" and r~= "north" and r~= "west" and r~= "east" then | |
908 | print(r.. " not recognized, north/south/east/west?") | |
909 | else | |
910 | break | |
911 | end | |
912 | end | |
913 | ||
914 | reference.relativeDirection = r | |
915 | print("don't forget to include wrench in turtle!") | |
916 | reference.wrench = true | |
917 | return reference | |
918 | end | |
919 | end | |
920 | end | |
921 | end | |
922 | return reference | |
923 | end | |
924 | ||
925 | local function Main() | |
926 | setup(filename) | |
927 | ||
928 | --save("blocks",blocks) | |
929 | --save("data",data) | |
930 | --save("uniqueblocks",uniqueblocks) | |
931 | ||
932 | local reference = { | |
933 | startx = 0, | |
934 | starty = 0, | |
935 | startz = 0, | |
936 | finalx = height-1, | |
937 | finaly = width-1, | |
938 | finalz = length-1, | |
939 | height = height, | |
940 | width = width, | |
941 | length = length, | |
942 | wrench = false, | |
943 | multiturtle = false, -- otherwise its a number (1,2,4,8,12,etc), | |
944 | relativeDirection = "south", | |
945 | numChests = false, | |
946 | filename = false, | |
947 | } | |
948 | ||
949 | if not slots then | |
950 | slots = textutils.unserialize( fs.open("slots","r").readAll() ) | |
951 | end | |
952 | ||
953 | reference = orientation_check(reference,slots) | |
954 | ||
955 | local ins = blueprint(reference.startx,reference.starty,reference.startz,reference.finalx,reference.finaly,reference.finalz) | |
956 | if tArgs[2] == "tsp" then | |
957 | ins = improveBlueprint(ins,reference.startx,reference.starty,reference.startz,reference.finalx,reference.finaly,reference.finalz) | |
958 | end | |
959 | ||
960 | --textutils.pagedPrint(textutils.serialize(ins)) | |
961 | --saveIns("instructions",ins) | |
962 | local fname = saveBlueprint(reference,slots,ins,uniqueblocks) | |
963 | print(fname," saved") | |
964 | --delete slots,reference,ins,uniqueblocks files | |
965 | end | |
966 | ||
967 | Main() |