local m = peripheral.find "modem" local CHAN = 7101 m.open(CHAN) local ephem_ID = math.random(0, 0xFFFFFFF) local function receive() while true do local _, _, c, rc, ms = os.pullEvent "modem_message" if type(ms) == "table" then return ms end end end local function send(ms) m.transmit(CHAN, CHAN, ms) end local raw_exec_async, pull_event = commands.execAsync, os.pullEvent local tasks = {} local tasks_debug = {} local tasks_count = 0 local tasks_limit = 1000 local half_tasks_limit = tasks_limit / 2 local function exec_async(name, ...) if tasks_count >= tasks_limit then print "task limit reached, blocking" while tasks_count >= half_tasks_limit do pull_event "task_complete" end print "blocking complete" end local id = raw_exec_async(table.concat({name, ...}, " ")) tasks_count = tasks_count + 1 tasks[id] = true tasks_debug[id] = {name, ...} end local function fill(ax, ay, az, bx, by, bz, block) exec_async("fill", ax, ay, az, bx, by, bz, block, 0, "replace") end local env = {} local function add(x) for k, v in pairs(x) do env[k] = v end end add(math) add(bit) add(bit32) env[vector] = vector local function plot(args) print "plotting" parallel.waitForAll(function() local ax, ay, az = unpack(args.f_min) local bx, by, bz = unpack(args.f_max) local rx, ry, rz = (bx-ax), (by-ay), (bz-az) local fn = load(("local x, y, z = ...; return %s"):format(args.equation), "=eqn", "t", math) --[[print "Clearing" for x = args.x_min, args.x_max do end print "Cleared plot area"]] for x = args.x_min, args.x_max do local go = true if args.x_mod and args.x_mod_eq then if x % args.x_mod ~= args.x_mod_eq then go = false end end if go then -- clear thing fill(x, args.y_min, args.z_min, x, args.y_max, args.z_max, "air") for y = args.y_min, args.y_max do local pz = nil for z = args.z_min, args.z_max do local sx, sy, sz = (((x-ax)/rx)*2)-1, (((y-ay)/ry)*2)-1, (((z-az)/rz)*2)-1 --print(sx, sy, sz) local place_here = fn(sx, sy, sz) if place_here and not pz then pz = z elseif pz and not place_here then fill(x, y, pz, x, y, z - 1, args.block) --print(x, y, pz, x, y, z - 1, args.block) pz = nil end end if pz then fill(x, y, pz, x, y, args.z_max, args.block) --print(x, y, pz, x, y, args.z_max, args.block) end end end end end, function() while true do local event, id, success, result, output = pull_event "task_complete" if tasks[id] then tasks_count = tasks_count - 1 tasks[id] = nil if not success then error("thing failed: " .. table.concat(output, " ")) elseif not result and output[1] ~= "No blocks filled" then printError(table.concat(output, " ")) _G.debug_task = tasks_debug[id] end tasks_debug[id] = nil end if tasks_count == 0 then return end end end) return "done" end while true do local ty, arg = unpack(receive()) if ty == "ping" then send { "pong", ephem_ID } elseif ty == "plot" and arg.id == ephem_ID then print("plot command received, running", arg.x_min, arg.x_max) local ok, err = pcall(plot, arg) print(err) send { "response", { id = ephem_ID, response = err } } end end