local old = {} cPos = {} local glass = "minecraft:glass" local officialRelease = false local activateTheExamples = true -- You won't be able to use it as an API if you activate this but you will have access to cool examples when you launch it dangerousAmountOfQueries = 850 -- blocks restingTime = 0.1 -- seconds xa,ya,za = commands.getBlockPosition() -- xa,ya and za are used everywhere so... cPos.x = xa cPos.y = ya cPos.z = za theFourDirections = {"north", "south", "east", "west"} -- computer's position is stored there slab = "chisel:marble_slab" asphalt = "chisel:antiBlock" paint = "chisel:marble" buildingColors = { "gray", "lightGray", "brown", "white" } buildingTypes = { "squareBuilding", "squareBuilding", "spikyBuilding" } typesOfLastFloors = { "penthouse", "terrace" } wallBlocks = {} wallBlocks["gray"] = { "chisel:cobblestone:1", "chisel:cobblestone:2", "chisel:cobblestone:3", "chisel:cobblestone:4", "chisel:cobblestone:7", "chisel:cobblestone:15" } wallBlocks["lightGray"] = { "chisel:andesite:2", "chisel:andesite:1", "chisel:andesite:3", "chisel:andesite:4", "chisel:cobblestone:10" } wallBlocks["brown"] = { "chisel:concrete:1", "chisel:concrete:2", "chisel:concrete:5", "chisel:concrete:7", "chisel:concrete:3", "chisel:factoryblock:1" } wallBlocks["white"] = { "chisel:holystone:4", "chisel:holystone:6", "chisel:holystone:13", "chisel:diorite:1", "chisel:diorite:2", "chisel:diorite:3", "chisel:diorite:6" } floorBlocks = {} floorBlocks["gray"] = { "chisel:cobblestone:1", "chisel:cobblestone:2", "chisel:cobblestone:3", "chisel:cobblestone:4", "chisel:cobblestone:7", "chisel:cobblestone:15" } floorBlocks["lightGray"] = { "chisel:andesite:1", "chisel:andesite:3", "chisel:cobblestone:10" } floorBlocks["brown"] = { "chisel:concrete:1", "chisel:concrete:2", "chisel:concrete:5", "chisel:concrete:7", "chisel:concrete:3", "chisel:concrete:9", "chisel:concrete:8", "chisel:factoryblock:1" } floorBlocks["white"] = { "chisel:holystone:4", "chisel:holystone:6", "chisel:holystone:12", "chisel:diorite:1", "chisel:diorite:3", "chisel:diorite:6" } complementBlocks = {} complementBlocks["gray"] = { "chisel:cobblestone:1", "chisel:cobblestone:2", "chisel:cobblestone:3", "chisel:cobblestone:4", "chisel:cobblestone:7", "chisel:cobblestone:15" } complementBlocks["lightGray"] = { "chisel:andesite:1", "chisel:andesite:3", "chisel:cobblestone:10" } complementBlocks["brown"] = { "chisel:concrete:1", "chisel:concrete:2", "chisel:concrete:5", "chisel:concrete:7", "chisel:concrete:3", "chisel:concrete:9", "chisel:concrete:8", "chisel:factoryblock:1" } complementBlocks["white"] = { "chisel:holystone:4", "chisel:holystone:6", "chisel:holystone:12", "chisel:diorite:1", "chisel:diorite:3", "chisel:diorite:6" } glassBlocks = { "minecraft:glass", "TConstruct:GlassBlock", "TConstruct:GlassBlock.StainedClear", "TConstruct:GlassBlock.StainedClear:7", "TConstruct:GlassBlock.StainedClear:15", "chisel:stained_glass_white", "chisel:stained_glass_white:1", "chisel:stained_glass_white:2" } air = "minecraft:air" if not officialRelease then strtp = fs.open("startup", "w") strtp.write('shell.run("dl", "citybuilder") shell.run("citybuilder")') strtp.close() end plan = {width = 120, length = 120} plan[1] = {} plan[2] = {} function plan:at(i,j,layer) if layer == nil then layer = 1 end ret = plan[layer][i+plan.width*j] while ret == nil do if layer <= 1 then break end layer = layer-1 ret = plan[layer][i+plan.width*j] end return plan[layer][i+plan.width*j] end function plan:set(i,j,v,layer) if layer == nil then layer = 1 end plan[layer][i+plan.width*j] = v end local function deltaT(timerID) if type(lastCallFromTheID) ~= "table" then lastCallFromTheID = {} end if lastCallFromTheID[timerID] == nil then lastCallFromTheID[timerID] = os.clock() end temp = os.clock()-lastCallFromTheID[timerID] lastCallFromTheID[timerID] = os.clock() return temp end old.execAsync = commands.execAsync -- Editing the default execAsync command to include a safeguard local function execAsync(str) -- Too many queries in a single blast will cause problems. if execAsyncQueries == nil then execAsyncQueries = 0 end timeDiff2 = deltaT("execAsync") -- I'll measure how long I waited between each queries -- As CC time units don't go after the 2d decimal i'll wait 0.1s every 850 queries -- I call a row of queries a "blast" -- (8500 q/s at best) if timeDiff2 > restingTime then execAsyncQueries = 0 --Blast of queries was cut off. I consider this one finished else execAsyncQueries = execAsyncQueries+1 end -- console(execAsyncQueries, 7) if execAsyncQueries > dangerousAmountOfQueries then sleep(restingTime) execAsyncQueries = 0 --just to be sure, manually consider the blast as finished end return old.execAsync(str) end commands.execAsync = execAsync local function isTrue(number) if number == 0 then return false else return true end end local function count(str,s) lastPos = 0 i=0 while string.find(str,s,lastPos) ~= nil do lastPos = string.find(str,s,lastPos) lastPos = lastPos+1 i=i+1 end return i end string.count = count local function pickRandom(t) return t[math.random(1,#t)] end table.pickRandom = pickRandom local function round(num, idp) local mult = 10^(idp or 0) return math.floor(num * mult + 0.5) / mult end math.round = round local function console(txt,line) if monitor == nil then monitor = term end if not officialRelease then if line == nil then line = 1 end monitor.setCursorPos(1,line) monitor.clearLine(line) monitor.write(txt) monitor.setCursorPos(1,line+1) end end local function forEachColumnOfAWallDoMyFunc(yourFunc, xa, ya, za, width, length) startXPos = xa -- This is all complicated isn't it ? Why not do startYPos = ya -- for i=xa, xa+width ? column = 1 -- Well, because it doesn't work. I tried and tried and tried. It should work, but it doesn't, and I can't see why, so I gave up and made this instead. for i=1,#validColumns.front do yourFunc(xa, ya, za, column, "south") yourFunc(xa, ya+length-1, za, column, "north") column = column+1 xa = xa+1 end xa = startXPos column = 1 for i=1, #validColumns.side do yourFunc(xa, ya, za, column, "west") yourFunc(xa+width-1, ya, za, column, "east") column = column+1 ya = ya+1 end end local function printTable(tbl) for i,v in pairs(tbl) do print("["..tostring(i).."]:'"..tostring(v).."'") end end function getBlockInfo(xa,ya,za) xa = xa+cPos.x ya = (-1)*ya+cPos.z za = za+cPos.y -- print(xa..","..ya..","..za) if type(oldBlockHandling) ~= "string" then oldBlockHandling = "" end if type(dataValue) ~= "string" then dataValue = "" end groszizi = commands.getBlockInfo(xa,za,ya) --local block = "minecraft:sponge" --commands.execAsync("setblock " .. tostring(xa) .. " " .. tostring(za) .. " ".. tostring(ya) .. " " .. tostring(block) .. " " .. tostring(dataValue) .. " " .. tostring(oldBlockHandling)) return groszizi end function setBlock(block,xa,ya,za,oldBlockHandling) local dataValue = "" ya = (-1)*ya -- NORTH IS NOT -y FUCK THIS if type(oldBlockHandling) ~= "string" then oldBlockHandling = "" end if string.find(block, ":") ~= nil then -- if blockname divided in parts separated by ":"s i=0 local words = {} for part in string.gmatch(block, "[^:]+") do -- get each part i=i+1 words[i] = part end if string.match(words[#words], "%d") then -- if last part of blockname is a number dataValue = words[#words] -- it's a dataValue table.remove(words, #words) -- i like to enter block names the old school way. -- mod:block:metadata block = table.concat(words, ":") end end -- print("setblock ~" .. tostring(xa) .. " ~" .. tostring(za) .. " ~".. tostring(ya) .. " " .. tostring(block) .. " " .. tostring(dataValue) .. " " .. tostring(oldBlockHandling)) commands.execAsync("setblock ~" .. tostring(xa) .. " ~" .. tostring(za) .. " ~".. tostring(ya) .. " " .. tostring(block) .. " " .. tostring(dataValue) .. " " .. tostring(oldBlockHandling)) end function fill(block, xa, ya, za, width, length, height) queries = 0 if width <= 0 then width=1 end if length <= 0 then length=1 end if height <= 0 then height=1 end -- fill(air,-7,1,-1,7,21,0) for i=xa,xa+width-1 do for j=ya,ya+length-1 do for k=za,za+height-1 do setBlock(block, i, j, k) queries = queries+1 end end end return queries end function fillInside(blockInside, blockOutside, xa, ya, za, width, length, height) queries = fill(blockOutside, xa, ya, za, width, length, height) queries = queries + fill(blockInside, xa+1, ya+1, za, width-2, length-2, height) return queries end function floor(blockInside, blockOutside, xa, ya, za, width, length) return fillInside(blockInside, blockOutside, xa, ya, za, width, length, 1) end function walls(block, xa, ya, za, width, length, height) queries = fill(block, xa, ya, za, width, length, height) queries = queries + fill(air, xa+1, ya+1, za, width-2, length-2, height) return queries end function room(blockFloor, blockWalls, blockComplement, xa, ya, za, width, length, height) queries = fill(air, xa, ya, za, width, length, height) queries = floor(blockFloor, blockComplement, xa, ya, za, width, length) + queries queries = walls(blockWalls, xa, ya, za+1, width, length, height-2) + queries queries = floor(blockFloor, blockComplement, xa, ya, za+height-1, width, length) + queries return queries end function getValidWindowsPostions(xa, ya, za, width, length, height, numberOfWindowsFront, numberOfWindowsSide) local numberOfWindowsFront, numberOfWindowsSide if numberOfWindowsFront == nil then numberOfWindowsFront = math.floor(math.sqrt(width)) end if numberOfWindowsSide == nil then numberOfWindowsSide = math.floor(math.sqrt(length)) end local frontWindowsLength = math.floor((width-numberOfWindowsFront-1)/numberOfWindowsFront) local frontMiddleWindowLength = width-(numberOfWindowsFront+1)-((numberOfWindowsFront-1)*frontWindowsLength) local frontMiddleWindow = math.ceil(numberOfWindowsFront/2) local frontMiddleWindowPosition = frontMiddleWindow + (frontMiddleWindow-1)*frontWindowsLength local sideWindowsLength = math.floor((length-numberOfWindowsSide-1)/numberOfWindowsSide) local sideMiddleWindowLength = length-(numberOfWindowsSide+1)-((numberOfWindowsSide-1)*sideWindowsLength) local sideMiddleWindow = math.ceil(numberOfWindowsSide/2) local sideMiddleWindowPosition = sideMiddleWindow + (sideMiddleWindow-1)*sideWindowsLength -- Maintenant on a les dimensions des fenêtres. Longueurs. Positions. Tout. -- L'idée est de parcourir le contour du mur et de dessiner les fenêtres. validColumns = {} validColumns.front = {} validColumns.side = {} -- Murs de face et arrière for i=1,width do --tout en verre validColumns.front[i] = true end validColumns.front[1] = false --sauf le début validColumns.front[width] = false --et la fin i=1 while i < width/2 do --puis on fait vitre après vitre de gauche à droite jusqu'au milieu validColumns.front[i] = false i=i+frontWindowsLength+1 end i=width while i > width/2 do --puis de droite à gauche jusqu'au milieu (pour faire une symétrie) validColumns.front[i] = false i=i-frontWindowsLength-1 end for i=frontMiddleWindowPosition+1,frontMiddleWindowPosition+frontMiddleWindowLength do validColumns.front[i] = true end -- Murs des côtés for i=1,length do --tout en verre validColumns.side[i] = true end validColumns.side[1] = false --sauf le début validColumns.side[length] = false --et la fin i=1 while i < length/2 do --puis on fait vitre après vitre depuis le début jusqu'au milieu validColumns.side[i] = false i=i+sideWindowsLength+1 end i=length while i > length/2 do --puis de la fin jusqu'au milieu validColumns.side[i] = false i=i-sideWindowsLength-1 end local center = (length/2) local otherCenter = math.ceil(sideMiddleWindowPosition+(sideMiddleWindowLength/2)) -- those are currently useless return validColumns end function roomWithWindows(blockFloor, blockWalls, blockComplement, glassBlock, xa, ya, za, width, length, height, numberOfWindowsFront, numberOfWindowsSide) room(blockFloor, blockWalls, blockComplement, xa, ya, za, width, length, height) if tonumber(length) < 3 or tonumber(width) < 3 or tonumber(height) < 3 then return false end validColumns = getValidWindowsPostions(xa, ya, za, width, length, height, numberOfWindowsFront, numberOfWindowsSide) -- L'idée est de parcourir le contour du mur et de dessiner les fenêtres. function myFuncToPlaceOrnaments(xa,ya,za,column,wallSide) if wallSide == "north" then if validColumns.front[column] == true then fill(glassBlock, xa, ya, za+1, 1, 1, height-2) --glassify column elseif validColumns.front[column] == false then fill(blockWalls, xa, ya+1, za, 1, 1, height) --make a pillar end elseif wallSide == "south" then if validColumns.front[column] == true then txt = " glass: "..xa..","..ya..","..tostring(za+1) fill(glassBlock, xa, ya, za+1, 1, 1, height-2) --glassify column elseif validColumns.front[column] == false then txt = " pilla: "..xa..","..tostring(ya-1)..","..za fill(blockWalls, xa, ya-1, za, 1, 1, height) --make a pillar end elseif wallSide == "east" then if validColumns.side[column] == true then fill(glassBlock, xa, ya, za+1, 1, 1, height-2) --glassify column elseif validColumns.side[column] == false then fill(blockWalls, xa+1, ya, za, 1, 1, height) --make a pillar end elseif wallSide == "west" then if validColumns.side[column] == true then fill(glassBlock, xa, ya, za+1, 1, 1, height-2) --glassify column elseif validColumns.side[column] == false then fill(blockWalls, xa-1, ya, za, 1, 1, height) --make a pillar end end end forEachColumnOfAWallDoMyFunc(myFuncToPlaceOrnaments, xa, ya, za, width, length) return true end function squareBuilding(numberOfFloors, blockFloor, blockWalls, blockComplement, glassBlock, xa, ya, za, width, length, ceilingHeight, numberOfWindowsFront, numberOfWindowsSide) ----[[ local width = width-2 -- foreseeing the width/length gain of the pillars around it local length = length-2 local xa = xa+1 local ya = ya+1 --]] zPositionStart = za for i=1, numberOfFloors-1 do roomWithWindows(blockFloor, blockWalls, blockComplement, glassBlock, xa, ya, za, width, length, ceilingHeight, numberOfWindowsFront, numberOfWindowsSide) za = za+ceilingHeight-1 end lastFloor("random", blockFloor, blockWalls, blockComplement, glassBlock, xa, ya, za, width, length, ceilingHeight, numberOfWindowsFront, numberOfWindowsSide) end function spikyBuilding(numberOfFloors, blockFloor, blockWalls, blockComplement, glassBlock, xa, ya, za, width, length, ceilingHeight, numberOfWindowsFront, numberOfWindowsSide) --[[local width = width-2 -- foreseeing the width/length gain of the pillars around it local length = length-2 local xa = xa+1 local ya = ya+1--]] if numberOfFloors < 3 then return false end zPositionStart = za shrink = math.random(2,numberOfFloors-1) shrinkage = 0 for i=0, numberOfFloors do if i%shrink == 0 then if length < 5 or width < 5 then -- can't shrink anymore return true else shrinkage = shrinkage+1 -- width = width-2 -- length = length-2 -- xa = xa+1 -- ya = ya+1 end end roomWithWindows(blockFloor, blockWalls, blockComplement, glassBlock, xa+shrinkage, ya+shrinkage, za, width-2*shrinkage, length-2*shrinkage, ceilingHeight, numberOfWindowsFront, numberOfWindowsSide) za = za+ceilingHeight-1 end return true end function lastFloor(typeOfLastFloor, blockFloor, blockWalls, blockComplement, glassBlock, xa, ya, za, width, length, ceilingHeight, numberOfWindowsFront, numberOfWindowsSide) if typeOfLastFloor == "random" or typeOfLastFloor == nil then typeOfLastFloor = table.pickRandom(typesOfLastFloors) end if typeOfLastFloor == "terrace" then roomWithWindows(blockFloor, blockWalls, blockComplement, glassBlock, xa, ya, za, width, length, ceilingHeight, numberOfWindowsFront, numberOfWindowsSide) za = za+ceilingHeight fillInside(air, "minecraft:fence", xa, ya, za, width, length, 1) elseif typeOfLastFloor == "normal" then roomWithWindows(blockFloor, blockWalls, blockComplement, glassBlock, xa, ya, za, width, length, ceilingHeight, numberOfWindowsFront, numberOfWindowsSide) elseif typeOfLastFloor == "penthouse" then roomWithWindows(blockFloor, blockWalls, blockComplement, glassBlock, xa, ya, za, width, length, ceilingHeight*2+1, numberOfWindowsFront, numberOfWindowsSide) fill(blockFloor, xa+1, ya+1, za+ceilingHeight, math.round(0.75*width), math.round(0.5*length), 1) fill("minecraft:fence", xa+1, ya+math.round(0.5*length), za+ceilingHeight+1, math.round(0.75*width), 1, 1) fill("minecraft:fence", xa+math.round(0.75*width), ya+1, za+ceilingHeight+1, 1, math.round(0.5*length), 1) end end function randomBuilding(buildingColor, xa, ya, za, numberOfFloors, length, width) glassBlock = table.pickRandom(glassBlocks) floorBlock = table.pickRandom(floorBlocks[buildingColor]) wallBlock = table.pickRandom(wallBlocks[buildingColor]) complementBlock = table.pickRandom(complementBlocks[buildingColor]) buildingType = table.pickRandom(buildingTypes) if numberOfFloors == nil then numberOfFloors = math.random(2,6) end if width == nil then width = math.random(8,20) end if length == nil then length = math.random(8,20) end console("Building a " .. width .. " by " .. length .. " " .. buildingColor .. " " .. buildingType .. " of "..numberOfFloors.." floors.", 1) if buildingType == "squareBuilding" then success = squareBuilding(numberOfFloors, floorBlock, wallBlock, complementBlock, glassBlock, xa,ya,za, width, length,5) elseif buildingType == "spikyBuilding" then success = spikyBuilding(numberOfFloors, floorBlock, wallBlock, complementBlock, glassBlock, xa,ya,za, width, length,5) end console("Built a " .. width .. " by " .. length .. " " .. buildingColor .. " " .. buildingType .. " of "..numberOfFloors.." floors.", 1) return success end function tryAndPaintThatBlock(xa,ya,za,direction) slab = "chisel:marble_slab" asphalt = "chisel:antiBlock" paint = "chisel:marble" if direction == nil then direction = "all" end if direction == "north" or direction == "south" or direction == "all" then if (ya%7) > 3 then setBlock(paint,xa,ya,za) else setBlock(asphalt,xa,ya,za) end end if direction == "east" or direction == "west" or direction == "all" then if (xa%7) > 3 then setBlock(paint,xa,ya,za) else setBlock(asphalt,xa,ya,za) end end end function road(xa,ya,za,direction,length) if direction == "north" then -- north: y+ for i=ya,ya+length-1 do setBlock(slab, xa+6, i, za) setBlock(slab, xa+5, i, za) setBlock(slab, xa+4, i, za) setBlock(asphalt, xa+3, i, za-1) setBlock(asphalt, xa+2, i, za-1) setBlock(asphalt, xa+1, i, za-1) tryAndPaintThatBlock(xa,i,za-1,direction) --[[ if (i%7) > 3 then -- 0,0,0,0,1,1,1,0,0,0,0,1,1,1 setBlock(paint,xa,i,za-1) else setBlock(asphalt, xa, i, za-1) end ]]-- setBlock(asphalt, xa-1, i, za-1) setBlock(asphalt, xa-2, i, za-1) setBlock(asphalt, xa-3, i, za-1) setBlock(slab, xa-4, i, za) setBlock(slab, xa-5, i, za) setBlock(slab, xa-6, i, za) end elseif direction == "south" then -- south: y- for i=ya,ya-length+1,-1 do setBlock(slab, xa+6, i, za) setBlock(slab, xa+5, i, za) setBlock(slab, xa+4, i, za) setBlock(asphalt, xa+3, i, za-1) setBlock(asphalt, xa+2, i, za-1) setBlock(asphalt, xa+1, i, za-1) tryAndPaintThatBlock(xa,i,za-1,direction) --[[ if (i%7) > 3 then -- 0,0,0,0,1,1,1,0,0,0,0,1,1,1 setBlock(paint,xa,i,za-1) else setBlock(asphalt, xa, i, za-1) end ]]-- setBlock(asphalt, xa-1, i, za-1) setBlock(asphalt, xa-2, i, za-1) setBlock(asphalt, xa-3, i, za-1) setBlock(slab, xa-4, i, za) setBlock(slab, xa-5, i, za) setBlock(slab, xa-6, i, za) end elseif direction == "east" then -- east: x+ for i=xa,xa+length-1 do setBlock(slab, i, ya+6, za) setBlock(slab, i, ya+5, za) setBlock(slab, i, ya+4, za) setBlock(asphalt, i, ya+3, za-1) setBlock(asphalt, i, ya+2, za-1) setBlock(asphalt, i, ya+1, za-1) tryAndPaintThatBlock(i,ya,za-1,direction) --[[ if (i%7) > 3 then -- 0,0,0,0,1,1,1,0,0,0,0,1,1,1 setBlock(paint,i,ya,za-1) else setBlock(asphalt, i, ya, za-1) end --]] setBlock(asphalt, i, ya-1, za-1) setBlock(asphalt, i, ya-2, za-1) setBlock(asphalt, i, ya-3, za-1) setBlock(slab, i, ya-4, za) setBlock(slab, i, ya-5, za) setBlock(slab, i, ya-6, za) end elseif direction == "west" then -- west: x- for i=xa,xa-length+1,-1 do setBlock(slab, i, ya+6, za) setBlock(slab, i, ya+5, za) setBlock(slab, i, ya+4, za) setBlock(asphalt, i, ya+3, za-1) setBlock(asphalt, i, ya+2, za-1) setBlock(asphalt, i, ya+1, za-1) tryAndPaintThatBlock(i,ya,za-1,direction) --[[ if (i%7) > 3 then -- 0,0,0,0,1,1,1,0,0,0,0,1,1,1 setBlock(paint,i,ya,za-1) else setBlock(asphalt, i, ya, za-1) end --]] setBlock(asphalt, i, ya-1, za-1) setBlock(asphalt, i, ya-2, za-1) setBlock(asphalt, i, ya-3, za-1) setBlock(slab, i, ya-4, za) setBlock(slab, i, ya-5, za) setBlock(slab, i, ya-6, za) end end end function roadIntersectionAnalysis(xa,ya,za) directions = {} print("jusque la ca va") northBlock = getBlockInfo(xa,ya+12,za-1) print(1) southBlock = getBlockInfo(xa,ya-12,za-1) print(2) eastBlock = getBlockInfo(xa+12,ya,za-1) print(3) westBlock = getBlockInfo(xa-12,ya,za-1) print("on a les blockInfo") if northBlock.name == asphalt or northBlock.name == paint then table.insert(directions, "north") end if southBlock.name == asphalt or southBlock.name == paint then table.insert(directions, "south") end if eastBlock.name == asphalt or eastBlock.name == paint then table.insert(directions, "east") end if westBlock.name == asphalt or westBlock.name == paint then table.insert(directions, "west") end print("returnage") return table.concat(directions, ",") end function roadIntersection(xa,ya,za, openDirections) if openDirections == nil then -- Careful with that, it was buggy when I implemented it. commands.getBlockInfo() does some weird shit and will once in a while get stuck in an infinite loop openDirections = roadIntersectionAnalysis(xa,ya,za) if openDirections == "" then print("Error: Couldn't find nearby roads") return false end end fill(slab, xa-6, ya-6, za, 13, 13, 1) -- pavements all around fill(air, xa-3, ya-3, za, 7, 7, 1) -- empty middle square fill(asphalt, xa-6, ya-6, za-1, 13, 13, 1) -- big asphalt square underneath if string.count(openDirections, ",") >= 2 then -- If this is an intersection fill(paint, xa-6, ya-2, za-1, 13, 1, 1) -- painted crosswalks fill(paint, xa-6, ya, za-1, 13, 1, 1) fill(paint, xa-6, ya+2, za-1, 13, 1, 1) fill(paint, xa-2, ya-6, za-1, 1, 13, 1) fill(paint, xa, ya-6, za-1, 1, 13, 1) fill(paint, xa+2, ya-6, za-1, 1, 13, 1) fill(asphalt, xa-3, ya-3, za-1, 7, 7, 1) -- middle asphalt square else -- If this is just a road turn fill(asphalt, xa-3, ya-3, za-1, 7, 7, 1) -- middle asphalt square xMin = 0 xMax = 0 yMin = 0 yMax = 0 if string.find(openDirections, "north") then yMax = 6 end if string.find(openDirections, "south") then yMin = (-6) end if string.find(openDirections, "east") then xMax = 6 end if string.find(openDirections, "west") then xMin = (-6) end for i=xa+xMin,xa+xMax do tryAndPaintThatBlock(i,ya,za-1,"east") end for i=ya+yMin,ya+yMax do tryAndPaintThatBlock(xa,i,za-1,"north") end end if type(openDirections) == "string" then for i in string.gmatch(openDirections, "%a+") do if i=="north" then fill(air, xa-3, ya+4, za, 7, 3, 1) elseif i=="south" then fill(air, xa-3, ya-6, za, 7, 3, 1) elseif i=="east" then fill(air, xa+4, ya-3, za, 3, 7, 1) elseif i=="west" then fill(air, xa-6, ya-3, za, 3, 7, 1) end end end end function clearTerrain(size, height) if height == nil then height = 2 end fill(air, (-0.5)*size,(-0.5)*size,-2,size,size,2) if height > 2 then fill(air, (-0.5)*size,(-0.5)*size,1,size,size,height-3) end fill("minecraft:sandstone", (-0.5)*size,(-0.5)*size,-2,size,size,1) end function oppositeDirectionOf(direction) if direction == "north" then return "south" elseif direction == "south" then return "north" elseif direction == "east" then return "west" elseif direction == "west" then return "east" else return "" end end function roadPathExample(iterations) clearTerrain(80, 10) theFourDirections = {"north", "south", "east", "west"} roads = {} for i=1,iterations do if i>1 then lastRoad = roads[i-1] else lastRoad = {} lastRoad.direction = "north" lastRoad.x = 0 lastRoad.y = 0 lastRoad.z = -1 end thisRoad = {} thisRoad.direction = pickRandom(theFourDirections) while thisRoad.direction == oppositeDirectionOf(lastRoad.direction) do thisRoad.direction = pickRandom(theFourDirections) end thisRoad.length = math.random(18,30) road(lastRoad.x,lastRoad.y,lastRoad.z,thisRoad.direction,thisRoad.length) thisRoad.x = lastRoad.x thisRoad.y = lastRoad.y thisRoad.z = lastRoad.z if thisRoad.direction == "north" then -- north: y+ thisRoad.y = lastRoad.y + thisRoad.length - 7 elseif thisRoad.direction == "south" then -- south: y- thisRoad.y = lastRoad.y - thisRoad.length + 7 elseif thisRoad.direction == "east" then -- east: x+ thisRoad.x = lastRoad.x + thisRoad.length - 7 elseif thisRoad.direction == "west" then -- west: x- thisRoad.x = lastRoad.x - thisRoad.length + 7 end roadIntersection(lastRoad.x, lastRoad.y, lastRoad.z, oppositeDirectionOf(lastRoad.direction)..","..thisRoad.direction) -- print(table.concat(thisRoad, ",")) fill("minecraft:stone", thisRoad.x, thisRoad.y, thisRoad.z,0,0,0) roads[i] = thisRoad sleep(2) end end function detectIntersections(xa,ya) directions = {} if plan:at(xa,ya) == "road" then if plan:at(xa,ya+1) == "road" then table.insert(directions, "north") end if plan:at(xa,ya-1) == "road" then table.insert(directions, "south") end if plan:at(xa+1,ya) == "road" then table.insert(directions, "east") end if plan:at(xa-1,ya) == "road" then table.insert(directions, "west") end if #directions > 1 then directions = table.concat(directions,",") else return "road" end if directions == "north,south" then return "road" elseif directions == "east,west" then return "road" else plan:set(xa,ya,directions,2) return plan:at(xa,ya,2) end else return plan:at(xa,ya) end end function generateCityPlan(size) --This function generates city blocks line by line by performing an algorithm according to what blocks are in the upper line --Generating the first line is different though plan.size = math.floor(size/13) maxBuildingSize = 3 start = 0 x = start while start plan.size then buildingSize = plan.size-(start+1) end for x=start,start+buildingSize-1 do plan:set(x,0,"building") end plan:set(start+buildingSize,0,"road") start = start+buildingSize+1 end --Next lines now --I'm checking a defined set of rules for each block of the plan. -- X = the current chunk -- R = road chunk -- B = building chunk y=0 while y<=plan.size-1 do x=-1 while x<=plan.size-1 do repeat -- so when I do "break" it breaks the repeat and continues the "while" loop. I ended up not using any "breaks" but i'll keep it just in case for modularity's sake. x = x+1 if plan:at(x,y) == nil then if plan:at(x,y-1) == "road" and plan:at(x+1,y-1) == "road" then --X --RR plan:set(x,y,"building") elseif plan:at(x,y-1) == "building" and plan:at(x-1,y-1) == "building" and plan:at(x-2,y-1) == "building" then --X --BBB plan:set(x,y,"road") elseif plan:at(x,y-1) == "road" then -- X -- R rand = math.random(1,2) if rand==1 then plan:set(x,y,"road") plan:set(x+1,y,"road") else plan:set(x,y,"road") end elseif plan:at(x,y-1) == "building" then -- R -- B plan:set(x,y,"building") end end until true end --endWhile y=y+1 end --endWhile --Closing up the city with a building belt for y=0,plan.size-1 do for x=0,plan.size-1 do -- if x<2 or y<2 or y>=plan.size-2 or x>=plan.size-2 then -- plan:set(x,y,"building") -- end print(tostring(x)..","..tostring(y)..":"..detectIntersections(x,y)) end end end function debugPlanBuild() print("Building the plan...") if not plan.size then return end fill(air,1,1,0,plan.size,plan.size,1) print("cleared the area") for i=0,plan.size-1 do for j=0,plan.size-1 do print(plan:at(i,j,2)) if plan:at(i,j,2) == "road" then setBlock("minecraft:obsidian",i+1,j+1,0) elseif plan:at(i,j,2) == "building" then setBlock("minecraft:stone",i+1,j+1,0) else setBlock("minecraft:sponge",i+1,j+1,0) end end end end function roadDirectionAnalysis(xa,ya) northBlock = plan:at(xa,ya+1) southBlock = plan:at(xa,ya-1) eastBlock = plan:at(xa+1,ya) westBlock = plan:at(xa-1,ya) -- print(table.concat({northBlock,southBlock,eastBlock,westBlock},",")) if northBlock == "road" or southBlock == "road" then return "north" end if eastBlock == "road" or westBlock == "road" then return "west" end return false end function planBuild() if not plan.size then return end -- fill(air,1,1,0,plan.size,plan.size,1) for i=0,plan.size-1 do --x for j=0,plan.size-1 do --y xa = 13*(i)+1 ya = 13*(j)+1 if plan:at(i,j,2) == "road" then --fill("minecraft:obsidian",xa,ya,0,13,13,1) direction = roadDirectionAnalysis(i,j) --print(direction) if direction == "north" then --setBlock("minecraft:sponge",xa,ya,0) road(xa+6,ya,0, "north", 13) else --setBlock("minecraft:redstone_block",xa,ya,0) road(xa+12,ya+6,0, "west", 13) end elseif string.find(tostring(plan:at(i,j,2)), ",") then print(plan:at(i,j,2)) roadIntersection(xa+6,ya+6,0,plan:at(i,j,2)) -- fill("minecraft:stone",xa,ya,0,13,13,1) elseif plan:at(i,j,2) == nil then fill("minecraft:sponge",xa,ya,-1,13,13,1) else fill("minecraft:stone",xa,ya,0,13,13,1) end end end --[[ print("Finished first part") for i=0,plan.size do --x for j=0,plan.size do --y xa = 13*(i)+1 ya = 13*(j)+1 if plan:at(i,j) == "intersection" then -- print("prout") fill("minecraft:sponge",xa,ya,-1,13,13,1) roadIntersection(xa+7,ya+7,0) end end end ]]-- end -- END OF THE API PART -- FROM THERE, IT'S JUST SOME RANDOM CODE TO TEST THE API. I HAVE INCLUDED IT JUST SO A COUPLE OF PEOPLE CAN MAYBE ENJOY IT. if activateTheExamples then commands.execAsync("gamerule commandBlockOutput false") term.clear() term.setCursorPos(1,1) print("What test shall I perform ? Pick a number") input = tonumber(io.read()) if input==1 then floor("minecraft:wool:5", "minecraft:wool:14", 0,0,-1,22,22) while true do buildingColor = table.pickRandom(buildingColors) fill(air,1,1,0,40,20,40) term.clear() while randomBuilding(buildingColor, 1,1,0,math.random(4,7)) == false do end sleep(4) end elseif input == 2 then --while true do sleep(2) clearTerrain(32) direction = {} numberOfWays = math.random(2,3) for i=1, numberOfWays do direction[i] = pickRandom(theFourDirections) end print(table.concat(direction, ",")) for i=1,#direction do road(0,0,-1,direction[i],15) end roadIntersection(0,0,-1) --end elseif input == 3 then roadPathExample(10) elseif input == 4 then fill(air, 1,1,0,100,100,3) generateCityPlan(500) debugPlanBuild() elseif input == 5 then size = 256 fill(air,1,1,-1,size+20,size+20,2) generateCityPlan(size) planBuild() else print("Nah, I didn't get it") end end