Sleeping for however long every however many commands should indeed work, but I suspect that the actual values involved would vary depending on the power of the computer running Minecraft. Dunno. There's also a bit of a problem in that sleep() may decide to go forever while commands are running.
I've taken a liking to this kind of structure:
local curCommands, maxCommands = 0, 230
local function doCommand(...)
while curCommands > maxCommands do os.pullEvent("task_complete") end
curCommands = curCommands + 1
commands.execAsync(...)
end
local function regularScript()
-- Your actual script contents go in here, or at least the bits that perform commands.
-- Any time you want to call commands.execAsync(),
-- call doCommand() instead.
end
parallel.waitForAny(regularScript,
function()
while true do
os.pullEvent("task_complete")
curCommands = curCommands - 1
end
end)
Any time you queue a command to be performed, curCommands goes up. Any time a command completes, curCommands goes down. If the queue of commands approaches a dangerous level then doCommand() starts yielding, in such a way that it slows the script down to match the pace Minecraft is actually completing commands at.
Edit:
Another thing you may wish to consider is the handling of your loops.
When the user enters in their co-ords, you aren't checking that x1 < x2, y1 < y2, etc. I suggest checking and sorting these values, as your loops won't run backwards.
On the other hand, you may
want to force the loop running on the y-axis to go backwards. Deleting layers from top to bottom ensures all fluids and sand/gravel get cleared out properly, whereas they may otherwise fall from the upper (yet to be cleared) layers into the lower (supposedly cleared) layers while the script's in action.