View difference between Paste ID: w3gwbP5R and dbeFxjwf
SHOW: | | - or go back to the newest paste.
1-
local pkg = {[".Firewolf_Data"]={["server_software"]="!@#&--  !@#&--  Firewolf Server Software!@#&--  Created By GravityScore and 1lann!@#&--  License found here: https://raw.github.com/1lann/Firewolf/master/LICENSE  !@#&--!@#&--  Orignal Idea from RednetExplorer 2.4.1!@#&--  RednetExplorer Made by ComputerCraftFan11!@#&--  !@#&!@#&!@#&--  -------- Variables!@#&!@#&-- Version!@#&local version = \"2.5\"!@#&local serverID = \"release\"!@#&!@#&-- Prevent Control-T!@#&os.pullEvent = os.pullEventRaw!@#&!@#&-- Updating!@#&local autoupdate = true!@#&!@#&-- Responding!@#&local enableSearch = true!@#&local enableResponse = true!@#&local enableRecording = true!@#&!@#&-- Download URLs!@#&local serverURL = \"https://raw.github.com/1lann/firewolf/master/server/server-\" .. serverID .. \".lua\"!@#&!@#&-- Events!@#&local event_stopServer = \"firewolf_stopServerEvent\"!@#&!@#&-- Statistics!@#&local searches = 0!@#&local visits = 0!@#&!@#&-- Theme!@#&local theme = {}!@#&!@#&-- Databases!@#&local ignoreDatabase = {}!@#&local permantentIgnoreDatabase = {}!@#&local suspected = {}!@#&!@#&-- Server!@#&local w, h = term.getSize()!@#&local args = {...}!@#&local website = \"\"!@#&local dataLocation = \"\"!@#&local pages = {}!@#&local totalRecordLines = {}!@#&local recordLines = {}!@#&local serverPassword = nil!@#&local serverLocked = false!@#&!@#&-- Locations!@#&local rootFolder = \"/.Firewolf_Data\"!@#&local serverFolder = rootFolder .. \"/servers\"!@#&local statsLocation = rootFolder .. \"/\" .. website .. \"_stats\"!@#&local themeLocation = rootFolder .. \"/theme\"!@#&local defaultThemeLocation = rootFolder .. \"/default_theme\"!@#&local passwordDataLocation = rootFolder .. \"/.\" .. website .. \"_password\"!@#&local serverLocation = \"/\" .. shell.getRunningProgram()!@#&!@#&-- Parse Arguments!@#&if #args >= 2 then!@#&	website = args[1]:gsub(\"^%s*(.-)%s*$\", \"%1\")!@#&	dataLocation = args[2]:gsub(\"^%s*(.-)%s*$\", \"%1\")!@#&	statsLocation = rootFolder .. \"/\" .. website .. \"_stats\"!@#&	passwordDataLocation = rootFolder .. \"/.\" .. website .. \"_password\"!@#&else!@#&	print(\"Invalid Arguments! D:\")!@#&	error()!@#&end!@#&!@#&!@#&--  -------- Utility Functions!@#&!@#&local function isAdvanced()!@#&	if term.isColor then return term.isColor()!@#&	else return false end!@#&end!@#&!@#&local function oldPullEvent(ex)!@#&	local event, p1, p2, p3, p4, p5 = os.pullEventRaw(ex)!@#&	if event == \"terminate\" then!@#&		print(\"Terminated\")!@#&		error()!@#&	else!@#&		return event, p1, p2, p3, p4, p5!@#&	end!@#&end!@#&!@#&--  Drawing!@#&!@#&local function printWithType(t, func)!@#&	if type(t) == \"table\" then!@#&		for _, v in pairs(t) do env.pcall(function() printWithType(v, func) end) end!@#&	else func(tostring(t)) end!@#&end!@#&!@#&local function centerWrite(text)!@#&	printWithType(text, function(t)!@#&		local x, y = term.getCursorPos()!@#&		term.setCursorPos(math.ceil((w + 1)/2 - t:len()/2), y)!@#&		write(t)!@#&	end)!@#&end!@#&!@#&local function centerPrint(text)!@#&	printWithType(text, function(t)!@#&		local x, y = term.getCursorPos()!@#&		term.setCursorPos(math.ceil((w + 2)/2 - t:len()/2), y)!@#&		print(t)!@#&	end)!@#&end!@#&!@#&local function leftPrint(text)!@#&	printWithType(text, function(t)!@#&		local x, y = term.getCursorPos()!@#&		term.setCursorPos(1, y)!@#&		print(t)!@#&	end)!@#&end!@#&!@#&local function rightPrint(text)!@#&	printWithType(text, function(t)!@#&		local x, y = term.getCursorPos()!@#&		term.setCursorPos(w - t:len() + 1, y)!@#&		print(t)!@#&	end)!@#&end!@#&!@#&local function clearPage(r)!@#&	-- Site title!@#&	title = \"Hosting: rdnt://\" .. website!@#&!@#&	-- Address Bar!@#&	term.setTextColor(colors[theme[\"address-bar-text\"]])!@#&	term.setCursorPos(2, 1)!@#&	term.setBackgroundColor(colors[theme[\"address-bar-background\"]])!@#&	term.clearLine()!@#&	term.setCursorPos(2, 1)!@#&	if title:len() > 42 then title = title:sub(1, 39) .. \"...\" end!@#&	write(title)!@#&!@#&	-- Records!@#&	term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&	for i = 1, 11 do!@#&		term.setCursorPos(1, i + 7) !@#&		centerWrite(string.rep(\" \", 47)) !@#&	end!@#&	if r == true then!@#&		for i, v in ipairs(recordLines) do!@#&			term.setCursorPos(5, i + 8)!@#&			write(v)!@#&		end!@#&	end!@#&!@#&	term.setBackgroundColor(colors.black)!@#&	term.setTextColor(colors.white)!@#&	print(\"\")!@#&end!@#&!@#&!@#&--  Prompt!@#&!@#&local function prompt(list)!@#&	if isAdvanced() then!@#&		for _, v in pairs(list) do!@#&			if v.bg then term.setBackgroundColor(v.bg) end!@#&			if v.tc then term.setTextColor(v.tc) end!@#&			if v[2] == -1 then v[2] = math.ceil((w + 1)/2 - (v[1]:len() + 6)/2) end!@#&!@#&			term.setCursorPos(v[2], v[3])!@#&			write(\"[- \" .. v[1])!@#&			term.setCursorPos(v[2] + v[1]:len() + 3, v[3])!@#&			write(\" -]\")!@#&		end!@#&!@#&		while true do!@#&			local e, but, x, y = os.pullEvent()!@#&			if e == \"mouse_click\" then!@#&				for _, v in pairs(list) do!@#&					if x >= v[2] and x <= v[2] + v[1]:len() + 5 and y == v[3] then!@#&						return v[1]!@#&					end!@#&				end!@#&			end!@#&		end!@#&	else!@#&		for _, v in pairs(list) do!@#&			term.setBackgroundColor(colors.black)!@#&			term.setTextColor(colors.white)!@#&			if v[2] == -1 then v[2] = math.ceil((w + 1)/2 - (v[1]:len() + 4)/2) end!@#&!@#&			term.setCursorPos(v[2], v[3])!@#&			write(\"  \" .. v[1])!@#&			term.setCursorPos(v[2] + v[1]:len() + 2, v[3])!@#&			write(\"  \")!@#&		end!@#&!@#&		local key1 = dir == \"horizontal\" and 203 or 200!@#&		local key2 = dir == \"horizontal\" and 205 or 208!@#&!@#&		local curSel = 1!@#&		term.setCursorPos(list[curSel][2], list[curSel][3])!@#&		write(\"[\")!@#&		term.setCursorPos(list[curSel][2] + list[curSel][1]:len() + 3, list[curSel][3])!@#&		write(\"]\")!@#&		while true do!@#&			local e, key = os.pullEvent()!@#&			term.setCursorPos(list[curSel][2], list[curSel][3])!@#&			write(\" \")!@#&			term.setCursorPos(list[curSel][2] + list[curSel][1]:len() + 3, list[curSel][3])!@#&			write(\" \")!@#&			if e == \"key\" and key == key1 and curSel > 1 then!@#&				curSel = curSel - 1!@#&			elseif e == \"key\" and key == key2 and curSel < #list then!@#&				curSel = curSel + 1!@#&			elseif e == \"key\" and key == 28 then!@#&				return list[curSel][1]!@#&			end!@#&			term.setCursorPos(list[curSel][2], list[curSel][3])!@#&			write(\"[\")!@#&			term.setCursorPos(list[curSel][2] + list[curSel][1]:len() + 3, list[curSel][3])!@#&			write(\"]\")!@#&		end!@#&	end!@#&end!@#&!@#&local function scrollingPrompt(list, x, y, len, width)!@#&	local wid = width!@#&	if wid == nil then wid = w - 3 end!@#&!@#&	local function updateDisplayList(items, loc, len)!@#&		local ret = {}!@#&		for i = 1, len do!@#&			local item = items[i + loc - 1]!@#&			if item ~= nil then table.insert(ret, item) end!@#&		end!@#&		return ret!@#&	end!@#&!@#&	if isAdvanced() then!@#&		local function draw(a)!@#&			for i, v in ipairs(a) do!@#&				term.setCursorPos(x, y + i - 1)!@#&				write(string.rep(\" \", wid))!@#&				term.setCursorPos(x, y + i - 1)!@#&				write(\"[ \" .. v:sub(1, wid - 5))!@#&				term.setCursorPos(wid + x - 2, y + i - 1)!@#&				write(\"  ]\")!@#&			end!@#&		end!@#&!@#&		local loc = 1!@#&		local disList = updateDisplayList(list, loc, len)!@#&		draw(disList)!@#&		!@#&		while true do!@#&			local e, but, clx, cly = os.pullEvent()!@#&			if e == \"key\" and but == 200 and loc > 1 then!@#&				loc = loc - 1!@#&				disList = updateDisplayList(list, loc, len)!@#&				draw(disList)!@#&			elseif e == \"key\" and but == 208 and loc + len - 1 < #list then!@#&				loc = loc + 1!@#&				disList = updateDisplayList(list, loc, len)!@#&				draw(disList)!@#&			elseif e == \"mouse_scroll\" and but > 0 and loc + len - 1 < #list then!@#&				loc = loc + but!@#&				disList = updateDisplayList(list, loc, len)!@#&				draw(disList)!@#&			elseif e == \"mouse_scroll\" and but < 0 and loc > 1 then!@#&				loc = loc + but!@#&				disList = updateDisplayList(list, loc, len)!@#&				draw(disList)!@#&			elseif e == \"mouse_click\" then!@#&				for i, v in ipairs(disList) do!@#&					if clx >= x and clx <= x + wid and cly == i + y - 1 then!@#&						return v!@#&					end!@#&				end!@#&			end!@#&		end!@#&	else!@#&		local function draw(a)!@#&			for i, v in ipairs(a) do!@#&				term.setCursorPos(x, y + i - 1)!@#&				write(string.rep(\" \", wid))!@#&				term.setCursorPos(x, y + i - 1)!@#&				write(\"[ ] \" .. v:sub(1, wid - 5))!@#&			end!@#&		end!@#&!@#&		local loc = 1!@#&		local curSel = 1!@#&		local disList = updateDisplayList(list, loc, len)!@#&		draw(disList)!@#&		term.setCursorPos(x + 1, y + curSel - 1)!@#&		write(\"x\")!@#&!@#&		while true do!@#&			local e, key = os.pullEvent()!@#&			term.setCursorPos(x + 1, y + curSel - 1)!@#&			write(\" \")!@#&			if e == \"key\" and key == 200 then!@#&				if curSel > 1 then!@#&					curSel = curSel - 1!@#&				elseif loc > 1 then!@#&					loc = loc - 1!@#&					disList = updateDisplayList(list, loc, len)!@#&					draw(disList)!@#&				end!@#&			elseif e == \"key\" and key == 208 then!@#&				if curSel < #disList then!@#&					curSel = curSel + 1!@#&				elseif loc + len - 1 < #list then!@#&					loc = loc + 1!@#&					disList = updateDisplayList(list, loc, len)!@#&					draw(disList)!@#&				end!@#&			elseif e == \"key\" and key == 28 then!@#&				return list[curSel + loc - 1]!@#&			end!@#&			term.setCursorPos(x + 1, y + curSel - 1)!@#&			write(\"x\")!@#&		end!@#&	end!@#&end!@#&!@#&!@#&--  -------- Themes!@#&!@#&local defaultTheme = {!@#&	[\"address-bar-text\"] = \"white\",!@#&	[\"address-bar-background\"] = \"gray\",!@#&	[\"address-bar-base\"] = \"lightGray\",!@#&	[\"top-box\"] = \"red\",!@#&	[\"bottom-box\"] = \"orange\",!@#&	[\"text-color\"] = \"white\",!@#&	[\"background\"] = \"gray\"!@#&} local originalTheme = {!@#&	[\"address-bar-text\"] = \"white\",!@#&	[\"address-bar-background\"] = \"black\",!@#&	[\"address-bar-base\"] = \"black\",!@#&	[\"top-box\"] = \"black\",!@#&	[\"bottom-box\"] = \"black\",!@#&	[\"text-color\"] = \"white\",!@#&	[\"background\"] = \"black\"!@#&}!@#&!@#&local function loadTheme(path)!@#&	if fs.exists(path) and not fs.isDir(path) then!@#&		local a = {}!@#&		local f = io.open(path, \"r\")!@#&		local l = f:read(\"*l\")!@#&		while l do!@#&			l = l:gsub(\"^%s*(.-)%s*$\", \"%1\")!@#&			if l and l ~= \"\" and l ~= \"\\n\" and l:sub(1, 2) ~= \"--\" then!@#&				local k, v = string.match(l, \"^(%a+)=(%a+)\")!@#&				if k and v then a[k] = v!@#&				else return nil end!@#&			end!@#&			l = f:read(\"*l\")!@#&		end!@#&		f:close()!@#&		return a!@#&	end!@#&end!@#&!@#&!@#&--  -------- Filesystem!@#&!@#&local function download(url, path)!@#&	for i = 1, 3 do!@#&		local response = http.get(url)!@#&		if response then!@#&			local data = response.readAll()!@#&			response.close()!@#&			local f = io.open(path, \"w\")!@#&			f:write(data)!@#&			f:close()!@#&			return true!@#&		end!@#&	end!@#&!@#&	return false!@#&end!@#&!@#&local function validateFilesystem()!@#&	if not fs.exists(rootFolder) or not fs.exists(serverFolder) or not fs.exists(dataLocation) or!@#&			not fs.exists(serverLocation) or not fs.exists(dataLocation .. \"/home\") then!@#&		term.setBackgroundColor(colors[theme[\"background\"]])!@#&		term.setTextColor(colors[theme[\"text-color\"]])!@#&		term.clear()!@#&		term.setCursorPos(1, 1)!@#&		print(\"\")!@#&		term.setTextColor(colors[theme[\"text-color\"]])!@#&		term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&		centerPrint(string.rep(\" \", 47))!@#&		centerWrite(string.rep(\" \", 47))!@#&		centerPrint(\"Invalid Filesystem!\")!@#&		centerPrint(string.rep(\" \", 47))!@#&		print(\"\")!@#&!@#&		term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&		centerPrint(string.rep(\" \", 47))!@#&		centerPrint(\"  The files required to run this server        \")!@#&		centerPrint(\"  cannot be found! Run Firewolf to create      \")!@#&		centerPrint(\"  them!                                        \")!@#&		centerPrint(string.rep(\" \", 47))!@#&		centerWrite(string.rep(\" \", 47))!@#&		if isAdvanced() then centerPrint(\"Click to exit...\")!@#&		else centerPrint(\"Press any key to exit...\") end!@#&		centerPrint(string.rep(\" \", 47))!@#&!@#&		while true do!@#&			local e = os.pullEvent()!@#&			if e == \"key\" or e == \"mouse_click\" then break end!@#&		end!@#&!@#&		return false!@#&	else!@#&		return true!@#&	end!@#&end!@#&!@#&local function updateClient()!@#&	local updateLocation = rootFolder .. \"/server-update\"!@#&	fs.delete(updateLocation)!@#&!@#&	download(serverURL, updateLocation)!@#&	local a = io.open(updateLocation, \"r\")!@#&	local b = io.open(serverLocation, \"r\")!@#&	local new = a:read(\"*a\")!@#&	local cur = b:read(\"*a\")!@#&	a:close()!@#&	b:close()!@#&!@#&	if cur ~= new then!@#&		fs.delete(serverLocation)!@#&		fs.move(updateLocation, serverLocation)!@#&		shell.run(serverLocation, args[1], args[2])!@#&		error()!@#&	else!@#&		fs.delete(updateLocation)!@#&	end!@#&end!@#&!@#&!@#&--  -------- Loading!@#&!@#&local serverAPIContent = [[!@#&!@#&--  !@#&--  Custom Server API!@#&--  !@#&!@#&-- Notes:!@#&-- - These functions are called when events occur!@#&-- - Their names are required to be kept the same!@#&-- - These functions must be able to execute!@#&--   instantly, else your server may be DDoS-able!@#&!@#&!@#&uponSuccessfulRequest = function(page, id)!@#&	-- Called when a request for a page is successful!@#&!@#&	-- Your Code Here...!@#&end!@#&!@#&uponFailedRequest = function(page, id)!@#&	-- Called when a request for a page is unsuccessful!@#&!@#&	-- Your Code Here...!@#&end!@#&!@#&uponAnyOtherMessage = function(message, id)!@#&	-- Called when any rendet message is received!@#&	-- that is not requesting a page!@#&!@#&	-- Your Code Here...!@#&end!@#&!@#&uponAnyMessage = function(message, id)!@#&	-- Called when any rednet message is received!@#&!@#&	-- Your Code Here...!@#&end!@#&!@#&parallelWithServer = function()!@#&	-- Runs in a parallel alongside the server!@#&!@#&	-- Your Code Here...!@#&end!@#&!@#&local function uponServerApiLoad()!@#&	-- Called when this Server API is loaded!@#&!@#&	-- Your Code Here...!@#&end!@#&!@#&uponServerApiLoad()!@#&!@#&]]!@#&!@#&local function loadServerAPI()!@#&	if not fs.exists(dataLocation .. \"/serverapi\") then!@#&		local f = io.open(dataLocation .. \"/serverapi\", \"w\")!@#&		f:write(serverAPIContent)!@#&		f:close()!@#&	end!@#&!@#&	shell.run(dataLocation .. \"/serverapi\")!@#&	if type(uponSuccessfulRequest) ~= \"function\" then!@#&		uponSuccessfulRequest = nil!@#&	end if type(uponFailedRequest) ~= \"function\" then!@#&		uponFailedRequest = nil!@#&	end if type(uponAnyOtherMessage) ~= \"function\" then!@#&		uponAnyOtherMessage = nil!@#&	end if type(uponAnyMessage) ~= \"function\" then!@#&		uponAnyMessage = nil!@#&	end if type(parallelWithServer) ~= \"function\" then!@#&		parallelWithServer = nil!@#&	end!@#&end!@#&!@#&local function loadPages(loc)!@#&	local a = fs.list(loc)!@#&	local p = {}!@#&	for i = 1, #a do!@#&		if not fs.isDir(loc .. \"/\" .. a[i]) then!@#&			local f = io.open(loc .. \"/\" .. a[i])!@#&			local cont = f:read(\"*a\")!@#&			f:close()!@#&!@#&			p[loc .. \"/\" .. a[i]] = cont!@#&		else!@#&			local b = loadPages(loc .. \"/\" .. a[i])!@#&			for x = 1, #b do!@#&				table.insert(p, b[x])!@#&			end!@#&		end!@#&	end!@#&!@#&	return p!@#&end!@#&!@#&local function checkForModem()!@#&	while true do!@#&		local present = false!@#&		for _, v in pairs(rs.getSides()) do!@#&			if peripheral.getType(v) == \"modem\" then!@#&				rednet.open(v)!@#&				present = true!@#&				break!@#&			end!@#&		end!@#&!@#&		if not present then!@#&			term.setTextColor(colors[theme[\"text-color\"]])!@#&			term.setBackgroundColor(colors[theme[\"background\"]])!@#&			term.clear()!@#&			term.setCursorPos(1, 2)!@#&			print(\"\")!@#&			term.setTextColor(colors[theme[\"text-color\"]])!@#&			term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&			centerPrint(string.rep(\" \", 43))!@#&			centerWrite(string.rep(\" \", 43))!@#&			centerPrint(\"No Modem Attached! D:\")!@#&			centerPrint(string.rep(\" \", 43))!@#&			print(\"\")!@#&!@#&			term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&			centerPrint(string.rep(\" \", 43))!@#&			centerWrite(string.rep(\" \", 43))!@#&			centerPrint(\"No wireless modem was found on this\")!@#&			centerWrite(string.rep(\" \", 43))!@#&			centerPrint(\"computer, and Firewolf is not able to\")!@#&			centerWrite(string.rep(\" \", 43))!@#&			centerPrint(\"run without one!\")!@#&			centerPrint(string.rep(\" \", 43))!@#&			centerWrite(string.rep(\" \", 43))!@#&			centerPrint(\"Waiting for a modem to be attached...\")!@#&			centerWrite(string.rep(\" \", 43))!@#&			if isAdvanced() then centerPrint(\"Click to exit...\")!@#&			else centerPrint(\"Press any key to exit...\") end!@#&			centerPrint(string.rep(\" \", 43))!@#&!@#&			while true do!@#&				local e, id = os.pullEvent()!@#&				if e == \"key\" or e == \"mouse_click\" then return false!@#&				elseif e == \"peripheral\" then break end!@#&			end!@#&		else!@#&			return true!@#&		end!@#&	end!@#&end!@#&!@#&!@#&--  -------- Respond to Messages!@#&!@#&local i = 1!@#&local function record(text)!@#&	local oldX, oldY = term.getCursorPos()!@#&	local a = tostring(i) .. \":\" .. string.rep(\" \", 4 - tostring(i):len()) .. text!@#&	table.insert(totalRecordLines, a)!@#&	if #recordLines > 8 then table.remove(recordLines, 1) end!@#&	table.insert(recordLines, a)!@#&!@#&	if enableRecording then clearPage(true) end!@#&	i = i + 1!@#&	term.setCursorPos(oldX, oldY)!@#&	if enableRecording then!@#&	term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&	term.setTextColor(colors[theme[\"text-color\"]])!@#&	end!@#&end!@#&!@#&local function respondToEvents()!@#&	if uponSuccessfulRequest == nil or uponFailedRequest == nil or uponAnyMessage == nil or !@#&			uponAnyOtherMessage == nil or parallelWithServer == nil then!@#&		record(\"Warning - Failed To Load Server API:\")!@#&		if uponSuccessfulRequest == nil then record(\" - uponSuccessfulRequest()\") end!@#&		if uponFailedRequest == nil then record(\" - uponFailedRequest()\") end!@#&		if uponAnyMessage == nil then record(\" - uponAnyMessage()\") end!@#&		if uponAnyOtherMessage == nil then record(\" - uponAnyOtherMessage()\") end!@#&		if parallelWithServer == nil then record(\" - parallelWithServer()\") end!@#&	else record(\"Loaded Server API\") end!@#&!@#&	local writingClock = os.clock()!@#&	local ignoreClock = os.clock()!@#&	while true do!@#&		if os.clock() - ignoreClock < 6 then!@#&			for k, v in pairs(suspected) do!@#&				if v > 10 then table.insert(ignoreDatabase, tostring(k)) end!@#&			end!@#&		else!@#&			ignoreDatabase = {}!@#&			suspected = {}!@#&			ignoreClock = os.clock()!@#&		end!@#&!@#&		local e, id, mes = os.pullEvent()!@#&!@#&		local ignore = false!@#&		for _, v in pairs(ignoreDatabase) do!@#&			if tostring(id) == v then ignore = true break end!@#&		end for _, v in pairs(permantentIgnoreDatabase) do!@#&			if tostring(id) == v then ignore = true break end!@#&		end!@#&!@#&		if e == \"rednet_message\" and enableResponse == true and not ignore then!@#&			if mes == website or mes == website .. \"/\" or mes == website .. \"/home\" then!@#&				if suspected[tostring(id)] then suspected[tostring(id)] = suspected[tostring(id)] + 1!@#&				else suspected[tostring(id)] = 1 end!@#&				for i = 1, 3 do rednet.send(id, pages[dataLocation .. \"/home\"]) end!@#&				record(\"/home : \" .. tostring(id))!@#&				visits = visits + 1!@#&!@#&				if uponSuccessfulRequest ~= nil then uponSuccessfulRequest(\"/home\", id) end!@#&			elseif mes:find(\"/\") then!@#&				local a = mes:sub(1, mes:find(\"/\") - 1)!@#&				if a == website then!@#&					if suspected[tostring(id)] then !@#&						suspected[tostring(id)] = suspected[tostring(id)] + 1!@#&					else suspected[tostring(id)] = 1 end!@#&					local b = mes:sub(mes:find(\"/\"), -1)!@#&					local c = b!@#&					if c:len() > 18 then c = c:sub(1, 15) .. \"...\" end!@#&					if pages[dataLocation .. b] and b ~= \"/serverapi\" then!@#&						for i = 1, 3 do rednet.send(id, pages[dataLocation .. b]) end!@#&						record(c .. \" : \" .. id)!@#&						visits = visits + 1!@#&!@#&						if uponSuccessfulRequest ~= nil then uponSuccessfulRequest(b, id) end!@#&					else!@#&						record(\"Failed - \" .. c .. \" : \" .. id)!@#&						if uponFailedRequest ~= nil then uponFailedRequest(b, id) end!@#&					end!@#&				end!@#&			elseif mes == \"firewolf.broadcast.dns.list\" then!@#&				if suspected[tostring(id)] then suspected[tostring(id)] = suspected[tostring(id)] + 1!@#&				else suspected[tostring(id)] = 1 end!@#&				rednet.send(id, \"firewolf-site:\" .. website)!@#&				searches = searches + 1!@#&			else!@#&				if uponAnyOtherMessage ~= nil then uponAnyOtherMessage(mes, id) end!@#&			end!@#&!@#&			if uponAnyMessage ~= nil then uponAnyMessage(mes, id) end!@#&		elseif e == event_stopServer then!@#&			return!@#&		end!@#&!@#&		-- Save stats!@#&		if os.clock() - writingClock > 5 then!@#&			local f = io.open(statsLocation, \"w\")!@#&			f:write(tostring(visits) .. \"\\n\" .. tostring(searches) .. \"\\n\" ..!@#&				textutils.serialize(permantentIgnoreDatabase))!@#&			f:close()!@#&			writingClock = os.clock()!@#&		end!@#&	end!@#&end!@#&!@#&!@#&--  -------- GUI!@#&!@#&local function edit()!@#&	openAddressBar = false!@#&	local oldLoc = shell.dir()!@#&	local commandHis = {}!@#&	local dir = dataLocation!@#&	term.setBackgroundColor(colors.black)!@#&	term.setTextColor(colors.white)!@#&	term.clear()!@#&	term.setCursorPos(1, 1)!@#&	print(\"\")!@#&	print(\" Server Shell Editing\")!@#&	print(\" Type 'exit' to return to Firewolf.\")!@#&	print(\" The 'home' file is the index of your site\")!@#&	print(\"\")!@#&!@#&	local allowed = {\"move\", \"mv\", \"cp\", \"copy\", \"drive\", \"delete\", \"rm\", \"edit\", !@#&		\"eject\", \"exit\", \"help\", \"id\", \"monitor\", \"rename\", \"alias\", \"clear\",!@#&		\"paint\", \"firewolf\", \"lua\", \"redstone\", \"rs\", \"redprobe\", \"redpulse\", \"programs\",!@#&		\"redset\", \"reboot\", \"hello\", \"label\", \"list\", \"ls\", \"easter\", \"pastebin\", \"dir\"}!@#&	!@#&	while true do!@#&		shell.setDir(serverFolder .. \"/\" .. website)!@#&		term.setBackgroundColor(colors.black)!@#&		if isAdvanced() then term.setTextColor(colors.yellow)!@#&		else term.setTextColor(colors.white) end!@#&		write(\"> \")!@#&		term.setTextColor(colors.white)!@#&		local line = read(nil, commandHis)!@#&		table.insert(commandHis, line)!@#&!@#&		local words = {}!@#&		for m in string.gmatch(line, \"[^ \\t]+\") do!@#&			local a = m:gsub(\"^%s*(.-)%s*$\", \"%1\")!@#&			table.insert(words, a)!@#&		end!@#&!@#&		local com = words[1]!@#&		if com == \"exit\" then!@#&			break!@#&		elseif com then!@#&			local a = false!@#&			for _, v in pairs(allowed) do!@#&				if com == v then a = true break end!@#&			end!@#&!@#&			if a then!@#&				term.setBackgroundColor(colors.black)!@#&				term.setTextColor(colors.white)!@#&				shell.run(com, unpack(words, 2))!@#&			else!@#&				term.setTextColor(colors.red)!@#&				print(\"Program Not Allowed!\")!@#&			end!@#&		end!@#&	end!@#&	shell.setDir(oldLoc)!@#&end!@#&!@#&local function addLock()!@#&	clearPage()!@#&	term.setCursorPos(1, 8)!@#&	term.setTextColor(colors[theme[\"text-color\"]])!@#&	term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&	for i = 1, 11 do centerPrint(string.rep(\" \", 47)) end!@#&	term.setCursorPos(5, 9)!@#&	write(\"Enter a password to secure your\")!@#&	term.setCursorPos(5, 10)!@#&	write(\"server from being managed by others:\")!@#&	term.setCursorPos(5, 11)!@#&	write(\"> \")!@#&	local newPassword = read(\"*\")!@#&	if newPassword == \"\" then return end!@#&	term.setCursorPos(5, 13)!@#&	write(\"Enter the password again:\")!@#&	term.setCursorPos(5, 14)!@#&	write(\"> \")!@#&	local pass2 = read(\"*\")!@#&	if pass2 == \"\" then return!@#&	elseif pass2 == newPassword then!@#&		serverPassword = newPassword!@#&		serverLocked = false!@#&		local f = io.open(passwordDataLocation, \"w\")!@#&		f:write(newPassword)!@#&		f:close()!@#&		term.setCursorPos(5, 16)!@#&		write(\"Password Set!\")!@#&		sleep(1.3)!@#&	else!@#&		term.setCursorPos(5, 16)!@#&		print(\"Passwords did not match!\")!@#&		sleep(1.3)!@#&	end!@#&end!@#&!@#&local function manageServer()!@#&	while true do!@#&		clearPage()!@#&		term.setCursorPos(1, 8)!@#&		term.setTextColor(colors[theme[\"text-color\"]])!@#&		term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&		for i = 1, 11 do centerPrint(string.rep(\" \", 47)) end!@#&!@#&		term.setCursorPos(5, 9)!@#&		write(\"Visits: \" .. tostring(visits))!@#&		term.setCursorPos(5, 10)!@#&		write(\"Searches: \" .. tostring(searches))!@#&		local opt = \"\"!@#&		if serverPassword then!@#&			opt = prompt({{\"Manage Blocked IDs\", 9, 12}, {\"Remove Password\", 9, 13}, !@#&				{\"Delete Server\", 9, 14}, {\"Back\", 9, 16}}, \"vertical\")!@#&		else!@#&			opt = prompt({{\"Manage Blocked IDs\", 9, 12}, {\"Delete Server\", 9, 13}, !@#&				{\"Back\", 9, 15}}, \"vertical\")!@#&		end!@#&		if opt == \"Manage Blocked IDs\" then!@#&			while true do!@#&				clearPage()!@#&				term.setCursorPos(1, 8)!@#&				term.setTextColor(colors[theme[\"text-color\"]])!@#&				term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&				for i = 1, 11 do centerPrint(string.rep(\" \", 47)) end!@#&!@#&				term.setCursorPos(5, 9)!@#&				if isAdvanced() then write(\"Blocked IDs: (Click to Unblock)\")!@#&				else write(\"Blocked IDs: (Select to Unblock)\") end!@#&				local a = {\"Back\", \"Block New ID\"}!@#&				for _, v in pairs(permantentIgnoreDatabase) do!@#&					table.insert(a, v)!@#&				end!@#&!@#&				local b = scrollingPrompt(a, 5, 11, 7, 43)!@#&				if b == \"Back\" then!@#&					break!@#&				elseif b == \"Block New ID\" then!@#&					term.setCursorPos(5, 10)!@#&					write(\"ID: \")!@#&					local c = read():gsub(\"^%s*(.-)%s*$\", \"%1\")!@#&					local d = tonumber(c)!@#&					local found = false!@#&					for k, v in pairs(permantentIgnoreDatabase) do!@#&						if v == tostring(d) then found = true break end!@#&					end!@#&					if d == nil then!@#&						term.setCursorPos(1, 10)!@#&						centerWrite(string.rep(\" \", 47))!@#&						term.setCursorPos(5, 10)!@#&						write(\"Not a Valid ID!\")!@#&						sleep(1.1)!@#&					elseif found == true then!@#&						term.setCursorPos(1, 10)!@#&						centerWrite(string.rep(\" \", 47))!@#&						term.setCursorPos(5, 10)!@#&						write(\"ID Already Exists!\")!@#&						sleep(1.1)!@#&					else!@#&						term.setCursorPos(1, 10)!@#&						centerWrite(string.rep(\" \", 47))!@#&						term.setCursorPos(5, 10)!@#&						write(\"Blocked ID: \" .. c .. \"!\")!@#&						table.insert(permantentIgnoreDatabase, tostring(d))!@#&						sleep(1.1)!@#&					end!@#&				else!@#&					for i, v in ipairs(permantentIgnoreDatabase) do!@#&						if v == b then table.remove(permantentIgnoreDatabase, i) end!@#&					end!@#&				end!@#&			end!@#&		elseif opt == \"Delete Server\" then!@#&			clearPage()!@#&			term.setCursorPos(1, 8)!@#&			term.setTextColor(colors[theme[\"text-color\"]])!@#&			term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&			for i = 1, 11 do centerPrint(string.rep(\" \", 47)) end!@#&			term.setCursorPos(9, 11)!@#&			centerPrint(\"Are you sure you want to delete the server?\")!@#&			centerPrint(\"This cannot be undone!\")!@#&			local opt = prompt({{\"No\", 11, 14}, {\"Yes\", 35, 14}}, \"horizontal\")!@#&			if opt == \"Yes\" then!@#&				fs.delete(dataLocation)!@#&				os.queueEvent(event_stopServer)!@#&				return!@#&			end!@#&		elseif opt == \"Remove Password\" then!@#&			clearPage()!@#&			term.setCursorPos(1, 8)!@#&			term.setTextColor(colors[theme[\"text-color\"]])!@#&			term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&			for i = 1, 11 do centerPrint(string.rep(\" \", 47)) end!@#&			term.setCursorPos(9, 11)!@#&			print(\"Enter your password:\")!@#&			term.setCursorPos(9, 12)!@#&			write(\"> \")!@#&			local oldPass = read(\"*\")!@#&			if oldPass == \"\" then!@#&			elseif oldPass == serverPassword then!@#&				fs.delete(passwordDataLocation)!@#&				serverPassword = nil!@#&				serverLocked = false!@#&				term.setCursorPos(9, 14)!@#&				print(\"Password Removed!\")!@#&				sleep(1.3)!@#&				break!@#&			else!@#&				term.setCursorPos(9, 14)!@#&				print(\"Password Incorrect! Locking Server...\")!@#&				os.pullEvent = os.pullEventRaw!@#&				serverLocked = true!@#&				sleep(1.3)!@#&				break!@#&			end!@#&		elseif opt == \"Back\" then!@#&			break!@#&		end!@#&	end!@#&end!@#&!@#&local function interface()!@#&	local opt = \"\"!@#&	while true do!@#&		term.setBackgroundColor(colors[theme[\"background\"]])!@#&		term.setTextColor(colors[theme[\"text-color\"]])!@#&		term.clear()!@#&		term.setCursorPos(1, 1)!@#&		clearPage(true)!@#&		term.setCursorPos(1, 2)!@#&		print(\"\")!@#&		term.setTextColor(colors[theme[\"text-color\"]])!@#&		term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&		for i = 1, 4 do centerPrint(string.rep(\" \", 47)) end!@#&		print(\"\")!@#&		term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&!@#&		if enableResponse == false then p1 = \"Unpause Server\" end!@#&		term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&		if not serverLocked and not serverPassword then!@#&			os.pullEvent = oldPullEvent!@#&			opt = prompt({{\"Add Lock\", 5, 4}, {\"Edit\", 5, 5}, {\"Manage\", w - 15, 4}, !@#&				{\"Stop\", w - 13, 5}}, \"vertical\")!@#&		elseif not serverLocked and serverPassword then!@#&			opt = prompt({{\"Lock Server\", 5, 4}, {\"Edit\", 5, 5}, {\"Manage\", w - 15, 4}, !@#&				{\"Stop\", w - 13, 5}}, \"vertical\")!@#&		elseif serverLocked then!@#&			while true do!@#&				enableRecording = true!@#&				term.setCursorPos(1, 2)!@#&				print(\"\")!@#&				term.setTextColor(colors[theme[\"text-color\"]])!@#&				term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&				for i = 1, 4 do centerPrint(string.rep(\" \", 47)) end!@#&				term.setCursorPos(5, 4)!@#&				print(\"Enter Password:\")!@#&				term.setCursorPos(5, 5)!@#&				write(\"> \")!@#&				local enteredPassword = read(\"*\")!@#&				if enteredPassword == serverPassword then!@#&					term.setCursorPos(1, 2)!@#&					print(\"\")!@#&					term.setTextColor(colors[theme[\"text-color\"]])!@#&					term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&					for i = 1, 4 do centerPrint(string.rep(\" \", 47)) end!@#&					term.setCursorPos(5, 4)!@#&					write(\"Password Accepted!\")!@#&					opt = \"\"!@#&					serverLocked = false!@#&					os.pullEvent = oldPullEvent!@#&					sleep(1.3)!@#&					break!@#&				else!@#&					term.setCursorPos(1, 2)!@#&					print(\"\")!@#&					term.setTextColor(colors[theme[\"text-color\"]])!@#&					term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&					for i = 1, 4 do centerPrint(string.rep(\" \", 47)) end!@#&					term.setCursorPos(5, 4)!@#&					write(\"Password Incorrect!\")!@#&					sleep(1.3)!@#&				end!@#&			end!@#&		end!@#&!@#&		if opt == p1 then!@#&			enableResponse = not enableResponse!@#&		elseif opt == \"Manage\" then!@#&			enableRecording = false!@#&			manageServer()!@#&			enableRecording = true!@#&		elseif opt == \"Edit\" then!@#&			enableRecording = false!@#&			term.setBackgroundColor(colors.black)!@#&			term.setTextColor(colors.white)!@#&			term.clear()!@#&			term.setCursorPos(1, 1)!@#&			edit()!@#&!@#&			term.clear()!@#&			pages = loadPages(dataLocation)!@#&			loadServerAPI()!@#&			if uponSuccessfulRequest == nil or uponFailedRequest == nil or uponAnyMessage == nil or !@#&					uponAnyOtherMessage == nil or parallelWithServer == nil then!@#&				record(\"Warning - Failed To Load Server API:\")!@#&				if uponSuccessfulRequest == nil then record(\" - uponSuccessfulRequest()\") end!@#&				if uponFailedRequest == nil then record(\" - uponFailedRequest()\") end!@#&				if uponAnyMessage == nil then record(\" - uponAnyMessage()\") end!@#&				if uponAnyOtherMessage == nil then record(\" - uponAnyOtherMessage()\") end!@#&				if parallelWithServer == nil then record(\" - parallelWithServer()\") end!@#&			else record(\"Re-Loaded Server API\") end!@#&			enableRecording = true!@#&		elseif opt == \"Add Lock\" then!@#&			enableRecording = false!@#&			addLock()!@#&			enableRecording = false!@#&		elseif opt == \"Lock Server\" then!@#&			os.pullEvent = os.pullEventRaw!@#&			serverLocked = true!@#&			term.setCursorPos(1, 2)!@#&			print(\"\")!@#&			term.setTextColor(colors[theme[\"text-color\"]])!@#&			term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&			for i = 1, 4 do centerPrint(string.rep(\" \", 47)) end!@#&			term.setCursorPos(5, 4)!@#&			print(\"Server Locked!\")!@#&			sleep(2)!@#&		elseif opt == \"Stop\" then!@#&			os.queueEvent(event_stopServer)!@#&			return!@#&		end!@#&	end!@#&end!@#&!@#&!@#&--  -------- Main!@#&!@#&local function main()!@#&	-- Logo!@#&	term.setBackgroundColor(colors[theme[\"background\"]])!@#&	term.setTextColor(colors[theme[\"text-color\"]])!@#&	term.clear()!@#&	term.setCursorPos(1, 2)!@#&	term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&	leftPrint(string.rep(\" \", 47))!@#&	leftPrint([[          ______ ____ ____   ______            ]])!@#&	leftPrint([[ ------- / ____//  _// __ \\ / ____/            ]])!@#&	leftPrint([[ ------ / /_    / / / /_/ // __/               ]])!@#&	leftPrint([[ ----- / __/  _/ / / _  _// /___               ]])!@#&	leftPrint([[ ---- / /    /___//_/ |_|/_____/               ]])!@#&	leftPrint([[ --- / /       _       __ ____   __     ______ ]])!@#&	leftPrint([[ -- /_/       | |     / // __ \\ / /    / ____/ ]])!@#&	leftPrint([[              | | /| / // / / // /    / /_     ]])!@#&	leftPrint([[              | |/ |/ // /_/ // /___ / __/     ]])!@#&	leftPrint([[              |__/|__/ \\____//_____//_/        ]])!@#&	leftPrint(string.rep(\" \", 47))!@#&	print(\"\\n\")!@#&	term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&!@#&	rightPrint(string.rep(\" \", 27 + version:len()))!@#&	rightPrint(\"  Loading Firewolf Server \" .. version .. \" \")!@#&	rightPrint(string.rep(\" \", 27 + version:len()))!@#&!@#&	-- Filesystem!@#&	if not validateFilesystem() then return end!@#&!@#&	-- Update!@#&	if autoupdate then updateClient() end!@#&!@#&	-- Load!@#&	pages = loadPages(dataLocation)!@#&	loadServerAPI()!@#&	if fs.exists(statsLocation) then!@#&		local f = io.open(statsLocation, \"r\")!@#&		local a = tonumber(f:read(\"*l\"))!@#&		local b = tonumber(f:read(\"*l\"))!@#&		local c = f:read(\"*l\")!@#&		if a then visits = a end!@#&		if b then searches = b end!@#&		if c then permantentIgnoreDatabase = textutils.unserialize(c) end!@#&		f:close()!@#&	end!@#&	if not checkForModem() then return end!@#&!@#&	-- Start UI!@#&	parallel.waitForAll(respondToEvents, interface, parallelWithServer)!@#&end!@#&!@#&local function startup()!@#&	-- HTTP API!@#&	if not http then!@#&		term.setTextColor(colors[theme[\"text-color\"]])!@#&		term.setBackgroundColor(colors[theme[\"background\"]])!@#&		term.clear()!@#&		term.setCursorPos(1, 2)!@#&		term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&		leftPrint(string.rep(\" \", 24))!@#&		leftPrint(\" HTTP Not Enabled!  \")!@#&		leftPrint(string.rep(\" \", 24))!@#&		print(\"\")!@#&!@#&		term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&		rightPrint(string.rep(\" \", 36))!@#&		rightPrint(\"  Firewolf is unable to run without \")!@#&		rightPrint(\"       the HTTP Enabled! Please \")!@#&		rightPrint(\"    enable it in your ComputerCraft \")!@#&		rightPrint(\"                            Config! \")!@#&		rightPrint(string.rep(\" \", 36))!@#&!@#&		if isAdvanced() then rightPrint(\"                   Click to exit... \")!@#&		else rightPrint(\"           Press any key to exit... \") end!@#&		rightPrint(string.rep(\" \", 36))!@#&!@#&		while true do!@#&			local e, but, x, y = os.pullEvent()!@#&			if e == \"mouse_click\" or e == \"key\" then break end!@#&		end!@#&!@#&		return false !@#&	end!@#&!@#&	-- Turtle!@#&	if turtle then!@#&		term.clear()!@#&		term.setCursorPos(1, 2)!@#&		centerPrint(\"Advanced Comptuer Required!\")!@#&		print(\"\\n\")!@#&		centerPrint(\"This version of Firewolf requires\")!@#&		centerPrint(\"an Advanced Comptuer to run!\")!@#&		print(\"\")!@#&		centerPrint(\"Turtles may not be used to run\")!@#&		centerPrint(\"Firewolf! :(\")!@#&		print(\"\")!@#&		centerPrint(\"Press any key to exit...\")!@#&!@#&		os.pullEvent(\"key\")!@#&		return false!@#&	end!@#&!@#&	-- Run!@#&	local _, err = pcall(main)!@#&	if err and err ~= \"parallel:22: Terminated\" then!@#&		term.setTextColor(colors[theme[\"text-color\"]])!@#&		term.setBackgroundColor(colors[theme[\"background\"]])!@#&		term.clear()!@#&		term.setCursorPos(1, 2)!@#&		term.setCursorBlink(false)!@#&		term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&		leftPrint(string.rep(\" \", 27))!@#&		leftPrint(\" Firewolf has Crashed! D:  \")!@#&		leftPrint(string.rep(\" \", 27))!@#&		print(\"\")!@#&		term.setBackgroundColor(colors[theme[\"background\"]])!@#&		print(\"\")!@#&		print(\"  \" .. err)!@#&		print(\"\")!@#&!@#&		term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&		rightPrint(string.rep(\" \", 41))!@#&		if autoupdate == \"true\" then!@#&			rightPrint(\"    Please report this error to 1lann or \")!@#&			rightPrint(\"  GravityScore so we are able to fix it! \")!@#&			rightPrint(\"  If this problem persists, try deleting \")!@#&			rightPrint(\"                         \" .. rootFolder .. \" \")!@#&		else!@#&			rightPrint(\"        Automatic updating is off! A new \")!@#&			rightPrint(\"     version may have have been released \")!@#&			rightPrint(\"                that may fix this error! \")!@#&			rightPrint(\"        If you didn't turn auto updating \")!@#&			rightPrint(\"             off, delete \" .. rootFolder .. \" \")!@#&		end!@#&!@#&		rightPrint(string.rep(\" \", 41))!@#&		if isAdvanced() then rightPrint(\"                        Click to exit... \")!@#&		else rightPrint(\"                Press any key to exit... \") end!@#&		rightPrint(string.rep(\" \", 41))!@#&!@#&		while true do!@#&			local e, but, x, y = os.pullEvent()!@#&			if e == \"mouse_click\" or e == \"key\" then break end!@#&		end!@#&!@#&		return false!@#&	end!@#&!@#&	return true!@#&end!@#&!@#&-- Check If Read Only!@#&if fs.isReadOnly(serverLocation) or fs.isReadOnly(rootFolder) then!@#&	print(\"Firewolf cannot modify itself or its root folder!\")!@#&	print(\"\")!@#&	print(\"This cold be caused by Firewolf being placed in\")!@#&	print(\"the rom folder, or another program may be\")!@#&	print(\"preventing the modification of Firewolf.\")!@#&!@#&	-- Reset Environment and Exit!@#&	setfenv(1, oldEnv)!@#&	error()!@#&end!@#&!@#&-- Theme!@#&if not isAdvanced() then !@#&	theme = originalTheme!@#&else!@#&	theme = loadTheme(themeLocation)!@#&	if theme == nil then theme = defaultTheme end!@#&end!@#&!@#&-- Pasword!@#&if fs.exists(passwordDataLocation) then!@#&	local f = io.open(passwordDataLocation, \"r\")!@#&	serverPassword = f:read(\"*l\")!@#&	f:close()!@#&	serverLocked = true!@#&else!@#&	serverLocked = false!@#&end!@#&!@#&-- Start!@#&startup()!@#&!@#&-- Clear!@#&term.setBackgroundColor(colors.black)!@#&term.setTextColor(colors.white)!@#&term.clear()!@#&term.setCursorPos(1, 1)!@#&centerPrint(\"Thank You for Using Firewolf Server \" .. version)!@#&centerPrint(\"Made by 1lann and GravityScore\")!@#&!@#&-- Close Rednet!@#&for _, v in pairs(rs.getSides()) do !@#&	if peripheral.getType(v) == \"modem\" then rednet.close(v) end!@#&end",["servers"]={},["user_whitelist"]="",["cache"]={},["website_data"]={},["user_blacklist"]="",["settings"]="{[\"home\"]=\"firewolf\",[\"incog\"]=\"false\",[\"auto\"]=\"true\",}",},["startup"]="os.pullEvent = os.pullEventRaw!@#&!@#&if not term.isColour() then!@#& error(\"You need an advanced computer!\", 0)!@#&elseif not http then!@#& error(\"HTTP api needs to be enabled!\", 0)!@#&end!@#&!@#&--[[ Unlocalized variables ]]--!@#&!@#&root = \"OS\"!@#&slc = 0!@#&settingsFile = \"/\"..root..\"/os.cfg\"!@#&useIdeEdit = false!@#&logged = false!@#&userFile = \"/\"..root..\"/system/.users\"!@#&!@#&--[[  LuaIde edit  ]]--!@#&if useIdeEdit == true then!@#& shell.setAlias(\"edit\", \"/\"..root..\"/programs/luaide\")!@#&end!@#&!@#&--[[  Localized variables  ]]--!@#&!@#&local endMessage = true!@#&local username = nil --dont change!@#&!@#&--[[  Functions  ]]--!@#&!@#&for i,v in ipairs(fs.list(\"/\"..root..\"/apis/\")) do!@#& os.unloadAPI(\"/\"..root..\"/apis/\"..v)!@#& os.loadAPI(\"/\"..root..\"/apis/\"..v)  !@#&end!@#&!@#&function loadSettings()!@#&  shell.run(settingsFile)!@#&  !@#&  bgColor = settings[\"bgColor\"]!@#&  textColor = settings[\"textColor\"]!@#&  barColor = settings[\"barColor\"]!@#&  bgImg = settings[\"bgImg\"]!@#&  filesImg = settings[\"filesImg\"]!@#&  snakeImg = settings[\"snakeImg\"]!@#&  fwImg = settings[\"fwImg\"]!@#&  liImg = settings[\"liImg\"]!@#&  paImg = settings[\"paImg\"]!@#&end!@#&!@#&function drawBar()!@#& term.setCursorPos(1,1)!@#& term.setBackgroundColour(barColor)!@#& term.clearLine()!@#& term.setTextColour(textColor)!@#& term.setCursorPos(3, 1)!@#& write(\"[HD-OS]\")!@#& term.setCursorPos(15, 1)!@#& write(\"[User]\")!@#& !@#& local maxX, maxY = term.getSize()!@#& term.setCursorPos(maxX-#username-3, 1)!@#& write(\"[\"..username..\"]\")!@#&end!@#&!@#&function centerPrint(text, color)!@#& if tonumber(color) then!@#&  term.setTextColour(color)!@#& else!@#&  if colors[color] ~= nil then!@#&   term.setTextColour(colors[color])!@#&  end!@#& end!@#& !@#& local xPos, yPos = term.getCursorPos()!@#& local maxX, maxY = term.getSize()!@#& term.setCursorPos(maxX/2-#text/2, yPos)!@#& print(text)!@#&end!@#&!@#&function clear()!@#& term.clear()!@#& term.setCursorPos(1,1)!@#&end!@#&!@#&function drawWall()!@#& local bg = paintutils.loadImage(bgImg)!@#& term.setBackgroundColour(bgColor)!@#& term.clear()!@#& paintutils.drawImage(bg, 1, 1)!@#& drawBar()!@#& !@#& --[[  Icon 1  ]]--!@#& local snakeIcon = paintutils.loadImage(snakeImg)!@#& paintutils.drawImage(snakeIcon, 3, 4)!@#& term.setTextColour(colors.gray)!@#& term.setCursorPos(3,9)!@#& term.setBackgroundColour(colors.white)!@#& write(\"Games\")!@#& --[[ \\Icon 1\\ ]]--!@#& !@#& ------------------!@#& !@#& --[[  Icon 2  ]]--!@#& local filesIcon = paintutils.loadImage(filesImg)!@#& paintutils.drawImage(filesIcon, 44, 5)!@#& term.setTextColour(colors.gray)!@#& term.setCursorPos(44, 10)!@#& term.setBackgroundColour(colors.white)!@#& write(\"Files\")!@#& --[[ \\Icon 2\\ ]]--!@#& !@#& ------------------!@#& !@#& --[[  Icon 3  ]]--!@#& local fwIcon = paintutils.loadImage(fwImg)!@#& paintutils.drawImage(fwIcon, 10, 12)!@#& term.setTextColour(colors.gray)!@#& term.setCursorPos(8, 17)!@#& term.setBackgroundColour(colors.white)!@#& write(\"Fire-Wolf\")!@#& --[[ \\Icon 3\\ ]]--!@#& !@#& ------------------!@#& !@#& --[[  Icon 4  ]]--!@#& local liIcon = paintutils.loadImage(liImg)!@#& paintutils.drawImage(liIcon, 26, 13)!@#& term.setTextColour(colors.white)!@#& term.setCursorPos(27, 14)!@#& write(\">_\")!@#& term.setTextColour(colors.gray)!@#& term.setCursorPos(25, 18)!@#& term.setBackgroundColour(colors.white)!@#& write(\"Lua IDE\")!@#& --[[ \\Icon 4\\ ]]--!@#& !@#& ------------------!@#& !@#& --[[  Icon 5  ]]--!@#& local paIcon = paintutils.loadImage(paImg)!@#& paintutils.drawImage(paIcon, 40, 12)!@#& term.setCursorPos(40, 17)!@#& term.setBackgroundColour(colors.white)!@#& write(\"Paint\")!@#& --[[ \\Icon 5\\ ]]--!@#&end!@#&!@#&function drawMenu1()!@#& for i=1,9 do!@#&  paintutils.drawLine(2, 1+i, 11, 1+i, colors.lightGray)!@#&  sleep(.001)!@#& end!@#& !@#& term.setCursorPos(3, 3)!@#& write(\"Reboot\")!@#& term.setCursorPos(3, 4)!@#& write(\"Shutdown\")!@#& term.setCursorPos(3, 5)!@#& write(\"Lua\")!@#& term.setCursorPos(3, 6)!@#& write(\"Shell\")!@#& term.setCursorPos(3, 7)!@#& write(\"Version\")!@#& term.setCursorPos(3, 8)!@#& write(\"Settings\")!@#& term.setCursorPos(3, 9)!@#& write(\"Exit\")!@#&end!@#&!@#&function drawMenu2()!@#& for i=1, 6 do!@#&  paintutils.drawLine(11, 1+i, 24, 1+i, colors.lightGray)!@#&  sleep(.001)!@#& end!@#& !@#& term.setTextColour(colors.gray)!@#& !@#& term.setCursorPos(12, 3)!@#& write(\"Add User\")!@#& term.setCursorPos(12, 4)!@#& write(\"Remove User\")!@#& term.setCursorPos(12, 5)!@#& write(\"List Users\")!@#& term.setCursorPos(12, 6)!@#& write(\"Log out\")!@#&end!@#&!@#&function msgBox(text, title, width, height)!@#& local maxX, maxY = term.getSize()!@#& for i=1, height do!@#&  paintutils.drawLine(maxX/2-width/2, (maxY/2-3)+i, maxX/2+width/2, (maxY/2-3)+i, colors.lightGray)!@#& end!@#& !@#& term.setCursorPos(maxX/2-#title/2, maxY/2-2)!@#& term.setTextColour(colors.gray)!@#& write(title)!@#& term.setCursorPos((maxX/2-width/2)+1, maxY/2)!@#& term.setBackgroundColour(colors.white)!@#& write(text)!@#& term.setBackgroundColour(colors.lightGray)!@#& local pullKeyText = \"Pull any event\"!@#& term.setCursorPos((maxX/2-#pullKeyText/2)+1, maxY/2+2)!@#& write(pullKeyText)!@#& os.pullEvent()!@#&end!@#&!@#&function checkUser(name, pwd)!@#& A = fs.open(userFile, \"r\")!@#& local usrTable = textutils.unserialize(A.readAll())!@#& A.close()!@#& !@#& for i,v in ipairs(usrTable) do!@#&  if name == usrTable[i][\"username\"] and pwd == usrTable[i][\"password\"] then!@#&   local username = name!@#&   return true!@#&  end!@#& end!@#&  errorBox(\"Username or password is incorrect!\")!@#&end!@#&!@#&function errorBox(text)!@#& local maxX, maxY = term.getSize()!@#& term.setTextColour(colors.white)!@#& term.setBackgroundColour(colors.red)!@#& term.setCursorPos(1, maxY/2-1)!@#& term.clearLine()!@#& term.setCursorPos(maxX/2-#text/2, maxY/2)!@#& term.clearLine()!@#& write(text)!@#& term.setCursorPos(1, maxY/2+1)!@#& term.clearLine()!@#& sleep(2)!@#&end!@#&!@#&function goLogin()!@#& repeat!@#&  term.setBackgroundColour(colors.white)!@#&  clear()!@#&  term.setTextColour(colors.gray)!@#&  term.setBackgroundColour(colors.lightGray)!@#&  term.setCursorPos(1, 2)!@#&  term.clearLine()!@#&  write(\"Username: \")!@#&  term.setCursorPos(1, 4)!@#&  term.clearLine()!@#&  write(\"Password: \")!@#&  !@#&  term.setCursorPos(11, 2)!@#&  input = read()!@#&  term.setCursorPos(11, 4)!@#&  pwd = read(\"*\")!@#&  !@#&  logged = checkUser(input, pwd)!@#& until logged == true!@#& OS(input)!@#&end!@#&!@#&function doFileCreate(name)!@#& term.setBackgroundColour(colors.white)!@#& clear()!@#& term.setTextColour(colors.gray)!@#& term.setBackgroundColour(colors.lightGray)!@#& term.setCursorPos(1,2)!@#& term.clearLine()!@#& write(\"Filename: \")!@#& local filename = read()!@#& shell.run(\"/\"..root..\"/programs/luaide\", \"/\"..root..\"/users/\"..name..\"/\"..filename)!@#&end!@#&!@#&function doFilePaint(name)!@#& term.setBackgroundColour(colors.white)!@#& clear()!@#& term.setTextColour(colors.gray)!@#& term.setBackgroundColour(colors.lightGray)!@#& term.setCursorPos(1,2)!@#& term.clearLine()!@#& write(\"Filename: \")!@#& local filename = read()!@#& shell.run(\"/\"..root..\"/programs/npaintpro\", \"/\"..root..\"/users/\"..name..\"/\"..filename)!@#&end!@#&!@#&--[[  Main OS  ]]--!@#&if not fs.exists(userFile) then!@#& shell.run(\"/\"..root..\"/system/addUser\")!@#&end!@#&!@#&function OS(name)!@#&username = name!@#&loadSettings()!@#&drawWall()!@#&local path = \"/\"..root..\"/users/\"..name!@#&while true do!@#& ev, b, X, Y = os.pullEventRaw(\"mouse_click\")!@#& if slc == 0 then!@#&  if X >= 3 and X <= 9 and Y == 1 then!@#&   drawMenu1()!@#&   slc = 1!@#&  elseif X >= 15 and X <= 20 and Y == 1 then!@#&   drawMenu2()!@#&   slc = 2!@#&  elseif X >= 3 and X <= 8 and Y >= 4 and Y <= 9 then!@#&   term.setBackgroundColour(colors.black)!@#&   clear()!@#&   shell.run(\"/\"..root..\"/programs/games\")!@#&   drawWall()!@#&   slc = 0!@#&  elseif X >= 44 and X <= 49 and Y >= 5 and Y <= 10 then!@#&   term.setBackgroundColour(colors.black)!@#&   clear()!@#&   shell.run(\"/\"..root..\"/programs/filebrowser\", path)!@#&   drawWall()!@#&   slc = 0!@#&  elseif X >= 8 and X <= 17 and Y >= 12 and Y <= 17 then!@#&   term.setBackgroundColour(colors.black)!@#&   clear()!@#&   shell.run(\"/\"..root..\"/programs/firewolf\")!@#&   drawWall()!@#&   slc = 0!@#&  elseif X >= 25 and X <= 32 and Y >= 13 and Y <= 18 then!@#&   term.setBackgroundColour(colors.black)!@#&   clear()!@#&   doFileCreate(name)!@#&   sleep(1)!@#&   drawWall()!@#&   slc = 0!@#&  elseif X >= 40 and X <= 45 and Y >= 12 and Y <= 17 then!@#&   term.setBackgroundColour(colors.black)!@#&   clear()!@#&   doFilePaint(name)!@#&   sleep(1)!@#&   drawWall()!@#&   slc = 0!@#&  else!@#&   drawWall()!@#&  end!@#& elseif slc == 1 then!@#&  if X >= 2 and X <= 11 and Y == 3 then!@#&   os.reboot()!@#&  elseif X >= 2 and X <= 11 and Y == 4 then!@#&   os.shutdown()!@#&  elseif X >= 2 and X <= 11 and Y == 5 then!@#&   term.setBackgroundColour(colors.black)!@#&   clear()!@#&   shell.run(\"rom/programs/lua\")!@#&   drawWall()!@#&   slc = 0!@#&  elseif X >= 2 and X <= 11 and Y == 6 then!@#&   term.setBackgroundColour(colors.black)!@#&   clear()!@#&   shell.run(\"rom/programs/shell\")!@#&   drawWall()!@#&   slc = 0!@#&  elseif X >= 2 and X <= 11 and Y == 7 then!@#&   local msg = \"You are running HD-OS v2.5\"!@#&   msgBox(msg, \"Version\", #msg+1, 5)!@#&   drawWall()!@#&   slc = 0!@#&  elseif X >= 2 and X <= 11 and Y == 8 then!@#&   term.setBackgroundColour(colors.black)!@#&   clear()!@#&   shell.run(\"edit\",  \"/\"..root..\"/os.cfg\")!@#&   loadSettings()!@#&   drawWall()!@#&   slc = 0!@#&  elseif X >= 2 and X <= 11 and Y == 9 then!@#&   term.setBackgroundColour(colors.black)!@#&   clear()!@#&   if endMessage == true then centerPrint(\"Thank you for using HD-OS v2.5\", 2^math.random(0,14)) end!@#&   break!@#&  else!@#&   drawWall()!@#&   slc = 0!@#&  end!@#& elseif slc == 2 then!@#&  if X >= 12 and X <= 24 and Y == 3 then!@#&   term.setBackgroundColour(colors.black)!@#&   clear()!@#&   shell.run(\"/\"..root..\"/system/addUser\")!@#&   drawWall()!@#&   slc = 0!@#&  elseif X >= 12 and X <= 24 and Y == 4 then!@#&   term.setBackgroundColour(colors.black)!@#&   shell.run(\"/\"..root..\"/system/delUser\")!@#&   drawWall()!@#&   slc = 0!@#&  elseif X >= 12 and X <= 24 and Y == 5 then!@#&   term.setBackgroundColour(colors.black)!@#&   clear()!@#&   shell.run(\"/\"..root..\"/system/listUsers\")!@#&   drawWall()!@#&   slc = 0!@#&  elseif X >= 12 and X <= 24 and Y == 6 then!@#&   goLogin()!@#&  else!@#&   drawWall()!@#&   slc = 0!@#&  end!@#& end!@#&end!@#&!@#&end!@#&--[[  End Of OS  ]]--!@#&!@#&goLogin()!@#&",["OS"]={["os.cfg"]="settings = {!@#& [\"bgColor\"] = colors.white,!@#& [\"bgImg\"] = root..\"/images/wallpaper\",!@#& [\"textColor\"] = colors.white,!@#& [\"barColor\"] = colors.red,!@#& [\"snakeImg\"] = root..\"/images/snake\",!@#& [\"filesImg\"] = root..\"/images/files\",!@#& [\"fwImg\"] = root..\"/images/firewolf\",!@#& [\"liImg\"] = root..\"/images/luaide\",!@#& [\"paImg\"] = root..\"/images/npaintpro\"!@#&}",["games"]={["worm"]="!@#&-- Display the start screen!@#&local w,h = term.getSize()!@#&!@#&local headingColour, textColour, wormColour, fruitColour!@#&if term.isColour() then!@#&	headingColour = colours.yellow!@#&	textColour = colours.white!@#&	wormColour = colours.green!@#&	fruitColour = colours.red!@#&else!@#&	headingColour = colours.white!@#&	textColour = colours.white!@#&	wormColour = colours.white!@#&	fruitColour = colours.white!@#&end!@#&!@#&function printCentred( y, s )!@#&	local x = math.floor((w - string.len(s)) / 2)!@#&	term.setCursorPos(x,y)!@#&	--term.clearLine()!@#&	term.write( s )!@#&end!@#&!@#&local xVel,yVel = 1,0!@#&local xPos, yPos = math.floor(w/2), math.floor(h/2)!@#&local pxVel, pyVel = nil, nil!@#&!@#&local nLength = 1!@#&local nExtraLength = 6!@#&local bRunning = true!@#&!@#&local tailX,tailY = xPos,yPos!@#&local nScore = 0!@#&local nDifficulty = 2!@#&local nSpeed, nInterval!@#&!@#&-- Setup the screen!@#&local screen = {}!@#&for x=1,w do!@#&	screen[x] = {}!@#&	for y=1,h do!@#&		screen[x][y] = {}!@#&	end!@#&end!@#&screen[xPos][yPos] = { snake = true }!@#&!@#&local nFruit = 1!@#&local tFruits = {!@#&	\"A\", \"B\", \"C\", \"D\", \"E\", \"F\", \"G\", \"H\",!@#&	\"I\", \"J\", \"K\", \"L\", \"M\", \"N\", \"O\", \"P\",!@#&	\"Q\", \"R\", \"S\", \"T\", \"U\", \"V\", \"W\", \"X\",!@#&	\"Y\", \"Z\",!@#&	\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\",!@#&	\"i\", \"j\", \"k\", \"l\", \"m\", \"n\", \"o\", \"p\",!@#&	\"q\", \"r\", \"s\", \"t\", \"u\", \"v\", \"w\", \"x\",!@#&	\"y\", \"z\",!@#&	\"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\", \"0\",!@#&	\"@\", \"$\", \"%\", \"#\", \"&\", \"!\", \"?\", \"+\", \"*\", \"~\"!@#&}!@#&!@#&local function addFruit()!@#&	while true do!@#&		local x = math.random(1,w)!@#&		local y = math.random(2,h)!@#&		local fruit = screen[x][y]!@#&		if fruit.snake == nil and fruit.wall == nil and fruit.fruit == nil then!@#&			screen[x][y] = { fruit = true }!@#&			term.setCursorPos(x,y)!@#&			term.setBackgroundColour( fruitColour )!@#&			term.write(\" \")!@#&			term.setBackgroundColour( colours.black )!@#&			break!@#&		end!@#&	end!@#&	!@#&	nFruit = nFruit + 1!@#&	if nFruit > #tFruits then!@#&		nFruit = 1!@#&	end!@#&end!@#&!@#&local function drawMenu()!@#&	term.setTextColour( headingColour )!@#&	term.setCursorPos(1,1)!@#&	term.write( \"SCORE \" )!@#&	!@#&	term.setTextColour( textColour )!@#&	term.setCursorPos(7,1)!@#&	term.write( tostring(nScore) )!@#&!@#&	term.setTextColour( headingColour )!@#&	term.setCursorPos(w-11,1)!@#&	term.write( \"DIFFICULTY \")!@#&!@#&	term.setTextColour( textColour )!@#&	term.setCursorPos(w,1)!@#&	term.write( tostring(nDifficulty or \"?\") ) !@#&!@#&	term.setTextColour( colours.white )!@#&end!@#&!@#&local function update( )!@#&	local x,y = xPos,yPos!@#&	if pxVel and pyVel then!@#&		xVel, yVel = pxVel, pyVel!@#&		pxVel, pyVel = nil, nil!@#&	end!@#&!@#&	-- Remove the tail!@#&	if nExtraLength == 0 then!@#&		local tail = screen[tailX][tailY]!@#&		screen[tailX][tailY] = {}!@#&		term.setCursorPos(tailX,tailY)!@#&		term.write(\" \")!@#&		tailX = tail.nextX!@#&		tailY = tail.nextY!@#&	else!@#&		nExtraLength = nExtraLength - 1!@#&	end!@#&	!@#&	-- Update the head!@#&	local head = screen[xPos][yPos]!@#&	local newXPos = xPos + xVel!@#&	local newYPos = yPos + yVel!@#&	if newXPos < 1 then!@#&		newXPos = w!@#&	elseif newXPos > w then!@#&		newXPos = 1!@#&	end!@#&	if newYPos < 2 then!@#&		newYPos = h!@#&	elseif newYPos > h then!@#&		newYPos = 2!@#&	end!@#&	!@#&	local newHead = screen[newXPos][newYPos]!@#&	term.setCursorPos(1,1);!@#&	print( newHead.snake )!@#&	if newHead.snake == true or newHead.wall == true then!@#&		bRunning = false!@#&		!@#&	else!@#&		if newHead.fruit == true then!@#&			nScore = nScore + 10!@#&			nExtraLength = nExtraLength + 1!@#&			addFruit()!@#&		end!@#&		xPos = newXPos!@#&		yPos = newYPos!@#&		head.nextX = newXPos!@#&		head.nextY = newYPos!@#&		screen[newXPos][newYPos] = { snake = true }!@#&		!@#&	end!@#&	!@#&	term.setCursorPos(xPos,yPos)!@#&	term.setBackgroundColour( wormColour )!@#&	term.write(\" \")!@#&	term.setBackgroundColour( colours.black )!@#&!@#&	drawMenu()!@#&end!@#&!@#&-- Display the frontend!@#&term.clear()!@#&local function drawFrontend()!@#&	term.setTextColour( headingColour )!@#&	printCentred( math.floor(h/2) - 3, \"\" )!@#&	printCentred( math.floor(h/2) - 2, \" SELECT DIFFICULTY \" )!@#&	printCentred( math.floor(h/2) - 1, \"\" )!@#&	!@#&	printCentred( math.floor(h/2) + 0, \"            \" )!@#&	printCentred( math.floor(h/2) + 1, \"            \" )!@#&	printCentred( math.floor(h/2) + 2, \"            \" )!@#&	printCentred( math.floor(h/2) - 1 + nDifficulty, \" [        ] \" )!@#&!@#&	term.setTextColour( textColour )!@#&	printCentred( math.floor(h/2) + 0, \"EASY\" )!@#&	printCentred( math.floor(h/2) + 1, \"MEDIUM\" )!@#&	printCentred( math.floor(h/2) + 2, \"HARD\" )!@#&	printCentred( math.floor(h/2) + 3, \"\" )!@#&!@#&	term.setTextColour( colours.white )!@#&end!@#&!@#&drawMenu()!@#&drawFrontend()!@#&while true do!@#&	local e,key = os.pullEvent( \"key\" )!@#&	if key == keys.up or key == keys.w then!@#&		-- Up!@#&		if nDifficulty > 1 then!@#&			nDifficulty = nDifficulty - 1!@#&			drawMenu()!@#&			drawFrontend()!@#&		end!@#&	elseif key == keys.down or key == keys.s then!@#&		-- Down!@#&		if nDifficulty < 3 then!@#&			nDifficulty = nDifficulty + 1!@#&			drawMenu()!@#&			drawFrontend()!@#&		end!@#&	elseif key == keys.enter then!@#&		-- Enter!@#&		break!@#&	end!@#&end!@#&!@#&local tSpeeds = { 5, 10, 25 }!@#&nSpeed = tSpeeds[nDifficulty]!@#&nInterval = 1 / nSpeed!@#&!@#&-- Grow the snake to its intended size!@#&term.clear()!@#&drawMenu()!@#&screen[tailX][tailY].snake = true!@#&while nExtraLength > 0 do!@#&	update()!@#&end!@#&addFruit()!@#&addFruit()!@#&!@#&-- Play the game!@#&local timer = os.startTimer(0)!@#&while bRunning do!@#&	local event, p1, p2 = os.pullEvent()!@#&	if event == \"timer\" and p1 == timer then!@#&		timer = os.startTimer(nInterval)!@#&		update( false )!@#&	!@#&	elseif event == \"key\" then!@#&		local key = p1!@#&		if key == keys.up or key == keys.w then!@#&			-- Up!@#&			if yVel == 0 then!@#&				pxVel,pyVel = 0,-1!@#&			end!@#&		elseif key == keys.down or key == keys.s then!@#&			-- Down!@#&			if yVel == 0 then!@#&				pxVel,pyVel = 0,1!@#&			end!@#&		elseif key == keys.left or key == keys.a then!@#&			-- Left!@#&			if xVel == 0 then!@#&				pxVel,pyVel = -1,0!@#&			end!@#&		!@#&		elseif key == keys.right or key == keys.d then!@#&			-- Right!@#&			if xVel == 0 then!@#&				pxVel,pyVel = 1,0!@#&			end!@#&		!@#&		end	!@#&	end!@#&end!@#&!@#&-- Display the gameover screen!@#&term.setTextColour( headingColour )!@#&printCentred( math.floor(h/2) - 2, \"                   \" )!@#&printCentred( math.floor(h/2) - 1, \" G A M E   O V E R \" )!@#&!@#&term.setTextColour( textColour )!@#&printCentred( math.floor(h/2) + 0, \"                 \" )!@#&printCentred( math.floor(h/2) + 1, \" FINAL SCORE \"..nScore..\" \" )!@#&printCentred( math.floor(h/2) + 2, \"                 \" )!@#&term.setTextColour( colours.white )!@#&!@#&local timer = os.startTimer(2.5)!@#&repeat!@#&	local e,p = os.pullEvent()!@#&	if e == \"timer\" and p == timer then!@#&		term.setTextColour( textColour )!@#&		printCentred( math.floor(h/2) + 2, \" PRESS ANY KEY \" )!@#&		printCentred( math.floor(h/2) + 3, \"               \" )!@#&		term.setTextColour( colours.white )!@#&	end!@#&until e == \"char\"!@#&!@#&term.clear()!@#&term.setCursorPos(1,1)!@#&!@#&		",["maze3d"]="--[[!@#&	Project info:!@#&	!@#&	Name: Maze 3D!@#&	Creator: Jesusthekiller!@#&	Language: Lua (CC)!@#&	Website: None!@#&	License: GNU GPL!@#&		License file can be fount at www.jesusthekiller.com/license-gpl.html!@#&!@#&	Version: 2.1!@#&]]--!@#&!@#&--[[!@#&	Big thanks to Gopher for 3D engine!!@#&	http://www.computercraft.info/forums2/index.php?/topic/10786-wolf3d-style-3d-engine-proof-of-concept/page__hl__wolf3d!@#&]]--!@#&!@#&--[[!@#&	Changelog:!@#&	  1.0:!@#&	    Initial Release!@#&	  2.0:!@#&	    No-HTTP version for Treasure disk!@#&	  2.1:!@#&	    No more temp files!!@#&]]--!@#&!@#&--[[!@#&	LICENSE:!@#&	!@#&	Maze 3D!@#&	Copyright (c) 2013 Jesusthekiller!@#&!@#&	This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.!@#&!@#&	This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.!@#&!@#&	See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.!@#&]]--!@#&!@#&-- The color check!@#&if (not term.isColor()) or turtle then!@#&	print(\"This program has to be run on advanced computer.\")!@#&	error()!@#&end!@#&!@#&-- The cprint!@#&local function cwrite(msg)!@#&	msg = tostring(msg)!@#&	local x, y = term.getCursorPos()!@#&	term.setCursorPos((51-#msg)/2, y)!@#&	write(msg)!@#&end!@#&!@#&local function cprint(msg)!@#&	cwrite(msg..\"\\n\")!@#&end!@#&!@#&--[[!@#&-- The logo!@#&local f = fs.open(\"maze_logo\", \"w\") or error(\"Error while opening file maze_logo\", 0)!@#&f.write(\"0   0  00   0000 0000\\n00 00 0  0     0 0   \\n0 0 0 0000   00  000 \\n0   0 0  0  0    0   \\n0   0 0  0  0000 0000\\n        \\n   eeee    9999      \\n    777e   97779     \\n   eeee 7  97  97    \\n    777e   97  97    \\n   eeee 7  999977    \\n    7777    7777\")!@#&f.close()!@#&!@#&f = paintutils.loadImage(\"maze_logo\")!@#&!@#&--fs.delete(\"maze_logo\")]]!@#&!@#&-- The splash!@#&term.setBackgroundColor(colors.black)!@#&term.setTextColor(colors.white)!@#&term.clear()!@#&!@#&paintutils.drawImage({[1]={[1]=1,[2]=0,[3]=0,[4]=0,[5]=1,[6]=0,[7]=0,[8]=1,[9]=1,[10]=0,[11]=0,[12]=0,[13]=1,[14]=1,[15]=1,[16]=1,[17]=0,[18]=1,[19]=1,[20]=1,[21]=1,},[2]={[1]=1,[2]=1,[3]=0,[4]=1,[5]=1,[6]=0,[7]=1,[8]=0,[9]=0,[10]=1,[11]=0,[12]=0,[13]=0,[14]=0,[15]=0,[16]=1,[17]=0,[18]=1,[19]=0,[20]=0,[21]=0,},[3]={[1]=1,[2]=0,[3]=1,[4]=0,[5]=1,[6]=0,[7]=1,[8]=1,[9]=1,[10]=1,[11]=0,[12]=0,[13]=0,[14]=1,[15]=1,[16]=0,[17]=0,[18]=1,[19]=1,[20]=1,[21]=0,},[4]={[1]=1,[2]=0,[3]=0,[4]=0,[5]=1,[6]=0,[7]=1,[8]=0,[9]=0,[10]=1,[11]=0,[12]=0,[13]=1,[14]=0,[15]=0,[16]=0,[17]=0,[18]=1,[19]=0,[20]=0,[21]=0,},[5]={[1]=1,[2]=0,[3]=0,[4]=0,[5]=1,[6]=0,[7]=1,[8]=0,[9]=0,[10]=1,[11]=0,[12]=0,[13]=1,[14]=1,[15]=1,[16]=1,[17]=0,[18]=1,[19]=1,[20]=1,[21]=1,},[6]={[1]=0,[2]=0,[3]=0,[4]=0,[5]=0,[6]=0,[7]=0,[8]=0,},[7]={[1]=0,[2]=0,[3]=0,[4]=16384,[5]=16384,[6]=16384,[7]=16384,[8]=0,[9]=0,[10]=0,[11]=0,[12]=512,[13]=512,[14]=512,[15]=512,[16]=0,[17]=0,[18]=0,[19]=0,[20]=0,[21]=0,},[8]={[1]=0,[2]=0,[3]=0,[4]=0,[5]=128,[6]=128,[7]=128,[8]=16384,[9]=0,[10]=0,[11]=0,[12]=512,[13]=128,[14]=128,[15]=128,[16]=512,[17]=0,[18]=0,[19]=0,[20]=0,[21]=0,},[9]={[1]=0,[2]=0,[3]=0,[4]=16384,[5]=16384,[6]=16384,[7]=16384,[8]=0,[9]=128,[10]=0,[11]=0,[12]=512,[13]=128,[14]=0,[15]=0,[16]=512,[17]=128,[18]=0,[19]=0,[20]=0,[21]=0,},[10]={[1]=0,[2]=0,[3]=0,[4]=0,[5]=128,[6]=128,[7]=128,[8]=16384,[9]=0,[10]=0,[11]=0,[12]=512,[13]=128,[14]=0,[15]=0,[16]=512,[17]=128,[18]=0,[19]=0,[20]=0,[21]=0,},[11]={[1]=0,[2]=0,[3]=0,[4]=16384,[5]=16384,[6]=16384,[7]=16384,[8]=0,[9]=128,[10]=0,[11]=0,[12]=512,[13]=512,[14]=512,[15]=512,[16]=128,[17]=128,[18]=0,[19]=0,[20]=0,[21]=0,},[12]={[1]=0,[2]=0,[3]=0,[4]=0,[5]=128,[6]=128,[7]=128,[8]=128,[9]=0,[10]=0,[11]=0,[12]=0,[13]=128,[14]=128,[15]=128,[16]=128,},}, 15, 3)!@#&!@#&parallel.waitForAny(!@#&	function() coroutine.yield(); os.pullEvent(\"key\"); coroutine.yield() end,!@#&	function() term.setBackgroundColor(colors.black); term.setTextColor(colors.white) while true do term.setCursorPos(18, 16); term.write(\"Press any key..\"); sleep(0.5); term.clearLine(); sleep(0.5) end end!@#&)!@#&!@#&-- The size!@#&local size!@#&!@#&repeat!@#&	term.setCursorPos(1, 16)!@#&	term.clearLine()!@#&!@#&	cwrite(\"Enter maze size (5-99):\")!@#&	size = read()!@#&	!@#&	size = tonumber(size)!@#&	if not size then!@#&		size = 0!@#&	end!@#&until size > 4 and size < 100!@#&!@#&-- The generate!@#&local function mazeGen(mx, my)!@#&	!@#&	--[[!@#&		Format:!@#&		!@#&		maze.x.y.(1/2/3/4) = true/false!@#&		!@#&		1 - top!@#&		2 - bottom!@#&		3 - right!@#&		4 - left!@#&	]]--!@#&	!@#&	local maze = {}!@#&	for i = 1, mx do!@#&		maze[i] = {}!@#&		for j = 1, my do!@#&			maze[i][j] = {}!@#&			for k = 1, 4 do!@#&				maze[i][j][k] = true!@#&			end!@#&		end!@#&	end!@#&!@#&	local vis = 1!@#&	local tot = mx * my!@#&	local curr = {}!@#&	curr.x = math.random(1, mx)!@#&	curr.y = math.random(1, my)!@#&	local stack = {}!@#&!@#&	while vis < tot do!@#&		local intact = {}!@#&		local x = curr.x!@#&		local y = curr.y!@#&		!@#&		if x - 1 >= 1 and maze[x-1][y][1] and maze[x-1][y][2] and maze[x-1][y][3] and maze[x-1][y][4] then -- Check for full cells!@#&			intact[#intact+1] = {x-1, y, 1}!@#&		end!@#&		!@#&		if x + 1 <= mx and maze[x+1][y][1] and maze[x+1][y][2] and maze[x+1][y][3] and maze[x+1][y][4] then!@#&			intact[#intact+1] = {x+1, y, 2}!@#&		end!@#&		!@#&		if y + 1 <= my and maze[x][y+1][1] and maze[x][y+1][2] and maze[x][y+1][3] and maze[x][y+1][4] then!@#&			intact[#intact+1] = {x, y+1, 3}!@#&		end!@#&		!@#&		if y - 1 >= 1 and maze[x][y-1][1] and maze[x][y-1][2] and maze[x][y-1][3] and maze[x][y-1][4] then!@#&			intact[#intact+1] = {x, y-1, 4}!@#&		end!@#&		!@#&		if #intact > 0 then!@#&			local i = math.random(1, #intact) -- Choose random!@#&			!@#&			if intact[i][3] == 1 then -- Set intact's attached wall to false!@#&				maze[intact[i][1]][intact[i][2]][2] = false!@#&			elseif intact[i][3] == 2 then!@#&				maze[intact[i][1]][intact[i][2]][1] = false!@#&			elseif intact[i][3] == 3 then!@#&				maze[intact[i][1]][intact[i][2]][4] = false!@#&			elseif intact[i][3] == 4 then!@#&				maze[intact[i][1]][intact[i][2]][3] = false!@#&			end!@#&			!@#&			maze[x][y][intact[i][3]] = false -- Set attached wall to false!@#&			!@#&			vis = vis + 1 -- Increase vis!@#&			!@#&			stack[#stack+1] = intact[i] -- Add to stack!@#&		else!@#&			local tmp = table.remove(stack) -- Get last cell!@#&			curr.x = tmp[1]!@#&			curr.y = tmp[2]!@#&		end!@#&	end!@#&	!@#&	return maze!@#&end!@#&!@#&local m = mazeGen(size, size)!@#&!@#&-- The game init!@#&local posx = 2!@#&local posy = 2!@#&!@#&local offsetx = 51/2-2!@#&local offsety = 19/2-2!@#&!@#&-- The maze-to-table!@#&local tab = {}!@#&!@#&for x = 1, size * 2 + 1 do!@#&	tab[x] = {}!@#&	!@#&	for y = 1, size * 2 + 1 do!@#&		if x % 2 == 0 and y % 2 == 0 then -- Fill cells (empty)!@#&			tab[x][y] = \" \"!@#&		elseif x % 2 == 1 and y % 2 == 1 then -- Fill corners (full)!@#&			tab[x][y] = \"1\"!@#&		end!@#&	end!@#&end!@#&!@#&for x, tV in ipairs(m) do!@#&	for y, v in ipairs(tV) do!@#&		if x == size and y == size then!@#&			v[1] = v[1] and \"2\" or \" \"!@#&			v[2] = v[2] and \"2\" or \" \"!@#&			v[3] = v[3] and \"2\" or \" \"!@#&			v[4] = v[4] and \"2\" or \" \"!@#&			tab[x*2-1][y*2] = v[1] -- Up!@#&			tab[x*2+1][y*2] = v[2] -- Down!@#&			tab[x*2][y*2+1] = v[3] -- Right!@#&			tab[x*2][y*2-1] = v[4] -- Left!@#&		else!@#&			v[1] = v[1] and \"1\" or \" \"!@#&			v[2] = v[2] and \"1\" or \" \"!@#&			v[3] = v[3] and \"1\" or \" \"!@#&			v[4] = v[4] and \"1\" or \" \"!@#&			tab[x*2-1][y*2] = v[1] -- Up!@#&			tab[x*2+1][y*2] = v[2] -- Down!@#&			tab[x*2][y*2+1] = v[3] -- Right!@#&			tab[x*2][y*2-1] = v[4] -- Left!@#&		end!@#&	end!@#&end!@#&!@#&local gtab = {}!@#&!@#&for k, v in ipairs(tab) do!@#&	gtab[#gtab+1] = table.concat(v)!@#&end!@#&!@#&size = size * 2 + 1!@#&!@#&--[[!@#&local template = fs.open(\"maze3d_template\", \"r\")!@#&local game = fs.open(\"maze3d_game\", \"w\")!@#&!@#&game.writeLine(\"local mapH, mapW = \"..size..\",\"..size)!@#&game.writeLine(\"local dir = \"..(gtab[2]:sub(3,3) == \" \" and '0' or '88'))!@#&game.writeLine(\"local map = {\")!@#&!@#&for k, v in ipairs(gtab) do!@#&	game.writeLine('\"'..v..'\",')!@#&end!@#&!@#&game.writeLine(\"}\")!@#&!@#&game.writeLine(template.readAll())!@#&game.close()!@#&template.close()!@#&!@#&shell.run(\"maze3d_game\")!@#&!@#&fs.delete(\"maze3d_game\")!@#&fs.delete(\"maze3d_template\")]]!@#&!@#&local mapH, mapW = size, size!@#&local dir = gtab[2]:sub(3,3) == \" \" and '0' or '88'!@#&local map = gtab!@#&local startdir = dir!@#&!@#&------------------------------------------------------------------------------------------------------!@#&--GOPHER'S CODE HERE!@#&!@#&local buffer=term!@#&local loadedAPI=false!@#&!@#&local stime = os.clock()!@#&!@#&if redirect then!@#&  buffer=redirect.createRedirectBuffer()!@#&  print(\"redirect API found, using buffer\")!@#&else!@#&  local pe=printError!@#&  rawset(_G,\"printError\",error)  !@#&  local ok, err=pcall(os.loadAPI,\"redirect\")!@#&  if not ok then!@#&    print(\"trying \"..shell.dir()..\"/redirect\")!@#&    ok,err=pcall(os.loadAPI,shell.dir()..\"/redirect\")!@#&  end!@#&  if ok then    !@#&    print(\"Loaded redirect API, using buffer\")!@#&    buffer=redirect.createRedirectBuffer()!@#&    loadedAPI=true!@#&  else!@#&    print(\"redirect API not found or could not be loaded, drawing directly; this may cause flickering.\")!@#&  end!@#&  rawset(_G,\"printError\",pe)!@#&end !@#&!@#&local colorSchemes = {!@#&  {0,8}, --white+gray!@#&  {3,11}, --blue!@#&  {6,14}, --red!@#&  {5,13}, --green!@#&  {4,1}, --yellow/orange!@#&}!@#&!@#&!@#&local function cast(cx,cy,angle)!@#&  --direction vector!@#&  local vx,vy=math.cos(angle), math.sin(angle)!@#&  local slope=vy/vx!@#&  --next distance, x and y axis points!@#&  local ndx, ndy!@#&  --steps, distance and block!@#&  local dsx, dsy, bsx, bsy!@#&  if vx<0 then!@#&    local x=(cx%1)!@#&    bsx=-1!@#&    ndx=math.sqrt(x*x*(1+slope*slope))!@#&    dsx=math.sqrt((1+slope*slope))!@#&  else!@#&    local x=1-(cx%1)!@#&    bsx=1!@#&    ndx=math.sqrt(x*x*(1+slope*slope))!@#&    dsx=math.sqrt((1+slope*slope))!@#&  end!@#&!@#&  if vy<0 then!@#&    local y=(cy%1)!@#&    bsy=-1!@#&    ndy=math.sqrt(y*y*(1+1/(slope*slope)))!@#&    dsy=math.sqrt((1+1/(slope*slope)))!@#&  else!@#&    local y=1-(cy%1)!@#&    bsy=1!@#&    ndy=math.sqrt(y*y*(1+1/(slope*slope)))!@#&    dsy=math.sqrt((1+1/(slope*slope)))!@#&  end!@#&!@#&  local x,y=math.floor(cx),math.floor(cy)!@#&  while x>0 and x<=mapW and y>0 and y<=mapH do!@#&    local hitD!@#&    local isX!@#&    if ndx<ndy then!@#&      --x crossing is next!@#&      x=x+bsx!@#&      isX=true!@#&      hitD=ndx!@#&      ndx=ndx+dsx!@#&    else!@#&      y=y+bsy!@#&      isX=false!@#&      hitD=ndy!@#&      ndy=ndy+dsy!@#&    end!@#&    local wall=map[y]:sub(x,x)!@#&    if wall~=\" \" then!@#&      !@#&      return colorSchemes[tonumber(wall)][isX and 1 or 2], hitD!@#&    end!@#&  end  !@#&end!@#&!@#&local w,h=term.getSize()!@#&local centerX, centerY=math.floor((w+1)/2), math.floor((h+1)/2)!@#&!@#&local px, py=2.5,2.5!@#&--local dir=0!@#&local fx,fy!@#&local speed=.1!@#&local turnSpeed=4!@#&!@#&local function turn(amt)!@#&  dir=dir+amt!@#&  fx,fy=math.cos(math.rad(dir)), math.sin(math.rad(dir))!@#&end!@#&!@#&turn(0)!@#&!@#&--build table of angles and base distances per scanline!@#&local screenDist=.55*w!@#&local scan={}!@#&!@#&for x=1,w do!@#&  local t={}!@#&  scan[x]=t!@#&  t.angle=math.atan2(x-centerX,screenDist)!@#&  t.dist=((x-centerX)^2+screenDist^2)^.5/screenDist!@#&end!@#&  !@#&local function redraw()!@#&  if buffer.isBuffer then!@#&    term.redirect(buffer)!@#&  end!@#&  for x=1,w do!@#&    local wall,dist=cast(px,py,math.rad(dir)+scan[x].angle)!@#&    if wall then!@#&      --calc wall height based on distance!@#&      local height=scan[x].dist/dist!@#&      height=math.floor(math.min(height*centerY,(h+1)/2))!@#&      term.setBackgroundColor(colors.gray)!@#&      for y=1,(h+1)/2-height-1 do!@#&        term.setCursorPos(x,y)!@#&        term.write(\" \")!@#&      end!@#&      for y=centerY+height+1,h do!@#&        term.setCursorPos(x,y)!@#&        term.write(\" \")!@#&      end!@#&      term.setBackgroundColor(2^wall)!@#&      for y=centerY-height,centerY+height do!@#&        term.setCursorPos(x,y)!@#&        term.write(\" \")!@#&      end!@#&    end!@#&  end!@#&  if buffer.isBuffer then!@#&    term.restore()!@#&    buffer.blit()!@#&  end!@#&end!@#&!@#&local function clampCollision(x,y,radius)!@#&  --am I *in* a block?!@#&  local gx,gy=math.floor(x),math.floor(y)!@#&  if map[gy]:sub(gx,gx)~=\" \" then!@#&    --I am. Complete fail, do nothing.!@#&    return x,y!@#&  end!@#&  !@#&  --ok, check the neighbors.!@#&  local right=math.floor(x+radius)>gx!@#&  local left=math.floor(x-radius)<gx!@#&  local front=math.floor(y-radius)<gy!@#&  local back=math.floor(y+radius)>gy!@#&  !@#&  local pushed=false!@#&  !@#&  if right and map[gy]:sub(gx+1,gx+1)~=\" \" then!@#&    --push left!@#&    pushed=true!@#&    x=gx+1-radius!@#&  elseif left  and map[gy]:sub(gx-1,gx-1)~=\" \" then!@#&    --push right!@#&    pushed=true!@#&    x=gx+radius!@#&  end!@#&  !@#&  if front and map[gy-1]:sub(gx,gx)~=\" \" then!@#&    --push back!@#&    pushed=true!@#&    y=gy+radius!@#&  elseif back and map[gy+1]:sub(gx,gx)~=\" \" then!@#&    --push forward!@#&    pushed=true!@#&!@#&!@#&!@#&    y=gy+1-radius!@#&  end!@#& !@#&  --if I wasn't pushed out on any side, I might be hitting a corner!@#&  if not pushed then!@#&    --square rad!@#&    local r2=radius^2!@#&    local pushx,pushy=0,0!@#&    if left then!@#&      if front and map[gy-1]:sub(gx-1,gx-1)~=\" \" then!@#&        --check front-left!@#&        local dist2=(gx-x)^2+(gy-y)^2!@#&        if dist2<r2 then!@#&          local pushd=(r2-dist2)/2^.5!@#&          pushx,pushy=pushd,pushd!@#&        end!@#&      elseif back and map[gy+1]:sub(gx-1,gx-1)~=\" \" then!@#&        local dist2=(gx-x)^2+(gy+1-y)^2!@#&        if dist2<r2 then!@#&          local pushd=(r2-dist2)/2^.5!@#&          pushx,pushy=pushd,-pushd!@#&        end!@#&      end!@#&    elseif right then!@#&      if front and map[gy-1]:sub(gx+1,gx+1)~=\" \" then!@#&        --check front-left!@#&        local dist2=(gx+1-x)^2+(gy-y)^2!@#&        if dist2<r2 then!@#&          local pushd=(r2-dist2)/2^.5!@#&          pushx,pushy=-pushd,pushd!@#&        end!@#&      elseif back and map[gy+1]:sub(gx+1,gx+1)~=\" \" then!@#&        local dist2=(gx+1-x)^2+(gy+1-y)^2!@#&        if dist2<r2 then!@#&          local pushd=(r2-dist2)/2^.5!@#&          pushx,pushy=-pushd,-pushd!@#&        end!@#&      end!@#&    end!@#&    x=x+pushx!@#&    y=y+pushy!@#&  end!@#&  !@#&  return x,y!@#&end!@#&!@#&term.setBackgroundColor(colors.black)!@#&--term.setTextColor(colors.white)!@#&term.clear()!@#&term.setCursorPos(1, 1)!@#&!@#&term.setTextColor(colors.yellow)!@#&write(\"Move:                                          \")!@#&term.setTextColor(colors.lime)!@#&print(\"WASD\")!@#&!@#&term.setTextColor(colors.yellow)!@#&write(\"Turn:                              \")!@#&term.setTextColor(colors.lime)!@#&print(\"Left/Right arrow\")!@#&!@#&term.setTextColor(colors.yellow)!@#&write(\"Teleport to start:                                \")!@#&term.setTextColor(colors.lime)!@#&print(\"R\")!@#&!@#&term.setTextColor(colors.yellow)!@#&write(\"Quit:                                             \")!@#&term.setTextColor(colors.lime)!@#&print(\"Q\\n\")!@#&!@#&term.setTextColor(colors.white)!@#&write(\"Goal: go to \")!@#&term.setTextColor(colors.lightBlue)!@#&write(\"blue\")!@#&term.setTextColor(colors.white)!@#&print(\" spot (opposite corner of the map)\\n\\n\\n\\n\")!@#&!@#&term.setTextColor(colors.white)!@#&cprint(\"Press any key to start!\")!@#&!@#&os.pullEvent(\"key\")!@#&!@#&local frameTimer=os.startTimer(0.5)!@#&local prevTick=0!@#&local dirty=true!@#&local win = false!@#&while true do!@#&  px,py=clampCollision(px,py,.25)!@#&  if dirty then!@#&    redraw()!@#&    dirty=false!@#&  end!@#&  !@#&  local e={os.pullEvent()}!@#&  if e[1]==\"key\" then!@#&    if e[2]==keys.left then!@#&      turn(-turnSpeed)!@#&      dirty=true!@#&    elseif e[2]==keys.right then!@#&      turn(turnSpeed)!@#&      dirty=true!@#&    elseif e[2]==keys.up or e[2]==keys.w then!@#&      px=px+fx*speed!@#&      py=py+fy*speed!@#&      dirty=true!@#&    elseif e[2]==keys.down or e[2]==keys.s then!@#&      px=px-fx*speed!@#&      py=py-fy*speed!@#&      dirty=true!@#&    elseif e[2]==keys.a then!@#&      px=px+fy*speed!@#&      py=py-fx*speed!@#&      dirty=true!@#&    elseif e[2]==keys.d then!@#&      px=px-fy*speed!@#&      py=py+fx*speed!@#&      dirty=true!@#&    elseif e[2]==keys.q then!@#&      break!@#&    elseif e[2]==keys.r then!@#&      px,py = 2.5,2.5!@#&      dir=startdir!@#&      dirty=true!@#&    end!@#&    !@#&    if px >= mapW-1 and py >= mapH-1 then!@#&      win = true!@#&      break!@#&    end!@#&  end!@#&end!@#&!@#&!@#&if loadedAPI then!@#&  os.unloadAPI(\"redirect\")!@#&end!@#&!@#&-- JESUS PART!@#&!@#&-- The win/loose message!@#&term.setBackgroundColor(colors.white)!@#&term.setTextColor(colors.black)!@#&term.clear()!@#&term.setCursorPos(1, 1)!@#&!@#&if win then!@#&  local ntime = os.clock()!@#&  write(\"\\n\")!@#&  cprint(\"Congratulations!\")!@#&  cprint(\"You made it in\")!@#&  cprint(tostring(math.floor((ntime-stime)/60))..\" minutes and \"..tostring(math.ceil((ntime-stime)%60))..\" seconds\")!@#&  cprint(\"Size of maze: \"..(mapW-1)/2)!@#&sleep(1)!@#&else!@#&  write(\"\\n\")!@#&  cprint(\"Oh noes D:\")!@#&end!@#&!@#&!@#&!@#&parallel.waitForAny(!@#&  function() coroutine.yield(); os.pullEvent(\"key\"); coroutine.yield() end,!@#&  function() term.setBackgroundColor(colors.white); term.setTextColor(colors.black) while true do term.setCursorPos(18, 14); term.write(\"Press any key..\"); sleep(0.5); term.clearLine(); sleep(0.5) end end!@#&)!@#&!@#&term.setBackgroundColor(colors.black)!@#&term.setTextColor(colors.white)!@#&term.clear()!@#&term.setCursorPos(1, 1)!@#&cprint(\"  Maze by Jesusthekiller. Thanks for playing!\")!@#&cprint(\"3D engine by Gopher, He is A-W-E-S-O-M-E\")",["adventure"]="!@#&local tBiomes = {!@#&	\"in a forest\",!@#&	\"in a pine forest\",!@#&	\"knee deep in a swamp\",!@#&	!@#&	\"in a mountain range\",!@#&	\"in a desert\",!@#&	\"in a grassy plain\",!@#&	\"in frozen tundra\",!@#&	!@#&	--\"in the ocean\",!@#&}!@#&!@#&local function hasTrees( _nBiome )!@#&	return _nBiome <= 3!@#&end!@#&!@#&local function hasStone( _nBiome )!@#&	return _nBiome == 4!@#&end!@#&!@#&local function hasRivers( _nBiome )!@#&	return _nBiome ~= 3 and _nBiome ~= 5!@#&end!@#&!@#&local items = {!@#&	[\"no tea\"] = {!@#&		droppable = false,!@#&		desc = \"Pull yourself together man.\",!@#&	},!@#&	[\"a pig\"] = {!@#&		heavy = true,!@#&		creature = true,!@#&		drops = { \"some pork\" },!@#&		aliases = { \"pig\" },!@#&		desc = \"The pig has a square nose.\",!@#&	},!@#&	[\"a cow\"] = {!@#&		heavy = true,!@#&		creature = true,!@#&		aliases = { \"cow\" },!@#&		desc = \"The cow stares at you blankly.\",!@#&	},!@#&	[\"a sheep\"] = {!@#&		heavy = true,!@#&		creature = true,!@#&		hitDrops = { \"some wool\" },!@#&		aliases = { \"sheep\" },!@#&		desc = \"The sheep is fluffy.\",!@#&	},!@#&	[\"a chicken\"] = {!@#&		heavy = true,!@#&		creature = true,!@#&		drops = { \"some chicken\" },!@#&		aliases = { \"chicken\" },!@#&		desc = \"The chicken looks delicious.\",!@#&	},!@#&	[\"a creeper\"] = {!@#&		heavy = true,!@#&		creature = true,!@#&		monster = true,!@#&		aliases = { \"creeper\" },!@#&		desc = \"The creeper needs a hug.\",!@#&	},!@#&	[\"a skeleton\"] = {!@#&		heavy = true,!@#&		creature = true,!@#&		monster = true,!@#&		aliases = { \"skeleton\" },!@#&		nocturnal = true,!@#&		desc = \"The head bone's connected to the neck bone, the neck bones connected to the chest bone, the chest bones connected to the arm bone, the arm bones connected to the bow, and the bow is pointed at you.\",!@#&	},!@#&	[\"a zombie\"] = {!@#&		heavy = true,!@#&		creature = true,!@#&		monster = true,!@#&		aliases = { \"zombie\" },!@#&		nocturnal = true,!@#&		desc = \"All he wants to do is eat your brains.\",!@#&	},!@#&	[\"a spider\"] = {!@#&		heavy = true,!@#&		creature = true,!@#&		monster = true,!@#&		aliases = { \"spider\" },!@#&		desc = \"Dozens of eyes stare back at you.\",!@#&	},!@#&	[\"a cave entrance\"] = {!@#&		heavy = true,!@#&		aliases = { \"cave entance\", \"cave\", \"entrance\" },!@#&		desc = \"The entrance to the cave is dark, but it looks like you can climb down.\",!@#&	},!@#&	[\"an exit to the surface\"] = {!@#&		heavy = true,!@#&		aliases = { \"exit to the surface\", \"exit\", \"opening\" },!@#&		desc = \"You can just see the sky through the opening.\",!@#&	},!@#&	[\"a river\"] = {!@#&		heavy = true,!@#&		aliases = { \"river\" },!@#&		desc = \"The river flows majestically towards the horizon.\",!@#&	},!@#&	[\"some wood\"] = {!@#&		aliases = { \"wood\" },!@#&		material = true,!@#&		desc = \"You could easilly craft this wood into planks.\",!@#&	},!@#&	[\"some planks\"] = {!@#&		aliases = { \"planks\", \"wooden planks\", \"wood planks\" },!@#&		desc = \"You could easilly craft these planks into sticks.\",!@#&	},!@#&	[\"some sticks\"] = {!@#&		aliases = { \"sticks\", \"wooden sticks\", \"wood sticks\" },!@#&		desc = \"A perfect handle for torches or a pickaxe.\",!@#&	},!@#&	[\"a crafting table\"] = {!@#&		aliases = { \"crafting table\", \"craft table\", \"work bench\", \"workbench\", \"crafting bench\", \"table\", },!@#&		desc = \"It's a crafting table. I shouldn't tell you this, but these don't actually do anything in this game, you can craft tools whenever you like.\",!@#&	},!@#&	[\"a furnace\"] = {!@#&		aliases = { \"furnace\" },!@#&		desc = \"It's a furnace. Between you and me, these don't actually do anything in this game.\",!@#&	},!@#&	[\"a wooden pickaxe\"] = {!@#&		aliases = { \"pickaxe\", \"pick\", \"wooden pick\", \"wooden pickaxe\", \"wood pick\", \"wood pickaxe\" },!@#&		tool = true,!@#&		toolLevel = 1,!@#&		toolType = \"pick\",!@#&		desc = \"The pickaxe looks good for breaking stone and coal.\",!@#&	},!@#&	[\"a stone pickaxe\"] = {!@#&		aliases = { \"pickaxe\", \"pick\", \"stone pick\", \"stone pickaxe\" },!@#&		tool = true,!@#&		toolLevel = 2,!@#&		toolType = \"pick\",!@#&		desc = \"The pickaxe looks good for breaking iron.\",!@#&	},!@#&	[\"an iron pickaxe\"] = {!@#&		aliases = { \"pickaxe\", \"pick\", \"iron pick\", \"iron pickaxe\" },!@#&		tool = true,!@#&		toolLevel = 3,!@#&		toolType = \"pick\",!@#&		desc = \"The pickaxe looks strong enough to break diamond.\",!@#&	},!@#&	[\"a diamond pickaxe\"] = {!@#&		aliases = { \"pickaxe\", \"pick\", \"diamond pick\", \"diamond pickaxe\" },!@#&		tool = true,!@#&		toolLevel = 4,!@#&		toolType = \"pick\",!@#&		desc = \"Best. Pickaxe. Ever.\",!@#&	},!@#&	[\"a wooden sword\"] = {!@#&		aliases = { \"sword\", \"wooden sword\", \"wood sword\" },!@#&		tool = true,!@#&		toolLevel = 1,!@#&		toolType = \"sword\",!@#&		desc = \"Flimsy, but better than nothing.\",!@#&	},!@#&	[\"a stone sword\"] = {!@#&		aliases = { \"sword\", \"stone sword\" },!@#&		tool = true,!@#&		toolLevel = 2,!@#&		toolType = \"sword\",!@#&		desc = \"A pretty good sword.\",!@#&	},!@#&	[\"an iron sword\"] = {!@#&		aliases = { \"sword\", \"iron sword\" },!@#&		tool = true,!@#&		toolLevel = 3,!@#&		toolType = \"sword\",!@#&		desc = \"This sword can slay any enemy.\",!@#&	},!@#&	[\"a diamond sword\"] = {!@#&		aliases = { \"sword\", \"diamond sword\" },!@#&		tool = true,!@#&		toolLevel = 4,!@#&		toolType = \"sword\",!@#&		desc = \"Best. Sword. Ever.\",!@#&	},!@#&	[\"a wooden shovel\"] = {!@#&		aliases = { \"shovel\", \"wooden shovel\", \"wood shovel\" },!@#&		tool = true,!@#&		toolLevel = 1,!@#&		toolType = \"shovel\",!@#&		desc = \"Good for digging holes.\",!@#&	},!@#&	[\"a stone shovel\"] = {!@#&		aliases = { \"shovel\", \"stone shovel\" },!@#&		tool = true,!@#&		toolLevel = 2,!@#&		toolType = \"shovel\",!@#&		desc = \"Good for digging holes.\",!@#&	},!@#&	[\"an iron shovel\"] = {!@#&		aliases = { \"shovel\", \"iron shovel\" },!@#&		tool = true,!@#&		toolLevel = 3,!@#&		toolType = \"shovel\",!@#&		desc = \"Good for digging holes.\",!@#&	},!@#&	[\"a diamond shovel\"] = {!@#&		aliases = { \"shovel\", \"diamond shovel\" },!@#&		tool = true,!@#&		toolLevel = 4,!@#&		toolType = \"shovel\",!@#&		desc = \"Good for digging holes.\",!@#&	},!@#&	[\"some coal\"] = {!@#&		aliases = { \"coal\" },!@#&		ore = true,!@#&		toolLevel = 1,!@#&		toolType = \"pick\",!@#&		desc = \"That coal looks useful for building torches, if only you had a pickaxe to mine it.\",!@#&	},!@#&	[\"some dirt\"] = {!@#&		aliases = { \"dirt\" },!@#&		material = true,!@#&		desc = \"Why not build a mudhut?\",!@#&	},!@#&	[\"some stone\"] = {!@#&		aliases = { \"stone\", \"cobblestone\" },!@#&		material = true,!@#&		ore = true,!@#&		infinite = true,!@#&		toolLevel = 1,!@#&		toolType = \"pick\",!@#&		desc = \"Stone is useful for building things, and making stone pickaxes.\",!@#&	},!@#&	[\"some iron\"] = {!@#&		aliases = { \"iron\" },!@#&		material = true,!@#&		ore = true,!@#&		toolLevel = 2,!@#&		toolType = \"pick\",!@#&		desc = \"That iron looks mighty strong, you'll need a stone pickaxe to mine it.\",!@#&	},!@#&	[\"some diamond\"] = {!@#&		aliases = { \"diamond\", \"diamonds\" },!@#&		material = true,!@#&		ore = true,!@#&		toolLevel = 3,!@#&		toolType = \"pick\",!@#&		desc = \"Sparkly, rare, and impossible to mine without an iron pickaxe.\",!@#&	},!@#&	[\"some torches\"] = {!@#&		aliases = { \"torches\", \"torch\" },!@#&		desc = \"These won't run out for a while.\",!@#&	},!@#&	[\"a torch\"] = {!@#&		aliases = { \"torch\" },!@#&		desc = \"Fire, fire, burn so bright, won't you light my cave tonight?\",!@#&	},!@#&	[\"some wool\"] = {!@#&		aliases = { \"wool\" },!@#&		material = true,!@#&		desc = \"Soft and good for building.\",!@#&	},!@#&	[\"some pork\"] = {!@#&		aliases = { \"pork\", \"porkchops\" },!@#&		food = true,!@#&		desc = \"Delicious and nutricious.\",!@#&	},!@#&	[\"some chicken\"] = {!@#&		aliases = { \"chicken\" },!@#&		food = true,!@#&		desc = \"Finger licking good.\",!@#&	},!@#&}!@#&!@#&local tAnimals = {!@#&	\"a pig\", \"a cow\", \"a sheep\", \"a chicken\",!@#&}!@#&!@#&local tMonsters = {!@#&	\"a creeper\", \"a skeleton\", \"a zombie\", \"a spider\"!@#&}!@#&!@#&local tRecipes = {!@#&	[\"some planks\"] = { \"some wood\" },!@#&	[\"some sticks\"] = { \"some planks\" },!@#&	[\"some sticks\"] = { \"some planks\" },!@#&	[\"a crafting table\"] = { \"some planks\" },!@#&	[\"a furnace\"] = { \"some stone\" },!@#&	[\"some torches\"] = { \"some sticks\", \"some coal\" },!@#&	!@#&	[\"a wooden pickaxe\"] = { \"some planks\", \"some sticks\" },!@#&	[\"a stone pickaxe\"] = { \"some stone\", \"some sticks\" },!@#&	[\"an iron pickaxe\"] = { \"some iron\", \"some sticks\" },!@#&	[\"a diamond pickaxe\"] = { \"some diamond\", \"some sticks\" },!@#&!@#&	[\"a wooden sword\"] = { \"some planks\", \"some sticks\" },!@#&	[\"a stone sword\"] = { \"some stone\", \"some sticks\" },!@#&	[\"an iron sword\"] = { \"some iron\", \"some sticks\" },!@#&	[\"a diamond sword\"] = { \"some diamond\", \"some sticks\" },!@#&!@#&	[\"a wooden shovel\"] = { \"some planks\", \"some sticks\" },!@#&	[\"a stone shovel\"] = { \"some stone\", \"some sticks\" },!@#&	[\"an iron shovel\"] = { \"some iron\", \"some sticks\" },!@#&	[\"a diamond shovel\"] = { \"some diamond\", \"some sticks\" },!@#&}!@#&!@#&local tGoWest = {!@#&	\"(life is peaceful there)\",!@#&	\"(lots of open air)\",!@#&	\"(to begin life anew)\",!@#&	\"(this is what we'll do)\",!@#&	\"(sun in winter time)\",!@#&	\"(we will do just fine)\",!@#&	\"(where the skies are blue)\",!@#&	\"(this and more we'll do)\",!@#&}!@#&local nGoWest = 0!@#&!@#&local bRunning = true!@#&local tMap = { { {}, }, }!@#&local x,y,z = 0,0,0!@#&local inventory = {!@#&	[\"no tea\"] = items[\"no tea\"],!@#&}!@#&!@#&local nTurn = 0!@#&local nTimeInRoom = 0!@#&local bInjured = false!@#&!@#&local tDayCycle = {!@#&	\"It is daytime.\",!@#&	\"It is daytime.\",!@#&	\"It is daytime.\",!@#&	\"It is daytime.\",!@#&	\"It is daytime.\",!@#&	\"It is daytime.\",!@#&	\"It is daytime.\",!@#&	\"It is daytime.\",!@#&	\"The sun is setting.\",!@#&	\"It is night.\",!@#&	\"It is night.\",!@#&	\"It is night.\",!@#&	\"It is night.\",!@#&	\"It is night.\",!@#&	\"The sun is rising.\",!@#&}!@#&!@#&local function getTimeOfDay()!@#&	return math.fmod( math.floor(nTurn/3), #tDayCycle ) + 1!@#&end!@#&!@#&local function isSunny()!@#&	return (getTimeOfDay() < 10)!@#&end!@#&!@#&local function getRoom( x, y, z, dontCreate )!@#&	tMap[x] = tMap[x] or {}!@#&	tMap[x][y] = tMap[x][y] or {}!@#&	if not tMap[x][y][z] and dontCreate ~= true then!@#& 		local room = {!@#& 			items = {},!@#& 			exits = {},!@#& 			nMonsters = 0,!@#& 		}!@#&		tMap[x][y][z] = room!@#&		!@#&		if y == 0 then!@#&			-- Room is above ground!@#&!@#&			-- Pick biome!@#&			room.nBiome = math.random( 1, #tBiomes )!@#&			room.trees = hasTrees( room.nBiome )!@#&		!@#&			-- Add animals!@#&			if math.random(1,3) == 1 then!@#&				for n = 1,math.random(1,2) do!@#&					local sAnimal = tAnimals[ math.random( 1, #tAnimals ) ]!@#&					room.items[ sAnimal ] = items[ sAnimal ]!@#&				end!@#&			end!@#&			!@#&			-- Add surface ore!@#&			if math.random(1,5) == 1 or hasStone( room.nBiome ) then!@#&				room.items[ \"some stone\" ] = items[ \"some stone\" ]!@#&			end!@#&			if math.random(1,8) == 1 then!@#&				room.items[ \"some coal\" ] = items[ \"some coal\" ]!@#&			end!@#&			if math.random(1,8) == 1 and hasRivers( room.nBiome ) then!@#&				room.items[ \"a river\" ] = items[ \"a river\" ]!@#&			end!@#&		!@#&			-- Add exits!@#&			room.exits = {!@#&				[\"north\"] = true,!@#&				[\"south\"] = true,!@#&				[\"east\"] = true,!@#&				[\"west\"] = true,!@#&			}!@#&			if math.random(1,8) == 1 then!@#&				room.exits[\"down\"] = true!@#&				room.items[\"a cave entrance\"] = items[\"a cave entrance\"]!@#&			end!@#&						!@#&		else!@#&			-- Room is underground!@#&			-- Add exits!@#&			local function tryExit( sDir, sOpp, x, y, z )!@#&				local adj = getRoom( x, y, z, true )!@#&				if adj then!@#&					if adj.exits[sOpp] then!@#&						room.exits[sDir] = true!@#&					end!@#&				else!@#&					if math.random(1,3) == 1 then!@#&						room.exits[sDir] = true!@#&					end!@#&				end!@#&			end!@#&			!@#&			if y == -1 then!@#&				local above = getRoom( x, y + 1, z )!@#&				if above.exits[\"down\"] then!@#&					room.exits[\"up\"] = true!@#&					room.items[\"an exit to the surface\"] = items[\"an exit to the surface\"]!@#&				end!@#&			else!@#&				tryExit( \"up\", \"down\", x, y + 1, z )!@#&			end!@#&			!@#&			if y > -3 then!@#&				tryExit( \"down\", \"up\", x, y - 1, z )!@#&			end!@#&			!@#&			tryExit( \"east\", \"west\", x - 1, y, z )!@#&			tryExit( \"west\", \"east\", x + 1, y, z )!@#&			tryExit( \"north\", \"south\", x, y, z + 1 )!@#&			tryExit( \"south\", \"north\", x, y, z - 1 )	!@#&			!@#&			-- Add ores!@#&			room.items[ \"some stone\" ] = items[ \"some stone\" ]!@#&			if math.random(1,3) == 1 then!@#&				room.items[ \"some coal\" ] = items[ \"some coal\" ]!@#&			end!@#&			if math.random(1,8) == 1 then!@#&				room.items[ \"some iron\" ] = items[ \"some iron\" ]!@#&			end!@#&			if y == -3 and math.random(1,15) == 1 then!@#&				room.items[ \"some diamond\" ] = items[ \"some diamond\" ]!@#&			end!@#&			!@#&			-- Turn out the lights!@#&			room.dark = true!@#&		end!@#&	end!@#&	return tMap[x][y][z]!@#&end!@#&!@#&local function itemize( t )!@#&	local item = next( t )!@#&	if item == nil then!@#&		return \"nothing\"!@#&	end!@#&	!@#&	local text = \"\"!@#&	while item do!@#&		text = text .. item!@#&		!@#&		local nextItem = next( t, item )!@#&		if nextItem ~= nil then!@#&			local nextNextItem = next( t, nextItem )!@#&			if nextNextItem == nil then!@#&				text = text .. \" and \"!@#&			else!@#&				text = text .. \", \"!@#&			end!@#&		end!@#&		item = nextItem!@#&	end!@#&	return text!@#&end!@#&!@#&function findItem( _tList, _sQuery )!@#&	for sItem, tItem in pairs( _tList ) do!@#&		if sItem == _sQuery then!@#&			return sItem!@#&		end!@#&		if tItem.aliases ~= nil then!@#&			for n, sAlias in pairs( tItem.aliases ) do!@#&				if sAlias == _sQuery then!@#&					return sItem!@#&				end!@#&			end!@#&		end!@#&	end!@#&	return nil!@#&end!@#&!@#&local tMatches = {!@#&	[\"wait\"] = {!@#&		\"wait\",!@#&	},!@#&	[\"look\"] = {!@#&		\"look at the ([%a ]+)\",!@#&		\"look at ([%a ]+)\",!@#&		\"look\",!@#&		\"inspect ([%a ]+)\",!@#&		\"inspect the ([%a ]+)\",!@#&		\"inspect\",!@#&	},!@#&	[\"inventory\"] = {!@#&		\"check self\",!@#&		\"check inventory\",!@#&		\"inventory\",!@#&		\"i\",!@#&	},!@#&	[\"go\"] = {!@#&		\"go (%a+)\",!@#&		\"travel (%a+)\",!@#&		\"walk (%a+)\",!@#&		\"run (%a+)\",!@#&		\"go\",!@#&	},!@#&	[\"dig\"] = {!@#&		\"dig (%a+) using ([%a ]+)\",!@#&		\"dig (%a+) with ([%a ]+)\",!@#&		\"dig (%a+)\",!@#&		\"dig\",!@#&	},!@#&	[\"take\"] = {!@#&		\"pick up the ([%a ]+)\",!@#&		\"pick up ([%a ]+)\",!@#&		\"pickup ([%a ]+)\",!@#&		\"take the ([%a ]+)\",!@#&		\"take ([%a ]+)\",!@#&		\"take\",!@#&	},!@#&	[\"drop\"] = {!@#&		\"put down the ([%a ]+)\",!@#&		\"put down ([%a ]+)\",!@#&		\"drop the ([%a ]+)\",!@#&		\"drop ([%a ]+)\",!@#&		\"drop\",!@#&	},!@#&	[\"place\"] = {!@#&		\"place the ([%a ]+)\",!@#&		\"place ([%a ]+)\",!@#&		\"place\",!@#&	},!@#&	[\"cbreak\"] = {!@#&		\"punch the ([%a ]+)\",!@#&		\"punch ([%a ]+)\",!@#&		\"punch\",!@#&		\"break the ([%a ]+) with the ([%a ]+)\",!@#&		\"break ([%a ]+) with ([%a ]+) \",!@#&		\"break the ([%a ]+)\",!@#&		\"break ([%a ]+)\",!@#&		\"break\",!@#&	},!@#&	[\"mine\"] = {!@#&		\"mine the ([%a ]+) with the ([%a ]+)\",!@#&		\"mine ([%a ]+) with ([%a ]+)\",!@#&		\"mine ([%a ]+)\",!@#&		\"mine\",!@#&	},!@#&	[\"attack\"] = {!@#&		\"attack the ([%a ]+) with the ([%a ]+)\",!@#&		\"attack ([%a ]+) with ([%a ]+)\",!@#&		\"attack ([%a ]+)\",!@#&		\"attack\",!@#&		\"kill the ([%a ]+) with the ([%a ]+)\",!@#&		\"kill ([%a ]+) with ([%a ]+)\",!@#&		\"kill ([%a ]+)\",!@#&		\"kill\",!@#&		\"hit the ([%a ]+) with the ([%a ]+)\",!@#&		\"hit ([%a ]+) with ([%a ]+)\",!@#&		\"hit ([%a ]+)\",!@#&		\"hit\",!@#&	},!@#&	[\"craft\"] = {!@#&		\"craft a ([%a ]+)\",!@#&		\"craft some ([%a ]+)\",!@#&		\"craft ([%a ]+)\",!@#&		\"craft\",!@#&		\"make a ([%a ]+)\",!@#&		\"make some ([%a ]+)\",!@#&		\"make ([%a ]+)\",!@#&		\"make\",!@#&	},!@#&	[\"build\"] = {!@#&		\"build ([%a ]+) out of ([%a ]+)\",!@#&		\"build ([%a ]+) from ([%a ]+)\",!@#&		\"build ([%a ]+)\",!@#&		\"build\",!@#&	},!@#&	[\"eat\"] = {!@#&		\"eat a ([%a ]+)\",!@#&		\"eat the ([%a ]+)\",!@#&		\"eat ([%a ]+)\",!@#&		\"eat\",!@#&	},!@#&	[\"help\"] = {!@#&		\"help me\",!@#&		\"help\",!@#&	},!@#&	[\"exit\"] = {!@#&		\"exit\",!@#&		\"quit\",!@#&		\"goodbye\",!@#&		\"good bye\",!@#&		\"bye\",!@#&		\"farewell\",!@#&	},!@#&}!@#&!@#&local commands = {}!@#&function doCommand( text )!@#&	if text == \"\" then!@#&		commands[ \"noinput\" ]()!@#&		return!@#&	end!@#&	!@#&	for sCommand, t in pairs( tMatches ) do!@#&		for n, sMatch in pairs( t ) do!@#&			local tCaptures = { string.match( text, \"^\" .. sMatch .. \"$\" ) }!@#&			if #tCaptures ~= 0 then!@#&				local fnCommand = commands[ sCommand ]!@#&				if #tCaptures == 1 and tCaptures[1] == sMatch then!@#&					fnCommand()!@#&				else!@#&					fnCommand( unpack( tCaptures ) )!@#&				end!@#&				return!@#&			end!@#&		end!@#&	end!@#&	commands[ \"badinput\" ]()!@#&end!@#&!@#&function commands.wait()!@#&	print( \"Time passes...\" )!@#&end!@#&!@#&function commands.look( _sTarget )!@#&	local room = getRoom( x,y,z )!@#&	if room.dark then!@#&		print( \"It is pitch dark.\" )!@#&		return!@#&	end!@#&!@#&	if _sTarget == nil then!@#&		-- Look at the world!@#&		if y == 0 then!@#&			io.write( \"You are standing \" .. tBiomes[room.nBiome] .. \". \" )!@#&			print( tDayCycle[ getTimeOfDay() ] )!@#&		else!@#&			io.write( \"You are underground. \" )!@#&			if next( room.exits ) ~= nil then!@#&				print( \"You can travel \"..itemize( room.exits )..\".\" )!@#&			else!@#&				print()!@#&			end!@#&		end!@#&		if next( room.items ) ~= nil then!@#&			print( \"There is \" .. itemize( room.items ) .. \" here.\" )!@#&		end!@#&		if room.trees then!@#&			print( \"There are trees here.\" )!@#&		end!@#&		!@#&	else!@#&		-- Look at stuff!@#&		if room.trees and (_sTarget == \"tree\" or _sTarget == \"trees\") then!@#&			print( \"The trees look easy to break.\" )!@#&		elseif _sTarget == \"self\" or _sTarget == \"myself\" then!@#&			print( \"Very handsome.\" )!@#&		else!@#&			local tItem = nil!@#&			local sItem = findItem( room.items, _sTarget )!@#&			if sItem then!@#&				tItem = room.items[sItem]!@#&			else!@#&				sItem = findItem( inventory, _sTarget )!@#&				if sItem then!@#&					tItem = inventory[sItem]!@#&				end!@#&			end!@#&			!@#&			if tItem then!@#&				print( tItem.desc or (\"You see nothing special about \"..sItem..\".\") )!@#&			else!@#&				print( \"You don't see any \".._sTarget..\" here.\" )!@#&			end!@#&		end!@#&	end!@#&end!@#&!@#&function commands.go( _sDir )!@#&	local room = getRoom( x,y,z )!@#&	if _sDir == nil then!@#&		print( \"Go where?\" )!@#&		return!@#&	end!@#&	!@#&	if nGoWest ~= nil then!@#&		if _sDir == \"west\" then!@#&			nGoWest = nGoWest + 1!@#&			if nGoWest > #tGoWest then!@#&				nGoWest = 1!@#&			end!@#&			print( tGoWest[ nGoWest ] )!@#&		else!@#&			if nGoWest > 0 or nTurn > 6 then!@#&				nGoWest = nil!@#&			end!@#&		end!@#&	end!@#&	!@#&	if room.exits[_sDir] == nil then!@#&		print( \"You can't go that way.\" )!@#&		return!@#&	end!@#&	!@#&	if _sDir == \"north\" then!@#&		z = z + 1!@#&	elseif _sDir == \"south\" then!@#&		z = z - 1!@#&	elseif _sDir == \"east\" then!@#&		x = x - 1!@#&	elseif _sDir == \"west\" then!@#&		x = x + 1!@#&	elseif _sDir == \"up\" then!@#&		y = y + 1!@#&	elseif _sDir == \"down\" then!@#&		y = y - 1!@#&	else!@#&		print( \"I don't understand that direction.\" )!@#&		return!@#&	end!@#&	!@#&	nTimeInRoom = 0!@#&	doCommand( \"look\" )!@#&end!@#&!@#&function commands.dig( _sDir, _sTool )!@#&	local room = getRoom( x,y,z )!@#&	if _sDir == nil then!@#&		print( \"Dig where?\" )!@#&		return!@#&	end!@#&	!@#&	local sTool = nil!@#&	local tTool = nil!@#&	if _sTool ~= nil then!@#&		sTool = findItem( inventory, _sTool )!@#&		if not sTool then!@#&			print( \"You're not carrying a \".._sTool..\".\" )!@#&			return!@#&		end!@#&		tTool = inventory[ sTool ]!@#&	end!@#&	!@#&	local room = getRoom( x, y, z )!@#&	local bActuallyDigging = (room.exits[ _sDir ] ~= true)!@#&	if bActuallyDigging then!@#&		if sTool == nil or tTool.toolType ~= \"pick\" then!@#&			print( \"You need to use a pickaxe to dig through stone.\" )!@#&			return!@#&		end!@#&	end!@#&	!@#&	if _sDir == \"north\" then!@#&		room.exits[\"north\"] = true!@#&		z = z + 1!@#&		getRoom( x, y, z ).exits[\"south\"] = true!@#&!@#&	elseif _sDir == \"south\" then!@#&		room.exits[\"south\"] = true!@#&		z = z - 1!@#&		getRoom( x, y, z ).exits[\"north\"] = true!@#&		!@#&	elseif _sDir == \"east\" then!@#&		room.exits[\"east\"] = true!@#&		x = x - 1!@#&		getRoom( x, y, z ).exits[\"west\"] = true!@#&		!@#&	elseif _sDir == \"west\" then!@#&		room.exits[\"west\"] = true!@#&		x = x + 1!@#&		getRoom( x, y, z ).exits[\"east\"] = true!@#&		!@#&	elseif _sDir == \"up\" then!@#&		if y == 0 then!@#&			print( \"You can't dig that way.\" )!@#&			return!@#&		end!@#&!@#&		room.exits[\"up\"] = true!@#&		if y == -1 then!@#&			room.items[ \"an exit to the surface\" ] = items[ \"an exit to the surface\" ]!@#&		end!@#&		y = y + 1!@#&		!@#&		room = getRoom( x, y, z )!@#&		room.exits[\"down\"] = true!@#&		if y == 0 then!@#&			room.items[ \"a cave entrance\" ] = items[ \"a cave entrance\" ]!@#&		end!@#&		!@#&	elseif _sDir == \"down\" then!@#&		if y <= -3 then!@#&			print( \"You hit bedrock.\" )!@#&			return!@#&		end!@#&!@#&		room.exits[\"down\"] = true!@#&		if y == 0 then!@#&			room.items[ \"a cave entrance\" ] = items[ \"a cave entrance\" ]!@#&		end!@#&		y = y - 1!@#&		!@#&		room = getRoom( x, y, z )!@#&		room.exits[\"up\"] = true!@#&		if y == -1 then!@#&			room.items[ \"an exit to the surface\" ] = items[ \"an exit to the surface\" ]!@#&		end!@#&		!@#&	else!@#&		print( \"I don't understand that direction.\" )!@#&		return!@#&	end!@#&	!@#&	--!@#&	if bActuallyDigging then!@#&		if _sDir == \"down\" and y == -1 or!@#&		   _sDir == \"up\" and y == 0 then!@#&			inventory[ \"some dirt\" ] = items[ \"some dirt\" ]!@#&			inventory[ \"some stone\" ] = items[ \"some stone\" ]!@#&			print( \"You dig \".._sDir..\" using \"..sTool..\" and collect some dirt and stone.\" )!@#&		else!@#&			inventory[ \"some stone\" ] = items[ \"some stone\" ]!@#&			print( \"You dig \".._sDir..\" using \"..sTool..\" and collect some stone.\" )!@#&		end!@#&	end!@#&	!@#&	nTimeInRoom = 0!@#&	doCommand( \"look\" )!@#&end!@#&!@#&function commands.inventory()!@#&	print( \"You are carrying \" .. itemize( inventory ) .. \".\" )!@#&end!@#&!@#&function commands.drop( _sItem )!@#&	if _sItem == nil then!@#&		print( \"Drop what?\" )!@#&		return!@#&	end!@#&	!@#&	local room = getRoom( x,y,z )!@#&	local sItem = findItem( inventory, _sItem )!@#&	if sItem then!@#&		local tItem = inventory[ sItem ]!@#&		if tItem.droppable == false then!@#&			print( \"You can't drop that.\" )!@#&		else!@#&			room.items[ sItem ] = tItem!@#&			inventory[ sItem ] = nil!@#&			print( \"Dropped.\" )!@#&		end!@#&	else!@#&		print( \"You don't have a \".._sItem..\".\" )!@#&	end!@#&end!@#&!@#&function commands.place( _sItem )!@#&	if _sItem == nil then!@#&		print( \"Place what?\" )!@#&		return!@#&	end!@#&	!@#&	if _sItem == \"torch\" or _sItem == \"a torch\" then!@#&		local room = getRoom( x,y,z )!@#&		if inventory[\"some torches\"] or inventory[\"a torch\"] then!@#&			inventory[\"a torch\"] = nil!@#&			room.items[\"a torch\"] = items[\"a torch\"]!@#&			if room.dark then!@#&				print( \"The cave lights up under the torchflame.\" )!@#&				room.dark = false!@#&			elseif y == 0 and not isSunny() then!@#&				print( \"The night gets a little brighter.\" )!@#&			else!@#&				print( \"Placed.\" )!@#&			end!@#&		else!@#&			print( \"You don't have torches.\" )!@#&		end!@#&		return!@#&	end!@#&	!@#&	commands.drop( _sItem )!@#&end!@#&!@#&function commands.take( _sItem )!@#&	if _sItem == nil then!@#&		print( \"Take what?\" )!@#&		return!@#&	end!@#&!@#&	local room = getRoom( x,y,z )!@#&	local sItem = findItem( room.items, _sItem )!@#&	if sItem then!@#&		local tItem = room.items[ sItem ]!@#&		if tItem.heavy == true then!@#&			print( \"You can't carry \"..sItem..\".\" )!@#&		elseif tItem.ore == true then!@#&			print( \"You need to mine this ore.\" )!@#&		else!@#&			if tItem.infinite ~= true then!@#&				room.items[ sItem ] = nil!@#&			end!@#&			inventory[ sItem ] = tItem!@#&			!@#&			if inventory[\"some torches\"] and inventory[\"a torch\"] then!@#&				inventory[\"a torch\"] = nil!@#&			end!@#&			if sItem == \"a torch\" and y < 0 then!@#&				room.dark = true!@#&				print( \"The cave plunges into darkness.\" )!@#&			else!@#&				print( \"Taken.\" )!@#&			end!@#&		end!@#&	else!@#&		print( \"You don't see a \".._sItem..\" here.\" )!@#&	end!@#&end!@#&!@#&function commands.mine( _sItem, _sTool )!@#&	if _sItem == nil then!@#&		print( \"Mine what?\" )!@#&		return!@#&	end!@#&	if _sTool == nil then!@#&		print( \"Mine \".._sItem..\" with what?\" )!@#&		return!@#&	end	!@#&	commands.cbreak( _sItem, _sTool )!@#&end!@#&!@#&function commands.attack( _sItem, _sTool )!@#&	if _sItem == nil then!@#&		print( \"Attack what?\" )!@#&		return!@#&	end!@#&	commands.cbreak( _sItem, _sTool )!@#&end!@#&!@#&function commands.cbreak( _sItem, _sTool )!@#&	if _sItem == nil then!@#&		print( \"Break what?\" )!@#&		return!@#&	end!@#&	!@#&	local sTool = nil!@#&	if _sTool ~= nil then!@#&		sTool = findItem( inventory, _sTool )!@#&		if sTool == nil then!@#&			print( \"You're not carrying a \".._sTool..\".\" )!@#&			return!@#&		end!@#&	end!@#&!@#&	local room = getRoom( x,y,z )!@#&	if _sItem == \"tree\" or _sItem == \"trees\" or _sItem == \"a tree\" then!@#&		print( \"The tree breaks into blocks of wood, which you pick up.\" )!@#&		inventory[ \"some wood\" ] = items[ \"some wood\" ]!@#&		return!@#&	elseif _sItem == \"self\" or _sItem == \"myself\" then!@#&		if term.isColour() then!@#&			term.setTextColour( colours.red )!@#&		end!@#&		print( \"You have died.\" )!@#&		print( \"Score: &e0\" )!@#&		term.setTextColour( colours.white )!@#&		bRunning = false!@#&		return!@#&	end!@#&	!@#&	local sItem = findItem( room.items, _sItem )!@#&	if sItem then!@#&		local tItem = room.items[ sItem ]!@#&		if tItem.ore == true then!@#&			-- Breaking ore!@#&			if not sTool then!@#&				print( \"You need a tool to break this ore.\" )!@#&				return!@#&			end!@#&			local tTool = inventory[ sTool ]!@#&			if tTool.tool then!@#&				if tTool.toolLevel < tItem.toolLevel then!@#&					print( sTool ..\" is not strong enough to break this ore.\" )!@#&				elseif tTool.toolType ~= tItem.toolType then!@#&					print( \"You need a different kind of tool to break this ore.\" )!@#&				else!@#&					print( \"The ore breaks, dropping \"..sItem..\", which you pick up.\" )!@#&					inventory[ sItem ] = items[ sItem ]!@#&					if tItem.infinite ~= true then!@#&						room.items[ sItem ] = nil!@#&					end!@#&				end!@#&			else!@#&				print( \"You can't break \"..sItem..\" with \"..sTool..\".\")!@#&			end!@#&			!@#&		elseif tItem.creature == true then!@#&			-- Fighting monsters (or pigs)!@#&			local toolLevel = 0!@#&			local tTool = nil!@#&			if sTool then!@#&				tTool = inventory[ sTool ]!@#&				if tTool.toolType == \"sword\" then!@#&					toolLevel = tTool.toolLevel!@#&				end!@#&			end!@#&						!@#&			local tChances = { 0.2, 0.4, 0.55, 0.8, 1 }!@#&			if math.random() <= tChances[ toolLevel + 1 ] then!@#&				room.items[ sItem ] = nil!@#&				print( \"The \"..tItem.aliases[1]..\" dies.\" )!@#&	!@#&				if tItem.drops then!@#&					for n, sDrop in pairs( tItem.drops ) do!@#&						if not room.items[sDrop] then!@#&							print( \"The \"..tItem.aliases[1]..\" dropped \"..sDrop..\".\" )!@#&							room.items[sDrop] = items[sDrop]!@#&						end!@#&					end!@#&				end!@#&				!@#&				if tItem.monster then!@#&					room.nMonsters = room.nMonsters - 1!@#&				end!@#&			else!@#&				print( \"The \"..tItem.aliases[1]..\" is injured by your blow.\" )!@#&			end!@#&			!@#&			if tItem.hitDrops then!@#&				for n, sDrop in pairs( tItem.hitDrops ) do!@#&					if not room.items[sDrop] then!@#&						print( \"The \"..tItem.aliases[1]..\" dropped \"..sDrop..\".\" )!@#&						room.items[sDrop] = items[sDrop]!@#&					end!@#&				end!@#&			end!@#&		!@#&		else!@#&			print( \"You can't break \"..sItem..\".\" )!@#&		end!@#&	else!@#&		print( \"You don't see a \".._sItem..\" here.\" )!@#&	end!@#&end!@#&!@#&function commands.craft( _sItem )!@#&	if _sItem == nil then!@#&		print( \"Craft what?\" )!@#&		return!@#&	end!@#&	!@#&	if _sItem == \"computer\" or _sItem == \"a computer\" then!@#&		print( \"By creating a computer in a computer in a computer, you tear a hole in the spacetime continuum from which no mortal being can escape.\" )!@#&		if term.isColour() then!@#&			term.setTextColour( colours.red )!@#&		end!@#&		print( \"You have died.\" )!@#&		print( \"Score: &e0\" )!@#&		term.setTextColour( colours.white )!@#&		bRunning = false!@#&		return!@#&	end!@#&	!@#&	local room = getRoom( x,y,z )!@#&	local sItem = findItem( items, _sItem )!@#&	local tRecipe = (sItem and tRecipes[ sItem ]) or nil!@#&	if tRecipe then!@#&		for n,sReq in ipairs( tRecipe ) do!@#&			if inventory[sReq] == nil then!@#&				print( \"You don't have the items you need to craft \"..sItem..\".\" )!@#&				return!@#&			end!@#&		end!@#&		!@#&		for n,sReq in ipairs( tRecipe ) do!@#&			inventory[sReq] = nil!@#&		end!@#&		inventory[ sItem ] = items[ sItem ]!@#&		if inventory[\"some torches\"] and inventory[\"a torch\"] then!@#&			inventory[\"a torch\"] = nil!@#&		end!@#&		print( \"Crafted.\" )!@#&	else!@#&		print( \"You don't know how to make \"..(sItem or _sItem)..\".\" )!@#&	end	!@#&end!@#&!@#&function commands.build( _sThing, _sMaterial )!@#&	if _sThing == nil then!@#&		print( \"Build what?\" )!@#&		return!@#&	end!@#&		!@#&	local sMaterial = nil!@#&	if _sMaterial == nil then!@#&		for sItem, tItem in pairs( inventory ) do!@#&			if tItem.material then!@#&				sMaterial = sItem!@#&				break!@#&			end!@#&		end!@#&		if sMaterial == nil then!@#&			print( \"You don't have any building materials.\" )!@#&			return!@#&		end!@#&	else!@#&		sMaterial = findItem( inventory, _sMaterial )!@#&		if not sMaterial then!@#&			print( \"You don't have any \".._sMaterial )!@#&			return!@#&		end!@#&		!@#&		if inventory[sMaterial].material ~= true then!@#&			print( sMaterial..\" is not a good building material.\" )!@#&			return!@#&		end!@#&	end!@#&	!@#&	local alias = nil!@#&	if string.sub(_sThing, 1, 1) == \"a\" then!@#&		alias = string.match( _sThing, \"a ([%a ]+)\" )!@#&	end!@#&	!@#&	local room = getRoom( x,y,z )!@#&	inventory[sMaterial] = nil!@#&	room.items[ _sThing ] = {!@#&		heavy = true,!@#&		aliases = { alias },!@#&		desc = \"As you look at your creation (made from \"..sMaterial..\"), you feel a swelling sense of pride.\",!@#&	}!@#&!@#&	print( \"Your construction is complete.\" )!@#&end!@#&!@#&function commands.help()!@#&	local sText = !@#&		\"Welcome to adventure, the greatest text adventure game on CraftOS. \" ..!@#&		\"To get around the world, type actions, and the adventure will \" ..!@#&		\"be read back to you. The actions availiable to you are go, look, inspect, inventory, \" ..!@#&		\"take, drop, place, punch, attack, mine, dig, craft, build, eat and exit.\"!@#&	print( sText )!@#&end!@#&!@#&function commands.eat( _sItem )!@#&	if _sItem == nil then!@#&		print( \"Eat what?\" )!@#&		return!@#&	end!@#&!@#&	local sItem = findItem( inventory, _sItem )!@#&	if not sItem then!@#&		print( \"You don't have any \".._sItem..\".\" )!@#&		return!@#&	end!@#&	!@#&	local tItem = inventory[sItem]!@#&	if tItem.food then!@#&		print( \"That was delicious!\" )!@#&		inventory[sItem] = nil!@#&		!@#&		if bInjured then!@#&			print( \"You are no longer injured.\" )!@#&			bInjured = false!@#&		end!@#&	else!@#&		print( \"You can't eat \"..sItem..\".\" )!@#&	end!@#&end!@#&!@#&function commands.exit()!@#&	bRunning = false!@#&end!@#&!@#&function commands.badinput()!@#&	local tResponses = {!@#&		\"I don't understand.\",!@#&		\"I don't understand you.\",!@#&		\"You can't do that.\",!@#&		\"Nope.\",!@#&		\"Huh?\",!@#&		\"Say again?\",!@#&		\"That's crazy talk.\",!@#&		\"Speak clearly.\",!@#&		\"I'll think about it.\",!@#&		\"Let me get back to you on that one.\",!@#&		\"That doesn't make any sense.\",!@#&		\"What?\",!@#&	}!@#&	print( tResponses[ math.random(1,#tResponses) ] )!@#&end!@#&!@#&function commands.noinput()!@#&	local tResponses = {!@#&		\"Speak up.\",!@#&		\"Enunciate.\",!@#&		\"Project your voice.\",!@#&		\"Don't be shy.\",!@#&		\"Use your words.\",!@#&	}!@#&	print( tResponses[ math.random(1,#tResponses) ] )!@#&end!@#&!@#&local function simulate()!@#&	local bNewMonstersThisRoom = false!@#&	!@#&	-- Spawn monsters in nearby rooms!@#&	for sx = -2,2 do!@#&		for sy = -1,1 do!@#&			for sz = -2,2 do!@#&				local h = y + sy!@#&				if h >= -3 and h <= 0 then!@#&					local room = getRoom( x + sx, h, z + sz )!@#&					!@#&					-- Spawn monsters!@#&					if room.nMonsters < 2 and!@#&					   ((h == 0 and not isSunny() and not room.items[\"a torch\"]) or room.dark) and!@#&					   math.random(1,6) == 1 then!@#&					   !@#&						local sMonster = tMonsters[ math.random(1,#tMonsters) ]!@#&						if room.items[ sMonster ] == nil then!@#&					   		room.items[ sMonster ] = items[ sMonster ]!@#&					   		room.nMonsters = room.nMonsters + 1!@#&					   		!@#&					   		if sx == 0 and sy == 0 and sz == 0 and not room.dark then!@#&					   			print( \"From the shadows, \"..sMonster..\" appears.\" )!@#&					   			bNewMonstersThisRoom = true!@#&					   		end!@#&						end	!@#&					end!@#&					!@#&					-- Burn monsters!@#&					if h == 0 and isSunny() then!@#&						for n,sMonster in ipairs( tMonsters ) do!@#&							if room.items[sMonster] and items[sMonster].nocturnal then!@#&								room.items[sMonster] = nil!@#&						   		if sx == 0 and sy == 0 and sz == 0 and not room.dark then!@#&						   			print( \"With the sun high in the sky, the \"..items[sMonster].aliases[1]..\" bursts into flame and dies.\" )!@#&						   		end!@#&						   		room.nMonsters = room.nMonsters - 1!@#&						   	end!@#&						end!@#&					end	!@#&				end!@#&			end!@#&		end!@#&	end!@#&!@#&	-- Make monsters attack!@#&	local room = getRoom( x, y, z )!@#&	if nTimeInRoom >= 2 and not bNewMonstersThisRoom then!@#&		for n,sMonster in ipairs( tMonsters ) do!@#&			if room.items[sMonster] then!@#&				if math.random(1,4) == 1 and!@#&				   not (y == 0 and isSunny() and (sMonster == \"a spider\")) then!@#&					if sMonster == \"a creeper\" then!@#&						if room.dark then!@#&							print( \"A creeper explodes.\" )!@#&						else!@#&							print( \"The creeper explodes.\" )!@#&						end!@#&						room.items[sMonster] = nil!@#&						room.nMonsters = room.nMonsters - 1!@#&					else!@#&						if room.dark then!@#&							print( \"A \"..items[sMonster].aliases[1]..\" attacks you.\" )!@#&						else!@#&							print( \"The \"..items[sMonster].aliases[1]..\" attacks you.\" )!@#&						end!@#&					end!@#&					!@#&					if bInjured then!@#&						if term.isColour() then!@#&							term.setTextColour( colours.red )!@#&						end!@#&						print( \"You have died.\" )!@#&						print( \"Score: &e0\" )!@#&						term.setTextColour( colours.white )!@#&						bRunning = false!@#&						return!@#&					else!@#&						bInjured = true!@#&					end!@#&					!@#&					break!@#&				end!@#&			end!@#&		end!@#&	end!@#&	!@#&	-- Always print this!@#&	if bInjured then!@#&		if term.isColour() then!@#&			term.setTextColour( colours.red )!@#&		end!@#&		print( \"You are injured.\" )!@#&		term.setTextColour( colours.white )!@#&	end!@#&	!@#&	-- Advance time!@#&	nTurn = nTurn + 1!@#&	nTimeInRoom = nTimeInRoom + 1!@#&end!@#&!@#&doCommand( \"look\" )!@#&simulate()!@#&!@#&local tCommandHistory = {}!@#&while bRunning do!@#&	if term.isColour() then!@#&		term.setTextColour( colours.yellow )!@#&	end!@#&    write( \"? \" )!@#&	term.setTextColour( colours.white )!@#&		!@#&    local sRawLine = read( nil, tCommandHistory )!@#&    table.insert( tCommandHistory, sRawLine )!@#&    !@#&    local sLine = nil!@#&	for match in string.gmatch(sRawLine, \"%a+\") do!@#&		if sLine then!@#&			sLine = sLine .. \" \" .. string.lower(match)!@#&		else!@#&			sLine = string.lower(match)!@#&		end!@#&	end!@#&	!@#&	doCommand( sLine or \"\" )!@#&    if bRunning then!@#&	    simulate()!@#&	end!@#&end",},["apis"]={["seperator"]="function seperate(str, sep)!@#& local sep, fields = (sep~='' and sep) or \" \", {}!@#& local pattern = string.format(\"([^%s]+)\", sep)!@#&  str:gsub(pattern, function(c) fields[#fields+1] = c end)!@#& return fields!@#&end!@#&!@#&function help()!@#&  return \"seperator.seperate(string, seperation_character) returns table with every word seperated by seperation_character\",!@#&  \"seperator.listMethods() -lists all methods\"!@#&end!@#&!@#&function listMethods()!@#&  return \"seperator.help()\",!@#&  \"seperator.seperate(str, sep)\",!@#&  \"seperator.listMethods()\"!@#&end",},["programs"]={["npaintpro"]="--[[!@#&                NPaintPro!@#&                By NitrogenFingers!@#&]]--!@#& !@#&--The screen size!@#&local w,h = term.getSize()!@#&--Whether or not the program is currently waiting on user input!@#&local inMenu = false!@#&--Whether or not a drop down menu is active!@#&local inDropDown = false!@#&--Whether or not animation tools are enabled (use -a to turn them on)!@#&local animated = false!@#&--Whether or not the text tools are enabled (use -t to turn them on)!@#&local textual = false!@#&--Whether or not \"blueprint\" display mode is on!@#&local blueprint = false!@#&--Whether or not the \"layer\" display is on!@#&local layerDisplay = false!@#&--Whether or not the interface is presently hidden!@#&local interfaceHidden = false!@#&--Whether or not the \"direction\" display is on!@#&local printDirection = false!@#&--The tool/mode npaintpro is currently in. Default is \"paint\"!@#&--For a list of modes, check out the help file!@#&local state = \"paint\"!@#&--Whether or not the program is presently running!@#&local isRunning = true!@#&--The rednet address of the 3D printer, if one has been attached!@#&local printer = nil!@#& !@#&--The list of every frame, containing every image in the picture/animation!@#&--Note: nfp files always have the picture at frame 1!@#&local frames = { }!@#&--How many frames are currently in the given animation.!@#&local frameCount = 1!@#&--The Colour Picker column!@#&local column = {}!@#&--The offset of visible colours in the picker column, if the screen cannot fit all 16!@#&local columnoffset = 0!@#&--The currently selected left and right colours!@#&local lSel,rSel = colours.black,nil!@#&--The amount of scrolling on the X and Y axis!@#&local sx,sy = 0,0!@#&--The alpha channel colour!@#&--Change this to change default canvas colour!@#&local alphaC = colours.white!@#&--The currently selected frame. Default is 1!@#&local sFrame = 1!@#&--The contents of the image buffer- contains contents, width and height!@#&local buffer = nil!@#&--The position, width and height of the selection rectangle!@#&local selectrect = nil!@#& !@#&--Whether or not text tools are enabled for this document!@#&local textEnabled = false!@#&--The X and Y positions of the text cursor!@#&local textCurX, textCurY = 1,1!@#& !@#&--The currently calculated required materials!@#&local requiredMaterials = {}!@#&--Whether or not required materials are being displayed in the pallette!@#&local requirementsDisplayed = false!@#&--A list of the rednet ID's all in-range printers located!@#&local printerList = { }!@#&--A list of the names of all in-range printers located. Same as the printerList in reference!@#&local printerNames = { }!@#&--The selected printer!@#&local selectedPrinter = 1!@#&--The X,Y,Z and facing of the printer!@#&local px,py,pz,pfx,pfz = 0,0,0,0,0!@#&--The form of layering used!@#&local layering = \"up\"!@#& !@#&--The animation state of the selection rectangle and image buffer!@#&local rectblink = 0!@#&--The ID for the timer!@#&local recttimer = nil!@#&--The radius of the brush tool!@#&local brushsize = 3!@#&--Whether or not \"record\" mode is activated (animation mode only)!@#&local record = false!@#&--The time between each frame when in play mode (animation mode only)!@#&local animtime = 0.3!@#& !@#&--The current \"cursor position\" in text mode!@#&local cursorTexX,cursorTexY = 1,1!@#& !@#&--A list of hexidecimal conversions from numbers to hex digits!@#&local hexnums = { [10] = \"a\", [11] = \"b\", [12] = \"c\", [13] = \"d\", [14] = \"e\" , [15] = \"f\" }!@#&--The NPaintPro logo (divine, isn't it?)!@#&local logo = {!@#&\"fcc              3   339\";!@#&\" fcc          9333    33\";!@#&\"  fcc        933 333  33\";!@#&\"   fcc       933  33  33\";!@#&\"    fcc      933   33 33\";!@#&\"     c88     333   93333\";!@#&\"     888     333    9333\";!@#&\"      333 3  333     939\";!@#&}!@#&--The Layer Up and Layer Forward printing icons!@#&local layerUpIcon = {!@#&        \"0000000\";!@#&        \"0088880\";!@#&        \"0888870\";!@#&        \"07777f0\";!@#&        \"0ffff00\";!@#&        \"0000000\";!@#&}!@#&local layerForwardIcon = {!@#&        \"0000000\";!@#&        \"000fff0\";!@#&        \"00777f0\";!@#&        \"0888700\";!@#&        \"0888000\";!@#&        \"0000000\";!@#&}!@#&--The available menu options in the ctrl menu!@#&local mChoices = {\"Save\",\"Exit\"}!@#&--The available modes from the dropdown menu- tables indicate submenus (include a name!)!@#&local ddModes = { { \"paint\", \"brush\", \"pippette\", \"flood\", \"move\", \"clear\", \"select\", name = \"painting\" }, { \"alpha to left\", \"alpha to right\", \"hide interface\", name = \"display\" }, \"help\", { \"print\", \"save\", \"exit\", name = \"file\" }, name = \"menu\" }!@#&--The available modes from the selection right-click menu!@#&local srModes = { \"cut\", \"copy\", \"paste\", \"clear\", \"hide\", name = \"selection\" }!@#&--The list of available help topics for each mode 127!@#&local helpTopics = {!@#&        [1] = {!@#&                name = \"Paint Mode\",!@#&                key = nil,!@#&                animonly = false,!@#&                textonly = false,!@#&                message = \"The default mode for NPaintPro, for painting pixels.\"!@#&                ..\" Controls here that are not overridden will apply for all other modes. Leaving a mode by selecting that mode \"!@#&                ..\" again will always send the user back to paint mode.\",!@#&                controls = {!@#&                        { \"Arrow keys\", \"Scroll the canvas\" },!@#&                        { \"Left Click\", \"Paint/select left colour\" },!@#&                        { \"Right Click\", \"Paint/select right colour\" },!@#&                        { \"Z Key\", \"Clear image on screen\" },!@#&                        { \"Tab Key\", \"Hide selection rectangle if visible\" },!@#&                        { \"Q Key\", \"Set alpha mask to left colour\" },!@#&                        { \"W Key\", \"Set alpha mask to right colour\" },!@#&                        { \"Number Keys\", \"Swich between frames 1-9\" },!@#&                        { \"</> keys\", \"Move to the next/last frame\" },!@#&                        { \"R Key\", \"Removes every frame after the current frame\"}!@#&                }!@#&        },!@#&        [2] = {!@#&                name = \"Brush Mode\",!@#&                key = \"b\",!@#&                animonly = false,!@#&                textonly = false,!@#&                message = \"Brush mode allows painting a circular area of variable diameter rather than a single pixel, working in \"..!@#&                \"the exact same way as paint mode in all other regards.\",!@#&                controls = {!@#&                        { \"Left Click\", \"Paints a brush blob with the left colour\" },!@#&                        { \"Right Click\", \"Paints a brush blob with the right colour\" },!@#&                        { \"Number Keys\", \"Changes the radius of the brush blob from 2-9\" }!@#&                }!@#&        },!@#&        [3] = {!@#&                name = \"Pippette Mode\",!@#&                key = \"p\",!@#&                animonly = false,!@#&                textonly = false,!@#&                message = \"Pippette mode allows the user to click the canvas and set the colour clicked to the left or right \"..!@#&                \"selected colour, for later painting.\",!@#&                controls = {!@#&                        { \"Left Click\", \"Sets clicked colour to the left selected colour\" },!@#&                        { \"Right Click\", \"Sets clicked colour to the right selected colour\" }!@#&                }!@#&        },!@#&        [4] = {!@#&                name = \"Move Mode\",!@#&                key = \"m\",!@#&                animonly = false,!@#&                textonly = false,!@#&                message = \"Mode mode allows the moving of the entire image on the screen. This is especially useful for justifying\"..!@#&                \" the image to the top-left for animations or game assets.\",!@#&                controls = {!@#&                        { \"Left/Right Click\", \"Moves top-left corner of image to selected square\" },!@#&                        { \"Arrow keys\", \"Moves image one pixel in any direction\" }!@#&                }!@#&        },!@#&        [5] = {!@#&                name = \"Flood Mode\",!@#&                key = \"f\",!@#&                animonly = false,!@#&                textonly = false,!@#&                message = \"Flood mode allows the changing of an area of a given colour to that of the selected colour. \"..!@#&                \"The tool uses a flood4 algorithm and will not fill diagonally. Transparency cannot be flood filled.\",!@#&                controls = {!@#&                        { \"Left Click\", \"Flood fills selected area to left colour\" },!@#&                        { \"Right Click\", \"Flood fills selected area to right colour\" }!@#&                }!@#&        },!@#&        [6] = {!@#&                name = \"Select Mode\",!@#&                key = \"s\",!@#&                animonly = false,!@#&                textonly = false,!@#&                message = \"Select mode allows the creation and use of the selection rectangle, to highlight specific areas on \"..!@#&                \"the screen and perform operations on the selected area of the image. The selection rectangle can contain an \"..!@#&                \"image on the clipboard- if it does, the image will flash inside the rectangle, and the rectangle edges will \"..!@#&                \"be light grey instead of dark grey.\",!@#&                controls = {!@#&                        { \"C Key\", \"Copy: Moves selection into the clipboard\" },!@#&                        { \"X Key\", \"Cut: Clears canvas under the rectangle, and moves it into the clipboard\" },!@#&                        { \"V Key\", \"Paste: Copys clipboard to the canvas\" },!@#&                        { \"Z Key\", \"Clears clipboard\" },!@#&                        { \"Left Click\", \"Moves top-left corner of rectangle to selected pixel\" },!@#&                        { \"Right Click\", \"Opens selection menu\" },!@#&                        { \"Arrow Keys\", \"Moves rectangle one pixel in any direction\" }!@#&                }!@#&        },!@#&        [7] = {!@#&                name = \"Corner Select Mode\",!@#&                key = nil,!@#&                animonly = false,!@#&                textonly = false,!@#&                message = \"If a selection rectangle isn't visible, this mode is selected automatically. It allows the \"..!@#&                \"defining of the corners of the rectangle- one the top-left and bottom-right corners have been defined, \"..!@#&                \"NPaintPro switches to selection mode. Note rectangle must be at least 2 pixels wide and high.\",!@#&                controls = {!@#&                        { \"Left/Right Click\", \"Defines a corner of the selection rectangle\" }!@#&                }!@#&        },!@#&        [8] = {!@#&                name = \"Play Mode\",!@#&                key = \"space\",!@#&                animonly = true,!@#&                textonly = false,!@#&                message = \"Play mode will loop through each frame in your animation at a constant rate. Editing tools are \"..!@#&                \"locked in this mode, and the coordinate display will turn green to indicate it is on.\",!@#&                controls = {!@#&                        { \"</> Keys\", \"Increases/Decreases speed of the animation\" },!@#&                        { \"Space Bar\", \"Returns to paint mode\" }!@#&                }!@#&        },!@#&        [9] = {!@#&                name = \"Record Mode\",!@#&                key = \"\\\\\",!@#&                animonly = true,!@#&                textonly = false,!@#&                message = \"Record mode is not a true mode, but influences how other modes work. Changes made that modify the \"..!@#&                \"canvas in record mode will affect ALL frames in the animation. The coordinates will turn red to indicate that \"..!@#&                \"record mode is on.\",!@#&                controls = {!@#&                        { \"\", \"Affects:\" },!@#&                        { \"- Paint Mode\", \"\" },!@#&                        { \"- Brush Mode\", \"\" },!@#&                        { \"- Cut and Paste in Select Mode\", \"\"},!@#&                        { \"- Move Mode\", \"\"}!@#&                }!@#&        },!@#&		[10] = {!@#&				name = \"Hide Interface\",!@#&				key = \"~\",!@#&				animonly = false,!@#&				textonly = false,!@#&				message = \"Hides the sidebar and colour picker so only the image is visible.\"..!@#&				\" The program can be started with the interface hidden using the -d command line option.\"..!@#&				\" When hidden, if a file is animated it will automatically go to play mode.\\n\"..!@#&				\"Note that all other input is locked until the display is revealed again in this\"..!@#&				\" mode.\",!@#&				controls = {!@#&                    { \"</> Keys\", \"Increases/Decreases speed of the animation\" },!@#&					{ \"~ Key\", \"Shows interface\"}!@#&				}!@#&		},!@#&        [11] = {!@#&                name = \"Help Mode\",!@#&                key = \"h\",!@#&                animonly = false,!@#&                textonly = false,!@#&                message = \"Displays this help screen. Clicking on options will display help on that topic. Clicking out of the screen\"..!@#&                \" will leave this mode.\",!@#&                controls = {!@#&                        { \"Left/Right Click\", \"Displays a topic/Leaves the mode\" }!@#&                }!@#&        },!@#&        [12] = {!@#&                name = \"File Mode\",!@#&                key = nil,!@#&                animonly = false,!@#&                textonly = false,!@#&                message = \"Clicking on the mode display at the bottom of the screen will open the options menu. Here you can\"..!@#&                \" activate all of the modes in the program with a simple mouse click. Pressing left control will open up the\"..!@#&                \" file menu automatically.\",!@#&                controls = {!@#&                        { \"leftCtrl\", \"Opens the file menu\" },!@#&                        { \"leftAlt\", \"Opens the paint menu\" }!@#&                }!@#&        },!@#&        [13] = {!@#&                name = \"Text Mode\",!@#&                key = \"t\",!@#&                animonly = false,!@#&                textonly = true,!@#&                message = \"In this mode, the user is able to type letters onto the document for display. The left colour \"..!@#&                \"pallette value determines what colour the text will be, and the right determines what colour the background \"..!@#&                \"will be (set either to nil to keep the same colours as already there).\",!@#&                controls = {!@#&                        { \"Backspace\", \"Deletes the character on the previous line\" },!@#&                        { \"Arrow Keys\", \"Moves the cursor in any direction\" },!@#&                        { \"Left Click\", \"Moves the cursor to beneath the mouse cursor\" }!@#&                }!@#&        },!@#&        [14] = {!@#&                name = \"Textpaint Mode\",!@#&                key = \"y\",!@#&                animonly = false,!@#&                textonly = true,!@#&                message = \"Allows the user to paint any text on screen to the desired colour with the mouse. If affects the text colour\"..!@#&                \" values rather than the background values, but operates identically to paint mode in all other regards.\",!@#&                controls = {!@#&                        { \"Left Click\", \"Paints the text with the left colour\" },!@#&                        { \"Right Click\", \"Paints the text with the right colour\" }!@#&                }!@#&        },!@#&        [15] = {!@#&                name = \"About NPaintPro\",!@#&                keys = nil,!@#&                animonly = false,!@#&                textonly = false,!@#&                message = \"NPaintPro: The feature-bloated paint program for ComputerCraft by Nitrogen Fingers.\",!@#&                controls = {!@#&                        { \"Testers:\", \" \"},!@#&                        { \" \", \"Faubiguy\"},!@#&                        { \" \", \"TheOriginalBIT\"}!@#&                }!@#&        }!@#&}!@#&--The \"bounds\" of the image- the first/last point on both axes where a pixel appears!@#&local toplim,botlim,leflim,riglim = nil,nil,nil,nil!@#&--The selected path!@#&local sPath = nil!@#&!@#&!@#&--Screen Size Parameters- decided dynamically further down the program!@#&--Whether or not the help screen is available!@#&local helpAvailable = true!@#&--Whether or not the main menu is available!@#&local mainAvailable = true!@#&--Whether or not selection box dropdowns are available!@#&local boxdropAvailable = true!@#&--Whether or not a manual file descriptor option is available (part of the title)!@#&local filemakerAvailable = true!@#& !@#&--[[  !@#&                        Section:  Helpers              !@#&]]--!@#& !@#&--[[Converts a colour parameter into a single-digit hex coordinate for the colour!@#&    Params: colour:int = The colour to be converted!@#&        Returns:string A string conversion of the colour!@#&]]--!@#&local function getHexOf(colour)!@#&        if not colour or not tonumber(colour) then!@#&                return \" \"!@#&        end!@#&        local value = math.log(colour)/math.log(2)!@#&        if value > 9 then!@#&                value = hexnums[value]!@#&        end!@#&        return value!@#&end!@#& !@#&--[[Converts a hex digit into a colour value!@#&        Params: hex:?string = the hex digit to be converted!@#&        Returns:string A colour value corresponding to the hex, or nil if the character is invalid!@#&]]--!@#&local function getColourOf(hex)!@#&        local value = tonumber(hex, 16)!@#&        if not value then return nil end!@#&        value = math.pow(2,value)!@#&        return value!@#&end!@#& !@#&--[[Finds the largest width and height of the text in a given menu. Should conform to the format!@#&	of all standard menus (number indexed values and a 'name' field).!@#&	This is done recursively. It's just easier that way.!@#&	Params: menu:table = the table being tested for the max width and height!@#&	Returns:number,number = the max width and height of the text or names of any menu or submenu.!@#&]]--!@#&local function findMaxWH(menu)!@#&	local wmax,hmax = #menu.name, #menu!@#&	for _,entry in pairs(menu) do!@#&		if type(entry) == \"table\" then!@#&			local nw,nh = findMaxWH(entry)!@#&			wmax = math.max(wmax,nw)!@#&			hmax = math.max(hmax,nh)!@#&		else!@#&			wmax = math.max(wmax,#entry)!@#&		end!@#&	end!@#&	return wmax,hmax!@#&end!@#& !@#&--[[Determines what services are available depending on the size of the screen. Certain features!@#&	may be disabled with screen real estate does not allow for it.!@#&	Params: none!@#&	Returns:nil!@#&]]--!@#&local function determineAvailableServices()!@#&	--Help files were designed to fit a 'standard' CC screen, of 51 x 19. The height of the screen!@#&	--needs to match the number of available options plus white space, but for consistency with!@#&	--the files themselves, a natural size of 51 is required for the screen width as well.!@#&	if w < 51 or h < #helpTopics+3 then helpAvailable = false end!@#&	if not helpAvailable then table.remove(ddModes,3) end!@#&	--These hard-coded values mirror the drawLogo values, with extra consideration for the !@#&	--additional menu options!@#&	if h < 14 or w < 24 then filemakerAvailable = false end!@#&	!@#&	--Menus can't cover the picker and need 2 spaces for branches. 4 whitespace on X total.!@#&	--Menus need a title and can't eclipse the footer. 2 whitespace on Y total.!@#&	local wmin,hmin = findMaxWH(ddModes)!@#&	if w < wmin+4 or h < hmin+2 then mainAvailable = false end!@#&	wmin,hmin = findMaxWH(srModes)!@#&	if w < wmin+4 or h < hmin+2 then boxdropAvailable = false end!@#&end!@#& !@#&--[[Finds the biggest and smallest bounds of the image- the outside points beyond which pixels do not appear!@#&        These values are assigned to the \"lim\" parameters for access by other methods!@#&        Params: forAllFrames:bool = True if all frames should be used to find bounds, otherwise false or nil!@#&        Returns:nil!@#&]]--!@#&local function updateImageLims(forAllFrames)!@#&        local f,l = sFrame,sFrame!@#&        if forAllFrames == true then f,l = 1,framecount end!@#&       !@#&        toplim,botlim,leflim,riglim = nil,nil,nil,nil!@#&        for locf = f,l do!@#&                for y,_ in pairs(frames[locf]) do!@#&                        if type(y) == \"number\" then!@#&                                for x,_ in pairs(frames[locf][y]) do!@#&                                        if frames[locf][y][x] ~= nil then!@#&                                                if leflim == nil or x < leflim then leflim = x end!@#&                                                if toplim == nil or y < toplim then toplim = y end!@#&                                                if riglim == nil or x > riglim then riglim = x end!@#&                                                if botlim == nil or y > botlim then botlim = y end!@#&                                        end!@#&                                end!@#&                        end!@#&                end!@#&        end!@#&       !@#&        --There is just... no easier way to do this. It's horrible, but necessary!@#&        if textEnabled then!@#&                for locf = f,l do!@#&                        for y,_ in pairs(frames[locf].text) do!@#&                                for x,_ in pairs(frames[locf].text[y]) do!@#&                                        if frames[locf].text[y][x] ~= nil then!@#&                                                if leflim == nil or x < leflim then leflim = x end!@#&                                                if toplim == nil or y < toplim then toplim = y end!@#&                                                if riglim == nil or x > riglim then riglim = x end!@#&                                                if botlim == nil or y > botlim then botlim = y end!@#&                                        end!@#&                                end!@#&                        end!@#&                        for y,_ in pairs(frames[locf].textcol) do!@#&                                for x,_ in pairs(frames[locf].textcol[y]) do!@#&                                        if frames[locf].textcol[y][x] ~= nil then!@#&                                                if leflim == nil or x < leflim then leflim = x end!@#&                                                if toplim == nil or y < toplim then toplim = y end!@#&                                                if riglim == nil or x > riglim then riglim = x end!@#&                                                if botlim == nil or y > botlim then botlim = y end!@#&                                        end!@#&                                end!@#&                        end!@#&                end!@#&        end!@#&end!@#& !@#&--[[Determines how much of each material is required for a print. Done each time printing is called.!@#&        Params: none!@#&        Returns:table A complete list of how much of each material is required.!@#&]]--!@#&function calculateMaterials()!@#&        updateImageLims(animated)!@#&        requiredMaterials = {}!@#&        for i=1,16 do!@#&                requiredMaterials[i] = 0!@#&        end!@#&       !@#&        if not toplim then return end!@#&       !@#&        for i=1,#frames do!@#&                for y = toplim, botlim do!@#&                        for x = leflim, riglim do!@#&                                if type(frames[i][y][x]) == \"number\" then!@#&                                        requiredMaterials[math.log10(frames[i][y][x])/math.log10(2) + 1] =!@#&                                                requiredMaterials[math.log10(frames[i][y][x])/math.log10(2) + 1] + 1!@#&                                end    !@#&                        end!@#&                end!@#&        end!@#&end!@#& !@#& !@#&--[[Updates the rectangle blink timer. Should be called anywhere events are captured, along with a timer capture.!@#&        Params: nil!@#&        Returns:nil!@#&]]--!@#&local function updateTimer(id)!@#&        if id == recttimer then!@#&                recttimer = os.startTimer(0.5)!@#&                rectblink = (rectblink % 2) + 1!@#&        end!@#&end!@#& !@#&--[[Constructs a message based on the state currently selected!@#&        Params: nil!@#&        Returns:string A message regarding the state of the application!@#&]]--!@#&local function getStateMessage()!@#&        local msg = \" \"..string.upper(string.sub(state, 1, 1))..string.sub(state, 2, #state)..\" mode\"!@#&        if state == \"brush\" then msg = msg..\", size=\"..brushsize end!@#&        return msg!@#&end!@#& !@#&--[[Calls the rednet_message event, but also looks for timer events to keep then!@#&        system timer ticking.!@#&        Params: timeout:number how long before the event times out!@#&        Returns:number the id of the sender!@#&                   :number the message send!@#&]]--!@#&local function rsTimeReceive(timeout)!@#&        local timerID!@#&        if timeout then timerID = os.startTimer(timeout) end!@#&       !@#&        local id,key,msg = nil,nil!@#&        while true do!@#&                id,key,msg = os.pullEvent()!@#&               !@#&                if id == \"timer\" then!@#&                        if key == timerID then return!@#&                        else updateTimer(key) end!@#&                end!@#&                if id == \"rednet_message\" then!@#&                        return key,msg!@#&                end!@#&        end!@#&end!@#& !@#&--[[Draws a picture, in paint table format on the screen!@#&        Params: image:table = the image to display!@#&                        xinit:number = the x position of the top-left corner of the image!@#&                        yinit:number = the y position of the top-left corner of the image!@#&                        alpha:number = the color to display for the alpha channel. Default is white.!@#&        Returns:nil!@#&]]--!@#&local function drawPictureTable(image, xinit, yinit, alpha)!@#&        if not alpha then alpha = 1 end!@#&        for y=1,#image do!@#&                for x=1,#image[y] do!@#&                        term.setCursorPos(xinit + x-1, yinit + y-1)!@#&                        local col = getColourOf(string.sub(image[y], x, x))!@#&                        if not col then col = alpha end!@#&                        term.setBackgroundColour(col)!@#&                        term.write(\" \")!@#&                end!@#&        end!@#&end!@#& !@#&--[[  !@#&                        Section: Loading  !@#&]]--!@#& !@#&--[[Loads a non-animted paint file into the program!@#&        Params: path:string = The path in which the file is located!@#&        Returns:nil!@#&]]--!@#&local function loadNFP(path)!@#&        sFrame = 1!@#&        frames[sFrame] = { }!@#&        if fs.exists(path) then!@#&                local file = io.open(path, \"r\" )!@#&                local sLine = file:read()!@#&                local num = 1!@#&                while sLine do!@#&                        table.insert(frames[sFrame], num, {})!@#&                        for i=1,#sLine do!@#&                                frames[sFrame][num][i] = getColourOf(string.sub(sLine,i,i))!@#&                        end!@#&                        num = num+1!@#&                        sLine = file:read()!@#&                end!@#&                file:close()!@#&        end!@#&end!@#& !@#&--[[Loads a text-paint file into the program!@#&        Params: path:string = The path in which the file is located!@#&        Returns:nil!@#&]]--!@#&local function loadNFT(path)!@#&        sFrame = 1!@#&        frames[sFrame] = { }!@#&        frames[sFrame].text = { }!@#&        frames[sFrame].textcol = { }!@#&       !@#&        if fs.exists(path) then!@#&                local file = io.open(path, \"r\")!@#&                local sLine = file:read()!@#&                local num = 1!@#&                while sLine do!@#&                        table.insert(frames[sFrame], num, {})!@#&                        table.insert(frames[sFrame].text, num, {})!@#&                        table.insert(frames[sFrame].textcol, num, {})!@#&                       !@#&                        --As we're no longer 1-1, we keep track of what index to write to!@#&                        local writeIndex = 1!@#&                        --Tells us if we've hit a 30 or 31 (BG and FG respectively)- next char specifies the curr colour!@#&                        local bgNext, fgNext = false, false!@#&                        --The current background and foreground colours!@#&                        local currBG, currFG = nil,nil!@#&                        term.setCursorPos(1,1)!@#&                        for i=1,#sLine do!@#&                                local nextChar = string.sub(sLine, i, i)!@#&                                if nextChar:byte() == 30 then!@#&                                        bgNext = true!@#&                                elseif nextChar:byte() == 31 then!@#&                                        fgNext = true!@#&                                elseif bgNext then!@#&                                        currBG = getColourOf(nextChar)!@#&                                        bgNext = false!@#&                                elseif fgNext then!@#&                                        currFG = getColourOf(nextChar)!@#&                                        fgNext = false!@#&                                else!@#&                                        if nextChar ~= \" \" and currFG == nil then!@#&                                                currFG = colours.white!@#&                                        end!@#&                                        frames[sFrame][num][writeIndex] = currBG!@#&                                        frames[sFrame].textcol[num][writeIndex] = currFG!@#&                                        frames[sFrame].text[num][writeIndex] = nextChar!@#&                                        writeIndex = writeIndex + 1!@#&                                end!@#&                        end!@#&                        num = num+1!@#&                        sLine = file:read()!@#&                end!@#&                file:close()!@#&        end!@#&end!@#& !@#&--[[Loads an animated paint file into the program!@#&        Params: path:string = The path in which the file is located!@#&        Returns:nil!@#&]]--!@#&local function loadNFA(path)!@#&        frames[sFrame] = { }!@#&        if fs.exists(path) then!@#&                local file = io.open(path, \"r\" )!@#&                local sLine = file:read()!@#&                local num = 1!@#&                while sLine do!@#&                        table.insert(frames[sFrame], num, {})!@#&                        if sLine == \"~\" then!@#&                                sFrame = sFrame + 1!@#&                                frames[sFrame] = { }!@#&                                num = 1!@#&                        else!@#&                                for i=1,#sLine do!@#&                                        frames[sFrame][num][i] = getColourOf(string.sub(sLine,i,i))!@#&                                end!@#&                                num = num+1!@#&                        end!@#&                        sLine = file:read()!@#&                end!@#&                file:close()!@#&        end!@#&        framecount = sFrame!@#&        sFrame = 1!@#&end!@#& !@#&--[[Saves a non-animated paint file to the specified path!@#&        Params: path:string = The path to save the file to!@#&        Returns:nil!@#&]]--!@#&local function saveNFP(path)!@#&        local sDir = string.sub(sPath, 1, #sPath - #fs.getName(sPath))!@#&        if not fs.exists(sDir) then!@#&                fs.makeDir(sDir)!@#&        end!@#& !@#&        local file = io.open(path, \"w\")!@#&        updateImageLims(false)!@#&        if not toplim then!@#&                file:close()!@#&                return!@#&        end!@#&        for y=1,botlim do!@#&                local line = \"\"!@#&                if frames[sFrame][y] then!@#&                        for x=1,riglim do!@#&                                line = line..getHexOf(frames[sFrame][y][x])!@#&                        end!@#&                end!@#&                file:write(line..\"\\n\")!@#&        end!@#&        file:close()!@#&end!@#& !@#&--[[Saves a text-paint file to the specified path!@#&        Params: path:string = The path to save the file to!@#&        Returns:nil!@#&]]--!@#&local function saveNFT(path)!@#&        local sDir = string.sub(sPath, 1, #sPath - #fs.getName(sPath))!@#&        if not fs.exists(sDir) then!@#&                fs.makeDir(sDir)!@#&        end!@#&       !@#&        local file = io.open(path, \"w\")!@#&        updateImageLims(false)!@#&        if not toplim then!@#&                file:close()!@#&                return!@#&        end!@#&        for y=1,botlim do!@#&                local line = \"\"!@#&                local currBG, currFG = nil,nil!@#&                for x=1,riglim do!@#&                        if frames[sFrame][y] and frames[sFrame][y][x] ~= currBG then!@#&                                line = line..string.char(30)..getHexOf(frames[sFrame][y][x])!@#&                                currBG = frames[sFrame][y][x]!@#&                        end!@#&                        if frames[sFrame].textcol[y] and frames[sFrame].textcol[y][x] ~= currFG then!@#&                                line = line..string.char(31)..getHexOf(frames[sFrame].textcol[y][x])!@#&                                currFG = frames[sFrame].textcol[y][x]!@#&                        end!@#&                        if frames[sFrame].text[y] then!@#&                                local char = frames[sFrame].text[y][x]!@#&                                if not char then char = \" \" end!@#&                                line = line..char!@#&                        end!@#&                end!@#&                file:write(line..\"\\n\")!@#&        end!@#&        file:close()!@#&end!@#& !@#&--[[Saves a animated paint file to the specified path!@#&        Params: path:string = The path to save the file to!@#&        Returns:nil!@#&]]--!@#&local function saveNFA(path)!@#&        local sDir = string.sub(sPath, 1, #sPath - #fs.getName(sPath))!@#&        if not fs.exists(sDir) then!@#&                fs.makeDir(sDir)!@#&        end!@#&       !@#&        local file = io.open(path, \"w\")!@#&        updateImageLims(true)!@#&        if not toplim then!@#&                file:close()!@#&                return!@#&        end!@#&        for i=1,#frames do!@#&                for y=1,botlim do!@#&                        local line = \"\"!@#&                        if frames[i][y] then!@#&                                for x=1,riglim do!@#&                                        line = line..getHexOf(frames[i][y][x])!@#&                                end!@#&                        end!@#&                        file:write(line..\"\\n\")!@#&                end!@#&                if i < #frames then file:write(\"~\\n\") end!@#&        end!@#&        file:close()!@#&end!@#&!@#&--[[Runs a special pre-program dialogue to determine the filename and filepath. Done if!@#&	there's room, and a file name hasn't been specified!@#&	Params: none!@#&	Returns:bool= true if file is created; false otherwise!@#&]]--!@#&local function runFileMaker()!@#&	local newFName = \"\"!@#&	local fileType = 1!@#&	if animated then fileType = 2!@#&	elseif textEnabled then fileType = 3 end!@#&	!@#&	local tlx,tly = math.floor(w/2 - #logo[1]/2), math.floor(h/2 + #logo/2 + 1)!@#&!@#&	--This is done on top of the logo, so it backpedals a bit.!@#&	term.setCursorPos(tlx, tly)!@#&	term.clearLine()!@#&	term.write(\"Name: \")!@#&	term.setCursorPos(tlx, tly + 1)!@#&	term.clearLine()!@#&	term.write(\"Filetype:   Sprite\")!@#&	term.setCursorPos(tlx + 12, tly + 2)!@#&	term.write(\"Animation\")!@#&	term.setCursorPos(tlx + 12, tly + 3)!@#&	term.write(\"Text\")!@#&	!@#&	while true do!@#&		term.setCursorPos(tlx + 6, tly)!@#&		term.setBackgroundColour(colours.lightGrey)!@#&		term.setTextColour(colours.grey)!@#&		term.write(newFName..string.rep(\" \", 15-#newFName))!@#&		term.setBackgroundColour(colours.white)!@#&		term.setTextColour(colours.black)!@#&		local extension = \".nfp\"!@#&		if fileType == 2 then extension = \".nfa\"!@#&		elseif fileType == 3 then extension = \".nft\" end!@#&		term.write(extension)!@#&		!@#&		term.setBackgroundColour(colours.lightGrey)!@#&		term.setTextColour(colours.grey)!@#&		for i=1,3 do!@#&			term.setCursorPos(tlx + 24, tly + i)!@#&			if i==fileType then term.write(\"X\")!@#&			else term.write(\" \") end!@#&		end!@#&		!@#&		local fPath = shell.resolve(newFName..extension)!@#&		term.setCursorPos(tlx, tly + 3)!@#&		local fileValid = true!@#&		if (fs.exists(fPath) and fs.isDir(fPath)) or newFName == \"\" then!@#&			term.setBackgroundColour(colours.white)!@#&			term.setTextColour(colours.red)!@#&			term.write(\"Invalid \")!@#&			fileValid = false!@#&		elseif fs.exists(fPath) then!@#&			term.setBackgroundColour(colours.grey)!@#&			term.setTextColour(colours.lightGrey)!@#&			term.write(\" Edit  \")!@#&		else!@#&			term.setBackgroundColour(colours.grey)!@#&			term.setTextColour(colours.lightGrey)!@#&			term.write(\" Create \")!@#&		end!@#&		!@#&		term.setTextColour(colours.grey)!@#&		term.setCursorPos(tlx + 6 + #newFName, tly)!@#&		term.setCursorBlink(true)!@#&		!@#&		local id,p1,p2,p3 = os.pullEvent()!@#&		if id == \"key\" then!@#&			if p1 == keys.backspace and #newFName > 0 then !@#&				newFName = string.sub(newFName, 1, #newFName-1)!@#&			elseif p1 == keys.enter and fileValid then!@#&				sPath = fPath!@#&				return true!@#&			end!@#&		elseif id == \"char\" and p1 ~= \".\" and p1 ~= \" \" and #newFName < 15 then!@#&			newFName = newFName..p1!@#&		elseif id == \"mouse_click\" then!@#&			--The option boxes. Man, hardcoding is ugly...!@#&			if p2 == tlx + 24 then!@#&				for i=1,3 do !@#&					if p3 == tly+i then fileType = i end !@#&				end!@#&			end!@#&			if p3 == tly + 3 and p2 >= tlx and p2 <= tlx + 8 and fileValid then!@#&				sPath = fPath!@#&				return true!@#&			end!@#&		end!@#&	end!@#&end!@#& !@#&--[[Initializes the program, by loading in the paint file. Called at the start of each program.!@#&        Params: none!@#&        Returns:nil!@#&]]--!@#&local function init()!@#&        if textEnabled then!@#&                loadNFT(sPath)!@#&                table.insert(ddModes, 2, { \"text\", \"textpaint\", name = \"text\"})!@#&        elseif animated then!@#&                loadNFA(sPath)!@#&                table.insert(ddModes, #ddModes, { \"record\", \"play\", name = \"anim\" })!@#&                table.insert(ddModes, #ddModes, { \"go to\", \"remove\", name = \"frames\"})!@#&                table.insert(ddModes[2], #ddModes[2], \"blueprint on\")!@#&                table.insert(ddModes[2], #ddModes[2], \"layers on\")!@#&        else!@#&                loadNFP(sPath)!@#&                table.insert(ddModes[2], #ddModes[2], \"blueprint on\")!@#&        end!@#&		!@#&        for i=0,15 do!@#&                table.insert(column, math.pow(2,i))!@#&        end!@#&end!@#& !@#&--[[  !@#&                        Section: Drawing  !@#&]]--!@#& !@#& !@#&--[[Draws the rather superflous logo. Takes about 1 second, before user is able to move to the!@#&        actual program.!@#&        Params: none!@#&        Returns:bool= true if the file select ran successfully; false otherwise.!@#&]]--!@#&local function drawLogo()!@#&        term.setBackgroundColour(colours.white)!@#&        term.clear()!@#&		if h >= 12 and w >= 24 then!@#&			drawPictureTable(logo, w/2 - #logo[1]/2, h/2 - #logo/2, colours.white)!@#&			term.setBackgroundColour(colours.white)!@#&			term.setTextColour(colours.black)!@#&			local msg = \"NPaintPro\"!@#&			term.setCursorPos(w/2 - #msg/2, h/2 + #logo/2 + 1)!@#&			term.write(msg)!@#&			msg = \"By NitrogenFingers\"!@#&			term.setCursorPos(w/2 - #msg/2, h/2 + #logo/2 + 2)!@#&			term.write(msg)!@#&        elseif w >= 15 then!@#&			local msg = \"NPaintPro\"!@#&			term.setCursorPos(math.ceil(w/2 - #msg/2), h/2)!@#&			term.setTextColour(colours.cyan)!@#&			term.write(msg)!@#&			msg = \"NitrogenFingers\"!@#&			term.setCursorPos(math.ceil(w/2 - #msg/2), h/2 + 1)!@#&			term.setTextColour(colours.black)!@#&			term.write(msg)!@#&		else!@#&			local msg = \"NPP\"!@#&			term.setCursorPos(math.ceil(w/2 - #msg/2), math.floor(h/2))!@#&			term.setTextColour(colours.cyan)!@#&			term.write(msg)!@#&			msg = \"By NF\"!@#&			term.setCursorPos(math.ceil(w/2 - #msg/2), math.ceil(h/2))!@#&			term.setTextColour(colours.black)!@#&			term.write(msg)!@#&		end!@#&        os.pullEvent()!@#&end!@#& !@#&--[[Clears the display to the alpha channel colour, draws the canvas, the image buffer and the selection!@#&        rectanlge if any of these things are present.!@#&        Params: none!@#&        Returns:nil!@#&]]--!@#&local function drawCanvas()!@#&        --We have to readjust the position of the canvas if we're printing!@#&        turtlechar = \"@\"!@#&        if state == \"active print\" then!@#&                if layering == \"up\" then!@#&                        if py >= 1 and py <= #frames then!@#&                                sFrame = py!@#&                        end!@#&                        if pz < sy then sy = pz!@#&                        elseif pz > sy + h - 1 then sy = pz + h - 1 end!@#&                        if px < sx then sx = px!@#&                        elseif px > sx + w - 2 then sx = px + w - 2 end!@#&                else!@#&                        if pz >= 1 and pz <= #frames then!@#&                                sFrame = pz!@#&                        end!@#&                       !@#&                        if py < sy then sy = py!@#&                        elseif py > sy + h - 1 then sy = py + h - 1 end!@#&                        if px < sx then sx = px!@#&                        elseif px > sx + w - 2 then sx = px + w - 2 end!@#&                end!@#&               !@#&                if pfx == 1 then turtlechar = \">\"!@#&                elseif pfx == -1 then turtlechar = \"<\"!@#&                elseif pfz == 1 then turtlechar = \"V\"!@#&                elseif pfz == -1 then turtlechar = \"^\"!@#&                end!@#&        end!@#& !@#&        --Picture next!@#&        local topLayer, botLayer!@#&        if layerDisplay then!@#&                topLayer = sFrame!@#&                botLayer = 1!@#&        else!@#&                topLayer,botLayer = sFrame,sFrame!@#&        end!@#&       !@#&	    --How far the canvas draws. If the interface is visible, it stops short of that.!@#&	    local wlim,hlim = 0,0!@#&		if not interfaceHidden then!@#&			wlim = 2!@#&			hlim = 1!@#&		end!@#&	   !@#&        for currframe = botLayer,topLayer,1 do!@#&                for y=sy+1,sy+h-hlim do!@#&                        if frames[currframe][y] then!@#&                                for x=sx+1,sx+w-wlim do!@#&                                        term.setCursorPos(x-sx,y-sy)!@#&                                        if frames[currframe][y][x] then!@#&                                                term.setBackgroundColour(frames[currframe][y][x])!@#&                                                if textEnabled and frames[currframe].textcol[y][x] and frames[currframe].text[y][x] then!@#&                                                        term.setTextColour(frames[currframe].textcol[y][x])!@#&                                                        term.write(frames[currframe].text[y][x])!@#&                                                else!@#&                                                        term.write(\" \")!@#&                                                end!@#&                                        else!@#&                                                tileExists = false!@#&                                                for i=currframe-1,botLayer,-1 do!@#&                                                        if frames[i][y][x] then!@#&                                                                tileExists = true!@#&                                                                break!@#&                                                        end!@#&                                                end!@#&                                               !@#&                                                if not tileExists then!@#&                                                        if blueprint then!@#&                                                                term.setBackgroundColour(colours.blue)!@#&                                                                term.setTextColour(colours.white)!@#&                                                                if x == sx+1 and y % 4 == 1 then!@#&                                                                        term.write(\"\"..((y/4) % 10))!@#&                                                                elseif y == sy + 1 and x % 4 == 1 then!@#&                                                                        term.write(\"\"..((x/4) % 10))!@#&                                                                elseif x % 2 == 1 and y % 2 == 1 then!@#&                                                                        term.write(\"+\")!@#&                                                                elseif x % 2 == 1 then!@#&                                                                        term.write(\"|\")!@#&                                                                elseif y % 2 == 1 then!@#&                                                                        term.write(\"-\")!@#&                                                                else!@#&                                                                        term.write(\" \")!@#&                                                                end!@#&                                                        else!@#&                                                                term.setBackgroundColour(alphaC)!@#&                                                                if textEnabled and frames[currframe].textcol[y][x] and frames[currframe].text[y][x] then!@#&                                                                        term.setTextColour(frames[currframe].textcol[y][x])!@#&                                                                        term.write(frames[currframe].text[y][x])!@#&                                                                else!@#&                                                                        term.write(\" \")!@#&                                                                end!@#&                                                        end!@#&                                                end!@#&                                        end!@#&                                end!@#&                        else!@#&                                for x=sx+1,sx+w-wlim do!@#&                                        term.setCursorPos(x-sx,y-sy)!@#&                                       !@#&                                        tileExists = false!@#&                                        for i=currframe-1,botLayer,-1 do!@#&                                                if frames[i][y] and frames[i][y][x] then!@#&                                                        tileExists = true!@#&                                                        break!@#&                                                end!@#&                                        end!@#&                                       !@#&                                        if not tileExists then!@#&                                                if blueprint then!@#&                                                        term.setBackgroundColour(colours.blue)!@#&                                                        term.setTextColour(colours.white)!@#&                                                        if x == sx+1 and y % 4 == 1 then!@#&                                                                term.write(\"\"..((y/4) % 10))!@#&                                                        elseif y == sy + 1 and x % 4 == 1 then!@#&                                                                term.write(\"\"..((x/4) % 10))!@#&                                                        elseif x % 2 == 1 and y % 2 == 1 then!@#&                                                                term.write(\"+\")!@#&                                                        elseif x % 2 == 1 then!@#&                                                                term.write(\"|\")!@#&                                                        elseif y % 2 == 1 then!@#&                                                                term.write(\"-\")!@#&                                                        else!@#&                                                                term.write(\" \")!@#&                                                        end!@#&                                                else!@#&                                                        term.setBackgroundColour(alphaC)!@#&                                                        term.write(\" \")!@#&                                                end!@#&                                        end!@#&                                end!@#&                        end!@#&                end!@#&        end!@#&       !@#&        --Then the printer, if he's on!@#&        if state == \"active print\" then!@#&                local bgColour = alphaC!@#&                if layering == \"up\" then!@#&                        term.setCursorPos(px-sx,pz-sy)!@#&                        if frames[sFrame] and frames[sFrame][pz-sy] and frames[sFrame][pz-sy][px-sx] then!@#&                                bgColour = frames[sFrame][pz-sy][px-sx]!@#&                        elseif blueprint then bgColour = colours.blue end!@#&                else!@#&                        term.setCursorPos(px-sx,py-sy)!@#&                        if frames[sFrame] and frames[sFrame][py-sy] and frames[sFrame][py-sy][px-sx] then!@#&                                bgColour = frames[sFrame][py-sy][px-sx]!@#&                        elseif blueprint then bgColour = colours.blue end!@#&                end!@#&               !@#&                term.setBackgroundColour(bgColour)!@#&                if bgColour == colours.black then term.setTextColour(colours.white)!@#&                else term.setTextColour(colours.black) end!@#&               !@#&                term.write(turtlechar)!@#&        end!@#&       !@#&        --Then the buffer!@#&        if selectrect then!@#&                if buffer and rectblink == 1 then!@#&                for y=selectrect.y1, math.min(selectrect.y2, selectrect.y1 + buffer.height-1) do!@#&                        for x=selectrect.x1, math.min(selectrect.x2, selectrect.x1 + buffer.width-1) do!@#&                                if buffer.contents[y-selectrect.y1+1][x-selectrect.x1+1] then!@#&                                        term.setCursorPos(x+sx,y+sy)!@#&                                        term.setBackgroundColour(buffer.contents[y-selectrect.y1+1][x-selectrect.x1+1])!@#&                                        term.write(\" \")!@#&                                end!@#&                        end!@#&                end!@#&                end!@#&       !@#&                --This draws the \"selection\" box!@#&                local add = nil!@#&                if buffer then!@#&                        term.setBackgroundColour(colours.lightGrey)!@#&                else!@#&                        term.setBackgroundColour(colours.grey)!@#&                end!@#&                for i=selectrect.x1, selectrect.x2 do!@#&                        add = (i + selectrect.y1 + rectblink) % 2 == 0!@#&                        term.setCursorPos(i-sx,selectrect.y1-sy)!@#&                        if add then term.write(\" \") end!@#&                        add = (i + selectrect.y2 + rectblink) % 2 == 0!@#&                        term.setCursorPos(i-sx,selectrect.y2-sy)!@#&                        if add then term.write(\" \") end!@#&                end!@#&                for i=selectrect.y1 + 1, selectrect.y2 - 1 do!@#&                        add = (i + selectrect.x1 + rectblink) % 2 == 0!@#&                        term.setCursorPos(selectrect.x1-sx,i-sy)!@#&                        if add then term.write(\" \") end!@#&                        add = (i + selectrect.x2 + rectblink) % 2 == 0!@#&                        term.setCursorPos(selectrect.x2-sx,i-sy)!@#&                        if add then term.write(\" \") end!@#&                end!@#&        end!@#&end!@#& !@#&--[[Draws the colour picker on the right side of the screen, the colour pallette and the footer with any!@#&        messages currently being displayed!@#&        Params: none!@#&        Returns:nil!@#&]]--!@#&local function drawInterface()!@#&        --Picker!@#&		local coffset,ioffset = 0,0!@#&		local maxcsize = h-2!@#&		if h < #column + 2 then!@#&			maxcsize = h-4!@#&			coffset = columnoffset!@#&			ioffset = 1!@#&			term.setBackgroundColour(colours.lightGrey)!@#&			term.setTextColour(colours.grey)!@#&			term.setCursorPos(w-1,1)!@#&			term.write(\"^^\")!@#&			term.setCursorPos(w-1,h-2)!@#&			term.write(\"VV\")!@#&		end!@#&        for i=1,math.min(#column+1,maxcsize) do!@#&			term.setCursorPos(w-1, i + ioffset)!@#&			local ci = i+coffset!@#&			if ci == #column+1 then!@#&				term.setBackgroundColour(colours.black)!@#&				term.setTextColour(colours.red)!@#&				term.write(\"XX\")!@#&			elseif state == \"print\" then!@#&				term.setBackgroundColour(column[ci])!@#&				if column[ci] == colours.black then!@#&					term.setTextColour(colours.white)!@#&				else term.setTextColour(colours.black) end!@#&				!@#&				if requirementsDisplayed then!@#&						if requiredMaterials[i] < 10 then term.write(\" \") end!@#&						term.setCursorPos(w-#tostring(requiredMaterials[i])+1, i)!@#&						term.write(requiredMaterials[i])!@#&				else!@#&						if i+coffset < 10 then term.write(\" \") end!@#&						term.write(i+coffset)!@#&				end!@#&			else!@#&				term.setBackgroundColour(column[ci])!@#&				term.write(\"  \")!@#&			end!@#&        end!@#&		--Filling the whitespace with... 'greyspace' *shudder*!@#&		if h > #column+3 then!@#&			term.setTextColour(colours.grey)!@#&			term.setBackgroundColour(colours.lightGrey)!@#&			for y=#column+2,h-2 do!@#&				term.setCursorPos(w-1,y)!@#&				term.write(\"| \")!@#&			end!@#&		end!@#&        --Pallette!@#&        term.setCursorPos(w-1,h-1)!@#&        if not lSel then!@#&                term.setBackgroundColour(colours.black)!@#&                term.setTextColour(colours.red)!@#&                term.write(\"X\")!@#&        else!@#&                term.setBackgroundColour(lSel)!@#&                term.setTextColour(lSel)!@#&                term.write(\" \")!@#&        end!@#&        if not rSel then!@#&                term.setBackgroundColour(colours.black)!@#&                term.setTextColour(colours.red)!@#&                term.write(\"X\")!@#&        else!@#&                term.setBackgroundColour(rSel)!@#&                term.setTextColour(rSel)!@#&                term.write(\" \")!@#&        end!@#&        --Footer!@#&        if inMenu then return end!@#&       !@#&        term.setCursorPos(1, h)!@#&        term.setBackgroundColour(colours.lightGrey)!@#&        term.setTextColour(colours.grey)!@#&        term.clearLine()!@#&		if mainAvailable then!@#&			if inDropDown then!@#&					term.write(string.rep(\" \", #ddModes.name + 2))!@#&			else!@#&					term.setBackgroundColour(colours.grey)!@#&					term.setTextColour(colours.lightGrey)!@#&					term.write(ddModes.name..\"  \")!@#&			end!@#&		end!@#&        term.setBackgroundColour(colours.lightGrey)!@#&        term.setTextColour(colours.grey)!@#&        term.write(getStateMessage())!@#&       !@#&        local coords=\"X:\"..sx..\" Y:\"..sy!@#&        if animated then coords = coords..\" Frame:\"..sFrame..\"/\"..framecount..\"   \" end!@#&        term.setCursorPos(w-#coords+1,h)!@#&        if state == \"play\" then term.setBackgroundColour(colours.lime)!@#&        elseif record then term.setBackgroundColour(colours.red) end!@#&        term.write(coords)!@#&       !@#&        if animated then!@#&                term.setCursorPos(w-1,h)!@#&                term.setBackgroundColour(colours.grey)!@#&                term.setTextColour(colours.lightGrey)!@#&                term.write(\"<>\")!@#&        end!@#&end!@#& !@#&--[[Runs an interface where users can select topics of help. Will return once the user quits the help screen.!@#&        Params: none!@#&        Returns:nil!@#&]]--!@#&local function drawHelpScreen()!@#&        local selectedHelp = nil!@#&        while true do!@#&                term.setBackgroundColour(colours.lightGrey)!@#&                term.clear()!@#&                if not selectedHelp then!@#&                        term.setCursorPos(4, 1)!@#&                        term.setTextColour(colours.brown)!@#&                        term.write(\"Available modes (click for info):\")!@#&                        for i=1,#helpTopics do!@#&                                term.setCursorPos(2, 2 + i)!@#&                                term.setTextColour(colours.black)!@#&                                term.write(helpTopics[i].name)!@#&                                if helpTopics[i].key then!@#&                                        term.setTextColour(colours.red)!@#&                                        term.write(\" (\"..helpTopics[i].key..\")\")!@#&                                end!@#&                        end!@#&                        term.setCursorPos(4,h)!@#&                        term.setTextColour(colours.black)!@#&                        term.write(\"Press any key to exit\")!@#&                else!@#&                        term.setCursorPos(4,1)!@#&                        term.setTextColour(colours.brown)!@#&                        term.write(helpTopics[selectedHelp].name)!@#&                        if helpTopics[selectedHelp].key then!@#&                                term.setTextColour(colours.red)!@#&                                term.write(\" (\"..helpTopics[selectedHelp].key..\")\")!@#&                        end!@#&                        term.setCursorPos(1,3)!@#&                        term.setTextColour(colours.black)!@#&                        print(helpTopics[selectedHelp].message..\"\\n\")!@#&                        for i=1,#helpTopics[selectedHelp].controls do!@#&                                term.setTextColour(colours.brown)!@#&                                term.write(helpTopics[selectedHelp].controls[i][1]..\" \")!@#&                                term.setTextColour(colours.black)!@#&                                print(helpTopics[selectedHelp].controls[i][2])!@#&                        end!@#&                end!@#&               !@#&                local id,p1,p2,p3 = os.pullEvent()!@#&               !@#&                if id == \"timer\" then updateTimer(p1)!@#&                elseif id == \"key\" then!@#&                        if selectedHelp then selectedHelp = nil!@#&                        else break end!@#&                elseif id == \"mouse_click\" then!@#&                        if not selectedHelp then!@#&                                if p3 >=3 and p3 <= 2+#helpTopics then!@#&                                        selectedHelp = p3-2!@#&                                else break end!@#&                        else!@#&                                selectedHelp = nil!@#&                        end!@#&                end!@#&        end!@#&end!@#& !@#&--[[Draws a message in the footer bar. A helper for DrawInterface, but can be called for custom messages, if the!@#&        inMenu paramter is set to true while this is being done (remember to set it back when done!)!@#&        Params: message:string = The message to be drawn!@#&        Returns:nil!@#&]]--!@#&local function drawMessage(message)!@#&        term.setCursorPos(1,h)!@#&        term.setBackgroundColour(colours.lightGrey)!@#&        term.setTextColour(colours.grey)!@#&        term.clearLine()!@#&        term.write(message)!@#&end!@#& !@#&--[[!@#&                        Section: Generic Interfaces!@#&]]--!@#& !@#& !@#&--[[One of my generic text printing methods, printing a message at a specified position with width and offset.!@#&        No colour materials included.!@#&        Params: msg:string = The message to print off-center!@#&                        height:number = The starting height of the message!@#&                        width:number = The limit as to how many characters long each line may be!@#&                        offset:number = The starting width offset of the message!@#&        Returns:number the number of lines used in printing the message!@#&]]--!@#&local function wprintOffCenter(msg, height, width, offset)!@#&        local inc = 0!@#&        local ops = 1!@#&        while #msg - ops > width do!@#&                local nextspace = 0!@#&                while string.find(msg, \" \", ops + nextspace) and!@#&                                string.find(msg, \" \", ops + nextspace) - ops < width do!@#&                        nextspace = string.find(msg, \" \", nextspace + ops) + 1 - ops!@#&                end!@#&                local ox,oy = term.getCursorPos()!@#&                term.setCursorPos(width/2 - (nextspace)/2 + offset, height + inc)!@#&                inc = inc + 1!@#&                term.write(string.sub(msg, ops, nextspace + ops - 1))!@#&                ops = ops + nextspace!@#&        end!@#&        term.setCursorPos(width/2 - #string.sub(msg, ops)/2 + offset, height + inc)!@#&        term.write(string.sub(msg, ops))!@#&       !@#&        return inc + 1!@#&end!@#& !@#&--[[Draws a message that must be clicked on or a key struck to be cleared. No options, so used for displaying!@#&        generic information.!@#&        Params: ctitle:string = The title of the confirm dialogue!@#&                        msg:string = The message displayed in the dialogue!@#&        Returns:nil!@#&]]--!@#&local function displayConfirmDialogue(ctitle, msg)!@#&        local dialogoffset = 8!@#&        --We actually print twice- once to get the lines, second time to print proper. Easier this way.!@#&        local lines = wprintOffCenter(msg, 5, w - (dialogoffset+2) * 2, dialogoffset + 2)!@#&       !@#&        term.setCursorPos(dialogoffset, 3)!@#&        term.setBackgroundColour(colours.grey)!@#&        term.setTextColour(colours.lightGrey)!@#&        term.write(string.rep(\" \", w - dialogoffset * 2))!@#&        term.setCursorPos(dialogoffset + (w - dialogoffset * 2)/2 - #ctitle/2, 3)!@#&        term.write(ctitle)!@#&        term.setTextColour(colours.grey)!@#&        term.setBackgroundColour(colours.lightGrey)!@#&        term.setCursorPos(dialogoffset, 4)!@#&        term.write(string.rep(\" \", w - dialogoffset * 2))!@#&        for i=5,5+lines do!@#&                term.setCursorPos(dialogoffset, i)!@#&                term.write(\" \"..string.rep(\" \", w - (dialogoffset) * 2 - 2)..\" \")!@#&        end!@#&        wprintOffCenter(msg, 5, w - (dialogoffset+2) * 2, dialogoffset + 2)!@#&       !@#&        --In the event of a message, the player hits anything to continue!@#&        while true do!@#&                local id,key = os.pullEvent()!@#&                if id == \"timer\" then updateTimer(key);!@#&                elseif id == \"key\" or id == \"mouse_click\" or id == \"mouse_drag\" then break end!@#&        end!@#&end!@#& !@#&--[[Produces a nice dropdown menu based on a table of strings. Depending on the position, this will auto-adjust the position!@#&        of the menu drawn, and allows nesting of menus and sub menus. Clicking anywhere outside the menu will cancel and return nothing!@#&        Params: x:int = the x position the menu should be displayed at!@#&                        y:int = the y position the menu should be displayed at!@#&                        options:table = the list of options available to the user, as strings or submenus (tables of strings, with a name parameter)!@#&        Returns:string the selected menu option.!@#&]]--!@#&local function displayDropDown(x, y, options)!@#&        inDropDown = true!@#&        --Figures out the dimensions of our thing!@#&        local longestX = #options.name!@#&        for i=1,#options do!@#&                local currVal = options[i]!@#&                if type(currVal) == \"table\" then currVal = currVal.name end!@#&               !@#&                longestX = math.max(longestX, #currVal)!@#&        end!@#&        local xOffset = math.max(0, longestX - ((w-2) - x) + 1)!@#&        local yOffset = math.max(0, #options - ((h-1) - y))!@#&       !@#&        local clickTimes = 0!@#&        local tid = nil!@#&        local selection = nil!@#&        while clickTimes < 2 do!@#&                drawCanvas()!@#&                drawInterface()!@#&               !@#&                term.setCursorPos(x-xOffset,y-yOffset)!@#&                term.setBackgroundColour(colours.grey)!@#&                term.setTextColour(colours.lightGrey)!@#&                term.write(options.name..string.rep(\" \", longestX-#options.name + 2))!@#&       !@#&                for i=1,#options do!@#&                        term.setCursorPos(x-xOffset, y-yOffset+i)!@#&                        if i==selection and clickTimes % 2 == 0 then!@#&                                term.setBackgroundColour(colours.grey)!@#&                                term.setTextColour(colours.lightGrey)!@#&                        else!@#&                                term.setBackgroundColour(colours.lightGrey)!@#&                                term.setTextColour(colours.grey)!@#&                        end!@#&                        local currVal = options[i]!@#&                        if type(currVal) == \"table\" then!@#&                                term.write(currVal.name..string.rep(\" \", longestX-#currVal.name + 1))!@#&                                term.setBackgroundColour(colours.grey)!@#&                                term.setTextColour(colours.lightGrey)!@#&                                term.write(\">\")!@#&                        else!@#&                                term.write(currVal..string.rep(\" \", longestX-#currVal + 2))!@#&                        end!@#&                end!@#&               !@#&                local id, p1, p2, p3 = os.pullEvent()!@#&                if id == \"timer\" then!@#&                        if p1 == tid then!@#&                                clickTimes = clickTimes + 1!@#&                                if clickTimes > 2 then!@#&                                        break!@#&                                else!@#&                                        tid = os.startTimer(0.1)!@#&                                end!@#&                        else!@#&                                updateTimer(p1)!@#&                                drawCanvas()!@#&                                drawInterface()!@#&                        end!@#&                elseif id == \"mouse_click\" then!@#&                        if p2 >=x-xOffset and p2 <= x-xOffset + longestX + 1 and p3 >= y-yOffset+1 and p3 <= y-yOffset+#options then!@#&                                selection = p3-(y-yOffset)!@#&                                tid = os.startTimer(0.1)!@#&                        else!@#&                                selection = \"\"!@#&                                break!@#&                        end!@#&                end!@#&        end!@#&       !@#&        if type(selection) == \"number\" then!@#&                selection = options[selection]!@#&        end!@#&       !@#&        if type(selection) == \"string\" then!@#&                inDropDown = false!@#&                return selection!@#&        elseif type(selection) == \"table\" then!@#&                return displayDropDown(x, y, selection)!@#&        end!@#&end!@#& !@#&--[[A custom io.read() function with a few differences- it limits the number of characters being printed,!@#&        waits a 1/100th of a second so any keys still in the event library are removed before input is read and!@#&        the timer for the selectionrectangle is continuously updated during the process.!@#&        Params: lim:int = the number of characters input is allowed!@#&        Returns:string the inputted string, trimmed of leading and tailing whitespace!@#&]]--!@#&local function readInput(lim)!@#&        term.setCursorBlink(true)!@#& !@#&        local inputString = \"\"!@#&        if not lim or type(lim) ~= \"number\" or lim < 1 then lim = w - ox end!@#&        local ox,oy = term.getCursorPos()!@#&        --We only get input from the footer, so this is safe. Change if recycling!@#&        term.setBackgroundColour(colours.lightGrey)!@#&        term.setTextColour(colours.grey)!@#&        term.write(string.rep(\" \", lim))!@#&        term.setCursorPos(ox, oy)!@#&        --As events queue immediately, we may get an unwanted key... this will solve that problem!@#&        local inputTimer = os.startTimer(0.01)!@#&        local keysAllowed = false!@#&       !@#&        while true do!@#&                local id,key = os.pullEvent()!@#&               !@#&                if keysAllowed then!@#&                        if id == \"key\" and key == 14 and #inputString > 0 then!@#&                                inputString = string.sub(inputString, 1, #inputString-1)!@#&                                term.setCursorPos(ox + #inputString,oy)!@#&                                term.write(\" \")!@#&                        elseif id == \"key\" and key == 28 and inputString ~= string.rep(\" \", #inputString) then!@#&                                break!@#&                        elseif id == \"key\" and key == keys.leftCtrl then!@#&                                return \"\"!@#&                        elseif id == \"char\" and #inputString < lim then!@#&                                inputString = inputString..key!@#&                        end!@#&                end!@#&               !@#&                if id == \"timer\" then!@#&                        if key == inputTimer then!@#&                                keysAllowed = true!@#&                        else!@#&                                updateTimer(key)!@#&                                drawCanvas()!@#&                                drawInterface()!@#&                                term.setBackgroundColour(colours.lightGrey)!@#&                                term.setTextColour(colours.grey)!@#&                        end!@#&                end!@#&                term.setCursorPos(ox,oy)!@#&                term.write(inputString)!@#&                term.setCursorPos(ox + #inputString, oy)!@#&        end!@#&       !@#&        while string.sub(inputString, 1, 1) == \" \" do!@#&                inputString = string.sub(inputString, 2, #inputString)!@#&        end!@#&        while string.sub(inputString, #inputString, #inputString) == \" \" do!@#&                inputString = string.sub(inputString, 1, #inputString-1)!@#&        end!@#&        term.setCursorBlink(false)!@#&       !@#&        return inputString!@#&end!@#& !@#&--[[  !@#&                        Section: Image tools!@#&]]--!@#& !@#& !@#&--[[Copies all pixels beneath the selection rectangle into the image buffer. Empty buffers are converted to nil.!@#&        Params: removeImage:bool = true if the image is to be erased after copying, false otherwise!@#&        Returns:nil!@#&]]--!@#&local function copyToBuffer(removeImage)!@#&        buffer = { width = selectrect.x2 - selectrect.x1 + 1, height = selectrect.y2 - selectrect.y1 + 1, contents = { } }!@#&       !@#&        local containsSomething = false!@#&        for y=1,buffer.height do!@#&                buffer.contents[y] = { }!@#&                local f,l = sFrame,sFrame!@#&                if record then f,l = 1, framecount end!@#&               !@#&                for fra = f,l do!@#&                        if frames[fra][selectrect.y1 + y - 1] then!@#&                                for x=1,buffer.width do!@#&                                        buffer.contents[y][x] = frames[sFrame][selectrect.y1 + y - 1][selectrect.x1 + x - 1]!@#&                                        if removeImage then frames[fra][selectrect.y1 + y - 1][selectrect.x1 + x - 1] = nil end!@#&                                        if buffer.contents[y][x] then containsSomething = true end!@#&                                end!@#&                        end!@#&                end!@#&        end!@#&        --I don't classify an empty buffer as a real buffer- confusing to the user.!@#&        if not containsSomething then buffer = nil end!@#&end!@#& !@#&--[[Replaces all pixels under the selection rectangle with the image buffer (or what can be seen of it). Record-dependent.!@#&        Params: removeBuffer:bool = true if the buffer is to be emptied after copying, false otherwise!@#&        Returns:nil!@#&]]--!@#&local function copyFromBuffer(removeBuffer)!@#&        if not buffer then return end!@#& !@#&        for y = 1, math.min(buffer.height,selectrect.y2-selectrect.y1+1) do!@#&                local f,l = sFrame, sFrame!@#&                if record then f,l = 1, framecount end!@#&               !@#&                for fra = f,l do!@#&                        if not frames[fra][selectrect.y1+y-1] then frames[fra][selectrect.y1+y-1] = { } end!@#&                        for x = 1, math.min(buffer.width,selectrect.x2-selectrect.x1+1) do!@#&                                frames[fra][selectrect.y1+y-1][selectrect.x1+x-1] = buffer.contents[y][x]!@#&                        end!@#&                end!@#&        end!@#&       !@#&        if removeBuffer then buffer = nil end!@#&end!@#& !@#&--[[Moves the entire image (or entire animation) to the specified coordinates. Record-dependent.!@#&        Params: newx:int = the X coordinate to move the image to!@#&                        newy:int = the Y coordinate to move the image to!@#&        Returns:nil!@#&]]--!@#&local function moveImage(newx,newy)!@#&        if not leflim or not toplim then return end!@#&        if newx <=0 or newy <=0 then return end!@#&        local f,l = sFrame,sFrame!@#&        if record then f,l = 1,framecount end!@#&       !@#&        for i=f,l do!@#&                local newlines = { }!@#&                for y=toplim,botlim do!@#&                        local line = frames[i][y]!@#&                        if line then!@#&                                newlines[y-toplim+newy] = { }!@#&                                for x,char in pairs(line) do!@#&                                        newlines[y-toplim+newy][x-leflim+newx] = char!@#&                                end!@#&                        end!@#&                end!@#&                --Exceptions that allow us to move the text as well!@#&                if textEnabled then!@#&                        newlines.text = { }!@#&                        for y=toplim,botlim do!@#&                                local line = frames[i].text[y]!@#&                                if line then!@#&                                        newlines.text[y-toplim+newy] = { }!@#&                                        for x,char in pairs(line) do!@#&                                                newlines.text[y-toplim+newy][x-leflim+newx] = char!@#&                                        end!@#&                                end!@#&                        end!@#&                       !@#&                        newlines.textcol = { }!@#&                        for y=toplim,botlim do!@#&                                local line = frames[i].textcol[y]!@#&                                if line then!@#&                                        newlines.textcol[y-toplim+newy] = { }!@#&                                        for x,char in pairs(line) do!@#&                                                newlines.textcol[y-toplim+newy][x-leflim+newx] = char!@#&                                        end!@#&                                end!@#&                        end!@#&                end!@#&               !@#&                frames[i] = newlines!@#&        end!@#&end!@#& !@#&--[[Prompts the user to clear the current frame or all frames. Record-dependent.,!@#&        Params: none!@#&        Returns:nil!@#&]]--!@#&local function clearImage()!@#&        inMenu = true!@#&        if not animated then!@#&                drawMessage(\"Clear image? Y/N: \")!@#&        elseif record then!@#&                drawMessage(\"Clear ALL frames? Y/N: \")!@#&        else!@#&                drawMessage(\"Clear current frame? Y/N :\")!@#&        end!@#&        if string.find(string.upper(readInput(1)), \"Y\") then!@#&                local f,l = sFrame,sFrame!@#&                if record then f,l = 1,framecount end!@#&               !@#&                for i=f,l do!@#&                        frames[i] = { }!@#&                end!@#&        end!@#&        inMenu = false!@#&end!@#& !@#&--[[A recursively called method (watch out for big calls!) in which every pixel of a set colour is!@#&        changed to another colour. Does not work on the nil colour, for obvious reasons.!@#&        Params: x:int = The X coordinate of the colour to flood-fill!@#&                        y:int = The Y coordinate of the colour to flood-fill!@#&                        targetColour:colour = the colour that is being flood-filled!@#&                        newColour:colour = the colour with which to replace the target colour!@#&        Returns:nil!@#&]]--!@#&local function floodFill(x, y, targetColour, newColour)!@#&        if not newColour or not targetColour then return end!@#&        local nodeList = { }!@#&       !@#&        table.insert(nodeList, {x = x, y = y})!@#&       !@#&        while #nodeList > 0 do!@#&                local node = nodeList[1]!@#&                if frames[sFrame][node.y] and frames[sFrame][node.y][node.x] == targetColour then!@#&                        frames[sFrame][node.y][node.x] = newColour!@#&                        table.insert(nodeList, { x = node.x + 1, y = node.y})!@#&                        table.insert(nodeList, { x = node.x, y = node.y + 1})!@#&                        if x > 1 then table.insert(nodeList, { x = node.x - 1, y = node.y}) end!@#&                        if y > 1 then table.insert(nodeList, { x = node.x, y = node.y - 1}) end!@#&                end!@#&                table.remove(nodeList, 1)!@#&        end!@#&end!@#& !@#&--[[  !@#&                        Section: Animation Tools  !@#&]]--!@#& !@#&--[[Enters play mode, allowing the animation to play through. Interface is restricted to allow this,!@#&        and method only leaves once the player leaves play mode.!@#&        Params: none!@#&        Returns:nil!@#&]]--!@#&local function playAnimation()!@#&        state = \"play\"!@#&        selectedrect = nil!@#&       !@#&        local animt = os.startTimer(animtime)!@#&        repeat!@#&                drawCanvas()!@#&                drawInterface()!@#&               !@#&                local id,key,_,y = os.pullEvent()!@#&               !@#&                if id==\"timer\" then!@#&                        if key == animt then!@#&                                animt = os.startTimer(animtime)!@#&                                sFrame = (sFrame % framecount) + 1!@#&                        else!@#&                                updateTimer(key)!@#&                        end!@#&                elseif id==\"key\" then!@#&                        if key == keys.comma and animtime > 0.1 then animtime = animtime - 0.05!@#&                        elseif key == keys.period and animtime < 0.5 then animtime = animtime + 0.05!@#&                        elseif key == keys.space then state = \"paint\" end!@#&                elseif id==\"mouse_click\" and y == h then!@#&                        state = \"paint\"!@#&                end!@#&        until state ~= \"play\"!@#&        os.startTimer(0.5)!@#&end!@#& !@#&--[[Changes the selected frame (sFrame) to the chosen frame. If this frame is above the framecount,!@#&        additional frames are created with a copy of the image on the selected frame.!@#&        Params: newframe:int = the new frame to move to!@#&        Returns:nil!@#&]]--!@#&local function changeFrame(newframe)!@#&        inMenu = true!@#&        if not tonumber(newframe) then!@#&                term.setCursorPos(1,h)!@#&                term.setBackgroundColour(colours.lightGrey)!@#&                term.setTextColour(colours.grey)!@#&                term.clearLine()!@#&       !@#&                term.write(\"Go to frame: \")!@#&                newframe = tonumber(readInput(2))!@#&                if not newframe or newframe <= 0 then!@#&                        inMenu = false!@#&                        return!@#&                end!@#&        elseif newframe <= 0 then return end!@#&       !@#&        if newframe > framecount then!@#&                for i=framecount+1,newframe do!@#&                        frames[i] = {}!@#&                        for y,line in pairs(frames[sFrame]) do!@#&                                frames[i][y] = { }!@#&                                for x,v in pairs(line) do!@#&                                        frames[i][y][x] = v!@#&                                end!@#&                        end!@#&                end!@#&                framecount = newframe!@#&        end!@#&        sFrame = newframe!@#&        inMenu = false!@#&end!@#& !@#&--[[Removes every frame leading after the frame passed in!@#&        Params: frame:int the non-inclusive lower bounds of the delete!@#&        Returns:nil!@#&]]--!@#&local function removeFramesAfter(frame)!@#&        inMenu = true!@#&        if frame==framecount then return end!@#&        drawMessage(\"Remove frames \"..(frame+1)..\"/\"..framecount..\"? Y/N :\")!@#&        local answer = string.upper(readInput(1))!@#&       !@#&        if string.find(answer, string.upper(\"Y\")) ~= 1 then!@#&                inMenu = false!@#&                return!@#&        end!@#&       !@#&        for i=frame+1, framecount do!@#&                frames[i] = nil!@#&        end!@#&        framecount = frame!@#&        inMenu = false!@#&end!@#& !@#&--[[!@#&                        Section: Printing Tools!@#&]]--!@#& !@#&--[[Constructs a new facing to the left of the current facing!@#&        Params: curx:number = The facing on the X axis!@#&                        curz:number = The facing on the Z axis!@#&                        hand:string = The hand of the axis (\"right\" or \"left\")!@#&        Returns:number,number = the new facing on the X and Z axis after a left turn!@#&]]--!@#&local function getLeft(curx, curz)!@#&        local hand = \"left\"!@#&        if layering == \"up\" then hand = \"right\" end!@#&       !@#&        if hand == \"right\" then!@#&                if curx == 1 then return 0,-1 end!@#&                if curx == -1 then return 0,1 end!@#&                if curz == 1 then return 1,0 end!@#&                if curz == -1 then return -1,0 end!@#&        else!@#&                if curx == 1 then return 0,1 end!@#&                if curx == -1 then return 0,-1 end!@#&                if curz == 1 then return -1,0 end!@#&                if curz == -1 then return 1,0 end!@#&        end!@#&end!@#& !@#&--[[Constructs a new facing to the right of the current facing!@#&        Params: curx:number = The facing on the X axis!@#&                        curz:number = The facing on the Z axis!@#&                        hand:string = The hand of the axis (\"right\" or \"left\")!@#&        Returns:number,number = the new facing on the X and Z axis after a right turn!@#&]]--!@#&local function getRight(curx, curz)!@#&        local hand = \"left\"!@#&        if layering == \"up\" then hand = \"right\" end!@#&       !@#&        if hand == \"right\" then!@#&                if curx == 1 then return 0,1 end!@#&                if curx == -1 then return 0,-1 end!@#&                if curz == 1 then return -1,0 end!@#&                if curz == -1 then return 1,0 end!@#&        else!@#&                if curx == 1 then return 0,-1 end!@#&                if curx == -1 then return 0,1 end!@#&                if curz == 1 then return 1,0 end!@#&                if curz == -1 then return -1,0 end!@#&        end!@#&end!@#& !@#& !@#&--[[Sends out a rednet signal requesting local printers, and will listen for any responses. Printers found are added to the!@#&        printerList (for ID's) and printerNames (for names)!@#&        Params: nil!@#&        Returns:nil!@#&]]--!@#&local function locatePrinters()!@#&        printerList = { }!@#&        printerNames = { name = \"Printers\" }!@#&        local oldState = state!@#&        state = \"Locating printers, please wait...   \"!@#&        drawCanvas()!@#&        drawInterface()!@#&        state = oldState!@#&       !@#&        local modemOpened = false!@#&        for k,v in pairs(rs.getSides()) do!@#&                if peripheral.isPresent(v) and peripheral.getType(v) == \"modem\" then!@#&                        rednet.open(v)!@#&                        modemOpened = true!@#&                        break!@#&                end!@#&        end!@#&       !@#&        if not modemOpened then!@#&                displayConfirmDialogue(\"Modem not found!\", \"No modem peripheral. Must have network modem to locate printers.\")!@#&                return false!@#&        end!@#&       !@#&        rednet.broadcast(\"$3DPRINT IDENTIFY\")!@#&       !@#&        while true do!@#&                local id, msg = rsTimeReceive(1)!@#&               !@#&                if not id then break end!@#&                if string.find(msg, \"$3DPRINT IDACK\") == 1 then!@#&                        msg = string.gsub(msg, \"$3DPRINT IDACK \", \"\")!@#&                        table.insert(printerList, id)!@#&                        table.insert(printerNames, msg)!@#&                end!@#&        end!@#&       !@#&        if #printerList == 0 then!@#&                displayConfirmDialogue(\"Printers not found!\", \"No active printers found in proximity of this computer.\")!@#&                return false!@#&        else!@#&                return true!@#&        end!@#&end!@#& !@#&--[[Sends a request to the printer. Waits on a response and updates the state of the application accordingly.!@#&        Params: command:string the command to send!@#&                        param:string a parameter to send, if any!@#&        Returns:nil!@#&]]--!@#&local function sendPC(command,param)!@#&        local msg = \"$PC \"..command!@#&        if param then msg = msg..\" \"..param end!@#&        rednet.send(printerList[selectedPrinter], msg)!@#&       !@#&        while true do!@#&                local id,key = rsTimeReceive()!@#&                if id == printerList[selectedPrinter] then!@#&                        if key == \"$3DPRINT ACK\" then!@#&                                break!@#&                        elseif key == \"$3DPRINT DEP\" then!@#&                                displayConfirmDialogue(\"Printer Empty\", \"The printer has exhasted a material. Please refill slot \"..param..!@#&                                        \", and click this message when ready to continue.\")!@#&                                rednet.send(printerList[selectedPrinter], msg)!@#&                        elseif key == \"$3DPRINT OOF\" then!@#&                                displayConfirmDialogue(\"Printer Out of Fuel\", \"The printer has no fuel. Please replace the material \"..!@#&                                        \"in slot 1 with a fuel source, then click this message.\")!@#&                                rednet.send(printerList[selectedPrinter], \"$PC SS 1\")!@#&                                id,key = rsTimeReceive()!@#&                                rednet.send(printerList[selectedPrinter], \"$PC RF\")!@#&                                id,key = rsTimeReceive()!@#&                                rednet.send(printerList[selectedPrinter], msg)!@#&                        end!@#&                end!@#&        end!@#&       !@#&        --Changes to position are handled after the event has been successfully completed!@#&        if command == \"FW\" then!@#&                px = px + pfx!@#&                pz = pz + pfz!@#&        elseif command == \"BK\" then!@#&                px = px - pfx!@#&                pz = pz - pfz!@#&        elseif command == \"UP\" then!@#&                if layering == \"up\" then!@#&                        py = py + 1!@#&                else!@#&                        py = py - 1!@#&                end!@#&        elseif command == \"DW\" then!@#&                if layering == \"up\" then!@#&                        py = py - 1!@#&                else    !@#&                        py = py + 1!@#&                end!@#&        elseif command == \"TL\" then!@#&                pfx,pfz = getLeft(pfx,pfz)!@#&        elseif command == \"TR\" then!@#&                pfx,pfz = getRight(pfx,pfz)!@#&        elseif command == \"TU\" then!@#&                pfx = -pfx!@#&                pfz = -pfz!@#&        end!@#&       !@#&        drawCanvas()!@#&        drawInterface()!@#&end!@#& !@#&--[[A printing function that commands the printer to turn to face the desired direction, if it is not already doing so!@#&        Params: desx:number = the normalized x direction to face!@#&                        desz:number = the normalized z direction to face!@#&        Returns:nil!@#&]]--!@#&local function turnToFace(desx,desz)!@#&        if desx ~= 0 then!@#&                if pfx ~= desx then!@#&                        local temppfx,_ = getLeft(pfx,pfz)!@#&                        if temppfx == desx then!@#&                                sendPC(\"TL\")!@#&                        elseif temppfx == -desx then!@#&                                sendPC(\"TR\")!@#&                        else!@#&                                sendPC(\"TU\")!@#&                        end!@#&                end!@#&        else!@#&                print(\"on the z axis\")!@#&                if pfz ~= desz then!@#&                        local _,temppfz = getLeft(pfx,pfz)!@#&                        if temppfz == desz then!@#&                                sendPC(\"TL\")!@#&                        elseif temppfz == -desz then!@#&                                sendPC(\"TR\")!@#&                        else!@#&                                sendPC(\"TU\")!@#&                        end!@#&                end!@#&        end!@#&end!@#& !@#&--[[Performs the print!@#&        Params: nil!@#&        Returns:nil!@#&]]--!@#&local function performPrint()!@#&        state = \"active print\"!@#&        if layering == \"up\" then!@#&                --An up layering starts our builder bot on the bottom left corner of our build!@#&                px,py,pz = leflim, 0, botlim + 1!@#&                pfx,pfz = 0,-1!@#&               !@#&                --We move him forward and up a bit from his original position.!@#&                sendPC(\"FW\")!@#&                sendPC(\"UP\")!@#&                --For each layer that needs to be completed, we go up by one each time!@#&                for layers=1,#frames do!@#&                        --We first decide if we're going forwards or back, depending on what side we're on!@#&                        local rowbot,rowtop,rowinc = nil,nil,nil!@#&                        if pz == botlim then!@#&                                rowbot,rowtop,rowinc = botlim,toplim,-1!@#&                        else!@#&                                rowbot,rowtop,rowinc = toplim,botlim,1!@#&                        end!@#&                       !@#&                        for rows = rowbot,rowtop,rowinc do!@#&                                --Then we decide if we're going left or right, depending on what side we're on!@#&                                local linebot,linetop,lineinc = nil,nil,nil!@#&                                if px == leflim then!@#&                                        --Facing from the left side has to be easterly- it's changed here!@#&                                        turnToFace(1,0)!@#&                                        linebot,linetop,lineinc = leflim,riglim,1!@#&                                else!@#&                                        --Facing from the right side has to be westerly- it's changed here!@#&                                        turnToFace(-1,0)!@#&                                        linebot,linetop,lineinc = riglim,leflim,-1!@#&                                end!@#&                               !@#&                                for lines = linebot,linetop,lineinc do!@#&                                        --We move our turtle forward, placing the right material at each step!@#&                                        local material = frames[py][pz][px]!@#&                                        if material then!@#&                                                material = math.log10(frames[py][pz][px])/math.log10(2) + 1!@#&                                                sendPC(\"SS\", material)!@#&                                                sendPC(\"PD\")!@#&                                        end!@#&                                        if lines ~= linetop then!@#&                                                sendPC(\"FW\")!@#&                                        end!@#&                                end!@#&                               !@#&                                --The printer then has to do a U-turn, depending on which way he's facing and!@#&                                --which way he needs to go!@#&                                local temppfx,temppfz = getLeft(pfx,pfz)!@#&                                if temppfz == rowinc and rows ~= rowtop then!@#&                                        sendPC(\"TL\")!@#&                                        sendPC(\"FW\")!@#&                                        sendPC(\"TL\")!@#&                                elseif temppfz == -rowinc and rows ~= rowtop then!@#&                                        sendPC(\"TR\")!@#&                                        sendPC(\"FW\")!@#&                                        sendPC(\"TR\")!@#&                                end!@#&                        end!@#&                        --Now at the end of a run he does a 180 and moves up to begin the next part of the print!@#&                        sendPC(\"TU\")!@#&                        if layers ~= #frames then!@#&                                sendPC(\"UP\")!@#&                        end!@#&                end!@#&                --All done- now we head back to where we started.!@#&                if px ~= leflim then!@#&                        turnToFace(-1,0)!@#&                        while px ~= leflim do!@#&                                sendPC(\"FW\")!@#&                        end!@#&                end!@#&                if pz ~= botlim then!@#&                        turnToFace(0,-1)!@#&                        while pz ~= botlim do!@#&                                sendPC(\"BK\")!@#&                        end!@#&                end!@#&                turnToFace(0,-1)!@#&                sendPC(\"BK\")!@#&                while py > 0 do!@#&                        sendPC(\"DW\")!@#&                end!@#&        else!@#&                --The front facing is at the top-left corner, facing south not north!@#&                px,py,pz = leflim, botlim, 1!@#&                pfx,pfz = 0,1!@#&                --We move the printer to the last layer- he prints from the back forwards!@#&                while pz < #frames do!@#&                        sendPC(\"FW\")!@#&                end!@#&               !@#&                --For each layer in the frame we build our wall, the move back!@#&                for layers = 1,#frames do!@#&                        --We first decide if we're going left or right based on our position!@#&                        local rowbot,rowtop,rowinc = nil,nil,nil!@#&                        if px == leflim then!@#&                                rowbot,rowtop,rowinc = leflim,riglim,1!@#&                        else!@#&                                rowbot,rowtop,rowinc = riglim,leflim,-1!@#&                        end!@#&                       !@#&                        for rows = rowbot,rowtop,rowinc do!@#&                                --Then we decide if we're going up or down, depending on our given altitude!@#&                                local linebot,linetop,lineinc = nil,nil,nil!@#&                                if py == botlim then!@#&                                        linebot,linetop,lineinc = botlim,toplim,-1!@#&                                else!@#&                                        linebot,linetop,lineinc = toplim,botlim,1!@#&                                end!@#&                               !@#&                                for lines = linebot,linetop,lineinc do!@#&                                --We move our turtle up/down, placing the right material at each step!@#&                                        local material = frames[pz][py][px]!@#&                                        if material then!@#&                                                material = math.log10(frames[pz][py][px])/math.log10(2) + 1!@#&                                                sendPC(\"SS\", material)!@#&                                                sendPC(\"PF\")!@#&                                        end!@#&                                        if lines ~= linetop then!@#&                                                if lineinc == 1 then sendPC(\"DW\")!@#&                                                else sendPC(\"UP\") end!@#&                                        end!@#&                                end!@#&                                       !@#&                                if rows ~= rowtop then!@#&                                        turnToFace(rowinc,0)!@#&                                        sendPC(\"FW\")!@#&                                        turnToFace(0,1)!@#&                                end!@#&                        end!@#&                       !@#&                        if layers ~= #frames then!@#&                                sendPC(\"TU\")!@#&                                sendPC(\"FW\")!@#&                                sendPC(\"TU\")!@#&                        end!@#&                end!@#&                --He's easy to reset!@#&                while px ~= leflim do!@#&                        turnToFace(-1,0)!@#&                        sendPC(\"FW\")!@#&                end!@#&                turnToFace(0,1)!@#&        end!@#&       !@#&        sendPC(\"DE\")!@#&       !@#&        displayConfirmDialogue(\"Print complete\", \"The 3D print was successful.\")!@#&end!@#& !@#&--[[  !@#&                        Section: Interface  !@#&]]--!@#& !@#&--[[Runs the printing interface. Allows users to find/select a printer, the style of printing to perform and to begin the operation!@#&        Params: none!@#&        Returns:boolean true if printing was started, false otherwse!@#&]]--!@#&local function runPrintInterface()!@#&        calculateMaterials()!@#&        --There's nothing on canvas yet!!@#&        if not botlim then!@#&                displayConfirmDialogue(\"Cannot Print Empty Canvas\", \"There is nothing on canvas that \"..!@#&                                \"can be printed, and the operation cannot be completed.\")!@#&                return false!@#&        end!@#&        --No printers nearby!@#&        if not locatePrinters() then!@#&                return false!@#&        end!@#&       !@#&        layering = \"up\"!@#&        requirementsDisplayed = false!@#&        selectedPrinter = 1!@#&        while true do!@#&                drawCanvas()!@#&                term.setBackgroundColour(colours.lightGrey)!@#&                for i=1,10 do!@#&                        term.setCursorPos(1,i)!@#&                        term.clearLine()!@#&                end!@#&                drawInterface()!@#&                term.setBackgroundColour(colours.lightGrey)!@#&                term.setTextColour(colours.black)!@#&               !@#&                local msg = \"3D Printing\"!@#&                term.setCursorPos(w/2-#msg/2 - 2, 1)!@#&                term.write(msg)!@#&                term.setBackgroundColour(colours.grey)!@#&                term.setTextColour(colours.lightGrey)!@#&                if(requirementsDisplayed) then!@#&                        msg = \"Count:\"!@#&                else!@#&                        msg = \" Slot:\"!@#&                end!@#&                term.setCursorPos(w-3-#msg, 1)!@#&                term.write(msg)!@#&                term.setBackgroundColour(colours.lightGrey)!@#&                term.setTextColour(colours.black)!@#&               !@#&                term.setCursorPos(7, 2)!@#&                term.write(\"Layering\")!@#&                drawPictureTable(layerUpIcon, 3, 3, colours.white)!@#&                drawPictureTable(layerForwardIcon, 12, 3, colours.white)!@#&                if layering == \"up\" then!@#&                        term.setBackgroundColour(colours.red)!@#&                else!@#&                        term.setBackgroundColour(colours.lightGrey)!@#&                end!@#&                term.setCursorPos(3, 9)!@#&                term.write(\"Upwards\")!@#&                if layering == \"forward\" then!@#&                        term.setBackgroundColour(colours.red)!@#&                else!@#&                        term.setBackgroundColour(colours.lightGrey)!@#&                end!@#&                term.setCursorPos(12, 9)!@#&                term.write(\"Forward\")!@#&               !@#&                term.setBackgroundColour(colours.lightGrey)!@#&                term.setTextColour(colours.black)!@#&                term.setCursorPos(31, 2)!@#&                term.write(\"Printer ID\")!@#&                term.setCursorPos(33, 3)!@#&                if #printerList > 1 then!@#&                        term.setBackgroundColour(colours.grey)!@#&                        term.setTextColour(colours.lightGrey)!@#&                else!@#&                        term.setTextColour(colours.red)!@#&                end!@#&                term.write(\" \"..printerNames[selectedPrinter]..\" \")!@#&               !@#&                term.setBackgroundColour(colours.grey)!@#&                term.setTextColour(colours.lightGrey)!@#&                term.setCursorPos(25, 10)!@#&                term.write(\" Cancel \")!@#&                term.setCursorPos(40, 10)!@#&                term.write(\" Print \")!@#&               !@#&                local id, p1, p2, p3 = os.pullEvent()!@#&               !@#&                if id == \"timer\" then!@#&                        updateTimer(p1)!@#&                elseif id == \"mouse_click\" then!@#&                        --Layering Buttons!@#&                        if p2 >= 3 and p2 <= 9 and p3 >= 3 and p3 <= 9 then!@#&                                layering = \"up\"!@#&                        elseif p2 >= 12 and p2 <= 18 and p3 >= 3 and p3 <= 9 then!@#&                                layering = \"forward\"!@#&                        --Count/Slot!@#&                        elseif p2 >= w - #msg - 3 and p2 <= w - 3 and p3 == 1 then!@#&                                requirementsDisplayed = not requirementsDisplayed!@#&                        --Printer ID!@#&                        elseif p2 >= 33 and p2 <= 33 + #printerNames[selectedPrinter] and p3 == 3 and #printerList > 1 then!@#&                                local chosenName = displayDropDown(33, 3, printerNames)!@#&                                for i=1,#printerNames do!@#&                                        if printerNames[i] == chosenName then!@#&                                                selectedPrinter = i!@#&                                                break;!@#&                                        end!@#&                                end!@#&                        --Print and Cancel!@#&                        elseif p2 >= 25 and p2 <= 32 and p3 == 10 then!@#&                                break!@#&                        elseif p2 >= 40 and p2 <= 46 and p3 == 10 then!@#&                                rednet.send(printerList[selectedPrinter], \"$3DPRINT ACTIVATE\")!@#&                                ready = false!@#&                                while true do!@#&                                        local id,msg = rsTimeReceive(10)!@#&                                       !@#&                                        if id == printerList[selectedPrinter] and msg == \"$3DPRINT ACTACK\" then!@#&                                                ready = true!@#&                                                break!@#&                                        end!@#&                                end!@#&                                if ready then!@#&                                        performPrint()!@#&                                        break!@#&                                else!@#&                                        displayConfirmDialogue(\"Printer Didn't Respond\", \"The printer didn't respond to the activation command. Check to see if it's online\")!@#&                                end!@#&                        end!@#&                end!@#&        end!@#&        state = \"paint\"!@#&end!@#&!@#&--[[Performs a legacy save. When the dropdown menu is unavailable, it requests the user to save!@#&	or exit using keyboard shortcuts rather than selecting a menu option from the dropdown.!@#&	Pressing the control key again will cancel the save operation.!@#&	Params: none!@#&	Returns:string = the selection made!@#&]]--!@#&local function performLegacySaveExit()!@#&	local saveMsg = \"(S)ave/(E)xit?\"!@#&	if w < #saveMsg then saveMsg = \"S/E?\" end!@#&	!@#&	term.setCursorPos(1,h)!@#&	term.setBackgroundColour(colours.lightGrey)!@#&	term.setTextColour(colours.grey)!@#&	term.clearLine()!@#&	term.write(saveMsg)!@#&	!@#&	while true do!@#&		local id,val = os.pullEvent()!@#&		if id == \"timer\" then updateTimer(val)!@#&		elseif id == \"key\" then!@#&			if val == keys.s then return \"save\" !@#&			elseif val == keys.e then!@#&				--Get rid of the extra event!@#&				os.pullEvent(\"char\")!@#&				return \"exit\"!@#&			elseif val == keys.leftCtrl then return nil!@#&			end!@#&		end!@#&	end!@#&end!@#& !@#&--[[This function changes the current paint program to another tool or mode, depending on user input. Handles!@#&        any necessary changes in logic involved in that.!@#&        Params: mode:string = the name of the mode to change to!@#&        Returns:nil!@#&]]--!@#&local function performSelection(mode)!@#&        if not mode or mode == \"\" then return!@#&       !@#&        elseif mode == \"help\" and helpAvailable then!@#&                drawHelpScreen()!@#&               !@#&        elseif mode == \"blueprint on\" then!@#&                blueprint = true!@#&				for i=1,#ddModes[2] do if ddModes[2][i] == \"blueprint on\" then!@#&					ddModes[2][i] = \"blueprint off\"!@#&				end end!@#&               !@#&        elseif mode == \"blueprint off\" then!@#&                blueprint = false!@#&				for i=1,#ddModes[2] do if ddModes[2][i] == \"blueprint off\" then!@#&					ddModes[2][i] = \"blueprint on\"!@#&				end end!@#&               !@#&        elseif mode == \"layers on\" then!@#&                layerDisplay = true!@#&				for i=1,#ddModes[2] do if ddModes[2][i] == \"layers on\" then!@#&					ddModes[2][i] = \"layers off\"!@#&				end end!@#&       !@#&        elseif mode == \"layers off\" then!@#&                layerDisplay = false!@#&				for i=1,#ddModes[2] do if ddModes[2][i] == \"layers off\" then!@#&					ddModes[2][i] = \"layers on\"!@#&				end end!@#&       !@#&        elseif mode == \"direction on\" then!@#&                printDirection = true!@#&				for i=1,#ddModes[2] do if ddModes[2][i] == \"direction on\" then!@#&					ddModes[2][i] = \"direction off\"!@#&				end end!@#&               !@#&        elseif mode == \"direction off\" then!@#&                printDirection = false!@#&				for i=1,#ddModes[2] do if ddModes[2][i] == \"direction off\" then!@#&					ddModes[2][i] = \"direction on\"!@#&				end end!@#&		!@#&		elseif mode == \"hide interface\" then!@#&				interfaceHidden = true!@#&			!@#&		elseif mode == \"show interface\" then!@#&				interfaceHidden = false!@#&       !@#&        elseif mode == \"go to\" then!@#&                changeFrame()!@#&       !@#&        elseif mode == \"remove\" then!@#&                removeFramesAfter(sFrame)!@#&       !@#&        elseif mode == \"play\" then!@#&                playAnimation()!@#&               !@#&        elseif mode == \"copy\" then!@#&                if selectrect and selectrect.x1 ~= selectrect.x2 then!@#&                        copyToBuffer(false)!@#&                end!@#&       !@#&        elseif mode == \"cut\" then!@#&                if selectrect and selectrect.x1 ~= selectrect.x2 then!@#&                        copyToBuffer(true)!@#&                end!@#&               !@#&        elseif mode == \"paste\" then!@#&                if selectrect and selectrect.x1 ~= selectrect.x2 then!@#&                        copyFromBuffer(false)!@#&                end!@#&               !@#&        elseif mode == \"hide\" then!@#&                selectrect = nil!@#&                if state == \"select\" then state = \"corner select\" end!@#&			   !@#&        elseif mode == \"alpha to left\" then!@#&                if lSel then alphaC = lSel end!@#&               !@#&        elseif mode == \"alpha to right\" then!@#&                if rSel then alphaC = rSel end!@#&               !@#&        elseif mode == \"record\" then!@#&                record = not record!@#&               !@#&        elseif mode == \"clear\" then!@#&                if state==\"select\" then buffer = nil!@#&                else clearImage() end!@#&       !@#&        elseif mode == \"select\" then!@#&                if state==\"corner select\" or state==\"select\" then!@#&                        state = \"paint\"!@#&                elseif selectrect and selectrect.x1 ~= selectrect.x2 then!@#&                        state = \"select\"!@#&                else!@#&                        state = \"corner select\"!@#&                end!@#&               !@#&        elseif mode == \"print\" then!@#&                state = \"print\"!@#&                runPrintInterface()!@#&                state = \"paint\"!@#&               !@#&        elseif mode == \"save\" then!@#&                if animated then saveNFA(sPath)!@#&                elseif textEnabled then saveNFT(sPath)!@#&                else saveNFP(sPath) end!@#&               !@#&        elseif mode == \"exit\" then!@#&                isRunning = false!@#&       !@#&        elseif mode ~= state then state = mode!@#&        else state = \"paint\"!@#&        end!@#&end!@#& !@#&--[[The main function of the program, reads and handles all events and updates them accordingly. Mode changes,!@#&        painting to the canvas and general selections are done here.!@#&        Params: none!@#&        Returns:nil!@#&]]--!@#&local function handleEvents()!@#&        recttimer = os.startTimer(0.5)!@#&        while isRunning do!@#&                drawCanvas()!@#&                if not interfaceHidden then drawInterface() end!@#&               !@#&                if state == \"text\" then!@#&                        term.setCursorPos(textCurX - sx, textCurY - sy)!@#&                        term.setCursorBlink(true)!@#&                end!@#&               !@#&                local id,p1,p2,p3 = os.pullEvent()!@#&                term.setCursorBlink(false)!@#&                if id==\"timer\" then!@#&                        updateTimer(p1)!@#&                elseif (id==\"mouse_click\" or id==\"mouse_drag\") and not interfaceHidden then!@#&                        if p2 >=w-1 and p3 < #column+1 then!@#&								local off = 0!@#&								local cansel = true!@#&								if h < #column + 2 then!@#&									if p3 == 1 then !@#&										if columnoffset > 0 then columnoffset = columnoffset-1 end!@#&										cansel = false!@#&									elseif p3 == h-2 then!@#&										if columnoffset < #column-(h-4)+1 then columnoffset = columnoffset+1 end!@#&										cansel = false!@#&									else!@#&										off = columnoffset - 1!@#&									end!@#&								end!@#&								--This rather handily accounts for the nil case (p3+off=#column+1)!@#&								if p1==1 and cansel then lSel = column[p3+off]!@#&                                elseif p1==2 and cansel then rSel = column[p3+off] end!@#&                        elseif p2 >=w-1 and p3==#column+1 then!@#&                                if p1==1 then lSel = nil!@#&                                else rSel = nil end!@#&                        elseif p2==w-1 and p3==h and animated then!@#&                                changeFrame(sFrame-1)!@#&                        elseif p2==w and p3==h and animated then!@#&                                changeFrame(sFrame+1)!@#&                        elseif p2 <= #ddModes.name + 2 and p3==h and mainAvailable then!@#&                                local sel = displayDropDown(1, h-1, ddModes)!@#&                                performSelection(sel)!@#&                        elseif p2 < w-1 and p3 <= h-1 then!@#&                                if state==\"pippette\" then!@#&                                        if p1==1 then!@#&                                                if frames[sFrame][p3+sy] and frames[sFrame][p3+sy][p2+sx] then!@#&                                                        lSel = frames[sFrame][p3+sy][p2+sx]!@#&                                                end!@#&                                        elseif p1==2 then!@#&                                                if frames[sFrame][p3+sy] and frames[sFrame][p3+sy][p2+sx] then!@#&                                                        rSel = frames[sFrame][p3+sy][p2+sx]!@#&                                                end!@#&                                        end!@#&                                elseif state==\"move\" then!@#&                                        updateImageLims(record)!@#&                                        moveImage(p2,p3)!@#&                                elseif state==\"flood\" then!@#&                                        if p1 == 1 and lSel and frames[sFrame][p3+sy]  then!@#&                                                floodFill(p2,p3,frames[sFrame][p3+sy][p2+sx],lSel)!@#&                                        elseif p1 == 2 and rSel and frames[sFrame][p3+sy] then!@#&                                                floodFill(p2,p3,frames[sFrame][p3+sy][p2+sx],rSel)!@#&                                        end!@#&                                elseif state==\"corner select\" then!@#&                                        if not selectrect then!@#&                                                selectrect = { x1=p2+sx, x2=p2+sx, y1=p3+sy, y2=p3+sy }!@#&                                        elseif selectrect.x1 ~= p2+sx and selectrect.y1 ~= p3+sy then!@#&                                                if p2+sx<selectrect.x1 then selectrect.x1 = p2+sx!@#&                                                else selectrect.x2 = p2+sx end!@#&                                               !@#&                                                if p3+sy<selectrect.y1 then selectrect.y1 = p3+sy!@#&                                                else selectrect.y2 = p3+sy end!@#&                                               !@#&                                                state = \"select\"!@#&                                        end!@#&                                elseif state==\"textpaint\" then!@#&                                        local paintCol = lSel!@#&                                        if p1 == 2 then paintCol = rSel end!@#&                                        if frames[sFrame].textcol[p3+sy] then!@#&                                                frames[sFrame].textcol[p3+sy][p2+sx] = paintCol!@#&                                        end!@#&                                elseif state==\"text\" then!@#&                                        textCurX = p2 + sx!@#&                                        textCurY = p3 + sy!@#&                                elseif state==\"select\" then!@#&                                        if p1 == 1 then!@#&                                                local swidth = selectrect.x2 - selectrect.x1!@#&                                                local sheight = selectrect.y2 - selectrect.y1!@#&                                       !@#&                                                selectrect.x1 = p2 + sx!@#&                                                selectrect.y1 = p3 + sy!@#&                                                selectrect.x2 = p2 + swidth + sx!@#&                                                selectrect.y2 = p3 + sheight + sy!@#&                                        elseif p1 == 2 and p2 < w-2 and p3 < h-1 and boxdropAvailable then!@#&                                                inMenu = true!@#&                                                local sel = displayDropDown(p2, p3, srModes)!@#&                                                inMenu = false!@#&                                                performSelection(sel)!@#&                                        end!@#&                                else!@#&                                        local f,l = sFrame,sFrame!@#&                                        if record then f,l = 1,framecount end!@#&                                        local bwidth = 0!@#&                                        if state == \"brush\" then bwidth = brushsize-1 end!@#&                               !@#&                                        for i=f,l do!@#&                                                for x = math.max(1,p2+sx-bwidth),p2+sx+bwidth do!@#&                                                        for y = math.max(1,p3+sy-bwidth), p3+sy+bwidth do!@#&                                                                if math.abs(x - (p2+sx)) + math.abs(y - (p3+sy)) <= bwidth then!@#&                                                                        if not frames[i][y] then frames[i][y] = {} end!@#&                                                                        if p1==1 then frames[i][y][x] = lSel!@#&                                                                        else frames[i][y][x] = rSel end!@#&                                                                       !@#&                                                                        if textEnabled then!@#&                                                                                if not frames[i].text[y] then frames[i].text[y] = { } end!@#&                                                                                if not frames[i].textcol[y] then frames[i].textcol[y] = { } end!@#&                                                                        end!@#&                                                                end!@#&                                                        end!@#&                                                end!@#&                                        end!@#&                                end!@#&                        end!@#&                elseif id==\"char\" then!@#&                        if state==\"text\" then!@#&                                if not frames[sFrame][textCurY] then frames[sFrame][textCurY] = { } end!@#&                                if not frames[sFrame].text[textCurY] then frames[sFrame].text[textCurY] = { } end!@#&                                if not frames[sFrame].textcol[textCurY] then frames[sFrame].textcol[textCurY] = { } end!@#&                               !@#&                                if rSel then frames[sFrame][textCurY][textCurX] = rSel end!@#&                                if lSel then!@#&                                        frames[sFrame].text[textCurY][textCurX] = p1!@#&                                        frames[sFrame].textcol[textCurY][textCurX] = lSel!@#&                                else!@#&                                        frames[sFrame].text[textCurY][textCurX] = \" \"!@#&                                        frames[sFrame].textcol[textCurY][textCurX] = rSel!@#&                                end!@#&                               !@#&                                textCurX = textCurX+1!@#&                                if textCurX > w + sx - 2 then sx = textCurX - w + 2 end!@#&                        elseif tonumber(p1) then!@#&                                if state==\"brush\" and tonumber(p1) > 1 then!@#&                                        brushsize = tonumber(p1)!@#&                                elseif animated and tonumber(p1) > 0 then!@#&                                        changeFrame(tonumber(p1))!@#&                                end!@#&                        end!@#&                elseif id==\"key\" then!@#&						--All standard interface methods are locked when the interface is hidden!@#&						if interfaceHidden then!@#&							if p1==keys.grave then!@#&								performSelection(\"show interface\") !@#&							end!@#&                        --Text needs special handlers (all other keyboard shortcuts are of course reserved for typing)!@#&                        elseif state==\"text\" then!@#&                                if p1==keys.backspace and textCurX > 1 then!@#&                                        textCurX = textCurX-1!@#&                                        if frames[sFrame].text[textCurY] then!@#&                                                frames[sFrame].text[textCurY][textCurX] = nil!@#&                                                frames[sFrame].textcol[textCurY][textCurX] = nil!@#&                                        end!@#&                                        if textCurX < sx then sx = textCurX end!@#&                                elseif p1==keys.left and textCurX > 1 then!@#&                                        textCurX = textCurX-1!@#&                                        if textCurX-1 < sx then sx = textCurX-1 end!@#&                                elseif p1==keys.right then!@#&                                        textCurX = textCurX+1!@#&                                        if textCurX > w + sx - 2 then sx = textCurX - w + 2 end!@#&                                elseif p1==keys.up and textCurY > 1 then!@#&                                        textCurY = textCurY-1!@#&                                        if textCurY-1 < sy then sy = textCurY-1 end!@#&                                elseif p1==keys.down then!@#&                                        textCurY = textCurY+1!@#&                                        if textCurY > h + sy - 1 then sy = textCurY - h + 1 end!@#&                                end!@#&                       !@#&                        elseif p1==keys.leftCtrl then!@#&                                local sel = nil!@#&								if mainAvailable then !@#&									sel = displayDropDown(1, h-1, ddModes[#ddModes])!@#&								else sel = performLegacySaveExit() end!@#&                                performSelection(sel)!@#&                        elseif p1==keys.leftAlt then!@#&                                local sel = displayDropDown(1, h-1, ddModes[1])!@#&                                performSelection(sel)!@#&                        elseif p1==keys.h then!@#&                                performSelection(\"help\")!@#&                        elseif p1==keys.x then!@#&                                performSelection(\"cut\")!@#&                        elseif p1==keys.c then!@#&                                performSelection(\"copy\")!@#&                        elseif p1==keys.v then!@#&                                performSelection(\"paste\")!@#&                        elseif p1==keys.z then!@#&                                performSelection(\"clear\")!@#&                        elseif p1==keys.s then!@#&                                performSelection(\"select\")!@#&                        elseif p1==keys.tab then!@#&                                performSelection(\"hide\")!@#&                        elseif p1==keys.q then!@#&                                performSelection(\"alpha to left\")!@#&                        elseif p1==keys.w then!@#&                                performSelection(\"alpha to right\")!@#&                        elseif p1==keys.f then!@#&                                performSelection(\"flood\")!@#&                        elseif p1==keys.b then!@#&                                performSelection(\"brush\")!@#&                        elseif p1==keys.m then!@#&                                performSelection(\"move\")!@#&                        elseif p1==keys.backslash and animated then!@#&                                performSelection(\"record\")!@#&                        elseif p1==keys.p then!@#&                                performSelection(\"pippette\")!@#&                        elseif p1==keys.g and animated then!@#&                                performSelection(\"go to\")!@#&						elseif p1==keys.grave then !@#&								performSelection(\"hide interface\")!@#&                        elseif p1==keys.period and animated then!@#&                                changeFrame(sFrame+1)!@#&                        elseif p1==keys.comma and animated then!@#&                                changeFrame(sFrame-1)!@#&                        elseif p1==keys.r and animated then!@#&                                performSelection(\"remove\")!@#&                        elseif p1==keys.space and animated then!@#&                                performSelection(\"play\")!@#&                        elseif p1==keys.t and textEnabled then!@#&                                performSelection(\"text\")!@#&                                sleep(0.01)!@#&                        elseif p1==keys.y and textEnabled then!@#&                                performSelection(\"textpaint\")!@#&                        elseif p1==keys.left then!@#&                                if state == \"move\" and toplim then!@#&                                        updateImageLims(record)!@#&                                        if toplim and leflim then!@#&                                                moveImage(leflim-1,toplim)!@#&                                        end!@#&                                elseif state==\"select\" and selectrect.x1 > 1 then!@#&                                        selectrect.x1 = selectrect.x1-1!@#&                                        selectrect.x2 = selectrect.x2-1!@#&                                elseif sx > 0 then sx=sx-1 end!@#&                        elseif p1==keys.right then!@#&                                if state == \"move\" then!@#&                                        updateImageLims(record)!@#&                                        if toplim and leflim then!@#&                                                moveImage(leflim+1,toplim)!@#&                                        end!@#&                                elseif state==\"select\" then!@#&                                        selectrect.x1 = selectrect.x1+1!@#&                                        selectrect.x2 = selectrect.x2+1!@#&                                else sx=sx+1 end!@#&                        elseif p1==keys.up then!@#&                                if state == \"move\" then!@#&                                        updateImageLims(record)!@#&                                        if toplim and leflim then!@#&                                                moveImage(leflim,toplim-1)!@#&                                        end!@#&                                elseif state==\"select\" and selectrect.y1 > 1 then!@#&                                        selectrect.y1 = selectrect.y1-1!@#&                                        selectrect.y2 = selectrect.y2-1!@#&                                elseif sy > 0 then sy=sy-1 end!@#&                        elseif p1==keys.down then!@#&                                if state == \"move\" then!@#&                                        updateImageLims(record)!@#&                                        if toplim and leflim then!@#&                                                moveImage(leflim,toplim+1)!@#&                                        end!@#&                                elseif state==\"select\" then!@#&                                        selectrect.y1 = selectrect.y1+1!@#&                                        selectrect.y2 = selectrect.y2+1!@#&                                else sy=sy+1 end!@#&                        end!@#&                end!@#&        end!@#&end!@#& !@#&--[[!@#&                        Section: Main  !@#&]]--!@#& !@#&--The first thing done is deciding what features we actually have, given the screen size!@#&if w < 7 or h < 4 then!@#&	--NPaintPro simply doesn't work at certain configurations!@#&	shell.run(\"clear\")!@#&	print(\"Screen too small\")!@#&	os.pullEvent(\"key\")!@#&	return!@#&end!@#&--And reduces the number of features in others.!@#&determineAvailableServices()!@#& !@#&--There is no b&w support for NPP.!@#&if not term.isColour() then!@#&	shell.run(\"clear\")!@#&	print(\"NPaintPro\\nBy NitrogenFingers\\n\\nNPaintPro can only be run on advanced \"..!@#&	\"computers. Please reinstall on an advanced computer.\")!@#&    return!@#&end!@#& !@#&--Taken almost directly from edit (for consistency)!@#&local tArgs = {...}!@#& !@#&--Command line options can appear before the file path to specify the file format!@#&local ca = 1!@#&while ca <= #tArgs do!@#&	if tArgs[ca] == \"-a\" then animated = true!@#&	elseif tArgs[ca] == \"-t\" then textEnabled = true!@#&	elseif tArgs[ca] == \"-d\" then interfaceHidden = true!@#&	elseif string.sub(tArgs[ca], 1, 1) == \"-\" then!@#&		print(\"Unrecognized option: \"..tArgs[ca])!@#&		return!@#&	else break end!@#&	ca = ca + 1!@#&end!@#&!@#&--Presently, animations and text files are not supported!@#&if animated and textEnabled then!@#&    print(\"No support for animated text files- cannot have both -a and -t\")!@#&	return!@#&end!@#&!@#&--Filepaths must be added if the screen is too small!@#&if #tArgs < ca then!@#&	if not filemakerAvailable then!@#&		print(\"Usage: npaintpro [-a,-t,-d] <path>\")!@#&		return!@#&	else!@#&		--Otherwise do the logo draw early, to determine the file.!@#&		drawLogo()!@#&		if not runFileMaker() then return end!@#&	end!@#&else!@#&	if not interfaceHidden then drawLogo() end!@#&	sPath = shell.resolve(tArgs[ca])!@#&end!@#& !@#&if fs.exists(sPath) then!@#&        if fs.isDir(sPath) then!@#&                print(\"Cannot edit a directory.\")!@#&                return!@#&        elseif string.find(sPath, \".nfp\") ~= #sPath-3 and string.find(sPath, \".nfa\") ~= #sPath-3 and!@#&                        string.find(sPath, \".nft\") ~= #sPath-3 then!@#&                print(\"Can only edit .nfp, .nft and .nfa files:\",string.find(sPath, \".nfp\"),#sPath-3)!@#&                return!@#&        end!@#&       !@#&        if string.find(sPath, \".nfa\") == #sPath-3 then!@#&                animated = true!@#&        end!@#&       !@#&        if string.find(sPath, \".nft\") == #sPath-3 then!@#&                textEnabled = true!@#&        end    !@#&       !@#&        if string.find(sPath, \".nfp\") == #sPath-3 and animated then!@#&                print(\"Convert to nfa? Y/N\")!@#&                if string.find(string.lower(io.read()), \"y\") then!@#&                        local nsPath = string.sub(sPath, 1, #sPath-1)..\"a\"!@#&                        fs.move(sPath, nsPath)!@#&                        sPath = nsPath!@#&                else!@#&                        animated = false!@#&                end!@#&        end!@#&       !@#&        --Again this is possible, I just haven't done it. Maybe I will?!@#&        if textEnabled and (string.find(sPath, \".nfp\") == #sPath-3 or string.find(sPath, \".nfa\") == #sPath-3) then!@#&                print(\"Cannot convert to nft\")!@#&        end!@#&else!@#&        if not animated and not textEnabled and string.find(sPath, \".nfp\") ~= #sPath-3 then!@#&                sPath = sPath..\".nfp\"!@#&        elseif animated and string.find(sPath, \".nfa\") ~= #sPath-3 then!@#&                sPath = sPath..\".nfa\"!@#&        elseif textEnabled and string.find(sPath, \".nft\") ~= #sPath-3 then!@#&                sPath = sPath..\".nft\"!@#&        end!@#&end!@#& !@#&init()!@#&handleEvents()!@#& !@#&term.setBackgroundColour(colours.black)!@#&shell.run(\"clear\")",["luaide"]="!@#&--  !@#&--  Lua IDE!@#&--  Made by GravityScore!@#&--  !@#&!@#&!@#&--  -------- Variables!@#&!@#&-- Version!@#&local version = \"1.0\"!@#&local args = {...}!@#&!@#&-- Editing!@#&local w, h = term.getSize()!@#&local tabWidth = 2!@#&!@#&local autosaveInterval = 20!@#&local allowEditorEvent = true!@#&local keyboardShortcutTimeout = 0.4!@#&!@#&-- Clipboard!@#&local clipboard = nil!@#&!@#&-- Theme!@#&local theme = {}!@#&!@#&-- Language!@#&local languages = {}!@#&local curLanguage = {}!@#&!@#&-- Events!@#&local event_distract = \"luaide_distractionEvent\"!@#&!@#&-- Locations!@#&local updateURL = \"https://raw.github.com/GravityScore/LuaIDE/master/luaide.lua\"!@#&local ideLocation = \"/\" .. shell.getRunningProgram()!@#&local themeLocation = \"/.LuaIDE-Theme\"!@#&!@#&local function isAdvanced() return term.isColor and term.isColor() end!@#&!@#&!@#&--  -------- Utilities!@#&!@#&local function modRead(properties)!@#&	local w, h = term.getSize()!@#&	local defaults = {replaceChar = nil, history = nil, visibleLength = nil, textLength = nil, !@#&		liveUpdates = nil, exitOnKey = nil}!@#&	if not properties then properties = {} end!@#&	for k, v in pairs(defaults) do if not properties[k] then properties[k] = v end end!@#&	if properties.replaceChar then properties.replaceChar = properties.replaceChar:sub(1, 1) end!@#&	if not properties.visibleLength then properties.visibleLength = w end!@#&!@#&	local sx, sy = term.getCursorPos()!@#&	local line = \"\"!@#&	local pos = 0!@#&	local historyPos = nil!@#&!@#&	local function redraw(repl)!@#&		local scroll = 0!@#&		if properties.visibleLength and sx + pos > properties.visibleLength + 1 then !@#&			scroll = (sx + pos) - (properties.visibleLength + 1)!@#&		end!@#&!@#&		term.setCursorPos(sx, sy)!@#&		local a = repl or properties.replaceChar!@#&		if a then term.write(string.rep(a, line:len() - scroll))!@#&		else term.write(line:sub(scroll + 1, -1)) end!@#&		term.setCursorPos(sx + pos - scroll, sy)!@#&	end!@#&!@#&	local function sendLiveUpdates(event, ...)!@#&		if type(properties.liveUpdates) == \"function\" then!@#&			local ox, oy = term.getCursorPos()!@#&			local a, data = properties.liveUpdates(line, event, ...)!@#&			if a == true and data == nil then!@#&				term.setCursorBlink(false)!@#&				return line!@#&			elseif a == true and data ~= nil then!@#&				term.setCursorBlink(false)!@#&				return data!@#&			end!@#&			term.setCursorPos(ox, oy)!@#&		end!@#&	end!@#&!@#&	term.setCursorBlink(true)!@#&	while true do!@#&		local e, but, x, y, p4, p5 = os.pullEvent()!@#&!@#&		if e == \"char\" then!@#&			local s = false!@#&			if properties.textLength and line:len() < properties.textLength then s = true!@#&			elseif not properties.textLength then s = true end!@#&!@#&			local canType = true!@#&			if not properties.grantPrint and properties.refusePrint then!@#&				local canTypeKeys = {}!@#&				if type(properties.refusePrint) == \"table\" then!@#&					for _, v in pairs(properties.refusePrint) do!@#&						table.insert(canTypeKeys, tostring(v):sub(1, 1))!@#&					end!@#&				elseif type(properties.refusePrint) == \"string\" then!@#&					for char in properties.refusePrint:gmatch(\".\") do!@#&						table.insert(canTypeKeys, char)!@#&					end!@#&				end!@#&				for _, v in pairs(canTypeKeys) do if but == v then canType = false end end!@#&			elseif properties.grantPrint then!@#&				canType = false!@#&				local canTypeKeys = {}!@#&				if type(properties.grantPrint) == \"table\" then!@#&					for _, v in pairs(properties.grantPrint) do!@#&						table.insert(canTypeKeys, tostring(v):sub(1, 1))!@#&					end!@#&				elseif type(properties.grantPrint) == \"string\" then!@#&					for char in properties.grantPrint:gmatch(\".\") do!@#&						table.insert(canTypeKeys, char)!@#&					end!@#&				end!@#&				for _, v in pairs(canTypeKeys) do if but == v then canType = true end end!@#&			end!@#&!@#&			if s and canType then!@#&				line = line:sub(1, pos) .. but .. line:sub(pos + 1, -1)!@#&				pos = pos + 1!@#&				redraw()!@#&			end!@#&		elseif e == \"key\" then!@#&			if but == keys.enter then break!@#&			elseif but == keys.left then if pos > 0 then pos = pos - 1 redraw() end!@#&			elseif but == keys.right then if pos < line:len() then pos = pos + 1 redraw() end!@#&			elseif (but == keys.up or but == keys.down) and properties.history then!@#&				redraw(\" \")!@#&				if but == keys.up then!@#&					if historyPos == nil and #properties.history > 0 then !@#&						historyPos = #properties.history!@#&					elseif historyPos > 1 then !@#&						historyPos = historyPos - 1!@#&					end!@#&				elseif but == keys.down then!@#&					if historyPos == #properties.history then historyPos = nil!@#&					elseif historyPos ~= nil then historyPos = historyPos + 1 end!@#&				end!@#&!@#&				if properties.history and historyPos then!@#&					line = properties.history[historyPos]!@#&					pos = line:len()!@#&				else!@#&					line = \"\"!@#&					pos = 0!@#&				end!@#&!@#&				redraw()!@#&				local a = sendLiveUpdates(\"history\")!@#&				if a then return a end!@#&			elseif but == keys.backspace and pos > 0 then!@#&				redraw(\" \")!@#&				line = line:sub(1, pos - 1) .. line:sub(pos + 1, -1)!@#&				pos = pos - 1!@#&				redraw()!@#&				local a = sendLiveUpdates(\"delete\")!@#&				if a then return a end!@#&			elseif but == keys.home then!@#&				pos = 0!@#&				redraw()!@#&			elseif but == keys.delete and pos < line:len() then!@#&				redraw(\" \")!@#&				line = line:sub(1, pos) .. line:sub(pos + 2, -1)!@#&				redraw()!@#&				local a = sendLiveUpdates(\"delete\")!@#&				if a then return a end!@#&			elseif but == keys[\"end\"] then!@#&				pos = line:len()!@#&				redraw()!@#&			elseif properties.exitOnKey then !@#&				if but == properties.exitOnKey or (properties.exitOnKey == \"control\" and !@#&						(but == 29 or but == 157)) then !@#&					term.setCursorBlink(false)!@#&					return nil!@#&				end!@#&			end!@#&		end!@#&		local a = sendLiveUpdates(e, but, x, y, p4, p5)!@#&		if a then return a end!@#&	end!@#&!@#&	term.setCursorBlink(false)!@#&	if line ~= nil then line = line:gsub(\"^%s*(.-)%s*$\", \"%1\") end!@#&	return line!@#&end!@#&!@#&!@#&--  -------- Themes!@#&!@#&local defaultTheme = {!@#&	background = \"gray\",!@#&	backgroundHighlight = \"lightGray\",!@#&	prompt = \"cyan\",!@#&	promptHighlight = \"lightBlue\",!@#&	err = \"red\",!@#&	errHighlight = \"pink\",!@#&!@#&	editorBackground = \"gray\",!@#&	editorLineHightlight = \"lightBlue\",!@#&	editorLineNumbers = \"gray\",!@#&	editorLineNumbersHighlight = \"lightGray\",!@#&	editorError = \"pink\",!@#&	editorErrorHighlight = \"red\",!@#&!@#&	textColor = \"white\",!@#&	conditional = \"yellow\",!@#&	constant = \"orange\",!@#&	[\"function\"] = \"magenta\",!@#&	string = \"red\",!@#&	comment = \"lime\"!@#&}!@#&!@#&local normalTheme = {!@#&	background = \"black\",!@#&	backgroundHighlight = \"black\",!@#&	prompt = \"black\",!@#&	promptHighlight = \"black\",!@#&	err = \"black\",!@#&	errHighlight = \"black\",!@#&!@#&	editorBackground = \"black\",!@#&	editorLineHightlight = \"black\",!@#&	editorLineNumbers = \"black\",!@#&	editorLineNumbersHighlight = \"white\",!@#&	editorError = \"black\",!@#&	editorErrorHighlight = \"black\",!@#&!@#&	textColor = \"white\",!@#&	conditional = \"white\",!@#&	constant = \"white\",!@#&	[\"function\"] = \"white\",!@#&	string = \"white\",!@#&	comment = \"white\"!@#&}!@#&!@#&local availableThemes = {!@#&	{\"Water (Default)\", \"https://raw.github.com/GravityScore/LuaIDE/master/themes/default.txt\"},!@#&	{\"Fire\", \"https://raw.github.com/GravityScore/LuaIDE/master/themes/fire.txt\"},!@#&	{\"Sublime Text 2\", \"https://raw.github.com/GravityScore/LuaIDE/master/themes/st2.txt\"},!@#&	{\"Midnight\", \"https://raw.github.com/GravityScore/LuaIDE/master/themes/midnight.txt\"},!@#&	{\"TheOriginalBIT\", \"https://raw.github.com/GravityScore/LuaIDE/master/themes/bit.txt\"},!@#&	{\"Superaxander\", \"https://raw.github.com/GravityScore/LuaIDE/master/themes/superaxander.txt\"},!@#&	{\"Forest\", \"https://raw.github.com/GravityScore/LuaIDE/master/themes/forest.txt\"},!@#&	{\"Night\", \"https://raw.github.com/GravityScore/LuaIDE/master/themes/night.txt\"},!@#&	{\"Original\", \"https://raw.github.com/GravityScore/LuaIDE/master/themes/original.txt\"},!@#&}!@#&!@#&local function loadTheme(path)!@#&	local f = io.open(path)!@#&	local l = f:read(\"*l\")!@#&	local config = {}!@#&	while l ~= nil do!@#&		local k, v = string.match(l, \"^(%a+)=(%a+)\")!@#&		if k and v then config[k] = v end!@#&		l = f:read(\"*l\")!@#&	end!@#&	f:close()!@#&	return config!@#&end!@#&!@#&-- Load Theme!@#&if isAdvanced() then theme = defaultTheme!@#&else theme = normalTheme end!@#&!@#&!@#&--  -------- Drawing!@#&!@#&local function centerPrint(text, ny)!@#&	if type(text) == \"table\" then for _, v in pairs(text) do centerPrint(v) end!@#&	else!@#&		local x, y = term.getCursorPos()!@#&		local w, h = term.getSize()!@#&		term.setCursorPos(w/2 - text:len()/2 + (#text % 2 == 0 and 1 or 0), ny or y)!@#&		print(text)!@#&	end!@#&end!@#&!@#&local function title(t)!@#&	term.setTextColor(colors[theme.textColor])!@#&	term.setBackgroundColor(colors[theme.background])!@#&	term.clear()!@#&!@#&	term.setBackgroundColor(colors[theme.backgroundHighlight])!@#&	for i = 2, 4 do term.setCursorPos(1, i) term.clearLine() end!@#&	term.setCursorPos(3, 3)!@#&	term.write(t)!@#&end!@#&!@#&local function centerRead(wid, begt)!@#&	local function liveUpdate(line, e, but, x, y, p4, p5)!@#&		if isAdvanced() and e == \"mouse_click\" and x >= w/2 - wid/2 and x <= w/2 - wid/2 + 10 !@#&				and y >= 13 and y <= 15 then!@#&			return true, \"\"!@#&		end!@#&	end!@#&!@#&	if not begt then begt = \"\" end!@#&	term.setTextColor(colors[theme.textColor])!@#&	term.setBackgroundColor(colors[theme.promptHighlight])!@#&	for i = 8, 10 do!@#&		term.setCursorPos(w/2 - wid/2, i)!@#&		term.write(string.rep(\" \", wid))!@#&	end!@#&!@#&	if isAdvanced() then!@#&		term.setBackgroundColor(colors[theme.errHighlight])!@#&		for i = 13, 15 do!@#&			term.setCursorPos(w/2 - wid/2 + 1, i)!@#&			term.write(string.rep(\" \", 10))!@#&		end!@#&		term.setCursorPos(w/2 - wid/2 + 2, 14)!@#&		term.write(\"> Cancel\")!@#&	end!@#&!@#&	term.setBackgroundColor(colors[theme.promptHighlight])!@#&	term.setCursorPos(w/2 - wid/2 + 1, 9)!@#&	term.write(\"> \" .. begt)!@#&	return modRead({visibleLength = w/2 + wid/2, liveUpdates = liveUpdate})!@#&end!@#&!@#&!@#&--  -------- Prompt!@#&!@#&local function prompt(list, dir, isGrid)!@#&	local function draw(sel)!@#&		for i, v in ipairs(list) do!@#&			if i == sel then term.setBackgroundColor(v.highlight or colors[theme.promptHighlight])!@#&			else term.setBackgroundColor(v.bg or colors[theme.prompt]) end!@#&			term.setTextColor(v.tc or colors[theme.textColor])!@#&			for i = -1, 1 do!@#&				term.setCursorPos(v[2], v[3] + i)!@#&				term.write(string.rep(\" \", v[1]:len() + 4))!@#&			end!@#&!@#&			term.setCursorPos(v[2], v[3])!@#&			if i == sel then!@#&				term.setBackgroundColor(v.highlight or colors[theme.promptHighlight])!@#&				term.write(\" > \")!@#&			else term.write(\" - \") end!@#&			term.write(v[1] .. \" \")!@#&		end!@#&	end!@#&!@#&	local key1 = dir == \"horizontal\" and 203 or 200!@#&	local key2 = dir == \"horizontal\" and 205 or 208!@#&	local sel = 1!@#&	draw(sel)!@#&!@#&	while true do!@#&		local e, but, x, y = os.pullEvent()!@#&		if e == \"key\" and but == 28 then!@#&			return list[sel][1]!@#&		elseif e == \"key\" and but == key1 and sel > 1 then!@#&			sel = sel - 1!@#&			draw(sel)!@#&		elseif e == \"key\" and but == key2 and ((err == true and sel < #list - 1) or (sel < #list)) then!@#&			sel = sel + 1!@#&			draw(sel)!@#&		elseif isGrid and e == \"key\" and but == 203 and sel > 2 then!@#&			sel = sel - 2!@#&			draw(sel)!@#&		elseif isGrid and e == \"key\" and but == 205 and sel < 3 then!@#&			sel = sel + 2!@#&			draw(sel)!@#&		elseif e == \"mouse_click\" then!@#&			for i, v in ipairs(list) do!@#&				if x >= v[2] - 1 and x <= v[2] + v[1]:len() + 3 and y >= v[3] - 1 and y <= v[3] + 1 then!@#&					return list[i][1]!@#&				end!@#&			end!@#&		end!@#&	end!@#&end!@#&!@#&local function scrollingPrompt(list)!@#&	local function draw(items, sel, loc)!@#&		for i, v in ipairs(items) do!@#&			local bg = colors[theme.prompt]!@#&			local bghigh = colors[theme.promptHighlight]!@#&			if v:find(\"Back\") or v:find(\"Return\") then!@#&				bg = colors[theme.err]!@#&				bghigh = colors[theme.errHighlight]!@#&			end!@#&!@#&			if i == sel then term.setBackgroundColor(bghigh)!@#&			else term.setBackgroundColor(bg) end!@#&			term.setTextColor(colors[theme.textColor])!@#&			for x = -1, 1 do!@#&				term.setCursorPos(3, (i * 4) + x + 4)!@#&				term.write(string.rep(\" \", w - 13))!@#&			end!@#&!@#&			term.setCursorPos(3, i * 4 + 4)!@#&			if i == sel then!@#&				term.setBackgroundColor(bghigh)!@#&				term.write(\" > \")!@#&			else term.write(\" - \") end!@#&			term.write(v .. \" \")!@#&		end!@#&	end!@#&!@#&	local function updateDisplayList(items, loc, len)!@#&		local ret = {}!@#&		for i = 1, len do!@#&			local item = items[i + loc - 1]!@#&			if item then table.insert(ret, item) end!@#&		end!@#&		return ret!@#&	end!@#&!@#&	-- Variables!@#&	local sel = 1!@#&	local loc = 1!@#&	local len = 3!@#&	local disList = updateDisplayList(list, loc, len)!@#&	draw(disList, sel, loc)!@#&!@#&	-- Loop!@#&	while true do!@#&		local e, key, x, y = os.pullEvent()!@#&!@#&		if e == \"mouse_click\" then!@#&			for i, v in ipairs(disList) do!@#&				if x >= 3 and x <= w - 11 and y >= i * 4 + 3 and y <= i * 4 + 5 then return v end!@#&			end!@#&		elseif e == \"key\" and key == 200 then!@#&			if sel > 1 then!@#&				sel = sel - 1!@#&				draw(disList, sel, loc)!@#&			elseif loc > 1 then!@#&				loc = loc - 1!@#&				disList = updateDisplayList(list, loc, len)!@#&				draw(disList, sel, loc)!@#&			end!@#&		elseif e == \"key\" and key == 208 then!@#&			if sel < len then!@#&				sel = sel + 1!@#&				draw(disList, sel, loc)!@#&			elseif loc + len - 1 < #list then!@#&				loc = loc + 1!@#&				disList = updateDisplayList(list, loc, len)!@#&				draw(disList, sel, loc)!@#&			end!@#&		elseif e == \"mouse_scroll\" then!@#&			os.queueEvent(\"key\", key == -1 and 200 or 208)!@#&		elseif e == \"key\" and key == 28 then!@#&			return disList[sel]!@#&		end!@#&	end!@#&end!@#&!@#&function monitorKeyboardShortcuts()!@#&	local ta, tb = nil, nil!@#&	local allowChar = false!@#&	local shiftPressed = false!@#&	while true do!@#&		local event, char = os.pullEvent()!@#&		if event == \"key\" and (char == 42 or char == 52) then!@#&			shiftPressed = true!@#&			tb = os.startTimer(keyboardShortcutTimeout)!@#&		elseif event == \"key\" and (char == 29 or char == 157 or char == 219 or char == 220) then!@#&			allowEditorEvent = false!@#&			allowChar = true!@#&			ta = os.startTimer(keyboardShortcutTimeout)!@#&		elseif event == \"key\" and allowChar then!@#&			local name = nil!@#&			for k, v in pairs(keys) do!@#&				if v == char then!@#&					if shiftPressed then os.queueEvent(\"shortcut\", \"ctrl shift\", k:lower())!@#&					else os.queueEvent(\"shortcut\", \"ctrl\", k:lower()) end!@#&					sleep(0.005)!@#&					allowEditorEvent = true!@#&				end!@#&			end!@#&			if shiftPressed then os.queueEvent(\"shortcut\", \"ctrl shift\", char)!@#&			else os.queueEvent(\"shortcut\", \"ctrl\", char) end!@#&		elseif event == \"timer\" and char == ta then!@#&			allowEditorEvent = true!@#&			allowChar = false!@#&		elseif event == \"timer\" and char == tb then!@#&			shiftPressed = false!@#&		end!@#&	end!@#&end!@#&!@#&!@#&--  -------- Saving and Loading!@#&!@#&local function download(url, path)!@#&	for i = 1, 3 do!@#&		local response = http.get(url)!@#&		if response then!@#&			local data = response.readAll()!@#&			response.close()!@#&			if path then!@#&				local f = io.open(path, \"w\")!@#&				f:write(data)!@#&				f:close()!@#&			end!@#&			return true!@#&		end!@#&	end!@#&!@#&	return false!@#&end!@#&!@#&local function saveFile(path, lines)!@#&	local dir = path:sub(1, path:len() - fs.getName(path):len())!@#&	if not fs.exists(dir) then fs.makeDir(dir) end!@#&	if not fs.isDir(path) and not fs.isReadOnly(path) then!@#&		local a = \"\"!@#&		for _, v in pairs(lines) do a = a .. v .. \"\\n\" end!@#&!@#&		local f = io.open(path, \"w\")!@#&		f:write(a)!@#&		f:close()!@#&		return true!@#&	else return false end!@#&end!@#&!@#&local function loadFile(path)!@#&	if not fs.exists(path) then!@#&		local dir = path:sub(1, path:len() - fs.getName(path):len())!@#&		if not fs.exists(dir) then fs.makeDir(dir) end!@#&		local f = io.open(path, \"w\")!@#&		f:write(\"\")!@#&		f:close()!@#&	end!@#&!@#&	local l = {}!@#&	if fs.exists(path) and not fs.isDir(path) then!@#&		local f = io.open(path, \"r\")!@#&		if f then!@#&			local a = f:read(\"*l\")!@#&			while a do!@#&				table.insert(l, a)!@#&				a = f:read(\"*l\")!@#&			end!@#&			f:close()!@#&		end!@#&	else return nil end!@#&!@#&	if #l < 1 then table.insert(l, \"\") end!@#&	return l!@#&end!@#&!@#&!@#&--  -------- Languages!@#&!@#&languages.lua = {}!@#&languages.brainfuck = {}!@#&languages.none = {}!@#&!@#&--  Lua!@#&!@#&languages.lua.helpTips = {!@#&	\"A function you tried to call doesn't exist.\",!@#&	\"You made a typo.\",!@#&	\"The index of an array is nil.\",!@#&	\"The wrong variable type was passed.\",!@#&	\"A function/variable doesn't exist.\",!@#&	\"You missed an 'end'.\",!@#&	\"You missed a 'then'.\",!@#&	\"You declared a variable incorrectly.\",!@#&	\"One of your variables is mysteriously nil.\"!@#&}!@#&!@#&languages.lua.defaultHelpTips = {!@#&	2, 5!@#&}!@#&!@#&languages.lua.errors = {!@#&	[\"Attempt to call nil.\"] = {1, 2},!@#&	[\"Attempt to index nil.\"] = {3, 2},!@#&	[\".+ expected, got .+\"] = {4, 2, 9},!@#&	[\"'end' expected\"] = {6, 2},!@#&	[\"'then' expected\"] = {7, 2},!@#&	[\"'=' expected\"] = {8, 2}!@#&}!@#&!@#&languages.lua.keywords = {!@#&	[\"and\"] = \"conditional\",!@#&	[\"break\"] = \"conditional\",!@#&	[\"do\"] = \"conditional\",!@#&	[\"else\"] = \"conditional\",!@#&	[\"elseif\"] = \"conditional\",!@#&	[\"end\"] = \"conditional\",!@#&	[\"for\"] = \"conditional\",!@#&	[\"function\"] = \"conditional\",!@#&	[\"if\"] = \"conditional\",!@#&	[\"in\"] = \"conditional\",!@#&	[\"local\"] = \"conditional\",!@#&	[\"not\"] = \"conditional\",!@#&	[\"or\"] = \"conditional\",!@#&	[\"repeat\"] = \"conditional\",!@#&	[\"return\"] = \"conditional\",!@#&	[\"then\"] = \"conditional\",!@#&	[\"until\"] = \"conditional\",!@#&	[\"while\"] = \"conditional\",!@#&!@#&	[\"true\"] = \"constant\",!@#&	[\"false\"] = \"constant\",!@#&	[\"nil\"] = \"constant\",!@#&!@#&	[\"print\"] = \"function\",!@#&	[\"write\"] = \"function\",!@#&	[\"sleep\"] = \"function\",!@#&	[\"pairs\"] = \"function\",!@#&	[\"ipairs\"] = \"function\",!@#&	[\"loadstring\"] = \"function\",!@#&	[\"loadfile\"] = \"function\",!@#&	[\"dofile\"] = \"function\",!@#&	[\"rawset\"] = \"function\",!@#&	[\"rawget\"] = \"function\",!@#&	[\"setfenv\"] = \"function\",!@#&	[\"getfenv\"] = \"function\",!@#&}!@#&!@#&languages.lua.parseError = function(e)!@#&	local ret = {filename = \"unknown\", line = -1, display = \"Unknown!\", err = \"\"}!@#&	if e and e ~= \"\" then!@#&		ret.err = e!@#&		if e:find(\":\") then!@#&			ret.filename = e:sub(1, e:find(\":\") - 1):gsub(\"^%s*(.-)%s*$\", \"%1\")!@#&			-- The \"\" is needed to circumvent a CC bug!@#&			e = (e:sub(e:find(\":\") + 1) .. \"\"):gsub(\"^%s*(.-)%s*$\", \"%1\")!@#&			if e:find(\":\") then!@#&				ret.line = e:sub(1, e:find(\":\") - 1)!@#&				e = e:sub(e:find(\":\") + 2):gsub(\"^%s*(.-)%s*$\", \"%1\") .. \"\"!@#&			end!@#&		end!@#&		ret.display = e:sub(1, 1):upper() .. e:sub(2, -1) .. \".\"!@#&	end!@#&!@#&	return ret!@#&end!@#&!@#&languages.lua.getCompilerErrors = function(code)!@#&	code = \"local function ee65da6af1cb6f63fee9a081246f2fd92b36ef2(...)\\n\\n\" .. code .. \"\\n\\nend\"!@#&	local fn, err = loadstring(code)!@#&	if not err then!@#&		local _, e = pcall(fn)!@#&		if e then err = e end!@#&	end!@#&!@#&	if err then!@#&		local a = err:find(\"]\", 1, true)!@#&		if a then err = \"string\" .. err:sub(a + 1, -1) end!@#&		local ret = languages.lua.parseError(err)!@#&		if tonumber(ret.line) then ret.line = tonumber(ret.line) end!@#&		return ret!@#&	else return languages.lua.parseError(nil) end!@#&end!@#&!@#&languages.lua.run = function(path, ar)!@#&	local fn, err = loadfile(path)!@#&	setfenv(fn, getfenv())!@#&	if not err then!@#&		_, err = pcall(function() fn(unpack(ar)) end)!@#&	end!@#&	return err!@#&end!@#&!@#&!@#&--  Brainfuck!@#&!@#&languages.brainfuck.helpTips = {!@#&	\"Well idk...\",!@#&	\"Isn't this the whole point of the language?\",!@#&	\"Ya know... Not being able to debug it?\",!@#&	\"You made a typo.\"!@#&}!@#&!@#&languages.brainfuck.defaultHelpTips = {!@#&	1, 2, 3!@#&}!@#&!@#&languages.brainfuck.errors = {!@#&	[\"No matching '['\"] = {1, 2, 3, 4}!@#&}!@#&!@#&languages.brainfuck.keywords = {}!@#&!@#&languages.brainfuck.parseError = function(e)!@#&	local ret = {filename = \"unknown\", line = -1, display = \"Unknown!\", err = \"\"}!@#&	if e and e ~= \"\" then!@#&		ret.err = e!@#&		ret.line = e:sub(1, e:find(\":\") - 1)!@#&		e = e:sub(e:find(\":\") + 2):gsub(\"^%s*(.-)%s*$\", \"%1\") .. \"\"!@#&		ret.display = e:sub(1, 1):upper() .. e:sub(2, -1) .. \".\"!@#&	end!@#&!@#&	return ret!@#&end!@#&!@#&languages.brainfuck.mapLoops = function(code)!@#&	-- Map loops!@#&	local loopLocations = {}!@#&	local loc = 1!@#&	local line = 1!@#&	for let in string.gmatch(code, \".\") do!@#&		if let == \"[\" then!@#&			loopLocations[loc] = true!@#&		elseif let == \"]\" then!@#&			local found = false!@#&			for i = loc, 1, -1 do !@#&				if loopLocations[i] == true then!@#&					loopLocations[i] = loc!@#&					found = true!@#&				end!@#&			end!@#&!@#&			if not found then!@#&				return line .. \": No matching '['\"!@#&			end!@#&		end!@#&!@#&		if let == \"\\n\" then line = line + 1 end!@#&		loc = loc + 1!@#&	end!@#&	return loopLocations!@#&end!@#&!@#&languages.brainfuck.getCompilerErrors = function(code)!@#&	local a = languages.brainfuck.mapLoops(code)!@#&	if type(a) == \"string\" then return languages.brainfuck.parseError(a)!@#&	else return languages.brainfuck.parseError(nil) end!@#&end!@#&!@#&languages.brainfuck.run = function(path)!@#&	-- Read from file!@#&	local f = io.open(path, \"r\")!@#&	local content = f:read(\"*a\")!@#&	f:close()!@#&!@#&	-- Define environment!@#&	local dataCells = {}!@#&	local dataPointer = 1!@#&	local instructionPointer = 1!@#&!@#&	-- Map loops!@#&	local loopLocations = languages.brainfuck.mapLoops(content)!@#&	if type(loopLocations) == \"string\" then return loopLocations end!@#&!@#&	-- Execute code!@#&	while true do!@#&		local let = content:sub(instructionPointer, instructionPointer)!@#&!@#&		if let == \">\" then!@#&			dataPointer = dataPointer + 1!@#&			if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end!@#&		elseif let == \"<\" then!@#&			if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end!@#&			dataPointer = dataPointer - 1!@#&			if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end!@#&		elseif let == \"+\" then!@#&			if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end!@#&			dataCells[tostring(dataPointer)] = dataCells[tostring(dataPointer)] + 1!@#&		elseif let == \"-\" then!@#&			if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end!@#&			dataCells[tostring(dataPointer)] = dataCells[tostring(dataPointer)] - 1!@#&		elseif let == \".\" then!@#&			if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end!@#&			if term.getCursorPos() >= w then print(\"\") end!@#&			write(string.char(math.max(1, dataCells[tostring(dataPointer)])))!@#&		elseif let == \",\" then!@#&			if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end!@#&			term.setCursorBlink(true)!@#&			local e, but = os.pullEvent(\"char\")!@#&			term.setCursorBlink(false)!@#&			dataCells[tostring(dataPointer)] = string.byte(but)!@#&			if term.getCursorPos() >= w then print(\"\") end!@#&			write(but)!@#&		elseif let == \"/\" then!@#&			if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end!@#&			if term.getCursorPos() >= w then print(\"\") end!@#&			write(dataCells[tostring(dataPointer)])!@#&		elseif let == \"[\" then!@#&			if dataCells[tostring(dataPointer)] == 0 then!@#&				for k, v in pairs(loopLocations) do!@#&					if k == instructionPointer then instructionPointer = v end!@#&				end!@#&			end!@#&		elseif let == \"]\" then!@#&			for k, v in pairs(loopLocations) do!@#&				if v == instructionPointer then instructionPointer = k - 1 end!@#&			end!@#&		end!@#&!@#&		instructionPointer = instructionPointer + 1!@#&		if instructionPointer > content:len() then print(\"\") break end!@#&	end!@#&end!@#&!@#&--  None!@#&!@#&languages.none.helpTips = {}!@#&languages.none.defaultHelpTips = {}!@#&languages.none.errors = {}!@#&languages.none.keywords = {}!@#&!@#&languages.none.parseError = function(err)!@#&	return {filename = \"\", line = -1, display = \"\", err = \"\"}!@#&end!@#&!@#&languages.none.getCompilerErrors = function(code)!@#&	return languages.none.parseError(nil)!@#&end!@#&!@#&languages.none.run = function(path) end!@#&!@#&!@#&-- Load language!@#&curLanguage = languages.lua!@#&!@#&!@#&--  -------- Run GUI!@#&!@#&local function viewErrorHelp(e)!@#&	title(\"LuaIDE - Error Help\")!@#&!@#&	local tips = nil!@#&	for k, v in pairs(curLanguage.errors) do!@#&		if e.display:find(k) then tips = v break end!@#&	end!@#&!@#&	term.setBackgroundColor(colors[theme.err])!@#&	for i = 6, 8 do!@#&		term.setCursorPos(5, i)!@#&		term.write(string.rep(\" \", 35))!@#&	end!@#&!@#&	term.setBackgroundColor(colors[theme.prompt])!@#&	for i = 10, 18 do!@#&		term.setCursorPos(5, i)!@#&		term.write(string.rep(\" \", 46))!@#&	end!@#&!@#&	if tips then!@#&		term.setBackgroundColor(colors[theme.err])!@#&		term.setCursorPos(6, 7)!@#&		term.write(\"Error Help\")!@#&!@#&		term.setBackgroundColor(colors[theme.prompt])!@#&		for i, v in ipairs(tips) do!@#&			term.setCursorPos(7, i + 10)!@#&			term.write(\"- \" .. curLanguage.helpTips[v])!@#&		end!@#&	else!@#&		term.setBackgroundColor(colors[theme.err])!@#&		term.setCursorPos(6, 7)!@#&		term.write(\"No Error Tips Available!\")!@#&!@#&		term.setBackgroundColor(colors[theme.prompt])!@#&		term.setCursorPos(6, 11)!@#&		term.write(\"There are no error tips available, but\")!@#&		term.setCursorPos(6, 12)!@#&		term.write(\"you could see if it was any of these:\")!@#&!@#&		for i, v in ipairs(curLanguage.defaultHelpTips) do!@#&			term.setCursorPos(7, i + 12)!@#&			term.write(\"- \" .. curLanguage.helpTips[v])!@#&		end!@#&	end!@#&!@#&	prompt({{\"Back\", w - 8, 7}}, \"horizontal\")!@#&end!@#&!@#&local function run(path, lines, useArgs)!@#&	local ar = {}!@#&	if useArgs then!@#&		title(\"LuaIDE - Run \" .. fs.getName(path))!@#&		local s = centerRead(w - 13, fs.getName(path) .. \" \")!@#&		for m in string.gmatch(s, \"[^ \\t]+\") do ar[#ar + 1] = m:gsub(\"^%s*(.-)%s*$\", \"%1\") end!@#&	end!@#&	!@#&	saveFile(path, lines)!@#&	term.setCursorBlink(false)!@#&	term.setBackgroundColor(colors.black)!@#&	term.setTextColor(colors.white)!@#&	term.clear()!@#&	term.setCursorPos(1, 1)!@#&	local err = curLanguage.run(path, ar)!@#&!@#&	term.setBackgroundColor(colors.black)!@#&	print(\"\\n\")!@#&	if err then!@#&		if isAdvanced() then term.setTextColor(colors.red) end!@#&		centerPrint(\"The program has crashed!\")!@#&	end!@#&	term.setTextColor(colors.white)!@#&	centerPrint(\"Press any key to return to LuaIDE...\")!@#&	while true do!@#&		local e = os.pullEvent()!@#&		if e == \"key\" then break end!@#&	end!@#&!@#&	-- To prevent key from showing up in editor!@#&	os.queueEvent(event_distract)!@#&	os.pullEvent()!@#&!@#&	if err then!@#&		if curLanguage == languages.lua and err:find(\"]\") then!@#&			err = fs.getName(path) .. err:sub(err:find(\"]\", 1, true) + 1, -1)!@#&		end!@#&!@#&		while true do!@#&			title(\"LuaIDE - Error!\")!@#&!@#&			term.setBackgroundColor(colors[theme.err])!@#&			for i = 6, 8 do!@#&				term.setCursorPos(3, i)!@#&				term.write(string.rep(\" \", w - 5))!@#&			end!@#&			term.setCursorPos(4, 7)!@#&			term.write(\"The program has crashed!\")!@#&!@#&			term.setBackgroundColor(colors[theme.prompt])!@#&			for i = 10, 14 do!@#&				term.setCursorPos(3, i)!@#&				term.write(string.rep(\" \", w - 5))!@#&			end!@#&!@#&			local formattedErr = curLanguage.parseError(err)!@#&			term.setCursorPos(4, 11)!@#&			term.write(\"Line: \" .. formattedErr.line)!@#&			term.setCursorPos(4, 12)!@#&			term.write(\"Error:\")!@#&			term.setCursorPos(5, 13)!@#&!@#&			local a = formattedErr.display!@#&			local b = nil!@#&			if a:len() > w - 8 then!@#&				for i = a:len(), 1, -1 do!@#&					if a:sub(i, i) == \" \" then!@#&						b = a:sub(i + 1, -1)!@#&						a = a:sub(1, i)!@#&						break!@#&					end!@#&				end!@#&			end!@#&!@#&			term.write(a)!@#&			if b then!@#&				term.setCursorPos(5, 14)!@#&				term.write(b)!@#&			end!@#&			!@#&			local opt = prompt({{\"Error Help\", w/2 - 15, 17}, {\"Go To Line\", w/2 + 2, 17}},!@#&				\"horizontal\")!@#&			if opt == \"Error Help\" then!@#&				viewErrorHelp(formattedErr)!@#&			elseif opt == \"Go To Line\" then!@#&				-- To prevent key from showing up in editor!@#&				os.queueEvent(event_distract)!@#&				os.pullEvent()!@#&!@#&				return \"go to\", tonumber(formattedErr.line)!@#&			end!@#&		end!@#&	end!@#&end!@#&!@#&!@#&--  -------- Functions!@#&!@#&local function goto()!@#&	term.setBackgroundColor(colors[theme.backgroundHighlight])!@#&	term.setCursorPos(2, 1)!@#&	term.clearLine()!@#&	term.write(\"Line: \")!@#&	local line = modRead({visibleLength = w - 2})!@#&!@#&	local num = tonumber(line)!@#&	if num and num > 0 then return num!@#&	else!@#&		term.setCursorPos(2, 1)!@#&		term.clearLine()!@#&		term.write(\"Not a line number!\")!@#&		sleep(1.6)!@#&		return nil!@#&	end!@#&end!@#&!@#&local function setsyntax()!@#&	local opts = {!@#&		\"[Lua]   Brainfuck    None \",!@#&		\" Lua   [Brainfuck]   None \",!@#&		\" Lua    Brainfuck   [None]\"!@#&	}!@#&	local sel = 1!@#&!@#&	term.setCursorBlink(false)!@#&	term.setBackgroundColor(colors[theme.backgroundHighlight])!@#&	term.setCursorPos(2, 1)!@#&	term.clearLine()!@#&	term.write(opts[sel])!@#&	while true do!@#&		local e, but, x, y = os.pullEvent(\"key\")!@#&		if but == 203 then!@#&			sel = math.max(1, sel - 1)!@#&			term.setCursorPos(2, 1)!@#&			term.clearLine()!@#&			term.write(opts[sel])!@#&		elseif but == 205 then!@#&			sel = math.min(#opts, sel + 1)!@#&			term.setCursorPos(2, 1)!@#&			term.clearLine()!@#&			term.write(opts[sel])!@#&		elseif but == 28 then!@#&			if sel == 1 then curLanguage = languages.lua!@#&			elseif sel == 2 then curLanguage = languages.brainfuck!@#&			elseif sel == 3 then curLanguage = languages.none end!@#&			term.setCursorBlink(true)!@#&			return!@#&		end!@#&	end!@#&end!@#&!@#&!@#&--  -------- Re-Indenting!@#&!@#&local tabWidth = 2!@#&!@#&local comments = {}!@#&local strings = {}!@#&!@#&local increment = {!@#&	\"if%s+.+%s+then%s*$\",!@#&	\"for%s+.+%s+do%s*$\",!@#&	\"while%s+.+%s+do%s*$\",!@#&	\"repeat%s*$\",!@#&	\"function%s+[a-zA-Z_0-9]\\(.*\\)%s*$\"!@#&}!@#&!@#&local decrement = {!@#&	\"end\",!@#&	\"until%s+.+\"!@#&}!@#&!@#&local special = {!@#&	\"else%s*$\",!@#&	\"elseif%s+.+%s+then%s*$\"!@#&}!@#&!@#&local function check(func)!@#&	for _, v in pairs(func) do!@#&		local cLineStart = v[\"lineStart\"]!@#&		local cLineEnd = v[\"lineEnd\"]!@#&		local cCharStart = v[\"charStart\"]!@#&		local cCharEnd = v[\"charEnd\"]!@#&!@#&		if line >= cLineStart and line <= cLineEnd then!@#&			if line == cLineStart then return cCharStart < charNumb!@#&			elseif line == cLineEnd then return cCharEnd > charNumb!@#&			else return true end!@#&		end!@#&	end!@#&end!@#&!@#&local function isIn(line, loc)!@#&	if check(comments) then return true end!@#&	if check(strings) then return true end!@#&	return false!@#&end!@#&!@#&local function setComment(ls, le, cs, ce)!@#&	comments[#comments + 1] = {}!@#&	comments[#comments].lineStart = ls!@#&	comments[#comments].lineEnd = le!@#&	comments[#comments].charStart = cs!@#&	comments[#comments].charEnd = ce!@#&end!@#&!@#&local function setString(ls, le, cs, ce)!@#&	strings[#strings + 1] = {}!@#&	strings[#strings].lineStart = ls!@#&	strings[#strings].lineEnd = le!@#&	strings[#strings].charStart = cs!@#&	strings[#strings].charEnd = ce!@#&end!@#&!@#&local function map(contents)!@#&	local inCom = false!@#&	local inStr = false!@#&!@#&	for i = 1, #contents do!@#&		if content[i]:find(\"%-%-%[%[\") and not inStr and not inCom then!@#&			local cStart = content[i]:find(\"%-%-%[%[\")!@#&			setComment(i, nil, cStart, nil)!@#&			inCom = true!@#&		elseif content[i]:find(\"%-%-%[=%[\") and not inStr and not inCom then!@#&			local cStart = content[i]:find(\"%-%-%[=%[\")!@#&			setComment(i, nil, cStart, nil)!@#&			inCom = true!@#&		elseif content[i]:find(\"%[%[\") and not inStr and not inCom then!@#&			local cStart = content[i]:find(\"%[%[\")!@#&			setString(i, nil, cStart, nil)!@#&			inStr = true!@#&		elseif content[i]:find(\"%[=%[\") and not inStr and not inCom then!@#&			local cStart = content[i]:find(\"%[=%[\")!@#&			setString(i, nil, cStart, nil)!@#&			inStr = true!@#&		end!@#&!@#&		if content[i]:find(\"%]%]\") and inStr and not inCom then!@#&			local cStart, cEnd = content[i]:find(\"%]%]\")!@#&			strings[#strings].lineEnd = i!@#&			strings[#strings].charEnd = cEnd!@#&			inStr = false!@#&		elseif content[i]:find(\"%]=%]\") and inStr and not inCom then!@#&			local cStart, cEnd = content[i]:find(\"%]=%]\")!@#&			strings[#strings].lineEnd = i!@#&			strings[#strings].charEnd = cEnd!@#&			inStr = false!@#&		end!@#&!@#&		if content[i]:find(\"%]%]\") and not inStr and inCom then!@#&			local cStart, cEnd = content[i]:find(\"%]%]\")!@#&			comments[#comments].lineEnd = i!@#&			comments[#comments].charEnd = cEnd!@#&			inCom = false!@#&		elseif content[i]:find(\"%]=%]\") and not inStr and inCom then!@#&			local cStart, cEnd = content[i]:find(\"%]=%]\")!@#&			comments[#comments].lineEnd = i!@#&			comments[#comments].charEnd = cEnd!@#&			inCom = false!@#&		end!@#&!@#&		if content[i]:find(\"%-%-\") and not inStr and not inCom then!@#&			local cStart = content[i]:find(\"%-%-\")!@#&			setComment(i, i, cStart, -1)!@#&		elseif content[i]:find(\"'\") and not inStr and not inCom then!@#&			local cStart, cEnd = content[i]:find(\"'\")!@#&			local nextChar = content[i]:sub(cEnd + 1, string.len(content[i]))!@#&			local _, cEnd = nextChar:find(\"'\")!@#&			setString(i, i, cStart, cEnd)!@#&		elseif content[i]:find('\"') and not inStr and not inCom then!@#&			local cStart, cEnd = content[i]:find('\"')!@#&			local nextChar = content[i]:sub(cEnd + 1, string.len(content[i]))!@#&			local _, cEnd = nextChar:find('\"')!@#&			setString(i, i, cStart, cEnd)!@#&		end!@#&	end!@#&end!@#&!@#&local function reindent(contents)!@#&	local err = nil!@#&	if curLanguage ~= languages.lua then!@#&		err = \"Cannot indent languages other than Lua!\"!@#&	elseif curLanguage.getCompilerErrors(table.concat(contents, \"\\n\")).line ~= -1 then!@#&		err = \"Cannot indent a program with errors!\"!@#&	end!@#&!@#&	if err then!@#&		term.setCursorBlink(false)!@#&		term.setCursorPos(2, 1)!@#&		term.setBackgroundColor(colors[theme.backgroundHighlight])!@#&		term.clearLine()!@#&		term.write(err)!@#&		sleep(1.6)!@#&		return contents!@#&	end!@#&!@#&	local new = {}!@#&	local level = 0!@#&	for k, v in pairs(contents) do!@#&		local incrLevel = false!@#&		local foundIncr = false!@#&		for _, incr in pairs(increment) do!@#&			if v:find(incr) and not isIn(k, v:find(incr)) then!@#&				incrLevel = true!@#&			end!@#&			if v:find(incr:sub(1, -2)) and not isIn(k, v:find(incr)) then!@#&				foundIncr = true!@#&			end!@#&		end!@#&!@#&		local decrLevel = false!@#&		if not incrLevel then!@#&			for _, decr in pairs(decrement) do!@#&				if v:find(decr) and not isIn(k, v:find(decr)) and not foundIncr then!@#&					level = math.max(0, level - 1)!@#&					decrLevel = true!@#&				end!@#&			end!@#&		end!@#&!@#&		if not decrLevel then!@#&			for _, sp in pairs(special) do!@#&				if v:find(sp) and not isIn(k, v:find(sp)) then!@#&					incrLevel = true!@#&					level = math.max(0, level - 1)!@#&				end!@#&			end!@#&		end!@#&!@#&		new[k] = string.rep(\" \", level * tabWidth) .. v!@#&		if incrLevel then level = level + 1 end!@#&	end!@#&!@#&	return new!@#&end!@#&!@#&!@#&--  -------- Menu!@#&!@#&local menu = {!@#&	[1] = {\"File\",!@#&--		\"About\",!@#&--		\"Settings\",!@#&--		\"\",!@#&		\"New File  ^+N\",!@#&		\"Open File ^+O\",!@#&		\"Save File ^+S\",!@#&		\"Close     ^+W\",!@#&		\"Print     ^+P\",!@#&		\"Quit      ^+Q\"!@#&	}, [2] = {\"Edit\",!@#&		\"Cut Line   ^+X\",!@#&		\"Copy Line  ^+C\",!@#&		\"Paste Line ^+V\",!@#&		\"Delete Line\",!@#&		\"Clear Line\"!@#&	}, [3] = {\"Functions\",!@#&		\"Go To Line    ^+G\",!@#&		\"Re-Indent     ^+I\",!@#&		\"Set Syntax    ^+E\",!@#&		\"Start of Line ^+<\",!@#&		\"End of Line   ^+>\"!@#&	}, [4] = {\"Run\",!@#&		\"Run Program       ^+R\",!@#&		\"Run w/ Args ^+Shift+R\"!@#&	}!@#&}!@#&!@#&local shortcuts = {!@#&	-- File!@#&	[\"ctrl n\"] = \"New File  ^+N\",!@#&	[\"ctrl o\"] = \"Open File ^+O\",!@#&	[\"ctrl s\"] = \"Save File ^+S\",!@#&	[\"ctrl w\"] = \"Close     ^+W\",!@#&	[\"ctrl p\"] = \"Print     ^+P\",!@#&	[\"ctrl q\"] = \"Quit      ^+Q\",!@#&!@#&	-- Edit!@#&	[\"ctrl x\"] = \"Cut Line   ^+X\",!@#&	[\"ctrl c\"] = \"Copy Line  ^+C\",!@#&	[\"ctrl v\"] = \"Paste Line ^+V\",!@#&!@#&	-- Functions!@#&	[\"ctrl g\"] = \"Go To Line    ^+G\",!@#&	[\"ctrl i\"] = \"Re-Indent     ^+I\",!@#&	[\"ctrl e\"] = \"Set Syntax    ^+E\",!@#&	[\"ctrl 203\"] = \"Start of Line ^+<\",!@#&	[\"ctrl 205\"] = \"End of Line   ^+>\",!@#&!@#&	-- Run!@#&	[\"ctrl r\"] = \"Run Program       ^+R\",!@#&	[\"ctrl shift r\"] = \"Run w/ Args ^+Shift+R\"!@#&}!@#&!@#&local menuFunctions = {!@#&	-- File!@#&--	[\"About\"] = function() end,!@#&--	[\"Settings\"] = function() end,!@#&	[\"New File  ^+N\"] = function(path, lines) saveFile(path, lines) return \"new\" end,!@#&	[\"Open File ^+O\"] = function(path, lines) saveFile(path, lines) return \"open\" end,!@#&	[\"Save File ^+S\"] = function(path, lines) saveFile(path, lines) end,!@#&	[\"Close     ^+W\"] = function(path, lines) saveFile(path, lines) return \"menu\" end,!@#&	[\"Print     ^+P\"] = function(path, lines) saveFile(path, lines) return nil end,!@#&	[\"Quit      ^+Q\"] = function(path, lines) saveFile(path, lines) return \"exit\" end,!@#&!@#&	-- Edit!@#&	[\"Cut Line   ^+X\"] = function(path, lines, y)!@#&		clipboard = lines[y] table.remove(lines, y) return nil, lines end,!@#&	[\"Copy Line  ^+C\"] = function(path, lines, y) clipboard = lines[y] end,!@#&	[\"Paste Line ^+V\"] = function(path, lines, y)!@#&		if clipboard then table.insert(lines, y, clipboard) end return nil, lines end,!@#&	[\"Delete Line\"] = function(path, lines, y) table.remove(lines, y) return nil, lines end,!@#&	[\"Clear Line\"] = function(path, lines, y) lines[y] = \"\" return nil, lines, \"cursor\" end,!@#&!@#&	-- Functions!@#&	[\"Go To Line    ^+G\"] = function() return nil, \"go to\", goto() end,!@#&	[\"Re-Indent     ^+I\"] = function(path, lines)!@#&		local a = reindent(lines) saveFile(path, lines) return nil, a!@#&	end,!@#&	[\"Set Syntax    ^+E\"] = function(path, lines)!@#&		setsyntax()!@#&		if curLanguage == languages.brainfuck and lines[1] ~= \"-- Syntax: Brainfuck\" then!@#&			table.insert(lines, 1, \"-- Syntax: Brainfuck\")!@#&			return nil, lines!@#&		end!@#&	end,!@#&	[\"Start of Line ^+<\"] = function() os.queueEvent(\"key\", 199) end,!@#&	[\"End of Line   ^+>\"] = function() os.queueEvent(\"key\", 207) end,!@#&!@#&	-- Run!@#&	[\"Run Program       ^+R\"] = function(path, lines)!@#&		saveFile(path, lines)!@#&		return nil, run(path, lines, false)!@#&	end,!@#&	[\"Run w/ Args ^+Shift+R\"] = function(path, lines)!@#&		saveFile(path, lines)!@#&		return nil, run(path, lines, true)!@#&	end,!@#&}!@#&!@#&local function drawMenu(open)!@#&	term.setCursorPos(1, 1)!@#&	term.setTextColor(colors[theme.textColor])!@#&	term.setBackgroundColor(colors[theme.backgroundHighlight])!@#&	term.clearLine()!@#&	local curX = 0!@#&	for _, v in pairs(menu) do!@#&		term.setCursorPos(3 + curX, 1)!@#&		term.write(v[1])!@#&		curX = curX + v[1]:len() + 3!@#&	end!@#&!@#&	if open then!@#&		local it = {}!@#&		local x = 1!@#&		for _, v in pairs(menu) do!@#&			if open == v[1] then!@#&				it = v!@#&				break!@#&			end!@#&			x = x + v[1]:len() + 3!@#&		end!@#&		x = x + 1!@#&!@#&		local items = {}!@#&		for i = 2, #it do!@#&			table.insert(items, it[i])!@#&		end!@#&!@#&		local len = 1!@#&		for _, v in pairs(items) do if v:len() + 2 > len then len = v:len() + 2 end end!@#&!@#&		for i, v in ipairs(items) do!@#&			term.setCursorPos(x, i + 1)!@#&			term.write(string.rep(\" \", len))!@#&			term.setCursorPos(x + 1, i + 1)!@#&			term.write(v)!@#&		end!@#&		term.setCursorPos(x, #items + 2)!@#&		term.write(string.rep(\" \", len))!@#&		return items, len!@#&	end!@#&end!@#&!@#&local function triggerMenu(cx, cy)!@#&	-- Determine clicked menu!@#&	local curX = 0!@#&	local open = nil!@#&	for _, v in pairs(menu) do!@#&		if cx >= curX + 3 and cx <= curX + v[1]:len() + 2 then!@#&			open = v[1]!@#&			break!@#&		end!@#&		curX = curX + v[1]:len() + 3!@#&	end!@#&	local menux = curX + 2!@#&	if not open then return false end!@#&!@#&	-- Flash menu item!@#&	term.setCursorBlink(false)!@#&	term.setCursorPos(menux, 1)!@#&	term.setBackgroundColor(colors[theme.background])!@#&	term.write(string.rep(\" \", open:len() + 2))!@#&	term.setCursorPos(menux + 1, 1)!@#&	term.write(open)!@#&	sleep(0.1)!@#&	local items, len = drawMenu(open)!@#&!@#&	local ret = true!@#&!@#&	-- Pull events on menu!@#&	local ox, oy = term.getCursorPos()!@#&	while type(ret) ~= \"string\" do!@#&		local e, but, x, y = os.pullEvent()!@#&		if e == \"mouse_click\" then!@#&			-- If clicked outside menu!@#&			if x < menux - 1 or x > menux + len - 1 then break!@#&			elseif y > #items + 2 then break!@#&			elseif y == 1 then break end!@#&!@#&			for i, v in ipairs(items) do!@#&				if y == i + 1 and x >= menux and x <= menux + len - 2 then!@#&					-- Flash when clicked!@#&					term.setCursorPos(menux, y)!@#&					term.setBackgroundColor(colors[theme.background])!@#&					term.write(string.rep(\" \", len))!@#&					term.setCursorPos(menux + 1, y)!@#&					term.write(v)!@#&					sleep(0.1)!@#&					drawMenu(open)!@#&!@#&					-- Return item!@#&					ret = v!@#&					break!@#&				end!@#&			end!@#&		end!@#&	end!@#&!@#&	term.setCursorPos(ox, oy)!@#&	term.setCursorBlink(true)!@#&	return ret!@#&end!@#&!@#&!@#&--  -------- Editing!@#&!@#&local standardsCompletions = {!@#&	\"if%s+.+%s+then%s*$\",!@#&	\"for%s+.+%s+do%s*$\",!@#&	\"while%s+.+%s+do%s*$\",!@#&	\"repeat%s*$\",!@#&	\"function%s+[a-zA-Z_0-9]?\\(.*\\)%s*$\",!@#&	\"=%s*function%s*\\(.*\\)%s*$\",!@#&	\"else%s*$\",!@#&	\"elseif%s+.+%s+then%s*$\"!@#&}!@#&!@#&local liveCompletions = {!@#&	[\"(\"] = \")\",!@#&	[\"{\"] = \"}\",!@#&	[\"[\"] = \"]\",!@#&	[\"\\\"\"] = \"\\\"\",!@#&	[\"'\"] = \"'\",!@#&}!@#&!@#&local x, y = 0, 0!@#&local edw, edh = 0, h - 1!@#&local offx, offy = 0, 1!@#&local scrollx, scrolly = 0, 0!@#&local lines = {}!@#&local liveErr = curLanguage.parseError(nil)!@#&local displayCode = true!@#&local lastEventClock = os.clock()!@#&!@#&local function attemptToHighlight(line, regex, col)!@#&	local match = string.match(line, regex)!@#&	if match then!@#&		if type(col) == \"number\" then term.setTextColor(col)!@#&		elseif type(col) == \"function\" then term.setTextColor(col(match)) end!@#&		term.write(match)!@#&		term.setTextColor(colors[theme.textColor])!@#&		return line:sub(match:len() + 1, -1)!@#&	end!@#&	return nil!@#&end!@#&!@#&local function writeHighlighted(line)!@#&	if curLanguage == languages.lua then!@#&		while line:len() > 0 do	!@#&			line = attemptToHighlight(line, \"^%-%-%[%[.-%]%]\", colors[theme.comment]) or!@#&				attemptToHighlight(line, \"^%-%-.*\", colors[theme.comment]) or!@#&				attemptToHighlight(line, \"^\\\".*[^\\\\]\\\"\", colors[theme.string]) or!@#&				attemptToHighlight(line, \"^\\'.*[^\\\\]\\'\", colors[theme.string]) or!@#&				attemptToHighlight(line, \"^%[%[.-%]%]\", colors[theme.string]) or!@#&				attemptToHighlight(line, \"^[%w_]+\", function(match)!@#&					if curLanguage.keywords[match] then!@#&						return colors[theme[curLanguage.keywords[match]]]!@#&					end!@#&					return colors[theme.textColor]!@#&				end) or!@#&				attemptToHighlight(line, \"^[^%w_]\", colors[theme.textColor])!@#&		end!@#&	else term.write(line) end!@#&end!@#&!@#&local function draw()!@#&	-- Menu!@#&	term.setTextColor(colors[theme.textColor])!@#&	term.setBackgroundColor(colors[theme.editorBackground])!@#&	term.clear()!@#&	drawMenu()!@#&!@#&	-- Line numbers!@#&	offx, offy = tostring(#lines):len() + 1, 1!@#&	edw, edh = w - offx, h - 1!@#&!@#&	-- Draw text!@#&	for i = 1, edh do!@#&		local a = lines[scrolly + i]!@#&		if a then!@#&			local ln = string.rep(\" \", offx - 1 - tostring(scrolly + i):len()) .. tostring(scrolly + i) !@#&			local l = a:sub(scrollx + 1, edw + scrollx + 1)!@#&			ln = ln .. \":\"!@#&!@#&			if liveErr.line == scrolly + i then ln = string.rep(\" \", offx - 2) .. \"!:\" end!@#&!@#&			term.setCursorPos(1, i + offy)!@#&			term.setBackgroundColor(colors[theme.editorBackground])!@#&			if scrolly + i == y then!@#&				if scrolly + i == liveErr.line and os.clock() - lastEventClock > 3 then!@#&					term.setBackgroundColor(colors[theme.editorErrorHighlight])!@#&				else term.setBackgroundColor(colors[theme.editorLineHightlight]) end!@#&				term.clearLine()!@#&			elseif scrolly + i == liveErr.line then!@#&				term.setBackgroundColor(colors[theme.editorError])!@#&				term.clearLine()!@#&			end!@#&!@#&			term.setCursorPos(1 - scrollx + offx, i + offy)!@#&			if scrolly + i == y then!@#&				if scrolly + i == liveErr.line and os.clock() - lastEventClock > 3 then!@#&					term.setBackgroundColor(colors[theme.editorErrorHighlight])!@#&				else term.setBackgroundColor(colors[theme.editorLineHightlight]) end!@#&			elseif scrolly + i == liveErr.line then term.setBackgroundColor(colors[theme.editorError])!@#&			else term.setBackgroundColor(colors[theme.editorBackground]) end!@#&			if scrolly + i == liveErr.line then!@#&				if displayCode then term.write(a)!@#&				else term.write(liveErr.display) end!@#&			else writeHighlighted(a) end!@#&!@#&			term.setCursorPos(1, i + offy)!@#&			if scrolly + i == y then!@#&				if scrolly + i == liveErr.line and os.clock() - lastEventClock > 3 then!@#&					term.setBackgroundColor(colors[theme.editorError])!@#&				else term.setBackgroundColor(colors[theme.editorLineNumbersHighlight]) end!@#&			elseif scrolly + i == liveErr.line then!@#&				term.setBackgroundColor(colors[theme.editorErrorHighlight])!@#&			else term.setBackgroundColor(colors[theme.editorLineNumbers]) end!@#&			term.write(ln)!@#&		end!@#&	end!@#&	term.setCursorPos(x - scrollx + offx, y - scrolly + offy)!@#&end!@#&!@#&local function drawLine(...)!@#&	local ls = {...}!@#&	offx = tostring(#lines):len() + 1!@#&	for _, ly in pairs(ls) do!@#&		local a = lines[ly]!@#&		if a then!@#&			local ln = string.rep(\" \", offx - 1 - tostring(ly):len()) .. tostring(ly) !@#&			local l = a:sub(scrollx + 1, edw + scrollx + 1)!@#&			ln = ln .. \":\"!@#&!@#&			if liveErr.line == ly then ln = string.rep(\" \", offx - 2) .. \"!:\" end!@#&!@#&			term.setCursorPos(1, (ly - scrolly) + offy)!@#&			term.setBackgroundColor(colors[theme.editorBackground])!@#&			if ly == y then!@#&				if ly == liveErr.line and os.clock() - lastEventClock > 3 then!@#&					term.setBackgroundColor(colors[theme.editorErrorHighlight])!@#&				else term.setBackgroundColor(colors[theme.editorLineHightlight]) end!@#&			elseif ly == liveErr.line then!@#&				term.setBackgroundColor(colors[theme.editorError])!@#&			end!@#&			term.clearLine()!@#&!@#&			term.setCursorPos(1 - scrollx + offx, (ly - scrolly) + offy)!@#&			if ly == y then!@#&				if ly == liveErr.line and os.clock() - lastEventClock > 3 then!@#&					term.setBackgroundColor(colors[theme.editorErrorHighlight])!@#&				else term.setBackgroundColor(colors[theme.editorLineHightlight]) end!@#&			elseif ly == liveErr.line then term.setBackgroundColor(colors[theme.editorError])!@#&			else term.setBackgroundColor(colors[theme.editorBackground]) end!@#&			if ly == liveErr.line then!@#&				if displayCode then term.write(a)!@#&				else term.write(liveErr.display) end!@#&			else writeHighlighted(a) end!@#&!@#&			term.setCursorPos(1, (ly - scrolly) + offy)!@#&			if ly == y then!@#&				if ly == liveErr.line and os.clock() - lastEventClock > 3 then!@#&					term.setBackgroundColor(colors[theme.editorError])!@#&				else term.setBackgroundColor(colors[theme.editorLineNumbersHighlight]) end!@#&			elseif ly == liveErr.line then!@#&				term.setBackgroundColor(colors[theme.editorErrorHighlight])!@#&			else term.setBackgroundColor(colors[theme.editorLineNumbers]) end!@#&			term.write(ln)!@#&		end!@#&	end!@#&	term.setCursorPos(x - scrollx + offx, y - scrolly + offy)!@#&end!@#&!@#&local function cursorLoc(x, y, force)!@#&	local sx, sy = x - scrollx, y - scrolly!@#&	local redraw = false!@#&	if sx < 1 then!@#&		scrollx = x - 1!@#&		sx = 1!@#&		redraw = true!@#&	elseif sx > edw then!@#&		scrollx = x - edw!@#&		sx = edw!@#&		redraw = true!@#&	end if sy < 1 then!@#&		scrolly = y - 1!@#&		sy = 1!@#&		redraw = true!@#&	elseif sy > edh then!@#&		scrolly = y - edh!@#&		sy = edh!@#&		redraw = true!@#&	end if redraw or force then draw() end!@#&	term.setCursorPos(sx + offx, sy + offy)!@#&end!@#&!@#&local function executeMenuItem(a, path)!@#&	if type(a) == \"string\" and menuFunctions[a] then!@#&		local opt, nl, gtln = menuFunctions[a](path, lines, y)!@#&		if type(opt) == \"string\" then term.setCursorBlink(false) return opt end!@#&		if type(nl) == \"table\" then!@#&			if #lines < 1 then table.insert(lines, \"\") end!@#&			y = math.min(y, #lines)!@#&			x = math.min(x, lines[y]:len() + 1)!@#&			lines = nl!@#&		elseif type(nl) == \"string\" then!@#&			if nl == \"go to\" and gtln then!@#&				x, y = 1, math.min(#lines, gtln)!@#&				cursorLoc(x, y)!@#&			end!@#&		end!@#&	end!@#&	term.setCursorBlink(true)!@#&	draw()!@#&	term.setCursorPos(x - scrollx + offx, y - scrolly + offy)!@#&end!@#&!@#&local function edit(path)!@#&	-- Variables!@#&	x, y = 1, 1!@#&	offx, offy = 0, 1!@#&	scrollx, scrolly = 0, 0!@#&	lines = loadFile(path)!@#&	if not lines then return \"menu\" end!@#&!@#&	-- Enable brainfuck!@#&	if lines[1] == \"-- Syntax: Brainfuck\" then!@#&		curLanguage = languages.brainfuck!@#&	end!@#&!@#&	-- Clocks!@#&	local autosaveClock = os.clock()!@#&	local scrollClock = os.clock() -- To prevent redraw flicker!@#&	local liveErrorClock = os.clock()!@#&	local hasScrolled = false!@#&!@#&	-- Draw!@#&	draw()!@#&	term.setCursorPos(x + offx, y + offy)!@#&	term.setCursorBlink(true)!@#&	!@#&	-- Main loop!@#&	local tid = os.startTimer(3)!@#&	while true do!@#&		local e, key, cx, cy = os.pullEvent()!@#&		if e == \"key\" and allowEditorEvent then!@#&			if key == 200 and y > 1 then!@#&				-- Up!@#&				x, y = math.min(x, lines[y - 1]:len() + 1), y - 1!@#&				drawLine(y, y + 1)!@#&				cursorLoc(x, y)!@#&			elseif key == 208 and y < #lines then!@#&				-- Down!@#&				x, y = math.min(x, lines[y + 1]:len() + 1), y + 1!@#&				drawLine(y, y - 1)!@#&				cursorLoc(x, y)!@#&			elseif key == 203 and x > 1 then!@#&				-- Left!@#&				x = x - 1!@#&				local force = false!@#&				if y - scrolly + offy < offy + 1 then force = true end!@#&				cursorLoc(x, y, force)!@#&			elseif key == 205 and x < lines[y]:len() + 1 then!@#&				-- Right!@#&				x = x + 1!@#&				local force = false!@#&				if y - scrolly + offy < offy + 1 then force = true end!@#&				cursorLoc(x, y, force)!@#&			elseif (key == 28 or key == 156) and (displayCode and true or y + scrolly - 1 ==!@#&					liveErr.line) then!@#&				-- Enter!@#&				local f = nil!@#&				for _, v in pairs(standardsCompletions) do!@#&					if lines[y]:find(v) then f = v end!@#&				end!@#&!@#&				local _, spaces = lines[y]:find(\"^[ ]+\")!@#&				if not spaces then spaces = 0 end!@#&				if f then!@#&					table.insert(lines, y + 1, string.rep(\" \", spaces + 2))!@#&					if not f:find(\"else\", 1, true) and not f:find(\"elseif\", 1, true) then!@#&						table.insert(lines, y + 2, string.rep(\" \", spaces) .. !@#&							(f:find(\"repeat\", 1, true) and \"until \" or f:find(\"{\", 1, true) and \"}\" or !@#&							\"end\"))!@#&					end!@#&					x, y = spaces + 3, y + 1!@#&					cursorLoc(x, y, true)!@#&				else!@#&					local oldLine = lines[y]!@#&!@#&					lines[y] = lines[y]:sub(1, x - 1)!@#&					table.insert(lines, y + 1, string.rep(\" \", spaces) .. oldLine:sub(x, -1))!@#&!@#&					x, y = spaces + 1, y + 1!@#&					cursorLoc(x, y, true)!@#&				end!@#&			elseif key == 14 and (displayCode and true or y + scrolly - 1 == liveErr.line) then!@#&				-- Backspace!@#&				if x > 1 then!@#&					local f = false!@#&					for k, v in pairs(liveCompletions) do!@#&						if lines[y]:sub(x - 1, x - 1) == k then f = true end!@#&					end!@#&!@#&					lines[y] = lines[y]:sub(1, x - 2) .. lines[y]:sub(x + (f and 1 or 0), -1)!@#&					drawLine(y)!@#&					x = x - 1!@#&					cursorLoc(x, y)!@#&				elseif y > 1 then!@#&					local prevLen = lines[y - 1]:len() + 1!@#&					lines[y - 1] = lines[y - 1] .. lines[y]!@#&					table.remove(lines, y)!@#&					x, y = prevLen, y - 1!@#&					cursorLoc(x, y, true)!@#&				end!@#&			elseif key == 199 then!@#&				-- Home!@#&				x = 1!@#&				local force = false!@#&				if y - scrolly + offy < offy + 1 then force = true end!@#&				cursorLoc(x, y, force)!@#&			elseif key == 207 then!@#&				-- End!@#&				x = lines[y]:len() + 1!@#&				local force = false!@#&				if y - scrolly + offy < offy + 1 then force = true end!@#&				cursorLoc(x, y, force)!@#&			elseif key == 211 and (displayCode and true or y + scrolly - 1 == liveErr.line) then!@#&				-- Forward Delete!@#&				if x < lines[y]:len() + 1 then!@#&					lines[y] = lines[y]:sub(1, x - 1) .. lines[y]:sub(x + 1)!@#&					local force = false!@#&					if y - scrolly + offy < offy + 1 then force = true end!@#&					drawLine(y)!@#&					cursorLoc(x, y, force)!@#&				elseif y < #lines then!@#&					lines[y] = lines[y] .. lines[y + 1]!@#&					table.remove(lines, y + 1)!@#&					draw()!@#&					cursorLoc(x, y)!@#&				end!@#&			elseif key == 15 and (displayCode and true or y + scrolly - 1 == liveErr.line) then!@#&				-- Tab!@#&				lines[y] = string.rep(\" \", tabWidth) .. lines[y]!@#&				x = x + 2!@#&				local force = false!@#&				if y - scrolly + offy < offy + 1 then force = true end!@#&				drawLine(y)!@#&				cursorLoc(x, y, force)!@#&			elseif key == 201 then!@#&				-- Page up!@#&				y = math.min(math.max(y - edh, 1), #lines)!@#&				x = math.min(lines[y]:len() + 1, x)!@#&				cursorLoc(x, y, true)!@#&			elseif key == 209 then!@#&				-- Page down!@#&				y = math.min(math.max(y + edh, 1), #lines)!@#&				x = math.min(lines[y]:len() + 1, x)!@#&				cursorLoc(x, y, true)!@#&			end!@#&		elseif e == \"char\" and allowEditorEvent and (displayCode and true or !@#&				y + scrolly - 1 == liveErr.line) then!@#&			local shouldIgnore = false!@#&			for k, v in pairs(liveCompletions) do!@#&				if key == v and lines[y]:find(k, 1, true) and lines[y]:sub(x, x) == v then!@#&					shouldIgnore = true!@#&				end!@#&			end!@#&!@#&			local addOne = false!@#&			if not shouldIgnore then!@#&				for k, v in pairs(liveCompletions) do!@#&					if key == k and lines[y]:sub(x, x) ~= k then key = key .. v addOne = true end!@#&				end!@#&				lines[y] = lines[y]:sub(1, x - 1) .. key .. lines[y]:sub(x, -1)!@#&			end!@#&!@#&			x = x + (addOne and 1 or key:len())!@#&			local force = false!@#&			if y - scrolly + offy < offy + 1 then force = true end!@#&			drawLine(y)!@#&			cursorLoc(x, y, force)!@#&		elseif e == \"mouse_click\" and key == 1 then!@#&			if cy > 1 then!@#&				if cx <= offx and cy - offy == liveErr.line - scrolly then!@#&					displayCode = not displayCode!@#&					drawLine(liveErr.line)!@#&				else!@#&					local oldy = y!@#&					y = math.min(math.max(scrolly + cy - offy, 1), #lines)!@#&					x = math.min(math.max(scrollx + cx - offx, 1), lines[y]:len() + 1)!@#&					if oldy ~= y then drawLine(oldy, y) end!@#&					cursorLoc(x, y)!@#&				end!@#&			else!@#&				local a = triggerMenu(cx, cy)!@#&				if a then!@#&					local opt = executeMenuItem(a, path)!@#&					if opt then return opt end!@#&				end!@#&			end!@#&		elseif e == \"shortcut\" then!@#&			local a = shortcuts[key .. \" \" .. cx]!@#&			if a then!@#&				local parent = nil!@#&				local curx = 0!@#&				for i, mv in ipairs(menu) do!@#&					for _, iv in pairs(mv) do!@#&						if iv == a then!@#&							parent = menu[i][1]!@#&							break!@#&						end!@#&					end!@#&					if parent then break end!@#&					curx = curx + mv[1]:len() + 3!@#&				end!@#&				local menux = curx + 2!@#&!@#&				-- Flash menu item!@#&				term.setCursorBlink(false)!@#&				term.setCursorPos(menux, 1)!@#&				term.setBackgroundColor(colors[theme.background])!@#&				term.write(string.rep(\" \", parent:len() + 2))!@#&				term.setCursorPos(menux + 1, 1)!@#&				term.write(parent)!@#&				sleep(0.1)!@#&				drawMenu()!@#&!@#&				-- Execute item!@#&				local opt = executeMenuItem(a, path)!@#&				if opt then return opt end!@#&			end!@#&		elseif e == \"mouse_scroll\" then!@#&			if key == -1 and scrolly > 0 then!@#&				scrolly = scrolly - 1!@#&				if os.clock() - scrollClock > 0.0005 then!@#&					draw()!@#&					term.setCursorPos(x - scrollx + offx, y - scrolly + offy)!@#&				end!@#&				scrollClock = os.clock()!@#&				hasScrolled = true!@#&			elseif key == 1 and scrolly < #lines - edh then!@#&				scrolly = scrolly + 1!@#&				if os.clock() - scrollClock > 0.0005 then!@#&					draw()!@#&					term.setCursorPos(x - scrollx + offx, y - scrolly + offy)!@#&				end!@#&				scrollClock = os.clock()!@#&				hasScrolled = true!@#&			end!@#&		elseif e == \"timer\" and key == tid then!@#&			drawLine(y)!@#&			tid = os.startTimer(3)!@#&		end!@#&!@#&		-- Draw!@#&		if hasScrolled and os.clock() - scrollClock > 0.1 then!@#&			draw()!@#&			term.setCursorPos(x - scrollx + offx, y - scrolly + offy)!@#&			hasScrolled = false!@#&		end!@#&!@#&		-- Autosave!@#&		if os.clock() - autosaveClock > autosaveInterval then!@#&			saveFile(path, lines)!@#&			autosaveClock = os.clock()!@#&		end!@#&!@#&		-- Errors!@#&		if os.clock() - liveErrorClock > 1 then!@#&			local prevLiveErr = liveErr!@#&			liveErr = curLanguage.parseError(nil)!@#&			local code = \"\"!@#&			for _, v in pairs(lines) do code = code .. v .. \"\\n\" end!@#&!@#&			liveErr = curLanguage.getCompilerErrors(code)!@#&			liveErr.line = math.min(liveErr.line - 2, #lines)!@#&			if liveErr ~= prevLiveErr then draw() end!@#&			liveErrorClock = os.clock()!@#&		end!@#&	end!@#&!@#&	return \"menu\"!@#&end!@#&!@#&!@#&--  -------- Open File!@#&!@#&local function newFile()!@#&	local wid = w - 13!@#&!@#&	-- Get name!@#&	title(\"Lua IDE - New File\")!@#&	local name = centerRead(wid, \"/\")!@#&	if not name or name == \"\" then return \"menu\" end!@#&	name = \"/\" .. name!@#&!@#&	-- Clear!@#&	title(\"Lua IDE - New File\")!@#&	term.setTextColor(colors[theme.textColor])!@#&	term.setBackgroundColor(colors[theme.promptHighlight])!@#&	for i = 8, 10 do!@#&		term.setCursorPos(w/2 - wid/2, i)!@#&		term.write(string.rep(\" \", wid))!@#&	end!@#&	term.setCursorPos(1, 9)!@#&	if fs.isDir(name) then!@#&		centerPrint(\"Cannot Edit a Directory!\")!@#&		sleep(1.6)!@#&		return \"menu\"!@#&	elseif fs.exists(name) then!@#&		centerPrint(\"File Already Exists!\")!@#&		local opt = prompt({{\"Open\", w/2 - 9, 14}, {\"Cancel\", w/2 + 2, 14}}, \"horizontal\")!@#&		if opt == \"Open\" then return \"edit\", name!@#&		elseif opt == \"Cancel\" then return \"menu\" end!@#&	else return \"edit\", name end!@#&end!@#&!@#&local function openFile()!@#&	local wid = w - 13!@#&!@#&	-- Get name!@#&	title(\"Lua IDE - Open File\")!@#&	local name = centerRead(wid, \"/\")!@#&	if not name or name == \"\" then return \"menu\" end!@#&	name = \"/\" .. name!@#&!@#&	-- Clear!@#&	title(\"Lua IDE - New File\")!@#&	term.setTextColor(colors[theme.textColor])!@#&	term.setBackgroundColor(colors[theme.promptHighlight])!@#&	for i = 8, 10 do!@#&		term.setCursorPos(w/2 - wid/2, i)!@#&		term.write(string.rep(\" \", wid))!@#&	end!@#&	term.setCursorPos(1, 9)!@#&	if fs.isDir(name) then!@#&		centerPrint(\"Cannot Open a Directory!\")!@#&		sleep(1.6)!@#&		return \"menu\"!@#&	elseif not fs.exists(name) then!@#&		centerPrint(\"File Doesn't Exist!\")!@#&		local opt = prompt({{\"Create\", w/2 - 11, 14}, {\"Cancel\", w/2 + 2, 14}}, \"horizontal\")!@#&		if opt == \"Create\" then return \"edit\", name!@#&		elseif opt == \"Cancel\" then return \"menu\" end!@#&	else return \"edit\", name end!@#&end!@#&!@#&!@#&--  -------- Settings!@#&!@#&local function update()!@#&	local function draw(status)!@#&		title(\"LuaIDE - Update\")!@#&		term.setBackgroundColor(colors[theme.prompt])!@#&		term.setTextColor(colors[theme.textColor])!@#&		for i = 8, 10 do!@#&			term.setCursorPos(w/2 - (status:len() + 4), i)!@#&			write(string.rep(\" \", status:len() + 4))!@#&		end!@#&		term.setCursorPos(w/2 - (status:len() + 4), 9)!@#&		term.write(\" - \" .. status .. \" \")!@#&!@#&		term.setBackgroundColor(colors[theme.errHighlight])!@#&		for i = 8, 10 do!@#&			term.setCursorPos(w/2 + 2, i)!@#&			term.write(string.rep(\" \", 10))!@#&		end!@#&		term.setCursorPos(w/2 + 2, 9)!@#&		term.write(\" > Cancel \")!@#&	end!@#&!@#&	if not http then!@#&		draw(\"HTTP API Disabled!\")!@#&		sleep(1.6)!@#&		return \"settings\"!@#&	end!@#&!@#&	draw(\"Updating...\")!@#&	local tID = os.startTimer(10)!@#&	http.request(updateURL)!@#&	while true do!@#&		local e, but, x, y = os.pullEvent()!@#&		if (e == \"key\" and but == 28) or!@#&				(e == \"mouse_click\" and x >= w/2 + 2 and x <= w/2 + 12 and y == 9) then!@#&			draw(\"Cancelled\")!@#&			sleep(1.6)!@#&			break!@#&		elseif e == \"http_success\" and but == updateURL then!@#&			local new = x.readAll()!@#&			local curf = io.open(ideLocation, \"r\")!@#&			local cur = curf:read(\"*a\")!@#&			curf:close()!@#&!@#&			if cur ~= new then!@#&				draw(\"Update Found\")!@#&				sleep(1.6)!@#&				local f = io.open(ideLocation, \"w\")!@#&				f:write(new)!@#&				f:close()!@#&!@#&				draw(\"Click to Exit\")!@#&				while true do!@#&					local e = os.pullEvent()!@#&					if e == \"mouse_click\" or (not isAdvanced() and e == \"key\") then break end!@#&				end!@#&				return \"exit\"!@#&			else!@#&				draw(\"No Updates Found!\")!@#&				sleep(1.6)!@#&				break!@#&			end!@#&		elseif e == \"http_failure\" or (e == \"timer\" and but == tID) then!@#&			draw(\"Update Failed!\")!@#&			sleep(1.6)!@#&			break!@#&		end!@#&	end!@#&!@#&	return \"settings\"!@#&end!@#&!@#&local function changeTheme()!@#&	title(\"LuaIDE - Theme\")!@#&!@#&	if isAdvanced() then!@#&		local disThemes = {\"Back\"}!@#&		for _, v in pairs(availableThemes) do table.insert(disThemes, v[1]) end!@#&		local t = scrollingPrompt(disThemes)!@#&		local url = nil!@#&		for _, v in pairs(availableThemes) do if v[1] == t then url = v[2] end end!@#&!@#&		if not url then return \"settings\" end!@#&		if t == \"Dawn (Default)\" then!@#&			term.setBackgroundColor(colors[theme.backgroundHighlight])!@#&			term.setCursorPos(3, 3)!@#&			term.clearLine()!@#&			term.write(\"LuaIDE - Loaded Theme!\")!@#&			sleep(1.6)!@#&!@#&			fs.delete(themeLocation)!@#&			theme = defaultTheme!@#&			return \"menu\"!@#&		end!@#&!@#&		term.setBackgroundColor(colors[theme.backgroundHighlight])!@#&		term.setCursorPos(3, 3)!@#&		term.clearLine()!@#&		term.write(\"LuaIDE - Downloading...\")!@#&!@#&		fs.delete(\"/.LuaIDE_temp_theme_file\")!@#&		download(url, \"/.LuaIDE_temp_theme_file\")!@#&		local a = loadTheme(\"/.LuaIDE_temp_theme_file\")!@#&!@#&		term.setCursorPos(3, 3)!@#&		term.clearLine()!@#&		if a then!@#&			term.write(\"LuaIDE - Loaded Theme!\")!@#&			fs.delete(themeLocation)!@#&			fs.move(\"/.LuaIDE_temp_theme_file\", themeLocation)!@#&			theme = a!@#&			sleep(1.6)!@#&			return \"menu\"!@#&		end!@#&		!@#&		term.write(\"LuaIDE - Could Not Load Theme!\")!@#&		fs.delete(\"/.LuaIDE_temp_theme_file\")!@#&		sleep(1.6)!@#&		return \"settings\"!@#&	else!@#&		term.setCursorPos(1, 8)!@#&		centerPrint(\"Themes are not available on\")!@#&		centerPrint(\"normal computers!\")!@#&	end!@#&end!@#&!@#&local function settings()!@#&	title(\"LuaIDE - Settings\")!@#&!@#&	local opt = prompt({{\"Change Theme\", w/2 - 17, 8}, {\"Return to Menu\", w/2 - 22, 13},!@#&		{\"Check for Updates\", w/2 + 2, 8}, {\"Exit IDE\", w/2 + 2, 13, bg = colors[theme.err], !@#&		highlight = colors[theme.errHighlight]}}, \"vertical\", true)!@#&	if opt == \"Change Theme\" then return changeTheme()!@#&	elseif opt == \"Check for Updates\" then return update()!@#&	elseif opt == \"Return to Menu\" then return \"menu\"!@#&	elseif opt == \"Exit IDE\" then return \"exit\" end!@#&end!@#&!@#&!@#&--  -------- Menu!@#&!@#&local function menu()!@#&	title(\"Welcome to LuaIDE \" .. version)!@#&!@#&	local opt = prompt({{\"New File\", w/2 - 13, 8}, {\"Open File\", w/2 - 14, 13},!@#&		{\"Settings\", w/2 + 2, 8}, {\"Exit IDE\", w/2 + 2, 13, bg = colors[theme.err],!@#&		highlight = colors[theme.errHighlight]}}, \"vertical\", true)!@#&	if opt == \"New File\" then return \"new\"!@#&	elseif opt == \"Open File\" then return \"open\"!@#&	elseif opt == \"Settings\" then return \"settings\"!@#&	elseif opt == \"Exit IDE\" then return \"exit\" end!@#&end!@#&!@#&!@#&--  -------- Main!@#&!@#&local function main(arguments)!@#&	local opt, data = \"menu\", nil!@#&!@#&	-- Check arguments!@#&	if type(arguments) == \"table\" and #arguments > 0 then!@#&		local f = \"/\" .. shell.resolve(arguments[1])!@#&		if fs.isDir(f) then print(\"Cannot edit a directory.\") end!@#&		opt, data = \"edit\", f!@#&	end!@#&!@#&	-- Main run loop!@#&	while true do!@#&		-- Menu!@#&		if opt == \"menu\" then opt = menu() end!@#&!@#&		-- Other!@#&		if opt == \"new\" then opt, data = newFile()!@#&		elseif opt == \"open\" then opt, data = openFile()!@#&		elseif opt == \"settings\" then opt = settings()!@#&		end if opt == \"exit\" then break end!@#&!@#&		-- Edit!@#&		if opt == \"edit\" and data then opt = edit(data) end!@#&	end!@#&end!@#&!@#&-- Load Theme!@#&if fs.exists(themeLocation) then theme = loadTheme(themeLocation) end!@#&if not theme and isAdvanced() then theme = defaultTheme!@#&elseif not theme then theme = normalTheme end!@#&!@#&-- Run!@#&local _, err = pcall(function()!@#&	parallel.waitForAny(function() main(args) end, monitorKeyboardShortcuts)!@#&end)!@#&!@#&-- Catch errors!@#&if err and not err:find(\"Terminated\") then!@#&	term.setCursorBlink(false)!@#&	title(\"LuaIDE - Crash! D:\")!@#&!@#&	term.setBackgroundColor(colors[theme.err])!@#&	for i = 6, 8 do!@#&		term.setCursorPos(5, i)!@#&		term.write(string.rep(\" \", 36))!@#&	end!@#&	term.setCursorPos(6, 7)!@#&	term.write(\"LuaIDE Has Crashed! D:\")!@#&!@#&	term.setBackgroundColor(colors[theme.background])!@#&	term.setCursorPos(2, 10)!@#&	print(err)!@#&!@#&	term.setBackgroundColor(colors[theme.prompt])!@#&	local _, cy = term.getCursorPos()!@#&	for i = cy + 1, cy + 4 do!@#&		term.setCursorPos(5, i)!@#&		term.write(string.rep(\" \", 36))!@#&	end!@#&	term.setCursorPos(6, cy + 2)!@#&	term.write(\"Please report this error to\")!@#&	term.setCursorPos(6, cy + 3)!@#&	term.write(\"GravityScore! \")!@#&	!@#&	term.setBackgroundColor(colors[theme.background])!@#&	if isAdvanced() then centerPrint(\"Click to Exit...\", h - 1)!@#&	else centerPrint(\"Press Any Key to Exit...\", h - 1) end!@#&	while true do!@#&		local e = os.pullEvent()!@#&		if e == \"mouse_click\" or (not isAdvanced() and e == \"key\") then break end!@#&	end!@#&!@#&	-- Prevent key from being shown!@#&	os.queueEvent(event_distract)!@#&	os.pullEvent()!@#&end!@#&!@#&-- Exit!@#&term.setBackgroundColor(colors.black)!@#&term.setTextColor(colors.white)!@#&term.clear()!@#&term.setCursorPos(1, 1)!@#&centerPrint(\"Thank You for Using Lua IDE \" .. version)!@#&centerPrint(\"Made by GravityScore\")",["filebrowser"]="--[[!@#&		Mouse File Browser!@#&		by:!@#&			Stiepen irc(Kilobyte)!@#&			Cruor!@#&			BigSHinyToys!@#&		!@#&		note: send link to nightin9ale on CC forums!@#&--]]!@#&!@#&local tArgs = {...}!@#&local ver = \"1.4\"!@#&local sTitle = \"File Browser\"!@#&local bugTest, norun, dir, showAll!@#&local _tArgs = {}!@#&local config = \"mouse.cfg\"!@#&!@#&local temp!@#&if shell and shell.getRunningProgram then!@#&	temp = shell.getRunningProgram()!@#&end!@#&!@#&temp = temp or \"/bla\"!@#&local localPath = string.sub(temp,1,#temp-string.len(fs.getName(temp)))!@#&temp = nil -- just because not needed!@#&!@#&-- load config file!@#&!@#&local configSet = {}!@#&local cnf = {}!@#&!@#&if fs.exists(localPath..\"/\"..config) then!@#&	local file = fs.open(localPath..\"/\"..config,\"r\")!@#&	if file then!@#&		local item = file.readLine()!@#&		while item do!@#&			table.insert(cnf,item)!@#&			item = file.readLine()!@#&		end!@#&		file.close()!@#&	end	!@#&end!@#&!@#&for i = 1,10 do!@#&	local test,data = pcall(textutils.unserialize,cnf[i])!@#&	if test then!@#&		configSet[i] = data!@#&	else!@#&		configSet[i] = nil!@#&	end!@#&end!@#&cnf = nil!@#&!@#&-- color configuration work in progress!@#&local titleBar = configSet[1] or {txt = colors.black,back = colors.blue}!@#&local addressBar = configSet[2] or {txt = colors.black,back = colors.lightGray}!@#&local itemWindo = configSet[3] or {txt = colors.black,back = colors.cyan}!@#&local rcmList = configSet[4] or {txt = colors.black,back = colors.lightGray} -- rcm = Right Click Menu List!@#&local rcmTitle = configSet[5] or {txt = colors.black,back = colors.blue}!@#&local dialogTitle = configSet[6] or {txt = colors.black,back = colors.blue}!@#&local dialogWindo = configSet[7] or {txt = colors.black,back = colors.white}!@#&local scrollCol = configSet[8] or {off = colors.gray, button = colors.gray,back = colors.lightGray}!@#&!@#&local tIcons = configSet[9] or {!@#&	back = {tCol = \"lightGray\",bCol = \"blue\",txt = \" < \"},!@#&	disk = {tCol = \"lime\",bCol = \"green\",txt = \"[*]\"},!@#&	audio = {tCol = \"yellow\",bCol = \"red\",txt = \"(o)\"},!@#&	folder = {tCol = \"lightGray\",bCol = \"blue\",txt = \"[=]\"},!@#&	file = {tCol = nil ,bCol = nil ,txt = nil}!@#&}!@#&!@#&local customLaunch = configSet[10] or {!@#&	[\"Edit\"] = \"rom/programs/edit\",!@#&	[\"Paint\"] = \"rom/programs/color/paint\"!@#&}!@#&!@#&local function saveCFG(overWrite)!@#&	if not fs.exists(localPath..\"/\"..config) or overWrite then!@#&		local cnf = {}!@#&		local file = fs.open(localPath..\"/\"..config,\"w\")!@#&		if file then!@#&			file.write(textutils.serialize(titleBar)..\"\\n\")!@#&			file.write(textutils.serialize(addressBar)..\"\\n\")!@#&			file.write(textutils.serialize(itemWindo)..\"\\n\")!@#&			file.write(textutils.serialize(rcmList)..\"\\n\")!@#&			file.write(textutils.serialize(rcmTitle)..\"\\n\")!@#&			file.write(textutils.serialize(dialogTitle)..\"\\n\")!@#&			file.write(textutils.serialize(dialogWindo)..\"\\n\")!@#&			file.write(textutils.serialize(scrollCol)..\"\\n\")!@#&			file.write(textutils.serialize(tIcons)..\"\\n\")!@#&			file.write(textutils.serialize(customLaunch)..\"\\n\")!@#&			file.close()!@#&		elseif overWrite then!@#&		end!@#&	end!@#&end!@#&!@#&saveCFG()!@#&!@#&-- end configuration!@#&!@#&local function help()!@#&	print([[Usage: browser [-d] [-h] [-a] [-u] [--debug] [--help] [--dir <dir>] [--all] [--update]!@#&--debug or -d: enable debug mode!@#&--help or -h: display this screen!@#&--dir: define initial directory!@#&--all or -a: show hidden files!@#&--update -u: update]])!@#&end!@#&!@#&local function inBouwndry(clickX,clickY,boxX,boxY,width,hight)!@#&	return ( clickX >= boxX and clickX < boxX + width and clickY >= boxY and clickY < boxY + hight )!@#&end!@#&!@#&local function update()!@#&	print(\"Checking for Updates\")!@#&	local isHTTP = false!@#&	local response!@#&	if http then!@#&		isHTTP = true!@#&		print(\"http on\")!@#&		response = http.get(\"http://pastebin.com/raw.php?i=rLbnyM1U\")!@#&	end!@#&	local flag = false!@#&	local isNewFlag = false!@#&	local newVerID!@#&	if response and isHTTP then!@#&		print(\"recived\")!@#&		local sInfo = response.readLine()!@#&		print(sInfo)!@#&		while sInfo do!@#&			print(sInfo)!@#&			if flag then!@#&				if sInfo == ver then!@#&					print(\"Mouse File Browser is up to date\")!@#&					break!@#&				else!@#&					newVerID = sInfo!@#&					flag = false!@#&					isNewFlag = true!@#&				end!@#&			elseif sInfo == sTitle then!@#&				flag = true!@#&			elseif isNewFlag then!@#&				isNewFlag = sInfo!@#&				response.close()!@#&				break!@#&			end!@#&			sInfo = response.readLine()!@#&		end!@#&		if isNewFlag then!@#&			print(\"New vershion avalible \"..newVerID)!@#&			print('downloading to \\Browser')!@#&			if fs.exists(\"Browser\") then!@#&				write(\"Browser exists OverWrite Browser Y/N : \")!@#&				local input = string.lower(read())!@#&				while input ~= \"y\" and input ~= \"n\" do!@#&					print(\"y or n required\")!@#&					input = string.lower(read())!@#&				end!@#&				if input == \"y\" then!@#&					print(\"Over Writeing Browser\")!@#&					print(\"Downloading new File\")!@#&					local response = http.get(\"http://pastebin.com/raw.php?i=\"..isNewFlag)!@#&					if response then!@#&						print(\"file downloaded\")!@#&						print(\"installing\")!@#&						fs.delete(\"Browser\")!@#&						local handel = fs.open(\"Browser\",\"w\")!@#&						if handel then!@#&							handel.write(response.readAll())!@#&							handel.close()!@#&							print(\"Update Complete\")!@#&						end!@#&						response.close()!@#&					end!@#&				else!@#&					print(\"Update aborted\")!@#&				end!@#&			else!@#&				print(\"Downloading new File\")!@#&				local response = http.get(\"http://pastebin.com/raw.php?i=\"..isNewFlag)!@#&				if response then!@#&					print(\"file downloaded\")!@#&					print(\"installing\")!@#&					local handel = fs.open(\"Browser\",\"w\")!@#&					if handel then!@#&						handel.write(response.readAll())!@#&						handel.close()!@#&						print(\"Update Complete\")!@#&					end!@#&					response.close()!@#&				end!@#&			end!@#&		end!@#&	elseif isHTTP then!@#&		print(\"Error downloading update file Please contact BigSHinyToys on the CC forums\")!@#&		print(\"http://www.computercraft.info/forums2/index.php?/topic/5509-advanced-computer-mouse-file-browser/\")!@#&	elseif not isHTTP then!@#&		print(\"HTTP API is turned off\")!@#&		print(\"Access Computer Craft Configer and change line\")!@#&		print([[enableapi_http {!@#&# Enable the \"http\" API on Computers!@#&general=false!@#&}!@#&TO THIS :!@#&enableapi_http {!@#&# Enable the \"http\" API on Computers!@#&general=true!@#&}]])!@#&	end!@#&	notCMD = false!@#&	norun = true!@#&end!@#&!@#&for a = 1, #tArgs do!@#&	if tArgs[a]:sub(1,2) == \"--\" then!@#&		local cmd = tArgs[a]:sub(3):lower()!@#&		if cmd == \"debug\" then!@#&			bugTest = true!@#&		elseif cmd == \"help\" then!@#&			help()!@#&			norun = true!@#&		elseif cmd == \"dir\" then!@#&			dir = tArgs[a+1]!@#&			a = a + 1!@#&		elseif cmd == \"all\" then!@#&			showAll = true!@#&		elseif cmd == \"update\" then!@#&			update()!@#&		end!@#&	elseif tArgs[a]:sub(1,1) == \"-\" then!@#&		for b = 2, #tArgs[a] do!@#&			cmd = tArgs[a]:sub(b, b)!@#&			if cmd == \"d\" then!@#&				bugTest = true!@#&			elseif cmd == \"h\" then!@#&				help()!@#&				norun = true!@#&			elseif cmd == \"p\" then!@#&				dir = tArgs[a+1]!@#&				a = a + 1!@#&			elseif cmd == \"a\" then!@#&				showAll = true!@#&			elseif cmd == \"u\" then!@#&				update()!@#&			end!@#&		end!@#&	else!@#&		table.insert(_tArgs, tArgs[a])!@#&	end!@#&end!@#&!@#&if (not dir) and shell and shell.dir then!@#&	dir = shell.dir()!@#&end!@#&!@#&if dir and shell and shell.resolve then!@#&	dir = shell.resolve(dir)!@#&end!@#&!@#&dir = dir or \"/\"!@#&!@#&if bugTest then -- this is that the var is for testing!@#&	print(\"Dir: \"..dir)!@#&	os.startTimer(4)!@#&	os.pullEvent()!@#&end!@#&!@#&local function clear()!@#&	term.setBackgroundColor(colors.black)!@#&	term.setTextColor(colors.white)!@#&	term.clear()!@#&	term.setCursorBlink(false)!@#&	term.setCursorPos(1,1)!@#&end!@#&!@#&--[[!@#&		Code thanks to Cruor !@#&		http://www.computercraft.info/forums2/index.php?/topic/5802-support-for-shell/!@#&]]--!@#&!@#&local function fixArgs(...)!@#&	local tReturn={}!@#&	local str=table.concat({...},\" \")!@#&	local sMatch!@#&	while str and #str>0 do!@#&		if string.sub(str,1,1)==\"\\\"\" then!@#&			sMatch, str=string.match(str, \"\\\"(.-)\\\"%s*(.*)\")!@#&		else!@#&			sMatch, str=string.match(str, \"(%S+)%s*(.*)\")!@#&		end!@#&		table.insert(tReturn,sMatch)!@#&	end!@#&	return tReturn!@#&end!@#&!@#&--[[ end Cruor function ]]--!@#&!@#&!@#&-- modified read made to play nice with coroutines!@#&!@#&local function readMOD( _sReplaceChar, _tHistory,_wdth)!@#&	local sLine = \"\"!@#&	term.setCursorBlink( true )!@#&!@#&	local nHistoryPos = nil!@#&	local nPos = 0!@#&    if _sReplaceChar then!@#&		_sReplaceChar = string.sub( _sReplaceChar, 1, 1 )!@#&	end!@#&	!@#&	local sx, sy = term.getCursorPos()	!@#&!@#&	local w, h = term.getSize()!@#&	if _wdth and type(_wdth) == \"number\" then!@#&		w = sx + _wdth - 1!@#&	end!@#&	!@#&	local function redraw( _sCustomReplaceChar )!@#&		local nScroll = 0!@#&		if sx + nPos >= w then!@#&			nScroll = (sx + nPos) - w!@#&		end!@#&			!@#&		term.setCursorPos( sx + _wdth - 1, sy )!@#&		term.write(\" \")!@#&		term.setCursorPos( sx, sy )!@#&		local sReplace = _sCustomReplaceChar or _sReplaceChar!@#&		if sReplace then!@#&			term.write( string.rep(sReplace,_wdth) )!@#&		else!@#&			term.write( string.sub( sLine, nScroll + 1 ,nScroll + _wdth) )!@#&		end!@#&		term.setCursorPos( sx + nPos - nScroll, sy )!@#&	end!@#&	!@#&	while true do!@#&		local sEvent, param = os.pullEvent()!@#&		if sEvent == \"char\" then!@#&			sLine = string.sub( sLine, 1, nPos ) .. param .. string.sub( sLine, nPos + 1 )!@#&			nPos = nPos + 1!@#&			redraw()!@#&			!@#&		elseif sEvent == \"key\" then!@#&			!@#&			if param == keys.left then!@#&				-- Left!@#&				if nPos > 0 then!@#&					nPos = nPos - 1!@#&					redraw()!@#&				end!@#&				!@#&			elseif param == keys.right then!@#&				-- Right				!@#&				if nPos < string.len(sLine) then!@#&					nPos = nPos + 1!@#&					redraw()!@#&				end!@#&			!@#&			elseif param == keys.up or param == keys.down then!@#&                -- Up or down!@#&				if _tHistory then!@#&					redraw(\" \");!@#&					if param == keys.up then!@#&						-- Up!@#&						if nHistoryPos == nil then!@#&							if #_tHistory > 0 then!@#&								nHistoryPos = #_tHistory!@#&							end!@#&						elseif nHistoryPos > 1 then!@#&							nHistoryPos = nHistoryPos - 1!@#&						end!@#&					else!@#&						-- Down!@#&						if nHistoryPos == #_tHistory then!@#&							nHistoryPos = nil!@#&						elseif nHistoryPos ~= nil then!@#&							nHistoryPos = nHistoryPos + 1!@#&						end						!@#&					end!@#&					!@#&					if nHistoryPos then!@#&                    	sLine = _tHistory[nHistoryPos]!@#&                    	nPos = string.len( sLine ) !@#&                    else!@#&						sLine = \"\"!@#&						nPos = 0!@#&					end!@#&					redraw()!@#&                end!@#&			elseif param == keys.backspace then!@#&				-- Backspace!@#&				if nPos > 0 then!@#&					redraw(\" \");!@#&					sLine = string.sub( sLine, 1, nPos - 1 ) .. string.sub( sLine, nPos + 1 )!@#&					nPos = nPos - 1					!@#&					redraw()!@#&				end!@#&			elseif param == keys.home then!@#&				-- Home!@#&				nPos = 0!@#&				redraw()		!@#&			elseif param == keys.delete then!@#&				if nPos < string.len(sLine) then!@#&					redraw(\" \");!@#&					sLine = string.sub( sLine, 1, nPos ) .. string.sub( sLine, nPos + 2 )				!@#&					redraw()!@#&				end!@#&			elseif param == keys[\"end\"] then!@#&				-- End!@#&				nPos = string.len(sLine)!@#&				redraw()!@#&			end!@#&		elseif sEvent == \"redraw\" then!@#&			redraw()!@#&		elseif sEvent == \"return\" then!@#&			term.setCursorBlink( false )!@#&			return sLine!@#&		end!@#&	end!@#&	!@#&	term.setCursorBlink( false )!@#&	!@#&	return sLine!@#&end!@#&!@#&-- end modified read!@#&!@#&local function printC(posX,posY,textCol,backCol,text)!@#&	term.setCursorPos(posX,posY)!@#&	term.setTextColor(colors[textCol] or textCol)!@#&	term.setBackgroundColor(colors[backCol] or backCol)!@#&	term.write(text)!@#&end!@#&!@#&local function InputBox(title)!@#&	local boxW,boxH = 26,3!@#&	local termX,termY = term.getSize()!@#&	local ofsX,ofsY = math.ceil((termX/2) - (boxW/2)) , math.ceil((termY/2) - (boxH/2)) -- offset from top left!@#&	local options = {\"ok\",\"cancel\"}!@#&	!@#&	local selected = 1!@#&	local space = 0!@#&	local range = {}!@#&	for i = 1,#options do!@#&		range[i] = {s = space,f = space + string.len(options[i])}!@#&		space = space + string.len(options[i])+3!@#&	end!@#&	local ofC = (boxW/2) - (space/2)!@#&	!@#&	local function drawBox()!@#&		printC(ofsX,ofsY,colors.black,colors.blue,string.rep(\" \",boxW))!@#&		printC(ofsX+1,ofsY,colors.black,colors.blue,(title or \"User Input\"))!@#&		printC(ofsX,ofsY+1,colors.black,colors.white,string.rep(\" \",boxW))!@#&		printC(ofsX,ofsY+2,colors.black,colors.white,string.rep(\" \",boxW))!@#&		printC(ofsX,ofsY+3,colors.black,colors.white,string.rep(\" \",boxW))!@#&		!@#&		for i = 1,#options do!@#&			if i == selected then!@#&				term.setBackgroundColor(colors.lightGray)!@#&				term.setCursorPos(range[i].s + ofC + ofsX - 1,ofsY + 3)!@#&				term.write(\"[\"..options[i]..\"]\")!@#&				term.setBackgroundColor(colors.white)!@#&				term.write(\" \")!@#&			else!@#&				term.setCursorPos(range[i].s + ofC + ofsX - 1,ofsY + 3)!@#&				term.write(\" \"..options[i]..\" \")!@#&			end!@#&		end!@#&		!@#&		printC(ofsX+2,ofsY+2,colors.black,colors.lightGray,string.rep(\" \",boxW-4))!@#&	end!@#&	drawBox()!@#&	term.setCursorPos(ofsX+2,ofsY+2)!@#&	local co = coroutine.create(function() return readMOD(nil,nil,boxW - 4) end)!@#&	while true do!@#&		local event = {os.pullEvent()}!@#&		if event[1] == \"key\" or event[1] == \"char\" then!@#&			if event[2] == 28 then!@#&				local test,data = coroutine.resume(co,\"return\")!@#&				return data!@#&			else!@#&				coroutine.resume(co,unpack(event))!@#&			end!@#&		elseif event[1] == \"mouse_click\" then!@#&			if event[4] == ofsY + 3 then!@#&				for i = 1,#options do!@#&					if event[3] >= range[i].s + ofC + ofsX - 1 and event[3] <= range[i].f + ofC + ofsX then!@#&						if options[i] == \"ok\" then!@#&							local test,data = coroutine.resume(co,\"return\")!@#&							return data!@#&						elseif options[i] == \"cancel\" then!@#&							return false!@#&						end!@#&					end!@#&				end!@#&			end!@#&		end!@#&	end!@#&end!@#&!@#&local function dialogBox(title,message,options, h, w)!@#&	term.setCursorBlink(false)!@#&	local selected = 1!@#&	title = title or \"\"!@#&	message = message or \"\"!@#&	options = options or {}!@#&	local boxW,boxH = (w or 26), (h or 3)!@#&	local termX,termY = term.getSize()!@#&	local ofsX,ofsY = math.ceil((termX/2) - (boxW/2)) , math.ceil((termY/2) - (boxH/2)) -- offset from top left!@#&	!@#&	local space = 0!@#&	local range = {}!@#&	for i = 1,#options do!@#&		range[i] = {s = space,f = space + string.len(options[i])}!@#&		space = space + string.len(options[i])+3!@#&	end!@#&	local ofC = math.ceil((boxW/2)) - math.ceil((space/2))!@#&	!@#&	local function drawBox()!@#&		printC(ofsX,ofsY,dialogTitle.txt,dialogTitle.back,\" \"..title..string.rep(\" \",boxW-#title-5)..\"_[]\")!@#&		term.setBackgroundColor(colors.red)!@#&		term.setTextColor(colors.white)!@#&		term.write(\"X\")!@#&		printC(ofsX,ofsY+1,dialogWindo.txt,dialogWindo.back,string.sub(\" \"..message..string.rep(\" \",boxW),1,boxW))!@#&		term.setCursorPos(ofsX,ofsY+2)!@#&		term.write(string.rep(\" \",boxW))!@#&		term.setCursorPos(ofsX,ofsY+3)!@#&		term.write(string.rep(\" \",boxW))!@#&		for i = 1,#options do!@#&			if i == selected then!@#&				printC(range[i].s + ofC + ofsX - 1,ofsY + 3,\"black\",\"lightGray\",\"[\"..options[i]..\"]\")!@#&				term.setBackgroundColor(dialogWindo.back)!@#&				term.setTextColor(dialogWindo.txt)!@#&				term.write(\" \")!@#&			else!@#&				term.setCursorPos(range[i].s + ofC + ofsX - 1,ofsY + 3)!@#&				term.write(\" \"..options[i]..\" \")!@#&			end!@#&		end!@#&		term.setCursorPos(ofsX + ofC + space,ofsY + 3)!@#&		term.write(string.rep(\" \",boxW - (ofC + space)))!@#&		term.setBackgroundColor(colors.black)!@#&		term.setTextColor(colors.white)			!@#&	end!@#&	while true do!@#&		drawBox()!@#&		event = {os.pullEvent()}!@#&		if event[1] == \"key\" then!@#&			if event[2] == 203 then -- left!@#&				selected = selected - 1!@#&				if selected < 1 then!@#&					selected = #options!@#&				end!@#&			elseif event[2] == 205 then -- right!@#&				selected = selected + 1!@#&				if selected > #options then!@#&					selected = 1!@#&				end!@#&			elseif event[2] == 28 then -- enter!@#&				return selected , options[selected]!@#&			end!@#&		elseif event[1] == \"mouse_click\" then!@#&			!@#&			if bugTest then term.write(\"M \"..event[2]..\" X \"..event[3]..\" Y \"..event[4]..\"    \") end!@#&			!@#&			if event[2] == 1 then!@#&				if event[4] == ofsY + 3 then!@#&					for i = 1,#options do!@#&						if event[3] >= range[i].s + ofC + ofsX - 1 and event[3] <= range[i].f + ofC + ofsX then!@#&							return i , options[i]!@#&						end!@#&					end!@#&				end!@#&			end!@#&		end!@#&	end!@#&end!@#&!@#&local flag = true!@#&local fSlash = \"/\"!@#&local path = {dir:match(\"[^/]+\")}!@#&local function stringPath() -- compacted this a lot!@#&	return fSlash..table.concat(path,fSlash)!@#&end!@#&!@#&local function osRunSpaces(sFileLocation,...) -- getRunningProgram() [\"shell\"] = shell!@#&	clear()!@#&	if os.newThread then!@#&		os.newThread(false,...)!@#&	else!@#&	local fProg,probblem = loadfile(sFileLocation)!@#&		if fProg then!@#&			local tEnv = {[\"shell\"] = {}}!@#&			setmetatable(tEnv.shell,{ __index = shell})!@#&			tEnv.shell.getRunningProgram = function()!@#&				return sFileLocation!@#&			end!@#&			setmetatable(tEnv,{ __index = _G})!@#&			setfenv(fProg,tEnv)!@#&			local test,probblem = pcall(fProg,...)!@#&			if not test then!@#&				print(probblem)!@#&				dialogBox(\"ERROR\",tostring(probblem),{\"ok\"},3,30)!@#&			else!@#&				return true!@#&			end!@#&		else!@#&			print(probblem)!@#&			dialogBox(\"ERROR\",tostring(probblem),{\"ok\"},3,30)!@#&		end!@#&	end!@#&end!@#&!@#&local function rClickMenu(title,tList,tItem,posX,posY)!@#&!@#&	term.setCursorBlink(false)!@#&	local BoxTitle = title!@#&	local choices = {}!@#&	local termX,termY = term.getSize()!@#&	local offX,offY!@#&	!@#&	local width = #BoxTitle + 2!@#&	local hight!@#&	!@#&	for k,v in pairs(tList) do!@#&		if v ~= nil then!@#&			table.insert(choices,k)!@#&		end!@#&		if width < #k + 2 then!@#&			width = #k + 2!@#&		end!@#&	end!@#&	!@#&	if #choices == 0 then!@#&		return!@#&	end!@#&	!@#&	hight = #choices + 1!@#&	table.sort(choices)!@#&	!@#&	offX,offY = math.ceil((termX/2) - (width/2)),math.ceil((termY/2) - (hight/2))!@#&	!@#&	if posX and posY then -- offX,offY = posX,posY!@#&		if posX >= termX - width - 1 then!@#&			offX = termX - width - 1!@#&		else!@#&			offX = posX!@#&		end!@#&		if posY >= termY - hight then!@#&			offY = termY - hight!@#&		else!@#&			offY = posY!@#&		end!@#&	end!@#&	!@#&	local function reDrawer()!@#&		printC(offX,offY,rcmTitle.txt,rcmTitle.back,\" \"..BoxTitle..string.rep(\" \",width - #BoxTitle - 1))!@#&		for i = 1,#choices do!@#&			printC(offX,offY + i,rcmList.txt,rcmList.back,\" \"..choices[i]..string.rep(\" \",width - #choices[i] - 1))!@#&		end!@#&	end!@#&	!@#&	while true do!@#&		reDrawer()!@#&		local event = {os.pullEvent()}!@#&		if event[1] == \"mouse_click\" then!@#&			if event[2] == 1 then -- event[3] = x event[4] = y!@#&				if event[4] > offY and event[4] < hight + offY and event[3] >= offX and event[3] < width + offX then!@#&					--dialogBox(\"ERROR:\",type(tList[choices[event[4] - offY]]),{\"ok\"})!@#&					if type(tList[choices[event[4] - offY]]) == \"function\" then!@#&						return tList[choices[event[4] - offY]](tItem)!@#&					elseif type(tList[choices[event[4] - offY]]) == \"table\" then!@#&						return rClickMenu(\"Options\",tList[choices[event[4] - offY]],tItem,event[3],event[4])!@#&					elseif type(tList[choices[event[4] - offY]]) == \"string\" then!@#&						return osRunSpaces(!@#&								unpack(!@#&									fixArgs(!@#&										tList[choices[event[4] - offY]]..\" \\\"\"..stringPath()..fSlash..tItem.n..\"\\\"\"!@#&									)!@#&								)!@#&							)!@#&					else!@#&						dialogBox(\"ERROR:\",\"somthing up with new rMenu\",{\"ok\"})!@#&					end!@#&				else!@#&					return!@#&				end!@#&			elseif event[2] == 2 then!@#&				return!@#&			end!@#&		end!@#&	end!@#&	!@#&end!@#&!@#&local function preferences()!@#&	local tItem = {!@#&		{txt = \"Title Bar\",it = titleBar},!@#&		{txt = \"Address Bar\",it = addressBar},!@#&		{txt = \"Item Windo\", it = itemWindo},!@#&		{txt = \"Title Right Click Title\",it = rcmTitle},!@#&		{txt = \"Right Click Menu\",it = rcmList},!@#&		{txt = \"Title Dialog Box\",it = dialogTitle},!@#&		{txt = \"Dialog Box\",it = dialogWindo},!@#&		{txt = \"Scroll Bar\",it = scrollCol}!@#&	}!@#&	local topL,topR = 13,5!@#&	local width,hight = 23,6!@#&	local bottomL,bottomR = topL + width,topR + hight!@#&	!@#&	local listOffset = 0!@#&	local sel = 1!@#&	local otherSel = 1!@#&	local otherItems = {}!@#&	!@#&	if tItem[sel] then!@#&		for k,v in pairs(tItem[sel].it) do!@#&			table.insert(otherItems,{txt = k,it = v})!@#&		end!@#&	end!@#&	!@#&	local function draw()!@#&		printC(topL,topR,titleBar.txt,titleBar.back,string.sub(\" Preferences \"..string.rep(\" \",width),1,width))!@#&		for i = 0,12,4 do!@#&			for a = 1,4 do!@#&				--printC(topL + (a*12)-12 ,topR + ((i+4)/4),4,2^(a+i-1),\" \"..tostring(2^(a+i-1)))!@#&				printC(topL + a-1 ,topR + ((i+4)/4),4,2^(a+i-1),\" \")!@#&			end!@#&		end!@#&		local sSel = \" \"!@#&		for i = 1,hight - 2 do!@#&			if i == sel - listOffset then!@#&				sSel = \">\"!@#&			end!@#&			if tItem[i+listOffset] then!@#&				printC(topL + 4 ,topR + i,colors.black,colors.white,string.sub(sSel..tItem[i+listOffset].txt..string.rep(\" \",width),1,width - 4))!@#&			else!@#&				printC(topL + 4 ,topR + i,colors.black,colors.white,sSel..string.rep(\" \",width-5))!@#&			end!@#&			if i == sel - listOffset then!@#&				sSel = \" \"!@#&			end!@#&		end!@#&		term.setCursorPos(topL,topR + hight - 1)!@#&		local loop = 1!@#&		local length = 0!@#&			for i = 1,#otherItems do!@#&				if otherSel == i then!@#&					sSel = \">\"!@#&				end!@#&				if colors.black == otherItems[i].it or colors.gray == otherItems[i].it then!@#&					term.setTextColor(colors.white)!@#&				else!@#&					term.setTextColor(colors.black)!@#&				end!@#&				term.setBackgroundColor(otherItems[i].it)!@#&				term.write(sSel..tostring(otherItems[i].txt)..\" \")!@#&				length = length + #otherItems[i].txt + 2!@#&				if otherSel == i then!@#&					sSel = \" \"!@#&				end!@#&				loop = loop+1!@#&			end!@#&		term.setBackgroundColor(colors.white)!@#&		term.write(string.rep(\" \",width - length))!@#&	end!@#&	while true do!@#&		draw()!@#&		local event = {os.pullEvent()}!@#&		if event[1] == \"mouse_click\" and event[2] == 1 then!@#&			if inBouwndry(event[3],event[4],topL,topR,width,hight) then!@#&				local inSideX,inSideY = event[3] - topL,event[4] - topR!@#&				if inBouwndry(inSideX+1,inSideY,1,1,4,4) and tItem[sel] then!@#&					--[[!@#&					term.setCursorPos(1,1)!@#&					term.setBackgroundColor(2^(inSideX + ((inSideY*4)-4)))!@#&					print(2^(inSideX + ((inSideY*4)-4)),\" \",inSideX + ((inSideY*4)-4),\"     \")!@#&					]]--!@#&					tItem[sel][\"it\"][otherItems[otherSel].txt] = (2^(inSideX + ((inSideY*4)-4)))!@#&				end!@#&			end!@#&		elseif event[1] == \"key\" then!@#&			if event[2] == 200 then!@#&				sel = sel - 1!@#&			elseif event[2] == 208 then!@#&				sel = sel + 1!@#&			elseif event[2] == 203 then!@#&				otherSel = otherSel - 1!@#&			elseif event[2] == 205 then!@#&				otherSel = otherSel + 1!@#&			elseif event[2] == 28 then!@#&				if dialogBox(\"Confirm\",\"Save prefrences?\",{\"Yes\",\"No\"}) == 1 then!@#&					saveCFG(true)!@#&				end!@#&				return!@#&			end!@#&		end!@#&		if sel < 1 then!@#&			sel = 1!@#&		elseif sel > #tItem then!@#&			sel = #tItem!@#&		end!@#&		if sel > listOffset + hight - 2 then!@#&			listOffset = listOffset + 1!@#&		elseif sel - listOffset < 1 then!@#&			listOffset = listOffset - 1!@#&		end!@#&		!@#&		otherItems = {}!@#&		if tItem[sel] then!@#&			for k,v in pairs(tItem[sel].it) do!@#&				table.insert(otherItems,{txt = k,it = v})!@#&			end!@#&		end!@#&		!@#&		if otherSel < 1 then!@#&			otherSel = 1!@#&		elseif otherSel > #otherItems then!@#&			otherSel = #otherItems!@#&		end!@#&		!@#&		if bugTest then!@#&			term.setBackgroundColor(colors.black)!@#&			term.setTextColor(colors.white)!@#&			term.setCursorPos(1,1)!@#&			term.clearLine()!@#&			term.write(\"sel \"..sel..\" offset \"..listOffset)!@#&		end!@#&	end!@#&end!@#&!@#&local function fileSelect(mode) -- save_file open_file browse < not yet implemented!@#&	!@#&	local title = sTitle..\" \"..ver!@#&	local bRun = true!@#&	local clipboard = nil!@#&	local cut = false!@#&	!@#&	local termX,termY = term.getSize()!@#&	local offsetX,offsetY = 1,1!@#&	local hight,width = math.ceil(termY-2),math.ceil(termX-2)!@#&	local oldHight,oldWidth!@#&	!@#&	-- offsets!@#&	local boxOffX,boxOffY = offsetX,offsetY + 2!@#&	local boxH,boxW = hight - 2 ,width - 2!@#&	!@#&	local barX,barY = offsetX + 1,offsetY + 2!@#&	local barH,barW = 1,width - 1!@#&	!@#&	local tbarX,tbarY = offsetX + 1,offsetY + 1!@#&	local tbarH,tbarW = 1,width - 1!@#&	!@#&	local exitX,exitY = offsetX + width - 1 ,offsetY + 1!@#&	!@#&	local pading = string.rep(\" \",boxW)!@#&	local list!@#&	!@#&	local listOff = 0!@#&	!@#&	local sPath!@#&	local tItemList = {}!@#&	!@#&	local function newList()!@#&		listOff = 0!@#&		flag = true!@#&		tItemList = {{n = \"..\", id = \"back\"}} -- adds a back item at top of list!@#&		sPath = stringPath()!@#&		local folders = {}!@#&		local files = {}!@#&		local disks = {}!@#&		if not fs.exists(sPath) then!@#&			path = {}!@#&			sPath = stringPath()!@#&			dialogBox(\"ERROR:\",\"Path no longer exists\",{\"ok\"})!@#&		end!@#&		local test,list = pcall(fs.list,sPath) -- stopes fs.list crash!@#&		if list == nil then!@#&			list = {}!@#&			dialogBox(\"ERROR : \",\"fs.list crashed\",{\"ok\"})!@#&		end!@#&		if #path == 0 then!@#&			for i,v in pairs(rs.getSides()) do!@#&				if disk.isPresent(v) then!@#&					if disk.hasData(v) then!@#&						table.insert(tItemList,{n = disk.getMountPath(v), id = \"disk\",s = v})!@#&						disks[disk.getMountPath(v)] = true!@#&					elseif disk.hasAudio(v) then!@#&						table.insert(tItemList,{n = disk.getAudioTitle(v), id = \"audio\",s = v})!@#&					end!@#&				end!@#&			end!@#&		end!@#&		for i,v in pairs(list) do!@#&			if fs.isDir(sPath..fSlash..v) then!@#&				table.insert(folders,v)!@#&			else!@#&				table.insert(files,v)!@#&			end!@#&		end!@#&		table.sort(folders)!@#&		table.sort(files)!@#&		for i,v in pairs(folders) do!@#&			if disks[v] == nil then!@#&				table.insert(tItemList,{n = v, id = \"folder\"})!@#&			end!@#&		end!@#&		for i,v in pairs(files) do!@#&			table.insert(tItemList,{n = v, id = \"file\"})!@#&		end!@#&	end!@#&	!@#&	local function paste()!@#&		if cut then!@#&			local s, m = pcall(!@#&				function()!@#&					fs.move(clipboard[1]..fSlash..clipboard[2], stringPath()..fSlash..clipboard[2])!@#&					cut = false!@#&					clipboard = nil!@#&				end)!@#&			if not s then!@#&				dialogBox(\"Error\", (m or \"Couldn't move\"), {\"ok\"}, 4, 30)!@#&			end!@#&			if bugTest then!@#&				local x, y = term.getCursorPos()!@#&				term.setCursorPos(1, ({term.getSize()})[2])!@#&				write(\"from \"..clipboard[1]..fSlash..clipboard[2]..\" to \"..stringPath()..fSlash..clipboard[2])!@#&			end!@#&		else!@#&			local s, m = pcall(function()!@#&				if fs.exists(stringPath()..fSlash..clipboard[2]) then!@#&					fs.copy(clipboard[1]..fSlash..clipboard[2], stringPath()..fSlash..\"copy-\"..clipboard[2])!@#&				else!@#&					fs.copy(clipboard[1]..fSlash..clipboard[2], stringPath()..fSlash..clipboard[2])!@#&				end!@#&			end)!@#&			if not s then!@#&				dialogBox(\"Error\", (m or \"Couldn't copy\"), {\"ok\"}, 4, 30)!@#&			end!@#&			if bugTest then!@#&				local x, y = term.getCursorPos()!@#&				term.setCursorPos(1, ({term.getSize()})[2])!@#&				write(\"from \"..clipboard[1]..fSlash..clipboard[2]..\" to \"..stringPath()..fSlash..clipboard[2])!@#&			end!@#&		end!@#&		newList()!@#&	end!@#&	!@#&	-- this section bellow handles the right click menu!@#&	!@#&	local tmenu = {!@#&		disk = {!@#&			[\"Open\"] = function(tItem)!@#&				table.insert(path,tItem.n)!@#&				newList()!@#&			end,!@#&			[\"Copy\"] = function(tItem)!@#&				clipboard = {stringPath(), tItem.n}!@#&				cut = false!@#&			end,!@#&			[\"Eject\"] = function(tItem)!@#&				if dialogBox(\"Confirm\",\"Eject \"..fSlash..tItem.n..\" \"..tItem.s,{\"yes\",\"no\"}) == 1 then!@#&					disk.eject(tItem.s)!@#&					newList()!@#&				end!@#&			end,!@#&			[\"ID label\"] = function(tItem)!@#&				dialogBox(\"ID label\",disk.getDiskID(tItem.s)..\" \"..tostring(disk.getLabel(tItem.s)),{\"ok\"})!@#&			end,!@#&			[\"Set label\"] = function(tItem)!@#&				local name = InputBox(\"Label?\")!@#&				if name then!@#&					disk.setLabel(tItem.s,name)!@#&				end!@#&			end,!@#&			[\"Clear label\"] = function(tItem)!@#&				if dialogBox(\"Confirm\",\"Cleal Label from \"..tItem.s,{\"yes\",\"no\"}) == 1 then!@#&					disk.setLabel(tItem.s)!@#&				end!@#&			end!@#&		},!@#&		folder = {!@#&			[\"Open\"] = function(temp)!@#&				table.insert(path,temp.n)!@#&				newList()!@#&			end,!@#&			[\"Copy\"] = function(tItem)!@#&				clipboard = {stringPath(), tItem.n}!@#&				cut = false!@#&			end,!@#&			[\"Cut\"] = function(tItem)!@#&				clipboard = {stringPath(), tItem.n}!@#&				cut = true!@#&			end,!@#&			[\"Delete\"] = function(tItem)!@#&				if dialogBox(\"Confirm\",\"Delete \"..tItem.id..\" \"..tItem.n,{\"yes\",\"no\"}) == 1 then!@#&					if fs.isReadOnly(stringPath()..fSlash..tItem.n) then!@#&						dialogBox(\"ERROR\",tItem.id..\" Is read Only\",{\"ok\"})!@#&					else!@#&						fs.delete(stringPath()..fSlash..tItem.n)!@#&						newList()!@#&					end!@#&				end!@#&			end,!@#&			[\"Rename\"] = function(tItem)!@#&				local sName = InputBox(\"New Name\")!@#&				if type(sName) == \"string\" and sName ~= \"\" then!@#&					local s, m = pcall(function()!@#&						fs.move(stringPath()..fSlash..tItem.n,stringPath()..fSlash..sName)!@#&					end)!@#&					if not s then!@#&						dialogBox(\"Error\", (m or \"Rename failed\"), {\"ok\"})!@#&					end!@#&				end!@#&				newList()!@#&			end!@#&		},!@#&		file = {!@#&			[\"Run\"] = {!@#&				[\"Run\"] = function(tItem)!@#&					osRunSpaces(stringPath()..fSlash..tItem.n)!@#&				end,!@#&				[\"Run CMD\"] = function(tItem)!@#&					local cmd = InputBox(\"Commands\")!@#&					if cmd then!@#&						osRunSpaces(stringPath()..fSlash..tItem.n,unpack(fixArgs(cmd)))!@#&					end!@#&				end,!@#&			},!@#&			[\"Open With\"] = customLaunch,!@#&			[\"Rename\"] = function(tItem)!@#&				local sName = InputBox(\"New Name\")!@#&				if type(sName) == \"string\" and sName ~= \"\" then!@#&					local s, m = pcall(function()!@#&						fs.move(stringPath()..fSlash..tItem.n,stringPath()..fSlash..sName)!@#&					end)!@#&					if not s then!@#&						dialogBox(\"Error\", (m or \"Rename failed\"), {\"ok\"})!@#&					end!@#&				end!@#&				newList()!@#&			end,!@#&			[\"Delete\"] = function(tItem)!@#&				if dialogBox(\"Confirm\",\"Delete \"..tItem.id..\" \"..tItem.n,{\"yes\",\"no\"}) == 1 then!@#&					if fs.isReadOnly(stringPath()..fSlash..tItem.n) then!@#&						dialogBox(\"ERROR\",tItem.id..\" Is read Only\",{\"ok\"})!@#&					else!@#&						fs.delete(stringPath()..fSlash..tItem.n)!@#&						newList()!@#&					end!@#&				end!@#&			end,!@#&			[\"Cut\"] = function(tItem)!@#&				clipboard = {stringPath(), tItem.n}!@#&				cut = true!@#&			end,!@#&			[\"Copy\"] = function(tItem)!@#&				clipboard = {stringPath(), tItem.n}!@#&				cut = false!@#&			end!@#&		},!@#&		audio = {!@#&			[\"Play\"] = 1,!@#&			[\"Eject\"] = 1!@#&		},!@#&		back = {!@#&		},!@#&		blank = { -- tmenu.blank.Paste = !@#&			[\"Paste\"] = nil,!@#&			[\"New File\"] = function()!@#&				local name = InputBox()!@#&				if name then!@#&					if fs.exists(stringPath()..fSlash..name) then!@#&						dialogBox(\"ERROR\",\"Name exists\",{\"ok\"})!@#&					else!@#&						local file = fs.open(stringPath()..fSlash..name,\"w\")!@#&						if file then!@#&							file.write(\"\")!@#&							file.close()!@#&							newList()!@#&						else!@#&							dialogBox(\"ERROR\",\"File not created\",{\"ok\"})!@#&						end!@#&					end!@#&				end!@#&			end,!@#&			[\"New Folder\"] = function()!@#&				local name = InputBox()!@#&				if name then!@#&					if fs.exists(stringPath()..fSlash..name) then!@#&						dialogBox(\"ERROR\",\"Name exists\",{\"ok\"})!@#&					else!@#&						if pcall(fs.makeDir,stringPath()..fSlash..name) then!@#&							newList()!@#&						else!@#&							dialogBox(\"ERROR\",\"Access Denied\",{\"ok\"})!@#&						end!@#&					end!@#&				end!@#&			end,!@#&			[\"Preferences\"] = preferences!@#&		},!@#&	}!@#&	!@#&	-- end right click menu!@#&	!@#&	local function scrollBar(posX,posY)!@#&		if posX == boxOffX+boxW+1 and posY > boxOffY and posY <= boxOffY+boxH then!@#&			if #tItemList > boxH then!@#&				if posY == boxOffY + 1 then!@#&					listOff = 0!@#&				elseif posY == boxOffY+boxH then!@#&					listOff = #tItemList + 1 - boxH!@#&				else!@#&					listOff = math.ceil((posY - boxOffY - 1 )*(((#tItemList - boxH+2)/boxH)))!@#&				end!@#&				flag = true!@#&			end!@#&		end!@#&	end!@#&	!@#&	newList()!@#&	!@#&	while bRun do!@#&		if flag then!@#&			flag = false!@#&			-- clear!@#&			if oldHight ~= hight and oldWidth ~= width then!@#&				term.setBackgroundColor(colors.black)!@#&				term.clear()!@#&				oldHight,oldWidth = hight,width!@#&			end!@#&			-- draw top title bar!@#&			local b = tbarW - #title -2!@#&			if b < 0 then!@#&				b = 0!@#&			end!@#&			printC(tbarX,tbarY,titleBar.txt,titleBar.back,string.sub(\" \"..title,1,tbarW)..string.rep(\" \",b))!@#&			term.setTextColor(colors.white)!@#&			term.setBackgroundColor(colors.red)!@#&			term.write(\"X\")!@#&			!@#&			-- draw location bar!@#&			local a = barW - #sPath - 1!@#&			if a < 0 then!@#&				a = 0!@#&			end!@#&			local tmppath = sPath!@#&			if shell and shell.getDisplayName then!@#&				tmppath = shell.getDisplayName(sPath)!@#&				--dialogBox(\"yay\")!@#&			else!@#&				--dialogBox(\"moop\")!@#&			end!@#&			tmppath = tmppath or sPath!@#&			local a = barW - #tmppath - 1!@#&			if a < 0 then!@#&				a = 0!@#&			end!@#&			printC(barX,barY,addressBar.txt,addressBar.back,string.sub(\" \"..tmppath,1,barW)..string.rep(\" \",a))!@#&			!@#&			-- draw scroll bar!@#&			if #tItemList > boxH then!@#&				term.setBackgroundColor(scrollCol.back)!@#&				for i = 1,boxH do!@#&					term.setCursorPos(boxOffX+boxW+1,i + boxOffY)!@#&					local scroll = math.floor( boxH* (listOff/(#tItemList-boxH+2)) )+1!@#&					if i == scroll then!@#&						term.setBackgroundColor(scrollCol.button)!@#&						term.write(\" \")!@#&						term.setBackgroundColor(scrollCol.back)!@#&					else!@#&						term.write(\" \")!@#&					end!@#&				end!@#&			else!@#&				term.setBackgroundColor(scrollCol.off)!@#&				for i = 1,boxH do!@#&					term.setCursorPos(boxOffX+boxW+1,i + boxOffY)!@#&					term.write(\" \")!@#&				end!@#&			end!@#&			!@#&			-- draw main section!@#&!@#&			for i = 1,boxH do -- listOff!@#&				local sel = i+listOff!@#&				if tItemList[sel] then!@#&					printC(1+boxOffX,i+boxOffY,(tIcons[tItemList[sel].id].tCol or itemWindo.txt),(tIcons[tItemList[sel].id].bCol or itemWindo.back),( tIcons[tItemList[sel].id].txt or \"   \"))!@#&					printC(4+boxOffX,i+boxOffY,itemWindo.txt,itemWindo.back,string.sub(\" \"..tItemList[sel].n..pading,1,boxW-3))!@#&				else!@#&					printC(1+boxOffX,i+boxOffY,itemWindo.txt,itemWindo.back,pading)!@#&				end!@#&			end!@#&			!@#&			if bugTest then!@#&				printC(1,1,\"black\",\"white\",listOff..\" \"..boxOffY..\" \"..boxH)!@#&			end!@#&			!@#&		end!@#&		!@#&		-- react to events!@#&		local event = {os.pullEvent()}!@#&		!@#&		if event[1] == \"mouse_click\" then!@#&			if inBouwndry(event[3],event[4],boxOffX+1,boxOffY+1,boxW,boxH) then!@#&				local selected = tItemList[event[4]+listOff-boxOffY]!@#&				if selected and inBouwndry(event[3],event[4],boxOffX+1,event[4],#selected.n + 4,1) then!@#&					if event[2] == 1 then -- left mouse!@#&						if selected.id == \"back\" then!@#&							table.remove(path,#path)!@#&							newList()!@#&						elseif selected.id == \"folder\" or selected.id == \"disk\" then!@#&							table.insert(path,selected.n)!@#&							newList()!@#&						elseif selected.id == \"file\" then!@#&							if dialogBox(\"Run file ?\",selected.n,{\"yes\",\"no\"}) == 1 then!@#&								osRunSpaces(stringPath()..fSlash..selected.n)!@#&							end!@#&						flag = true!@#&						end!@#&					elseif event[2] == 2 then -- right mouse!@#&						rClickMenu(\"Options\",tmenu[selected.id],selected,event[3],event[4])!@#&						flag = true!@#&					end!@#&				elseif event[2] == 2 then -- right clicking not on object!@#&					if clipboard then!@#&						tmenu.blank.Paste = paste!@#&					else!@#&						tmenu.blank.Paste = nil!@#&					end!@#&					rClickMenu(\"Options\",tmenu[\"blank\"],selected,event[3],event[4])!@#&					flag = true!@#&				end!@#&			elseif event[2] == 1 and event[3] == exitX and event[4] == exitY then!@#&				if dialogBox(\"Confirm\",\"Exit application\",{\"yes\",\"no\"}) == 1 then!@#&					bRun = false!@#&				end!@#&				flag = true!@#&			elseif event[2] == 1 then!@#&				scrollBar(event[3],event[4])!@#&			end!@#&		elseif event[1] == \"mouse_scroll\" then -- flag this needs new math!@#&			local old = listOff!@#&			listOff = listOff + event[2]!@#&			if listOff < 0 then!@#&				listOff = 0!@#&			end!@#&			if #tItemList + 1 - boxH > 0 and listOff > #tItemList + 1 - boxH then!@#&				listOff = #tItemList + 1 - boxH!@#&			elseif listOff > 0 and #tItemList + 1 - boxH < 0 then!@#&				listOff = 0!@#&			end!@#&			if listOff ~= old then!@#&				flag = true!@#&			end!@#&		!@#&		elseif event[1] == \"mouse_drag\" then -- scroll bar!@#&			scrollBar(event[3],event[4])!@#&		elseif event[1] == \"disk\" or event[1] == \"disk_eject\" then!@#&			newList()!@#&		elseif event[1] == \"window_resize\" then!@#&			termX,termY = term.getSize()!@#&			offsetX,offsetY = 1,1!@#&			hight,width = math.ceil(termY-2),math.ceil(termX-2)!@#&			!@#&			boxOffX,boxOffY = offsetX,offsetY + 2!@#&			boxH,boxW = hight - 2 ,width - 2!@#&			!@#&			barX,barY = offsetX + 1,offsetY + 2!@#&			barH,barW = 1,width - 1!@#&			!@#&			tbarX,tbarY = offsetX + 1,offsetY + 1!@#&			tbarH,tbarW = 1,width - 1!@#&			!@#&			exitX,exitY = offsetX + width - 1 ,offsetY + 1!@#&			pading = string.rep(\" \",boxW)!@#&			!@#&			flag = true!@#&		elseif event[1] == \"redraw\" then!@#&			flag = true!@#&		end!@#&	end!@#&end!@#&!@#&local function main()!@#&	if term.isColor() then!@#&		clear()!@#&		fileSelect()!@#&		clear()!@#&	else!@#&		error(\"Not an Advanced Computer (gold) \")!@#&	end!@#&end!@#&!@#&local trash = (norun or main())",["firewolf"]="!@#&--!@#&--  Firewolf Website Browser!@#&--  Made by GravityScore and 1lann!@#&--  License found here: https://raw.github.com/1lann/Firewolf/master/LICENSE!@#&--!@#&--  Original Concept From RednetExplorer 2.4.1!@#&--  RednetExplorer Made by ComputerCraftFan11!@#&--!@#&!@#&!@#&--  -------- Variables!@#&!@#&-- Version!@#&local version = \"2.5\"!@#&local build = 36!@#&local browserAgent = \"Firewolf \" .. version!@#&local tArgs = {...}!@#&!@#&-- Server Identification!@#&local serverID = \"other\"!@#&local serverList = {experimental = \"Experimental\", other = \"Other\"}!@#&!@#&-- Updating!@#&local autoupdate = \"true\"!@#&local noInternet = false!@#&!@#&-- Resources!@#&local graphics = {}!@#&local files = {}!@#&local w, h = term.getSize()!@#&!@#&-- Debugging!@#&local debugFile = nil!@#&!@#&-- Environment!@#&local oldEnv = {}!@#&local env = {}!@#&local api = {}!@#&local override = {}!@#&local antivirus = {}!@#&!@#&-- Themes!@#&local theme = {}!@#&!@#&-- Databases!@#&local blacklist = {}!@#&local whitelist = {}!@#&local dnsDatabase = {{}, {}}!@#&!@#&-- Website Loading!@#&local pages = {}!@#&local errorPages = {}!@#&!@#&local website = \"\"!@#&local homepage = \"\"!@#&local timeout = 0.2!@#&local loadingRate, loadingClock = 0, nil!@#&local openAddressBar, clickableAddressBar = true, true!@#&local menuBarOpen = false!@#&local offsetclick = true!@#&local websiteerror = nil!@#&!@#&-- Tabs!@#&local tabs = {}!@#&local filters = {}!@#&local currentTab = 1!@#&!@#&-- Protocols!@#&local curProtocol = {}!@#&local protocols = {}!@#&!@#&-- History!@#&local addressBarHistory = {}!@#&!@#&-- Events!@#&local event_load = \"firewolf_websiteLoadEvent\"!@#&local event_redirect = \"firewolf_redirectEvent\"!@#&local event_error = \"firewolf_siteErrorEvent\"!@#&local event_exit = \"firewolf_exitEvent\"!@#&!@#&-- Download URLs!@#&local firewolfURL = \"https://raw.github.com/1lann/Firewolf/master/entities/other.lua\"!@#&local serverURL = \"https://raw.github.com/1lann/Firewolf/master/server/server-release.lua\"!@#&local buildURL = \"https://raw.github.com/1lann/Firewolf/master/build\"!@#&!@#&-- Data Locations!@#&local rootFolder = \"/.Firewolf_Data\"!@#&local cacheFolder = rootFolder .. \"/cache\"!@#&local serverFolder = rootFolder .. \"/servers\"!@#&local websiteDataFolder = rootFolder .. \"/website_data\"!@#&local themeLocation = rootFolder .. \"/theme\"!@#&local serverLocation = rootFolder .. \"/server_software\"!@#&local settingsLocation = rootFolder .. \"/settings\"!@#&local debugLogLocation = \"/firewolf-log\"!@#&local firewolfLocation = \"/\" .. shell.getRunningProgram()!@#&!@#&local userBlacklist = rootFolder .. \"/user_blacklist\"!@#&local userWhitelist = rootFolder .. \"/user_whitelist\"!@#&!@#&local function isAdvanced() return term.isColor and term.isColor() end!@#&!@#&local function modemPresent()!@#&	if curProtocol == protocols.rdnt then!@#&		for _, v in pairs(rs.getSides()) do!@#&			if peripheral.getType(v) == \"modem\" then rednet.open(v) return true end!@#&		end!@#&	else return true end!@#&	return false!@#&end!@#&!@#&!@#&--  -------- Utilities!@#&!@#&local function debugLog(n, ...)!@#&	local lArgs = {...}!@#&	if debugFile then!@#&		if not n then return end!@#&		debugFile:write(\"\\n\" .. tostring(n) .. \" : \")!@#&		for k, v in pairs(lArgs) do!@#&			if type(v) == \"string\" or type(v) == \"number\" or not type(v) or type(v) == \"boolean\" then!@#&				debugFile:write(tostring(v) .. \", \")!@#&			else debugFile:write(\"type-\" .. type(v) .. \", \") end!@#&		end!@#&	end!@#&end!@#&!@#&local function clear(site, background, drawmenu)!@#&	local titles = {!@#&		[\"firewolf\"] = \"Firewolf\",!@#&		[\"server/rdnt\"] = \"Server Management\",!@#&		[\"server/http\"] = \"Server Management\",!@#&		[\"help\"] = \"Help\",!@#&		[\"settings\"] = \"Settings\",!@#&		[\"credits\"] = \"Credits\",!@#&		[\"crash\"] = \"Crashed!\",!@#&		[\"overspeed\"] = \"Too Fast!\"!@#&	}!@#&!@#&	local title = titles[site] or \"\"!@#&	term.setBackgroundColor(background or colors.black)!@#&	term.setTextColor(colors[theme[\"address-bar-text\"]])!@#&	if drawmenu ~= true then term.clear() end!@#&!@#&	if not menuBarOpen then!@#&		term.setBackgroundColor(colors[theme[\"address-bar-background\"]])!@#&		term.setCursorPos(2, 1)!@#&		term.clearLine()!@#&		if site:len() > w - 10 then site = site:sub(1, 38) .. \"...\" end!@#&		if curProtocol == protocols.http then write(\"http://\" .. site)!@#&		else write(\"rdnt://\" .. site) end!@#&		term.setCursorPos(w - title:len() - 1, 1)!@#&		write(title)!@#&!@#&		if isAdvanced() then!@#&			term.setCursorPos(w, 1)!@#&			term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&			term.setTextColor(colors[theme[\"text-color\"]])!@#&			write(\"<\")!@#&		end!@#&!@#&		term.setBackgroundColor(background or colors.black)!@#&		term.setTextColor(colors.white)!@#&	else!@#&		term.setCursorPos(1, 1)!@#&		term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&		term.setTextColor(colors[theme[\"text-color\"]])!@#&		term.clearLine()!@#&		write(\"> [- Exit Firewolf -]                              \")!@#&	end!@#&!@#&	print(\"\")!@#&end!@#&!@#&local function modRead(properties)!@#&	local w, h = term.getSize()!@#&	local defaults = {replaceChar = nil, history = nil, visibleLength = nil, textLength = nil,!@#&		liveUpdates = nil, exitOnKey = nil}!@#&	if not properties then properties = {} end!@#&	for k, v in pairs(defaults) do if not properties[k] then properties[k] = v end end!@#&	if properties.replaceChar then properties.replaceChar = properties.replaceChar:sub(1, 1) end!@#&	if not properties.visibleLength then properties.visibleLength = w end!@#&!@#&	local sx, sy = term.getCursorPos()!@#&	local line = \"\"!@#&	local pos = 0!@#&	local historyPos = nil!@#&!@#&	local function redraw(repl)!@#&		local scroll = 0!@#&		if properties.visibleLength and sx + pos > properties.visibleLength + 1 then!@#&			scroll = (sx + pos) - (properties.visibleLength + 1)!@#&		end!@#&!@#&		term.setCursorPos(sx, sy)!@#&		local a = repl or properties.replaceChar!@#&		if a then term.write(string.rep(a, line:len() - scroll))!@#&		else term.write(line:sub(scroll + 1, -1)) end!@#&		term.setCursorPos(sx + pos - scroll, sy)!@#&	end!@#&!@#&	local function sendLiveUpdates(event, ...)!@#&		if type(properties.liveUpdates) == \"function\" then!@#&			local ox, oy = term.getCursorPos()!@#&			local a, data = properties.liveUpdates(line, event, ...)!@#&			if a == true and not data then!@#&				term.setCursorBlink(false)!@#&				return line!@#&			elseif a == true and data then!@#&				term.setCursorBlink(false)!@#&				return data!@#&			end!@#&			term.setCursorPos(ox, oy)!@#&		end!@#&	end!@#&!@#&	local a = sendLiveUpdates(\"delete\")!@#&	if a then return a end!@#&	term.setCursorBlink(true)!@#&	while true do!@#&		local e, but, x, y, p4, p5 = os.pullEvent()!@#&		if e == \"char\" then!@#&			local s = false!@#&			if properties.textLength and line:len() < properties.textLength then s = true!@#&			elseif not properties.textLength then s = true end!@#&!@#&			local canType = true!@#&			if not properties.grantPrint and properties.refusePrint then!@#&				local canTypeKeys = {}!@#&				if type(properties.refusePrint) == \"table\" then!@#&					for _, v in pairs(properties.refusePrint) do!@#&						table.insert(canTypeKeys, tostring(v):sub(1, 1))!@#&					end!@#&				elseif type(properties.refusePrint) == \"string\" then!@#&					for char in properties.refusePrint:gmatch(\".\") do!@#&						table.insert(canTypeKeys, char)!@#&					end!@#&				end!@#&				for _, v in pairs(canTypeKeys) do if but == v then canType = false end end!@#&			elseif properties.grantPrint then!@#&				canType = false!@#&				local canTypeKeys = {}!@#&				if type(properties.grantPrint) == \"table\" then!@#&					for _, v in pairs(properties.grantPrint) do!@#&						table.insert(canTypeKeys, tostring(v):sub(1, 1))!@#&					end!@#&				elseif type(properties.grantPrint) == \"string\" then!@#&					for char in properties.grantPrint:gmatch(\".\") do table.insert(canTypeKeys, char) end!@#&				end!@#&				for _, v in pairs(canTypeKeys) do if but == v then canType = true end end!@#&			end!@#&!@#&			if s and canType then!@#&				line = line:sub(1, pos) .. but .. line:sub(pos + 1, -1)!@#&				pos = pos + 1!@#&				redraw()!@#&			end!@#&		elseif e == \"key\" then!@#&			if but == keys.enter then break!@#&			elseif but == keys.left then if pos > 0 then pos = pos - 1 redraw() end!@#&			elseif but == keys.right then if pos < line:len() then pos = pos + 1 redraw() end!@#&			elseif (but == keys.up or but == keys.down) and properties.history and!@#&					#properties.history > 0 then!@#&				redraw(\" \")!@#&				if but == keys.up then!@#&					if not historyPos and #properties.history > 0 then!@#&						historyPos = #properties.history!@#&					elseif historyPos > 1 then historyPos = historyPos - 1 end!@#&				elseif but == keys.down then!@#&					if historyPos == #properties.history then historyPos = nil!@#&					elseif historyPos then historyPos = historyPos + 1 end!@#&				end!@#&!@#&				if properties.history and historyPos then!@#&					line = properties.history[historyPos]!@#&					pos = line:len()!@#&				else!@#&					line = \"\"!@#&					pos = 0!@#&				end!@#&!@#&				redraw()!@#&				local a = sendLiveUpdates(\"history\")!@#&				if a then return a end!@#&			elseif but == keys.backspace and pos > 0 then!@#&				redraw(\" \")!@#&				line = line:sub(1, pos - 1) .. line:sub(pos + 1, -1)!@#&				pos = pos - 1!@#&				redraw()!@#&				local a = sendLiveUpdates(\"delete\")!@#&				if a then return a end!@#&			elseif but == keys.home then!@#&				pos = 0!@#&				redraw()!@#&			elseif but == keys.delete and pos < line:len() then!@#&				redraw(\" \")!@#&				line = line:sub(1, pos) .. line:sub(pos + 2, -1)!@#&				redraw()!@#&				local a = sendLiveUpdates(\"delete\")!@#&				if a then return a end!@#&			elseif but == keys[\"end\"] then!@#&				pos = line:len()!@#&				redraw()!@#&			elseif properties.exitOnKey then!@#&				if but == properties.exitOnKey or (properties.exitOnKey == \"control\" and!@#&						(but == 29 or but == 157)) then!@#&					term.setCursorBlink(false)!@#&					return nil!@#&				end!@#&			end!@#&		end!@#&!@#&		local a = sendLiveUpdates(e, but, x, y, p4, p5)!@#&		if a then return a end!@#&	end!@#&!@#&	term.setCursorBlink(false)!@#&	if line then line = line:gsub(\"^%s*(.-)%s*$\", \"%1\") end!@#&	return line!@#&end!@#&!@#&!@#&--  -------- API!@#&!@#&--  Drawing!@#&!@#&local function printWithType(t, func)!@#&	if type(t) == \"table\" then!@#&		for _, v in pairs(t) do env.pcall(function() printWithType(v, func) end) end!@#&	else func(tostring(t)) end!@#&end!@#&!@#&api.centerWrite = function(text)!@#&	printWithType(text, function(t)!@#&		local x, y = term.getCursorPos()!@#&		term.setCursorPos(math.ceil((w + 1)/2 - t:len()/2), y)!@#&		write(t)!@#&	end)!@#&end!@#&!@#&api.centerPrint = function(text)!@#&	printWithType(text, function(t)!@#&		local x, y = term.getCursorPos()!@#&		term.setCursorPos(math.ceil((w + 2)/2 - t:len()/2), y)!@#&		print(t)!@#&	end)!@#&end!@#&!@#&api.leftWrite = function(text)!@#&	printWithType(text, function(t)!@#&		local x, y = term.getCursorPos()!@#&		term.setCursorPos(1, y)!@#&		write(t)!@#&	end)!@#&end!@#&!@#&api.leftPrint = function(text)!@#&	printWithType(text, function(t)!@#&		local x, y = term.getCursorPos()!@#&		term.setCursorPos(1, y)!@#&		print(t)!@#&	end)!@#&end!@#&!@#&api.rightWrite = function(text)!@#&	printWithType(text, function(t)!@#&		local x, y = term.getCursorPos()!@#&		term.setCursorPos(w - t:len() + 1, y)!@#&		write(t)!@#&	end)!@#&end!@#&!@#&api.rightPrint = function(text)!@#&	printWithType(text, function(t)!@#&		local x, y = term.getCursorPos()!@#&		term.setCursorPos(w - t:len() + 1, y)!@#&		print(t)!@#&	end)!@#&end!@#&!@#&api.clearArea = function() term.clear() term.setCursorPos(1, 1) end!@#&api.cPrint = function(text) api.centerPrint(text) end!@#&api.cWrite = function(text) api.centerWrite(text) end!@#&api.lPrint = function(text) api.leftPrint(text) end!@#&api.lWrite = function(text) api.leftWrite(text) end!@#&api.rPrint = function(text) api.rightPrint(text) end!@#&api.rWrite = function(text) api.rightWrite(text) end!@#&!@#&!@#&--  Server Interation!@#&!@#&api.loadFileFromServer = function(path)!@#&	if type(path) ~= \"string\" then error(\"expected string\", 2) end!@#&	sleep(0.05)!@#&	if path:sub(1, 1) == \"/\" then path = path:sub(2, -1) end!@#&	local id, content = curProtocol.getWebsite(website .. \"/\" .. path)!@#&	if id then return content end!@#&	return nil!@#&end!@#&!@#&api.ioReadFileFromServer = function(path)!@#&	local content = api.loadFileFromServer(path)!@#&	if content then!@#&		local f = env.io.open(rootFolder .. \"/temp_file\", \"w\")!@#&		f:write(content)!@#&		f:close()!@#&		return env.io.open(rootFolder .. \"/temp_file\", \"r\")!@#&	end!@#&	return nil!@#&end!@#&!@#&api.loadImageFromServer = function(path)!@#&	local content = api.loadFileFromServer(path)!@#&	if content then!@#&		local f = env.io.open(rootFolder .. \"/temp_file\", \"w\")!@#&		f:write(content)!@#&		f:close()!@#&!@#&		local image = paintutils.loadImage(rootFolder .. \"/temp_file\")!@#&		env.fs.delete(\"/temp_file\")!@#&		return image!@#&	end!@#&	return nil!@#&end!@#&!@#&api.writeDataFile = function(path, content)!@#&	if type(path) ~= \"string\" or type(content) ~= \"string\" then!@#&		error(\"expected string, string\", 2) end!@#&	if path:sub(1, 1) == \"/\" then path = path:sub(2, -1) end!@#&	local dataPath = websiteDataFolder .. \"/\" .. path:gsub(\"/\", \"$slazh$\")!@#&!@#&	if env.fs.isReadOnly(dataPath) then return false end!@#&	if env.fs.exists(dataPath) then env.fs.delete(dataPath) end!@#&	local f = env.io.open(dataPath, \"w\")!@#&	if not f then return false end!@#&	f:write(content)!@#&	f:close()!@#&	return true!@#&end!@#&!@#&api.readDataFile = function(path)!@#&	if type(path) ~= \"string\" then error(\"readDataFile: expected string\") end!@#&	if path:sub(1, 1) == \"/\" then path = path:sub(2, -1) end!@#&	local dataPath = websiteDataFolder .. \"/\" .. path:gsub(\"/\", \"$slazh$\")!@#&!@#&	if env.fs.isDir(dataPath) then env.fs.delete(dataPath) end!@#&	if env.fs.exists(dataPath) then!@#&		local f = env.io.open(dataPath, \"r\")!@#&		local cont = f:read(\"*a\")!@#&		f:close()!@#&		return cont!@#&	end!@#&	return nil!@#&end!@#&!@#&api.saveFileToUserComputer = function(content)!@#&	if type(content) ~= \"string\" then error(\"expected string\", 2) end!@#&	local oldback, oldtext = override.term.getBackgroundColor(), override.term.getTextColor()!@#&	local ox, oy = term.getCursorPos()!@#&!@#&	term.setTextColor(colors[theme[\"text-color\"]])!@#&	term.setBackgroundColor(colors[theme[\"background\"]])!@#&	term.clear()!@#&	term.setCursorPos(1, 1)!@#&	term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&	print(\"\")!@#&	leftPrint(string.rep(\" \", 20))!@#&	leftPrint(\" Save File Request  \")!@#&	leftPrint(string.rep(\" \", 20))!@#&	print(\"\")!@#&!@#&	term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&	for i = 1, 11 do rightPrint(string.rep(\" \", 36)) end!@#&	term.setCursorPos(1, 7)!@#&	rightPrint(\"The website: \")!@#&	rightPrint(website .. \"  \")!@#&	rightPrint(\"Is requesting to save a file \")!@#&	rightPrint(\"to your computer. \")!@#&!@#&	local ret = nil!@#&	local opt = prompt({{\"Save File\", w - 16, 12}, {\"Cancel\", w - 13, 13}}, \"vertical\")!@#&	if opt == \"Save File\" then!@#&		while not ret do!@#&			term.setCursorPos(1, 15)!@#&			rightWrite(string.rep(\" \", 36))!@#&			term.setCursorPos(w - 34, 15)!@#&			write(\"Path: /\")!@#&			local p = read()!@#&!@#&			term.setCursorPos(1, 15)!@#&			rightWrite(string.rep(\" \", 36))!@#&			if p == \"\" then!@#&				rightWrite(\"Cancelled \")!@#&				break!@#&			elseif fs.exists(\"/\" .. p) then!@#&				rightWrite(\"File Already Exists! \")!@#&			else!@#&				rightWrite(\"File Saved! \")!@#&				ret = \"/\" .. p!@#&				local f = env.io.open(ret, \"w\")!@#&				f:write(content)!@#&				f:close()!@#&			end!@#&!@#&			openAddressBar = false!@#&			sleep(1.3)!@#&			openAddressBar = true!@#&		end!@#&	elseif opt == \"Cancel\" then!@#&		term.setCursorPos(1, 15)!@#&		rightWrite(\"Saving Cancelled! \")!@#&	end!@#&!@#&	openAddressBar = false!@#&	sleep(1.3)!@#&	openAddressBar = true!@#&!@#&	term.setBackgroundColor(oldback or colors.black)!@#&	term.setTextColor(oldtext or colors.white)!@#&	term.clear()!@#&	term.setCursorPos(ox, oy)!@#&	return ret!@#&end!@#&!@#&api.urlDownload = function(url)!@#&	if type(url) ~= \"string\" then error(\"expected string\", 2) end!@#&	local source = nil!@#&	http.request(url)!@#&	local a = os.startTimer(10)!@#&	while true do!@#&		local e, surl, handle = os.pullEvent()!@#&		if e == \"http_success\" then!@#&			source = handle.readAll()!@#&			break!@#&		elseif e == \"http_failure\" or (e == \"timer\" and surl == a) then!@#&			break!@#&		end!@#&	end!@#&!@#&	if type(source) == \"string\" then!@#&		return api.saveFileToUserComputer(source)!@#&	else return nil end!@#&end!@#&!@#&api.pastebinDownload = function(code)!@#&	return api.urlDownload(\"http://pastebin.com/raw.php?i=\" .. tostring(code))!@#&end!@#&!@#&!@#&--  Redirection!@#&!@#&api.redirect = function(url)!@#&	if type(url) ~= \"string\" then url = \"home\" end!@#&	os.queueEvent(event_redirect, url:gsub(\"rdnt://\"):gsub(\"http://\"))!@#&	error()!@#&end!@#&!@#&!@#&--  Theme!@#&!@#&api.themeColor = function(tag)!@#&	if type(tag) ~= \"string\" then error(\"themeColor: expected string\") end!@#&	return colors[theme[tag] or defaultTheme[tag] or \"white\"]!@#&end!@#&!@#&api.themeColour = function(tag) return api.themeColor(tag) end!@#&!@#&!@#&--  Prompt!@#&!@#&api.prompt = function(list, dir)!@#&	if isAdvanced() then!@#&		for _, v in pairs(list) do!@#&			if v.bg then term.setBackgroundColor(v.bg) end!@#&			if v.tc then term.setTextColor(v.tc) end!@#&			if v[2] == -1 then v[2] = math.ceil((w + 1)/2 - (v[1]:len() + 6)/2) end!@#&!@#&			term.setCursorPos(v[2], v[3])!@#&			write(\"[- \" .. v[1])!@#&			term.setCursorPos(v[2] + v[1]:len() + 3, v[3])!@#&			write(\" -]\")!@#&		end!@#&!@#&		while true do!@#&			local e, but, x, y = os.pullEvent()!@#&			if e == \"mouse_click\" then!@#&				for _, v in pairs(list) do!@#&					if x >= v[2] and x <= v[2] + v[1]:len() + 5 and y + (v.coffset or 0) == v[3] then!@#&						return v[1]!@#&					end!@#&				end!@#&			end!@#&		end!@#&	else!@#&		for _, v in pairs(list) do!@#&			term.setBackgroundColor(colors.black)!@#&			term.setTextColor(colors.white)!@#&			if v[2] == -1 then v[2] = math.ceil((w + 1)/2 - (v[1]:len() + 4)/2) end!@#&!@#&			term.setCursorPos(v[2], v[3])!@#&			write(\"  \" .. v[1])!@#&			term.setCursorPos(v[2] + v[1]:len() + 2, v[3])!@#&			write(\"  \")!@#&		end!@#&!@#&		local key1 = dir == \"horizontal\" and 203 or 200!@#&		local key2 = dir == \"horizontal\" and 205 or 208!@#&!@#&		local curSel = 1!@#&		term.setCursorPos(list[curSel][2], list[curSel][3])!@#&		write(\"[\")!@#&		term.setCursorPos(list[curSel][2] + list[curSel][1]:len() + 3, list[curSel][3])!@#&		write(\"]\")!@#&		while true do!@#&			local e, key = os.pullEvent(\"key\")!@#&			term.setCursorPos(list[curSel][2], list[curSel][3])!@#&			write(\" \")!@#&			term.setCursorPos(list[curSel][2] + list[curSel][1]:len() + 3, list[curSel][3])!@#&			write(\" \")!@#&			if key == key1 and curSel > 1 then curSel = curSel - 1!@#&			elseif key == key2 and curSel < #list then curSel = curSel + 1!@#&			elseif key == 28 then return list[curSel][1] end!@#&			term.setCursorPos(list[curSel][2], list[curSel][3])!@#&			write(\"[\")!@#&			term.setCursorPos(list[curSel][2] + list[curSel][1]:len() + 3, list[curSel][3])!@#&			write(\"]\")!@#&		end!@#&	end!@#&end!@#&!@#&api.scrollingPrompt = function(list, x, y, len, width, coffset)!@#&	local wid = width!@#&	if not wid then wid = w - 3 end!@#&!@#&	local function updateDisplayList(items, loc, len)!@#&		local ret = {}!@#&		for i = 1, len do!@#&			local item = items[i + loc - 1]!@#&			if item then table.insert(ret, item) end!@#&		end!@#&		return ret!@#&	end!@#&!@#&	if isAdvanced() then!@#&		local function draw(a)!@#&			for i, v in ipairs(a) do!@#&				term.setCursorPos(x, y + i - 1)!@#&				write(string.rep(\" \", wid))!@#&				term.setCursorPos(x, y + i - 1)!@#&				write(\"[ \" .. v:sub(1, wid - 5))!@#&				term.setCursorPos(wid + x - 2, y + i - 1)!@#&				write(\"  ]\")!@#&			end!@#&		end!@#&!@#&		local loc = 1!@#&		local disList = updateDisplayList(list, loc, len)!@#&		draw(disList)!@#&		!@#&		while true do!@#&			local e, but, clx, cly = os.pullEvent()!@#&			if e == \"key\" and but == 200 and loc > 1 then!@#&				loc = loc - 1!@#&				disList = updateDisplayList(list, loc, len)!@#&				draw(disList)!@#&			elseif e == \"key\" and but == 208 and loc + len - 1 < #list then!@#&				loc = loc + 1!@#&				disList = updateDisplayList(list, loc, len)!@#&				draw(disList)!@#&			elseif e == \"mouse_scroll\" and but > 0 and loc + len - 1 < #list then!@#&				loc = loc + but!@#&				disList = updateDisplayList(list, loc, len)!@#&				draw(disList)!@#&			elseif e == \"mouse_scroll\" and but < 0 and loc > 1 then!@#&				loc = loc + but!@#&				disList = updateDisplayList(list, loc, len)!@#&				draw(disList)!@#&			elseif e == \"mouse_click\" then!@#&				for i, v in ipairs(disList) do!@#&					if clx >= x and clx <= x + wid and cly + coffset == i + y - 1 then return v end!@#&				end!@#&			end!@#&		end!@#&	else!@#&		local function draw(a)!@#&			for i, v in ipairs(a) do!@#&				term.setCursorPos(x, y + i - 1)!@#&				write(string.rep(\" \", wid))!@#&				term.setCursorPos(x, y + i - 1)!@#&				write(\"[ ] \" .. v:sub(1, wid - 5))!@#&			end!@#&		end!@#&!@#&		local loc = 1!@#&		local curSel = 1!@#&		local disList = updateDisplayList(list, loc, len)!@#&		draw(disList)!@#&		term.setCursorPos(x + 1, y + curSel - 1)!@#&		write(\"x\")!@#&!@#&		while true do!@#&			local e, key = os.pullEvent()!@#&			term.setCursorPos(x + 1, y + curSel - 1)!@#&			write(\" \")!@#&			if e == \"key\" and key == 200 then!@#&				if curSel > 1 then curSel = curSel - 1!@#&				elseif loc > 1 then!@#&					loc = loc - 1!@#&					disList = updateDisplayList(list, loc, len)!@#&					draw(disList)!@#&				end!@#&			elseif e == \"key\" and key == 208 then!@#&				if curSel < #disList then curSel = curSel + 1!@#&				elseif loc + len - 1 < #list then!@#&					loc = loc + 1!@#&					disList = updateDisplayList(list, loc, len)!@#&					draw(disList)!@#&				end!@#&			elseif e == \"key\" and key == 28 then return list[curSel + loc - 1] end!@#&			term.setCursorPos(x + 1, y + curSel - 1)!@#&			write(\"x\")!@#&		end!@#&	end!@#&end!@#&!@#&-- Set Environment!@#&for k, v in pairs(getfenv(0)) do env[k] = v end!@#&for k, v in pairs(getfenv(1)) do env[k] = v end!@#&for k, v in pairs(env) do oldEnv[k] = v end!@#&for k, v in pairs(api) do env[k] = v end!@#&!@#&!@#&--  -------- Override!@#&!@#&for k, v in pairs(env) do override[k] = v end!@#&local curtext, curbackground = colors.white, colors.black!@#&override.term = {}!@#&for k, v in pairs(env.term) do override.term[k] = v end!@#&override.os = {}!@#&for k, v in pairs(env.os) do override.os[k] = v end!@#&!@#&override.term.getSize = function()!@#&	local a, b = env.term.getSize()!@#&	return a, b - 2!@#&end!@#&!@#&override.term.setCursorPos = function(x, y)!@#&	if y < 1 then return env.term.setCursorPos(x, 2)!@#&	else return env.term.setCursorPos(x, y + 1) end!@#&end!@#&!@#&override.term.getCursorPos = function()!@#&	local x, y = env.term.getCursorPos()!@#&	return x, y - 1!@#&end!@#&!@#&override.term.getBackgroundColor = function() return curbackground end!@#&override.term.getBackgroundColour = function() return override.term.getBackgroundColor() end!@#&!@#&override.term.setBackgroundColor = function(col)!@#&	curbackground = col!@#&	return env.term.setBackgroundColor(col)!@#&end!@#&!@#&override.term.setBackgroundColour = function(col) return override.term.setBackgroundColor(col) end!@#&!@#&override.term.getTextColor = function() return curtext end!@#&override.term.getTextColour = function() return override.term.getTextColor() end!@#&!@#&override.term.setTextColor = function(col)!@#&	curtext = col!@#&	return env.term.setTextColor(col)!@#&end!@#&!@#&override.term.setTextColour = function(col) return override.term.setTextColor(col) end!@#&!@#&override.term.clear = function()!@#&	local x, y = term.getCursorPos()!@#&	local oldbackground = override.term.getBackgroundColor()!@#&	local oldtext = override.term.getTextColor()!@#&	clear(website, curbackground)!@#&!@#&	term.setBackgroundColor(oldbackground)!@#&	term.setTextColor(oldtext)!@#&	term.setCursorPos(x, y)!@#&end!@#&!@#&override.term.scroll = function(n)!@#&	local x, y = term.getCursorPos()!@#&	local oldbackground = override.term.getBackgroundColor()!@#&	local oldtext = override.term.getTextColor()!@#&!@#&	env.term.scroll(n)!@#&	clear(website, curbackground, true)!@#&	term.setBackgroundColor(oldbackground)!@#&	term.setTextColor(oldtext)!@#&	term.setCursorPos(x, y)!@#&end!@#&!@#&override.term.isColor = function() return isAdvanced() end!@#&override.term.isColour = function() return override.term.isColor() end!@#&!@#&override.os.queueEvent = function(event, ...)!@#&	if event == \"terminate\" or event == event_exit then return end!@#&	if event == event_error and not websiteerror then return end!@#&	env.os.queueEvent(event, ...)!@#&end!@#&!@#&override.prompt = function(list, dir)!@#&	local a = {}!@#&	for k, v in pairs(list) do!@#&		table.insert(a, {v[1], v[2], v[3] + 1, tc = v.tc or curtext,!@#&			bg = v.bg or curbackground, coffset = 1})!@#&	end!@#&	return env.prompt(a, dir)!@#&end!@#&!@#&override.scrollingPrompt = function(list, x, y, len, width)!@#&	return env.scrollingPrompt(list, x, y + 1, len, width, 1)!@#&end!@#&!@#&local barTerm = {}!@#&for k, v in pairs(override.term) do barTerm[k] = v end!@#&barTerm.clear = override.term.clear!@#&barTerm.scroll = override.term.scroll!@#&!@#&local safeTerm = {}!@#&for k, v in pairs(term) do safeTerm[k] = v end!@#&!@#&override.showBar = function()!@#&	offsetclick, clickableAddressBar = true, true!@#&	return os.pullEvent, barTerm!@#&end!@#&!@#&override.hideBar = function()!@#&	offsetclick, clickableAddressBar = false, false!@#&	return os.pullEvent, safeTerm!@#&end!@#&!@#&setfenv(api.saveFileToUserComputer, override)!@#&!@#&!@#&--  -------- Antivirus!@#&!@#&local antivirusOverrides = {!@#&	[\"Run Files\"] = {\"shell.run\", \"os.run\"},!@#&	[\"Modify System\"] = {\"shell.setAlias\", \"shell.clearAlias\", \"os.setComputerLabel\", !@#&		\"shell.setDir\", \"shell.setPath\"},!@#&	[\"Modify Files\"] = {\"fs.makeDir\", \"fs.move\", \"fs.copy\", \"fs.delete\", \"fs.open\",!@#&		\"io.open\", \"io.write\", \"io.read\", \"io.close\"},!@#&	[\"Shutdown Computer\"] = {\"os.shutdown\", \"os.reboot\", \"shell.exit\"}!@#&}!@#&!@#&local antivirusDestroy = {!@#&	\"rawset\", \"rawget\", \"setfenv\", \"loadfile\", \"loadstring\", \"dofile\", \"getfenv\"!@#&}!@#&!@#&local function triggerAntivirus(offence, onlyCancel)!@#&	local oldback, oldtext = curbackground, curtext!@#&	local ox, oy = term.getCursorPos()!@#&	openAddressBar = false!@#&	term.setBackgroundColor(colors[theme[\"address-bar-background\"]])!@#&	term.setTextColor(colors[theme[\"address-bar-text\"]])!@#&	term.setCursorPos(2, 1)!@#&	term.clearLine()!@#&	write(\"Request: \" .. offence)!@#&	term.setCursorPos(w - 8, 1)!@#&	write(\"[C]ancel\")!@#&	if not onlyCancel then!@#&		term.setCursorPos(w - 16, 1)!@#&		write(\"[A]llow\")!@#&	end!@#&!@#&	offsetclick = false!@#&	local stat = \"\"!@#&	while true do!@#&		local e, but, x, y = env.os.pullEvent()!@#&		if e == \"mouse_click\" and y == 1 then!@#&			if x >= w - 8 and x <= w - 1 then stat = \"cancel\"!@#&			elseif not onlyCancel and x >= w - 16 and x <= w - 9 then stat = \"allow\" end!@#&		elseif e == \"char\" and but == \"c\" then stat = \"cancel\"!@#&		elseif e == \"char\" and not onlyCancel and but == \"a\" then stat = \"allow\" end!@#&		if stat ~= \"\" then break end!@#&	end!@#&	offsetclick = true!@#&!@#&	clear(website, nil, true)!@#&	term.setTextColor(colors.white)!@#&	term.setBackgroundColor(colors.black)!@#&	term.setCursorPos(ox, oy)!@#&	term.setBackgroundColor(oldback)!@#&	term.setTextColor(oldtext)!@#&	if not onlyCancel and stat == \"allow\" then!@#&		-- To prevent the menu bar from opening!@#&		os.queueEvent(\"firewolf_requiredEvent\")!@#&		os.pullEvent()!@#&!@#&		openAddressBar = true!@#&		return true!@#&	elseif stat == \"cancel\" then!@#&		openAddressBar = true!@#&		redirect(\"home\")!@#&	end!@#&end!@#&!@#&for k, v in pairs(override) do antivirus[k] = v end!@#&!@#&antivirus.shell = {}!@#&for k, v in pairs(override.shell) do antivirus.shell[k] = v end!@#&antivirus.os = {}!@#&for k, v in pairs(override.os) do antivirus.os[k] = v end!@#&antivirus.fs = {}!@#&for k, v in pairs(override.fs) do antivirus.fs[k] = v end!@#&antivirus.io = {}!@#&for k, v in pairs(override.io) do antivirus.io[k] = v end!@#&!@#&for warning, v in pairs(antivirusOverrides) do!@#&	for k, func in pairs(v) do!@#&		if func:find(\".\", 1, true) then!@#&			-- Functions in another table!@#&			local table = func:sub(1, func:find(\".\", 1, true) - 1)!@#&			local funcname = func:sub(func:find(\".\", 1, true) + 1, -1)!@#&!@#&			antivirus[table][funcname] = function(...)!@#&				env.setfenv(triggerAntivirus, env)!@#&				if triggerAntivirus(warning) then!@#&					return override[table][funcname](...)!@#&				end!@#&			end!@#&		else!@#&			-- Plain functions!@#&			antivirus[func] = function(...)!@#&				env.setfenv(triggerAntivirus, env)!@#&				if triggerAntivirus(warning) then!@#&					return override[func](...)!@#&				end!@#&			end!@#&		end!@#&	end!@#&end!@#&!@#&for k, v in pairs(antivirusDestroy) do!@#&	antivirus[v] = function(...)!@#&		env.setfenv(triggerAntivirus, env)!@#&		triggerAntivirus(\"Destory your System! D:\", true)!@#&		return nil!@#&	end!@#&end!@#&!@#&antivirus.pcall = function(...)!@#&	local suc, err = env.pcall(...)!@#&	if err:lower():find(\"terminate\") then error(\"terminate\") end!@#&	return suc, err!@#&end!@#&!@#&!@#&--  -------- Themes!@#&!@#&local defaultTheme = {!@#&	[\"address-bar-text\"] = \"white\",!@#&	[\"address-bar-background\"] = \"gray\",!@#&	[\"address-bar-base\"] = \"lightGray\",!@#&	[\"top-box\"] = \"red\",!@#&	[\"bottom-box\"] = \"orange\",!@#&	[\"text-color\"] = \"white\",!@#&	[\"background\"] = \"gray\"!@#&} local originalTheme = {!@#&	[\"address-bar-text\"] = \"white\",!@#&	[\"address-bar-background\"] = \"black\",!@#&	[\"address-bar-base\"] = \"black\",!@#&	[\"top-box\"] = \"black\",!@#&	[\"bottom-box\"] = \"black\",!@#&	[\"text-color\"] = \"white\",!@#&	[\"background\"] = \"black\"!@#&}!@#&!@#&local function loadTheme(path)!@#&	if fs.exists(path) and not fs.isDir(path) then!@#&		local a = {}!@#&		local f = io.open(path, \"r\")!@#&		local l = f:read(\"*l\")!@#&		while l do!@#&			l = l:gsub(\"^%s*(.-)%s*$\", \"%1\")!@#&			if l and l ~= \"\" and l ~= \"\\n\" and l:sub(1, 2) ~= \"--\" then!@#&				local k, v = string.match(l, \"^(%a+)=(%a+)\")!@#&				if k and v then a[k] = v!@#&				else return nil end!@#&			end!@#&			l = f:read(\"*l\")!@#&		end!@#&		f:close()!@#&		return a!@#&	end!@#&	return nil!@#&end!@#&!@#&!@#&--  -------- Filesystem!@#&!@#&local function download(url, path)!@#&	for i = 1, 3 do!@#&		local response = http.get(url)!@#&		if response then!@#&			local data = response.readAll()!@#&			response.close()!@#&			if path then!@#&				local f = io.open(path, \"w\")!@#&				f:write(data)!@#&				f:close()!@#&			end!@#&			return true!@#&		end!@#&	end!@#&!@#&	return false!@#&end!@#&!@#&local function updateClient()!@#&	local skipNormal = false!@#&	if serverID ~= \"experimental\" then!@#&		http.request(buildURL)!@#&		local a = os.startTimer(10)!@#&		while true do!@#&			local e, url, handle = os.pullEvent()!@#&			if e == \"http_success\" then!@#&				local b = handle.readAll():gsub(\"^%s*(.-)%s*$\", \"%1\")!@#&				if not tonumber(b) or tonumber(b) > build then break!@#&				else return false end!@#&			elseif e == \"http_failure\" or (e == \"timer\" and url == a) then!@#&				skipNormal = true!@#&				break!@#&			end!@#&		end!@#&	end!@#&!@#&	local source = nil!@#&	if not skipNormal then!@#&		local _, y = term.getCursorPos()!@#&		term.setCursorPos(1, y - 2)!@#&		rightWrite(string.rep(\" \", 32))!@#&		rightWrite(\"Updating Firewolf... \")!@#&!@#&		http.request(firewolfURL)!@#&		local a = os.startTimer(10)!@#&		while true do!@#&			local e, url, handle = os.pullEvent()!@#&			if e == \"http_success\" then!@#&				source = handle!@#&				break!@#&			elseif e == \"http_failure\" or (e == \"timer\" and url == a) then!@#&				break!@#&			end!@#&		end!@#&	end!@#&!@#&	if not source then!@#&		if isAdvanced() then!@#&			term.setTextColor(colors[theme[\"text-color\"]])!@#&			term.setBackgroundColor(colors[theme[\"background\"]])!@#&			term.clear()!@#&			if not fs.exists(rootFolder) then fs.makeDir(rootFolder) end!@#&			local f = io.open(rootFolder .. \"/temp_file\", \"w\")!@#&			f:write(graphics.githubImage)!@#&			f:close()!@#&			local a = paintutils.loadImage(rootFolder .. \"/temp_file\")!@#&			paintutils.drawImage(a, 5, 5)!@#&			sleep(0.2)!@#&			fs.delete(rootFolder .. \"/temp_file\")!@#&!@#&			term.setCursorPos(19, 4)!@#&			term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&			write(string.rep(\" \", 32))!@#&			term.setCursorPos(19, 5)!@#&			write(\"  Could Not Connect to GitHub!  \")!@#&			term.setCursorPos(19, 6)!@#&			write(string.rep(\" \", 32))!@#&			term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&			term.setCursorPos(19, 8)!@#&			write(string.rep(\" \", 32))!@#&			term.setCursorPos(19, 9)!@#&			write(\"    Sorry, Firewolf could not   \")!@#&			term.setCursorPos(19, 10)!@#&			write(\" connect to GitHub to download  \")!@#&			term.setCursorPos(19, 11)!@#&			write(\" necessary files. Please check: \")!@#&			term.setCursorPos(19, 12)!@#&			write(\"    http://status.github.com    \")!@#&			term.setCursorPos(19, 13)!@#&			write(string.rep(\" \", 32))!@#&			term.setCursorPos(19, 14)!@#&			write(\"        Click to exit...        \")!@#&			term.setCursorPos(19, 15)!@#&			write(string.rep(\" \", 32))!@#&		else!@#&			term.clear()!@#&			term.setCursorPos(1, 1)!@#&			term.setBackgroundColor(colors.black)!@#&			term.setTextColor(colors.white)!@#&			print(\"\\n\")!@#&			centerPrint(\"Could not connect to GitHub!\")!@#&			print(\"\")!@#&			centerPrint(\"Sorry, Firewolf could not connect to\")!@#&			centerPrint(\"GitHub to download necessary files.\")!@#&			centerPrint(\"Please check:\")!@#&			centerPrint(\"http://status.github.com\")!@#&			print(\"\")!@#&			centerPrint(\"Press any key to exit...\")!@#&		end!@#&!@#&		while true do!@#&			local e = os.pullEvent()!@#&			if e == \"mouse_click\" or e == \"key\" then break end!@#&		end!@#&!@#&		return false!@#&	elseif source and autoupdate == \"true\" then!@#&		local b = io.open(firewolfLocation, \"r\")!@#&		local new = source.readAll()!@#&		local cur = b:read(\"*a\")!@#&		source.close()!@#&		b:close()!@#&!@#&		if cur ~= new then!@#&			fs.delete(firewolfLocation)!@#&			local f = io.open(firewolfLocation, \"w\")!@#&			f:write(new)!@#&			f:close()!@#&			return true!@#&		else!@#&			return false!@#&		end!@#&	end!@#&end!@#&!@#&local function resetFilesystem()!@#&	-- Migrate!@#&	fs.delete(rootFolder .. \"/available_themes\")!@#&	fs.delete(rootFolder .. \"/default_theme\")!@#&!@#&	-- Reset!@#&	if not fs.exists(rootFolder) then fs.makeDir(rootFolder)!@#&	elseif not fs.isDir(rootFolder) then fs.move(rootFolder, \"/Firewolf_Data.old\") end!@#&!@#&	for _, v in pairs({serverFolder, cacheFolder, websiteDataFolder}) do!@#&		if not fs.isDir(v) then fs.delete(v) end!@#&		if not fs.exists(v) then fs.makeDir(v) end!@#&	end!@#&!@#&	if fs.isDir(settingsLocation) then fs.delete(settingsLocation) end!@#&	if fs.isDir(serverLocation) then fs.delete(serverLocation) end!@#&!@#&	if not fs.exists(settingsLocation) then!@#&		local f = io.open(settingsLocation, \"w\")!@#&		f:write(textutils.serialize({auto = \"true\", incog = \"false\", home = \"firewolf\"}))!@#&		f:close()!@#&	end!@#&!@#&	if not fs.exists(serverLocation) then download(serverURL, serverLocation) end!@#&	fs.delete(rootFolder .. \"/temp_file\")!@#&!@#&	for _, v in pairs({userWhitelist, userBlacklist}) do!@#&		if fs.isDir(v) then fs.delete(v) end!@#&		if not fs.exists(v) then!@#&			local f = io.open(v, \"w\")!@#&			f:write(\"\")!@#&			f:close()!@#&		end!@#&	end!@#&end!@#&!@#&local function checkForModem(display)!@#&	while true do!@#&		local present = false!@#&		for _, v in pairs(rs.getSides()) do!@#&			if peripheral.getType(v) == \"modem\" then rednet.open(v) present = true break end!@#&		end!@#&!@#&		if not present and type(display) == \"function\" then display() os.pullEvent(\"peripheral\")!@#&		else return true end!@#&	end!@#&end!@#&!@#&!@#&--  -------- Databases!@#&!@#&local function loadDatabases()!@#&	if fs.exists(userBlacklist) and not fs.isDir(userBlacklist) then!@#&		local bf = io.open(userBlacklist, \"r\")!@#&		local l = bf:read(\"*l\")!@#&		while l do!@#&			if l and l ~= \"\" and l ~= \"\\n\" then!@#&				l = l:gsub(\"^%s*(.-)%s*$\", \"%1\")!@#&				table.insert(blacklist, l)!@#&			end!@#&			l = bf:read(\"*l\")!@#&		end!@#&		bf:close()!@#&	end!@#&!@#&	if fs.exists(userWhitelist) and not fs.isDir(userWhitelist) then!@#&		local wf = io.open(userWhitelist, \"r\")!@#&		local l = wf:read(\"*l\")!@#&		while l do!@#&			if l and l ~= \"\" and l ~= \"\\n\" then!@#&				l = l:gsub(\"^%s*(.-)%s*$\", \"%1\")!@#&				local a, b = l:find(\"| |\")!@#&				table.insert(whitelist, {l:sub(1, a - 1), l:sub(b + 1, -1)})!@#&			end!@#&			l = wf:read(\"*l\")!@#&		end!@#&		wf:close()!@#&	end!@#&end!@#&!@#&local function verifyBlacklist(id)!@#&	for _, v in pairs(blacklist) do if tostring(id) == v then return true end end!@#&	return false!@#&end!@#&!@#&local function verifyWhitelist(id, url)!@#&	for _, v in pairs(whitelist) do!@#&		if v[2] == tostring(id) and v[1] == tostring(url) then return true end!@#&	end!@#&	return false!@#&end!@#&!@#&!@#&--  -------- Graphics and Files!@#&!@#&graphics.githubImage = [[!@#&f       f!@#&fffffffff!@#&fffffffff!@#&f4244424f!@#&f4444444f!@#&fffffefffe!@#&   fffe e!@#& fffff e!@#&ff f fe e!@#&     e   e!@#&]]!@#&!@#&graphics.nomodem = function()!@#&	term.setTextColor(colors[theme[\"text-color\"]])!@#&	term.setBackgroundColor(colors[theme[\"background\"]])!@#&	term.clear()!@#&	term.setCursorPos(1, 1)!@#&	print(\"\\n\")!@#&	term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&	api.leftPrint(string.rep(\" \", 24))!@#&	api.leftPrint(\" No Modem Attached! D:  \")!@#&	api.leftPrint(string.rep(\" \", 24))!@#&	print(\"\\n\")!@#&!@#&	term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&	api.rightPrint(string.rep(\" \", 40))!@#&	api.rightPrint(\"    No wireless modem was found on this \")!@#&	api.rightPrint(\"  computer, and Firewolf cannot use the \")!@#&	api.rightPrint(\"             RDNT protocol without one! \")!@#&	api.rightPrint(string.rep(\" \", 40))!@#&	api.rightPrint(\"  Waiting for a modem to be attached... \")!@#&	api.rightPrint(string.rep(\" \", 40))!@#&end!@#&!@#&graphics.nonexistantwebpage = function()!@#&	term.setBackgroundColor(colors[theme[\"background\"]])!@#&	term.clear()!@#&	term.setCursorPos(1, 2)!@#&	term.setTextColor(colors[theme[\"text-color\"]])!@#&	term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&	leftPrint(string.rep(\" \", 11))!@#&	leftPrint(\" Oh Noes!  \")!@#&	leftPrint(string.rep(\" \", 11))!@#&	print(\"\\n\")!@#&!@#&	term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&	rightPrint(string.rep(\" \", 43))!@#&	rightPrint([[       ______                          __  ]])!@#&	rightPrint([[      / ____/_____ _____ ____   _____ / /  ]])!@#&	rightPrint([[     / __/  / ___// ___// __ \\ / ___// /   ]])!@#&	rightPrint([[    / /___ / /   / /   / /_/ // /   /_/    ]])!@#&	rightPrint([[   /_____//_/   /_/    \\____//_/   (_)     ]])!@#&	rightPrint(string.rep(\" \", 43))!@#&	rightPrint(\"  Could not connect to the website! It may \")!@#&	rightPrint(\"  be down, or not exist!                   \")!@#&	rightPrint(string.rep(\" \", 43))!@#&end!@#&!@#&graphics.nosearchresults = function()!@#&	term.setBackgroundColor(colors[theme[\"background\"]])!@#&	term.clear()!@#&	term.setCursorPos(1, 5)!@#&	term.setTextColor(colors[theme[\"text-color\"]])!@#&	term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&	centerPrint(string.rep(\" \", 40))!@#&	centerPrint(\"  No Websites are Currently Online! D:  \")!@#&	centerPrint(string.rep(\" \", 40))!@#&	centerPrint(\"       Why not make one yourself?       \")!@#&	centerPrint(\"          Visit rdnt://server!          \")!@#&	centerPrint(string.rep(\" \", 40))!@#&end!@#&!@#&files.availableThemes = [[!@#&https://raw.github.com/1lann/firewolf/master/themes/default.txt| |Fire (default)!@#&https://raw.github.com/1lann/firewolf/master/themes/ice.txt| |Ice!@#&https://raw.github.com/1lann/firewolf/master/themes/carbon.txt| |Carbon!@#&https://raw.github.com/1lann/firewolf/master/themes/christmas.txt| |Christmas!@#&https://raw.github.com/1lann/firewolf/master/themes/original.txt| |Original!@#&https://raw.github.com/1lann/firewolf/master/themes/ocean.txt| |Ocean!@#&https://raw.github.com/1lann/firewolf/master/themes/forest.txt| |Forest!@#&https://raw.github.com/1lann/firewolf/master/themes/pinky.txt| |Pinky!@#&https://raw.github.com/1lann/firewolf/master/themes/azhftech.txt| |AzhfTech!@#&]]!@#&!@#&files.newTheme = [[!@#&-- Address bar text color!@#&address-bar-text=!@#&!@#&-- Address bar background color!@#&address-bar-background=!@#&!@#&-- Color of separator bar on live search dropdown!@#&address-bar-base=!@#&!@#&-- Top box background color!@#&top-box=!@#&!@#&-- Bottom box background color!@#&bottom-box=!@#&!@#&-- Main background color!@#&background=!@#&!@#&-- Main text color!@#&text-color=!@#&!@#&]]!@#&!@#&!@#&--  -------- Protocols!@#&!@#&protocols.rdnt = {}!@#&protocols.http = {}!@#&!@#&protocols.rdnt.getSearchResults = function()!@#&	dnsDatabase = {[1] = {}, [2] = {}}!@#&	local resultIDs = {}!@#&	local conflict = {}!@#&!@#&	rednet.broadcast(\"firewolf.broadcast.dns.list\")!@#&	local startClock = os.clock()!@#&	while os.clock() - startClock < timeout do!@#&		local id, i = rednet.receive(timeout)!@#&		if id then!@#&			if i:sub(1, 14) == \"firewolf-site:\" then!@#&				i = i:sub(15, -1)!@#&				local bl, wl = verifyBlacklist(id), verifyWhitelist(id, i)!@#&				if not i:find(\" \") and i:len() < 40 and (not bl or (bl and wl)) then!@#&					if not resultIDs[tostring(id)] then resultIDs[tostring(id)] = 1!@#&					else resultIDs[tostring(id)] = resultIDs[tostring(id)] + 1 end!@#&					!@#&					if not i:find(\"rdnt://\") then i = (\"rdnt://\" .. i) end!@#&					local x = false!@#&					if conflict[i] then!@#&						x = true!@#&						table.insert(conflict[i], id)!@#&					else!@#&						for m, n in pairs(dnsDatabase[1]) do!@#&							if n:lower() == i:lower() then!@#&								x = true!@#&								table.remove(dnsDatabase[1], m)!@#&								table.remove(dnsDatabase[2], m)!@#&								if conflict[i] then table.insert(conflict[i], id)!@#&								else conflict[i] = {} table.insert(conflict[i], id) end!@#&								break!@#&							end!@#&						end!@#&					end!@#&!@#&					if not x and resultIDs[tostring(id)] <= 3 then!@#&						table.insert(dnsDatabase[1], i)!@#&						table.insert(dnsDatabase[2], id)!@#&					end!@#&				end!@#&			end!@#&		else break end!@#&	end!@#&!@#&	for k, v in pairs(conflict) do!@#&		table.sort(v)!@#&		table.insert(dnsDatabase[1], k)!@#&		table.insert(dnsDatabase[2], v[1])!@#&	end!@#&end!@#&!@#&protocols.rdnt.getWebsite = function(site)!@#&	local id, content, status = nil, nil, nil!@#&	local clock = os.clock()!@#&	local websiteID = nil!@#&	for k, v in pairs(dnsDatabase[1]) do!@#&		local web = site:gsub(\"rdnt://\", \"\")!@#&		if web:find(\"/\") then web = web:sub(1, web:find(\"/\") - 1) end!@#&		if web == v:gsub(\"rdnt://\", \"\") then websiteID = dnsDatabase[2][k] break end!@#&	end!@#&	if not websiteID then return nil, nil, nil end!@#&!@#&	sleep(timeout)!@#&	rednet.send(websiteID, site)!@#&	clock = os.clock()!@#&	while os.clock() - clock < timeout do!@#&		id, content = rednet.receive(timeout)!@#&		if id and id == websiteID then!@#&			local bl, wl = verifyBlacklist(id), verifyWhitelist(id, site)!@#&			status = nil!@#&			if (bl and not wl) or site == \"\" or site == \".\" or site == \"..\" then!@#&				-- Ignore!@#&			elseif wl then status = \"whitelist\" break!@#&			else status = \"safe\" break end!@#&		end!@#&	end!@#&!@#&	return id, content, status!@#&end!@#&!@#&protocols.http.getSearchResults = function()!@#&	dnsDatabase = {[1] = {}, [2] = {}}!@#&end!@#&!@#&protocols.http.getWebsite = function(site)!@#&	return nil, nil, nil!@#&end!@#&!@#&!@#&--  -------- Homepage!@#&!@#&pages[\"firewolf\"] = function()!@#&	term.setBackgroundColor(colors[theme[\"background\"]])!@#&	term.clear()!@#&	term.setTextColor(colors[theme[\"text-color\"]])!@#&	term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&	print(\"\")!@#&	leftPrint(string.rep(\" \", 42))!@#&	leftPrint([[        _,-='\"-.__               /\\_/\\    ]])!@#&	leftPrint([[         -.}        =._,.-==-._.,  @ @._, ]])!@#&	leftPrint([[            -.__  __,-.   )       _,.-'   ]])!@#&	leftPrint([[ Firewolf ]] .. version .. string.rep(\" \", 8 - version:len()) ..!@#&		[[\"    G..m-\"^m m'        ]])!@#&	leftPrint(string.rep(\" \", 42))!@#&	print(\"\\n\")!@#&!@#&	term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&	rightPrint(string.rep(\" \", 42))!@#&	if isAdvanced() then rightPrint(\"  News:                       [- Sites -] \")!@#&	else rightPrint(\"  News:                                   \") end!@#&	rightPrint(\"     Firewolf 2.5 is out! It rewrites the \")!@#&	rightPrint(\"    whole Firewolf's internals (again :P) \")!@#&	rightPrint(string.rep(\" \", 42))!@#&	rightPrint(\"   Firewolf 3.0 will be out soon! It will \")!@#&	rightPrint(\"     bring the long awaited HTTP support! \")!@#&	rightPrint(string.rep(\" \", 42))!@#&!@#&	while true do!@#&		local e, but, x, y = os.pullEvent()!@#&		if e == \"mouse_click\" and x >= 40 and x <= 50 and y == 11 then redirect(\"sites\") end!@#&	end!@#&end!@#&!@#&pages[\"sites\"] = function()!@#&	term.setBackgroundColor(colors[theme[\"background\"]])!@#&	term.clear()!@#&	term.setTextColor(colors[theme[\"text-color\"]])!@#&	term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&	print(\"\\n\")!@#&	leftPrint(string.rep(\" \", 17))!@#&	leftPrint(\" Built-In Sites  \")!@#&	leftPrint(string.rep(\" \", 17))!@#&!@#&	local sx = 8!@#&	term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&	term.setCursorPos(1, sx)!@#&	rightPrint(string.rep(\" \", 40))!@#&	rightPrint(\"  rdnt://firewolf              Homepage \")!@#&	rightPrint(\"  rdnt://sites                    Sites \")!@#&	rightPrint(\"  rdnt://server       Server Management \")!@#&	rightPrint(\"  rdnt://help                 Help Page \")!@#&	rightPrint(\"  rdnt://settings              Settings \")!@#&	rightPrint(\"  rdnt://credits                Credits \")!@#&	rightPrint(\"  rdnt://exit                      Exit \")!@#&	rightPrint(string.rep(\" \", 40))!@#&!@#&	local a = {\"firewolf\", \"sites\", \"server\", \"help\", \"settings\", \"credits\", \"exit\"}!@#&	while true do!@#&		local e, but, x, y = os.pullEvent()!@#&		if e == \"mouse_click\" and x >= 14 and x <= 50 then!@#&			for i, v in ipairs(a) do if y == sx + i and v ~= \"exit\" then redirect(v) end end!@#&		end!@#&	end!@#&end!@#&!@#&!@#&--  -------- Server Management!@#&!@#&local function manageServers(site, protocol, functionList, startServerName)!@#&	local servers = functionList[\"reload servers\"]()!@#&	local sy = 7!@#&!@#&	if not startServerName then startServerName = \"Start\" end!@#&	if isAdvanced() then!@#&		local function draw(l, sel)!@#&			term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&			term.setCursorPos(4, sy)!@#&			write(\"[- New Server -]\")!@#&			for i, v in ipairs(l) do!@#&				term.setCursorPos(3, i + sy)!@#&				write(string.rep(\" \", 24))!@#&				term.setCursorPos(4, i + sy)!@#&				local nv = v!@#&				if nv:len() > 18 then nv = nv:sub(1, 15) .. \"...\" end!@#&				if i == sel then write(\"[ \" .. nv .. \" ]\")!@#&				else write(\"  \" .. nv) end!@#&			end!@#&!@#&			if #l < 1 then!@#&				term.setCursorPos(4, sy + 2)!@#&				write(\"A website is literally\")!@#&				term.setCursorPos(4, sy + 3)!@#&				write(\"just a lua script!\")!@#&				term.setCursorPos(4, sy + 4)!@#&				write(\"Go ahead and make one!\")!@#&				term.setCursorPos(4, sy + 6)!@#&				write(\"Also, be sure to check\")!@#&				term.setCursorPos(4, sy + 7)!@#&				write(\"out Firewolf's APIs to\")!@#&				term.setCursorPos(4, sy + 8)!@#&				write(\"help you make your\")!@#&				term.setCursorPos(4, sy + 9)!@#&				write(\"site, at rdnt://help\")!@#&			end!@#&!@#&			term.setCursorPos(30, sy)!@#&			write(string.rep(\" \", 19))!@#&			term.setCursorPos(30, sy)!@#&			if l[sel] then!@#&				local nl = l[sel]!@#&				if nl:len() > 19 then nl = nl:sub(1, 16) .. \"...\" end!@#&				write(nl)!@#&			else write(\"No Server Selected!\") end!@#&			term.setCursorPos(30, sy + 2)!@#&			write(\"[- \" .. startServerName .. \" -]\")!@#&			term.setCursorPos(30, sy + 4)!@#&			write(\"[- Edit -]\")!@#&			term.setCursorPos(30, sy + 6)!@#&			if functionList[\"run on boot\"] then write(\"[- Run on Boot -]\") end!@#&			term.setCursorPos(30, sy + 8)!@#&			write(\"[- Delete -]\")!@#&		end!@#&!@#&		local function updateDisplayList(items, loc, len)!@#&			local ret = {}!@#&			for i = 1, len do!@#&				if items[i + loc - 1] then table.insert(ret, items[i + loc - 1]) end!@#&			end!@#&			return ret!@#&		end!@#&!@#&		while true do!@#&			term.setBackgroundColor(colors[theme[\"background\"]])!@#&			term.clear()!@#&			term.setCursorPos(1, 1)!@#&			term.setTextColor(colors[theme[\"text-color\"]])!@#&			term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&			print(\"\")!@#&			leftPrint(string.rep(\" \", 27))!@#&			leftPrint(\" Server Management - \" .. protocol:upper() .. \"  \")!@#&			leftPrint(string.rep(\" \", 27))!@#&			print(\"\")!@#&!@#&			term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&			for i = 1, 12 do!@#&				term.setCursorPos(3, i + sy - 2)!@#&				write(string.rep(\" \", 24))!@#&				term.setCursorPos(29, i + sy - 2)!@#&				write(string.rep(\" \", 21))!@#&			end!@#&!@#&			local sel, loc, len = 1, 1, 10!@#&			local disList = updateDisplayList(servers, loc, len)!@#&			draw(disList, sel)!@#&!@#&			while true do!@#&				local e, but, x, y = os.pullEvent()!@#&				if e == \"key\" and but == 200 and #servers > 0 and loc > 1 then!@#&					loc = loc - 1!@#&					disList = updateDisplayList(servers, loc, len)!@#&					draw(disList, sel)!@#&				elseif e == \"key\" and but == 208 and #servers > 0 and loc + len - 1 < #servers then!@#&					loc = loc + 1!@#&					disList = updateDisplayList(servers, loc, len)!@#&					draw(disList, sel)!@#&				elseif e == \"mouse_click\" then!@#&					if x >= 4 and x <= 25 then!@#&						if y == 7 then!@#&							functionList[\"new server\"]()!@#&							servers = functionList[\"reload servers\"]()!@#&							break!@#&						elseif #servers > 0 then!@#&							for i, v in ipairs(disList) do!@#&								if y == i + 7 then!@#&									sel = i!@#&									draw(disList, sel)!@#&								end!@#&							end!@#&						end!@#&					elseif x >= 30 and x <= 40 and y == 9 and #servers > 0 then!@#&						functionList[\"start\"](disList[sel])!@#&						servers = functionList[\"reload servers\"]()!@#&						break!@#&					elseif x >= 30 and x <= 39 and y == 11 and #servers > 0 then!@#&						functionList[\"edit\"](disList[sel])!@#&						servers = functionList[\"reload servers\"]()!@#&						break!@#&					elseif x >= 30 and x <= 46 and y == 13 and #servers > 0 and!@#&							functionList[\"run on boot\"] then!@#&						functionList[\"run on boot\"](disList[sel])!@#&						term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&						term.setCursorPos(32, 15)!@#&						write(\"Will Run on Boot!\")!@#&						openAddressBar = false!@#&						sleep(1.3)!@#&						openAddressBar = true!@#&						term.setCursorPos(32, 15)!@#&						write(string.rep(\" \", 18))!@#&						break!@#&					elseif x >= 30 and x <= 41 and y == 15 and #servers > 0 then!@#&						functionList[\"delete\"](disList[sel])!@#&						servers = functionList[\"reload servers\"]()!@#&						break!@#&					end!@#&				end!@#&			end!@#&		end!@#&	else!@#&		while true do!@#&			term.setBackgroundColor(colors[theme[\"background\"]])!@#&			term.clear()!@#&			term.setCursorPos(1, 1)!@#&			term.setTextColor(colors[theme[\"text-color\"]])!@#&			term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&			print(\"\")!@#&			centerPrint(string.rep(\" \", 27))!@#&			centerPrint(\" Server Management - \" .. protocol:upper() .. \"  \")!@#&			centerPrint(string.rep(\" \", 27))!@#&			print(\"\")!@#&!@#&			local a = {\"New Server\"}!@#&			for _, v in pairs(servers) do table.insert(a, v) end!@#&			local server = scrollingPrompt(a, 4, 7, 10)!@#&			if server == \"New Server\" then!@#&				functionList[\"new server\"]()!@#&				servers = functionList[\"reload servers\"]()!@#&			else!@#&				term.setCursorPos(30, 8)!@#&				write(server)!@#&				local a = {{\"Start\", 30, 9}, {\"Edit\", 30, 11}, {\"Run on Boot\", 30, 12},!@#&					{\"Delete\", 30, 13}, {\"Back\", 30, 15}}!@#&				if not functionList[\"run on boot\"] then!@#&					a = {{\"Start\", 30, 9}, {\"Edit\", 30, 11}, {\"Delete\", 30, 13}, {\"Back\", 30, 15}}!@#&				end!@#&				local opt = prompt(a, \"vertical\")!@#&				if opt == \"Start\" then!@#&					functionList[\"start\"](server)!@#&					servers = functionList[\"reload servers\"]()!@#&				elseif opt == \"Edit\" then!@#&					functionList[\"edit\"](server)!@#&					servers = functionList[\"reload servers\"](server)!@#&				elseif opt == \"Run on Boot\" and functionList[\"run on boot\"] then!@#&					functionList[\"run on boot\"](server)!@#&					term.setCursorPos(32, 16)!@#&					write(\"Will Run on Boot!\")!@#&					openAddressBar = false!@#&					sleep(1.3)!@#&					openAddressBar = true!@#&				elseif opt == \"Delete\" then!@#&					functionList[\"delete\"](server)!@#&					servers = functionList[\"reload servers\"]()!@#&				end!@#&			end!@#&		end!@#&	end!@#&end!@#&!@#&local function editPages(dir)!@#&	local oldLoc = shell.dir()!@#&	local commandHis = {}!@#&	term.setBackgroundColor(colors.black)!@#&	term.setTextColor(colors.white)!@#&	term.clear()!@#&	term.setCursorPos(1, 1)!@#&	print(\"\")!@#&	print(\" Server Shell Editing\")!@#&	print(\" Type 'exit' to return to Firewolf.\")!@#&	print(\" The 'home' file is the index of your site.\")!@#&	print(\"\")!@#&!@#&	local allowed = {\"move\", \"mv\", \"cp\", \"copy\", \"drive\", \"delete\", \"rm\", \"edit\",!@#&		\"eject\", \"exit\", \"help\", \"id\", \"monitor\", \"rename\", \"alias\", \"clear\",!@#&		\"paint\", \"lua\", \"redstone\", \"rs\", \"redprobe\", \"redpulse\", \"programs\",!@#&		\"redset\", \"reboot\", \"hello\", \"label\", \"list\", \"ls\", \"easter\", \"pastebin\", \"dir\"}!@#&	!@#&	while true do!@#&		shell.setDir(dir)!@#&		term.setBackgroundColor(colors.black)!@#&		if isAdvanced() then term.setTextColor(colors.yellow)!@#&		else term.setTextColor(colors.white) end!@#&		write(\"> \")!@#&		term.setTextColor(colors.white)!@#&		local line = read(nil, commandHis)!@#&		table.insert(commandHis, line)!@#&!@#&		local words = {}!@#&		for m in string.gmatch(line, \"[^ \\t]+\") do!@#&			local a = m:gsub(\"^%s*(.-)%s*$\", \"%1\")!@#&			table.insert(words, a)!@#&		end!@#&!@#&		local com = words[1]!@#&		if com == \"exit\" then break!@#&		elseif com then!@#&			local a = false!@#&			for _, v in pairs(allowed) do if com == v then a = true break end end!@#&!@#&			if a then!@#&				term.setBackgroundColor(colors.black)!@#&				term.setTextColor(colors.white)!@#&				shell.run(com, unpack(words, 2))!@#&			else!@#&				term.setTextColor(colors.red)!@#&				print(\"Program Not Allowed!\")!@#&			end!@#&		end!@#&	end!@#&	shell.setDir(oldLoc)!@#&end!@#&!@#&local function newServer(onCreate)!@#&	term.setBackgroundColor(colors[theme[\"background\"]])!@#&	for i = 1, 12 do!@#&		term.setCursorPos(3, i + 5)!@#&		term.clearLine()!@#&	end!@#&!@#&	term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&	term.setCursorPos(1, 7)!@#&	for i = 1, 8 do centerPrint(string.rep(\" \", 47)) end!@#&	term.setCursorPos(5, 8)!@#&	write(\"Name: \")!@#&	local name = modRead({refusePrint = \"`\", visibleLength = w - 4, textLength = 200})!@#&	term.setCursorPos(5, 10)!@#&	write(\"URL:\")!@#&	term.setCursorPos(8, 11)!@#&	write(\"rdnt://\")!@#&	local url = modRead({grantPrint = \"abcdefghijklmnopqrstuvwxyz1234567890-_.+\",!@#&		visibleLength = w - 4, textLength = 200})!@#&	url = url:gsub(\" \", \"\")!@#&	if name == \"\" or url == \"\" then!@#&		term.setCursorPos(5, 13)!@#&		write(\"URL or Name is Empty!\")!@#&		openAddressBar = false!@#&		sleep(1.3)!@#&		openAddressBar = true!@#&	else!@#&		local c = onCreate(name, url)!@#&!@#&		term.setCursorPos(5, 13)!@#&		if c and c == \"true\" then write(\"Successfully Created Server!\")!@#&		elseif c == \"false\" or not c then write(\"Server Creation Failed!\")!@#&		else write(c) end!@#&		openAddressBar = false!@#&		sleep(1.3)!@#&		openAddressBar = true!@#&	end!@#&end!@#&!@#&pages[\"server/rdnt\"] = function(site)!@#&	manageServers(site, \"rdnt\", {[\"reload servers\"] = function()!@#&		local servers = {}!@#&		for _, v in pairs(fs.list(serverFolder)) do!@#&			if fs.isDir(serverFolder .. \"/\" .. v) then table.insert(servers, v) end!@#&		end!@#&		return servers!@#&	end, [\"new server\"] = function()!@#&		newServer(function(name, url)!@#&			if fs.exists(serverFolder .. \"/\" .. url) then return \"Server Already Exists!\" end!@#&			fs.makeDir(serverFolder .. \"/\" .. url)!@#&			local f = io.open(serverFolder .. \"/\" .. url .. \"/home\", \"w\")!@#&			f:write(\"print(\\\"\\\")\\ncenterPrint(\\\"Welcome To \" .. name .. \"!\\\")\\n\\n\")!@#&			f:close()!@#&			return \"true\"!@#&		end)!@#&	end, [\"start\"] = function(server)!@#&		term.clear()!@#&		term.setCursorPos(1, 1)!@#&		term.setBackgroundColor(colors.black)!@#&		term.setTextColor(colors.white)!@#&		openAddressBar, offsetclick = false, false!@#&		setfenv(1, oldEnv)!@#&		shell.run(serverLocation, server, serverFolder .. \"/\" .. server)!@#&		setfenv(1, override)!@#&		openAddressBar, offsetclick = true, true!@#&		checkForModem()!@#&	end, [\"edit\"] = function(server)!@#&		openAddressBar, offsetclick = false, false!@#&		editPages(serverFolder .. \"/\" .. server)!@#&		openAddressBar, offsetclick = true, true!@#&		if not fs.exists(serverFolder .. \"/\" .. server .. \"/home\") then!@#&			local f = io.open(serverFolder .. \"/\" .. server .. \"/home\", \"w\")!@#&			f:write(\"print(\\\"\\\")\\ncenterPrint(\\\"Welcome To \" .. server .. \"!\\\")\\n\\n\")!@#&			f:close()!@#&		end!@#&	end, [\"run on boot\"] = function(server)!@#&		fs.delete(\"/old-startup\")!@#&		if fs.exists(\"/startup\") then fs.move(\"/startup\", \"/old-startup\") end!@#&		local f = io.open(\"/startup\", \"w\")!@#&		f:write(\"shell.run(\\\"\" .. serverLocation .. \"\\\", \\\"\" .. server .. \"\\\", \\\"\" ..!@#&			serverFolder .. \"/\" .. server .. \"\\\")\")!@#&		f:close()!@#&	end, [\"delete\"] = function(server)!@#&		fs.delete(serverFolder .. \"/\" .. server)!@#&	end})!@#&end!@#&!@#&pages[\"server/http\"] = function()!@#&	term.setTextColor(colors[theme[\"text-color\"]])!@#&	term.setBackgroundColor(colors[theme[\"background\"]])!@#&	term.clear()!@#&	print(\"\\n\\n\")!@#&	term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&	centerPrint(string.rep(\" \", 17))!@#&	centerPrint(\"  Comming Soon!  \")!@#&	centerPrint(string.rep(\" \", 17))!@#&end!@#&!@#&pages[\"server\"] = function()!@#&	setfenv(manageServers, override)!@#&	setfenv(newServer, override)!@#&	setfenv(editPages, env)!@#&	if curProtocol == protocols.rdnt then redirect(\"server/rdnt\")!@#&	elseif curProtocol == protocols.http then redirect(\"server/http\") end!@#&end!@#&!@#&!@#&--  -------- Help!@#&!@#&pages[\"help\"] = function()!@#&	term.setBackgroundColor(colors[theme[\"background\"]])!@#&	term.clear()!@#&	term.setTextColor(colors[theme[\"text-color\"]])!@#&	term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&	print(\"\")!@#&	leftPrint(string.rep(\" \", 16))!@#&	leftPrint(\" Firewolf Help  \")!@#&	leftPrint(string.rep(\" \", 16))!@#&	print(\"\\n\")!@#&!@#&	term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&	for i = 1, 11 do rightPrint(string.rep(\" \", 41)) end!@#&	term.setCursorPos(1, 15)!@#&	rightPrint(\"         View the full documentation at: \")!@#&	rightPrint(\"  https://github.com/1lann/Firewolf/wiki \")!@#&!@#&	local opt = prompt({{\"Getting Started\", w - 21, 8}, {\"Making a Theme\", w - 20, 10},!@#&		{\"API Documentation\", w - 23, 12}}, \"vertical\")!@#&	local pages = {}!@#&	if opt == \"Getting Started\" then!@#&		pages[1] = {title = \"Getting Started - Intoduction\", content = {!@#&			\"Hey there!\",!@#&			\"\",!@#&			\"Firewolf is an app that allows you to create\",!@#&			\"and visit websites! Each site has an address\",!@#&			\"(the URL) which you can type into the address\",!@#&			\"bar above, and then visit the site.\",!@#&			\"\",!@#&			\"You can open the address bar by clicking on\",!@#&			\"it, or by pressing control.\"!@#&		}} pages[2] = {title = \"Getting Started - Searching\", content = {!@#&			\"The address bar can be also be used to\",!@#&			\"search for sites, by simply typing in the\",!@#&			\"search term.\",!@#&			\"\",!@#&			\"To view all sites, just open it and hit\",!@#&			\"enter (leave the field blank).\"!@#&		}} pages[3] = {title = \"Getting Started - Built-In Websites\", content = {!@#&			\"Firewolf has a set of built-in websites\",!@#&			\"available for use:\",!@#&			\"\",!@#&			\"rdnt://firewolf   Normal hompage\",!@#&			\"rdnt://sites      Built-In Site\",!@#&			\"rdnt://server     Create websites\",!@#&			\"rdnt://help       Help and documentation\"!@#&		}} pages[4] = {title = \"Getting Started - Built-In Websites\", content = {!@#&			\"More built-in websites:\",!@#&			\"\",!@#&			\"rdnt://settings   Firewolf settings\",!@#&			\"rdnt://credits    View the credits\",!@#&			\"rdnt://exit       Exit the app\"!@#&		}}!@#&	elseif opt == \"Making a Theme\" then!@#&		pages[1] = {title = \"Making a Theme - Introduction\", content = {!@#&			\"Firewolf themes are files that tell Firewolf\",!@#&			\"to color which things what.\",!@#&			\"Several themes can already be downloaded for\",!@#&			\"Firewolf from rdnt://settings/themes.\",!@#&			\"\",!@#&			\"You can also make your own theme, use it in\",!@#&			\"your copy of Firewolf.Your theme can also be\",!@#&			\"submitted it to the themes list!\"!@#&		}} pages[2] = {title = \"Making a Theme - Example\", content = {!@#&			\"A theme file consists of several lines of\",!@#&			\"text. Here is the default theme file:\",!@#&			\"address-bar-text=white\",!@#&			\"address-bar-background=gray\",!@#&			\"address-bar-base=lightGray\",!@#&			\"top-box=red\",!@#&			\"bottom-box=orange\",!@#&			\"background=gray\",!@#&			\"text-color=white\"!@#&		}} pages[3] = {title = \"Making a Theme - Explanation\", content = {!@#&			\"On each line of the example, something is\",!@#&			\"given a color, like on the last line, the\",!@#&			\"text of the page is told to be white.\",!@#&			\"\",!@#&			\"The color specified after the = is the same\",!@#&			\"as when you call colors.[color name].\",!@#&			\"For example, specifying 'red' after the =\",!@#&			\"colors that object red.\"!@#&		}} pages[4] = {title = \"Making a Theme - Have a Go\", content = {!@#&			\"Themes can be made at rdnt://settings/themes,\",!@#&			\"click on 'Change Theme' button, and click on\",!@#&			\"'New Theme'.\",!@#&			\"\",!@#&			\"Enter a theme name, then exit Firewolf and\",!@#&			\"edit the newly created file\",!@#&			\"Specify the colors for each of the keys,\",!@#&			\"and return to the themes section of the\",!@#&			\"downloads center. Click 'Load Theme'.\"!@#&		}} pages[5] = {title = \"Making a Theme - Submitting\", content = {!@#&			\"To submit a theme to the theme list,\",!@#&			\"send GravityScore a message on the CCForums\",!@#&			\"that contains your theme file and name.\",!@#&			\"\",!@#&			\"He will message you back saying whether your\",!@#&			\"theme has been added, or if anything needs to\",!@#&			\"be changed before it is added.\"!@#&		}}!@#&	elseif opt == \"API Documentation\" then!@#&		pages[1] = {title = \"API Documentation - 1\", content = {!@#&			\"The Firewolf API is a bunch of global\",!@#&			\"functions that aim to simplify your life when\",!@#&			\"designing and coding websites.\",!@#&			\"\",!@#&			\"For a full documentation on these functions,\",!@#&			\"visit the Firewolf Wiki Page here:\",!@#&			\"https://github.com/1lann/Firewolf/wiki\"!@#&		}} pages[2] = {title = \"API Documentation - 2\", content = {!@#&			\"centerPrint(string text)\",!@#&			\"cPrint(string text)\",!@#&			\"centerWrite(string text)\",!@#&			\"cWrite(string text)\",!@#&			\"\",!@#&			\"leftPrint(string text)\",!@#&			\"lPrint(string text)\",!@#&		}} pages[3] = {title = \"API Documentation - 3\", content = {!@#&			\"leftWrite(string text)\",!@#&			\"lWrite(string text)\",!@#&			\"\",!@#&			\"rightPrint(string text)\",!@#&			\"rPrint(string text)\",!@#&			\"rightWrite(string text)\",!@#&			\"rWrite(string text)\"!@#&		}} pages[4] = {title = \"API Documentation - 4\", content = {!@#&			\"prompt(table list, string direction)\",!@#&			\"scrollingPrompt(table list, integer x,\",!@#&			\"   integer y, integer length[,\",!@#&			\"   integer width])\",!@#&			\"\",!@#&			\"urlDownload(string url)\",!@#&			\"pastebinDownload(string code)\",!@#&			\"redirect(string site)\",!@#&		}} pages[5] = {title = \"API Documentation - 5\", content = {!@#&			\"loadImageFromServer(string imagePath)\",!@#&			\"ioReadFileFromServer(string filePath)\",!@#&			\"fileFileFromServer(string filePath)\",!@#&			\"saveFileToUserComputer(string content)\",!@#&			\"\",!@#&			\"writeDataFile(string path, string contents)\",!@#&			\"readDataFile(string path)\"!@#&		}} pages[6] = {title = \"API Documentation - 6\", content = {!@#&			\"themeColor(string tag)\",!@#&			\"themeColour(string tag)\"!@#&		}}!@#&	end!@#&!@#&	local function drawPage(page)!@#&		term.setBackgroundColor(colors[theme[\"background\"]])!@#&		term.clear()!@#&		term.setCursorPos(1, 1)!@#&		term.setTextColor(colors[theme[\"text-color\"]])!@#&		term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&		print(\"\")!@#&		leftPrint(string.rep(\" \", page.title:len() + 3))!@#&		leftPrint(\" \" .. page.title .. \"  \")!@#&		leftPrint(string.rep(\" \", page.title:len() + 3))!@#&		print(\"\")!@#&!@#&		term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&		for i = 1, 12 do print(string.rep(\" \", w)) end!@#&		for i, v in ipairs(page.content) do!@#&			term.setCursorPos(4, i + 6)!@#&			write(v)!@#&		end!@#&	end!@#&!@#&	local curPage = 1!@#&	local a = {{\"Prev\", 26, 17}, {\"Next\", 38, 17}, {\"Back\",  14, 17}}!@#&	drawPage(pages[curPage])!@#&	while true do!@#&		local b = {a[3]}!@#&		if curPage == 1 then table.insert(b, a[2])!@#&		elseif curPage == #pages then table.insert(b, a[1])!@#&		else table.insert(b, a[1]) table.insert(b, a[2]) end!@#&!@#&		local opt = prompt(b, \"horizontal\")!@#&		if opt == \"Prev\" then curPage = curPage - 1!@#&		elseif opt == \"Next\" then curPage = curPage + 1!@#&		elseif opt == \"Back\" then break end!@#&		drawPage(pages[curPage])!@#&	end!@#&!@#&	redirect(\"help\")!@#&end!@#&!@#&!@#&--  -------- Settings!@#&!@#&pages[\"settings/themes\"] = function()!@#&	term.setBackgroundColor(colors[theme[\"background\"]])!@#&	term.clear()!@#&	term.setTextColor(colors[theme[\"text-color\"]])!@#&	term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&	print(\"\")!@#&	leftPrint(string.rep(\" \", 17))!@#&	leftPrint(\" Theme Settings  \")!@#&	leftPrint(string.rep(\" \", 17))!@#&	print(\"\")!@#&!@#&	if isAdvanced() then!@#&		term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&		for i = 1, 12 do rightPrint(string.rep(\" \", 36)) end!@#&!@#&		local themes = {}!@#&		local themenames = {\"Back\", \"New Theme\", \"Load Theme\"}!@#&		local f = io.open(rootFolder .. \"/temp_file\", \"w\")!@#&		f:write(files.availableThemes)!@#&		f:close()!@#&		local f = io.open(rootFolder .. \"/temp_file\", \"r\")!@#&		local l = f:read(\"*l\")!@#&		while l do!@#&			l = l:gsub(\"^%s*(.-)%s*$\", \"%1\")!@#&			local a, b = l:find(\"| |\")!@#&			table.insert(themenames, l:sub(b + 1, -1))!@#&			table.insert(themes, {name = l:sub(b + 1, -1), url = l:sub(1, a - 1)})!@#&			l = f:read(\"*l\")!@#&		end!@#&		f:close()!@#&		fs.delete(rootFolder .. \"/temp_file\")!@#&!@#&		local t = scrollingPrompt(themenames, w - 33, 7, 10, 32)!@#&		if t == \"Back\" then redirect(\"settings\")!@#&		elseif t == \"New Theme\" then!@#&			term.setCursorPos(w - 33, 17)!@#&			write(\"Path: /\")!@#&			local n = modRead({visibleLength = w - 2, textLength = 100})!@#&			if n ~= \"\" and n then!@#&				n = \"/\" .. n!@#&				local f = io.open(n, \"w\")!@#&				f:write(files.newTheme)!@#&				f:close()!@#&!@#&				term.setCursorPos(1, 17)!@#&				rightWrite(string.rep(\" \", 36))!@#&				term.setCursorPos(1, 17)!@#&				rightWrite(\"File Created! \")!@#&				openAddressBar = false!@#&				sleep(1.1)!@#&				openAddressBar = true!@#&				redirect(\"settings/themes\")!@#&			end!@#&		elseif t == \"Load Theme\" then!@#&			term.setCursorPos(w - 33, 17)!@#&			write(\"Path: /\")!@#&			local n = modRead({visibleLength = w - 2, textLength = 100})!@#&			if n ~= \"\" and n then!@#&				n = \"/\" .. n!@#&				term.setCursorPos(1, 17)!@#&				rightWrite(string.rep(\" \", 36))!@#&				!@#&				term.setCursorPos(1, 17)!@#&				if fs.exists(n) and not fs.isDir(n) then!@#&					local a = loadTheme(n)!@#&					if a then!@#&						fs.delete(themeLocation)!@#&						fs.copy(n, themeLocation)!@#&						theme = a!@#&						rightWrite(\"Theme File Loaded! :D \")!@#&					else rightWrite(\"Theme File is Corrupt! D: \") end!@#&				elseif not fs.exists(n) then rightWrite(\"File does not exist! \")!@#&				elseif fs.isDir(n) then rightWrite(\"File is a directory! \") end!@#&!@#&				openAddressBar = false!@#&				sleep(1.1)!@#&				openAddressBar = true!@#&				redirect(\"settings/themes\")!@#&			end!@#&		else!@#&			local url = \"\"!@#&			for _, v in pairs(themes) do if v.name == t then url = v.url break end end!@#&			term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&			term.setCursorPos(1, 3)!@#&			leftWrite(string.rep(\" \", 17))!@#&			leftWrite(\" Downloading...  \")!@#&!@#&			fs.delete(rootFolder .. \"/temp_file\")!@#&			download(url, rootFolder .. \"/temp_file\")!@#&			local th = loadTheme(rootFolder .. \"/temp_file\")!@#&			if not th then!@#&				term.setCursorPos(1, 3)!@#&				leftWrite(string.rep(\" \", 17))!@#&				leftWrite(\" Theme Corrupt!  \")!@#&				openAddressBar = false!@#&				sleep(1.3)!@#&				openAddressBar = true!@#&!@#&				fs.delete(rootFolder .. \"/temp_file\")!@#&				redirect(\"settings/themes\")!@#&			else!@#&				term.setCursorPos(1, 3)!@#&				leftWrite(string.rep(\" \", 17))!@#&				leftWrite(\" Theme Loaded!   \")!@#&				openAddressBar = false!@#&				sleep(1.3)!@#&				openAddressBar = true!@#&!@#&				fs.delete(themeLocation)!@#&				fs.move(rootFolder .. \"/temp_file\", themeLocation)!@#&				theme = th!@#&				redirect(\"home\")!@#&			end!@#&		end!@#&	else!@#&		print(\"\")!@#&		rightPrint(string.rep(\" \", 30))!@#&		rightPrint(\"  Themes are not available on \")!@#&		rightPrint(\"         normal computers! :( \")!@#&		rightPrint(string.rep(\" \", 30))!@#&	end!@#&end!@#&!@#&pages[\"settings\"] = function()!@#&	term.setBackgroundColor(colors[theme[\"background\"]])!@#&	term.clear()!@#&	term.setTextColor(colors[theme[\"text-color\"]])!@#&	term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&	print(\"\")!@#&	leftPrint(string.rep(\" \", 17 + serverList[serverID]:len()))!@#&	leftPrint(\" Firewolf Settings  \" .. string.rep(\" \", serverList[serverID]:len() - 3))!@#&	leftPrint(\" Designed For: \" .. serverList[serverID] .. \"  \")!@#&	leftPrint(string.rep(\" \", 17 + serverList[serverID]:len()))!@#&	print(\"\\n\")!@#&!@#&	local a = \"Automatic Updating - On\"!@#&	if autoupdate == \"false\" then a = \"Automatic Updating - Off\" end!@#&	local b = \"Home - rdnt://\" .. homepage!@#&	if b:len() >= 28 then b = b:sub(1, 24) .. \"...\" end!@#&!@#&	term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&	for i = 1, 9 do rightPrint(string.rep(\" \", 36)) end!@#&	local c = {{a, w - a:len() - 6, 9}, {\"Change Theme\", w - 18, 11}, {b, w - b:len() - 6, 13},!@#&		{\"Reset Firewolf\", w - 20, 15}}!@#&	if not isAdvanced() then!@#&		c = {{a, w - a:len(), 9}, {b, w - b:len(), 11}, {\"Reset Firewolf\", w - 14, 13}}!@#&	end!@#&!@#&	local opt = prompt(c, \"vertical\")!@#&	if opt == a then!@#&		if autoupdate == \"true\" then autoupdate = \"false\"!@#&		elseif autoupdate == \"false\" then autoupdate = \"true\" end!@#&	elseif opt == \"Change Theme\" and isAdvanced() then!@#&		redirect(\"settings/themes\")!@#&	elseif opt == b then!@#&		if isAdvanced() then term.setCursorPos(w - 30, 14)!@#&		else term.setCursorPos(w - 30, 12) end!@#&		write(\"rdnt://\")!@#&		local a = read()!@#&		if a ~= \"\" then homepage = a end!@#&	elseif opt == \"Reset Firewolf\" then!@#&		term.setBackgroundColor(colors[theme[\"background\"]])!@#&		term.clear()!@#&		term.setCursorPos(1, 1)!@#&		term.setTextColor(colors[theme[\"text-color\"]])!@#&		term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&		print(\"\")!@#&		leftPrint(string.rep(\" \", 17))!@#&		leftPrint(\" Reset Firewolf  \")!@#&		leftPrint(string.rep(\" \", 17))!@#&		print(\"\\n\")!@#&		term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&		for i = 1, 11 do rightPrint(string.rep(\" \", 26)) end!@#&		local opt = prompt({{\"Reset History\", w - 19, 8}, {\"Reset Servers\", w - 19, 9},!@#&			{\"Reset Theme\", w - 17, 10}, {\"Reset Cache\", w - 17, 11}, !@#&			{\"Reset Databases\", w - 21, 12},!@#&			{\"Reset Settings\", w - 20, 13}, {\"Back\", w - 10, 14}, {\"Reset All\", w - 15, 16}},!@#&			\"vertical\")!@#&!@#&		openAddressBar = false!@#&		if opt == \"Reset All\" then!@#&			fs.delete(rootFolder)!@#&		elseif opt == \"Reset History\" then!@#&			fs.delete(historyLocation)!@#&		elseif opt == \"Reset Servers\" then!@#&			fs.delete(serverFolder)!@#&			fs.delete(serverLocation)!@#&		elseif opt == \"Reset Cache\" then!@#&			fs.delete(cacheFolder)!@#&		elseif opt == \"Reset Databases\" then!@#&			fs.delete(userWhitelist)!@#&			fs.delete(userBlacklist)!@#&		elseif opt == \"Reset Settings\" then!@#&			fs.delete(settingsLocation)!@#&		elseif opt == \"Reset Theme\" then!@#&			fs.delete(themeLocation)!@#&		elseif opt == \"Back\" then!@#&			openAddressBar = true!@#&			redirect(\"settings\")!@#&		end!@#&!@#&		term.setBackgroundColor(colors[theme[\"background\"]])!@#&		term.clear()!@#&		term.setCursorPos(1, 1)!@#&		term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&		print(\"\\n\\n\")!@#&		leftPrint(string.rep(\" \", 17))!@#&		leftPrint(\" Reset Firewolf  \")!@#&		leftPrint(string.rep(\" \", 17))!@#&		print(\"\")!@#&!@#&		term.setCursorPos(1, 10)!@#&		term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&		rightPrint(string.rep(\" \", 27))!@#&		rightPrint(\"  Firewolf has been reset! \")!@#&		rightWrite(string.rep(\" \", 27))!@#&		if isAdvanced() then rightPrint(\"          Click to exit... \")!@#&		else rightPrint(\"  Press any key to exit... \") end!@#&		rightPrint(string.rep(\" \", 27))!@#&!@#&		while true do!@#&			local e = os.pullEvent()!@#&			if e == \"mouse_click\" or e == \"key\" then return true end!@#&		end!@#&	end!@#&!@#&	-- Save!@#&	local f = io.open(settingsLocation, \"w\")!@#&	f:write(textutils.serialize({auto = autoupdate, incog = incognito, home = homepage}))!@#&	f:close()!@#&!@#&	redirect(\"settings\")!@#&end!@#&!@#&!@#&--  -------- Credits!@#&!@#&pages[\"credits\"] = function()!@#&	term.setTextColor(colors[theme[\"text-color\"]])!@#&	term.setBackgroundColor(colors[theme[\"background\"]])!@#&	term.clear()!@#&	print(\"\\n\")!@#&	term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&	leftPrint(string.rep(\" \", 19))!@#&	leftPrint(\" Firewolf Credits  \")!@#&	leftPrint(string.rep(\" \", 19))!@#&	print(\"\\n\")!@#&!@#&	term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&	rightPrint(string.rep(\" \", 38))!@#&	rightPrint(\"  Coded by:              GravityScore \")!@#&	rightPrint(\"                            and 1lann \")!@#&	rightPrint(string.rep(\" \", 38))!@#&	rightPrint(\"  Based off:     RednetExplorer 2.4.1 \")!@#&	rightPrint(\"           Made by ComputerCraftFan11 \")!@#&	rightPrint(string.rep(\" \", 38))!@#&end!@#&!@#&!@#&--  -------- Error Pages!@#&!@#&errorPages[\"overspeed\"] = function()!@#&	clear(\"overspeed\", colors[theme[\"background\"]])!@#&	print(\"\")!@#&	term.setTextColor(colors[theme[\"text-color\"]])!@#&	term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&	leftPrint(string.rep(\" \", 14))!@#&	leftPrint(\" Warning! D:  \")!@#&	leftPrint(string.rep(\" \", 14))!@#&	print(\"\")!@#&!@#&	term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&	rightPrint(string.rep(\" \", 40))!@#&	rightPrint(\"  Website browsing sleep limit reached! \")!@#&	rightPrint(string.rep(\" \", 40))!@#&	rightPrint(\"      To prevent Firewolf from spamming \")!@#&	rightPrint(\"   rednet, Firewolf has stopped loading \")!@#&	rightPrint(\"                              the page. \")!@#&	for i = 1, 3 do rightPrint(string.rep(\" \", 40)) end!@#&!@#&	openAddressBar = false!@#&	for i = 1, 5 do!@#&		term.setCursorPos(1, 14)!@#&		rightWrite(string.rep(\" \", 43))!@#&		if 6 - i == 1 then rightWrite(\"                Please wait 1 second... \")!@#&		else rightWrite(\"                Please wait \" .. tostring(6 - i) .. \" seconds... \") end!@#&		sleep(1)!@#&	end!@#&	openAddressBar = true!@#&!@#&	term.setCursorPos(1, 14)!@#&	rightWrite(string.rep(\" \", 43))!@#&	rightWrite(\"            You may now browse normally \")!@#&end!@#&!@#&errorPages[\"crash\"] = function(error)!@#&	clear(\"crash\", colors[theme[\"background\"]])!@#&	print(\"\")!@#&	term.setTextColor(colors[theme[\"text-color\"]])!@#&	term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&	leftPrint(string.rep(\" \", 30))!@#&	leftPrint(\" The Website Has Crashed! D:  \")!@#&	leftPrint(string.rep(\" \", 30))!@#&	print(\"\")!@#&!@#&	term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&	rightPrint(string.rep(\" \", 31))!@#&	rightPrint(\"      The website has crashed! \")!@#&	rightPrint(\"  Report this to the operator: \")!@#&	rightPrint(string.rep(\" \", 31))!@#&	term.setBackgroundColor(colors[theme[\"background\"]])!@#&	print(\"\")!@#&	print(\" \" .. tostring(error))!@#&	print(\"\")!@#&!@#&	term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&	rightPrint(string.rep(\" \", 31))!@#&	rightPrint(\"   You may now browse normally \")!@#&	rightPrint(string.rep(\" \", 31))!@#&end!@#&!@#&!@#&--  -------- External!@#&!@#&local function validateexternal(site)!@#&	-- Modem!@#&	if not modemPresent() then return \"modem\" end!@#&!@#&	-- Website!@#&	local id, content, status = curProtocol.getWebsite(site)!@#&	if id and status then return \"exists\", id, content, status end!@#&!@#&	-- Cache!@#&	local cacheLoc = cacheFolder .. \"/\" .. site:gsub(\"/\", \"$slazh$\")!@#&	if fs.exists(cacheLoc) and not fs.isDir(cacheLoc) then return \"cache\" end!@#&!@#&	-- Search results!@#&	local res = {}!@#&	if site ~= \"\" then!@#&		for _, v in pairs(dnsDatabase[1]) do!@#&			if v:find(site:lower(), 1, true) then table.insert(res, v) end!@#&		end!@#&	else for _, v in pairs(dnsDatabase[1]) do table.insert(res, v) end end!@#&	table.sort(res)!@#&	table.sort(res, function(a, b)!@#&		local _, ac = a:gsub(\"rdnt://\", \"\"):gsub(\"http://\", \"\"):gsub(site:lower(), \"\")!@#&		local _, bc = b:gsub(\"rdnt://\", \"\"):gsub(\"http://\", \"\"):gsub(site:lower(), \"\")!@#&		return ac > bc!@#&	end)!@#&!@#&	if #res > 0 then return \"search\", res!@#&	elseif site == \"\" then return \"search\", res end!@#&!@#&	-- Doesn't exist!@#&	return \"false\"!@#&end!@#&!@#&local function loadexternal(site)!@#&	local a, res, content, status = validateexternal(site)!@#&	local func = nil!@#&!@#&	if a == \"exists\" then!@#&		local cacheLoc = cacheFolder .. \"/\" .. site:gsub(\"/\", \"$slazh$\")!@#&		local f = io.open(cacheLoc, \"w\")!@#&		f:write(content)!@#&		f:close()!@#&!@#&		local fn, err = loadfile(cacheLoc)!@#&		if not err then!@#&			setfenv(fn, antivirus)!@#&			if status == \"whitelist\" then setfenv(fn, override) end!@#&!@#&			func = function()!@#&				local _, err = pcall(fn)!@#&				if err then!@#&					websiteerror = err!@#&					os.queueEvent(event_error)!@#&				end!@#&			end!@#&		else!@#&			func = function()!@#&				local errf = errorPages[\"crash\"]!@#&				setfenv(errf, override)!@#&				pcall(function() errf(err) end)!@#&			end!@#&		end!@#&	elseif a == \"modem\" then!@#&		func = function() checkForModem(graphics.nomodem) end!@#&	elseif a == \"search\" then!@#&		if #res > 0 then!@#&			func = function()!@#&				term.setBackgroundColor(colors[theme[\"background\"]])!@#&				term.clear()!@#&				term.setCursorPos(1, 2)!@#&				term.setTextColor(colors[theme[\"text-color\"]])!@#&				term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&				local t = \"1 Search Result\"!@#&				if #res > 1 then t = #res .. \" Search Results\" end!@#&				leftPrint(string.rep(\" \", t:len() + 3))!@#&				leftPrint(\" \" .. t .. \"  \")!@#&				leftPrint(string.rep(\" \", t:len() + 3))!@#&				print(\"\")!@#&!@#&				term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&				for i = 1, 12 do rightPrint(string.rep(\" \", 42)) end!@#&				local opt = scrollingPrompt(res, w - 39, 7, 10, 38)!@#&				if opt then redirect(opt:gsub(\"rdnt://\", \"\"):gsub(\"http://\", \"\")) end!@#&			end!@#&		else!@#&			func = graphics.nosearchresults!@#&		end!@#&	elseif a == \"false\" or a == \"cache\" then!@#&		func = graphics.nonexistantwebpage!@#&	end!@#&!@#&	term.setBackgroundColor(colors.black)!@#&	term.setTextColor(colors.white)!@#&	term.clear()!@#&	term.setCursorPos(1, 1)!@#&!@#&	local a = override!@#&	a[\"browserAgent\"] = browserAgent!@#&	setfenv(func, a)!@#&	curtext, curbackground = colors.white, colors.black!@#&	tabs[currentTab] = coroutine.create(func)!@#&end!@#&!@#&!@#&--  -------- Website!@#&!@#&local function loadinternal(site)!@#&	if pages[site] then!@#&		local func = pages[site]!@#&		setfenv(func, override)!@#&		tabs[currentTab] = coroutine.create(function()!@#&			local _, err = pcall(function() func() end)!@#&			if err then!@#&				websiteerror = err!@#&				os.queueEvent(event_error)!@#&			end!@#&		end)!@#&!@#&		return true!@#&	else return false end!@#&end!@#&!@#&local function loadsite(site)!@#&	w, h = term.getSize()!@#&	clear(site)!@#&	term.setBackgroundColor(colors.black)!@#&	term.setTextColor(colors.white)!@#&	fs.delete(websiteDataFolder)!@#&	fs.makeDir(websiteDataFolder)!@#&!@#&	if site ~= \"exit\" and site ~= addressBarHistory[#addressBarHistory] then!@#&		table.insert(addressBarHistory, site)!@#&	end!@#&!@#&	checkForModem()!@#&	if os.clock() - loadingClock > 5 then loadingRate, loadingClock = 0, os.clock() end!@#&	if loadingRate >= 8 then!@#&		local overspeedFunc = errorPages[\"overspeed\"]!@#&		setfenv(overspeedFunc, override)!@#&		overspeedFunc()!@#&		loadingRate, loadingClock = 0, os.clock()!@#&	end!@#&!@#&	-- Load!@#&	os.queueEvent(event_load)!@#&	website = site!@#&	setfenv(loadinternal, override)!@#&	setfenv(loadexternal, override)!@#&	if not loadinternal(site) then loadexternal(site) end!@#&	if tabs[currentTab] then _, filters[currentTab] = coroutine.resume(tabs[currentTab]) end!@#&end!@#&!@#&!@#&--  -------- Address Bar!@#&!@#&local function addressbarread()!@#&	local len, list = 4, {}!@#&!@#&	local function draw(l)!@#&		local ox, oy = term.getCursorPos()!@#&		for i = 1, len do!@#&			term.setTextColor(colors[theme[\"address-bar-text\"]])!@#&			term.setBackgroundColor(colors[theme[\"address-bar-background\"]])!@#&			term.setCursorPos(1, i + 1)!@#&			write(string.rep(\" \", w))!@#&		end!@#&!@#&		term.setBackgroundColor(colors[theme[\"address-bar-base\"] or theme[\"bottom-box\"]])!@#&		term.setCursorPos(1, len + 2)!@#&		write(string.rep(\" \", w))!@#&		term.setBackgroundColor(colors[theme[\"address-bar-background\"]])!@#&		for i, v in ipairs(l) do term.setCursorPos(2, i + 1) write(v) end!@#&		term.setCursorPos(ox, oy)!@#&	end!@#&!@#&	local function update(line, event, ...)!@#&		local params = {...}!@#&		local y = params[3]!@#&		if event == \"char\" or event == \"history\" or event == \"delete\" then!@#&			list = {}!@#&			for _, v in pairs(dnsDatabase[1]) do!@#&				if #list < len and!@#&						v:gsub(\"rdnt://\", \"\"):gsub(\"http://\", \"\"):find(line:lower(), 1, true) then!@#&					table.insert(list, v)!@#&				end!@#&			end!@#&!@#&			table.sort(list)!@#&			table.sort(list, function(a, b)!@#&				local _, ac = a:gsub(\"rdnt://\", \"\"):gsub(\"http://\", \"\"):gsub(line:lower(), \"\")!@#&				local _, bc = b:gsub(\"rdnt://\", \"\"):gsub(\"http://\", \"\"):gsub(line:lower(), \"\")!@#&				return ac > bc!@#&			end)!@#&			draw(list)!@#&			return false!@#&		elseif event == \"mouse_click\" then!@#&			for i = 1, #list do!@#&				if y == i + 1 then return true, list[i]:gsub(\"rdnt://\", \"\"):gsub(\"http://\", \"\") end!@#&			end!@#&		end!@#&	end!@#&!@#&	if isAdvanced() and modemPresent() then!@#&		return modRead({history = addressBarHistory, visibleLength = w - 2, textLength = 300, !@#&			liveUpdates = update, exitOnKey = \"control\"})!@#&	else!@#&		return modRead({history = addressBarHistory, visibleLength = w - 2, textLength = 300,!@#&			exitOnKey = \"control\"})!@#&	end!@#&end!@#&!@#&!@#&--  -------- Main!@#&!@#&local function searchresults()!@#&	if modemPresent() then curProtocol.getSearchResults() end!@#&	local lastCheck = os.clock()!@#&	while true do!@#&		local e = os.pullEvent()!@#&		if e == event_load and modemPresent() and os.clock() - lastCheck > 5 then!@#&			curProtocol.getSearchResults()!@#&			lastCheck = os.clock()!@#&		end!@#&	end!@#&end!@#&!@#&local function run()!@#&	loadingClock = os.clock()!@#&	loadsite(homepage)!@#&	while true do!@#&		local e, but, x, y, p4, p5 = os.pullEvent()!@#&		if ((e == \"mouse_click\" and y == 1 and clickableAddressBar) or!@#&				(e == \"key\" and (but == 29 or but == 157))) and openAddressBar then!@#&			if e == \"key\" then x = -1 end!@#&			if not menuBarOpen and x == w then!@#&				-- Open menu bar!@#&				menuBarOpen = true!@#&				term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&				term.setTextColor(colors[theme[\"address-bar-text\"]])!@#&				term.setCursorPos(1, 1)!@#&				write(\"> [- Exit Firewolf -]                              \")!@#&			elseif menuBarOpen and (x == 1 or (but == 29 or but == 157)) then!@#&				-- Close menu bar!@#&				menuBarOpen = false!@#&				clear(website, nil, true)!@#&			elseif menuBarOpen and x > 2 and x < 22 then!@#&				return!@#&			elseif not menuBarOpen then!@#&				-- Stop!@#&				if tabs[currentTab] then tabs[currentTab] = nil end!@#&!@#&				-- Clear!@#&				term.setBackgroundColor(colors[theme[\"address-bar-background\"]])!@#&				term.setTextColor(colors[theme[\"address-bar-text\"]])!@#&				term.setCursorPos(2, 1)!@#&				term.clearLine()!@#&				if curProtocol == protocols.rdnt then write(\"rdnt://\")!@#&				elseif curProtocol == protocols.http then write(\"http://\") end!@#&!@#&				-- Read!@#&				local osite = website!@#&				local site = addressbarread()!@#&				if not site then site = osite!@#&				elseif site == \"home\" or site == \"homepage\" then site = homepage!@#&				elseif site == \"exit\" then return end!@#&!@#&				-- Load!@#&				loadsite(site)!@#&			end!@#&		elseif e == event_error and websiteerror then!@#&			-- Display!@#&			if tabs[currentTab] then tabs[currentTab] = nil end!@#&!@#&			local errf = errorPages[\"crash\"]!@#&			setfenv(errf, override)!@#&			errf(websiteerror)!@#&			websiteerror = nil!@#&		elseif e == event_redirect and openAddressBar then!@#&			-- Stop!@#&			if tabs[currentTab] then tabs[currentTab] = nil end!@#&!@#&			-- Load!@#&			if not but or but == \"exit\" then but = website!@#&			elseif but == \"home\" or but == \"homepage\" then but = homepage end!@#&			loadsite(but)!@#&		elseif tabs[currentTab] then!@#&			if coroutine.status(tabs[currentTab]) == \"suspended\" then!@#&				if e == \"mouse_click\" and offsetclick then y = y - 1 end!@#&				if (filters[currentTab] or e) == e then!@#&					_, filters[currentTab] = coroutine.resume(tabs[currentTab], e, but, x, y, !@#&						p4, p5)!@#&				end!@#&			end!@#&!@#&			for i = 1, #tabs do!@#&				if tabs[i] and coroutine.status(tabs[i]) == \"dead\" then!@#&					tabs[i] = nil!@#&				end!@#&			end!@#&		end!@#&	end!@#&end!@#&!@#&!@#&--  -------- Startup!@#&!@#&local function main()!@#&	-- Logo!@#&	term.setBackgroundColor(colors[theme[\"background\"]])!@#&	term.setTextColor(colors[theme[\"text-color\"]])!@#&	term.clear()!@#&	term.setCursorPos(1, 2)!@#&	term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&	leftPrint(string.rep(\" \", 47))!@#&	leftPrint([[          ______ ____ ____   ______            ]])!@#&	leftPrint([[ ------- / ____//  _// __ \\ / ____/            ]])!@#&	leftPrint([[ ------ / /_    / / / /_/ // __/               ]])!@#&	leftPrint([[ ----- / __/  _/ / / _  _// /___               ]])!@#&	leftPrint([[ ---- / /    /___//_/ |_|/_____/               ]])!@#&	leftPrint([[ --- / /       _       __ ____   __     ______ ]])!@#&	leftPrint([[ -- /_/       | |     / // __ \\ / /    / ____/ ]])!@#&	leftPrint([[              | | /| / // / / // /    / /_     ]])!@#&	leftPrint([[              | |/ |/ // /_/ // /___ / __/     ]])!@#&	leftPrint([[              |__/|__/ \\____//_____//_/        ]])!@#&	leftPrint(string.rep(\" \", 47))!@#&	print(\"\\n\")!@#&	term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&!@#&	-- Load Settings!@#&	if fs.exists(settingsLocation) and not fs.isDir(settingsLocation) then!@#&		local f = io.open(settingsLocation, \"r\")!@#&		local a = textutils.unserialize(f:read(\"*l\"))!@#&		if type(a) == \"table\" then autoupdate, incognito, homepage = a.auto, a.incog, a.home end!@#&		f:close()!@#&	else autoupdate, incognito, homepage = \"true\", \"false\", \"firewolf\" end!@#&	curProtocol = protocols.rdnt!@#&!@#&	-- Update!@#&	rightPrint(string.rep(\" \", 32))!@#&	rightPrint(\"        Checking for Updates... \")!@#&	rightPrint(string.rep(\" \", 32))!@#&	setfenv(updateClient, env)!@#&	if not noInternet then!@#&		if updateClient() then!@#&			if debugFile then debugFile:close() end!@#&			shell.run(firewolfLocation)!@#&			error()!@#&		end!@#&	end!@#&!@#&	-- Download Files!@#&	local x, y = term.getCursorPos()!@#&	term.setCursorPos(1, y - 2)!@#&	rightWrite(string.rep(\" \", 32))!@#&	rightWrite(\"  Downloading Required Files... \")!@#&	if not noInternet then resetFilesystem() end!@#&	loadDatabases()!@#&	checkForModem()!@#&!@#&	-- Run!@#&	setfenv(run, env)!@#&	parallel.waitForAny(run, searchresults)!@#&end!@#&!@#&local function startup()!@#&	-- HTTP!@#&	if not http and not noInternet then!@#&		term.setTextColor(colors[theme[\"text-color\"]])!@#&		term.setBackgroundColor(colors[theme[\"background\"]])!@#&		term.clear()!@#&		term.setCursorPos(1, 2)!@#&		term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&		api.leftPrint(string.rep(\" \", 24))!@#&		api.leftPrint(\" HTTP API Not Enabled!  \")!@#&		api.leftPrint(string.rep(\" \", 24))!@#&		print(\"\")!@#&!@#&		term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&		api.rightPrint(string.rep(\" \", 36))!@#&		api.rightPrint(\"  Firewolf is unable to run without \")!@#&		api.rightPrint(\"       the HTTP API Enabled! Please \")!@#&		api.rightPrint(\"    enable it in your ComputerCraft \")!@#&		api.rightPrint(\"                            Config! \")!@#&		api.rightPrint(string.rep(\" \", 36))!@#&!@#&		if isAdvanced() then api.rightPrint(\"                   Click to exit... \")!@#&		else api.rightPrint(\"           Press any key to exit... \") end!@#&		api.rightPrint(string.rep(\" \", 36))!@#&!@#&		while true do!@#&			local e, but, x, y = os.pullEvent()!@#&			if e == \"mouse_click\" or e == \"key\" then break end!@#&		end!@#&!@#&		return false!@#&	end!@#&!@#&	-- Turtle!@#&	if turtle then!@#&		term.clear()!@#&		term.setCursorPos(1, 2)!@#&		api.centerPrint(\"Advanced computer Required!\")!@#&		print(\"\\n\")!@#&		api.centerPrint(\"  This version of Firewolf requires  \")!@#&		api.centerPrint(\"  an Advanced computer to run!       \")!@#&		print(\"\")!@#&		api.centerPrint(\"  Turtles may not be used to run     \")!@#&		api.centerPrint(\"  Firewolf! :(                       \")!@#&		print(\"\")!@#&		api.centerPrint(\"Press any key to exit...\")!@#&!@#&		os.pullEvent(\"key\")!@#&		return false!@#&	end!@#&!@#&	-- Run!@#&	setfenv(main, env)!@#&	local _, err = pcall(main)!@#&	if err and not err:lower():find(\"terminated\") then!@#&		term.setTextColor(colors[theme[\"text-color\"]])!@#&		term.setBackgroundColor(colors[theme[\"background\"]])!@#&		term.clear()!@#&		term.setCursorPos(1, 2)!@#&		term.setCursorBlink(false)!@#&		term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&		api.leftPrint(string.rep(\" \", 27))!@#&		api.leftPrint(\" Firewolf has Crashed! D:  \")!@#&		api.leftPrint(string.rep(\" \", 27))!@#&		print(\"\")!@#&		term.setBackgroundColor(colors[theme[\"background\"]])!@#&		print(\"\")!@#&		print(\"  \" .. err)!@#&		print(\"\")!@#&!@#&		term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&		api.rightPrint(string.rep(\" \", 41))!@#&		if autoupdate == \"true\" then!@#&			api.rightPrint(\"    Please report this error to 1lann or \")!@#&			api.rightPrint(\"  GravityScore so we are able to fix it! \")!@#&			api.rightPrint(\"  If this problem persists, try deleting \")!@#&			api.rightPrint(\"                         \" .. rootFolder .. \" \")!@#&		else!@#&			api.rightPrint(\"        Automatic updating is off! A new \")!@#&			api.rightPrint(\"     version may have have been released \")!@#&			api.rightPrint(\"                that may fix this error! \")!@#&			api.rightPrint(\"        If you didn't turn auto updating \")!@#&			api.rightPrint(\"             off, delete \" .. rootFolder .. \" \")!@#&		end!@#&!@#&		api.rightPrint(string.rep(\" \", 41))!@#&		if isAdvanced() then api.rightPrint(\"                        Click to exit... \")!@#&		else api.rightPrint(\"                Press any key to exit... \") end!@#&		api.rightPrint(string.rep(\" \", 41))!@#&!@#&		while true do!@#&			local e, but, x, y = os.pullEvent()!@#&			if e == \"mouse_click\" or e == \"key\" then break end!@#&		end!@#&!@#&		return false!@#&	end!@#&end!@#&!@#&-- Check If Read Only!@#&if fs.isReadOnly(firewolfLocation) or fs.isReadOnly(rootFolder) then!@#&	print(\"Firewolf cannot modify itself or its root folder!\")!@#&	print(\"\")!@#&	print(\"This cold be caused by Firewolf being placed in\")!@#&	print(\"the rom folder, or another program may be\")!@#&	print(\"preventing the modification of Firewolf.\")!@#&	error()!@#&end!@#&!@#&-- Theme!@#&if not isAdvanced() then theme = originalTheme!@#&else theme = loadTheme(themeLocation) or defaultTheme end!@#&!@#&-- Debug File!@#&if #tArgs > 0 and tArgs[1] == \"debug\" then!@#&	print(\"Debug Mode Enabled\")!@#&	if fs.exists(debugLogLocation) then debugFile = io.open(debugLogLocation, \"a\")!@#&	else debugFile = io.open(debugLogLocation, \"w\") end!@#&	debugFile:write(\"\\n-- [\" .. textutils.formatTime(os.time()) .. \"] New Log --\")!@#&	sleep(1)!@#&end!@#&!@#&-- Start!@#&startup()!@#&!@#&-- Exit Message!@#&term.setBackgroundColor(colors.black)!@#&term.setTextColor(colors.white)!@#&term.setCursorBlink(false)!@#&term.clear()!@#&term.setCursorPos(1, 1)!@#&api.centerPrint(\"Thank You for Using Firewolf \" .. version)!@#&api.centerPrint(\"Made by 1lann and GravityScore\")!@#&!@#&-- Close!@#&for _, v in pairs(rs.getSides()) do !@#&	if peripheral.getType(v) == \"modem\" then rednet.close(v) end!@#&end!@#&if debugFile then debugFile:close() end",["mouse.cfg"]="{[\"txt\"]=32768,[\"back\"]=2048,}!@#&{[\"txt\"]=32768,[\"back\"]=256,}!@#&{[\"txt\"]=32768,[\"back\"]=512,}!@#&{[\"txt\"]=32768,[\"back\"]=256,}!@#&{[\"txt\"]=32768,[\"back\"]=2048,}!@#&{[\"txt\"]=32768,[\"back\"]=2048,}!@#&{[\"txt\"]=32768,[\"back\"]=1,}!@#&{[\"back\"]=256,[\"button\"]=128,[\"off\"]=128,}!@#&{[\"folder\"]={[\"txt\"]=\"[=]\",[\"bCol\"]=\"blue\",[\"tCol\"]=\"lightGray\",},[\"audio\"]={[\"txt\"]=\"(o)\",[\"bCol\"]=\"red\",[\"tCol\"]=\"yellow\",},[\"disk\"]={[\"txt\"]=\"[*]\",[\"bCol\"]=\"green\",[\"tCol\"]=\"lime\",},[\"file\"]={},[\"back\"]={[\"txt\"]=\" < \",[\"bCol\"]=\"blue\",[\"tCol\"]=\"lightGray\",},}!@#&{[\"Paint\"]=\"rom/programs/color/paint\",[\"Edit\"]=\"rom/programs/edit\",}",["games"]="local running = true!@#&!@#&function clear()!@#&  term.clear()!@#&  term.setCursorPos(1,1)!@#&end!@#&!@#&term.setBackgroundColour(colors.white)!@#&clear()!@#&local A = 0!@#&local games = {}!@#&term.setTextColour(colors.white)!@#&!@#&for i,v in ipairs(fs.list(\"/\"..root..\"/games/\")) do!@#&  if A == 0 then!@#&    term.setBackgroundColour(colors.gray)!@#&    term.setTextColour(colors.lightGray)!@#&    A = 1!@#&  elseif A == 1 then  !@#&    term.setBackgroundColour(colors.lightGray)!@#&    term.setTextColour(colors.gray)!@#&    A = 0!@#&  end!@#&  term.clearLine()!@#&  local str = string.upper(v:sub(1,1)) .. v:sub(2)!@#&  print(str)!@#&  table.insert(games, v)!@#&end!@#&!@#&local maxX, maxY = term.getSize()!@#&term.setCursorPos(1, maxY)!@#&term.setCursorPos((maxX/2), maxY)!@#&term.setBackgroundColour(colors.gray)!@#&term.clearLine()!@#&term.setTextColour(colors.lightGray)!@#&write(\"Exit\")!@#&!@#&while running do!@#&  ev, button, x, y = os.pullEvent(\"mouse_click\")!@#&!@#&  for i=1, #games do!@#&    if y == i then!@#&      term.setBackgroundColour(colors.black)!@#&      clear()!@#&      running = false!@#&      shell.run(\"/\"..root..\"/games/\"..games[i])!@#&    end!@#&  end!@#&!@#&  if y == maxY then!@#&    running = false!@#&    clear()!@#&  end!@#&end",},["system"]={["delUser"]="function clear()!@#& term.clear()!@#& term.setCursorPos(1,1)!@#&end!@#&!@#&function succesBox(text)!@#& local maxX, maxY = term.getSize()!@#& term.setTextColour(colors.white)!@#& term.setBackgroundColour(colors.green)!@#& term.setCursorPos(1, maxY/2-1)!@#& term.clearLine()!@#& term.setCursorPos(maxX/2-#text/2, maxY/2)!@#& term.clearLine()!@#& write(text)!@#& term.setCursorPos(1, maxY/2+1)!@#& term.clearLine()!@#& sleep(2)!@#&end!@#&!@#&function errorBox(text)!@#& local maxX, maxY = term.getSize()!@#& term.setTextColour(colors.white)!@#& term.setBackgroundColour(colors.red)!@#& term.setCursorPos(1, maxY/2-1)!@#& term.clearLine()!@#& term.setCursorPos(maxX/2-#text/2, maxY/2)!@#& term.clearLine()!@#& write(text)!@#& term.setCursorPos(1,maxY/2+1)!@#& term.clearLine()!@#& sleep(2)!@#&end!@#&!@#&function delUser(name, pwd)!@#& if name == \"\" or pwd == \"\" then!@#&  errorBox(\"Username or password cannot be empty!\")!@#& else!@#&  A = fs.open(\"/\"..root..\"/system/.users\", \"r\")!@#&  local usrTable = textutils.unserialize(A.readAll())!@#&  A.close()!@#&  !@#&  for i,v in ipairs(usrTable) do!@#&   if name == usrTable[i][\"username\"] and pwd == usrTable[i][\"password\"] then!@#&    table.remove(usrTable, i)!@#&    A = fs.open(\"/\"..root..\"/system/.users\", \"w\")!@#&    A.write(textutils.serialize(usrTable))!@#&    A.close()!@#&    succesBox(\"User succesfully removed!\")!@#&    return true!@#&   elseif name == usrTable[i][\"username\"] and pwd ~= usrTable[i][\"password\"] then!@#&    errorBox(\"Password does not match!\")!@#&    return false!@#&   end!@#&  end!@#& end!@#&end!@#&!@#&term.setBackgroundColour(colors.white)!@#&clear()!@#&term.setBackgroundColour(colors.lightGray)!@#&term.setCursorPos(1, 2)!@#&term.clearLine()!@#&write(\"Username: \")!@#&term.setCursorPos(1, 4)!@#&term.clearLine()!@#&write(\"Password: \")!@#&!@#&term.setCursorPos(11 , 2)!@#&input = read()!@#&term.setCursorPos(11, 4)!@#&pwd = read(\"*\")!@#&!@#&delUser(input, pwd)",["addUser"]="if not fs.exists(\"/\"..root..\"/system/.users\") then!@#& A = fs.open(\"/\"..root..\"/system/.users\", \"w\")!@#& local tbl = { [1] = {username = \"admin\", password = \"admin\" }}!@#& A.write(textutils.serialize(tbl))!@#& A.close()!@#& !@#& if not fs.exists(\"/\"..root..\"/users\") then!@#&  fs.makeDir(\"/\"..root..\"/users\")!@#&  fs.makeDir(\"/\"..root..\"/users/admin\")!@#& end!@#&!@#&end!@#&!@#&A = fs.open(\"/\"..root..\"/system/.users\", \"r\")!@#&local usrTable = textutils.unserialize(A.readAll())!@#&A.close()!@#&!@#&function clear()!@#& term.clear()!@#& term.setCursorPos(1,1)!@#&end!@#&!@#&function activate()!@#&term.setBackgroundColour(colors.white)!@#&clear()!@#&term.setTextColour(colors.gray)!@#&term.setCursorPos(1, 2)!@#&term.setBackgroundColour(colors.lightGray)!@#&term.clearLine()!@#&write(\"Username: \")!@#&!@#&term.setCursorPos(1, 4)!@#&term.clearLine()!@#&write(\"Password: \")!@#&!@#&term.setCursorPos(1, 6)!@#&term.clearLine()!@#&write(\"Re-type password: \")!@#&!@#&term.setCursorPos(11, 2)!@#&input = read()!@#&if input ~= \"\" then!@#& term.setCursorPos(11, 4)!@#& pw1 = read(\"*\")!@#& term.setCursorPos(19, 6)!@#& pw2 = read(\"*\")!@#& doUser()!@#&else!@#& errorBox(\"Username cannot be empty!\")!@#& return!@#&end!@#&end!@#&!@#&function errorBox(text)!@#& local maxX, maxY = term.getSize()!@#& term.setBackgroundColour(colors.red)!@#& term.setCursorPos(1, maxY/2-1)!@#& term.clearLine()!@#& term.setCursorPos(maxX/2-#text/2, maxY/2)!@#& term.clearLine()!@#& term.setTextColour(colors.white)!@#& write(text)!@#& term.setCursorPos(1, maxY/2+1)!@#& term.clearLine()!@#& sleep(2)!@#&end!@#&!@#&function succesBox(text)!@#& local maxX, maxY = term.getSize()!@#& term.setBackgroundColour(colors.green)!@#& term.setCursorPos(1, maxY/2-1)!@#& term.clearLine()!@#& term.setCursorPos(maxX/2-#text/2, maxY/2)!@#& term.clearLine()!@#& term.setTextColour(colors.white)!@#& write(text)!@#& term.setCursorPos(1, maxY/2+1)!@#& term.clearLine()!@#& sleep(2)!@#&end!@#&!@#&function addName(name, pwd)!@#& table.insert(usrTable, {username = name, password = pwd})!@#& A = fs.open(\"/\"..root..\"/system/.users\", \"w\")!@#& A.write(textutils.serialize(usrTable))!@#& A.close()!@#& fs.makeDir(\"/\"..root..\"/users/\"..name)!@#& succesBox(\"User succesfully added!\")!@#& return!@#&end!@#&!@#&function doUser()!@#& if pw1 ~= pw2 then!@#&  errorBox(\"Passwords do not match!\")!@#& else!@#&  for i,v in ipairs(usrTable) do!@#&   if input == usrTable[i][\"username\"] then!@#&    errorBox(\"User already exists!\")!@#&   end!@#&  end!@#&   addName(input, pw1)!@#&   --succesBox(\"User succesfully added!\")!@#& end!@#&end!@#&!@#&activate()",["listUsers"]="local file = \"/\"..root..\"/system/.users\"!@#&!@#&A = fs.open(file, \"r\")!@#&local usrTable = textutils.unserialize(A.readAll())!@#&A.close()!@#&!@#&local tbl = {}!@#&!@#&for i,v in ipairs(usrTable) do!@#& table.insert(tbl, usrTable[i][\"username\"])!@#&end!@#&!@#&table.sort(tbl)!@#&term.setBackgroundColour(colors.white)!@#&term.clear()!@#&term.setCursorPos(1,1)!@#&term.setTextColour(colors.gray)!@#&term.setBackgroundColour(colors.lightGray)!@#&textutils.pagedTabulate(tbl)!@#&!@#&local maxX, maxY = term.getSize()!@#&local text = \"Press any key to continue...\"!@#&term.setCursorPos(maxX/2-#text/2, maxY)!@#&term.clearLine()!@#&write(text)!@#&os.pullEvent(\"key\")",},["users"]={["admin"]={},},["images"]={["files"]="8888                                             !@#&8ff88                                            !@#&88888                                            !@#&8fff8                                            !@#&88888                                            !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 ",["luaide"]="fffff                                            !@#&fffff                                            !@#&fffff                                            !@#&fffff                                            !@#&fffff                                            !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 ",["firewolf"]=" 1  1                                            !@#&1e11e                                            !@#&eeeee                                            !@#&33e33                                            !@#&b333b                                            !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 ",["npaintpro"]="                                                 !@#&3                                                !@#& c  7                                            !@#&  c1                                             !@#& 1 c                                             !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 ",["snake"]="ddddd!@#&d   d!@#&d d!@#&d d e!@#&ddd  ",["wallpaper"]="                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                  1   5  9993                    !@#&                  1   5  9  33                   !@#&                  11155  9   3                   !@#&                  1   5  9   3                   !@#&                  1   5  9  33                   !@#&                  1   5  9993                    !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 ",},},["PkgMake"]="sPackage = \"local pkg = %@1 local function makeFile(_path, _content) local file = fs.open(_path, \\\"w\\\") _content = _content:gsub(\\\"\\!@\\\"..\\\"#&\\\", \\\"%\\\\n\\\") _content = textutils.unserialize(_content) file.write(_content) file.close() end local function makeFolder(_path, _content) fs.makeDir(_path) for k,v in pairs(_content) do if type(v) == \\\"table\\\" then makeFolder(_path .. \\\"/\\\" .. k, v) else makeFile(_path .. \\\"/\\\" .. k, v) end end end local sDest = shell.resolve( \\\"%@2\\\" ) or \\\"/\\\" if sDest == \\\"root\\\" then sDest = \\\"/\\\" end local tPackage = pkg makeFolder(sDest, tPackage) print(\\\"Package Extracted to '\\\" .. sDest .. \\\"'!\\\")\"!@#&!@#&function addFile(_package, _path)!@#&	if fs.getName(_path) == \".DS_Store\" then!@#&		return _package!@#&	end!@#&	local file, err = fs.open(_path, \"r\")!@#&	local content = file.readAll()!@#&	content = content:gsub(\"%\\n\", \"\\!@\"..\"#&\")!@#&	content = content:gsub(\"%%\", \"%%%%\")!@#&	_package[fs.getName(_path)] = content!@#&	file.close()!@#&	print(\"Added file '\".._path..\"'\")!@#&	return _package!@#&end!@#&!@#&function addFolder(_package, _path)!@#&	if string.sub(_path,1,string.len(\"rom\"))==\"rom\" or string.sub(_path,1,string.len(\"/rom\"))==\"/rom\" then!@#&		print(\"Ignored 'rom' folder. (\".._path..\")\")!@#&		return!@#&	end!@#&	_package = _package or {}!@#&	for _,f in ipairs(fs.list(_path)) do!@#&		local path = _path..\"/\"..f!@#&		if fs.isDir(path) then!@#&			_package[fs.getName(f)] = addFolder(_package[fs.getName(f)], path)!@#&		else!@#&			_package =  addFile(_package, path)!@#&		end!@#&	end!@#&	return _package!@#&end!@#&!@#&local tArgs = { ... }!@#&if #tArgs < 2 then!@#&	print( \"Usage: PkgMake <source> <destination>\" )!@#&	return!@#&end!@#&!@#&local sSource = shell.resolve( tArgs[1] )!@#&local sDest = shell.resolve( tArgs[2] )!@#&!@#&if fs.isDir( sDest ) then!@#&	error(\"Destination must not be a folder.\")!@#&end!@#&!@#&if sSource == sDest then!@#&	error(\"Source can not be equal to destination.\")!@#&end!@#&!@#&if fs.exists( sSource ) and fs.isDir( sSource ) then!@#&	tPackage = {}!@#&	tPackage = addFolder(tPackage, sSource)!@#&	fPackage = fs.open(sDest,\"w\")!@#&!@#&	sPackage = string.gsub(sPackage, \"%%@2\", fs.getName(sSource))!@#&	sPackage = string.gsub(sPackage, \"%%@1\", textutils.serialize(tPackage))!@#&	fPackage.write(sPackage)!@#&	fPackage.close()!@#&	print(\"Package Done! ('\" .. sDest .. \"')\")!@#&	print(\"Type '\" .. sDest .. \"' to run it.\")!@#&else!@#&	error(\"Source does not exist or is not a folder.\")!@#&end",} local function makeFile(_path, _content) local file = fs.open(_path, "w") _content = _content:gsub("!@".."#&", "%\n") _content = textutils.unserialize(_content) file.write(_content) file.close() end local function makeFolder(_path, _content) fs.makeDir(_path) for k,v in pairs(_content) do if type(v) == "table" then makeFolder(_path .. "/" .. k, v) else makeFile(_path .. "/" .. k, v) end end end local sDest = shell.resolve( "root" ) or "/" if sDest == "root" then sDest = "/" end local tPackage = pkg makeFolder(sDest, tPackage) print("Package Extracted to '" .. sDest .. "'!")
1+
local pkg = {[".Firewolf_Data"]={["server_software"]="!@#&--  !@#&--  Firewolf Server Software!@#&--  Created By GravityScore and 1lann!@#&--  License found here: https://raw.github.com/1lann/Firewolf/master/LICENSE  !@#&--!@#&--  Orignal Idea from RednetExplorer 2.4.1!@#&--  RednetExplorer Made by ComputerCraftFan11!@#&--  !@#&!@#&!@#&--  -------- Variables!@#&!@#&-- Version!@#&local version = \"2.5\"!@#&local serverID = \"release\"!@#&!@#&-- Prevent Control-T!@#&os.pullEvent = os.pullEventRaw!@#&!@#&-- Updating!@#&local autoupdate = true!@#&!@#&-- Responding!@#&local enableSearch = true!@#&local enableResponse = true!@#&local enableRecording = true!@#&!@#&-- Download URLs!@#&local serverURL = \"https://raw.github.com/1lann/firewolf/master/server/server-\" .. serverID .. \".lua\"!@#&!@#&-- Events!@#&local event_stopServer = \"firewolf_stopServerEvent\"!@#&!@#&-- Statistics!@#&local searches = 0!@#&local visits = 0!@#&!@#&-- Theme!@#&local theme = {}!@#&!@#&-- Databases!@#&local ignoreDatabase = {}!@#&local permantentIgnoreDatabase = {}!@#&local suspected = {}!@#&!@#&-- Server!@#&local w, h = term.getSize()!@#&local args = {...}!@#&local website = \"\"!@#&local dataLocation = \"\"!@#&local pages = {}!@#&local totalRecordLines = {}!@#&local recordLines = {}!@#&local serverPassword = nil!@#&local serverLocked = false!@#&!@#&-- Locations!@#&local rootFolder = \"/.Firewolf_Data\"!@#&local serverFolder = rootFolder .. \"/servers\"!@#&local statsLocation = rootFolder .. \"/\" .. website .. \"_stats\"!@#&local themeLocation = rootFolder .. \"/theme\"!@#&local defaultThemeLocation = rootFolder .. \"/default_theme\"!@#&local passwordDataLocation = rootFolder .. \"/.\" .. website .. \"_password\"!@#&local serverLocation = \"/\" .. shell.getRunningProgram()!@#&!@#&-- Parse Arguments!@#&if #args >= 2 then!@#&	website = args[1]:gsub(\"^%s*(.-)%s*$\", \"%1\")!@#&	dataLocation = args[2]:gsub(\"^%s*(.-)%s*$\", \"%1\")!@#&	statsLocation = rootFolder .. \"/\" .. website .. \"_stats\"!@#&	passwordDataLocation = rootFolder .. \"/.\" .. website .. \"_password\"!@#&else!@#&	print(\"Invalid Arguments! D:\")!@#&	error()!@#&end!@#&!@#&!@#&--  -------- Utility Functions!@#&!@#&local function isAdvanced()!@#&	if term.isColor then return term.isColor()!@#&	else return false end!@#&end!@#&!@#&local function oldPullEvent(ex)!@#&	local event, p1, p2, p3, p4, p5 = os.pullEventRaw(ex)!@#&	if event == \"terminate\" then!@#&		print(\"Terminated\")!@#&		error()!@#&	else!@#&		return event, p1, p2, p3, p4, p5!@#&	end!@#&end!@#&!@#&--  Drawing!@#&!@#&local function printWithType(t, func)!@#&	if type(t) == \"table\" then!@#&		for _, v in pairs(t) do env.pcall(function() printWithType(v, func) end) end!@#&	else func(tostring(t)) end!@#&end!@#&!@#&local function centerWrite(text)!@#&	printWithType(text, function(t)!@#&		local x, y = term.getCursorPos()!@#&		term.setCursorPos(math.ceil((w + 1)/2 - t:len()/2), y)!@#&		write(t)!@#&	end)!@#&end!@#&!@#&local function centerPrint(text)!@#&	printWithType(text, function(t)!@#&		local x, y = term.getCursorPos()!@#&		term.setCursorPos(math.ceil((w + 2)/2 - t:len()/2), y)!@#&		print(t)!@#&	end)!@#&end!@#&!@#&local function leftPrint(text)!@#&	printWithType(text, function(t)!@#&		local x, y = term.getCursorPos()!@#&		term.setCursorPos(1, y)!@#&		print(t)!@#&	end)!@#&end!@#&!@#&local function rightPrint(text)!@#&	printWithType(text, function(t)!@#&		local x, y = term.getCursorPos()!@#&		term.setCursorPos(w - t:len() + 1, y)!@#&		print(t)!@#&	end)!@#&end!@#&!@#&local function clearPage(r)!@#&	-- Site title!@#&	title = \"Hosting: rdnt://\" .. website!@#&!@#&	-- Address Bar!@#&	term.setTextColor(colors[theme[\"address-bar-text\"]])!@#&	term.setCursorPos(2, 1)!@#&	term.setBackgroundColor(colors[theme[\"address-bar-background\"]])!@#&	term.clearLine()!@#&	term.setCursorPos(2, 1)!@#&	if title:len() > 42 then title = title:sub(1, 39) .. \"...\" end!@#&	write(title)!@#&!@#&	-- Records!@#&	term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&	for i = 1, 11 do!@#&		term.setCursorPos(1, i + 7) !@#&		centerWrite(string.rep(\" \", 47)) !@#&	end!@#&	if r == true then!@#&		for i, v in ipairs(recordLines) do!@#&			term.setCursorPos(5, i + 8)!@#&			write(v)!@#&		end!@#&	end!@#&!@#&	term.setBackgroundColor(colors.black)!@#&	term.setTextColor(colors.white)!@#&	print(\"\")!@#&end!@#&!@#&!@#&--  Prompt!@#&!@#&local function prompt(list)!@#&	if isAdvanced() then!@#&		for _, v in pairs(list) do!@#&			if v.bg then term.setBackgroundColor(v.bg) end!@#&			if v.tc then term.setTextColor(v.tc) end!@#&			if v[2] == -1 then v[2] = math.ceil((w + 1)/2 - (v[1]:len() + 6)/2) end!@#&!@#&			term.setCursorPos(v[2], v[3])!@#&			write(\"[- \" .. v[1])!@#&			term.setCursorPos(v[2] + v[1]:len() + 3, v[3])!@#&			write(\" -]\")!@#&		end!@#&!@#&		while true do!@#&			local e, but, x, y = os.pullEvent()!@#&			if e == \"mouse_click\" then!@#&				for _, v in pairs(list) do!@#&					if x >= v[2] and x <= v[2] + v[1]:len() + 5 and y == v[3] then!@#&						return v[1]!@#&					end!@#&				end!@#&			end!@#&		end!@#&	else!@#&		for _, v in pairs(list) do!@#&			term.setBackgroundColor(colors.black)!@#&			term.setTextColor(colors.white)!@#&			if v[2] == -1 then v[2] = math.ceil((w + 1)/2 - (v[1]:len() + 4)/2) end!@#&!@#&			term.setCursorPos(v[2], v[3])!@#&			write(\"  \" .. v[1])!@#&			term.setCursorPos(v[2] + v[1]:len() + 2, v[3])!@#&			write(\"  \")!@#&		end!@#&!@#&		local key1 = dir == \"horizontal\" and 203 or 200!@#&		local key2 = dir == \"horizontal\" and 205 or 208!@#&!@#&		local curSel = 1!@#&		term.setCursorPos(list[curSel][2], list[curSel][3])!@#&		write(\"[\")!@#&		term.setCursorPos(list[curSel][2] + list[curSel][1]:len() + 3, list[curSel][3])!@#&		write(\"]\")!@#&		while true do!@#&			local e, key = os.pullEvent()!@#&			term.setCursorPos(list[curSel][2], list[curSel][3])!@#&			write(\" \")!@#&			term.setCursorPos(list[curSel][2] + list[curSel][1]:len() + 3, list[curSel][3])!@#&			write(\" \")!@#&			if e == \"key\" and key == key1 and curSel > 1 then!@#&				curSel = curSel - 1!@#&			elseif e == \"key\" and key == key2 and curSel < #list then!@#&				curSel = curSel + 1!@#&			elseif e == \"key\" and key == 28 then!@#&				return list[curSel][1]!@#&			end!@#&			term.setCursorPos(list[curSel][2], list[curSel][3])!@#&			write(\"[\")!@#&			term.setCursorPos(list[curSel][2] + list[curSel][1]:len() + 3, list[curSel][3])!@#&			write(\"]\")!@#&		end!@#&	end!@#&end!@#&!@#&local function scrollingPrompt(list, x, y, len, width)!@#&	local wid = width!@#&	if wid == nil then wid = w - 3 end!@#&!@#&	local function updateDisplayList(items, loc, len)!@#&		local ret = {}!@#&		for i = 1, len do!@#&			local item = items[i + loc - 1]!@#&			if item ~= nil then table.insert(ret, item) end!@#&		end!@#&		return ret!@#&	end!@#&!@#&	if isAdvanced() then!@#&		local function draw(a)!@#&			for i, v in ipairs(a) do!@#&				term.setCursorPos(x, y + i - 1)!@#&				write(string.rep(\" \", wid))!@#&				term.setCursorPos(x, y + i - 1)!@#&				write(\"[ \" .. v:sub(1, wid - 5))!@#&				term.setCursorPos(wid + x - 2, y + i - 1)!@#&				write(\"  ]\")!@#&			end!@#&		end!@#&!@#&		local loc = 1!@#&		local disList = updateDisplayList(list, loc, len)!@#&		draw(disList)!@#&		!@#&		while true do!@#&			local e, but, clx, cly = os.pullEvent()!@#&			if e == \"key\" and but == 200 and loc > 1 then!@#&				loc = loc - 1!@#&				disList = updateDisplayList(list, loc, len)!@#&				draw(disList)!@#&			elseif e == \"key\" and but == 208 and loc + len - 1 < #list then!@#&				loc = loc + 1!@#&				disList = updateDisplayList(list, loc, len)!@#&				draw(disList)!@#&			elseif e == \"mouse_scroll\" and but > 0 and loc + len - 1 < #list then!@#&				loc = loc + but!@#&				disList = updateDisplayList(list, loc, len)!@#&				draw(disList)!@#&			elseif e == \"mouse_scroll\" and but < 0 and loc > 1 then!@#&				loc = loc + but!@#&				disList = updateDisplayList(list, loc, len)!@#&				draw(disList)!@#&			elseif e == \"mouse_click\" then!@#&				for i, v in ipairs(disList) do!@#&					if clx >= x and clx <= x + wid and cly == i + y - 1 then!@#&						return v!@#&					end!@#&				end!@#&			end!@#&		end!@#&	else!@#&		local function draw(a)!@#&			for i, v in ipairs(a) do!@#&				term.setCursorPos(x, y + i - 1)!@#&				write(string.rep(\" \", wid))!@#&				term.setCursorPos(x, y + i - 1)!@#&				write(\"[ ] \" .. v:sub(1, wid - 5))!@#&			end!@#&		end!@#&!@#&		local loc = 1!@#&		local curSel = 1!@#&		local disList = updateDisplayList(list, loc, len)!@#&		draw(disList)!@#&		term.setCursorPos(x + 1, y + curSel - 1)!@#&		write(\"x\")!@#&!@#&		while true do!@#&			local e, key = os.pullEvent()!@#&			term.setCursorPos(x + 1, y + curSel - 1)!@#&			write(\" \")!@#&			if e == \"key\" and key == 200 then!@#&				if curSel > 1 then!@#&					curSel = curSel - 1!@#&				elseif loc > 1 then!@#&					loc = loc - 1!@#&					disList = updateDisplayList(list, loc, len)!@#&					draw(disList)!@#&				end!@#&			elseif e == \"key\" and key == 208 then!@#&				if curSel < #disList then!@#&					curSel = curSel + 1!@#&				elseif loc + len - 1 < #list then!@#&					loc = loc + 1!@#&					disList = updateDisplayList(list, loc, len)!@#&					draw(disList)!@#&				end!@#&			elseif e == \"key\" and key == 28 then!@#&				return list[curSel + loc - 1]!@#&			end!@#&			term.setCursorPos(x + 1, y + curSel - 1)!@#&			write(\"x\")!@#&		end!@#&	end!@#&end!@#&!@#&!@#&--  -------- Themes!@#&!@#&local defaultTheme = {!@#&	[\"address-bar-text\"] = \"white\",!@#&	[\"address-bar-background\"] = \"gray\",!@#&	[\"address-bar-base\"] = \"lightGray\",!@#&	[\"top-box\"] = \"red\",!@#&	[\"bottom-box\"] = \"orange\",!@#&	[\"text-color\"] = \"white\",!@#&	[\"background\"] = \"gray\"!@#&} local originalTheme = {!@#&	[\"address-bar-text\"] = \"white\",!@#&	[\"address-bar-background\"] = \"black\",!@#&	[\"address-bar-base\"] = \"black\",!@#&	[\"top-box\"] = \"black\",!@#&	[\"bottom-box\"] = \"black\",!@#&	[\"text-color\"] = \"white\",!@#&	[\"background\"] = \"black\"!@#&}!@#&!@#&local function loadTheme(path)!@#&	if fs.exists(path) and not fs.isDir(path) then!@#&		local a = {}!@#&		local f = io.open(path, \"r\")!@#&		local l = f:read(\"*l\")!@#&		while l do!@#&			l = l:gsub(\"^%s*(.-)%s*$\", \"%1\")!@#&			if l and l ~= \"\" and l ~= \"\\n\" and l:sub(1, 2) ~= \"--\" then!@#&				local k, v = string.match(l, \"^(%a+)=(%a+)\")!@#&				if k and v then a[k] = v!@#&				else return nil end!@#&			end!@#&			l = f:read(\"*l\")!@#&		end!@#&		f:close()!@#&		return a!@#&	end!@#&end!@#&!@#&!@#&--  -------- Filesystem!@#&!@#&local function download(url, path)!@#&	for i = 1, 3 do!@#&		local response = http.get(url)!@#&		if response then!@#&			local data = response.readAll()!@#&			response.close()!@#&			local f = io.open(path, \"w\")!@#&			f:write(data)!@#&			f:close()!@#&			return true!@#&		end!@#&	end!@#&!@#&	return false!@#&end!@#&!@#&local function validateFilesystem()!@#&	if not fs.exists(rootFolder) or not fs.exists(serverFolder) or not fs.exists(dataLocation) or!@#&			not fs.exists(serverLocation) or not fs.exists(dataLocation .. \"/home\") then!@#&		term.setBackgroundColor(colors[theme[\"background\"]])!@#&		term.setTextColor(colors[theme[\"text-color\"]])!@#&		term.clear()!@#&		term.setCursorPos(1, 1)!@#&		print(\"\")!@#&		term.setTextColor(colors[theme[\"text-color\"]])!@#&		term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&		centerPrint(string.rep(\" \", 47))!@#&		centerWrite(string.rep(\" \", 47))!@#&		centerPrint(\"Invalid Filesystem!\")!@#&		centerPrint(string.rep(\" \", 47))!@#&		print(\"\")!@#&!@#&		term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&		centerPrint(string.rep(\" \", 47))!@#&		centerPrint(\"  The files required to run this server        \")!@#&		centerPrint(\"  cannot be found! Run Firewolf to create      \")!@#&		centerPrint(\"  them!                                        \")!@#&		centerPrint(string.rep(\" \", 47))!@#&		centerWrite(string.rep(\" \", 47))!@#&		if isAdvanced() then centerPrint(\"Click to exit...\")!@#&		else centerPrint(\"Press any key to exit...\") end!@#&		centerPrint(string.rep(\" \", 47))!@#&!@#&		while true do!@#&			local e = os.pullEvent()!@#&			if e == \"key\" or e == \"mouse_click\" then break end!@#&		end!@#&!@#&		return false!@#&	else!@#&		return true!@#&	end!@#&end!@#&!@#&local function updateClient()!@#&	local updateLocation = rootFolder .. \"/server-update\"!@#&	fs.delete(updateLocation)!@#&!@#&	download(serverURL, updateLocation)!@#&	local a = io.open(updateLocation, \"r\")!@#&	local b = io.open(serverLocation, \"r\")!@#&	local new = a:read(\"*a\")!@#&	local cur = b:read(\"*a\")!@#&	a:close()!@#&	b:close()!@#&!@#&	if cur ~= new then!@#&		fs.delete(serverLocation)!@#&		fs.move(updateLocation, serverLocation)!@#&		shell.run(serverLocation, args[1], args[2])!@#&		error()!@#&	else!@#&		fs.delete(updateLocation)!@#&	end!@#&end!@#&!@#&!@#&--  -------- Loading!@#&!@#&local serverAPIContent = [[!@#&!@#&--  !@#&--  Custom Server API!@#&--  !@#&!@#&-- Notes:!@#&-- - These functions are called when events occur!@#&-- - Their names are required to be kept the same!@#&-- - These functions must be able to execute!@#&--   instantly, else your server may be DDoS-able!@#&!@#&!@#&uponSuccessfulRequest = function(page, id)!@#&	-- Called when a request for a page is successful!@#&!@#&	-- Your Code Here...!@#&end!@#&!@#&uponFailedRequest = function(page, id)!@#&	-- Called when a request for a page is unsuccessful!@#&!@#&	-- Your Code Here...!@#&end!@#&!@#&uponAnyOtherMessage = function(message, id)!@#&	-- Called when any rendet message is received!@#&	-- that is not requesting a page!@#&!@#&	-- Your Code Here...!@#&end!@#&!@#&uponAnyMessage = function(message, id)!@#&	-- Called when any rednet message is received!@#&!@#&	-- Your Code Here...!@#&end!@#&!@#&parallelWithServer = function()!@#&	-- Runs in a parallel alongside the server!@#&!@#&	-- Your Code Here...!@#&end!@#&!@#&local function uponServerApiLoad()!@#&	-- Called when this Server API is loaded!@#&!@#&	-- Your Code Here...!@#&end!@#&!@#&uponServerApiLoad()!@#&!@#&]]!@#&!@#&local function loadServerAPI()!@#&	if not fs.exists(dataLocation .. \"/serverapi\") then!@#&		local f = io.open(dataLocation .. \"/serverapi\", \"w\")!@#&		f:write(serverAPIContent)!@#&		f:close()!@#&	end!@#&!@#&	shell.run(dataLocation .. \"/serverapi\")!@#&	if type(uponSuccessfulRequest) ~= \"function\" then!@#&		uponSuccessfulRequest = nil!@#&	end if type(uponFailedRequest) ~= \"function\" then!@#&		uponFailedRequest = nil!@#&	end if type(uponAnyOtherMessage) ~= \"function\" then!@#&		uponAnyOtherMessage = nil!@#&	end if type(uponAnyMessage) ~= \"function\" then!@#&		uponAnyMessage = nil!@#&	end if type(parallelWithServer) ~= \"function\" then!@#&		parallelWithServer = nil!@#&	end!@#&end!@#&!@#&local function loadPages(loc)!@#&	local a = fs.list(loc)!@#&	local p = {}!@#&	for i = 1, #a do!@#&		if not fs.isDir(loc .. \"/\" .. a[i]) then!@#&			local f = io.open(loc .. \"/\" .. a[i])!@#&			local cont = f:read(\"*a\")!@#&			f:close()!@#&!@#&			p[loc .. \"/\" .. a[i]] = cont!@#&		else!@#&			local b = loadPages(loc .. \"/\" .. a[i])!@#&			for x = 1, #b do!@#&				table.insert(p, b[x])!@#&			end!@#&		end!@#&	end!@#&!@#&	return p!@#&end!@#&!@#&local function checkForModem()!@#&	while true do!@#&		local present = false!@#&		for _, v in pairs(rs.getSides()) do!@#&			if peripheral.getType(v) == \"modem\" then!@#&				rednet.open(v)!@#&				present = true!@#&				break!@#&			end!@#&		end!@#&!@#&		if not present then!@#&			term.setTextColor(colors[theme[\"text-color\"]])!@#&			term.setBackgroundColor(colors[theme[\"background\"]])!@#&			term.clear()!@#&			term.setCursorPos(1, 2)!@#&			print(\"\")!@#&			term.setTextColor(colors[theme[\"text-color\"]])!@#&			term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&			centerPrint(string.rep(\" \", 43))!@#&			centerWrite(string.rep(\" \", 43))!@#&			centerPrint(\"No Modem Attached! D:\")!@#&			centerPrint(string.rep(\" \", 43))!@#&			print(\"\")!@#&!@#&			term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&			centerPrint(string.rep(\" \", 43))!@#&			centerWrite(string.rep(\" \", 43))!@#&			centerPrint(\"No wireless modem was found on this\")!@#&			centerWrite(string.rep(\" \", 43))!@#&			centerPrint(\"computer, and Firewolf is not able to\")!@#&			centerWrite(string.rep(\" \", 43))!@#&			centerPrint(\"run without one!\")!@#&			centerPrint(string.rep(\" \", 43))!@#&			centerWrite(string.rep(\" \", 43))!@#&			centerPrint(\"Waiting for a modem to be attached...\")!@#&			centerWrite(string.rep(\" \", 43))!@#&			if isAdvanced() then centerPrint(\"Click to exit...\")!@#&			else centerPrint(\"Press any key to exit...\") end!@#&			centerPrint(string.rep(\" \", 43))!@#&!@#&			while true do!@#&				local e, id = os.pullEvent()!@#&				if e == \"key\" or e == \"mouse_click\" then return false!@#&				elseif e == \"peripheral\" then break end!@#&			end!@#&		else!@#&			return true!@#&		end!@#&	end!@#&end!@#&!@#&!@#&--  -------- Respond to Messages!@#&!@#&local i = 1!@#&local function record(text)!@#&	local oldX, oldY = term.getCursorPos()!@#&	local a = tostring(i) .. \":\" .. string.rep(\" \", 4 - tostring(i):len()) .. text!@#&	table.insert(totalRecordLines, a)!@#&	if #recordLines > 8 then table.remove(recordLines, 1) end!@#&	table.insert(recordLines, a)!@#&!@#&	if enableRecording then clearPage(true) end!@#&	i = i + 1!@#&	term.setCursorPos(oldX, oldY)!@#&	if enableRecording then!@#&	term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&	term.setTextColor(colors[theme[\"text-color\"]])!@#&	end!@#&end!@#&!@#&local function respondToEvents()!@#&	if uponSuccessfulRequest == nil or uponFailedRequest == nil or uponAnyMessage == nil or !@#&			uponAnyOtherMessage == nil or parallelWithServer == nil then!@#&		record(\"Warning - Failed To Load Server API:\")!@#&		if uponSuccessfulRequest == nil then record(\" - uponSuccessfulRequest()\") end!@#&		if uponFailedRequest == nil then record(\" - uponFailedRequest()\") end!@#&		if uponAnyMessage == nil then record(\" - uponAnyMessage()\") end!@#&		if uponAnyOtherMessage == nil then record(\" - uponAnyOtherMessage()\") end!@#&		if parallelWithServer == nil then record(\" - parallelWithServer()\") end!@#&	else record(\"Loaded Server API\") end!@#&!@#&	local writingClock = os.clock()!@#&	local ignoreClock = os.clock()!@#&	while true do!@#&		if os.clock() - ignoreClock < 6 then!@#&			for k, v in pairs(suspected) do!@#&				if v > 10 then table.insert(ignoreDatabase, tostring(k)) end!@#&			end!@#&		else!@#&			ignoreDatabase = {}!@#&			suspected = {}!@#&			ignoreClock = os.clock()!@#&		end!@#&!@#&		local e, id, mes = os.pullEvent()!@#&!@#&		local ignore = false!@#&		for _, v in pairs(ignoreDatabase) do!@#&			if tostring(id) == v then ignore = true break end!@#&		end for _, v in pairs(permantentIgnoreDatabase) do!@#&			if tostring(id) == v then ignore = true break end!@#&		end!@#&!@#&		if e == \"rednet_message\" and enableResponse == true and not ignore then!@#&			if mes == website or mes == website .. \"/\" or mes == website .. \"/home\" then!@#&				if suspected[tostring(id)] then suspected[tostring(id)] = suspected[tostring(id)] + 1!@#&				else suspected[tostring(id)] = 1 end!@#&				for i = 1, 3 do rednet.send(id, pages[dataLocation .. \"/home\"]) end!@#&				record(\"/home : \" .. tostring(id))!@#&				visits = visits + 1!@#&!@#&				if uponSuccessfulRequest ~= nil then uponSuccessfulRequest(\"/home\", id) end!@#&			elseif mes:find(\"/\") then!@#&				local a = mes:sub(1, mes:find(\"/\") - 1)!@#&				if a == website then!@#&					if suspected[tostring(id)] then !@#&						suspected[tostring(id)] = suspected[tostring(id)] + 1!@#&					else suspected[tostring(id)] = 1 end!@#&					local b = mes:sub(mes:find(\"/\"), -1)!@#&					local c = b!@#&					if c:len() > 18 then c = c:sub(1, 15) .. \"...\" end!@#&					if pages[dataLocation .. b] and b ~= \"/serverapi\" then!@#&						for i = 1, 3 do rednet.send(id, pages[dataLocation .. b]) end!@#&						record(c .. \" : \" .. id)!@#&						visits = visits + 1!@#&!@#&						if uponSuccessfulRequest ~= nil then uponSuccessfulRequest(b, id) end!@#&					else!@#&						record(\"Failed - \" .. c .. \" : \" .. id)!@#&						if uponFailedRequest ~= nil then uponFailedRequest(b, id) end!@#&					end!@#&				end!@#&			elseif mes == \"firewolf.broadcast.dns.list\" then!@#&				if suspected[tostring(id)] then suspected[tostring(id)] = suspected[tostring(id)] + 1!@#&				else suspected[tostring(id)] = 1 end!@#&				rednet.send(id, \"firewolf-site:\" .. website)!@#&				searches = searches + 1!@#&			else!@#&				if uponAnyOtherMessage ~= nil then uponAnyOtherMessage(mes, id) end!@#&			end!@#&!@#&			if uponAnyMessage ~= nil then uponAnyMessage(mes, id) end!@#&		elseif e == event_stopServer then!@#&			return!@#&		end!@#&!@#&		-- Save stats!@#&		if os.clock() - writingClock > 5 then!@#&			local f = io.open(statsLocation, \"w\")!@#&			f:write(tostring(visits) .. \"\\n\" .. tostring(searches) .. \"\\n\" ..!@#&				textutils.serialize(permantentIgnoreDatabase))!@#&			f:close()!@#&			writingClock = os.clock()!@#&		end!@#&	end!@#&end!@#&!@#&!@#&--  -------- GUI!@#&!@#&local function edit()!@#&	openAddressBar = false!@#&	local oldLoc = shell.dir()!@#&	local commandHis = {}!@#&	local dir = dataLocation!@#&	term.setBackgroundColor(colors.black)!@#&	term.setTextColor(colors.white)!@#&	term.clear()!@#&	term.setCursorPos(1, 1)!@#&	print(\"\")!@#&	print(\" Server Shell Editing\")!@#&	print(\" Type 'exit' to return to Firewolf.\")!@#&	print(\" The 'home' file is the index of your site\")!@#&	print(\"\")!@#&!@#&	local allowed = {\"move\", \"mv\", \"cp\", \"copy\", \"drive\", \"delete\", \"rm\", \"edit\", !@#&		\"eject\", \"exit\", \"help\", \"id\", \"monitor\", \"rename\", \"alias\", \"clear\",!@#&		\"paint\", \"firewolf\", \"lua\", \"redstone\", \"rs\", \"redprobe\", \"redpulse\", \"programs\",!@#&		\"redset\", \"reboot\", \"hello\", \"label\", \"list\", \"ls\", \"easter\", \"pastebin\", \"dir\"}!@#&	!@#&	while true do!@#&		shell.setDir(serverFolder .. \"/\" .. website)!@#&		term.setBackgroundColor(colors.black)!@#&		if isAdvanced() then term.setTextColor(colors.yellow)!@#&		else term.setTextColor(colors.white) end!@#&		write(\"> \")!@#&		term.setTextColor(colors.white)!@#&		local line = read(nil, commandHis)!@#&		table.insert(commandHis, line)!@#&!@#&		local words = {}!@#&		for m in string.gmatch(line, \"[^ \\t]+\") do!@#&			local a = m:gsub(\"^%s*(.-)%s*$\", \"%1\")!@#&			table.insert(words, a)!@#&		end!@#&!@#&		local com = words[1]!@#&		if com == \"exit\" then!@#&			break!@#&		elseif com then!@#&			local a = false!@#&			for _, v in pairs(allowed) do!@#&				if com == v then a = true break end!@#&			end!@#&!@#&			if a then!@#&				term.setBackgroundColor(colors.black)!@#&				term.setTextColor(colors.white)!@#&				shell.run(com, unpack(words, 2))!@#&			else!@#&				term.setTextColor(colors.red)!@#&				print(\"Program Not Allowed!\")!@#&			end!@#&		end!@#&	end!@#&	shell.setDir(oldLoc)!@#&end!@#&!@#&local function addLock()!@#&	clearPage()!@#&	term.setCursorPos(1, 8)!@#&	term.setTextColor(colors[theme[\"text-color\"]])!@#&	term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&	for i = 1, 11 do centerPrint(string.rep(\" \", 47)) end!@#&	term.setCursorPos(5, 9)!@#&	write(\"Enter a password to secure your\")!@#&	term.setCursorPos(5, 10)!@#&	write(\"server from being managed by others:\")!@#&	term.setCursorPos(5, 11)!@#&	write(\"> \")!@#&	local newPassword = read(\"*\")!@#&	if newPassword == \"\" then return end!@#&	term.setCursorPos(5, 13)!@#&	write(\"Enter the password again:\")!@#&	term.setCursorPos(5, 14)!@#&	write(\"> \")!@#&	local pass2 = read(\"*\")!@#&	if pass2 == \"\" then return!@#&	elseif pass2 == newPassword then!@#&		serverPassword = newPassword!@#&		serverLocked = false!@#&		local f = io.open(passwordDataLocation, \"w\")!@#&		f:write(newPassword)!@#&		f:close()!@#&		term.setCursorPos(5, 16)!@#&		write(\"Password Set!\")!@#&		sleep(1.3)!@#&	else!@#&		term.setCursorPos(5, 16)!@#&		print(\"Passwords did not match!\")!@#&		sleep(1.3)!@#&	end!@#&end!@#&!@#&local function manageServer()!@#&	while true do!@#&		clearPage()!@#&		term.setCursorPos(1, 8)!@#&		term.setTextColor(colors[theme[\"text-color\"]])!@#&		term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&		for i = 1, 11 do centerPrint(string.rep(\" \", 47)) end!@#&!@#&		term.setCursorPos(5, 9)!@#&		write(\"Visits: \" .. tostring(visits))!@#&		term.setCursorPos(5, 10)!@#&		write(\"Searches: \" .. tostring(searches))!@#&		local opt = \"\"!@#&		if serverPassword then!@#&			opt = prompt({{\"Manage Blocked IDs\", 9, 12}, {\"Remove Password\", 9, 13}, !@#&				{\"Delete Server\", 9, 14}, {\"Back\", 9, 16}}, \"vertical\")!@#&		else!@#&			opt = prompt({{\"Manage Blocked IDs\", 9, 12}, {\"Delete Server\", 9, 13}, !@#&				{\"Back\", 9, 15}}, \"vertical\")!@#&		end!@#&		if opt == \"Manage Blocked IDs\" then!@#&			while true do!@#&				clearPage()!@#&				term.setCursorPos(1, 8)!@#&				term.setTextColor(colors[theme[\"text-color\"]])!@#&				term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&				for i = 1, 11 do centerPrint(string.rep(\" \", 47)) end!@#&!@#&				term.setCursorPos(5, 9)!@#&				if isAdvanced() then write(\"Blocked IDs: (Click to Unblock)\")!@#&				else write(\"Blocked IDs: (Select to Unblock)\") end!@#&				local a = {\"Back\", \"Block New ID\"}!@#&				for _, v in pairs(permantentIgnoreDatabase) do!@#&					table.insert(a, v)!@#&				end!@#&!@#&				local b = scrollingPrompt(a, 5, 11, 7, 43)!@#&				if b == \"Back\" then!@#&					break!@#&				elseif b == \"Block New ID\" then!@#&					term.setCursorPos(5, 10)!@#&					write(\"ID: \")!@#&					local c = read():gsub(\"^%s*(.-)%s*$\", \"%1\")!@#&					local d = tonumber(c)!@#&					local found = false!@#&					for k, v in pairs(permantentIgnoreDatabase) do!@#&						if v == tostring(d) then found = true break end!@#&					end!@#&					if d == nil then!@#&						term.setCursorPos(1, 10)!@#&						centerWrite(string.rep(\" \", 47))!@#&						term.setCursorPos(5, 10)!@#&						write(\"Not a Valid ID!\")!@#&						sleep(1.1)!@#&					elseif found == true then!@#&						term.setCursorPos(1, 10)!@#&						centerWrite(string.rep(\" \", 47))!@#&						term.setCursorPos(5, 10)!@#&						write(\"ID Already Exists!\")!@#&						sleep(1.1)!@#&					else!@#&						term.setCursorPos(1, 10)!@#&						centerWrite(string.rep(\" \", 47))!@#&						term.setCursorPos(5, 10)!@#&						write(\"Blocked ID: \" .. c .. \"!\")!@#&						table.insert(permantentIgnoreDatabase, tostring(d))!@#&						sleep(1.1)!@#&					end!@#&				else!@#&					for i, v in ipairs(permantentIgnoreDatabase) do!@#&						if v == b then table.remove(permantentIgnoreDatabase, i) end!@#&					end!@#&				end!@#&			end!@#&		elseif opt == \"Delete Server\" then!@#&			clearPage()!@#&			term.setCursorPos(1, 8)!@#&			term.setTextColor(colors[theme[\"text-color\"]])!@#&			term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&			for i = 1, 11 do centerPrint(string.rep(\" \", 47)) end!@#&			term.setCursorPos(9, 11)!@#&			centerPrint(\"Are you sure you want to delete the server?\")!@#&			centerPrint(\"This cannot be undone!\")!@#&			local opt = prompt({{\"No\", 11, 14}, {\"Yes\", 35, 14}}, \"horizontal\")!@#&			if opt == \"Yes\" then!@#&				fs.delete(dataLocation)!@#&				os.queueEvent(event_stopServer)!@#&				return!@#&			end!@#&		elseif opt == \"Remove Password\" then!@#&			clearPage()!@#&			term.setCursorPos(1, 8)!@#&			term.setTextColor(colors[theme[\"text-color\"]])!@#&			term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&			for i = 1, 11 do centerPrint(string.rep(\" \", 47)) end!@#&			term.setCursorPos(9, 11)!@#&			print(\"Enter your password:\")!@#&			term.setCursorPos(9, 12)!@#&			write(\"> \")!@#&			local oldPass = read(\"*\")!@#&			if oldPass == \"\" then!@#&			elseif oldPass == serverPassword then!@#&				fs.delete(passwordDataLocation)!@#&				serverPassword = nil!@#&				serverLocked = false!@#&				term.setCursorPos(9, 14)!@#&				print(\"Password Removed!\")!@#&				sleep(1.3)!@#&				break!@#&			else!@#&				term.setCursorPos(9, 14)!@#&				print(\"Password Incorrect! Locking Server...\")!@#&				os.pullEvent = os.pullEventRaw!@#&				serverLocked = true!@#&				sleep(1.3)!@#&				break!@#&			end!@#&		elseif opt == \"Back\" then!@#&			break!@#&		end!@#&	end!@#&end!@#&!@#&local function interface()!@#&	local opt = \"\"!@#&	while true do!@#&		term.setBackgroundColor(colors[theme[\"background\"]])!@#&		term.setTextColor(colors[theme[\"text-color\"]])!@#&		term.clear()!@#&		term.setCursorPos(1, 1)!@#&		clearPage(true)!@#&		term.setCursorPos(1, 2)!@#&		print(\"\")!@#&		term.setTextColor(colors[theme[\"text-color\"]])!@#&		term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&		for i = 1, 4 do centerPrint(string.rep(\" \", 47)) end!@#&		print(\"\")!@#&		term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&!@#&		if enableResponse == false then p1 = \"Unpause Server\" end!@#&		term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&		if not serverLocked and not serverPassword then!@#&			os.pullEvent = oldPullEvent!@#&			opt = prompt({{\"Add Lock\", 5, 4}, {\"Edit\", 5, 5}, {\"Manage\", w - 15, 4}, !@#&				{\"Stop\", w - 13, 5}}, \"vertical\")!@#&		elseif not serverLocked and serverPassword then!@#&			opt = prompt({{\"Lock Server\", 5, 4}, {\"Edit\", 5, 5}, {\"Manage\", w - 15, 4}, !@#&				{\"Stop\", w - 13, 5}}, \"vertical\")!@#&		elseif serverLocked then!@#&			while true do!@#&				enableRecording = true!@#&				term.setCursorPos(1, 2)!@#&				print(\"\")!@#&				term.setTextColor(colors[theme[\"text-color\"]])!@#&				term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&				for i = 1, 4 do centerPrint(string.rep(\" \", 47)) end!@#&				term.setCursorPos(5, 4)!@#&				print(\"Enter Password:\")!@#&				term.setCursorPos(5, 5)!@#&				write(\"> \")!@#&				local enteredPassword = read(\"*\")!@#&				if enteredPassword == serverPassword then!@#&					term.setCursorPos(1, 2)!@#&					print(\"\")!@#&					term.setTextColor(colors[theme[\"text-color\"]])!@#&					term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&					for i = 1, 4 do centerPrint(string.rep(\" \", 47)) end!@#&					term.setCursorPos(5, 4)!@#&					write(\"Password Accepted!\")!@#&					opt = \"\"!@#&					serverLocked = false!@#&					os.pullEvent = oldPullEvent!@#&					sleep(1.3)!@#&					break!@#&				else!@#&					term.setCursorPos(1, 2)!@#&					print(\"\")!@#&					term.setTextColor(colors[theme[\"text-color\"]])!@#&					term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&					for i = 1, 4 do centerPrint(string.rep(\" \", 47)) end!@#&					term.setCursorPos(5, 4)!@#&					write(\"Password Incorrect!\")!@#&					sleep(1.3)!@#&				end!@#&			end!@#&		end!@#&!@#&		if opt == p1 then!@#&			enableResponse = not enableResponse!@#&		elseif opt == \"Manage\" then!@#&			enableRecording = false!@#&			manageServer()!@#&			enableRecording = true!@#&		elseif opt == \"Edit\" then!@#&			enableRecording = false!@#&			term.setBackgroundColor(colors.black)!@#&			term.setTextColor(colors.white)!@#&			term.clear()!@#&			term.setCursorPos(1, 1)!@#&			edit()!@#&!@#&			term.clear()!@#&			pages = loadPages(dataLocation)!@#&			loadServerAPI()!@#&			if uponSuccessfulRequest == nil or uponFailedRequest == nil or uponAnyMessage == nil or !@#&					uponAnyOtherMessage == nil or parallelWithServer == nil then!@#&				record(\"Warning - Failed To Load Server API:\")!@#&				if uponSuccessfulRequest == nil then record(\" - uponSuccessfulRequest()\") end!@#&				if uponFailedRequest == nil then record(\" - uponFailedRequest()\") end!@#&				if uponAnyMessage == nil then record(\" - uponAnyMessage()\") end!@#&				if uponAnyOtherMessage == nil then record(\" - uponAnyOtherMessage()\") end!@#&				if parallelWithServer == nil then record(\" - parallelWithServer()\") end!@#&			else record(\"Re-Loaded Server API\") end!@#&			enableRecording = true!@#&		elseif opt == \"Add Lock\" then!@#&			enableRecording = false!@#&			addLock()!@#&			enableRecording = false!@#&		elseif opt == \"Lock Server\" then!@#&			os.pullEvent = os.pullEventRaw!@#&			serverLocked = true!@#&			term.setCursorPos(1, 2)!@#&			print(\"\")!@#&			term.setTextColor(colors[theme[\"text-color\"]])!@#&			term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&			for i = 1, 4 do centerPrint(string.rep(\" \", 47)) end!@#&			term.setCursorPos(5, 4)!@#&			print(\"Server Locked!\")!@#&			sleep(2)!@#&		elseif opt == \"Stop\" then!@#&			os.queueEvent(event_stopServer)!@#&			return!@#&		end!@#&	end!@#&end!@#&!@#&!@#&--  -------- Main!@#&!@#&local function main()!@#&	-- Logo!@#&	term.setBackgroundColor(colors[theme[\"background\"]])!@#&	term.setTextColor(colors[theme[\"text-color\"]])!@#&	term.clear()!@#&	term.setCursorPos(1, 2)!@#&	term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&	leftPrint(string.rep(\" \", 47))!@#&	leftPrint([[          ______ ____ ____   ______            ]])!@#&	leftPrint([[ ------- / ____//  _// __ \\ / ____/            ]])!@#&	leftPrint([[ ------ / /_    / / / /_/ // __/               ]])!@#&	leftPrint([[ ----- / __/  _/ / / _  _// /___               ]])!@#&	leftPrint([[ ---- / /    /___//_/ |_|/_____/               ]])!@#&	leftPrint([[ --- / /       _       __ ____   __     ______ ]])!@#&	leftPrint([[ -- /_/       | |     / // __ \\ / /    / ____/ ]])!@#&	leftPrint([[              | | /| / // / / // /    / /_     ]])!@#&	leftPrint([[              | |/ |/ // /_/ // /___ / __/     ]])!@#&	leftPrint([[              |__/|__/ \\____//_____//_/        ]])!@#&	leftPrint(string.rep(\" \", 47))!@#&	print(\"\\n\")!@#&	term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&!@#&	rightPrint(string.rep(\" \", 27 + version:len()))!@#&	rightPrint(\"  Loading Firewolf Server \" .. version .. \" \")!@#&	rightPrint(string.rep(\" \", 27 + version:len()))!@#&!@#&	-- Filesystem!@#&	if not validateFilesystem() then return end!@#&!@#&	-- Update!@#&	if autoupdate then updateClient() end!@#&!@#&	-- Load!@#&	pages = loadPages(dataLocation)!@#&	loadServerAPI()!@#&	if fs.exists(statsLocation) then!@#&		local f = io.open(statsLocation, \"r\")!@#&		local a = tonumber(f:read(\"*l\"))!@#&		local b = tonumber(f:read(\"*l\"))!@#&		local c = f:read(\"*l\")!@#&		if a then visits = a end!@#&		if b then searches = b end!@#&		if c then permantentIgnoreDatabase = textutils.unserialize(c) end!@#&		f:close()!@#&	end!@#&	if not checkForModem() then return end!@#&!@#&	-- Start UI!@#&	parallel.waitForAll(respondToEvents, interface, parallelWithServer)!@#&end!@#&!@#&local function startup()!@#&	-- HTTP API!@#&	if not http then!@#&		term.setTextColor(colors[theme[\"text-color\"]])!@#&		term.setBackgroundColor(colors[theme[\"background\"]])!@#&		term.clear()!@#&		term.setCursorPos(1, 2)!@#&		term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&		leftPrint(string.rep(\" \", 24))!@#&		leftPrint(\" HTTP Not Enabled!  \")!@#&		leftPrint(string.rep(\" \", 24))!@#&		print(\"\")!@#&!@#&		term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&		rightPrint(string.rep(\" \", 36))!@#&		rightPrint(\"  Firewolf is unable to run without \")!@#&		rightPrint(\"       the HTTP Enabled! Please \")!@#&		rightPrint(\"    enable it in your ComputerCraft \")!@#&		rightPrint(\"                            Config! \")!@#&		rightPrint(string.rep(\" \", 36))!@#&!@#&		if isAdvanced() then rightPrint(\"                   Click to exit... \")!@#&		else rightPrint(\"           Press any key to exit... \") end!@#&		rightPrint(string.rep(\" \", 36))!@#&!@#&		while true do!@#&			local e, but, x, y = os.pullEvent()!@#&			if e == \"mouse_click\" or e == \"key\" then break end!@#&		end!@#&!@#&		return false !@#&	end!@#&!@#&	-- Turtle!@#&	if turtle then!@#&		term.clear()!@#&		term.setCursorPos(1, 2)!@#&		centerPrint(\"Advanced Comptuer Required!\")!@#&		print(\"\\n\")!@#&		centerPrint(\"This version of Firewolf requires\")!@#&		centerPrint(\"an Advanced Comptuer to run!\")!@#&		print(\"\")!@#&		centerPrint(\"Turtles may not be used to run\")!@#&		centerPrint(\"Firewolf! :(\")!@#&		print(\"\")!@#&		centerPrint(\"Press any key to exit...\")!@#&!@#&		os.pullEvent(\"key\")!@#&		return false!@#&	end!@#&!@#&	-- Run!@#&	local _, err = pcall(main)!@#&	if err and err ~= \"parallel:22: Terminated\" then!@#&		term.setTextColor(colors[theme[\"text-color\"]])!@#&		term.setBackgroundColor(colors[theme[\"background\"]])!@#&		term.clear()!@#&		term.setCursorPos(1, 2)!@#&		term.setCursorBlink(false)!@#&		term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&		leftPrint(string.rep(\" \", 27))!@#&		leftPrint(\" Firewolf has Crashed! D:  \")!@#&		leftPrint(string.rep(\" \", 27))!@#&		print(\"\")!@#&		term.setBackgroundColor(colors[theme[\"background\"]])!@#&		print(\"\")!@#&		print(\"  \" .. err)!@#&		print(\"\")!@#&!@#&		term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&		rightPrint(string.rep(\" \", 41))!@#&		if autoupdate == \"true\" then!@#&			rightPrint(\"    Please report this error to 1lann or \")!@#&			rightPrint(\"  GravityScore so we are able to fix it! \")!@#&			rightPrint(\"  If this problem persists, try deleting \")!@#&			rightPrint(\"                         \" .. rootFolder .. \" \")!@#&		else!@#&			rightPrint(\"        Automatic updating is off! A new \")!@#&			rightPrint(\"     version may have have been released \")!@#&			rightPrint(\"                that may fix this error! \")!@#&			rightPrint(\"        If you didn't turn auto updating \")!@#&			rightPrint(\"             off, delete \" .. rootFolder .. \" \")!@#&		end!@#&!@#&		rightPrint(string.rep(\" \", 41))!@#&		if isAdvanced() then rightPrint(\"                        Click to exit... \")!@#&		else rightPrint(\"                Press any key to exit... \") end!@#&		rightPrint(string.rep(\" \", 41))!@#&!@#&		while true do!@#&			local e, but, x, y = os.pullEvent()!@#&			if e == \"mouse_click\" or e == \"key\" then break end!@#&		end!@#&!@#&		return false!@#&	end!@#&!@#&	return true!@#&end!@#&!@#&-- Check If Read Only!@#&if fs.isReadOnly(serverLocation) or fs.isReadOnly(rootFolder) then!@#&	print(\"Firewolf cannot modify itself or its root folder!\")!@#&	print(\"\")!@#&	print(\"This cold be caused by Firewolf being placed in\")!@#&	print(\"the rom folder, or another program may be\")!@#&	print(\"preventing the modification of Firewolf.\")!@#&!@#&	-- Reset Environment and Exit!@#&	setfenv(1, oldEnv)!@#&	error()!@#&end!@#&!@#&-- Theme!@#&if not isAdvanced() then !@#&	theme = originalTheme!@#&else!@#&	theme = loadTheme(themeLocation)!@#&	if theme == nil then theme = defaultTheme end!@#&end!@#&!@#&-- Pasword!@#&if fs.exists(passwordDataLocation) then!@#&	local f = io.open(passwordDataLocation, \"r\")!@#&	serverPassword = f:read(\"*l\")!@#&	f:close()!@#&	serverLocked = true!@#&else!@#&	serverLocked = false!@#&end!@#&!@#&-- Start!@#&startup()!@#&!@#&-- Clear!@#&term.setBackgroundColor(colors.black)!@#&term.setTextColor(colors.white)!@#&term.clear()!@#&term.setCursorPos(1, 1)!@#&centerPrint(\"Thank You for Using Firewolf Server \" .. version)!@#&centerPrint(\"Made by 1lann and GravityScore\")!@#&!@#&-- Close Rednet!@#&for _, v in pairs(rs.getSides()) do !@#&	if peripheral.getType(v) == \"modem\" then rednet.close(v) end!@#&end",["servers"]={},["user_whitelist"]="",["cache"]={},["website_data"]={},["user_blacklist"]="",["settings"]="{[\"home\"]=\"firewolf\",[\"incog\"]=\"false\",[\"auto\"]=\"true\",}",},["startup"]="os.pullEvent = os.pullEventRaw!@#&!@#&if not term.isColour() then!@#& error(\"You need an advanced computer!\", 0)!@#&elseif not http then!@#& error(\"HTTP api needs to be enabled!\", 0)!@#&end!@#&!@#&--[[ Unlocalized variables ]]--!@#&!@#&root = \"OS\"!@#&slc = 0!@#&settingsFile = \"/\"..root..\"/os.cfg\"!@#&useIdeEdit = false!@#&logged = false!@#&userFile = \"/\"..root..\"/system/.users\"!@#&!@#&--[[  LuaIde edit  ]]--!@#&if useIdeEdit == true then!@#& shell.setAlias(\"edit\", \"/\"..root..\"/programs/luaide\")!@#&end!@#&!@#&--[[  Localized variables  ]]--!@#&!@#&local endMessage = true!@#&local username = nil --dont change!@#&!@#&--[[  Functions  ]]--!@#&!@#&for i,v in ipairs(fs.list(\"/\"..root..\"/apis/\")) do!@#& os.unloadAPI(\"/\"..root..\"/apis/\"..v)!@#& os.loadAPI(\"/\"..root..\"/apis/\"..v)  !@#&end!@#&!@#&function loadSettings()!@#&  shell.run(settingsFile)!@#&  !@#&  bgColor = settings[\"bgColor\"]!@#&  textColor = settings[\"textColor\"]!@#&  barColor = settings[\"barColor\"]!@#&  bgImg = settings[\"bgImg\"]!@#&  filesImg = settings[\"filesImg\"]!@#&  snakeImg = settings[\"snakeImg\"]!@#&  fwImg = settings[\"fwImg\"]!@#&  liImg = settings[\"liImg\"]!@#&  paImg = settings[\"paImg\"]!@#&end!@#&!@#&function drawBar()!@#& term.setCursorPos(1,1)!@#& term.setBackgroundColour(barColor)!@#& term.clearLine()!@#& term.setTextColour(textColor)!@#& term.setCursorPos(3, 1)!@#& write(\"[HD-OS]\")!@#& term.setCursorPos(15, 1)!@#& write(\"[User]\")!@#& !@#& local maxX, maxY = term.getSize()!@#& term.setCursorPos(maxX-#username-3, 1)!@#& write(\"[\"..username..\"]\")!@#&end!@#&!@#&function centerPrint(text, color)!@#& if tonumber(color) then!@#&  term.setTextColour(color)!@#& else!@#&  if colors[color] ~= nil then!@#&   term.setTextColour(colors[color])!@#&  end!@#& end!@#& !@#& local xPos, yPos = term.getCursorPos()!@#& local maxX, maxY = term.getSize()!@#& term.setCursorPos(maxX/2-#text/2, yPos)!@#& print(text)!@#&end!@#&!@#&function clear()!@#& term.clear()!@#& term.setCursorPos(1,1)!@#&end!@#&!@#&function drawWall()!@#& local bg = paintutils.loadImage(bgImg)!@#& term.setBackgroundColour(bgColor)!@#& term.clear()!@#& paintutils.drawImage(bg, 1, 1)!@#& drawBar()!@#& !@#& --[[  Icon 1  ]]--!@#& local snakeIcon = paintutils.loadImage(snakeImg)!@#& paintutils.drawImage(snakeIcon, 3, 4)!@#& term.setTextColour(colors.gray)!@#& term.setCursorPos(3,9)!@#& term.setBackgroundColour(colors.white)!@#& write(\"Games\")!@#& --[[ \\Icon 1\\ ]]--!@#& !@#& ------------------!@#& !@#& --[[  Icon 2  ]]--!@#& local filesIcon = paintutils.loadImage(filesImg)!@#& paintutils.drawImage(filesIcon, 44, 5)!@#& term.setTextColour(colors.gray)!@#& term.setCursorPos(44, 10)!@#& term.setBackgroundColour(colors.white)!@#& write(\"Files\")!@#& --[[ \\Icon 2\\ ]]--!@#& !@#& ------------------!@#& !@#& --[[  Icon 3  ]]--!@#& local fwIcon = paintutils.loadImage(fwImg)!@#& paintutils.drawImage(fwIcon, 10, 12)!@#& term.setTextColour(colors.gray)!@#& term.setCursorPos(8, 17)!@#& term.setBackgroundColour(colors.white)!@#& write(\"Fire-Wolf\")!@#& --[[ \\Icon 3\\ ]]--!@#& !@#& ------------------!@#& !@#& --[[  Icon 4  ]]--!@#& local liIcon = paintutils.loadImage(liImg)!@#& paintutils.drawImage(liIcon, 26, 13)!@#& term.setTextColour(colors.white)!@#& term.setCursorPos(27, 14)!@#& write(\">_\")!@#& term.setTextColour(colors.gray)!@#& term.setCursorPos(25, 18)!@#& term.setBackgroundColour(colors.white)!@#& write(\"Lua IDE\")!@#& --[[ \\Icon 4\\ ]]--!@#& !@#& ------------------!@#& !@#& --[[  Icon 5  ]]--!@#& local paIcon = paintutils.loadImage(paImg)!@#& paintutils.drawImage(paIcon, 40, 12)!@#& term.setCursorPos(40, 17)!@#& term.setBackgroundColour(colors.white)!@#& write(\"Paint\")!@#& --[[ \\Icon 5\\ ]]--!@#&end!@#&!@#&function drawMenu1()!@#& for i=1,9 do!@#&  paintutils.drawLine(2, 1+i, 11, 1+i, colors.lightGray)!@#&  sleep(.001)!@#& end!@#& !@#& term.setCursorPos(3, 3)!@#& write(\"Reboot\")!@#& term.setCursorPos(3, 4)!@#& write(\"Shutdown\")!@#& term.setCursorPos(3, 5)!@#& write(\"Lua\")!@#& term.setCursorPos(3, 6)!@#& write(\"Shell\")!@#& term.setCursorPos(3, 7)!@#& write(\"Version\")!@#& term.setCursorPos(3, 8)!@#& write(\"Settings\")!@#& term.setCursorPos(3, 9)!@#& write(\"Exit\")!@#&end!@#&!@#&function drawMenu2()!@#& for i=1, 6 do!@#&  paintutils.drawLine(11, 1+i, 24, 1+i, colors.lightGray)!@#&  sleep(.001)!@#& end!@#& !@#& term.setTextColour(colors.gray)!@#& !@#& term.setCursorPos(12, 3)!@#& write(\"Add User\")!@#& term.setCursorPos(12, 4)!@#& write(\"Remove User\")!@#& term.setCursorPos(12, 5)!@#& write(\"List Users\")!@#& term.setCursorPos(12, 6)!@#& write(\"Log out\")!@#&end!@#&!@#&function msgBox(text, title, width, height)!@#& local maxX, maxY = term.getSize()!@#& for i=1, height do!@#&  paintutils.drawLine(maxX/2-width/2, (maxY/2-3)+i, maxX/2+width/2, (maxY/2-3)+i, colors.lightGray)!@#& end!@#& !@#& term.setCursorPos(maxX/2-#title/2, maxY/2-2)!@#& term.setTextColour(colors.gray)!@#& write(title)!@#& term.setCursorPos((maxX/2-width/2)+1, maxY/2)!@#& term.setBackgroundColour(colors.white)!@#& write(text)!@#& term.setBackgroundColour(colors.lightGray)!@#& local pullKeyText = \"Pull any event\"!@#& term.setCursorPos((maxX/2-#pullKeyText/2)+1, maxY/2+2)!@#& write(pullKeyText)!@#& os.pullEvent()!@#&end!@#&!@#&function checkUser(name, pwd)!@#& A = fs.open(userFile, \"r\")!@#& local usrTable = textutils.unserialize(A.readAll())!@#& A.close()!@#& !@#& for i,v in ipairs(usrTable) do!@#&  if name == usrTable[i][\"username\"] and pwd == usrTable[i][\"password\"] then!@#&   local username = name!@#&   return true!@#&  end!@#& end!@#&  errorBox(\"Username or password is incorrect!\")!@#&end!@#&!@#&function errorBox(text)!@#& local maxX, maxY = term.getSize()!@#& term.setTextColour(colors.white)!@#& term.setBackgroundColour(colors.red)!@#& term.setCursorPos(1, maxY/2-1)!@#& term.clearLine()!@#& term.setCursorPos(maxX/2-#text/2, maxY/2)!@#& term.clearLine()!@#& write(text)!@#& term.setCursorPos(1, maxY/2+1)!@#& term.clearLine()!@#& sleep(2)!@#&end!@#&!@#&function goLogin()!@#& repeat!@#&  term.setBackgroundColour(colors.white)!@#&  clear()!@#&  term.setTextColour(colors.gray)!@#&  term.setBackgroundColour(colors.lightGray)!@#&  term.setCursorPos(1, 2)!@#&  term.clearLine()!@#&  write(\"Username: \")!@#&  term.setCursorPos(1, 4)!@#&  term.clearLine()!@#&  write(\"Password: \")!@#&  !@#&  term.setCursorPos(11, 2)!@#&  input = read()!@#&  term.setCursorPos(11, 4)!@#&  pwd = read(\"*\")!@#&  !@#&  logged = checkUser(input, pwd)!@#& until logged == true!@#& OS(input)!@#&end!@#&!@#&function doFileCreate(name)!@#& term.setBackgroundColour(colors.white)!@#& clear()!@#& term.setTextColour(colors.gray)!@#& term.setBackgroundColour(colors.lightGray)!@#& term.setCursorPos(1,2)!@#& term.clearLine()!@#& write(\"Filename: \")!@#& local filename = read()!@#& shell.run(\"/\"..root..\"/programs/luaide\", \"/\"..root..\"/users/\"..name..\"/\"..filename)!@#&end!@#&!@#&function doFilePaint(name)!@#& term.setBackgroundColour(colors.white)!@#& clear()!@#& term.setTextColour(colors.gray)!@#& term.setBackgroundColour(colors.lightGray)!@#& term.setCursorPos(1,2)!@#& term.clearLine()!@#& write(\"Filename: \")!@#& local filename = read()!@#& shell.run(\"/\"..root..\"/programs/npaintpro\", \"/\"..root..\"/users/\"..name..\"/\"..filename)!@#&end!@#&!@#&--[[  Main OS  ]]--!@#&if not fs.exists(userFile) then!@#& shell.run(\"/\"..root..\"/system/addUser\")!@#&end!@#&!@#&function OS(name)!@#&username = name!@#&loadSettings()!@#&drawWall()!@#&local path = \"/\"..root..\"/users/\"..name!@#&while true do!@#& ev, b, X, Y = os.pullEventRaw(\"mouse_click\")!@#& if slc == 0 then!@#&  if X >= 3 and X <= 9 and Y == 1 then!@#&   drawMenu1()!@#&   slc = 1!@#&  elseif X >= 15 and X <= 20 and Y == 1 then!@#&   drawMenu2()!@#&   slc = 2!@#&  elseif X >= 3 and X <= 8 and Y >= 4 and Y <= 9 then!@#&   term.setBackgroundColour(colors.black)!@#&   clear()!@#&   shell.run(\"/\"..root..\"/programs/games\")!@#&   drawWall()!@#&   slc = 0!@#&  elseif X >= 44 and X <= 49 and Y >= 5 and Y <= 10 then!@#&   term.setBackgroundColour(colors.black)!@#&   clear()!@#&   shell.run(\"/\"..root..\"/programs/filebrowser\", path)!@#&   drawWall()!@#&   slc = 0!@#&  elseif X >= 8 and X <= 17 and Y >= 12 and Y <= 17 then!@#&   term.setBackgroundColour(colors.black)!@#&   clear()!@#&   shell.run(\"/\"..root..\"/programs/firewolf\")!@#&   drawWall()!@#&   slc = 0!@#&  elseif X >= 25 and X <= 32 and Y >= 13 and Y <= 18 then!@#&   term.setBackgroundColour(colors.black)!@#&   clear()!@#&   doFileCreate(name)!@#&   sleep(1)!@#&   drawWall()!@#&   slc = 0!@#&  elseif X >= 40 and X <= 45 and Y >= 12 and Y <= 17 then!@#&   term.setBackgroundColour(colors.black)!@#&   clear()!@#&   doFilePaint(name)!@#&   sleep(1)!@#&   drawWall()!@#&   slc = 0!@#&  else!@#&   drawWall()!@#&  end!@#& elseif slc == 1 then!@#&  if X >= 2 and X <= 11 and Y == 3 then!@#&   os.reboot()!@#&  elseif X >= 2 and X <= 11 and Y == 4 then!@#&   os.shutdown()!@#&  elseif X >= 2 and X <= 11 and Y == 5 then!@#&   term.setBackgroundColour(colors.black)!@#&   clear()!@#&   shell.run(\"rom/programs/lua\")!@#&   drawWall()!@#&   slc = 0!@#&  elseif X >= 2 and X <= 11 and Y == 6 then!@#&   term.setBackgroundColour(colors.black)!@#&   clear()!@#&   shell.run(\"rom/programs/shell\")!@#&   drawWall()!@#&   slc = 0!@#&  elseif X >= 2 and X <= 11 and Y == 7 then!@#&   local msg = \"You are running HD-OS v2.5\"!@#&   msgBox(msg, \"Version\", #msg+1, 5)!@#&   drawWall()!@#&   slc = 0!@#&  elseif X >= 2 and X <= 11 and Y == 8 then!@#&   term.setBackgroundColour(colors.black)!@#&   clear()!@#&   shell.run(\"edit\",  \"/\"..root..\"/os.cfg\")!@#&   loadSettings()!@#&   drawWall()!@#&   slc = 0!@#&  elseif X >= 2 and X <= 11 and Y == 9 then!@#&   term.setBackgroundColour(colors.black)!@#&   clear()!@#&   if endMessage == true then centerPrint(\"Thank you for using HD-OS v2.5\", 2^math.random(0,14)) end!@#&   break!@#&  else!@#&   drawWall()!@#&   slc = 0!@#&  end!@#& elseif slc == 2 then!@#&  if X >= 12 and X <= 24 and Y == 3 then!@#&   term.setBackgroundColour(colors.black)!@#&   clear()!@#&   shell.run(\"/\"..root..\"/system/addUser\")!@#&   drawWall()!@#&   slc = 0!@#&  elseif X >= 12 and X <= 24 and Y == 4 then!@#&   term.setBackgroundColour(colors.black)!@#&   shell.run(\"/\"..root..\"/system/delUser\")!@#&   drawWall()!@#&   slc = 0!@#&  elseif X >= 12 and X <= 24 and Y == 5 then!@#&   term.setBackgroundColour(colors.black)!@#&   clear()!@#&   shell.run(\"/\"..root..\"/system/listUsers\")!@#&   drawWall()!@#&   slc = 0!@#&  elseif X >= 12 and X <= 24 and Y == 6 then!@#&   goLogin()!@#&  else!@#&   drawWall()!@#&   slc = 0!@#&  end!@#& end!@#&end!@#&!@#&end!@#&--[[  End Of OS  ]]--!@#&!@#&goLogin()!@#&",["OS"]={["os.cfg"]="settings = {!@#& [\"bgColor\"] = colors.white,!@#& [\"bgImg\"] = root..\"/images/wallpaper\",!@#& [\"textColor\"] = colors.white,!@#& [\"barColor\"] = colors.red,!@#& [\"snakeImg\"] = root..\"/images/snake\",!@#& [\"filesImg\"] = root..\"/images/files\",!@#& [\"fwImg\"] = root..\"/images/firewolf\",!@#& [\"liImg\"] = root..\"/images/luaide\",!@#& [\"paImg\"] = root..\"/images/npaintpro\"!@#&}",["games"]={["worm"]="!@#&-- Display the start screen!@#&local w,h = term.getSize()!@#&!@#&local headingColour, textColour, wormColour, fruitColour!@#&if term.isColour() then!@#&	headingColour = colours.yellow!@#&	textColour = colours.white!@#&	wormColour = colours.green!@#&	fruitColour = colours.red!@#&else!@#&	headingColour = colours.white!@#&	textColour = colours.white!@#&	wormColour = colours.white!@#&	fruitColour = colours.white!@#&end!@#&!@#&function printCentred( y, s )!@#&	local x = math.floor((w - string.len(s)) / 2)!@#&	term.setCursorPos(x,y)!@#&	--term.clearLine()!@#&	term.write( s )!@#&end!@#&!@#&local xVel,yVel = 1,0!@#&local xPos, yPos = math.floor(w/2), math.floor(h/2)!@#&local pxVel, pyVel = nil, nil!@#&!@#&local nLength = 1!@#&local nExtraLength = 6!@#&local bRunning = true!@#&!@#&local tailX,tailY = xPos,yPos!@#&local nScore = 0!@#&local nDifficulty = 2!@#&local nSpeed, nInterval!@#&!@#&-- Setup the screen!@#&local screen = {}!@#&for x=1,w do!@#&	screen[x] = {}!@#&	for y=1,h do!@#&		screen[x][y] = {}!@#&	end!@#&end!@#&screen[xPos][yPos] = { snake = true }!@#&!@#&local nFruit = 1!@#&local tFruits = {!@#&	\"A\", \"B\", \"C\", \"D\", \"E\", \"F\", \"G\", \"H\",!@#&	\"I\", \"J\", \"K\", \"L\", \"M\", \"N\", \"O\", \"P\",!@#&	\"Q\", \"R\", \"S\", \"T\", \"U\", \"V\", \"W\", \"X\",!@#&	\"Y\", \"Z\",!@#&	\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\",!@#&	\"i\", \"j\", \"k\", \"l\", \"m\", \"n\", \"o\", \"p\",!@#&	\"q\", \"r\", \"s\", \"t\", \"u\", \"v\", \"w\", \"x\",!@#&	\"y\", \"z\",!@#&	\"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\", \"0\",!@#&	\"@\", \"$\", \"%\", \"#\", \"&\", \"!\", \"?\", \"+\", \"*\", \"~\"!@#&}!@#&!@#&local function addFruit()!@#&	while true do!@#&		local x = math.random(1,w)!@#&		local y = math.random(2,h)!@#&		local fruit = screen[x][y]!@#&		if fruit.snake == nil and fruit.wall == nil and fruit.fruit == nil then!@#&			screen[x][y] = { fruit = true }!@#&			term.setCursorPos(x,y)!@#&			term.setBackgroundColour( fruitColour )!@#&			term.write(\" \")!@#&			term.setBackgroundColour( colours.black )!@#&			break!@#&		end!@#&	end!@#&	!@#&	nFruit = nFruit + 1!@#&	if nFruit > #tFruits then!@#&		nFruit = 1!@#&	end!@#&end!@#&!@#&local function drawMenu()!@#&	term.setTextColour( headingColour )!@#&	term.setCursorPos(1,1)!@#&	term.write( \"SCORE \" )!@#&	!@#&	term.setTextColour( textColour )!@#&	term.setCursorPos(7,1)!@#&	term.write( tostring(nScore) )!@#&!@#&	term.setTextColour( headingColour )!@#&	term.setCursorPos(w-11,1)!@#&	term.write( \"DIFFICULTY \")!@#&!@#&	term.setTextColour( textColour )!@#&	term.setCursorPos(w,1)!@#&	term.write( tostring(nDifficulty or \"?\") ) !@#&!@#&	term.setTextColour( colours.white )!@#&end!@#&!@#&local function update( )!@#&	local x,y = xPos,yPos!@#&	if pxVel and pyVel then!@#&		xVel, yVel = pxVel, pyVel!@#&		pxVel, pyVel = nil, nil!@#&	end!@#&!@#&	-- Remove the tail!@#&	if nExtraLength == 0 then!@#&		local tail = screen[tailX][tailY]!@#&		screen[tailX][tailY] = {}!@#&		term.setCursorPos(tailX,tailY)!@#&		term.write(\" \")!@#&		tailX = tail.nextX!@#&		tailY = tail.nextY!@#&	else!@#&		nExtraLength = nExtraLength - 1!@#&	end!@#&	!@#&	-- Update the head!@#&	local head = screen[xPos][yPos]!@#&	local newXPos = xPos + xVel!@#&	local newYPos = yPos + yVel!@#&	if newXPos < 1 then!@#&		newXPos = w!@#&	elseif newXPos > w then!@#&		newXPos = 1!@#&	end!@#&	if newYPos < 2 then!@#&		newYPos = h!@#&	elseif newYPos > h then!@#&		newYPos = 2!@#&	end!@#&	!@#&	local newHead = screen[newXPos][newYPos]!@#&	term.setCursorPos(1,1);!@#&	print( newHead.snake )!@#&	if newHead.snake == true or newHead.wall == true then!@#&		bRunning = false!@#&		!@#&	else!@#&		if newHead.fruit == true then!@#&			nScore = nScore + 10!@#&			nExtraLength = nExtraLength + 1!@#&			addFruit()!@#&		end!@#&		xPos = newXPos!@#&		yPos = newYPos!@#&		head.nextX = newXPos!@#&		head.nextY = newYPos!@#&		screen[newXPos][newYPos] = { snake = true }!@#&		!@#&	end!@#&	!@#&	term.setCursorPos(xPos,yPos)!@#&	term.setBackgroundColour( wormColour )!@#&	term.write(\" \")!@#&	term.setBackgroundColour( colours.black )!@#&!@#&	drawMenu()!@#&end!@#&!@#&-- Display the frontend!@#&term.clear()!@#&local function drawFrontend()!@#&	term.setTextColour( headingColour )!@#&	printCentred( math.floor(h/2) - 3, \"\" )!@#&	printCentred( math.floor(h/2) - 2, \" SELECT DIFFICULTY \" )!@#&	printCentred( math.floor(h/2) - 1, \"\" )!@#&	!@#&	printCentred( math.floor(h/2) + 0, \"            \" )!@#&	printCentred( math.floor(h/2) + 1, \"            \" )!@#&	printCentred( math.floor(h/2) + 2, \"            \" )!@#&	printCentred( math.floor(h/2) - 1 + nDifficulty, \" [        ] \" )!@#&!@#&	term.setTextColour( textColour )!@#&	printCentred( math.floor(h/2) + 0, \"EASY\" )!@#&	printCentred( math.floor(h/2) + 1, \"MEDIUM\" )!@#&	printCentred( math.floor(h/2) + 2, \"HARD\" )!@#&	printCentred( math.floor(h/2) + 3, \"\" )!@#&!@#&	term.setTextColour( colours.white )!@#&end!@#&!@#&drawMenu()!@#&drawFrontend()!@#&while true do!@#&	local e,key = os.pullEvent( \"key\" )!@#&	if key == keys.up or key == keys.w then!@#&		-- Up!@#&		if nDifficulty > 1 then!@#&			nDifficulty = nDifficulty - 1!@#&			drawMenu()!@#&			drawFrontend()!@#&		end!@#&	elseif key == keys.down or key == keys.s then!@#&		-- Down!@#&		if nDifficulty < 3 then!@#&			nDifficulty = nDifficulty + 1!@#&			drawMenu()!@#&			drawFrontend()!@#&		end!@#&	elseif key == keys.enter then!@#&		-- Enter!@#&		break!@#&	end!@#&end!@#&!@#&local tSpeeds = { 5, 10, 25 }!@#&nSpeed = tSpeeds[nDifficulty]!@#&nInterval = 1 / nSpeed!@#&!@#&-- Grow the snake to its intended size!@#&term.clear()!@#&drawMenu()!@#&screen[tailX][tailY].snake = true!@#&while nExtraLength > 0 do!@#&	update()!@#&end!@#&addFruit()!@#&addFruit()!@#&!@#&-- Play the game!@#&local timer = os.startTimer(0)!@#&while bRunning do!@#&	local event, p1, p2 = os.pullEvent()!@#&	if event == \"timer\" and p1 == timer then!@#&		timer = os.startTimer(nInterval)!@#&		update( false )!@#&	!@#&	elseif event == \"key\" then!@#&		local key = p1!@#&		if key == keys.up or key == keys.w then!@#&			-- Up!@#&			if yVel == 0 then!@#&				pxVel,pyVel = 0,-1!@#&			end!@#&		elseif key == keys.down or key == keys.s then!@#&			-- Down!@#&			if yVel == 0 then!@#&				pxVel,pyVel = 0,1!@#&			end!@#&		elseif key == keys.left or key == keys.a then!@#&			-- Left!@#&			if xVel == 0 then!@#&				pxVel,pyVel = -1,0!@#&			end!@#&		!@#&		elseif key == keys.right or key == keys.d then!@#&			-- Right!@#&			if xVel == 0 then!@#&				pxVel,pyVel = 1,0!@#&			end!@#&		!@#&		end	!@#&	end!@#&end!@#&!@#&-- Display the gameover screen!@#&term.setTextColour( headingColour )!@#&printCentred( math.floor(h/2) - 2, \"                   \" )!@#&printCentred( math.floor(h/2) - 1, \" G A M E   O V E R \" )!@#&!@#&term.setTextColour( textColour )!@#&printCentred( math.floor(h/2) + 0, \"                 \" )!@#&printCentred( math.floor(h/2) + 1, \" FINAL SCORE \"..nScore..\" \" )!@#&printCentred( math.floor(h/2) + 2, \"                 \" )!@#&term.setTextColour( colours.white )!@#&!@#&local timer = os.startTimer(2.5)!@#&repeat!@#&	local e,p = os.pullEvent()!@#&	if e == \"timer\" and p == timer then!@#&		term.setTextColour( textColour )!@#&		printCentred( math.floor(h/2) + 2, \" PRESS ANY KEY \" )!@#&		printCentred( math.floor(h/2) + 3, \"               \" )!@#&		term.setTextColour( colours.white )!@#&	end!@#&until e == \"char\"!@#&!@#&term.clear()!@#&term.setCursorPos(1,1)!@#&!@#&		",["maze3d"]="--[[!@#&	Project info:!@#&	!@#&	Name: Maze 3D!@#&	Creator: Jesusthekiller!@#&	Language: Lua (CC)!@#&	Website: None!@#&	License: GNU GPL!@#&		License file can be fount at www.jesusthekiller.com/license-gpl.html!@#&!@#&	Version: 2.1!@#&]]--!@#&!@#&--[[!@#&	Big thanks to Gopher for 3D engine!!@#&	http://www.computercraft.info/forums2/index.php?/topic/10786-wolf3d-style-3d-engine-proof-of-concept/page__hl__wolf3d!@#&]]--!@#&!@#&--[[!@#&	Changelog:!@#&	  1.0:!@#&	    Initial Release!@#&	  2.0:!@#&	    No-HTTP version for Treasure disk!@#&	  2.1:!@#&	    No more temp files!!@#&]]--!@#&!@#&--[[!@#&	LICENSE:!@#&	!@#&	Maze 3D!@#&	Copyright (c) 2013 Jesusthekiller!@#&!@#&	This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.!@#&!@#&	This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.!@#&!@#&	See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.!@#&]]--!@#&!@#&-- The color check!@#&if (not term.isColor()) or turtle then!@#&	print(\"This program has to be run on advanced computer.\")!@#&	error()!@#&end!@#&!@#&-- The cprint!@#&local function cwrite(msg)!@#&	msg = tostring(msg)!@#&	local x, y = term.getCursorPos()!@#&	term.setCursorPos((51-#msg)/2, y)!@#&	write(msg)!@#&end!@#&!@#&local function cprint(msg)!@#&	cwrite(msg..\"\\n\")!@#&end!@#&!@#&--[[!@#&-- The logo!@#&local f = fs.open(\"maze_logo\", \"w\") or error(\"Error while opening file maze_logo\", 0)!@#&f.write(\"0   0  00   0000 0000\\n00 00 0  0     0 0   \\n0 0 0 0000   00  000 \\n0   0 0  0  0    0   \\n0   0 0  0  0000 0000\\n        \\n   eeee    9999      \\n    777e   97779     \\n   eeee 7  97  97    \\n    777e   97  97    \\n   eeee 7  999977    \\n    7777    7777\")!@#&f.close()!@#&!@#&f = paintutils.loadImage(\"maze_logo\")!@#&!@#&--fs.delete(\"maze_logo\")]]!@#&!@#&-- The splash!@#&term.setBackgroundColor(colors.black)!@#&term.setTextColor(colors.white)!@#&term.clear()!@#&!@#&paintutils.drawImage({[1]={[1]=1,[2]=0,[3]=0,[4]=0,[5]=1,[6]=0,[7]=0,[8]=1,[9]=1,[10]=0,[11]=0,[12]=0,[13]=1,[14]=1,[15]=1,[16]=1,[17]=0,[18]=1,[19]=1,[20]=1,[21]=1,},[2]={[1]=1,[2]=1,[3]=0,[4]=1,[5]=1,[6]=0,[7]=1,[8]=0,[9]=0,[10]=1,[11]=0,[12]=0,[13]=0,[14]=0,[15]=0,[16]=1,[17]=0,[18]=1,[19]=0,[20]=0,[21]=0,},[3]={[1]=1,[2]=0,[3]=1,[4]=0,[5]=1,[6]=0,[7]=1,[8]=1,[9]=1,[10]=1,[11]=0,[12]=0,[13]=0,[14]=1,[15]=1,[16]=0,[17]=0,[18]=1,[19]=1,[20]=1,[21]=0,},[4]={[1]=1,[2]=0,[3]=0,[4]=0,[5]=1,[6]=0,[7]=1,[8]=0,[9]=0,[10]=1,[11]=0,[12]=0,[13]=1,[14]=0,[15]=0,[16]=0,[17]=0,[18]=1,[19]=0,[20]=0,[21]=0,},[5]={[1]=1,[2]=0,[3]=0,[4]=0,[5]=1,[6]=0,[7]=1,[8]=0,[9]=0,[10]=1,[11]=0,[12]=0,[13]=1,[14]=1,[15]=1,[16]=1,[17]=0,[18]=1,[19]=1,[20]=1,[21]=1,},[6]={[1]=0,[2]=0,[3]=0,[4]=0,[5]=0,[6]=0,[7]=0,[8]=0,},[7]={[1]=0,[2]=0,[3]=0,[4]=16384,[5]=16384,[6]=16384,[7]=16384,[8]=0,[9]=0,[10]=0,[11]=0,[12]=512,[13]=512,[14]=512,[15]=512,[16]=0,[17]=0,[18]=0,[19]=0,[20]=0,[21]=0,},[8]={[1]=0,[2]=0,[3]=0,[4]=0,[5]=128,[6]=128,[7]=128,[8]=16384,[9]=0,[10]=0,[11]=0,[12]=512,[13]=128,[14]=128,[15]=128,[16]=512,[17]=0,[18]=0,[19]=0,[20]=0,[21]=0,},[9]={[1]=0,[2]=0,[3]=0,[4]=16384,[5]=16384,[6]=16384,[7]=16384,[8]=0,[9]=128,[10]=0,[11]=0,[12]=512,[13]=128,[14]=0,[15]=0,[16]=512,[17]=128,[18]=0,[19]=0,[20]=0,[21]=0,},[10]={[1]=0,[2]=0,[3]=0,[4]=0,[5]=128,[6]=128,[7]=128,[8]=16384,[9]=0,[10]=0,[11]=0,[12]=512,[13]=128,[14]=0,[15]=0,[16]=512,[17]=128,[18]=0,[19]=0,[20]=0,[21]=0,},[11]={[1]=0,[2]=0,[3]=0,[4]=16384,[5]=16384,[6]=16384,[7]=16384,[8]=0,[9]=128,[10]=0,[11]=0,[12]=512,[13]=512,[14]=512,[15]=512,[16]=128,[17]=128,[18]=0,[19]=0,[20]=0,[21]=0,},[12]={[1]=0,[2]=0,[3]=0,[4]=0,[5]=128,[6]=128,[7]=128,[8]=128,[9]=0,[10]=0,[11]=0,[12]=0,[13]=128,[14]=128,[15]=128,[16]=128,},}, 15, 3)!@#&!@#&parallel.waitForAny(!@#&	function() coroutine.yield(); os.pullEvent(\"key\"); coroutine.yield() end,!@#&	function() term.setBackgroundColor(colors.black); term.setTextColor(colors.white) while true do term.setCursorPos(18, 16); term.write(\"Press any key..\"); sleep(0.5); term.clearLine(); sleep(0.5) end end!@#&)!@#&!@#&-- The size!@#&local size!@#&!@#&repeat!@#&	term.setCursorPos(1, 16)!@#&	term.clearLine()!@#&!@#&	cwrite(\"Enter maze size (5-99):\")!@#&	size = read()!@#&	!@#&	size = tonumber(size)!@#&	if not size then!@#&		size = 0!@#&	end!@#&until size > 4 and size < 100!@#&!@#&-- The generate!@#&local function mazeGen(mx, my)!@#&	!@#&	--[[!@#&		Format:!@#&		!@#&		maze.x.y.(1/2/3/4) = true/false!@#&		!@#&		1 - top!@#&		2 - bottom!@#&		3 - right!@#&		4 - left!@#&	]]--!@#&	!@#&	local maze = {}!@#&	for i = 1, mx do!@#&		maze[i] = {}!@#&		for j = 1, my do!@#&			maze[i][j] = {}!@#&			for k = 1, 4 do!@#&				maze[i][j][k] = true!@#&			end!@#&		end!@#&	end!@#&!@#&	local vis = 1!@#&	local tot = mx * my!@#&	local curr = {}!@#&	curr.x = math.random(1, mx)!@#&	curr.y = math.random(1, my)!@#&	local stack = {}!@#&!@#&	while vis < tot do!@#&		local intact = {}!@#&		local x = curr.x!@#&		local y = curr.y!@#&		!@#&		if x - 1 >= 1 and maze[x-1][y][1] and maze[x-1][y][2] and maze[x-1][y][3] and maze[x-1][y][4] then -- Check for full cells!@#&			intact[#intact+1] = {x-1, y, 1}!@#&		end!@#&		!@#&		if x + 1 <= mx and maze[x+1][y][1] and maze[x+1][y][2] and maze[x+1][y][3] and maze[x+1][y][4] then!@#&			intact[#intact+1] = {x+1, y, 2}!@#&		end!@#&		!@#&		if y + 1 <= my and maze[x][y+1][1] and maze[x][y+1][2] and maze[x][y+1][3] and maze[x][y+1][4] then!@#&			intact[#intact+1] = {x, y+1, 3}!@#&		end!@#&		!@#&		if y - 1 >= 1 and maze[x][y-1][1] and maze[x][y-1][2] and maze[x][y-1][3] and maze[x][y-1][4] then!@#&			intact[#intact+1] = {x, y-1, 4}!@#&		end!@#&		!@#&		if #intact > 0 then!@#&			local i = math.random(1, #intact) -- Choose random!@#&			!@#&			if intact[i][3] == 1 then -- Set intact's attached wall to false!@#&				maze[intact[i][1]][intact[i][2]][2] = false!@#&			elseif intact[i][3] == 2 then!@#&				maze[intact[i][1]][intact[i][2]][1] = false!@#&			elseif intact[i][3] == 3 then!@#&				maze[intact[i][1]][intact[i][2]][4] = false!@#&			elseif intact[i][3] == 4 then!@#&				maze[intact[i][1]][intact[i][2]][3] = false!@#&			end!@#&			!@#&			maze[x][y][intact[i][3]] = false -- Set attached wall to false!@#&			!@#&			vis = vis + 1 -- Increase vis!@#&			!@#&			stack[#stack+1] = intact[i] -- Add to stack!@#&		else!@#&			local tmp = table.remove(stack) -- Get last cell!@#&			curr.x = tmp[1]!@#&			curr.y = tmp[2]!@#&		end!@#&	end!@#&	!@#&	return maze!@#&end!@#&!@#&local m = mazeGen(size, size)!@#&!@#&-- The game init!@#&local posx = 2!@#&local posy = 2!@#&!@#&local offsetx = 51/2-2!@#&local offsety = 19/2-2!@#&!@#&-- The maze-to-table!@#&local tab = {}!@#&!@#&for x = 1, size * 2 + 1 do!@#&	tab[x] = {}!@#&	!@#&	for y = 1, size * 2 + 1 do!@#&		if x % 2 == 0 and y % 2 == 0 then -- Fill cells (empty)!@#&			tab[x][y] = \" \"!@#&		elseif x % 2 == 1 and y % 2 == 1 then -- Fill corners (full)!@#&			tab[x][y] = \"1\"!@#&		end!@#&	end!@#&end!@#&!@#&for x, tV in ipairs(m) do!@#&	for y, v in ipairs(tV) do!@#&		if x == size and y == size then!@#&			v[1] = v[1] and \"2\" or \" \"!@#&			v[2] = v[2] and \"2\" or \" \"!@#&			v[3] = v[3] and \"2\" or \" \"!@#&			v[4] = v[4] and \"2\" or \" \"!@#&			tab[x*2-1][y*2] = v[1] -- Up!@#&			tab[x*2+1][y*2] = v[2] -- Down!@#&			tab[x*2][y*2+1] = v[3] -- Right!@#&			tab[x*2][y*2-1] = v[4] -- Left!@#&		else!@#&			v[1] = v[1] and \"1\" or \" \"!@#&			v[2] = v[2] and \"1\" or \" \"!@#&			v[3] = v[3] and \"1\" or \" \"!@#&			v[4] = v[4] and \"1\" or \" \"!@#&			tab[x*2-1][y*2] = v[1] -- Up!@#&			tab[x*2+1][y*2] = v[2] -- Down!@#&			tab[x*2][y*2+1] = v[3] -- Right!@#&			tab[x*2][y*2-1] = v[4] -- Left!@#&		end!@#&	end!@#&end!@#&!@#&local gtab = {}!@#&!@#&for k, v in ipairs(tab) do!@#&	gtab[#gtab+1] = table.concat(v)!@#&end!@#&!@#&size = size * 2 + 1!@#&!@#&--[[!@#&local template = fs.open(\"maze3d_template\", \"r\")!@#&local game = fs.open(\"maze3d_game\", \"w\")!@#&!@#&game.writeLine(\"local mapH, mapW = \"..size..\",\"..size)!@#&game.writeLine(\"local dir = \"..(gtab[2]:sub(3,3) == \" \" and '0' or '88'))!@#&game.writeLine(\"local map = {\")!@#&!@#&for k, v in ipairs(gtab) do!@#&	game.writeLine('\"'..v..'\",')!@#&end!@#&!@#&game.writeLine(\"}\")!@#&!@#&game.writeLine(template.readAll())!@#&game.close()!@#&template.close()!@#&!@#&shell.run(\"maze3d_game\")!@#&!@#&fs.delete(\"maze3d_game\")!@#&fs.delete(\"maze3d_template\")]]!@#&!@#&local mapH, mapW = size, size!@#&local dir = gtab[2]:sub(3,3) == \" \" and '0' or '88'!@#&local map = gtab!@#&local startdir = dir!@#&!@#&------------------------------------------------------------------------------------------------------!@#&--GOPHER'S CODE HERE!@#&!@#&local buffer=term!@#&local loadedAPI=false!@#&!@#&local stime = os.clock()!@#&!@#&if redirect then!@#&  buffer=redirect.createRedirectBuffer()!@#&  print(\"redirect API found, using buffer\")!@#&else!@#&  local pe=printError!@#&  rawset(_G,\"printError\",error)  !@#&  local ok, err=pcall(os.loadAPI,\"redirect\")!@#&  if not ok then!@#&    print(\"trying \"..shell.dir()..\"/redirect\")!@#&    ok,err=pcall(os.loadAPI,shell.dir()..\"/redirect\")!@#&  end!@#&  if ok then    !@#&    print(\"Loaded redirect API, using buffer\")!@#&    buffer=redirect.createRedirectBuffer()!@#&    loadedAPI=true!@#&  else!@#&    print(\"redirect API not found or could not be loaded, drawing directly; this may cause flickering.\")!@#&  end!@#&  rawset(_G,\"printError\",pe)!@#&end !@#&!@#&local colorSchemes = {!@#&  {0,8}, --white+gray!@#&  {3,11}, --blue!@#&  {6,14}, --red!@#&  {5,13}, --green!@#&  {4,1}, --yellow/orange!@#&}!@#&!@#&!@#&local function cast(cx,cy,angle)!@#&  --direction vector!@#&  local vx,vy=math.cos(angle), math.sin(angle)!@#&  local slope=vy/vx!@#&  --next distance, x and y axis points!@#&  local ndx, ndy!@#&  --steps, distance and block!@#&  local dsx, dsy, bsx, bsy!@#&  if vx<0 then!@#&    local x=(cx%1)!@#&    bsx=-1!@#&    ndx=math.sqrt(x*x*(1+slope*slope))!@#&    dsx=math.sqrt((1+slope*slope))!@#&  else!@#&    local x=1-(cx%1)!@#&    bsx=1!@#&    ndx=math.sqrt(x*x*(1+slope*slope))!@#&    dsx=math.sqrt((1+slope*slope))!@#&  end!@#&!@#&  if vy<0 then!@#&    local y=(cy%1)!@#&    bsy=-1!@#&    ndy=math.sqrt(y*y*(1+1/(slope*slope)))!@#&    dsy=math.sqrt((1+1/(slope*slope)))!@#&  else!@#&    local y=1-(cy%1)!@#&    bsy=1!@#&    ndy=math.sqrt(y*y*(1+1/(slope*slope)))!@#&    dsy=math.sqrt((1+1/(slope*slope)))!@#&  end!@#&!@#&  local x,y=math.floor(cx),math.floor(cy)!@#&  while x>0 and x<=mapW and y>0 and y<=mapH do!@#&    local hitD!@#&    local isX!@#&    if ndx<ndy then!@#&      --x crossing is next!@#&      x=x+bsx!@#&      isX=true!@#&      hitD=ndx!@#&      ndx=ndx+dsx!@#&    else!@#&      y=y+bsy!@#&      isX=false!@#&      hitD=ndy!@#&      ndy=ndy+dsy!@#&    end!@#&    local wall=map[y]:sub(x,x)!@#&    if wall~=\" \" then!@#&      !@#&      return colorSchemes[tonumber(wall)][isX and 1 or 2], hitD!@#&    end!@#&  end  !@#&end!@#&!@#&local w,h=term.getSize()!@#&local centerX, centerY=math.floor((w+1)/2), math.floor((h+1)/2)!@#&!@#&local px, py=2.5,2.5!@#&--local dir=0!@#&local fx,fy!@#&local speed=.1!@#&local turnSpeed=4!@#&!@#&local function turn(amt)!@#&  dir=dir+amt!@#&  fx,fy=math.cos(math.rad(dir)), math.sin(math.rad(dir))!@#&end!@#&!@#&turn(0)!@#&!@#&--build table of angles and base distances per scanline!@#&local screenDist=.55*w!@#&local scan={}!@#&!@#&for x=1,w do!@#&  local t={}!@#&  scan[x]=t!@#&  t.angle=math.atan2(x-centerX,screenDist)!@#&  t.dist=((x-centerX)^2+screenDist^2)^.5/screenDist!@#&end!@#&  !@#&local function redraw()!@#&  if buffer.isBuffer then!@#&    term.redirect(buffer)!@#&  end!@#&  for x=1,w do!@#&    local wall,dist=cast(px,py,math.rad(dir)+scan[x].angle)!@#&    if wall then!@#&      --calc wall height based on distance!@#&      local height=scan[x].dist/dist!@#&      height=math.floor(math.min(height*centerY,(h+1)/2))!@#&      term.setBackgroundColor(colors.gray)!@#&      for y=1,(h+1)/2-height-1 do!@#&        term.setCursorPos(x,y)!@#&        term.write(\" \")!@#&      end!@#&      for y=centerY+height+1,h do!@#&        term.setCursorPos(x,y)!@#&        term.write(\" \")!@#&      end!@#&      term.setBackgroundColor(2^wall)!@#&      for y=centerY-height,centerY+height do!@#&        term.setCursorPos(x,y)!@#&        term.write(\" \")!@#&      end!@#&    end!@#&  end!@#&  if buffer.isBuffer then!@#&    term.restore()!@#&    buffer.blit()!@#&  end!@#&end!@#&!@#&local function clampCollision(x,y,radius)!@#&  --am I *in* a block?!@#&  local gx,gy=math.floor(x),math.floor(y)!@#&  if map[gy]:sub(gx,gx)~=\" \" then!@#&    --I am. Complete fail, do nothing.!@#&    return x,y!@#&  end!@#&  !@#&  --ok, check the neighbors.!@#&  local right=math.floor(x+radius)>gx!@#&  local left=math.floor(x-radius)<gx!@#&  local front=math.floor(y-radius)<gy!@#&  local back=math.floor(y+radius)>gy!@#&  !@#&  local pushed=false!@#&  !@#&  if right and map[gy]:sub(gx+1,gx+1)~=\" \" then!@#&    --push left!@#&    pushed=true!@#&    x=gx+1-radius!@#&  elseif left  and map[gy]:sub(gx-1,gx-1)~=\" \" then!@#&    --push right!@#&    pushed=true!@#&    x=gx+radius!@#&  end!@#&  !@#&  if front and map[gy-1]:sub(gx,gx)~=\" \" then!@#&    --push back!@#&    pushed=true!@#&    y=gy+radius!@#&  elseif back and map[gy+1]:sub(gx,gx)~=\" \" then!@#&    --push forward!@#&    pushed=true!@#&!@#&!@#&!@#&    y=gy+1-radius!@#&  end!@#& !@#&  --if I wasn't pushed out on any side, I might be hitting a corner!@#&  if not pushed then!@#&    --square rad!@#&    local r2=radius^2!@#&    local pushx,pushy=0,0!@#&    if left then!@#&      if front and map[gy-1]:sub(gx-1,gx-1)~=\" \" then!@#&        --check front-left!@#&        local dist2=(gx-x)^2+(gy-y)^2!@#&        if dist2<r2 then!@#&          local pushd=(r2-dist2)/2^.5!@#&          pushx,pushy=pushd,pushd!@#&        end!@#&      elseif back and map[gy+1]:sub(gx-1,gx-1)~=\" \" then!@#&        local dist2=(gx-x)^2+(gy+1-y)^2!@#&        if dist2<r2 then!@#&          local pushd=(r2-dist2)/2^.5!@#&          pushx,pushy=pushd,-pushd!@#&        end!@#&      end!@#&    elseif right then!@#&      if front and map[gy-1]:sub(gx+1,gx+1)~=\" \" then!@#&        --check front-left!@#&        local dist2=(gx+1-x)^2+(gy-y)^2!@#&        if dist2<r2 then!@#&          local pushd=(r2-dist2)/2^.5!@#&          pushx,pushy=-pushd,pushd!@#&        end!@#&      elseif back and map[gy+1]:sub(gx+1,gx+1)~=\" \" then!@#&        local dist2=(gx+1-x)^2+(gy+1-y)^2!@#&        if dist2<r2 then!@#&          local pushd=(r2-dist2)/2^.5!@#&          pushx,pushy=-pushd,-pushd!@#&        end!@#&      end!@#&    end!@#&    x=x+pushx!@#&    y=y+pushy!@#&  end!@#&  !@#&  return x,y!@#&end!@#&!@#&term.setBackgroundColor(colors.black)!@#&--term.setTextColor(colors.white)!@#&term.clear()!@#&term.setCursorPos(1, 1)!@#&!@#&term.setTextColor(colors.yellow)!@#&write(\"Move:                                          \")!@#&term.setTextColor(colors.lime)!@#&print(\"WASD\")!@#&!@#&term.setTextColor(colors.yellow)!@#&write(\"Turn:                              \")!@#&term.setTextColor(colors.lime)!@#&print(\"Left/Right arrow\")!@#&!@#&term.setTextColor(colors.yellow)!@#&write(\"Teleport to start:                                \")!@#&term.setTextColor(colors.lime)!@#&print(\"R\")!@#&!@#&term.setTextColor(colors.yellow)!@#&write(\"Quit:                                             \")!@#&term.setTextColor(colors.lime)!@#&print(\"Q\\n\")!@#&!@#&term.setTextColor(colors.white)!@#&write(\"Goal: go to \")!@#&term.setTextColor(colors.lightBlue)!@#&write(\"blue\")!@#&term.setTextColor(colors.white)!@#&print(\" spot (opposite corner of the map)\\n\\n\\n\\n\")!@#&!@#&term.setTextColor(colors.white)!@#&cprint(\"Press any key to start!\")!@#&!@#&os.pullEvent(\"key\")!@#&!@#&local frameTimer=os.startTimer(0.5)!@#&local prevTick=0!@#&local dirty=true!@#&local win = false!@#&while true do!@#&  px,py=clampCollision(px,py,.25)!@#&  if dirty then!@#&    redraw()!@#&    dirty=false!@#&  end!@#&  !@#&  local e={os.pullEvent()}!@#&  if e[1]==\"key\" then!@#&    if e[2]==keys.left then!@#&      turn(-turnSpeed)!@#&      dirty=true!@#&    elseif e[2]==keys.right then!@#&      turn(turnSpeed)!@#&      dirty=true!@#&    elseif e[2]==keys.up or e[2]==keys.w then!@#&      px=px+fx*speed!@#&      py=py+fy*speed!@#&      dirty=true!@#&    elseif e[2]==keys.down or e[2]==keys.s then!@#&      px=px-fx*speed!@#&      py=py-fy*speed!@#&      dirty=true!@#&    elseif e[2]==keys.a then!@#&      px=px+fy*speed!@#&      py=py-fx*speed!@#&      dirty=true!@#&    elseif e[2]==keys.d then!@#&      px=px-fy*speed!@#&      py=py+fx*speed!@#&      dirty=true!@#&    elseif e[2]==keys.q then!@#&      break!@#&    elseif e[2]==keys.r then!@#&      px,py = 2.5,2.5!@#&      dir=startdir!@#&      dirty=true!@#&    end!@#&    !@#&    if px >= mapW-1 and py >= mapH-1 then!@#&      win = true!@#&      break!@#&    end!@#&  end!@#&end!@#&!@#&!@#&if loadedAPI then!@#&  os.unloadAPI(\"redirect\")!@#&end!@#&!@#&-- JESUS PART!@#&!@#&-- The win/loose message!@#&term.setBackgroundColor(colors.white)!@#&term.setTextColor(colors.black)!@#&term.clear()!@#&term.setCursorPos(1, 1)!@#&!@#&if win then!@#&  local ntime = os.clock()!@#&  write(\"\\n\")!@#&  cprint(\"Congratulations!\")!@#&  cprint(\"You made it in\")!@#&  cprint(tostring(math.floor((ntime-stime)/60))..\" minutes and \"..tostring(math.ceil((ntime-stime)%60))..\" seconds\")!@#&  cprint(\"Size of maze: \"..(mapW-1)/2)!@#&sleep(1)!@#&else!@#&  write(\"\\n\")!@#&  cprint(\"Oh noes D:\")!@#&end!@#&!@#&!@#&!@#&parallel.waitForAny(!@#&  function() coroutine.yield(); os.pullEvent(\"key\"); coroutine.yield() end,!@#&  function() term.setBackgroundColor(colors.white); term.setTextColor(colors.black) while true do term.setCursorPos(18, 14); term.write(\"Press any key..\"); sleep(0.5); term.clearLine(); sleep(0.5) end end!@#&)!@#&!@#&term.setBackgroundColor(colors.black)!@#&term.setTextColor(colors.white)!@#&term.clear()!@#&term.setCursorPos(1, 1)!@#&cprint(\"  Maze by Jesusthekiller. Thanks for playing!\")!@#&cprint(\"3D engine by Gopher, He is A-W-E-S-O-M-E\")",["adventure"]="!@#&local tBiomes = {!@#&	\"in a forest\",!@#&	\"in a pine forest\",!@#&	\"knee deep in a swamp\",!@#&	!@#&	\"in a mountain range\",!@#&	\"in a desert\",!@#&	\"in a grassy plain\",!@#&	\"in frozen tundra\",!@#&	!@#&	--\"in the ocean\",!@#&}!@#&!@#&local function hasTrees( _nBiome )!@#&	return _nBiome <= 3!@#&end!@#&!@#&local function hasStone( _nBiome )!@#&	return _nBiome == 4!@#&end!@#&!@#&local function hasRivers( _nBiome )!@#&	return _nBiome ~= 3 and _nBiome ~= 5!@#&end!@#&!@#&local items = {!@#&	[\"no tea\"] = {!@#&		droppable = false,!@#&		desc = \"Pull yourself together man.\",!@#&	},!@#&	[\"a pig\"] = {!@#&		heavy = true,!@#&		creature = true,!@#&		drops = { \"some pork\" },!@#&		aliases = { \"pig\" },!@#&		desc = \"The pig has a square nose.\",!@#&	},!@#&	[\"a cow\"] = {!@#&		heavy = true,!@#&		creature = true,!@#&		aliases = { \"cow\" },!@#&		desc = \"The cow stares at you blankly.\",!@#&	},!@#&	[\"a sheep\"] = {!@#&		heavy = true,!@#&		creature = true,!@#&		hitDrops = { \"some wool\" },!@#&		aliases = { \"sheep\" },!@#&		desc = \"The sheep is fluffy.\",!@#&	},!@#&	[\"a chicken\"] = {!@#&		heavy = true,!@#&		creature = true,!@#&		drops = { \"some chicken\" },!@#&		aliases = { \"chicken\" },!@#&		desc = \"The chicken looks delicious.\",!@#&	},!@#&	[\"a creeper\"] = {!@#&		heavy = true,!@#&		creature = true,!@#&		monster = true,!@#&		aliases = { \"creeper\" },!@#&		desc = \"The creeper needs a hug.\",!@#&	},!@#&	[\"a skeleton\"] = {!@#&		heavy = true,!@#&		creature = true,!@#&		monster = true,!@#&		aliases = { \"skeleton\" },!@#&		nocturnal = true,!@#&		desc = \"The head bone's connected to the neck bone, the neck bones connected to the chest bone, the chest bones connected to the arm bone, the arm bones connected to the bow, and the bow is pointed at you.\",!@#&	},!@#&	[\"a zombie\"] = {!@#&		heavy = true,!@#&		creature = true,!@#&		monster = true,!@#&		aliases = { \"zombie\" },!@#&		nocturnal = true,!@#&		desc = \"All he wants to do is eat your brains.\",!@#&	},!@#&	[\"a spider\"] = {!@#&		heavy = true,!@#&		creature = true,!@#&		monster = true,!@#&		aliases = { \"spider\" },!@#&		desc = \"Dozens of eyes stare back at you.\",!@#&	},!@#&	[\"a cave entrance\"] = {!@#&		heavy = true,!@#&		aliases = { \"cave entance\", \"cave\", \"entrance\" },!@#&		desc = \"The entrance to the cave is dark, but it looks like you can climb down.\",!@#&	},!@#&	[\"an exit to the surface\"] = {!@#&		heavy = true,!@#&		aliases = { \"exit to the surface\", \"exit\", \"opening\" },!@#&		desc = \"You can just see the sky through the opening.\",!@#&	},!@#&	[\"a river\"] = {!@#&		heavy = true,!@#&		aliases = { \"river\" },!@#&		desc = \"The river flows majestically towards the horizon.\",!@#&	},!@#&	[\"some wood\"] = {!@#&		aliases = { \"wood\" },!@#&		material = true,!@#&		desc = \"You could easilly craft this wood into planks.\",!@#&	},!@#&	[\"some planks\"] = {!@#&		aliases = { \"planks\", \"wooden planks\", \"wood planks\" },!@#&		desc = \"You could easilly craft these planks into sticks.\",!@#&	},!@#&	[\"some sticks\"] = {!@#&		aliases = { \"sticks\", \"wooden sticks\", \"wood sticks\" },!@#&		desc = \"A perfect handle for torches or a pickaxe.\",!@#&	},!@#&	[\"a crafting table\"] = {!@#&		aliases = { \"crafting table\", \"craft table\", \"work bench\", \"workbench\", \"crafting bench\", \"table\", },!@#&		desc = \"It's a crafting table. I shouldn't tell you this, but these don't actually do anything in this game, you can craft tools whenever you like.\",!@#&	},!@#&	[\"a furnace\"] = {!@#&		aliases = { \"furnace\" },!@#&		desc = \"It's a furnace. Between you and me, these don't actually do anything in this game.\",!@#&	},!@#&	[\"a wooden pickaxe\"] = {!@#&		aliases = { \"pickaxe\", \"pick\", \"wooden pick\", \"wooden pickaxe\", \"wood pick\", \"wood pickaxe\" },!@#&		tool = true,!@#&		toolLevel = 1,!@#&		toolType = \"pick\",!@#&		desc = \"The pickaxe looks good for breaking stone and coal.\",!@#&	},!@#&	[\"a stone pickaxe\"] = {!@#&		aliases = { \"pickaxe\", \"pick\", \"stone pick\", \"stone pickaxe\" },!@#&		tool = true,!@#&		toolLevel = 2,!@#&		toolType = \"pick\",!@#&		desc = \"The pickaxe looks good for breaking iron.\",!@#&	},!@#&	[\"an iron pickaxe\"] = {!@#&		aliases = { \"pickaxe\", \"pick\", \"iron pick\", \"iron pickaxe\" },!@#&		tool = true,!@#&		toolLevel = 3,!@#&		toolType = \"pick\",!@#&		desc = \"The pickaxe looks strong enough to break diamond.\",!@#&	},!@#&	[\"a diamond pickaxe\"] = {!@#&		aliases = { \"pickaxe\", \"pick\", \"diamond pick\", \"diamond pickaxe\" },!@#&		tool = true,!@#&		toolLevel = 4,!@#&		toolType = \"pick\",!@#&		desc = \"Best. Pickaxe. Ever.\",!@#&	},!@#&	[\"a wooden sword\"] = {!@#&		aliases = { \"sword\", \"wooden sword\", \"wood sword\" },!@#&		tool = true,!@#&		toolLevel = 1,!@#&		toolType = \"sword\",!@#&		desc = \"Flimsy, but better than nothing.\",!@#&	},!@#&	[\"a stone sword\"] = {!@#&		aliases = { \"sword\", \"stone sword\" },!@#&		tool = true,!@#&		toolLevel = 2,!@#&		toolType = \"sword\",!@#&		desc = \"A pretty good sword.\",!@#&	},!@#&	[\"an iron sword\"] = {!@#&		aliases = { \"sword\", \"iron sword\" },!@#&		tool = true,!@#&		toolLevel = 3,!@#&		toolType = \"sword\",!@#&		desc = \"This sword can slay any enemy.\",!@#&	},!@#&	[\"a diamond sword\"] = {!@#&		aliases = { \"sword\", \"diamond sword\" },!@#&		tool = true,!@#&		toolLevel = 4,!@#&		toolType = \"sword\",!@#&		desc = \"Best. Sword. Ever.\",!@#&	},!@#&	[\"a wooden shovel\"] = {!@#&		aliases = { \"shovel\", \"wooden shovel\", \"wood shovel\" },!@#&		tool = true,!@#&		toolLevel = 1,!@#&		toolType = \"shovel\",!@#&		desc = \"Good for digging holes.\",!@#&	},!@#&	[\"a stone shovel\"] = {!@#&		aliases = { \"shovel\", \"stone shovel\" },!@#&		tool = true,!@#&		toolLevel = 2,!@#&		toolType = \"shovel\",!@#&		desc = \"Good for digging holes.\",!@#&	},!@#&	[\"an iron shovel\"] = {!@#&		aliases = { \"shovel\", \"iron shovel\" },!@#&		tool = true,!@#&		toolLevel = 3,!@#&		toolType = \"shovel\",!@#&		desc = \"Good for digging holes.\",!@#&	},!@#&	[\"a diamond shovel\"] = {!@#&		aliases = { \"shovel\", \"diamond shovel\" },!@#&		tool = true,!@#&		toolLevel = 4,!@#&		toolType = \"shovel\",!@#&		desc = \"Good for digging holes.\",!@#&	},!@#&	[\"some coal\"] = {!@#&		aliases = { \"coal\" },!@#&		ore = true,!@#&		toolLevel = 1,!@#&		toolType = \"pick\",!@#&		desc = \"That coal looks useful for building torches, if only you had a pickaxe to mine it.\",!@#&	},!@#&	[\"some dirt\"] = {!@#&		aliases = { \"dirt\" },!@#&		material = true,!@#&		desc = \"Why not build a mudhut?\",!@#&	},!@#&	[\"some stone\"] = {!@#&		aliases = { \"stone\", \"cobblestone\" },!@#&		material = true,!@#&		ore = true,!@#&		infinite = true,!@#&		toolLevel = 1,!@#&		toolType = \"pick\",!@#&		desc = \"Stone is useful for building things, and making stone pickaxes.\",!@#&	},!@#&	[\"some iron\"] = {!@#&		aliases = { \"iron\" },!@#&		material = true,!@#&		ore = true,!@#&		toolLevel = 2,!@#&		toolType = \"pick\",!@#&		desc = \"That iron looks mighty strong, you'll need a stone pickaxe to mine it.\",!@#&	},!@#&	[\"some diamond\"] = {!@#&		aliases = { \"diamond\", \"diamonds\" },!@#&		material = true,!@#&		ore = true,!@#&		toolLevel = 3,!@#&		toolType = \"pick\",!@#&		desc = \"Sparkly, rare, and impossible to mine without an iron pickaxe.\",!@#&	},!@#&	[\"some torches\"] = {!@#&		aliases = { \"torches\", \"torch\" },!@#&		desc = \"These won't run out for a while.\",!@#&	},!@#&	[\"a torch\"] = {!@#&		aliases = { \"torch\" },!@#&		desc = \"Fire, fire, burn so bright, won't you light my cave tonight?\",!@#&	},!@#&	[\"some wool\"] = {!@#&		aliases = { \"wool\" },!@#&		material = true,!@#&		desc = \"Soft and good for building.\",!@#&	},!@#&	[\"some pork\"] = {!@#&		aliases = { \"pork\", \"porkchops\" },!@#&		food = true,!@#&		desc = \"Delicious and nutricious.\",!@#&	},!@#&	[\"some chicken\"] = {!@#&		aliases = { \"chicken\" },!@#&		food = true,!@#&		desc = \"Finger licking good.\",!@#&	},!@#&}!@#&!@#&local tAnimals = {!@#&	\"a pig\", \"a cow\", \"a sheep\", \"a chicken\",!@#&}!@#&!@#&local tMonsters = {!@#&	\"a creeper\", \"a skeleton\", \"a zombie\", \"a spider\"!@#&}!@#&!@#&local tRecipes = {!@#&	[\"some planks\"] = { \"some wood\" },!@#&	[\"some sticks\"] = { \"some planks\" },!@#&	[\"some sticks\"] = { \"some planks\" },!@#&	[\"a crafting table\"] = { \"some planks\" },!@#&	[\"a furnace\"] = { \"some stone\" },!@#&	[\"some torches\"] = { \"some sticks\", \"some coal\" },!@#&	!@#&	[\"a wooden pickaxe\"] = { \"some planks\", \"some sticks\" },!@#&	[\"a stone pickaxe\"] = { \"some stone\", \"some sticks\" },!@#&	[\"an iron pickaxe\"] = { \"some iron\", \"some sticks\" },!@#&	[\"a diamond pickaxe\"] = { \"some diamond\", \"some sticks\" },!@#&!@#&	[\"a wooden sword\"] = { \"some planks\", \"some sticks\" },!@#&	[\"a stone sword\"] = { \"some stone\", \"some sticks\" },!@#&	[\"an iron sword\"] = { \"some iron\", \"some sticks\" },!@#&	[\"a diamond sword\"] = { \"some diamond\", \"some sticks\" },!@#&!@#&	[\"a wooden shovel\"] = { \"some planks\", \"some sticks\" },!@#&	[\"a stone shovel\"] = { \"some stone\", \"some sticks\" },!@#&	[\"an iron shovel\"] = { \"some iron\", \"some sticks\" },!@#&	[\"a diamond shovel\"] = { \"some diamond\", \"some sticks\" },!@#&}!@#&!@#&local tGoWest = {!@#&	\"(life is peaceful there)\",!@#&	\"(lots of open air)\",!@#&	\"(to begin life anew)\",!@#&	\"(this is what we'll do)\",!@#&	\"(sun in winter time)\",!@#&	\"(we will do just fine)\",!@#&	\"(where the skies are blue)\",!@#&	\"(this and more we'll do)\",!@#&}!@#&local nGoWest = 0!@#&!@#&local bRunning = true!@#&local tMap = { { {}, }, }!@#&local x,y,z = 0,0,0!@#&local inventory = {!@#&	[\"no tea\"] = items[\"no tea\"],!@#&}!@#&!@#&local nTurn = 0!@#&local nTimeInRoom = 0!@#&local bInjured = false!@#&!@#&local tDayCycle = {!@#&	\"It is daytime.\",!@#&	\"It is daytime.\",!@#&	\"It is daytime.\",!@#&	\"It is daytime.\",!@#&	\"It is daytime.\",!@#&	\"It is daytime.\",!@#&	\"It is daytime.\",!@#&	\"It is daytime.\",!@#&	\"The sun is setting.\",!@#&	\"It is night.\",!@#&	\"It is night.\",!@#&	\"It is night.\",!@#&	\"It is night.\",!@#&	\"It is night.\",!@#&	\"The sun is rising.\",!@#&}!@#&!@#&local function getTimeOfDay()!@#&	return math.fmod( math.floor(nTurn/3), #tDayCycle ) + 1!@#&end!@#&!@#&local function isSunny()!@#&	return (getTimeOfDay() < 10)!@#&end!@#&!@#&local function getRoom( x, y, z, dontCreate )!@#&	tMap[x] = tMap[x] or {}!@#&	tMap[x][y] = tMap[x][y] or {}!@#&	if not tMap[x][y][z] and dontCreate ~= true then!@#& 		local room = {!@#& 			items = {},!@#& 			exits = {},!@#& 			nMonsters = 0,!@#& 		}!@#&		tMap[x][y][z] = room!@#&		!@#&		if y == 0 then!@#&			-- Room is above ground!@#&!@#&			-- Pick biome!@#&			room.nBiome = math.random( 1, #tBiomes )!@#&			room.trees = hasTrees( room.nBiome )!@#&		!@#&			-- Add animals!@#&			if math.random(1,3) == 1 then!@#&				for n = 1,math.random(1,2) do!@#&					local sAnimal = tAnimals[ math.random( 1, #tAnimals ) ]!@#&					room.items[ sAnimal ] = items[ sAnimal ]!@#&				end!@#&			end!@#&			!@#&			-- Add surface ore!@#&			if math.random(1,5) == 1 or hasStone( room.nBiome ) then!@#&				room.items[ \"some stone\" ] = items[ \"some stone\" ]!@#&			end!@#&			if math.random(1,8) == 1 then!@#&				room.items[ \"some coal\" ] = items[ \"some coal\" ]!@#&			end!@#&			if math.random(1,8) == 1 and hasRivers( room.nBiome ) then!@#&				room.items[ \"a river\" ] = items[ \"a river\" ]!@#&			end!@#&		!@#&			-- Add exits!@#&			room.exits = {!@#&				[\"north\"] = true,!@#&				[\"south\"] = true,!@#&				[\"east\"] = true,!@#&				[\"west\"] = true,!@#&			}!@#&			if math.random(1,8) == 1 then!@#&				room.exits[\"down\"] = true!@#&				room.items[\"a cave entrance\"] = items[\"a cave entrance\"]!@#&			end!@#&						!@#&		else!@#&			-- Room is underground!@#&			-- Add exits!@#&			local function tryExit( sDir, sOpp, x, y, z )!@#&				local adj = getRoom( x, y, z, true )!@#&				if adj then!@#&					if adj.exits[sOpp] then!@#&						room.exits[sDir] = true!@#&					end!@#&				else!@#&					if math.random(1,3) == 1 then!@#&						room.exits[sDir] = true!@#&					end!@#&				end!@#&			end!@#&			!@#&			if y == -1 then!@#&				local above = getRoom( x, y + 1, z )!@#&				if above.exits[\"down\"] then!@#&					room.exits[\"up\"] = true!@#&					room.items[\"an exit to the surface\"] = items[\"an exit to the surface\"]!@#&				end!@#&			else!@#&				tryExit( \"up\", \"down\", x, y + 1, z )!@#&			end!@#&			!@#&			if y > -3 then!@#&				tryExit( \"down\", \"up\", x, y - 1, z )!@#&			end!@#&			!@#&			tryExit( \"east\", \"west\", x - 1, y, z )!@#&			tryExit( \"west\", \"east\", x + 1, y, z )!@#&			tryExit( \"north\", \"south\", x, y, z + 1 )!@#&			tryExit( \"south\", \"north\", x, y, z - 1 )	!@#&			!@#&			-- Add ores!@#&			room.items[ \"some stone\" ] = items[ \"some stone\" ]!@#&			if math.random(1,3) == 1 then!@#&				room.items[ \"some coal\" ] = items[ \"some coal\" ]!@#&			end!@#&			if math.random(1,8) == 1 then!@#&				room.items[ \"some iron\" ] = items[ \"some iron\" ]!@#&			end!@#&			if y == -3 and math.random(1,15) == 1 then!@#&				room.items[ \"some diamond\" ] = items[ \"some diamond\" ]!@#&			end!@#&			!@#&			-- Turn out the lights!@#&			room.dark = true!@#&		end!@#&	end!@#&	return tMap[x][y][z]!@#&end!@#&!@#&local function itemize( t )!@#&	local item = next( t )!@#&	if item == nil then!@#&		return \"nothing\"!@#&	end!@#&	!@#&	local text = \"\"!@#&	while item do!@#&		text = text .. item!@#&		!@#&		local nextItem = next( t, item )!@#&		if nextItem ~= nil then!@#&			local nextNextItem = next( t, nextItem )!@#&			if nextNextItem == nil then!@#&				text = text .. \" and \"!@#&			else!@#&				text = text .. \", \"!@#&			end!@#&		end!@#&		item = nextItem!@#&	end!@#&	return text!@#&end!@#&!@#&function findItem( _tList, _sQuery )!@#&	for sItem, tItem in pairs( _tList ) do!@#&		if sItem == _sQuery then!@#&			return sItem!@#&		end!@#&		if tItem.aliases ~= nil then!@#&			for n, sAlias in pairs( tItem.aliases ) do!@#&				if sAlias == _sQuery then!@#&					return sItem!@#&				end!@#&			end!@#&		end!@#&	end!@#&	return nil!@#&end!@#&!@#&local tMatches = {!@#&	[\"wait\"] = {!@#&		\"wait\",!@#&	},!@#&	[\"look\"] = {!@#&		\"look at the ([%a ]+)\",!@#&		\"look at ([%a ]+)\",!@#&		\"look\",!@#&		\"inspect ([%a ]+)\",!@#&		\"inspect the ([%a ]+)\",!@#&		\"inspect\",!@#&	},!@#&	[\"inventory\"] = {!@#&		\"check self\",!@#&		\"check inventory\",!@#&		\"inventory\",!@#&		\"i\",!@#&	},!@#&	[\"go\"] = {!@#&		\"go (%a+)\",!@#&		\"travel (%a+)\",!@#&		\"walk (%a+)\",!@#&		\"run (%a+)\",!@#&		\"go\",!@#&	},!@#&	[\"dig\"] = {!@#&		\"dig (%a+) using ([%a ]+)\",!@#&		\"dig (%a+) with ([%a ]+)\",!@#&		\"dig (%a+)\",!@#&		\"dig\",!@#&	},!@#&	[\"take\"] = {!@#&		\"pick up the ([%a ]+)\",!@#&		\"pick up ([%a ]+)\",!@#&		\"pickup ([%a ]+)\",!@#&		\"take the ([%a ]+)\",!@#&		\"take ([%a ]+)\",!@#&		\"take\",!@#&	},!@#&	[\"drop\"] = {!@#&		\"put down the ([%a ]+)\",!@#&		\"put down ([%a ]+)\",!@#&		\"drop the ([%a ]+)\",!@#&		\"drop ([%a ]+)\",!@#&		\"drop\",!@#&	},!@#&	[\"place\"] = {!@#&		\"place the ([%a ]+)\",!@#&		\"place ([%a ]+)\",!@#&		\"place\",!@#&	},!@#&	[\"cbreak\"] = {!@#&		\"punch the ([%a ]+)\",!@#&		\"punch ([%a ]+)\",!@#&		\"punch\",!@#&		\"break the ([%a ]+) with the ([%a ]+)\",!@#&		\"break ([%a ]+) with ([%a ]+) \",!@#&		\"break the ([%a ]+)\",!@#&		\"break ([%a ]+)\",!@#&		\"break\",!@#&	},!@#&	[\"mine\"] = {!@#&		\"mine the ([%a ]+) with the ([%a ]+)\",!@#&		\"mine ([%a ]+) with ([%a ]+)\",!@#&		\"mine ([%a ]+)\",!@#&		\"mine\",!@#&	},!@#&	[\"attack\"] = {!@#&		\"attack the ([%a ]+) with the ([%a ]+)\",!@#&		\"attack ([%a ]+) with ([%a ]+)\",!@#&		\"attack ([%a ]+)\",!@#&		\"attack\",!@#&		\"kill the ([%a ]+) with the ([%a ]+)\",!@#&		\"kill ([%a ]+) with ([%a ]+)\",!@#&		\"kill ([%a ]+)\",!@#&		\"kill\",!@#&		\"hit the ([%a ]+) with the ([%a ]+)\",!@#&		\"hit ([%a ]+) with ([%a ]+)\",!@#&		\"hit ([%a ]+)\",!@#&		\"hit\",!@#&	},!@#&	[\"craft\"] = {!@#&		\"craft a ([%a ]+)\",!@#&		\"craft some ([%a ]+)\",!@#&		\"craft ([%a ]+)\",!@#&		\"craft\",!@#&		\"make a ([%a ]+)\",!@#&		\"make some ([%a ]+)\",!@#&		\"make ([%a ]+)\",!@#&		\"make\",!@#&	},!@#&	[\"build\"] = {!@#&		\"build ([%a ]+) out of ([%a ]+)\",!@#&		\"build ([%a ]+) from ([%a ]+)\",!@#&		\"build ([%a ]+)\",!@#&		\"build\",!@#&	},!@#&	[\"eat\"] = {!@#&		\"eat a ([%a ]+)\",!@#&		\"eat the ([%a ]+)\",!@#&		\"eat ([%a ]+)\",!@#&		\"eat\",!@#&	},!@#&	[\"help\"] = {!@#&		\"help me\",!@#&		\"help\",!@#&	},!@#&	[\"exit\"] = {!@#&		\"exit\",!@#&		\"quit\",!@#&		\"goodbye\",!@#&		\"good bye\",!@#&		\"bye\",!@#&		\"farewell\",!@#&	},!@#&}!@#&!@#&local commands = {}!@#&function doCommand( text )!@#&	if text == \"\" then!@#&		commands[ \"noinput\" ]()!@#&		return!@#&	end!@#&	!@#&	for sCommand, t in pairs( tMatches ) do!@#&		for n, sMatch in pairs( t ) do!@#&			local tCaptures = { string.match( text, \"^\" .. sMatch .. \"$\" ) }!@#&			if #tCaptures ~= 0 then!@#&				local fnCommand = commands[ sCommand ]!@#&				if #tCaptures == 1 and tCaptures[1] == sMatch then!@#&					fnCommand()!@#&				else!@#&					fnCommand( unpack( tCaptures ) )!@#&				end!@#&				return!@#&			end!@#&		end!@#&	end!@#&	commands[ \"badinput\" ]()!@#&end!@#&!@#&function commands.wait()!@#&	print( \"Time passes...\" )!@#&end!@#&!@#&function commands.look( _sTarget )!@#&	local room = getRoom( x,y,z )!@#&	if room.dark then!@#&		print( \"It is pitch dark.\" )!@#&		return!@#&	end!@#&!@#&	if _sTarget == nil then!@#&		-- Look at the world!@#&		if y == 0 then!@#&			io.write( \"You are standing \" .. tBiomes[room.nBiome] .. \". \" )!@#&			print( tDayCycle[ getTimeOfDay() ] )!@#&		else!@#&			io.write( \"You are underground. \" )!@#&			if next( room.exits ) ~= nil then!@#&				print( \"You can travel \"..itemize( room.exits )..\".\" )!@#&			else!@#&				print()!@#&			end!@#&		end!@#&		if next( room.items ) ~= nil then!@#&			print( \"There is \" .. itemize( room.items ) .. \" here.\" )!@#&		end!@#&		if room.trees then!@#&			print( \"There are trees here.\" )!@#&		end!@#&		!@#&	else!@#&		-- Look at stuff!@#&		if room.trees and (_sTarget == \"tree\" or _sTarget == \"trees\") then!@#&			print( \"The trees look easy to break.\" )!@#&		elseif _sTarget == \"self\" or _sTarget == \"myself\" then!@#&			print( \"Very handsome.\" )!@#&		else!@#&			local tItem = nil!@#&			local sItem = findItem( room.items, _sTarget )!@#&			if sItem then!@#&				tItem = room.items[sItem]!@#&			else!@#&				sItem = findItem( inventory, _sTarget )!@#&				if sItem then!@#&					tItem = inventory[sItem]!@#&				end!@#&			end!@#&			!@#&			if tItem then!@#&				print( tItem.desc or (\"You see nothing special about \"..sItem..\".\") )!@#&			else!@#&				print( \"You don't see any \".._sTarget..\" here.\" )!@#&			end!@#&		end!@#&	end!@#&end!@#&!@#&function commands.go( _sDir )!@#&	local room = getRoom( x,y,z )!@#&	if _sDir == nil then!@#&		print( \"Go where?\" )!@#&		return!@#&	end!@#&	!@#&	if nGoWest ~= nil then!@#&		if _sDir == \"west\" then!@#&			nGoWest = nGoWest + 1!@#&			if nGoWest > #tGoWest then!@#&				nGoWest = 1!@#&			end!@#&			print( tGoWest[ nGoWest ] )!@#&		else!@#&			if nGoWest > 0 or nTurn > 6 then!@#&				nGoWest = nil!@#&			end!@#&		end!@#&	end!@#&	!@#&	if room.exits[_sDir] == nil then!@#&		print( \"You can't go that way.\" )!@#&		return!@#&	end!@#&	!@#&	if _sDir == \"north\" then!@#&		z = z + 1!@#&	elseif _sDir == \"south\" then!@#&		z = z - 1!@#&	elseif _sDir == \"east\" then!@#&		x = x - 1!@#&	elseif _sDir == \"west\" then!@#&		x = x + 1!@#&	elseif _sDir == \"up\" then!@#&		y = y + 1!@#&	elseif _sDir == \"down\" then!@#&		y = y - 1!@#&	else!@#&		print( \"I don't understand that direction.\" )!@#&		return!@#&	end!@#&	!@#&	nTimeInRoom = 0!@#&	doCommand( \"look\" )!@#&end!@#&!@#&function commands.dig( _sDir, _sTool )!@#&	local room = getRoom( x,y,z )!@#&	if _sDir == nil then!@#&		print( \"Dig where?\" )!@#&		return!@#&	end!@#&	!@#&	local sTool = nil!@#&	local tTool = nil!@#&	if _sTool ~= nil then!@#&		sTool = findItem( inventory, _sTool )!@#&		if not sTool then!@#&			print( \"You're not carrying a \".._sTool..\".\" )!@#&			return!@#&		end!@#&		tTool = inventory[ sTool ]!@#&	end!@#&	!@#&	local room = getRoom( x, y, z )!@#&	local bActuallyDigging = (room.exits[ _sDir ] ~= true)!@#&	if bActuallyDigging then!@#&		if sTool == nil or tTool.toolType ~= \"pick\" then!@#&			print( \"You need to use a pickaxe to dig through stone.\" )!@#&			return!@#&		end!@#&	end!@#&	!@#&	if _sDir == \"north\" then!@#&		room.exits[\"north\"] = true!@#&		z = z + 1!@#&		getRoom( x, y, z ).exits[\"south\"] = true!@#&!@#&	elseif _sDir == \"south\" then!@#&		room.exits[\"south\"] = true!@#&		z = z - 1!@#&		getRoom( x, y, z ).exits[\"north\"] = true!@#&		!@#&	elseif _sDir == \"east\" then!@#&		room.exits[\"east\"] = true!@#&		x = x - 1!@#&		getRoom( x, y, z ).exits[\"west\"] = true!@#&		!@#&	elseif _sDir == \"west\" then!@#&		room.exits[\"west\"] = true!@#&		x = x + 1!@#&		getRoom( x, y, z ).exits[\"east\"] = true!@#&		!@#&	elseif _sDir == \"up\" then!@#&		if y == 0 then!@#&			print( \"You can't dig that way.\" )!@#&			return!@#&		end!@#&!@#&		room.exits[\"up\"] = true!@#&		if y == -1 then!@#&			room.items[ \"an exit to the surface\" ] = items[ \"an exit to the surface\" ]!@#&		end!@#&		y = y + 1!@#&		!@#&		room = getRoom( x, y, z )!@#&		room.exits[\"down\"] = true!@#&		if y == 0 then!@#&			room.items[ \"a cave entrance\" ] = items[ \"a cave entrance\" ]!@#&		end!@#&		!@#&	elseif _sDir == \"down\" then!@#&		if y <= -3 then!@#&			print( \"You hit bedrock.\" )!@#&			return!@#&		end!@#&!@#&		room.exits[\"down\"] = true!@#&		if y == 0 then!@#&			room.items[ \"a cave entrance\" ] = items[ \"a cave entrance\" ]!@#&		end!@#&		y = y - 1!@#&		!@#&		room = getRoom( x, y, z )!@#&		room.exits[\"up\"] = true!@#&		if y == -1 then!@#&			room.items[ \"an exit to the surface\" ] = items[ \"an exit to the surface\" ]!@#&		end!@#&		!@#&	else!@#&		print( \"I don't understand that direction.\" )!@#&		return!@#&	end!@#&	!@#&	--!@#&	if bActuallyDigging then!@#&		if _sDir == \"down\" and y == -1 or!@#&		   _sDir == \"up\" and y == 0 then!@#&			inventory[ \"some dirt\" ] = items[ \"some dirt\" ]!@#&			inventory[ \"some stone\" ] = items[ \"some stone\" ]!@#&			print( \"You dig \".._sDir..\" using \"..sTool..\" and collect some dirt and stone.\" )!@#&		else!@#&			inventory[ \"some stone\" ] = items[ \"some stone\" ]!@#&			print( \"You dig \".._sDir..\" using \"..sTool..\" and collect some stone.\" )!@#&		end!@#&	end!@#&	!@#&	nTimeInRoom = 0!@#&	doCommand( \"look\" )!@#&end!@#&!@#&function commands.inventory()!@#&	print( \"You are carrying \" .. itemize( inventory ) .. \".\" )!@#&end!@#&!@#&function commands.drop( _sItem )!@#&	if _sItem == nil then!@#&		print( \"Drop what?\" )!@#&		return!@#&	end!@#&	!@#&	local room = getRoom( x,y,z )!@#&	local sItem = findItem( inventory, _sItem )!@#&	if sItem then!@#&		local tItem = inventory[ sItem ]!@#&		if tItem.droppable == false then!@#&			print( \"You can't drop that.\" )!@#&		else!@#&			room.items[ sItem ] = tItem!@#&			inventory[ sItem ] = nil!@#&			print( \"Dropped.\" )!@#&		end!@#&	else!@#&		print( \"You don't have a \".._sItem..\".\" )!@#&	end!@#&end!@#&!@#&function commands.place( _sItem )!@#&	if _sItem == nil then!@#&		print( \"Place what?\" )!@#&		return!@#&	end!@#&	!@#&	if _sItem == \"torch\" or _sItem == \"a torch\" then!@#&		local room = getRoom( x,y,z )!@#&		if inventory[\"some torches\"] or inventory[\"a torch\"] then!@#&			inventory[\"a torch\"] = nil!@#&			room.items[\"a torch\"] = items[\"a torch\"]!@#&			if room.dark then!@#&				print( \"The cave lights up under the torchflame.\" )!@#&				room.dark = false!@#&			elseif y == 0 and not isSunny() then!@#&				print( \"The night gets a little brighter.\" )!@#&			else!@#&				print( \"Placed.\" )!@#&			end!@#&		else!@#&			print( \"You don't have torches.\" )!@#&		end!@#&		return!@#&	end!@#&	!@#&	commands.drop( _sItem )!@#&end!@#&!@#&function commands.take( _sItem )!@#&	if _sItem == nil then!@#&		print( \"Take what?\" )!@#&		return!@#&	end!@#&!@#&	local room = getRoom( x,y,z )!@#&	local sItem = findItem( room.items, _sItem )!@#&	if sItem then!@#&		local tItem = room.items[ sItem ]!@#&		if tItem.heavy == true then!@#&			print( \"You can't carry \"..sItem..\".\" )!@#&		elseif tItem.ore == true then!@#&			print( \"You need to mine this ore.\" )!@#&		else!@#&			if tItem.infinite ~= true then!@#&				room.items[ sItem ] = nil!@#&			end!@#&			inventory[ sItem ] = tItem!@#&			!@#&			if inventory[\"some torches\"] and inventory[\"a torch\"] then!@#&				inventory[\"a torch\"] = nil!@#&			end!@#&			if sItem == \"a torch\" and y < 0 then!@#&				room.dark = true!@#&				print( \"The cave plunges into darkness.\" )!@#&			else!@#&				print( \"Taken.\" )!@#&			end!@#&		end!@#&	else!@#&		print( \"You don't see a \".._sItem..\" here.\" )!@#&	end!@#&end!@#&!@#&function commands.mine( _sItem, _sTool )!@#&	if _sItem == nil then!@#&		print( \"Mine what?\" )!@#&		return!@#&	end!@#&	if _sTool == nil then!@#&		print( \"Mine \".._sItem..\" with what?\" )!@#&		return!@#&	end	!@#&	commands.cbreak( _sItem, _sTool )!@#&end!@#&!@#&function commands.attack( _sItem, _sTool )!@#&	if _sItem == nil then!@#&		print( \"Attack what?\" )!@#&		return!@#&	end!@#&	commands.cbreak( _sItem, _sTool )!@#&end!@#&!@#&function commands.cbreak( _sItem, _sTool )!@#&	if _sItem == nil then!@#&		print( \"Break what?\" )!@#&		return!@#&	end!@#&	!@#&	local sTool = nil!@#&	if _sTool ~= nil then!@#&		sTool = findItem( inventory, _sTool )!@#&		if sTool == nil then!@#&			print( \"You're not carrying a \".._sTool..\".\" )!@#&			return!@#&		end!@#&	end!@#&!@#&	local room = getRoom( x,y,z )!@#&	if _sItem == \"tree\" or _sItem == \"trees\" or _sItem == \"a tree\" then!@#&		print( \"The tree breaks into blocks of wood, which you pick up.\" )!@#&		inventory[ \"some wood\" ] = items[ \"some wood\" ]!@#&		return!@#&	elseif _sItem == \"self\" or _sItem == \"myself\" then!@#&		if term.isColour() then!@#&			term.setTextColour( colours.red )!@#&		end!@#&		print( \"You have died.\" )!@#&		print( \"Score: &e0\" )!@#&		term.setTextColour( colours.white )!@#&		bRunning = false!@#&		return!@#&	end!@#&	!@#&	local sItem = findItem( room.items, _sItem )!@#&	if sItem then!@#&		local tItem = room.items[ sItem ]!@#&		if tItem.ore == true then!@#&			-- Breaking ore!@#&			if not sTool then!@#&				print( \"You need a tool to break this ore.\" )!@#&				return!@#&			end!@#&			local tTool = inventory[ sTool ]!@#&			if tTool.tool then!@#&				if tTool.toolLevel < tItem.toolLevel then!@#&					print( sTool ..\" is not strong enough to break this ore.\" )!@#&				elseif tTool.toolType ~= tItem.toolType then!@#&					print( \"You need a different kind of tool to break this ore.\" )!@#&				else!@#&					print( \"The ore breaks, dropping \"..sItem..\", which you pick up.\" )!@#&					inventory[ sItem ] = items[ sItem ]!@#&					if tItem.infinite ~= true then!@#&						room.items[ sItem ] = nil!@#&					end!@#&				end!@#&			else!@#&				print( \"You can't break \"..sItem..\" with \"..sTool..\".\")!@#&			end!@#&			!@#&		elseif tItem.creature == true then!@#&			-- Fighting monsters (or pigs)!@#&			local toolLevel = 0!@#&			local tTool = nil!@#&			if sTool then!@#&				tTool = inventory[ sTool ]!@#&				if tTool.toolType == \"sword\" then!@#&					toolLevel = tTool.toolLevel!@#&				end!@#&			end!@#&						!@#&			local tChances = { 0.2, 0.4, 0.55, 0.8, 1 }!@#&			if math.random() <= tChances[ toolLevel + 1 ] then!@#&				room.items[ sItem ] = nil!@#&				print( \"The \"..tItem.aliases[1]..\" dies.\" )!@#&	!@#&				if tItem.drops then!@#&					for n, sDrop in pairs( tItem.drops ) do!@#&						if not room.items[sDrop] then!@#&							print( \"The \"..tItem.aliases[1]..\" dropped \"..sDrop..\".\" )!@#&							room.items[sDrop] = items[sDrop]!@#&						end!@#&					end!@#&				end!@#&				!@#&				if tItem.monster then!@#&					room.nMonsters = room.nMonsters - 1!@#&				end!@#&			else!@#&				print( \"The \"..tItem.aliases[1]..\" is injured by your blow.\" )!@#&			end!@#&			!@#&			if tItem.hitDrops then!@#&				for n, sDrop in pairs( tItem.hitDrops ) do!@#&					if not room.items[sDrop] then!@#&						print( \"The \"..tItem.aliases[1]..\" dropped \"..sDrop..\".\" )!@#&						room.items[sDrop] = items[sDrop]!@#&					end!@#&				end!@#&			end!@#&		!@#&		else!@#&			print( \"You can't break \"..sItem..\".\" )!@#&		end!@#&	else!@#&		print( \"You don't see a \".._sItem..\" here.\" )!@#&	end!@#&end!@#&!@#&function commands.craft( _sItem )!@#&	if _sItem == nil then!@#&		print( \"Craft what?\" )!@#&		return!@#&	end!@#&	!@#&	if _sItem == \"computer\" or _sItem == \"a computer\" then!@#&		print( \"By creating a computer in a computer in a computer, you tear a hole in the spacetime continuum from which no mortal being can escape.\" )!@#&		if term.isColour() then!@#&			term.setTextColour( colours.red )!@#&		end!@#&		print( \"You have died.\" )!@#&		print( \"Score: &e0\" )!@#&		term.setTextColour( colours.white )!@#&		bRunning = false!@#&		return!@#&	end!@#&	!@#&	local room = getRoom( x,y,z )!@#&	local sItem = findItem( items, _sItem )!@#&	local tRecipe = (sItem and tRecipes[ sItem ]) or nil!@#&	if tRecipe then!@#&		for n,sReq in ipairs( tRecipe ) do!@#&			if inventory[sReq] == nil then!@#&				print( \"You don't have the items you need to craft \"..sItem..\".\" )!@#&				return!@#&			end!@#&		end!@#&		!@#&		for n,sReq in ipairs( tRecipe ) do!@#&			inventory[sReq] = nil!@#&		end!@#&		inventory[ sItem ] = items[ sItem ]!@#&		if inventory[\"some torches\"] and inventory[\"a torch\"] then!@#&			inventory[\"a torch\"] = nil!@#&		end!@#&		print( \"Crafted.\" )!@#&	else!@#&		print( \"You don't know how to make \"..(sItem or _sItem)..\".\" )!@#&	end	!@#&end!@#&!@#&function commands.build( _sThing, _sMaterial )!@#&	if _sThing == nil then!@#&		print( \"Build what?\" )!@#&		return!@#&	end!@#&		!@#&	local sMaterial = nil!@#&	if _sMaterial == nil then!@#&		for sItem, tItem in pairs( inventory ) do!@#&			if tItem.material then!@#&				sMaterial = sItem!@#&				break!@#&			end!@#&		end!@#&		if sMaterial == nil then!@#&			print( \"You don't have any building materials.\" )!@#&			return!@#&		end!@#&	else!@#&		sMaterial = findItem( inventory, _sMaterial )!@#&		if not sMaterial then!@#&			print( \"You don't have any \".._sMaterial )!@#&			return!@#&		end!@#&		!@#&		if inventory[sMaterial].material ~= true then!@#&			print( sMaterial..\" is not a good building material.\" )!@#&			return!@#&		end!@#&	end!@#&	!@#&	local alias = nil!@#&	if string.sub(_sThing, 1, 1) == \"a\" then!@#&		alias = string.match( _sThing, \"a ([%a ]+)\" )!@#&	end!@#&	!@#&	local room = getRoom( x,y,z )!@#&	inventory[sMaterial] = nil!@#&	room.items[ _sThing ] = {!@#&		heavy = true,!@#&		aliases = { alias },!@#&		desc = \"As you look at your creation (made from \"..sMaterial..\"), you feel a swelling sense of pride.\",!@#&	}!@#&!@#&	print( \"Your construction is complete.\" )!@#&end!@#&!@#&function commands.help()!@#&	local sText = !@#&		\"Welcome to adventure, the greatest text adventure game on CraftOS. \" ..!@#&		\"To get around the world, type actions, and the adventure will \" ..!@#&		\"be read back to you. The actions availiable to you are go, look, inspect, inventory, \" ..!@#&		\"take, drop, place, punch, attack, mine, dig, craft, build, eat and exit.\"!@#&	print( sText )!@#&end!@#&!@#&function commands.eat( _sItem )!@#&	if _sItem == nil then!@#&		print( \"Eat what?\" )!@#&		return!@#&	end!@#&!@#&	local sItem = findItem( inventory, _sItem )!@#&	if not sItem then!@#&		print( \"You don't have any \".._sItem..\".\" )!@#&		return!@#&	end!@#&	!@#&	local tItem = inventory[sItem]!@#&	if tItem.food then!@#&		print( \"That was delicious!\" )!@#&		inventory[sItem] = nil!@#&		!@#&		if bInjured then!@#&			print( \"You are no longer injured.\" )!@#&			bInjured = false!@#&		end!@#&	else!@#&		print( \"You can't eat \"..sItem..\".\" )!@#&	end!@#&end!@#&!@#&function commands.exit()!@#&	bRunning = false!@#&end!@#&!@#&function commands.badinput()!@#&	local tResponses = {!@#&		\"I don't understand.\",!@#&		\"I don't understand you.\",!@#&		\"You can't do that.\",!@#&		\"Nope.\",!@#&		\"Huh?\",!@#&		\"Say again?\",!@#&		\"That's crazy talk.\",!@#&		\"Speak clearly.\",!@#&		\"I'll think about it.\",!@#&		\"Let me get back to you on that one.\",!@#&		\"That doesn't make any sense.\",!@#&		\"What?\",!@#&	}!@#&	print( tResponses[ math.random(1,#tResponses) ] )!@#&end!@#&!@#&function commands.noinput()!@#&	local tResponses = {!@#&		\"Speak up.\",!@#&		\"Enunciate.\",!@#&		\"Project your voice.\",!@#&		\"Don't be shy.\",!@#&		\"Use your words.\",!@#&	}!@#&	print( tResponses[ math.random(1,#tResponses) ] )!@#&end!@#&!@#&local function simulate()!@#&	local bNewMonstersThisRoom = false!@#&	!@#&	-- Spawn monsters in nearby rooms!@#&	for sx = -2,2 do!@#&		for sy = -1,1 do!@#&			for sz = -2,2 do!@#&				local h = y + sy!@#&				if h >= -3 and h <= 0 then!@#&					local room = getRoom( x + sx, h, z + sz )!@#&					!@#&					-- Spawn monsters!@#&					if room.nMonsters < 2 and!@#&					   ((h == 0 and not isSunny() and not room.items[\"a torch\"]) or room.dark) and!@#&					   math.random(1,6) == 1 then!@#&					   !@#&						local sMonster = tMonsters[ math.random(1,#tMonsters) ]!@#&						if room.items[ sMonster ] == nil then!@#&					   		room.items[ sMonster ] = items[ sMonster ]!@#&					   		room.nMonsters = room.nMonsters + 1!@#&					   		!@#&					   		if sx == 0 and sy == 0 and sz == 0 and not room.dark then!@#&					   			print( \"From the shadows, \"..sMonster..\" appears.\" )!@#&					   			bNewMonstersThisRoom = true!@#&					   		end!@#&						end	!@#&					end!@#&					!@#&					-- Burn monsters!@#&					if h == 0 and isSunny() then!@#&						for n,sMonster in ipairs( tMonsters ) do!@#&							if room.items[sMonster] and items[sMonster].nocturnal then!@#&								room.items[sMonster] = nil!@#&						   		if sx == 0 and sy == 0 and sz == 0 and not room.dark then!@#&						   			print( \"With the sun high in the sky, the \"..items[sMonster].aliases[1]..\" bursts into flame and dies.\" )!@#&						   		end!@#&						   		room.nMonsters = room.nMonsters - 1!@#&						   	end!@#&						end!@#&					end	!@#&				end!@#&			end!@#&		end!@#&	end!@#&!@#&	-- Make monsters attack!@#&	local room = getRoom( x, y, z )!@#&	if nTimeInRoom >= 2 and not bNewMonstersThisRoom then!@#&		for n,sMonster in ipairs( tMonsters ) do!@#&			if room.items[sMonster] then!@#&				if math.random(1,4) == 1 and!@#&				   not (y == 0 and isSunny() and (sMonster == \"a spider\")) then!@#&					if sMonster == \"a creeper\" then!@#&						if room.dark then!@#&							print( \"A creeper explodes.\" )!@#&						else!@#&							print( \"The creeper explodes.\" )!@#&						end!@#&						room.items[sMonster] = nil!@#&						room.nMonsters = room.nMonsters - 1!@#&					else!@#&						if room.dark then!@#&							print( \"A \"..items[sMonster].aliases[1]..\" attacks you.\" )!@#&						else!@#&							print( \"The \"..items[sMonster].aliases[1]..\" attacks you.\" )!@#&						end!@#&					end!@#&					!@#&					if bInjured then!@#&						if term.isColour() then!@#&							term.setTextColour( colours.red )!@#&						end!@#&						print( \"You have died.\" )!@#&						print( \"Score: &e0\" )!@#&						term.setTextColour( colours.white )!@#&						bRunning = false!@#&						return!@#&					else!@#&						bInjured = true!@#&					end!@#&					!@#&					break!@#&				end!@#&			end!@#&		end!@#&	end!@#&	!@#&	-- Always print this!@#&	if bInjured then!@#&		if term.isColour() then!@#&			term.setTextColour( colours.red )!@#&		end!@#&		print( \"You are injured.\" )!@#&		term.setTextColour( colours.white )!@#&	end!@#&	!@#&	-- Advance time!@#&	nTurn = nTurn + 1!@#&	nTimeInRoom = nTimeInRoom + 1!@#&end!@#&!@#&doCommand( \"look\" )!@#&simulate()!@#&!@#&local tCommandHistory = {}!@#&while bRunning do!@#&	if term.isColour() then!@#&		term.setTextColour( colours.yellow )!@#&	end!@#&    write( \"? \" )!@#&	term.setTextColour( colours.white )!@#&		!@#&    local sRawLine = read( nil, tCommandHistory )!@#&    table.insert( tCommandHistory, sRawLine )!@#&    !@#&    local sLine = nil!@#&	for match in string.gmatch(sRawLine, \"%a+\") do!@#&		if sLine then!@#&			sLine = sLine .. \" \" .. string.lower(match)!@#&		else!@#&			sLine = string.lower(match)!@#&		end!@#&	end!@#&	!@#&	doCommand( sLine or \"\" )!@#&    if bRunning then!@#&	    simulate()!@#&	end!@#&end",},["apis"]={["seperator"]="function seperate(str, sep)!@#& local sep, fields = (sep~='' and sep) or \" \", {}!@#& local pattern = string.format(\"([^%s]+)\", sep)!@#&  str:gsub(pattern, function(c) fields[#fields+1] = c end)!@#& return fields!@#&end!@#&!@#&function help()!@#&  return \"seperator.seperate(string, seperation_character) returns table with every word seperated by seperation_character\",!@#&  \"seperator.listMethods() -lists all methods\"!@#&end!@#&!@#&function listMethods()!@#&  return \"seperator.help()\",!@#&  \"seperator.seperate(str, sep)\",!@#&  \"seperator.listMethods()\"!@#&end",},["programs"]={["npaintpro"]="--[[!@#&                NPaintPro!@#&                By NitrogenFingers!@#&]]--!@#& !@#&--The screen size!@#&local w,h = term.getSize()!@#&--Whether or not the program is currently waiting on user input!@#&local inMenu = false!@#&--Whether or not a drop down menu is active!@#&local inDropDown = false!@#&--Whether or not animation tools are enabled (use -a to turn them on)!@#&local animated = false!@#&--Whether or not the text tools are enabled (use -t to turn them on)!@#&local textual = false!@#&--Whether or not \"blueprint\" display mode is on!@#&local blueprint = false!@#&--Whether or not the \"layer\" display is on!@#&local layerDisplay = false!@#&--Whether or not the interface is presently hidden!@#&local interfaceHidden = false!@#&--Whether or not the \"direction\" display is on!@#&local printDirection = false!@#&--The tool/mode npaintpro is currently in. Default is \"paint\"!@#&--For a list of modes, check out the help file!@#&local state = \"paint\"!@#&--Whether or not the program is presently running!@#&local isRunning = true!@#&--The rednet address of the 3D printer, if one has been attached!@#&local printer = nil!@#& !@#&--The list of every frame, containing every image in the picture/animation!@#&--Note: nfp files always have the picture at frame 1!@#&local frames = { }!@#&--How many frames are currently in the given animation.!@#&local frameCount = 1!@#&--The Colour Picker column!@#&local column = {}!@#&--The offset of visible colours in the picker column, if the screen cannot fit all 16!@#&local columnoffset = 0!@#&--The currently selected left and right colours!@#&local lSel,rSel = colours.black,nil!@#&--The amount of scrolling on the X and Y axis!@#&local sx,sy = 0,0!@#&--The alpha channel colour!@#&--Change this to change default canvas colour!@#&local alphaC = colours.white!@#&--The currently selected frame. Default is 1!@#&local sFrame = 1!@#&--The contents of the image buffer- contains contents, width and height!@#&local buffer = nil!@#&--The position, width and height of the selection rectangle!@#&local selectrect = nil!@#& !@#&--Whether or not text tools are enabled for this document!@#&local textEnabled = false!@#&--The X and Y positions of the text cursor!@#&local textCurX, textCurY = 1,1!@#& !@#&--The currently calculated required materials!@#&local requiredMaterials = {}!@#&--Whether or not required materials are being displayed in the pallette!@#&local requirementsDisplayed = false!@#&--A list of the rednet ID's all in-range printers located!@#&local printerList = { }!@#&--A list of the names of all in-range printers located. Same as the printerList in reference!@#&local printerNames = { }!@#&--The selected printer!@#&local selectedPrinter = 1!@#&--The X,Y,Z and facing of the printer!@#&local px,py,pz,pfx,pfz = 0,0,0,0,0!@#&--The form of layering used!@#&local layering = \"up\"!@#& !@#&--The animation state of the selection rectangle and image buffer!@#&local rectblink = 0!@#&--The ID for the timer!@#&local recttimer = nil!@#&--The radius of the brush tool!@#&local brushsize = 3!@#&--Whether or not \"record\" mode is activated (animation mode only)!@#&local record = false!@#&--The time between each frame when in play mode (animation mode only)!@#&local animtime = 0.3!@#& !@#&--The current \"cursor position\" in text mode!@#&local cursorTexX,cursorTexY = 1,1!@#& !@#&--A list of hexidecimal conversions from numbers to hex digits!@#&local hexnums = { [10] = \"a\", [11] = \"b\", [12] = \"c\", [13] = \"d\", [14] = \"e\" , [15] = \"f\" }!@#&--The NPaintPro logo (divine, isn't it?)!@#&local logo = {!@#&\"fcc              3   339\";!@#&\" fcc          9333    33\";!@#&\"  fcc        933 333  33\";!@#&\"   fcc       933  33  33\";!@#&\"    fcc      933   33 33\";!@#&\"     c88     333   93333\";!@#&\"     888     333    9333\";!@#&\"      333 3  333     939\";!@#&}!@#&--The Layer Up and Layer Forward printing icons!@#&local layerUpIcon = {!@#&        \"0000000\";!@#&        \"0088880\";!@#&        \"0888870\";!@#&        \"07777f0\";!@#&        \"0ffff00\";!@#&        \"0000000\";!@#&}!@#&local layerForwardIcon = {!@#&        \"0000000\";!@#&        \"000fff0\";!@#&        \"00777f0\";!@#&        \"0888700\";!@#&        \"0888000\";!@#&        \"0000000\";!@#&}!@#&--The available menu options in the ctrl menu!@#&local mChoices = {\"Save\",\"Exit\"}!@#&--The available modes from the dropdown menu- tables indicate submenus (include a name!)!@#&local ddModes = { { \"paint\", \"brush\", \"pippette\", \"flood\", \"move\", \"clear\", \"select\", name = \"painting\" }, { \"alpha to left\", \"alpha to right\", \"hide interface\", name = \"display\" }, \"help\", { \"print\", \"save\", \"exit\", name = \"file\" }, name = \"menu\" }!@#&--The available modes from the selection right-click menu!@#&local srModes = { \"cut\", \"copy\", \"paste\", \"clear\", \"hide\", name = \"selection\" }!@#&--The list of available help topics for each mode 127!@#&local helpTopics = {!@#&        [1] = {!@#&                name = \"Paint Mode\",!@#&                key = nil,!@#&                animonly = false,!@#&                textonly = false,!@#&                message = \"The default mode for NPaintPro, for painting pixels.\"!@#&                ..\" Controls here that are not overridden will apply for all other modes. Leaving a mode by selecting that mode \"!@#&                ..\" again will always send the user back to paint mode.\",!@#&                controls = {!@#&                        { \"Arrow keys\", \"Scroll the canvas\" },!@#&                        { \"Left Click\", \"Paint/select left colour\" },!@#&                        { \"Right Click\", \"Paint/select right colour\" },!@#&                        { \"Z Key\", \"Clear image on screen\" },!@#&                        { \"Tab Key\", \"Hide selection rectangle if visible\" },!@#&                        { \"Q Key\", \"Set alpha mask to left colour\" },!@#&                        { \"W Key\", \"Set alpha mask to right colour\" },!@#&                        { \"Number Keys\", \"Swich between frames 1-9\" },!@#&                        { \"</> keys\", \"Move to the next/last frame\" },!@#&                        { \"R Key\", \"Removes every frame after the current frame\"}!@#&                }!@#&        },!@#&        [2] = {!@#&                name = \"Brush Mode\",!@#&                key = \"b\",!@#&                animonly = false,!@#&                textonly = false,!@#&                message = \"Brush mode allows painting a circular area of variable diameter rather than a single pixel, working in \"..!@#&                \"the exact same way as paint mode in all other regards.\",!@#&                controls = {!@#&                        { \"Left Click\", \"Paints a brush blob with the left colour\" },!@#&                        { \"Right Click\", \"Paints a brush blob with the right colour\" },!@#&                        { \"Number Keys\", \"Changes the radius of the brush blob from 2-9\" }!@#&                }!@#&        },!@#&        [3] = {!@#&                name = \"Pippette Mode\",!@#&                key = \"p\",!@#&                animonly = false,!@#&                textonly = false,!@#&                message = \"Pippette mode allows the user to click the canvas and set the colour clicked to the left or right \"..!@#&                \"selected colour, for later painting.\",!@#&                controls = {!@#&                        { \"Left Click\", \"Sets clicked colour to the left selected colour\" },!@#&                        { \"Right Click\", \"Sets clicked colour to the right selected colour\" }!@#&                }!@#&        },!@#&        [4] = {!@#&                name = \"Move Mode\",!@#&                key = \"m\",!@#&                animonly = false,!@#&                textonly = false,!@#&                message = \"Mode mode allows the moving of the entire image on the screen. This is especially useful for justifying\"..!@#&                \" the image to the top-left for animations or game assets.\",!@#&                controls = {!@#&                        { \"Left/Right Click\", \"Moves top-left corner of image to selected square\" },!@#&                        { \"Arrow keys\", \"Moves image one pixel in any direction\" }!@#&                }!@#&        },!@#&        [5] = {!@#&                name = \"Flood Mode\",!@#&                key = \"f\",!@#&                animonly = false,!@#&                textonly = false,!@#&                message = \"Flood mode allows the changing of an area of a given colour to that of the selected colour. \"..!@#&                \"The tool uses a flood4 algorithm and will not fill diagonally. Transparency cannot be flood filled.\",!@#&                controls = {!@#&                        { \"Left Click\", \"Flood fills selected area to left colour\" },!@#&                        { \"Right Click\", \"Flood fills selected area to right colour\" }!@#&                }!@#&        },!@#&        [6] = {!@#&                name = \"Select Mode\",!@#&                key = \"s\",!@#&                animonly = false,!@#&                textonly = false,!@#&                message = \"Select mode allows the creation and use of the selection rectangle, to highlight specific areas on \"..!@#&                \"the screen and perform operations on the selected area of the image. The selection rectangle can contain an \"..!@#&                \"image on the clipboard- if it does, the image will flash inside the rectangle, and the rectangle edges will \"..!@#&                \"be light grey instead of dark grey.\",!@#&                controls = {!@#&                        { \"C Key\", \"Copy: Moves selection into the clipboard\" },!@#&                        { \"X Key\", \"Cut: Clears canvas under the rectangle, and moves it into the clipboard\" },!@#&                        { \"V Key\", \"Paste: Copys clipboard to the canvas\" },!@#&                        { \"Z Key\", \"Clears clipboard\" },!@#&                        { \"Left Click\", \"Moves top-left corner of rectangle to selected pixel\" },!@#&                        { \"Right Click\", \"Opens selection menu\" },!@#&                        { \"Arrow Keys\", \"Moves rectangle one pixel in any direction\" }!@#&                }!@#&        },!@#&        [7] = {!@#&                name = \"Corner Select Mode\",!@#&                key = nil,!@#&                animonly = false,!@#&                textonly = false,!@#&                message = \"If a selection rectangle isn't visible, this mode is selected automatically. It allows the \"..!@#&                \"defining of the corners of the rectangle- one the top-left and bottom-right corners have been defined, \"..!@#&                \"NPaintPro switches to selection mode. Note rectangle must be at least 2 pixels wide and high.\",!@#&                controls = {!@#&                        { \"Left/Right Click\", \"Defines a corner of the selection rectangle\" }!@#&                }!@#&        },!@#&        [8] = {!@#&                name = \"Play Mode\",!@#&                key = \"space\",!@#&                animonly = true,!@#&                textonly = false,!@#&                message = \"Play mode will loop through each frame in your animation at a constant rate. Editing tools are \"..!@#&                \"locked in this mode, and the coordinate display will turn green to indicate it is on.\",!@#&                controls = {!@#&                        { \"</> Keys\", \"Increases/Decreases speed of the animation\" },!@#&                        { \"Space Bar\", \"Returns to paint mode\" }!@#&                }!@#&        },!@#&        [9] = {!@#&                name = \"Record Mode\",!@#&                key = \"\\\\\",!@#&                animonly = true,!@#&                textonly = false,!@#&                message = \"Record mode is not a true mode, but influences how other modes work. Changes made that modify the \"..!@#&                \"canvas in record mode will affect ALL frames in the animation. The coordinates will turn red to indicate that \"..!@#&                \"record mode is on.\",!@#&                controls = {!@#&                        { \"\", \"Affects:\" },!@#&                        { \"- Paint Mode\", \"\" },!@#&                        { \"- Brush Mode\", \"\" },!@#&                        { \"- Cut and Paste in Select Mode\", \"\"},!@#&                        { \"- Move Mode\", \"\"}!@#&                }!@#&        },!@#&		[10] = {!@#&				name = \"Hide Interface\",!@#&				key = \"~\",!@#&				animonly = false,!@#&				textonly = false,!@#&				message = \"Hides the sidebar and colour picker so only the image is visible.\"..!@#&				\" The program can be started with the interface hidden using the -d command line option.\"..!@#&				\" When hidden, if a file is animated it will automatically go to play mode.\\n\"..!@#&				\"Note that all other input is locked until the display is revealed again in this\"..!@#&				\" mode.\",!@#&				controls = {!@#&                    { \"</> Keys\", \"Increases/Decreases speed of the animation\" },!@#&					{ \"~ Key\", \"Shows interface\"}!@#&				}!@#&		},!@#&        [11] = {!@#&                name = \"Help Mode\",!@#&                key = \"h\",!@#&                animonly = false,!@#&                textonly = false,!@#&                message = \"Displays this help screen. Clicking on options will display help on that topic. Clicking out of the screen\"..!@#&                \" will leave this mode.\",!@#&                controls = {!@#&                        { \"Left/Right Click\", \"Displays a topic/Leaves the mode\" }!@#&                }!@#&        },!@#&        [12] = {!@#&                name = \"File Mode\",!@#&                key = nil,!@#&                animonly = false,!@#&                textonly = false,!@#&                message = \"Clicking on the mode display at the bottom of the screen will open the options menu. Here you can\"..!@#&                \" activate all of the modes in the program with a simple mouse click. Pressing left control will open up the\"..!@#&                \" file menu automatically.\",!@#&                controls = {!@#&                        { \"leftCtrl\", \"Opens the file menu\" },!@#&                        { \"leftAlt\", \"Opens the paint menu\" }!@#&                }!@#&        },!@#&        [13] = {!@#&                name = \"Text Mode\",!@#&                key = \"t\",!@#&                animonly = false,!@#&                textonly = true,!@#&                message = \"In this mode, the user is able to type letters onto the document for display. The left colour \"..!@#&                \"pallette value determines what colour the text will be, and the right determines what colour the background \"..!@#&                \"will be (set either to nil to keep the same colours as already there).\",!@#&                controls = {!@#&                        { \"Backspace\", \"Deletes the character on the previous line\" },!@#&                        { \"Arrow Keys\", \"Moves the cursor in any direction\" },!@#&                        { \"Left Click\", \"Moves the cursor to beneath the mouse cursor\" }!@#&                }!@#&        },!@#&        [14] = {!@#&                name = \"Textpaint Mode\",!@#&                key = \"y\",!@#&                animonly = false,!@#&                textonly = true,!@#&                message = \"Allows the user to paint any text on screen to the desired colour with the mouse. If affects the text colour\"..!@#&                \" values rather than the background values, but operates identically to paint mode in all other regards.\",!@#&                controls = {!@#&                        { \"Left Click\", \"Paints the text with the left colour\" },!@#&                        { \"Right Click\", \"Paints the text with the right colour\" }!@#&                }!@#&        },!@#&        [15] = {!@#&                name = \"About NPaintPro\",!@#&                keys = nil,!@#&                animonly = false,!@#&                textonly = false,!@#&                message = \"NPaintPro: The feature-bloated paint program for ComputerCraft by Nitrogen Fingers.\",!@#&                controls = {!@#&                        { \"Testers:\", \" \"},!@#&                        { \" \", \"Faubiguy\"},!@#&                        { \" \", \"TheOriginalBIT\"}!@#&                }!@#&        }!@#&}!@#&--The \"bounds\" of the image- the first/last point on both axes where a pixel appears!@#&local toplim,botlim,leflim,riglim = nil,nil,nil,nil!@#&--The selected path!@#&local sPath = nil!@#&!@#&!@#&--Screen Size Parameters- decided dynamically further down the program!@#&--Whether or not the help screen is available!@#&local helpAvailable = true!@#&--Whether or not the main menu is available!@#&local mainAvailable = true!@#&--Whether or not selection box dropdowns are available!@#&local boxdropAvailable = true!@#&--Whether or not a manual file descriptor option is available (part of the title)!@#&local filemakerAvailable = true!@#& !@#&--[[  !@#&                        Section:  Helpers              !@#&]]--!@#& !@#&--[[Converts a colour parameter into a single-digit hex coordinate for the colour!@#&    Params: colour:int = The colour to be converted!@#&        Returns:string A string conversion of the colour!@#&]]--!@#&local function getHexOf(colour)!@#&        if not colour or not tonumber(colour) then!@#&                return \" \"!@#&        end!@#&        local value = math.log(colour)/math.log(2)!@#&        if value > 9 then!@#&                value = hexnums[value]!@#&        end!@#&        return value!@#&end!@#& !@#&--[[Converts a hex digit into a colour value!@#&        Params: hex:?string = the hex digit to be converted!@#&        Returns:string A colour value corresponding to the hex, or nil if the character is invalid!@#&]]--!@#&local function getColourOf(hex)!@#&        local value = tonumber(hex, 16)!@#&        if not value then return nil end!@#&        value = math.pow(2,value)!@#&        return value!@#&end!@#& !@#&--[[Finds the largest width and height of the text in a given menu. Should conform to the format!@#&	of all standard menus (number indexed values and a 'name' field).!@#&	This is done recursively. It's just easier that way.!@#&	Params: menu:table = the table being tested for the max width and height!@#&	Returns:number,number = the max width and height of the text or names of any menu or submenu.!@#&]]--!@#&local function findMaxWH(menu)!@#&	local wmax,hmax = #menu.name, #menu!@#&	for _,entry in pairs(menu) do!@#&		if type(entry) == \"table\" then!@#&			local nw,nh = findMaxWH(entry)!@#&			wmax = math.max(wmax,nw)!@#&			hmax = math.max(hmax,nh)!@#&		else!@#&			wmax = math.max(wmax,#entry)!@#&		end!@#&	end!@#&	return wmax,hmax!@#&end!@#& !@#&--[[Determines what services are available depending on the size of the screen. Certain features!@#&	may be disabled with screen real estate does not allow for it.!@#&	Params: none!@#&	Returns:nil!@#&]]--!@#&local function determineAvailableServices()!@#&	--Help files were designed to fit a 'standard' CC screen, of 51 x 19. The height of the screen!@#&	--needs to match the number of available options plus white space, but for consistency with!@#&	--the files themselves, a natural size of 51 is required for the screen width as well.!@#&	if w < 51 or h < #helpTopics+3 then helpAvailable = false end!@#&	if not helpAvailable then table.remove(ddModes,3) end!@#&	--These hard-coded values mirror the drawLogo values, with extra consideration for the !@#&	--additional menu options!@#&	if h < 14 or w < 24 then filemakerAvailable = false end!@#&	!@#&	--Menus can't cover the picker and need 2 spaces for branches. 4 whitespace on X total.!@#&	--Menus need a title and can't eclipse the footer. 2 whitespace on Y total.!@#&	local wmin,hmin = findMaxWH(ddModes)!@#&	if w < wmin+4 or h < hmin+2 then mainAvailable = false end!@#&	wmin,hmin = findMaxWH(srModes)!@#&	if w < wmin+4 or h < hmin+2 then boxdropAvailable = false end!@#&end!@#& !@#&--[[Finds the biggest and smallest bounds of the image- the outside points beyond which pixels do not appear!@#&        These values are assigned to the \"lim\" parameters for access by other methods!@#&        Params: forAllFrames:bool = True if all frames should be used to find bounds, otherwise false or nil!@#&        Returns:nil!@#&]]--!@#&local function updateImageLims(forAllFrames)!@#&        local f,l = sFrame,sFrame!@#&        if forAllFrames == true then f,l = 1,framecount end!@#&       !@#&        toplim,botlim,leflim,riglim = nil,nil,nil,nil!@#&        for locf = f,l do!@#&                for y,_ in pairs(frames[locf]) do!@#&                        if type(y) == \"number\" then!@#&                                for x,_ in pairs(frames[locf][y]) do!@#&                                        if frames[locf][y][x] ~= nil then!@#&                                                if leflim == nil or x < leflim then leflim = x end!@#&                                                if toplim == nil or y < toplim then toplim = y end!@#&                                                if riglim == nil or x > riglim then riglim = x end!@#&                                                if botlim == nil or y > botlim then botlim = y end!@#&                                        end!@#&                                end!@#&                        end!@#&                end!@#&        end!@#&       !@#&        --There is just... no easier way to do this. It's horrible, but necessary!@#&        if textEnabled then!@#&                for locf = f,l do!@#&                        for y,_ in pairs(frames[locf].text) do!@#&                                for x,_ in pairs(frames[locf].text[y]) do!@#&                                        if frames[locf].text[y][x] ~= nil then!@#&                                                if leflim == nil or x < leflim then leflim = x end!@#&                                                if toplim == nil or y < toplim then toplim = y end!@#&                                                if riglim == nil or x > riglim then riglim = x end!@#&                                                if botlim == nil or y > botlim then botlim = y end!@#&                                        end!@#&                                end!@#&                        end!@#&                        for y,_ in pairs(frames[locf].textcol) do!@#&                                for x,_ in pairs(frames[locf].textcol[y]) do!@#&                                        if frames[locf].textcol[y][x] ~= nil then!@#&                                                if leflim == nil or x < leflim then leflim = x end!@#&                                                if toplim == nil or y < toplim then toplim = y end!@#&                                                if riglim == nil or x > riglim then riglim = x end!@#&                                                if botlim == nil or y > botlim then botlim = y end!@#&                                        end!@#&                                end!@#&                        end!@#&                end!@#&        end!@#&end!@#& !@#&--[[Determines how much of each material is required for a print. Done each time printing is called.!@#&        Params: none!@#&        Returns:table A complete list of how much of each material is required.!@#&]]--!@#&function calculateMaterials()!@#&        updateImageLims(animated)!@#&        requiredMaterials = {}!@#&        for i=1,16 do!@#&                requiredMaterials[i] = 0!@#&        end!@#&       !@#&        if not toplim then return end!@#&       !@#&        for i=1,#frames do!@#&                for y = toplim, botlim do!@#&                        for x = leflim, riglim do!@#&                                if type(frames[i][y][x]) == \"number\" then!@#&                                        requiredMaterials[math.log10(frames[i][y][x])/math.log10(2) + 1] =!@#&                                                requiredMaterials[math.log10(frames[i][y][x])/math.log10(2) + 1] + 1!@#&                                end    !@#&                        end!@#&                end!@#&        end!@#&end!@#& !@#& !@#&--[[Updates the rectangle blink timer. Should be called anywhere events are captured, along with a timer capture.!@#&        Params: nil!@#&        Returns:nil!@#&]]--!@#&local function updateTimer(id)!@#&        if id == recttimer then!@#&                recttimer = os.startTimer(0.5)!@#&                rectblink = (rectblink % 2) + 1!@#&        end!@#&end!@#& !@#&--[[Constructs a message based on the state currently selected!@#&        Params: nil!@#&        Returns:string A message regarding the state of the application!@#&]]--!@#&local function getStateMessage()!@#&        local msg = \" \"..string.upper(string.sub(state, 1, 1))..string.sub(state, 2, #state)..\" mode\"!@#&        if state == \"brush\" then msg = msg..\", size=\"..brushsize end!@#&        return msg!@#&end!@#& !@#&--[[Calls the rednet_message event, but also looks for timer events to keep then!@#&        system timer ticking.!@#&        Params: timeout:number how long before the event times out!@#&        Returns:number the id of the sender!@#&                   :number the message send!@#&]]--!@#&local function rsTimeReceive(timeout)!@#&        local timerID!@#&        if timeout then timerID = os.startTimer(timeout) end!@#&       !@#&        local id,key,msg = nil,nil!@#&        while true do!@#&                id,key,msg = os.pullEvent()!@#&               !@#&                if id == \"timer\" then!@#&                        if key == timerID then return!@#&                        else updateTimer(key) end!@#&                end!@#&                if id == \"rednet_message\" then!@#&                        return key,msg!@#&                end!@#&        end!@#&end!@#& !@#&--[[Draws a picture, in paint table format on the screen!@#&        Params: image:table = the image to display!@#&                        xinit:number = the x position of the top-left corner of the image!@#&                        yinit:number = the y position of the top-left corner of the image!@#&                        alpha:number = the color to display for the alpha channel. Default is white.!@#&        Returns:nil!@#&]]--!@#&local function drawPictureTable(image, xinit, yinit, alpha)!@#&        if not alpha then alpha = 1 end!@#&        for y=1,#image do!@#&                for x=1,#image[y] do!@#&                        term.setCursorPos(xinit + x-1, yinit + y-1)!@#&                        local col = getColourOf(string.sub(image[y], x, x))!@#&                        if not col then col = alpha end!@#&                        term.setBackgroundColour(col)!@#&                        term.write(\" \")!@#&                end!@#&        end!@#&end!@#& !@#&--[[  !@#&                        Section: Loading  !@#&]]--!@#& !@#&--[[Loads a non-animted paint file into the program!@#&        Params: path:string = The path in which the file is located!@#&        Returns:nil!@#&]]--!@#&local function loadNFP(path)!@#&        sFrame = 1!@#&        frames[sFrame] = { }!@#&        if fs.exists(path) then!@#&                local file = io.open(path, \"r\" )!@#&                local sLine = file:read()!@#&                local num = 1!@#&                while sLine do!@#&                        table.insert(frames[sFrame], num, {})!@#&                        for i=1,#sLine do!@#&                                frames[sFrame][num][i] = getColourOf(string.sub(sLine,i,i))!@#&                        end!@#&                        num = num+1!@#&                        sLine = file:read()!@#&                end!@#&                file:close()!@#&        end!@#&end!@#& !@#&--[[Loads a text-paint file into the program!@#&        Params: path:string = The path in which the file is located!@#&        Returns:nil!@#&]]--!@#&local function loadNFT(path)!@#&        sFrame = 1!@#&        frames[sFrame] = { }!@#&        frames[sFrame].text = { }!@#&        frames[sFrame].textcol = { }!@#&       !@#&        if fs.exists(path) then!@#&                local file = io.open(path, \"r\")!@#&                local sLine = file:read()!@#&                local num = 1!@#&                while sLine do!@#&                        table.insert(frames[sFrame], num, {})!@#&                        table.insert(frames[sFrame].text, num, {})!@#&                        table.insert(frames[sFrame].textcol, num, {})!@#&                       !@#&                        --As we're no longer 1-1, we keep track of what index to write to!@#&                        local writeIndex = 1!@#&                        --Tells us if we've hit a 30 or 31 (BG and FG respectively)- next char specifies the curr colour!@#&                        local bgNext, fgNext = false, false!@#&                        --The current background and foreground colours!@#&                        local currBG, currFG = nil,nil!@#&                        term.setCursorPos(1,1)!@#&                        for i=1,#sLine do!@#&                                local nextChar = string.sub(sLine, i, i)!@#&                                if nextChar:byte() == 30 then!@#&                                        bgNext = true!@#&                                elseif nextChar:byte() == 31 then!@#&                                        fgNext = true!@#&                                elseif bgNext then!@#&                                        currBG = getColourOf(nextChar)!@#&                                        bgNext = false!@#&                                elseif fgNext then!@#&                                        currFG = getColourOf(nextChar)!@#&                                        fgNext = false!@#&                                else!@#&                                        if nextChar ~= \" \" and currFG == nil then!@#&                                                currFG = colours.white!@#&                                        end!@#&                                        frames[sFrame][num][writeIndex] = currBG!@#&                                        frames[sFrame].textcol[num][writeIndex] = currFG!@#&                                        frames[sFrame].text[num][writeIndex] = nextChar!@#&                                        writeIndex = writeIndex + 1!@#&                                end!@#&                        end!@#&                        num = num+1!@#&                        sLine = file:read()!@#&                end!@#&                file:close()!@#&        end!@#&end!@#& !@#&--[[Loads an animated paint file into the program!@#&        Params: path:string = The path in which the file is located!@#&        Returns:nil!@#&]]--!@#&local function loadNFA(path)!@#&        frames[sFrame] = { }!@#&        if fs.exists(path) then!@#&                local file = io.open(path, \"r\" )!@#&                local sLine = file:read()!@#&                local num = 1!@#&                while sLine do!@#&                        table.insert(frames[sFrame], num, {})!@#&                        if sLine == \"~\" then!@#&                                sFrame = sFrame + 1!@#&                                frames[sFrame] = { }!@#&                                num = 1!@#&                        else!@#&                                for i=1,#sLine do!@#&                                        frames[sFrame][num][i] = getColourOf(string.sub(sLine,i,i))!@#&                                end!@#&                                num = num+1!@#&                        end!@#&                        sLine = file:read()!@#&                end!@#&                file:close()!@#&        end!@#&        framecount = sFrame!@#&        sFrame = 1!@#&end!@#& !@#&--[[Saves a non-animated paint file to the specified path!@#&        Params: path:string = The path to save the file to!@#&        Returns:nil!@#&]]--!@#&local function saveNFP(path)!@#&        local sDir = string.sub(sPath, 1, #sPath - #fs.getName(sPath))!@#&        if not fs.exists(sDir) then!@#&                fs.makeDir(sDir)!@#&        end!@#& !@#&        local file = io.open(path, \"w\")!@#&        updateImageLims(false)!@#&        if not toplim then!@#&                file:close()!@#&                return!@#&        end!@#&        for y=1,botlim do!@#&                local line = \"\"!@#&                if frames[sFrame][y] then!@#&                        for x=1,riglim do!@#&                                line = line..getHexOf(frames[sFrame][y][x])!@#&                        end!@#&                end!@#&                file:write(line..\"\\n\")!@#&        end!@#&        file:close()!@#&end!@#& !@#&--[[Saves a text-paint file to the specified path!@#&        Params: path:string = The path to save the file to!@#&        Returns:nil!@#&]]--!@#&local function saveNFT(path)!@#&        local sDir = string.sub(sPath, 1, #sPath - #fs.getName(sPath))!@#&        if not fs.exists(sDir) then!@#&                fs.makeDir(sDir)!@#&        end!@#&       !@#&        local file = io.open(path, \"w\")!@#&        updateImageLims(false)!@#&        if not toplim then!@#&                file:close()!@#&                return!@#&        end!@#&        for y=1,botlim do!@#&                local line = \"\"!@#&                local currBG, currFG = nil,nil!@#&                for x=1,riglim do!@#&                        if frames[sFrame][y] and frames[sFrame][y][x] ~= currBG then!@#&                                line = line..string.char(30)..getHexOf(frames[sFrame][y][x])!@#&                                currBG = frames[sFrame][y][x]!@#&                        end!@#&                        if frames[sFrame].textcol[y] and frames[sFrame].textcol[y][x] ~= currFG then!@#&                                line = line..string.char(31)..getHexOf(frames[sFrame].textcol[y][x])!@#&                                currFG = frames[sFrame].textcol[y][x]!@#&                        end!@#&                        if frames[sFrame].text[y] then!@#&                                local char = frames[sFrame].text[y][x]!@#&                                if not char then char = \" \" end!@#&                                line = line..char!@#&                        end!@#&                end!@#&                file:write(line..\"\\n\")!@#&        end!@#&        file:close()!@#&end!@#& !@#&--[[Saves a animated paint file to the specified path!@#&        Params: path:string = The path to save the file to!@#&        Returns:nil!@#&]]--!@#&local function saveNFA(path)!@#&        local sDir = string.sub(sPath, 1, #sPath - #fs.getName(sPath))!@#&        if not fs.exists(sDir) then!@#&                fs.makeDir(sDir)!@#&        end!@#&       !@#&        local file = io.open(path, \"w\")!@#&        updateImageLims(true)!@#&        if not toplim then!@#&                file:close()!@#&                return!@#&        end!@#&        for i=1,#frames do!@#&                for y=1,botlim do!@#&                        local line = \"\"!@#&                        if frames[i][y] then!@#&                                for x=1,riglim do!@#&                                        line = line..getHexOf(frames[i][y][x])!@#&                                end!@#&                        end!@#&                        file:write(line..\"\\n\")!@#&                end!@#&                if i < #frames then file:write(\"~\\n\") end!@#&        end!@#&        file:close()!@#&end!@#&!@#&--[[Runs a special pre-program dialogue to determine the filename and filepath. Done if!@#&	there's room, and a file name hasn't been specified!@#&	Params: none!@#&	Returns:bool= true if file is created; false otherwise!@#&]]--!@#&local function runFileMaker()!@#&	local newFName = \"\"!@#&	local fileType = 1!@#&	if animated then fileType = 2!@#&	elseif textEnabled then fileType = 3 end!@#&	!@#&	local tlx,tly = math.floor(w/2 - #logo[1]/2), math.floor(h/2 + #logo/2 + 1)!@#&!@#&	--This is done on top of the logo, so it backpedals a bit.!@#&	term.setCursorPos(tlx, tly)!@#&	term.clearLine()!@#&	term.write(\"Name: \")!@#&	term.setCursorPos(tlx, tly + 1)!@#&	term.clearLine()!@#&	term.write(\"Filetype:   Sprite\")!@#&	term.setCursorPos(tlx + 12, tly + 2)!@#&	term.write(\"Animation\")!@#&	term.setCursorPos(tlx + 12, tly + 3)!@#&	term.write(\"Text\")!@#&	!@#&	while true do!@#&		term.setCursorPos(tlx + 6, tly)!@#&		term.setBackgroundColour(colours.lightGrey)!@#&		term.setTextColour(colours.grey)!@#&		term.write(newFName..string.rep(\" \", 15-#newFName))!@#&		term.setBackgroundColour(colours.white)!@#&		term.setTextColour(colours.black)!@#&		local extension = \".nfp\"!@#&		if fileType == 2 then extension = \".nfa\"!@#&		elseif fileType == 3 then extension = \".nft\" end!@#&		term.write(extension)!@#&		!@#&		term.setBackgroundColour(colours.lightGrey)!@#&		term.setTextColour(colours.grey)!@#&		for i=1,3 do!@#&			term.setCursorPos(tlx + 24, tly + i)!@#&			if i==fileType then term.write(\"X\")!@#&			else term.write(\" \") end!@#&		end!@#&		!@#&		local fPath = shell.resolve(newFName..extension)!@#&		term.setCursorPos(tlx, tly + 3)!@#&		local fileValid = true!@#&		if (fs.exists(fPath) and fs.isDir(fPath)) or newFName == \"\" then!@#&			term.setBackgroundColour(colours.white)!@#&			term.setTextColour(colours.red)!@#&			term.write(\"Invalid \")!@#&			fileValid = false!@#&		elseif fs.exists(fPath) then!@#&			term.setBackgroundColour(colours.grey)!@#&			term.setTextColour(colours.lightGrey)!@#&			term.write(\" Edit  \")!@#&		else!@#&			term.setBackgroundColour(colours.grey)!@#&			term.setTextColour(colours.lightGrey)!@#&			term.write(\" Create \")!@#&		end!@#&		!@#&		term.setTextColour(colours.grey)!@#&		term.setCursorPos(tlx + 6 + #newFName, tly)!@#&		term.setCursorBlink(true)!@#&		!@#&		local id,p1,p2,p3 = os.pullEvent()!@#&		if id == \"key\" then!@#&			if p1 == keys.backspace and #newFName > 0 then !@#&				newFName = string.sub(newFName, 1, #newFName-1)!@#&			elseif p1 == keys.enter and fileValid then!@#&				sPath = fPath!@#&				return true!@#&			end!@#&		elseif id == \"char\" and p1 ~= \".\" and p1 ~= \" \" and #newFName < 15 then!@#&			newFName = newFName..p1!@#&		elseif id == \"mouse_click\" then!@#&			--The option boxes. Man, hardcoding is ugly...!@#&			if p2 == tlx + 24 then!@#&				for i=1,3 do !@#&					if p3 == tly+i then fileType = i end !@#&				end!@#&			end!@#&			if p3 == tly + 3 and p2 >= tlx and p2 <= tlx + 8 and fileValid then!@#&				sPath = fPath!@#&				return true!@#&			end!@#&		end!@#&	end!@#&end!@#& !@#&--[[Initializes the program, by loading in the paint file. Called at the start of each program.!@#&        Params: none!@#&        Returns:nil!@#&]]--!@#&local function init()!@#&        if textEnabled then!@#&                loadNFT(sPath)!@#&                table.insert(ddModes, 2, { \"text\", \"textpaint\", name = \"text\"})!@#&        elseif animated then!@#&                loadNFA(sPath)!@#&                table.insert(ddModes, #ddModes, { \"record\", \"play\", name = \"anim\" })!@#&                table.insert(ddModes, #ddModes, { \"go to\", \"remove\", name = \"frames\"})!@#&                table.insert(ddModes[2], #ddModes[2], \"blueprint on\")!@#&                table.insert(ddModes[2], #ddModes[2], \"layers on\")!@#&        else!@#&                loadNFP(sPath)!@#&                table.insert(ddModes[2], #ddModes[2], \"blueprint on\")!@#&        end!@#&		!@#&        for i=0,15 do!@#&                table.insert(column, math.pow(2,i))!@#&        end!@#&end!@#& !@#&--[[  !@#&                        Section: Drawing  !@#&]]--!@#& !@#& !@#&--[[Draws the rather superflous logo. Takes about 1 second, before user is able to move to the!@#&        actual program.!@#&        Params: none!@#&        Returns:bool= true if the file select ran successfully; false otherwise.!@#&]]--!@#&local function drawLogo()!@#&        term.setBackgroundColour(colours.white)!@#&        term.clear()!@#&		if h >= 12 and w >= 24 then!@#&			drawPictureTable(logo, w/2 - #logo[1]/2, h/2 - #logo/2, colours.white)!@#&			term.setBackgroundColour(colours.white)!@#&			term.setTextColour(colours.black)!@#&			local msg = \"NPaintPro\"!@#&			term.setCursorPos(w/2 - #msg/2, h/2 + #logo/2 + 1)!@#&			term.write(msg)!@#&			msg = \"By NitrogenFingers\"!@#&			term.setCursorPos(w/2 - #msg/2, h/2 + #logo/2 + 2)!@#&			term.write(msg)!@#&        elseif w >= 15 then!@#&			local msg = \"NPaintPro\"!@#&			term.setCursorPos(math.ceil(w/2 - #msg/2), h/2)!@#&			term.setTextColour(colours.cyan)!@#&			term.write(msg)!@#&			msg = \"NitrogenFingers\"!@#&			term.setCursorPos(math.ceil(w/2 - #msg/2), h/2 + 1)!@#&			term.setTextColour(colours.black)!@#&			term.write(msg)!@#&		else!@#&			local msg = \"NPP\"!@#&			term.setCursorPos(math.ceil(w/2 - #msg/2), math.floor(h/2))!@#&			term.setTextColour(colours.cyan)!@#&			term.write(msg)!@#&			msg = \"By NF\"!@#&			term.setCursorPos(math.ceil(w/2 - #msg/2), math.ceil(h/2))!@#&			term.setTextColour(colours.black)!@#&			term.write(msg)!@#&		end!@#&        os.pullEvent()!@#&end!@#& !@#&--[[Clears the display to the alpha channel colour, draws the canvas, the image buffer and the selection!@#&        rectanlge if any of these things are present.!@#&        Params: none!@#&        Returns:nil!@#&]]--!@#&local function drawCanvas()!@#&        --We have to readjust the position of the canvas if we're printing!@#&        turtlechar = \"@\"!@#&        if state == \"active print\" then!@#&                if layering == \"up\" then!@#&                        if py >= 1 and py <= #frames then!@#&                                sFrame = py!@#&                        end!@#&                        if pz < sy then sy = pz!@#&                        elseif pz > sy + h - 1 then sy = pz + h - 1 end!@#&                        if px < sx then sx = px!@#&                        elseif px > sx + w - 2 then sx = px + w - 2 end!@#&                else!@#&                        if pz >= 1 and pz <= #frames then!@#&                                sFrame = pz!@#&                        end!@#&                       !@#&                        if py < sy then sy = py!@#&                        elseif py > sy + h - 1 then sy = py + h - 1 end!@#&                        if px < sx then sx = px!@#&                        elseif px > sx + w - 2 then sx = px + w - 2 end!@#&                end!@#&               !@#&                if pfx == 1 then turtlechar = \">\"!@#&                elseif pfx == -1 then turtlechar = \"<\"!@#&                elseif pfz == 1 then turtlechar = \"V\"!@#&                elseif pfz == -1 then turtlechar = \"^\"!@#&                end!@#&        end!@#& !@#&        --Picture next!@#&        local topLayer, botLayer!@#&        if layerDisplay then!@#&                topLayer = sFrame!@#&                botLayer = 1!@#&        else!@#&                topLayer,botLayer = sFrame,sFrame!@#&        end!@#&       !@#&	    --How far the canvas draws. If the interface is visible, it stops short of that.!@#&	    local wlim,hlim = 0,0!@#&		if not interfaceHidden then!@#&			wlim = 2!@#&			hlim = 1!@#&		end!@#&	   !@#&        for currframe = botLayer,topLayer,1 do!@#&                for y=sy+1,sy+h-hlim do!@#&                        if frames[currframe][y] then!@#&                                for x=sx+1,sx+w-wlim do!@#&                                        term.setCursorPos(x-sx,y-sy)!@#&                                        if frames[currframe][y][x] then!@#&                                                term.setBackgroundColour(frames[currframe][y][x])!@#&                                                if textEnabled and frames[currframe].textcol[y][x] and frames[currframe].text[y][x] then!@#&                                                        term.setTextColour(frames[currframe].textcol[y][x])!@#&                                                        term.write(frames[currframe].text[y][x])!@#&                                                else!@#&                                                        term.write(\" \")!@#&                                                end!@#&                                        else!@#&                                                tileExists = false!@#&                                                for i=currframe-1,botLayer,-1 do!@#&                                                        if frames[i][y][x] then!@#&                                                                tileExists = true!@#&                                                                break!@#&                                                        end!@#&                                                end!@#&                                               !@#&                                                if not tileExists then!@#&                                                        if blueprint then!@#&                                                                term.setBackgroundColour(colours.blue)!@#&                                                                term.setTextColour(colours.white)!@#&                                                                if x == sx+1 and y % 4 == 1 then!@#&                                                                        term.write(\"\"..((y/4) % 10))!@#&                                                                elseif y == sy + 1 and x % 4 == 1 then!@#&                                                                        term.write(\"\"..((x/4) % 10))!@#&                                                                elseif x % 2 == 1 and y % 2 == 1 then!@#&                                                                        term.write(\"+\")!@#&                                                                elseif x % 2 == 1 then!@#&                                                                        term.write(\"|\")!@#&                                                                elseif y % 2 == 1 then!@#&                                                                        term.write(\"-\")!@#&                                                                else!@#&                                                                        term.write(\" \")!@#&                                                                end!@#&                                                        else!@#&                                                                term.setBackgroundColour(alphaC)!@#&                                                                if textEnabled and frames[currframe].textcol[y][x] and frames[currframe].text[y][x] then!@#&                                                                        term.setTextColour(frames[currframe].textcol[y][x])!@#&                                                                        term.write(frames[currframe].text[y][x])!@#&                                                                else!@#&                                                                        term.write(\" \")!@#&                                                                end!@#&                                                        end!@#&                                                end!@#&                                        end!@#&                                end!@#&                        else!@#&                                for x=sx+1,sx+w-wlim do!@#&                                        term.setCursorPos(x-sx,y-sy)!@#&                                       !@#&                                        tileExists = false!@#&                                        for i=currframe-1,botLayer,-1 do!@#&                                                if frames[i][y] and frames[i][y][x] then!@#&                                                        tileExists = true!@#&                                                        break!@#&                                                end!@#&                                        end!@#&                                       !@#&                                        if not tileExists then!@#&                                                if blueprint then!@#&                                                        term.setBackgroundColour(colours.blue)!@#&                                                        term.setTextColour(colours.white)!@#&                                                        if x == sx+1 and y % 4 == 1 then!@#&                                                                term.write(\"\"..((y/4) % 10))!@#&                                                        elseif y == sy + 1 and x % 4 == 1 then!@#&                                                                term.write(\"\"..((x/4) % 10))!@#&                                                        elseif x % 2 == 1 and y % 2 == 1 then!@#&                                                                term.write(\"+\")!@#&                                                        elseif x % 2 == 1 then!@#&                                                                term.write(\"|\")!@#&                                                        elseif y % 2 == 1 then!@#&                                                                term.write(\"-\")!@#&                                                        else!@#&                                                                term.write(\" \")!@#&                                                        end!@#&                                                else!@#&                                                        term.setBackgroundColour(alphaC)!@#&                                                        term.write(\" \")!@#&                                                end!@#&                                        end!@#&                                end!@#&                        end!@#&                end!@#&        end!@#&       !@#&        --Then the printer, if he's on!@#&        if state == \"active print\" then!@#&                local bgColour = alphaC!@#&                if layering == \"up\" then!@#&                        term.setCursorPos(px-sx,pz-sy)!@#&                        if frames[sFrame] and frames[sFrame][pz-sy] and frames[sFrame][pz-sy][px-sx] then!@#&                                bgColour = frames[sFrame][pz-sy][px-sx]!@#&                        elseif blueprint then bgColour = colours.blue end!@#&                else!@#&                        term.setCursorPos(px-sx,py-sy)!@#&                        if frames[sFrame] and frames[sFrame][py-sy] and frames[sFrame][py-sy][px-sx] then!@#&                                bgColour = frames[sFrame][py-sy][px-sx]!@#&                        elseif blueprint then bgColour = colours.blue end!@#&                end!@#&               !@#&                term.setBackgroundColour(bgColour)!@#&                if bgColour == colours.black then term.setTextColour(colours.white)!@#&                else term.setTextColour(colours.black) end!@#&               !@#&                term.write(turtlechar)!@#&        end!@#&       !@#&        --Then the buffer!@#&        if selectrect then!@#&                if buffer and rectblink == 1 then!@#&                for y=selectrect.y1, math.min(selectrect.y2, selectrect.y1 + buffer.height-1) do!@#&                        for x=selectrect.x1, math.min(selectrect.x2, selectrect.x1 + buffer.width-1) do!@#&                                if buffer.contents[y-selectrect.y1+1][x-selectrect.x1+1] then!@#&                                        term.setCursorPos(x+sx,y+sy)!@#&                                        term.setBackgroundColour(buffer.contents[y-selectrect.y1+1][x-selectrect.x1+1])!@#&                                        term.write(\" \")!@#&                                end!@#&                        end!@#&                end!@#&                end!@#&       !@#&                --This draws the \"selection\" box!@#&                local add = nil!@#&                if buffer then!@#&                        term.setBackgroundColour(colours.lightGrey)!@#&                else!@#&                        term.setBackgroundColour(colours.grey)!@#&                end!@#&                for i=selectrect.x1, selectrect.x2 do!@#&                        add = (i + selectrect.y1 + rectblink) % 2 == 0!@#&                        term.setCursorPos(i-sx,selectrect.y1-sy)!@#&                        if add then term.write(\" \") end!@#&                        add = (i + selectrect.y2 + rectblink) % 2 == 0!@#&                        term.setCursorPos(i-sx,selectrect.y2-sy)!@#&                        if add then term.write(\" \") end!@#&                end!@#&                for i=selectrect.y1 + 1, selectrect.y2 - 1 do!@#&                        add = (i + selectrect.x1 + rectblink) % 2 == 0!@#&                        term.setCursorPos(selectrect.x1-sx,i-sy)!@#&                        if add then term.write(\" \") end!@#&                        add = (i + selectrect.x2 + rectblink) % 2 == 0!@#&                        term.setCursorPos(selectrect.x2-sx,i-sy)!@#&                        if add then term.write(\" \") end!@#&                end!@#&        end!@#&end!@#& !@#&--[[Draws the colour picker on the right side of the screen, the colour pallette and the footer with any!@#&        messages currently being displayed!@#&        Params: none!@#&        Returns:nil!@#&]]--!@#&local function drawInterface()!@#&        --Picker!@#&		local coffset,ioffset = 0,0!@#&		local maxcsize = h-2!@#&		if h < #column + 2 then!@#&			maxcsize = h-4!@#&			coffset = columnoffset!@#&			ioffset = 1!@#&			term.setBackgroundColour(colours.lightGrey)!@#&			term.setTextColour(colours.grey)!@#&			term.setCursorPos(w-1,1)!@#&			term.write(\"^^\")!@#&			term.setCursorPos(w-1,h-2)!@#&			term.write(\"VV\")!@#&		end!@#&        for i=1,math.min(#column+1,maxcsize) do!@#&			term.setCursorPos(w-1, i + ioffset)!@#&			local ci = i+coffset!@#&			if ci == #column+1 then!@#&				term.setBackgroundColour(colours.black)!@#&				term.setTextColour(colours.red)!@#&				term.write(\"XX\")!@#&			elseif state == \"print\" then!@#&				term.setBackgroundColour(column[ci])!@#&				if column[ci] == colours.black then!@#&					term.setTextColour(colours.white)!@#&				else term.setTextColour(colours.black) end!@#&				!@#&				if requirementsDisplayed then!@#&						if requiredMaterials[i] < 10 then term.write(\" \") end!@#&						term.setCursorPos(w-#tostring(requiredMaterials[i])+1, i)!@#&						term.write(requiredMaterials[i])!@#&				else!@#&						if i+coffset < 10 then term.write(\" \") end!@#&						term.write(i+coffset)!@#&				end!@#&			else!@#&				term.setBackgroundColour(column[ci])!@#&				term.write(\"  \")!@#&			end!@#&        end!@#&		--Filling the whitespace with... 'greyspace' *shudder*!@#&		if h > #column+3 then!@#&			term.setTextColour(colours.grey)!@#&			term.setBackgroundColour(colours.lightGrey)!@#&			for y=#column+2,h-2 do!@#&				term.setCursorPos(w-1,y)!@#&				term.write(\"| \")!@#&			end!@#&		end!@#&        --Pallette!@#&        term.setCursorPos(w-1,h-1)!@#&        if not lSel then!@#&                term.setBackgroundColour(colours.black)!@#&                term.setTextColour(colours.red)!@#&                term.write(\"X\")!@#&        else!@#&                term.setBackgroundColour(lSel)!@#&                term.setTextColour(lSel)!@#&                term.write(\" \")!@#&        end!@#&        if not rSel then!@#&                term.setBackgroundColour(colours.black)!@#&                term.setTextColour(colours.red)!@#&                term.write(\"X\")!@#&        else!@#&                term.setBackgroundColour(rSel)!@#&                term.setTextColour(rSel)!@#&                term.write(\" \")!@#&        end!@#&        --Footer!@#&        if inMenu then return end!@#&       !@#&        term.setCursorPos(1, h)!@#&        term.setBackgroundColour(colours.lightGrey)!@#&        term.setTextColour(colours.grey)!@#&        term.clearLine()!@#&		if mainAvailable then!@#&			if inDropDown then!@#&					term.write(string.rep(\" \", #ddModes.name + 2))!@#&			else!@#&					term.setBackgroundColour(colours.grey)!@#&					term.setTextColour(colours.lightGrey)!@#&					term.write(ddModes.name..\"  \")!@#&			end!@#&		end!@#&        term.setBackgroundColour(colours.lightGrey)!@#&        term.setTextColour(colours.grey)!@#&        term.write(getStateMessage())!@#&       !@#&        local coords=\"X:\"..sx..\" Y:\"..sy!@#&        if animated then coords = coords..\" Frame:\"..sFrame..\"/\"..framecount..\"   \" end!@#&        term.setCursorPos(w-#coords+1,h)!@#&        if state == \"play\" then term.setBackgroundColour(colours.lime)!@#&        elseif record then term.setBackgroundColour(colours.red) end!@#&        term.write(coords)!@#&       !@#&        if animated then!@#&                term.setCursorPos(w-1,h)!@#&                term.setBackgroundColour(colours.grey)!@#&                term.setTextColour(colours.lightGrey)!@#&                term.write(\"<>\")!@#&        end!@#&end!@#& !@#&--[[Runs an interface where users can select topics of help. Will return once the user quits the help screen.!@#&        Params: none!@#&        Returns:nil!@#&]]--!@#&local function drawHelpScreen()!@#&        local selectedHelp = nil!@#&        while true do!@#&                term.setBackgroundColour(colours.lightGrey)!@#&                term.clear()!@#&                if not selectedHelp then!@#&                        term.setCursorPos(4, 1)!@#&                        term.setTextColour(colours.brown)!@#&                        term.write(\"Available modes (click for info):\")!@#&                        for i=1,#helpTopics do!@#&                                term.setCursorPos(2, 2 + i)!@#&                                term.setTextColour(colours.black)!@#&                                term.write(helpTopics[i].name)!@#&                                if helpTopics[i].key then!@#&                                        term.setTextColour(colours.red)!@#&                                        term.write(\" (\"..helpTopics[i].key..\")\")!@#&                                end!@#&                        end!@#&                        term.setCursorPos(4,h)!@#&                        term.setTextColour(colours.black)!@#&                        term.write(\"Press any key to exit\")!@#&                else!@#&                        term.setCursorPos(4,1)!@#&                        term.setTextColour(colours.brown)!@#&                        term.write(helpTopics[selectedHelp].name)!@#&                        if helpTopics[selectedHelp].key then!@#&                                term.setTextColour(colours.red)!@#&                                term.write(\" (\"..helpTopics[selectedHelp].key..\")\")!@#&                        end!@#&                        term.setCursorPos(1,3)!@#&                        term.setTextColour(colours.black)!@#&                        print(helpTopics[selectedHelp].message..\"\\n\")!@#&                        for i=1,#helpTopics[selectedHelp].controls do!@#&                                term.setTextColour(colours.brown)!@#&                                term.write(helpTopics[selectedHelp].controls[i][1]..\" \")!@#&                                term.setTextColour(colours.black)!@#&                                print(helpTopics[selectedHelp].controls[i][2])!@#&                        end!@#&                end!@#&               !@#&                local id,p1,p2,p3 = os.pullEvent()!@#&               !@#&                if id == \"timer\" then updateTimer(p1)!@#&                elseif id == \"key\" then!@#&                        if selectedHelp then selectedHelp = nil!@#&                        else break end!@#&                elseif id == \"mouse_click\" then!@#&                        if not selectedHelp then!@#&                                if p3 >=3 and p3 <= 2+#helpTopics then!@#&                                        selectedHelp = p3-2!@#&                                else break end!@#&                        else!@#&                                selectedHelp = nil!@#&                        end!@#&                end!@#&        end!@#&end!@#& !@#&--[[Draws a message in the footer bar. A helper for DrawInterface, but can be called for custom messages, if the!@#&        inMenu paramter is set to true while this is being done (remember to set it back when done!)!@#&        Params: message:string = The message to be drawn!@#&        Returns:nil!@#&]]--!@#&local function drawMessage(message)!@#&        term.setCursorPos(1,h)!@#&        term.setBackgroundColour(colours.lightGrey)!@#&        term.setTextColour(colours.grey)!@#&        term.clearLine()!@#&        term.write(message)!@#&end!@#& !@#&--[[!@#&                        Section: Generic Interfaces!@#&]]--!@#& !@#& !@#&--[[One of my generic text printing methods, printing a message at a specified position with width and offset.!@#&        No colour materials included.!@#&        Params: msg:string = The message to print off-center!@#&                        height:number = The starting height of the message!@#&                        width:number = The limit as to how many characters long each line may be!@#&                        offset:number = The starting width offset of the message!@#&        Returns:number the number of lines used in printing the message!@#&]]--!@#&local function wprintOffCenter(msg, height, width, offset)!@#&        local inc = 0!@#&        local ops = 1!@#&        while #msg - ops > width do!@#&                local nextspace = 0!@#&                while string.find(msg, \" \", ops + nextspace) and!@#&                                string.find(msg, \" \", ops + nextspace) - ops < width do!@#&                        nextspace = string.find(msg, \" \", nextspace + ops) + 1 - ops!@#&                end!@#&                local ox,oy = term.getCursorPos()!@#&                term.setCursorPos(width/2 - (nextspace)/2 + offset, height + inc)!@#&                inc = inc + 1!@#&                term.write(string.sub(msg, ops, nextspace + ops - 1))!@#&                ops = ops + nextspace!@#&        end!@#&        term.setCursorPos(width/2 - #string.sub(msg, ops)/2 + offset, height + inc)!@#&        term.write(string.sub(msg, ops))!@#&       !@#&        return inc + 1!@#&end!@#& !@#&--[[Draws a message that must be clicked on or a key struck to be cleared. No options, so used for displaying!@#&        generic information.!@#&        Params: ctitle:string = The title of the confirm dialogue!@#&                        msg:string = The message displayed in the dialogue!@#&        Returns:nil!@#&]]--!@#&local function displayConfirmDialogue(ctitle, msg)!@#&        local dialogoffset = 8!@#&        --We actually print twice- once to get the lines, second time to print proper. Easier this way.!@#&        local lines = wprintOffCenter(msg, 5, w - (dialogoffset+2) * 2, dialogoffset + 2)!@#&       !@#&        term.setCursorPos(dialogoffset, 3)!@#&        term.setBackgroundColour(colours.grey)!@#&        term.setTextColour(colours.lightGrey)!@#&        term.write(string.rep(\" \", w - dialogoffset * 2))!@#&        term.setCursorPos(dialogoffset + (w - dialogoffset * 2)/2 - #ctitle/2, 3)!@#&        term.write(ctitle)!@#&        term.setTextColour(colours.grey)!@#&        term.setBackgroundColour(colours.lightGrey)!@#&        term.setCursorPos(dialogoffset, 4)!@#&        term.write(string.rep(\" \", w - dialogoffset * 2))!@#&        for i=5,5+lines do!@#&                term.setCursorPos(dialogoffset, i)!@#&                term.write(\" \"..string.rep(\" \", w - (dialogoffset) * 2 - 2)..\" \")!@#&        end!@#&        wprintOffCenter(msg, 5, w - (dialogoffset+2) * 2, dialogoffset + 2)!@#&       !@#&        --In the event of a message, the player hits anything to continue!@#&        while true do!@#&                local id,key = os.pullEvent()!@#&                if id == \"timer\" then updateTimer(key);!@#&                elseif id == \"key\" or id == \"mouse_click\" or id == \"mouse_drag\" then break end!@#&        end!@#&end!@#& !@#&--[[Produces a nice dropdown menu based on a table of strings. Depending on the position, this will auto-adjust the position!@#&        of the menu drawn, and allows nesting of menus and sub menus. Clicking anywhere outside the menu will cancel and return nothing!@#&        Params: x:int = the x position the menu should be displayed at!@#&                        y:int = the y position the menu should be displayed at!@#&                        options:table = the list of options available to the user, as strings or submenus (tables of strings, with a name parameter)!@#&        Returns:string the selected menu option.!@#&]]--!@#&local function displayDropDown(x, y, options)!@#&        inDropDown = true!@#&        --Figures out the dimensions of our thing!@#&        local longestX = #options.name!@#&        for i=1,#options do!@#&                local currVal = options[i]!@#&                if type(currVal) == \"table\" then currVal = currVal.name end!@#&               !@#&                longestX = math.max(longestX, #currVal)!@#&        end!@#&        local xOffset = math.max(0, longestX - ((w-2) - x) + 1)!@#&        local yOffset = math.max(0, #options - ((h-1) - y))!@#&       !@#&        local clickTimes = 0!@#&        local tid = nil!@#&        local selection = nil!@#&        while clickTimes < 2 do!@#&                drawCanvas()!@#&                drawInterface()!@#&               !@#&                term.setCursorPos(x-xOffset,y-yOffset)!@#&                term.setBackgroundColour(colours.grey)!@#&                term.setTextColour(colours.lightGrey)!@#&                term.write(options.name..string.rep(\" \", longestX-#options.name + 2))!@#&       !@#&                for i=1,#options do!@#&                        term.setCursorPos(x-xOffset, y-yOffset+i)!@#&                        if i==selection and clickTimes % 2 == 0 then!@#&                                term.setBackgroundColour(colours.grey)!@#&                                term.setTextColour(colours.lightGrey)!@#&                        else!@#&                                term.setBackgroundColour(colours.lightGrey)!@#&                                term.setTextColour(colours.grey)!@#&                        end!@#&                        local currVal = options[i]!@#&                        if type(currVal) == \"table\" then!@#&                                term.write(currVal.name..string.rep(\" \", longestX-#currVal.name + 1))!@#&                                term.setBackgroundColour(colours.grey)!@#&                                term.setTextColour(colours.lightGrey)!@#&                                term.write(\">\")!@#&                        else!@#&                                term.write(currVal..string.rep(\" \", longestX-#currVal + 2))!@#&                        end!@#&                end!@#&               !@#&                local id, p1, p2, p3 = os.pullEvent()!@#&                if id == \"timer\" then!@#&                        if p1 == tid then!@#&                                clickTimes = clickTimes + 1!@#&                                if clickTimes > 2 then!@#&                                        break!@#&                                else!@#&                                        tid = os.startTimer(0.1)!@#&                                end!@#&                        else!@#&                                updateTimer(p1)!@#&                                drawCanvas()!@#&                                drawInterface()!@#&                        end!@#&                elseif id == \"mouse_click\" then!@#&                        if p2 >=x-xOffset and p2 <= x-xOffset + longestX + 1 and p3 >= y-yOffset+1 and p3 <= y-yOffset+#options then!@#&                                selection = p3-(y-yOffset)!@#&                                tid = os.startTimer(0.1)!@#&                        else!@#&                                selection = \"\"!@#&                                break!@#&                        end!@#&                end!@#&        end!@#&       !@#&        if type(selection) == \"number\" then!@#&                selection = options[selection]!@#&        end!@#&       !@#&        if type(selection) == \"string\" then!@#&                inDropDown = false!@#&                return selection!@#&        elseif type(selection) == \"table\" then!@#&                return displayDropDown(x, y, selection)!@#&        end!@#&end!@#& !@#&--[[A custom io.read() function with a few differences- it limits the number of characters being printed,!@#&        waits a 1/100th of a second so any keys still in the event library are removed before input is read and!@#&        the timer for the selectionrectangle is continuously updated during the process.!@#&        Params: lim:int = the number of characters input is allowed!@#&        Returns:string the inputted string, trimmed of leading and tailing whitespace!@#&]]--!@#&local function readInput(lim)!@#&        term.setCursorBlink(true)!@#& !@#&        local inputString = \"\"!@#&        if not lim or type(lim) ~= \"number\" or lim < 1 then lim = w - ox end!@#&        local ox,oy = term.getCursorPos()!@#&        --We only get input from the footer, so this is safe. Change if recycling!@#&        term.setBackgroundColour(colours.lightGrey)!@#&        term.setTextColour(colours.grey)!@#&        term.write(string.rep(\" \", lim))!@#&        term.setCursorPos(ox, oy)!@#&        --As events queue immediately, we may get an unwanted key... this will solve that problem!@#&        local inputTimer = os.startTimer(0.01)!@#&        local keysAllowed = false!@#&       !@#&        while true do!@#&                local id,key = os.pullEvent()!@#&               !@#&                if keysAllowed then!@#&                        if id == \"key\" and key == 14 and #inputString > 0 then!@#&                                inputString = string.sub(inputString, 1, #inputString-1)!@#&                                term.setCursorPos(ox + #inputString,oy)!@#&                                term.write(\" \")!@#&                        elseif id == \"key\" and key == 28 and inputString ~= string.rep(\" \", #inputString) then!@#&                                break!@#&                        elseif id == \"key\" and key == keys.leftCtrl then!@#&                                return \"\"!@#&                        elseif id == \"char\" and #inputString < lim then!@#&                                inputString = inputString..key!@#&                        end!@#&                end!@#&               !@#&                if id == \"timer\" then!@#&                        if key == inputTimer then!@#&                                keysAllowed = true!@#&                        else!@#&                                updateTimer(key)!@#&                                drawCanvas()!@#&                                drawInterface()!@#&                                term.setBackgroundColour(colours.lightGrey)!@#&                                term.setTextColour(colours.grey)!@#&                        end!@#&                end!@#&                term.setCursorPos(ox,oy)!@#&                term.write(inputString)!@#&                term.setCursorPos(ox + #inputString, oy)!@#&        end!@#&       !@#&        while string.sub(inputString, 1, 1) == \" \" do!@#&                inputString = string.sub(inputString, 2, #inputString)!@#&        end!@#&        while string.sub(inputString, #inputString, #inputString) == \" \" do!@#&                inputString = string.sub(inputString, 1, #inputString-1)!@#&        end!@#&        term.setCursorBlink(false)!@#&       !@#&        return inputString!@#&end!@#& !@#&--[[  !@#&                        Section: Image tools!@#&]]--!@#& !@#& !@#&--[[Copies all pixels beneath the selection rectangle into the image buffer. Empty buffers are converted to nil.!@#&        Params: removeImage:bool = true if the image is to be erased after copying, false otherwise!@#&        Returns:nil!@#&]]--!@#&local function copyToBuffer(removeImage)!@#&        buffer = { width = selectrect.x2 - selectrect.x1 + 1, height = selectrect.y2 - selectrect.y1 + 1, contents = { } }!@#&       !@#&        local containsSomething = false!@#&        for y=1,buffer.height do!@#&                buffer.contents[y] = { }!@#&                local f,l = sFrame,sFrame!@#&                if record then f,l = 1, framecount end!@#&               !@#&                for fra = f,l do!@#&                        if frames[fra][selectrect.y1 + y - 1] then!@#&                                for x=1,buffer.width do!@#&                                        buffer.contents[y][x] = frames[sFrame][selectrect.y1 + y - 1][selectrect.x1 + x - 1]!@#&                                        if removeImage then frames[fra][selectrect.y1 + y - 1][selectrect.x1 + x - 1] = nil end!@#&                                        if buffer.contents[y][x] then containsSomething = true end!@#&                                end!@#&                        end!@#&                end!@#&        end!@#&        --I don't classify an empty buffer as a real buffer- confusing to the user.!@#&        if not containsSomething then buffer = nil end!@#&end!@#& !@#&--[[Replaces all pixels under the selection rectangle with the image buffer (or what can be seen of it). Record-dependent.!@#&        Params: removeBuffer:bool = true if the buffer is to be emptied after copying, false otherwise!@#&        Returns:nil!@#&]]--!@#&local function copyFromBuffer(removeBuffer)!@#&        if not buffer then return end!@#& !@#&        for y = 1, math.min(buffer.height,selectrect.y2-selectrect.y1+1) do!@#&                local f,l = sFrame, sFrame!@#&                if record then f,l = 1, framecount end!@#&               !@#&                for fra = f,l do!@#&                        if not frames[fra][selectrect.y1+y-1] then frames[fra][selectrect.y1+y-1] = { } end!@#&                        for x = 1, math.min(buffer.width,selectrect.x2-selectrect.x1+1) do!@#&                                frames[fra][selectrect.y1+y-1][selectrect.x1+x-1] = buffer.contents[y][x]!@#&                        end!@#&                end!@#&        end!@#&       !@#&        if removeBuffer then buffer = nil end!@#&end!@#& !@#&--[[Moves the entire image (or entire animation) to the specified coordinates. Record-dependent.!@#&        Params: newx:int = the X coordinate to move the image to!@#&                        newy:int = the Y coordinate to move the image to!@#&        Returns:nil!@#&]]--!@#&local function moveImage(newx,newy)!@#&        if not leflim or not toplim then return end!@#&        if newx <=0 or newy <=0 then return end!@#&        local f,l = sFrame,sFrame!@#&        if record then f,l = 1,framecount end!@#&       !@#&        for i=f,l do!@#&                local newlines = { }!@#&                for y=toplim,botlim do!@#&                        local line = frames[i][y]!@#&                        if line then!@#&                                newlines[y-toplim+newy] = { }!@#&                                for x,char in pairs(line) do!@#&                                        newlines[y-toplim+newy][x-leflim+newx] = char!@#&                                end!@#&                        end!@#&                end!@#&                --Exceptions that allow us to move the text as well!@#&                if textEnabled then!@#&                        newlines.text = { }!@#&                        for y=toplim,botlim do!@#&                                local line = frames[i].text[y]!@#&                                if line then!@#&                                        newlines.text[y-toplim+newy] = { }!@#&                                        for x,char in pairs(line) do!@#&                                                newlines.text[y-toplim+newy][x-leflim+newx] = char!@#&                                        end!@#&                                end!@#&                        end!@#&                       !@#&                        newlines.textcol = { }!@#&                        for y=toplim,botlim do!@#&                                local line = frames[i].textcol[y]!@#&                                if line then!@#&                                        newlines.textcol[y-toplim+newy] = { }!@#&                                        for x,char in pairs(line) do!@#&                                                newlines.textcol[y-toplim+newy][x-leflim+newx] = char!@#&                                        end!@#&                                end!@#&                        end!@#&                end!@#&               !@#&                frames[i] = newlines!@#&        end!@#&end!@#& !@#&--[[Prompts the user to clear the current frame or all frames. Record-dependent.,!@#&        Params: none!@#&        Returns:nil!@#&]]--!@#&local function clearImage()!@#&        inMenu = true!@#&        if not animated then!@#&                drawMessage(\"Clear image? Y/N: \")!@#&        elseif record then!@#&                drawMessage(\"Clear ALL frames? Y/N: \")!@#&        else!@#&                drawMessage(\"Clear current frame? Y/N :\")!@#&        end!@#&        if string.find(string.upper(readInput(1)), \"Y\") then!@#&                local f,l = sFrame,sFrame!@#&                if record then f,l = 1,framecount end!@#&               !@#&                for i=f,l do!@#&                        frames[i] = { }!@#&                end!@#&        end!@#&        inMenu = false!@#&end!@#& !@#&--[[A recursively called method (watch out for big calls!) in which every pixel of a set colour is!@#&        changed to another colour. Does not work on the nil colour, for obvious reasons.!@#&        Params: x:int = The X coordinate of the colour to flood-fill!@#&                        y:int = The Y coordinate of the colour to flood-fill!@#&                        targetColour:colour = the colour that is being flood-filled!@#&                        newColour:colour = the colour with which to replace the target colour!@#&        Returns:nil!@#&]]--!@#&local function floodFill(x, y, targetColour, newColour)!@#&        if not newColour or not targetColour then return end!@#&        local nodeList = { }!@#&       !@#&        table.insert(nodeList, {x = x, y = y})!@#&       !@#&        while #nodeList > 0 do!@#&                local node = nodeList[1]!@#&                if frames[sFrame][node.y] and frames[sFrame][node.y][node.x] == targetColour then!@#&                        frames[sFrame][node.y][node.x] = newColour!@#&                        table.insert(nodeList, { x = node.x + 1, y = node.y})!@#&                        table.insert(nodeList, { x = node.x, y = node.y + 1})!@#&                        if x > 1 then table.insert(nodeList, { x = node.x - 1, y = node.y}) end!@#&                        if y > 1 then table.insert(nodeList, { x = node.x, y = node.y - 1}) end!@#&                end!@#&                table.remove(nodeList, 1)!@#&        end!@#&end!@#& !@#&--[[  !@#&                        Section: Animation Tools  !@#&]]--!@#& !@#&--[[Enters play mode, allowing the animation to play through. Interface is restricted to allow this,!@#&        and method only leaves once the player leaves play mode.!@#&        Params: none!@#&        Returns:nil!@#&]]--!@#&local function playAnimation()!@#&        state = \"play\"!@#&        selectedrect = nil!@#&       !@#&        local animt = os.startTimer(animtime)!@#&        repeat!@#&                drawCanvas()!@#&                drawInterface()!@#&               !@#&                local id,key,_,y = os.pullEvent()!@#&               !@#&                if id==\"timer\" then!@#&                        if key == animt then!@#&                                animt = os.startTimer(animtime)!@#&                                sFrame = (sFrame % framecount) + 1!@#&                        else!@#&                                updateTimer(key)!@#&                        end!@#&                elseif id==\"key\" then!@#&                        if key == keys.comma and animtime > 0.1 then animtime = animtime - 0.05!@#&                        elseif key == keys.period and animtime < 0.5 then animtime = animtime + 0.05!@#&                        elseif key == keys.space then state = \"paint\" end!@#&                elseif id==\"mouse_click\" and y == h then!@#&                        state = \"paint\"!@#&                end!@#&        until state ~= \"play\"!@#&        os.startTimer(0.5)!@#&end!@#& !@#&--[[Changes the selected frame (sFrame) to the chosen frame. If this frame is above the framecount,!@#&        additional frames are created with a copy of the image on the selected frame.!@#&        Params: newframe:int = the new frame to move to!@#&        Returns:nil!@#&]]--!@#&local function changeFrame(newframe)!@#&        inMenu = true!@#&        if not tonumber(newframe) then!@#&                term.setCursorPos(1,h)!@#&                term.setBackgroundColour(colours.lightGrey)!@#&                term.setTextColour(colours.grey)!@#&                term.clearLine()!@#&       !@#&                term.write(\"Go to frame: \")!@#&                newframe = tonumber(readInput(2))!@#&                if not newframe or newframe <= 0 then!@#&                        inMenu = false!@#&                        return!@#&                end!@#&        elseif newframe <= 0 then return end!@#&       !@#&        if newframe > framecount then!@#&                for i=framecount+1,newframe do!@#&                        frames[i] = {}!@#&                        for y,line in pairs(frames[sFrame]) do!@#&                                frames[i][y] = { }!@#&                                for x,v in pairs(line) do!@#&                                        frames[i][y][x] = v!@#&                                end!@#&                        end!@#&                end!@#&                framecount = newframe!@#&        end!@#&        sFrame = newframe!@#&        inMenu = false!@#&end!@#& !@#&--[[Removes every frame leading after the frame passed in!@#&        Params: frame:int the non-inclusive lower bounds of the delete!@#&        Returns:nil!@#&]]--!@#&local function removeFramesAfter(frame)!@#&        inMenu = true!@#&        if frame==framecount then return end!@#&        drawMessage(\"Remove frames \"..(frame+1)..\"/\"..framecount..\"? Y/N :\")!@#&        local answer = string.upper(readInput(1))!@#&       !@#&        if string.find(answer, string.upper(\"Y\")) ~= 1 then!@#&                inMenu = false!@#&                return!@#&        end!@#&       !@#&        for i=frame+1, framecount do!@#&                frames[i] = nil!@#&        end!@#&        framecount = frame!@#&        inMenu = false!@#&end!@#& !@#&--[[!@#&                        Section: Printing Tools!@#&]]--!@#& !@#&--[[Constructs a new facing to the left of the current facing!@#&        Params: curx:number = The facing on the X axis!@#&                        curz:number = The facing on the Z axis!@#&                        hand:string = The hand of the axis (\"right\" or \"left\")!@#&        Returns:number,number = the new facing on the X and Z axis after a left turn!@#&]]--!@#&local function getLeft(curx, curz)!@#&        local hand = \"left\"!@#&        if layering == \"up\" then hand = \"right\" end!@#&       !@#&        if hand == \"right\" then!@#&                if curx == 1 then return 0,-1 end!@#&                if curx == -1 then return 0,1 end!@#&                if curz == 1 then return 1,0 end!@#&                if curz == -1 then return -1,0 end!@#&        else!@#&                if curx == 1 then return 0,1 end!@#&                if curx == -1 then return 0,-1 end!@#&                if curz == 1 then return -1,0 end!@#&                if curz == -1 then return 1,0 end!@#&        end!@#&end!@#& !@#&--[[Constructs a new facing to the right of the current facing!@#&        Params: curx:number = The facing on the X axis!@#&                        curz:number = The facing on the Z axis!@#&                        hand:string = The hand of the axis (\"right\" or \"left\")!@#&        Returns:number,number = the new facing on the X and Z axis after a right turn!@#&]]--!@#&local function getRight(curx, curz)!@#&        local hand = \"left\"!@#&        if layering == \"up\" then hand = \"right\" end!@#&       !@#&        if hand == \"right\" then!@#&                if curx == 1 then return 0,1 end!@#&                if curx == -1 then return 0,-1 end!@#&                if curz == 1 then return -1,0 end!@#&                if curz == -1 then return 1,0 end!@#&        else!@#&                if curx == 1 then return 0,-1 end!@#&                if curx == -1 then return 0,1 end!@#&                if curz == 1 then return 1,0 end!@#&                if curz == -1 then return -1,0 end!@#&        end!@#&end!@#& !@#& !@#&--[[Sends out a rednet signal requesting local printers, and will listen for any responses. Printers found are added to the!@#&        printerList (for ID's) and printerNames (for names)!@#&        Params: nil!@#&        Returns:nil!@#&]]--!@#&local function locatePrinters()!@#&        printerList = { }!@#&        printerNames = { name = \"Printers\" }!@#&        local oldState = state!@#&        state = \"Locating printers, please wait...   \"!@#&        drawCanvas()!@#&        drawInterface()!@#&        state = oldState!@#&       !@#&        local modemOpened = false!@#&        for k,v in pairs(rs.getSides()) do!@#&                if peripheral.isPresent(v) and peripheral.getType(v) == \"modem\" then!@#&                        rednet.open(v)!@#&                        modemOpened = true!@#&                        break!@#&                end!@#&        end!@#&       !@#&        if not modemOpened then!@#&                displayConfirmDialogue(\"Modem not found!\", \"No modem peripheral. Must have network modem to locate printers.\")!@#&                return false!@#&        end!@#&       !@#&        rednet.broadcast(\"$3DPRINT IDENTIFY\")!@#&       !@#&        while true do!@#&                local id, msg = rsTimeReceive(1)!@#&               !@#&                if not id then break end!@#&                if string.find(msg, \"$3DPRINT IDACK\") == 1 then!@#&                        msg = string.gsub(msg, \"$3DPRINT IDACK \", \"\")!@#&                        table.insert(printerList, id)!@#&                        table.insert(printerNames, msg)!@#&                end!@#&        end!@#&       !@#&        if #printerList == 0 then!@#&                displayConfirmDialogue(\"Printers not found!\", \"No active printers found in proximity of this computer.\")!@#&                return false!@#&        else!@#&                return true!@#&        end!@#&end!@#& !@#&--[[Sends a request to the printer. Waits on a response and updates the state of the application accordingly.!@#&        Params: command:string the command to send!@#&                        param:string a parameter to send, if any!@#&        Returns:nil!@#&]]--!@#&local function sendPC(command,param)!@#&        local msg = \"$PC \"..command!@#&        if param then msg = msg..\" \"..param end!@#&        rednet.send(printerList[selectedPrinter], msg)!@#&       !@#&        while true do!@#&                local id,key = rsTimeReceive()!@#&                if id == printerList[selectedPrinter] then!@#&                        if key == \"$3DPRINT ACK\" then!@#&                                break!@#&                        elseif key == \"$3DPRINT DEP\" then!@#&                                displayConfirmDialogue(\"Printer Empty\", \"The printer has exhasted a material. Please refill slot \"..param..!@#&                                        \", and click this message when ready to continue.\")!@#&                                rednet.send(printerList[selectedPrinter], msg)!@#&                        elseif key == \"$3DPRINT OOF\" then!@#&                                displayConfirmDialogue(\"Printer Out of Fuel\", \"The printer has no fuel. Please replace the material \"..!@#&                                        \"in slot 1 with a fuel source, then click this message.\")!@#&                                rednet.send(printerList[selectedPrinter], \"$PC SS 1\")!@#&                                id,key = rsTimeReceive()!@#&                                rednet.send(printerList[selectedPrinter], \"$PC RF\")!@#&                                id,key = rsTimeReceive()!@#&                                rednet.send(printerList[selectedPrinter], msg)!@#&                        end!@#&                end!@#&        end!@#&       !@#&        --Changes to position are handled after the event has been successfully completed!@#&        if command == \"FW\" then!@#&                px = px + pfx!@#&                pz = pz + pfz!@#&        elseif command == \"BK\" then!@#&                px = px - pfx!@#&                pz = pz - pfz!@#&        elseif command == \"UP\" then!@#&                if layering == \"up\" then!@#&                        py = py + 1!@#&                else!@#&                        py = py - 1!@#&                end!@#&        elseif command == \"DW\" then!@#&                if layering == \"up\" then!@#&                        py = py - 1!@#&                else    !@#&                        py = py + 1!@#&                end!@#&        elseif command == \"TL\" then!@#&                pfx,pfz = getLeft(pfx,pfz)!@#&        elseif command == \"TR\" then!@#&                pfx,pfz = getRight(pfx,pfz)!@#&        elseif command == \"TU\" then!@#&                pfx = -pfx!@#&                pfz = -pfz!@#&        end!@#&       !@#&        drawCanvas()!@#&        drawInterface()!@#&end!@#& !@#&--[[A printing function that commands the printer to turn to face the desired direction, if it is not already doing so!@#&        Params: desx:number = the normalized x direction to face!@#&                        desz:number = the normalized z direction to face!@#&        Returns:nil!@#&]]--!@#&local function turnToFace(desx,desz)!@#&        if desx ~= 0 then!@#&                if pfx ~= desx then!@#&                        local temppfx,_ = getLeft(pfx,pfz)!@#&                        if temppfx == desx then!@#&                                sendPC(\"TL\")!@#&                        elseif temppfx == -desx then!@#&                                sendPC(\"TR\")!@#&                        else!@#&                                sendPC(\"TU\")!@#&                        end!@#&                end!@#&        else!@#&                print(\"on the z axis\")!@#&                if pfz ~= desz then!@#&                        local _,temppfz = getLeft(pfx,pfz)!@#&                        if temppfz == desz then!@#&                                sendPC(\"TL\")!@#&                        elseif temppfz == -desz then!@#&                                sendPC(\"TR\")!@#&                        else!@#&                                sendPC(\"TU\")!@#&                        end!@#&                end!@#&        end!@#&end!@#& !@#&--[[Performs the print!@#&        Params: nil!@#&        Returns:nil!@#&]]--!@#&local function performPrint()!@#&        state = \"active print\"!@#&        if layering == \"up\" then!@#&                --An up layering starts our builder bot on the bottom left corner of our build!@#&                px,py,pz = leflim, 0, botlim + 1!@#&                pfx,pfz = 0,-1!@#&               !@#&                --We move him forward and up a bit from his original position.!@#&                sendPC(\"FW\")!@#&                sendPC(\"UP\")!@#&                --For each layer that needs to be completed, we go up by one each time!@#&                for layers=1,#frames do!@#&                        --We first decide if we're going forwards or back, depending on what side we're on!@#&                        local rowbot,rowtop,rowinc = nil,nil,nil!@#&                        if pz == botlim then!@#&                                rowbot,rowtop,rowinc = botlim,toplim,-1!@#&                        else!@#&                                rowbot,rowtop,rowinc = toplim,botlim,1!@#&                        end!@#&                       !@#&                        for rows = rowbot,rowtop,rowinc do!@#&                                --Then we decide if we're going left or right, depending on what side we're on!@#&                                local linebot,linetop,lineinc = nil,nil,nil!@#&                                if px == leflim then!@#&                                        --Facing from the left side has to be easterly- it's changed here!@#&                                        turnToFace(1,0)!@#&                                        linebot,linetop,lineinc = leflim,riglim,1!@#&                                else!@#&                                        --Facing from the right side has to be westerly- it's changed here!@#&                                        turnToFace(-1,0)!@#&                                        linebot,linetop,lineinc = riglim,leflim,-1!@#&                                end!@#&                               !@#&                                for lines = linebot,linetop,lineinc do!@#&                                        --We move our turtle forward, placing the right material at each step!@#&                                        local material = frames[py][pz][px]!@#&                                        if material then!@#&                                                material = math.log10(frames[py][pz][px])/math.log10(2) + 1!@#&                                                sendPC(\"SS\", material)!@#&                                                sendPC(\"PD\")!@#&                                        end!@#&                                        if lines ~= linetop then!@#&                                                sendPC(\"FW\")!@#&                                        end!@#&                                end!@#&                               !@#&                                --The printer then has to do a U-turn, depending on which way he's facing and!@#&                                --which way he needs to go!@#&                                local temppfx,temppfz = getLeft(pfx,pfz)!@#&                                if temppfz == rowinc and rows ~= rowtop then!@#&                                        sendPC(\"TL\")!@#&                                        sendPC(\"FW\")!@#&                                        sendPC(\"TL\")!@#&                                elseif temppfz == -rowinc and rows ~= rowtop then!@#&                                        sendPC(\"TR\")!@#&                                        sendPC(\"FW\")!@#&                                        sendPC(\"TR\")!@#&                                end!@#&                        end!@#&                        --Now at the end of a run he does a 180 and moves up to begin the next part of the print!@#&                        sendPC(\"TU\")!@#&                        if layers ~= #frames then!@#&                                sendPC(\"UP\")!@#&                        end!@#&                end!@#&                --All done- now we head back to where we started.!@#&                if px ~= leflim then!@#&                        turnToFace(-1,0)!@#&                        while px ~= leflim do!@#&                                sendPC(\"FW\")!@#&                        end!@#&                end!@#&                if pz ~= botlim then!@#&                        turnToFace(0,-1)!@#&                        while pz ~= botlim do!@#&                                sendPC(\"BK\")!@#&                        end!@#&                end!@#&                turnToFace(0,-1)!@#&                sendPC(\"BK\")!@#&                while py > 0 do!@#&                        sendPC(\"DW\")!@#&                end!@#&        else!@#&                --The front facing is at the top-left corner, facing south not north!@#&                px,py,pz = leflim, botlim, 1!@#&                pfx,pfz = 0,1!@#&                --We move the printer to the last layer- he prints from the back forwards!@#&                while pz < #frames do!@#&                        sendPC(\"FW\")!@#&                end!@#&               !@#&                --For each layer in the frame we build our wall, the move back!@#&                for layers = 1,#frames do!@#&                        --We first decide if we're going left or right based on our position!@#&                        local rowbot,rowtop,rowinc = nil,nil,nil!@#&                        if px == leflim then!@#&                                rowbot,rowtop,rowinc = leflim,riglim,1!@#&                        else!@#&                                rowbot,rowtop,rowinc = riglim,leflim,-1!@#&                        end!@#&                       !@#&                        for rows = rowbot,rowtop,rowinc do!@#&                                --Then we decide if we're going up or down, depending on our given altitude!@#&                                local linebot,linetop,lineinc = nil,nil,nil!@#&                                if py == botlim then!@#&                                        linebot,linetop,lineinc = botlim,toplim,-1!@#&                                else!@#&                                        linebot,linetop,lineinc = toplim,botlim,1!@#&                                end!@#&                               !@#&                                for lines = linebot,linetop,lineinc do!@#&                                --We move our turtle up/down, placing the right material at each step!@#&                                        local material = frames[pz][py][px]!@#&                                        if material then!@#&                                                material = math.log10(frames[pz][py][px])/math.log10(2) + 1!@#&                                                sendPC(\"SS\", material)!@#&                                                sendPC(\"PF\")!@#&                                        end!@#&                                        if lines ~= linetop then!@#&                                                if lineinc == 1 then sendPC(\"DW\")!@#&                                                else sendPC(\"UP\") end!@#&                                        end!@#&                                end!@#&                                       !@#&                                if rows ~= rowtop then!@#&                                        turnToFace(rowinc,0)!@#&                                        sendPC(\"FW\")!@#&                                        turnToFace(0,1)!@#&                                end!@#&                        end!@#&                       !@#&                        if layers ~= #frames then!@#&                                sendPC(\"TU\")!@#&                                sendPC(\"FW\")!@#&                                sendPC(\"TU\")!@#&                        end!@#&                end!@#&                --He's easy to reset!@#&                while px ~= leflim do!@#&                        turnToFace(-1,0)!@#&                        sendPC(\"FW\")!@#&                end!@#&                turnToFace(0,1)!@#&        end!@#&       !@#&        sendPC(\"DE\")!@#&       !@#&        displayConfirmDialogue(\"Print complete\", \"The 3D print was successful.\")!@#&end!@#& !@#&--[[  !@#&                        Section: Interface  !@#&]]--!@#& !@#&--[[Runs the printing interface. Allows users to find/select a printer, the style of printing to perform and to begin the operation!@#&        Params: none!@#&        Returns:boolean true if printing was started, false otherwse!@#&]]--!@#&local function runPrintInterface()!@#&        calculateMaterials()!@#&        --There's nothing on canvas yet!!@#&        if not botlim then!@#&                displayConfirmDialogue(\"Cannot Print Empty Canvas\", \"There is nothing on canvas that \"..!@#&                                \"can be printed, and the operation cannot be completed.\")!@#&                return false!@#&        end!@#&        --No printers nearby!@#&        if not locatePrinters() then!@#&                return false!@#&        end!@#&       !@#&        layering = \"up\"!@#&        requirementsDisplayed = false!@#&        selectedPrinter = 1!@#&        while true do!@#&                drawCanvas()!@#&                term.setBackgroundColour(colours.lightGrey)!@#&                for i=1,10 do!@#&                        term.setCursorPos(1,i)!@#&                        term.clearLine()!@#&                end!@#&                drawInterface()!@#&                term.setBackgroundColour(colours.lightGrey)!@#&                term.setTextColour(colours.black)!@#&               !@#&                local msg = \"3D Printing\"!@#&                term.setCursorPos(w/2-#msg/2 - 2, 1)!@#&                term.write(msg)!@#&                term.setBackgroundColour(colours.grey)!@#&                term.setTextColour(colours.lightGrey)!@#&                if(requirementsDisplayed) then!@#&                        msg = \"Count:\"!@#&                else!@#&                        msg = \" Slot:\"!@#&                end!@#&                term.setCursorPos(w-3-#msg, 1)!@#&                term.write(msg)!@#&                term.setBackgroundColour(colours.lightGrey)!@#&                term.setTextColour(colours.black)!@#&               !@#&                term.setCursorPos(7, 2)!@#&                term.write(\"Layering\")!@#&                drawPictureTable(layerUpIcon, 3, 3, colours.white)!@#&                drawPictureTable(layerForwardIcon, 12, 3, colours.white)!@#&                if layering == \"up\" then!@#&                        term.setBackgroundColour(colours.red)!@#&                else!@#&                        term.setBackgroundColour(colours.lightGrey)!@#&                end!@#&                term.setCursorPos(3, 9)!@#&                term.write(\"Upwards\")!@#&                if layering == \"forward\" then!@#&                        term.setBackgroundColour(colours.red)!@#&                else!@#&                        term.setBackgroundColour(colours.lightGrey)!@#&                end!@#&                term.setCursorPos(12, 9)!@#&                term.write(\"Forward\")!@#&               !@#&                term.setBackgroundColour(colours.lightGrey)!@#&                term.setTextColour(colours.black)!@#&                term.setCursorPos(31, 2)!@#&                term.write(\"Printer ID\")!@#&                term.setCursorPos(33, 3)!@#&                if #printerList > 1 then!@#&                        term.setBackgroundColour(colours.grey)!@#&                        term.setTextColour(colours.lightGrey)!@#&                else!@#&                        term.setTextColour(colours.red)!@#&                end!@#&                term.write(\" \"..printerNames[selectedPrinter]..\" \")!@#&               !@#&                term.setBackgroundColour(colours.grey)!@#&                term.setTextColour(colours.lightGrey)!@#&                term.setCursorPos(25, 10)!@#&                term.write(\" Cancel \")!@#&                term.setCursorPos(40, 10)!@#&                term.write(\" Print \")!@#&               !@#&                local id, p1, p2, p3 = os.pullEvent()!@#&               !@#&                if id == \"timer\" then!@#&                        updateTimer(p1)!@#&                elseif id == \"mouse_click\" then!@#&                        --Layering Buttons!@#&                        if p2 >= 3 and p2 <= 9 and p3 >= 3 and p3 <= 9 then!@#&                                layering = \"up\"!@#&                        elseif p2 >= 12 and p2 <= 18 and p3 >= 3 and p3 <= 9 then!@#&                                layering = \"forward\"!@#&                        --Count/Slot!@#&                        elseif p2 >= w - #msg - 3 and p2 <= w - 3 and p3 == 1 then!@#&                                requirementsDisplayed = not requirementsDisplayed!@#&                        --Printer ID!@#&                        elseif p2 >= 33 and p2 <= 33 + #printerNames[selectedPrinter] and p3 == 3 and #printerList > 1 then!@#&                                local chosenName = displayDropDown(33, 3, printerNames)!@#&                                for i=1,#printerNames do!@#&                                        if printerNames[i] == chosenName then!@#&                                                selectedPrinter = i!@#&                                                break;!@#&                                        end!@#&                                end!@#&                        --Print and Cancel!@#&                        elseif p2 >= 25 and p2 <= 32 and p3 == 10 then!@#&                                break!@#&                        elseif p2 >= 40 and p2 <= 46 and p3 == 10 then!@#&                                rednet.send(printerList[selectedPrinter], \"$3DPRINT ACTIVATE\")!@#&                                ready = false!@#&                                while true do!@#&                                        local id,msg = rsTimeReceive(10)!@#&                                       !@#&                                        if id == printerList[selectedPrinter] and msg == \"$3DPRINT ACTACK\" then!@#&                                                ready = true!@#&                                                break!@#&                                        end!@#&                                end!@#&                                if ready then!@#&                                        performPrint()!@#&                                        break!@#&                                else!@#&                                        displayConfirmDialogue(\"Printer Didn't Respond\", \"The printer didn't respond to the activation command. Check to see if it's online\")!@#&                                end!@#&                        end!@#&                end!@#&        end!@#&        state = \"paint\"!@#&end!@#&!@#&--[[Performs a legacy save. When the dropdown menu is unavailable, it requests the user to save!@#&	or exit using keyboard shortcuts rather than selecting a menu option from the dropdown.!@#&	Pressing the control key again will cancel the save operation.!@#&	Params: none!@#&	Returns:string = the selection made!@#&]]--!@#&local function performLegacySaveExit()!@#&	local saveMsg = \"(S)ave/(E)xit?\"!@#&	if w < #saveMsg then saveMsg = \"S/E?\" end!@#&	!@#&	term.setCursorPos(1,h)!@#&	term.setBackgroundColour(colours.lightGrey)!@#&	term.setTextColour(colours.grey)!@#&	term.clearLine()!@#&	term.write(saveMsg)!@#&	!@#&	while true do!@#&		local id,val = os.pullEvent()!@#&		if id == \"timer\" then updateTimer(val)!@#&		elseif id == \"key\" then!@#&			if val == keys.s then return \"save\" !@#&			elseif val == keys.e then!@#&				--Get rid of the extra event!@#&				os.pullEvent(\"char\")!@#&				return \"exit\"!@#&			elseif val == keys.leftCtrl then return nil!@#&			end!@#&		end!@#&	end!@#&end!@#& !@#&--[[This function changes the current paint program to another tool or mode, depending on user input. Handles!@#&        any necessary changes in logic involved in that.!@#&        Params: mode:string = the name of the mode to change to!@#&        Returns:nil!@#&]]--!@#&local function performSelection(mode)!@#&        if not mode or mode == \"\" then return!@#&       !@#&        elseif mode == \"help\" and helpAvailable then!@#&                drawHelpScreen()!@#&               !@#&        elseif mode == \"blueprint on\" then!@#&                blueprint = true!@#&				for i=1,#ddModes[2] do if ddModes[2][i] == \"blueprint on\" then!@#&					ddModes[2][i] = \"blueprint off\"!@#&				end end!@#&               !@#&        elseif mode == \"blueprint off\" then!@#&                blueprint = false!@#&				for i=1,#ddModes[2] do if ddModes[2][i] == \"blueprint off\" then!@#&					ddModes[2][i] = \"blueprint on\"!@#&				end end!@#&               !@#&        elseif mode == \"layers on\" then!@#&                layerDisplay = true!@#&				for i=1,#ddModes[2] do if ddModes[2][i] == \"layers on\" then!@#&					ddModes[2][i] = \"layers off\"!@#&				end end!@#&       !@#&        elseif mode == \"layers off\" then!@#&                layerDisplay = false!@#&				for i=1,#ddModes[2] do if ddModes[2][i] == \"layers off\" then!@#&					ddModes[2][i] = \"layers on\"!@#&				end end!@#&       !@#&        elseif mode == \"direction on\" then!@#&                printDirection = true!@#&				for i=1,#ddModes[2] do if ddModes[2][i] == \"direction on\" then!@#&					ddModes[2][i] = \"direction off\"!@#&				end end!@#&               !@#&        elseif mode == \"direction off\" then!@#&                printDirection = false!@#&				for i=1,#ddModes[2] do if ddModes[2][i] == \"direction off\" then!@#&					ddModes[2][i] = \"direction on\"!@#&				end end!@#&		!@#&		elseif mode == \"hide interface\" then!@#&				interfaceHidden = true!@#&			!@#&		elseif mode == \"show interface\" then!@#&				interfaceHidden = false!@#&       !@#&        elseif mode == \"go to\" then!@#&                changeFrame()!@#&       !@#&        elseif mode == \"remove\" then!@#&                removeFramesAfter(sFrame)!@#&       !@#&        elseif mode == \"play\" then!@#&                playAnimation()!@#&               !@#&        elseif mode == \"copy\" then!@#&                if selectrect and selectrect.x1 ~= selectrect.x2 then!@#&                        copyToBuffer(false)!@#&                end!@#&       !@#&        elseif mode == \"cut\" then!@#&                if selectrect and selectrect.x1 ~= selectrect.x2 then!@#&                        copyToBuffer(true)!@#&                end!@#&               !@#&        elseif mode == \"paste\" then!@#&                if selectrect and selectrect.x1 ~= selectrect.x2 then!@#&                        copyFromBuffer(false)!@#&                end!@#&               !@#&        elseif mode == \"hide\" then!@#&                selectrect = nil!@#&                if state == \"select\" then state = \"corner select\" end!@#&			   !@#&        elseif mode == \"alpha to left\" then!@#&                if lSel then alphaC = lSel end!@#&               !@#&        elseif mode == \"alpha to right\" then!@#&                if rSel then alphaC = rSel end!@#&               !@#&        elseif mode == \"record\" then!@#&                record = not record!@#&               !@#&        elseif mode == \"clear\" then!@#&                if state==\"select\" then buffer = nil!@#&                else clearImage() end!@#&       !@#&        elseif mode == \"select\" then!@#&                if state==\"corner select\" or state==\"select\" then!@#&                        state = \"paint\"!@#&                elseif selectrect and selectrect.x1 ~= selectrect.x2 then!@#&                        state = \"select\"!@#&                else!@#&                        state = \"corner select\"!@#&                end!@#&               !@#&        elseif mode == \"print\" then!@#&                state = \"print\"!@#&                runPrintInterface()!@#&                state = \"paint\"!@#&               !@#&        elseif mode == \"save\" then!@#&                if animated then saveNFA(sPath)!@#&                elseif textEnabled then saveNFT(sPath)!@#&                else saveNFP(sPath) end!@#&               !@#&        elseif mode == \"exit\" then!@#&                isRunning = false!@#&       !@#&        elseif mode ~= state then state = mode!@#&        else state = \"paint\"!@#&        end!@#&end!@#& !@#&--[[The main function of the program, reads and handles all events and updates them accordingly. Mode changes,!@#&        painting to the canvas and general selections are done here.!@#&        Params: none!@#&        Returns:nil!@#&]]--!@#&local function handleEvents()!@#&        recttimer = os.startTimer(0.5)!@#&        while isRunning do!@#&                drawCanvas()!@#&                if not interfaceHidden then drawInterface() end!@#&               !@#&                if state == \"text\" then!@#&                        term.setCursorPos(textCurX - sx, textCurY - sy)!@#&                        term.setCursorBlink(true)!@#&                end!@#&               !@#&                local id,p1,p2,p3 = os.pullEvent()!@#&                term.setCursorBlink(false)!@#&                if id==\"timer\" then!@#&                        updateTimer(p1)!@#&                elseif (id==\"mouse_click\" or id==\"mouse_drag\") and not interfaceHidden then!@#&                        if p2 >=w-1 and p3 < #column+1 then!@#&								local off = 0!@#&								local cansel = true!@#&								if h < #column + 2 then!@#&									if p3 == 1 then !@#&										if columnoffset > 0 then columnoffset = columnoffset-1 end!@#&										cansel = false!@#&									elseif p3 == h-2 then!@#&										if columnoffset < #column-(h-4)+1 then columnoffset = columnoffset+1 end!@#&										cansel = false!@#&									else!@#&										off = columnoffset - 1!@#&									end!@#&								end!@#&								--This rather handily accounts for the nil case (p3+off=#column+1)!@#&								if p1==1 and cansel then lSel = column[p3+off]!@#&                                elseif p1==2 and cansel then rSel = column[p3+off] end!@#&                        elseif p2 >=w-1 and p3==#column+1 then!@#&                                if p1==1 then lSel = nil!@#&                                else rSel = nil end!@#&                        elseif p2==w-1 and p3==h and animated then!@#&                                changeFrame(sFrame-1)!@#&                        elseif p2==w and p3==h and animated then!@#&                                changeFrame(sFrame+1)!@#&                        elseif p2 <= #ddModes.name + 2 and p3==h and mainAvailable then!@#&                                local sel = displayDropDown(1, h-1, ddModes)!@#&                                performSelection(sel)!@#&                        elseif p2 < w-1 and p3 <= h-1 then!@#&                                if state==\"pippette\" then!@#&                                        if p1==1 then!@#&                                                if frames[sFrame][p3+sy] and frames[sFrame][p3+sy][p2+sx] then!@#&                                                        lSel = frames[sFrame][p3+sy][p2+sx]!@#&                                                end!@#&                                        elseif p1==2 then!@#&                                                if frames[sFrame][p3+sy] and frames[sFrame][p3+sy][p2+sx] then!@#&                                                        rSel = frames[sFrame][p3+sy][p2+sx]!@#&                                                end!@#&                                        end!@#&                                elseif state==\"move\" then!@#&                                        updateImageLims(record)!@#&                                        moveImage(p2,p3)!@#&                                elseif state==\"flood\" then!@#&                                        if p1 == 1 and lSel and frames[sFrame][p3+sy]  then!@#&                                                floodFill(p2,p3,frames[sFrame][p3+sy][p2+sx],lSel)!@#&                                        elseif p1 == 2 and rSel and frames[sFrame][p3+sy] then!@#&                                                floodFill(p2,p3,frames[sFrame][p3+sy][p2+sx],rSel)!@#&                                        end!@#&                                elseif state==\"corner select\" then!@#&                                        if not selectrect then!@#&                                                selectrect = { x1=p2+sx, x2=p2+sx, y1=p3+sy, y2=p3+sy }!@#&                                        elseif selectrect.x1 ~= p2+sx and selectrect.y1 ~= p3+sy then!@#&                                                if p2+sx<selectrect.x1 then selectrect.x1 = p2+sx!@#&                                                else selectrect.x2 = p2+sx end!@#&                                               !@#&                                                if p3+sy<selectrect.y1 then selectrect.y1 = p3+sy!@#&                                                else selectrect.y2 = p3+sy end!@#&                                               !@#&                                                state = \"select\"!@#&                                        end!@#&                                elseif state==\"textpaint\" then!@#&                                        local paintCol = lSel!@#&                                        if p1 == 2 then paintCol = rSel end!@#&                                        if frames[sFrame].textcol[p3+sy] then!@#&                                                frames[sFrame].textcol[p3+sy][p2+sx] = paintCol!@#&                                        end!@#&                                elseif state==\"text\" then!@#&                                        textCurX = p2 + sx!@#&                                        textCurY = p3 + sy!@#&                                elseif state==\"select\" then!@#&                                        if p1 == 1 then!@#&                                                local swidth = selectrect.x2 - selectrect.x1!@#&                                                local sheight = selectrect.y2 - selectrect.y1!@#&                                       !@#&                                                selectrect.x1 = p2 + sx!@#&                                                selectrect.y1 = p3 + sy!@#&                                                selectrect.x2 = p2 + swidth + sx!@#&                                                selectrect.y2 = p3 + sheight + sy!@#&                                        elseif p1 == 2 and p2 < w-2 and p3 < h-1 and boxdropAvailable then!@#&                                                inMenu = true!@#&                                                local sel = displayDropDown(p2, p3, srModes)!@#&                                                inMenu = false!@#&                                                performSelection(sel)!@#&                                        end!@#&                                else!@#&                                        local f,l = sFrame,sFrame!@#&                                        if record then f,l = 1,framecount end!@#&                                        local bwidth = 0!@#&                                        if state == \"brush\" then bwidth = brushsize-1 end!@#&                               !@#&                                        for i=f,l do!@#&                                                for x = math.max(1,p2+sx-bwidth),p2+sx+bwidth do!@#&                                                        for y = math.max(1,p3+sy-bwidth), p3+sy+bwidth do!@#&                                                                if math.abs(x - (p2+sx)) + math.abs(y - (p3+sy)) <= bwidth then!@#&                                                                        if not frames[i][y] then frames[i][y] = {} end!@#&                                                                        if p1==1 then frames[i][y][x] = lSel!@#&                                                                        else frames[i][y][x] = rSel end!@#&                                                                       !@#&                                                                        if textEnabled then!@#&                                                                                if not frames[i].text[y] then frames[i].text[y] = { } end!@#&                                                                                if not frames[i].textcol[y] then frames[i].textcol[y] = { } end!@#&                                                                        end!@#&                                                                end!@#&                                                        end!@#&                                                end!@#&                                        end!@#&                                end!@#&                        end!@#&                elseif id==\"char\" then!@#&                        if state==\"text\" then!@#&                                if not frames[sFrame][textCurY] then frames[sFrame][textCurY] = { } end!@#&                                if not frames[sFrame].text[textCurY] then frames[sFrame].text[textCurY] = { } end!@#&                                if not frames[sFrame].textcol[textCurY] then frames[sFrame].textcol[textCurY] = { } end!@#&                               !@#&                                if rSel then frames[sFrame][textCurY][textCurX] = rSel end!@#&                                if lSel then!@#&                                        frames[sFrame].text[textCurY][textCurX] = p1!@#&                                        frames[sFrame].textcol[textCurY][textCurX] = lSel!@#&                                else!@#&                                        frames[sFrame].text[textCurY][textCurX] = \" \"!@#&                                        frames[sFrame].textcol[textCurY][textCurX] = rSel!@#&                                end!@#&                               !@#&                                textCurX = textCurX+1!@#&                                if textCurX > w + sx - 2 then sx = textCurX - w + 2 end!@#&                        elseif tonumber(p1) then!@#&                                if state==\"brush\" and tonumber(p1) > 1 then!@#&                                        brushsize = tonumber(p1)!@#&                                elseif animated and tonumber(p1) > 0 then!@#&                                        changeFrame(tonumber(p1))!@#&                                end!@#&                        end!@#&                elseif id==\"key\" then!@#&						--All standard interface methods are locked when the interface is hidden!@#&						if interfaceHidden then!@#&							if p1==keys.grave then!@#&								performSelection(\"show interface\") !@#&							end!@#&                        --Text needs special handlers (all other keyboard shortcuts are of course reserved for typing)!@#&                        elseif state==\"text\" then!@#&                                if p1==keys.backspace and textCurX > 1 then!@#&                                        textCurX = textCurX-1!@#&                                        if frames[sFrame].text[textCurY] then!@#&                                                frames[sFrame].text[textCurY][textCurX] = nil!@#&                                                frames[sFrame].textcol[textCurY][textCurX] = nil!@#&                                        end!@#&                                        if textCurX < sx then sx = textCurX end!@#&                                elseif p1==keys.left and textCurX > 1 then!@#&                                        textCurX = textCurX-1!@#&                                        if textCurX-1 < sx then sx = textCurX-1 end!@#&                                elseif p1==keys.right then!@#&                                        textCurX = textCurX+1!@#&                                        if textCurX > w + sx - 2 then sx = textCurX - w + 2 end!@#&                                elseif p1==keys.up and textCurY > 1 then!@#&                                        textCurY = textCurY-1!@#&                                        if textCurY-1 < sy then sy = textCurY-1 end!@#&                                elseif p1==keys.down then!@#&                                        textCurY = textCurY+1!@#&                                        if textCurY > h + sy - 1 then sy = textCurY - h + 1 end!@#&                                end!@#&                       !@#&                        elseif p1==keys.leftCtrl then!@#&                                local sel = nil!@#&								if mainAvailable then !@#&									sel = displayDropDown(1, h-1, ddModes[#ddModes])!@#&								else sel = performLegacySaveExit() end!@#&                                performSelection(sel)!@#&                        elseif p1==keys.leftAlt then!@#&                                local sel = displayDropDown(1, h-1, ddModes[1])!@#&                                performSelection(sel)!@#&                        elseif p1==keys.h then!@#&                                performSelection(\"help\")!@#&                        elseif p1==keys.x then!@#&                                performSelection(\"cut\")!@#&                        elseif p1==keys.c then!@#&                                performSelection(\"copy\")!@#&                        elseif p1==keys.v then!@#&                                performSelection(\"paste\")!@#&                        elseif p1==keys.z then!@#&                                performSelection(\"clear\")!@#&                        elseif p1==keys.s then!@#&                                performSelection(\"select\")!@#&                        elseif p1==keys.tab then!@#&                                performSelection(\"hide\")!@#&                        elseif p1==keys.q then!@#&                                performSelection(\"alpha to left\")!@#&                        elseif p1==keys.w then!@#&                                performSelection(\"alpha to right\")!@#&                        elseif p1==keys.f then!@#&                                performSelection(\"flood\")!@#&                        elseif p1==keys.b then!@#&                                performSelection(\"brush\")!@#&                        elseif p1==keys.m then!@#&                                performSelection(\"move\")!@#&                        elseif p1==keys.backslash and animated then!@#&                                performSelection(\"record\")!@#&                        elseif p1==keys.p then!@#&                                performSelection(\"pippette\")!@#&                        elseif p1==keys.g and animated then!@#&                                performSelection(\"go to\")!@#&						elseif p1==keys.grave then !@#&								performSelection(\"hide interface\")!@#&                        elseif p1==keys.period and animated then!@#&                                changeFrame(sFrame+1)!@#&                        elseif p1==keys.comma and animated then!@#&                                changeFrame(sFrame-1)!@#&                        elseif p1==keys.r and animated then!@#&                                performSelection(\"remove\")!@#&                        elseif p1==keys.space and animated then!@#&                                performSelection(\"play\")!@#&                        elseif p1==keys.t and textEnabled then!@#&                                performSelection(\"text\")!@#&                                sleep(0.01)!@#&                        elseif p1==keys.y and textEnabled then!@#&                                performSelection(\"textpaint\")!@#&                        elseif p1==keys.left then!@#&                                if state == \"move\" and toplim then!@#&                                        updateImageLims(record)!@#&                                        if toplim and leflim then!@#&                                                moveImage(leflim-1,toplim)!@#&                                        end!@#&                                elseif state==\"select\" and selectrect.x1 > 1 then!@#&                                        selectrect.x1 = selectrect.x1-1!@#&                                        selectrect.x2 = selectrect.x2-1!@#&                                elseif sx > 0 then sx=sx-1 end!@#&                        elseif p1==keys.right then!@#&                                if state == \"move\" then!@#&                                        updateImageLims(record)!@#&                                        if toplim and leflim then!@#&                                                moveImage(leflim+1,toplim)!@#&                                        end!@#&                                elseif state==\"select\" then!@#&                                        selectrect.x1 = selectrect.x1+1!@#&                                        selectrect.x2 = selectrect.x2+1!@#&                                else sx=sx+1 end!@#&                        elseif p1==keys.up then!@#&                                if state == \"move\" then!@#&                                        updateImageLims(record)!@#&                                        if toplim and leflim then!@#&                                                moveImage(leflim,toplim-1)!@#&                                        end!@#&                                elseif state==\"select\" and selectrect.y1 > 1 then!@#&                                        selectrect.y1 = selectrect.y1-1!@#&                                        selectrect.y2 = selectrect.y2-1!@#&                                elseif sy > 0 then sy=sy-1 end!@#&                        elseif p1==keys.down then!@#&                                if state == \"move\" then!@#&                                        updateImageLims(record)!@#&                                        if toplim and leflim then!@#&                                                moveImage(leflim,toplim+1)!@#&                                        end!@#&                                elseif state==\"select\" then!@#&                                        selectrect.y1 = selectrect.y1+1!@#&                                        selectrect.y2 = selectrect.y2+1!@#&                                else sy=sy+1 end!@#&                        end!@#&                end!@#&        end!@#&end!@#& !@#&--[[!@#&                        Section: Main  !@#&]]--!@#& !@#&--The first thing done is deciding what features we actually have, given the screen size!@#&if w < 7 or h < 4 then!@#&	--NPaintPro simply doesn't work at certain configurations!@#&	shell.run(\"clear\")!@#&	print(\"Screen too small\")!@#&	os.pullEvent(\"key\")!@#&	return!@#&end!@#&--And reduces the number of features in others.!@#&determineAvailableServices()!@#& !@#&--There is no b&w support for NPP.!@#&if not term.isColour() then!@#&	shell.run(\"clear\")!@#&	print(\"NPaintPro\\nBy NitrogenFingers\\n\\nNPaintPro can only be run on advanced \"..!@#&	\"computers. Please reinstall on an advanced computer.\")!@#&    return!@#&end!@#& !@#&--Taken almost directly from edit (for consistency)!@#&local tArgs = {...}!@#& !@#&--Command line options can appear before the file path to specify the file format!@#&local ca = 1!@#&while ca <= #tArgs do!@#&	if tArgs[ca] == \"-a\" then animated = true!@#&	elseif tArgs[ca] == \"-t\" then textEnabled = true!@#&	elseif tArgs[ca] == \"-d\" then interfaceHidden = true!@#&	elseif string.sub(tArgs[ca], 1, 1) == \"-\" then!@#&		print(\"Unrecognized option: \"..tArgs[ca])!@#&		return!@#&	else break end!@#&	ca = ca + 1!@#&end!@#&!@#&--Presently, animations and text files are not supported!@#&if animated and textEnabled then!@#&    print(\"No support for animated text files- cannot have both -a and -t\")!@#&	return!@#&end!@#&!@#&--Filepaths must be added if the screen is too small!@#&if #tArgs < ca then!@#&	if not filemakerAvailable then!@#&		print(\"Usage: npaintpro [-a,-t,-d] <path>\")!@#&		return!@#&	else!@#&		--Otherwise do the logo draw early, to determine the file.!@#&		drawLogo()!@#&		if not runFileMaker() then return end!@#&	end!@#&else!@#&	if not interfaceHidden then drawLogo() end!@#&	sPath = shell.resolve(tArgs[ca])!@#&end!@#& !@#&if fs.exists(sPath) then!@#&        if fs.isDir(sPath) then!@#&                print(\"Cannot edit a directory.\")!@#&                return!@#&        elseif string.find(sPath, \".nfp\") ~= #sPath-3 and string.find(sPath, \".nfa\") ~= #sPath-3 and!@#&                        string.find(sPath, \".nft\") ~= #sPath-3 then!@#&                print(\"Can only edit .nfp, .nft and .nfa files:\",string.find(sPath, \".nfp\"),#sPath-3)!@#&                return!@#&        end!@#&       !@#&        if string.find(sPath, \".nfa\") == #sPath-3 then!@#&                animated = true!@#&        end!@#&       !@#&        if string.find(sPath, \".nft\") == #sPath-3 then!@#&                textEnabled = true!@#&        end    !@#&       !@#&        if string.find(sPath, \".nfp\") == #sPath-3 and animated then!@#&                print(\"Convert to nfa? Y/N\")!@#&                if string.find(string.lower(io.read()), \"y\") then!@#&                        local nsPath = string.sub(sPath, 1, #sPath-1)..\"a\"!@#&                        fs.move(sPath, nsPath)!@#&                        sPath = nsPath!@#&                else!@#&                        animated = false!@#&                end!@#&        end!@#&       !@#&        --Again this is possible, I just haven't done it. Maybe I will?!@#&        if textEnabled and (string.find(sPath, \".nfp\") == #sPath-3 or string.find(sPath, \".nfa\") == #sPath-3) then!@#&                print(\"Cannot convert to nft\")!@#&        end!@#&else!@#&        if not animated and not textEnabled and string.find(sPath, \".nfp\") ~= #sPath-3 then!@#&                sPath = sPath..\".nfp\"!@#&        elseif animated and string.find(sPath, \".nfa\") ~= #sPath-3 then!@#&                sPath = sPath..\".nfa\"!@#&        elseif textEnabled and string.find(sPath, \".nft\") ~= #sPath-3 then!@#&                sPath = sPath..\".nft\"!@#&        end!@#&end!@#& !@#&init()!@#&handleEvents()!@#& !@#&term.setBackgroundColour(colours.black)!@#&shell.run(\"clear\")",["luaide"]="!@#&--  !@#&--  Lua IDE!@#&--  Made by GravityScore!@#&--  !@#&!@#&!@#&--  -------- Variables!@#&!@#&-- Version!@#&local version = \"1.0\"!@#&local args = {...}!@#&!@#&-- Editing!@#&local w, h = term.getSize()!@#&local tabWidth = 2!@#&!@#&local autosaveInterval = 20!@#&local allowEditorEvent = true!@#&local keyboardShortcutTimeout = 0.4!@#&!@#&-- Clipboard!@#&local clipboard = nil!@#&!@#&-- Theme!@#&local theme = {}!@#&!@#&-- Language!@#&local languages = {}!@#&local curLanguage = {}!@#&!@#&-- Events!@#&local event_distract = \"luaide_distractionEvent\"!@#&!@#&-- Locations!@#&local updateURL = \"https://raw.github.com/GravityScore/LuaIDE/master/luaide.lua\"!@#&local ideLocation = \"/\" .. shell.getRunningProgram()!@#&local themeLocation = \"/.LuaIDE-Theme\"!@#&!@#&local function isAdvanced() return term.isColor and term.isColor() end!@#&!@#&!@#&--  -------- Utilities!@#&!@#&local function modRead(properties)!@#&	local w, h = term.getSize()!@#&	local defaults = {replaceChar = nil, history = nil, visibleLength = nil, textLength = nil, !@#&		liveUpdates = nil, exitOnKey = nil}!@#&	if not properties then properties = {} end!@#&	for k, v in pairs(defaults) do if not properties[k] then properties[k] = v end end!@#&	if properties.replaceChar then properties.replaceChar = properties.replaceChar:sub(1, 1) end!@#&	if not properties.visibleLength then properties.visibleLength = w end!@#&!@#&	local sx, sy = term.getCursorPos()!@#&	local line = \"\"!@#&	local pos = 0!@#&	local historyPos = nil!@#&!@#&	local function redraw(repl)!@#&		local scroll = 0!@#&		if properties.visibleLength and sx + pos > properties.visibleLength + 1 then !@#&			scroll = (sx + pos) - (properties.visibleLength + 1)!@#&		end!@#&!@#&		term.setCursorPos(sx, sy)!@#&		local a = repl or properties.replaceChar!@#&		if a then term.write(string.rep(a, line:len() - scroll))!@#&		else term.write(line:sub(scroll + 1, -1)) end!@#&		term.setCursorPos(sx + pos - scroll, sy)!@#&	end!@#&!@#&	local function sendLiveUpdates(event, ...)!@#&		if type(properties.liveUpdates) == \"function\" then!@#&			local ox, oy = term.getCursorPos()!@#&			local a, data = properties.liveUpdates(line, event, ...)!@#&			if a == true and data == nil then!@#&				term.setCursorBlink(false)!@#&				return line!@#&			elseif a == true and data ~= nil then!@#&				term.setCursorBlink(false)!@#&				return data!@#&			end!@#&			term.setCursorPos(ox, oy)!@#&		end!@#&	end!@#&!@#&	term.setCursorBlink(true)!@#&	while true do!@#&		local e, but, x, y, p4, p5 = os.pullEvent()!@#&!@#&		if e == \"char\" then!@#&			local s = false!@#&			if properties.textLength and line:len() < properties.textLength then s = true!@#&			elseif not properties.textLength then s = true end!@#&!@#&			local canType = true!@#&			if not properties.grantPrint and properties.refusePrint then!@#&				local canTypeKeys = {}!@#&				if type(properties.refusePrint) == \"table\" then!@#&					for _, v in pairs(properties.refusePrint) do!@#&						table.insert(canTypeKeys, tostring(v):sub(1, 1))!@#&					end!@#&				elseif type(properties.refusePrint) == \"string\" then!@#&					for char in properties.refusePrint:gmatch(\".\") do!@#&						table.insert(canTypeKeys, char)!@#&					end!@#&				end!@#&				for _, v in pairs(canTypeKeys) do if but == v then canType = false end end!@#&			elseif properties.grantPrint then!@#&				canType = false!@#&				local canTypeKeys = {}!@#&				if type(properties.grantPrint) == \"table\" then!@#&					for _, v in pairs(properties.grantPrint) do!@#&						table.insert(canTypeKeys, tostring(v):sub(1, 1))!@#&					end!@#&				elseif type(properties.grantPrint) == \"string\" then!@#&					for char in properties.grantPrint:gmatch(\".\") do!@#&						table.insert(canTypeKeys, char)!@#&					end!@#&				end!@#&				for _, v in pairs(canTypeKeys) do if but == v then canType = true end end!@#&			end!@#&!@#&			if s and canType then!@#&				line = line:sub(1, pos) .. but .. line:sub(pos + 1, -1)!@#&				pos = pos + 1!@#&				redraw()!@#&			end!@#&		elseif e == \"key\" then!@#&			if but == keys.enter then break!@#&			elseif but == keys.left then if pos > 0 then pos = pos - 1 redraw() end!@#&			elseif but == keys.right then if pos < line:len() then pos = pos + 1 redraw() end!@#&			elseif (but == keys.up or but == keys.down) and properties.history then!@#&				redraw(\" \")!@#&				if but == keys.up then!@#&					if historyPos == nil and #properties.history > 0 then !@#&						historyPos = #properties.history!@#&					elseif historyPos > 1 then !@#&						historyPos = historyPos - 1!@#&					end!@#&				elseif but == keys.down then!@#&					if historyPos == #properties.history then historyPos = nil!@#&					elseif historyPos ~= nil then historyPos = historyPos + 1 end!@#&				end!@#&!@#&				if properties.history and historyPos then!@#&					line = properties.history[historyPos]!@#&					pos = line:len()!@#&				else!@#&					line = \"\"!@#&					pos = 0!@#&				end!@#&!@#&				redraw()!@#&				local a = sendLiveUpdates(\"history\")!@#&				if a then return a end!@#&			elseif but == keys.backspace and pos > 0 then!@#&				redraw(\" \")!@#&				line = line:sub(1, pos - 1) .. line:sub(pos + 1, -1)!@#&				pos = pos - 1!@#&				redraw()!@#&				local a = sendLiveUpdates(\"delete\")!@#&				if a then return a end!@#&			elseif but == keys.home then!@#&				pos = 0!@#&				redraw()!@#&			elseif but == keys.delete and pos < line:len() then!@#&				redraw(\" \")!@#&				line = line:sub(1, pos) .. line:sub(pos + 2, -1)!@#&				redraw()!@#&				local a = sendLiveUpdates(\"delete\")!@#&				if a then return a end!@#&			elseif but == keys[\"end\"] then!@#&				pos = line:len()!@#&				redraw()!@#&			elseif properties.exitOnKey then !@#&				if but == properties.exitOnKey or (properties.exitOnKey == \"control\" and !@#&						(but == 29 or but == 157)) then !@#&					term.setCursorBlink(false)!@#&					return nil!@#&				end!@#&			end!@#&		end!@#&		local a = sendLiveUpdates(e, but, x, y, p4, p5)!@#&		if a then return a end!@#&	end!@#&!@#&	term.setCursorBlink(false)!@#&	if line ~= nil then line = line:gsub(\"^%s*(.-)%s*$\", \"%1\") end!@#&	return line!@#&end!@#&!@#&!@#&--  -------- Themes!@#&!@#&local defaultTheme = {!@#&	background = \"gray\",!@#&	backgroundHighlight = \"lightGray\",!@#&	prompt = \"cyan\",!@#&	promptHighlight = \"lightBlue\",!@#&	err = \"red\",!@#&	errHighlight = \"pink\",!@#&!@#&	editorBackground = \"gray\",!@#&	editorLineHightlight = \"lightBlue\",!@#&	editorLineNumbers = \"gray\",!@#&	editorLineNumbersHighlight = \"lightGray\",!@#&	editorError = \"pink\",!@#&	editorErrorHighlight = \"red\",!@#&!@#&	textColor = \"white\",!@#&	conditional = \"yellow\",!@#&	constant = \"orange\",!@#&	[\"function\"] = \"magenta\",!@#&	string = \"red\",!@#&	comment = \"lime\"!@#&}!@#&!@#&local normalTheme = {!@#&	background = \"black\",!@#&	backgroundHighlight = \"black\",!@#&	prompt = \"black\",!@#&	promptHighlight = \"black\",!@#&	err = \"black\",!@#&	errHighlight = \"black\",!@#&!@#&	editorBackground = \"black\",!@#&	editorLineHightlight = \"black\",!@#&	editorLineNumbers = \"black\",!@#&	editorLineNumbersHighlight = \"white\",!@#&	editorError = \"black\",!@#&	editorErrorHighlight = \"black\",!@#&!@#&	textColor = \"white\",!@#&	conditional = \"white\",!@#&	constant = \"white\",!@#&	[\"function\"] = \"white\",!@#&	string = \"white\",!@#&	comment = \"white\"!@#&}!@#&!@#&local availableThemes = {!@#&	{\"Water (Default)\", \"https://raw.github.com/GravityScore/LuaIDE/master/themes/default.txt\"},!@#&	{\"Fire\", \"https://raw.github.com/GravityScore/LuaIDE/master/themes/fire.txt\"},!@#&	{\"Sublime Text 2\", \"https://raw.github.com/GravityScore/LuaIDE/master/themes/st2.txt\"},!@#&	{\"Midnight\", \"https://raw.github.com/GravityScore/LuaIDE/master/themes/midnight.txt\"},!@#&	{\"TheOriginalBIT\", \"https://raw.github.com/GravityScore/LuaIDE/master/themes/bit.txt\"},!@#&	{\"Superaxander\", \"https://raw.github.com/GravityScore/LuaIDE/master/themes/superaxander.txt\"},!@#&	{\"Forest\", \"https://raw.github.com/GravityScore/LuaIDE/master/themes/forest.txt\"},!@#&	{\"Night\", \"https://raw.github.com/GravityScore/LuaIDE/master/themes/night.txt\"},!@#&	{\"Original\", \"https://raw.github.com/GravityScore/LuaIDE/master/themes/original.txt\"},!@#&}!@#&!@#&local function loadTheme(path)!@#&	local f = io.open(path)!@#&	local l = f:read(\"*l\")!@#&	local config = {}!@#&	while l ~= nil do!@#&		local k, v = string.match(l, \"^(%a+)=(%a+)\")!@#&		if k and v then config[k] = v end!@#&		l = f:read(\"*l\")!@#&	end!@#&	f:close()!@#&	return config!@#&end!@#&!@#&-- Load Theme!@#&if isAdvanced() then theme = defaultTheme!@#&else theme = normalTheme end!@#&!@#&!@#&--  -------- Drawing!@#&!@#&local function centerPrint(text, ny)!@#&	if type(text) == \"table\" then for _, v in pairs(text) do centerPrint(v) end!@#&	else!@#&		local x, y = term.getCursorPos()!@#&		local w, h = term.getSize()!@#&		term.setCursorPos(w/2 - text:len()/2 + (#text % 2 == 0 and 1 or 0), ny or y)!@#&		print(text)!@#&	end!@#&end!@#&!@#&local function title(t)!@#&	term.setTextColor(colors[theme.textColor])!@#&	term.setBackgroundColor(colors[theme.background])!@#&	term.clear()!@#&!@#&	term.setBackgroundColor(colors[theme.backgroundHighlight])!@#&	for i = 2, 4 do term.setCursorPos(1, i) term.clearLine() end!@#&	term.setCursorPos(3, 3)!@#&	term.write(t)!@#&end!@#&!@#&local function centerRead(wid, begt)!@#&	local function liveUpdate(line, e, but, x, y, p4, p5)!@#&		if isAdvanced() and e == \"mouse_click\" and x >= w/2 - wid/2 and x <= w/2 - wid/2 + 10 !@#&				and y >= 13 and y <= 15 then!@#&			return true, \"\"!@#&		end!@#&	end!@#&!@#&	if not begt then begt = \"\" end!@#&	term.setTextColor(colors[theme.textColor])!@#&	term.setBackgroundColor(colors[theme.promptHighlight])!@#&	for i = 8, 10 do!@#&		term.setCursorPos(w/2 - wid/2, i)!@#&		term.write(string.rep(\" \", wid))!@#&	end!@#&!@#&	if isAdvanced() then!@#&		term.setBackgroundColor(colors[theme.errHighlight])!@#&		for i = 13, 15 do!@#&			term.setCursorPos(w/2 - wid/2 + 1, i)!@#&			term.write(string.rep(\" \", 10))!@#&		end!@#&		term.setCursorPos(w/2 - wid/2 + 2, 14)!@#&		term.write(\"> Cancel\")!@#&	end!@#&!@#&	term.setBackgroundColor(colors[theme.promptHighlight])!@#&	term.setCursorPos(w/2 - wid/2 + 1, 9)!@#&	term.write(\"> \" .. begt)!@#&	return modRead({visibleLength = w/2 + wid/2, liveUpdates = liveUpdate})!@#&end!@#&!@#&!@#&--  -------- Prompt!@#&!@#&local function prompt(list, dir, isGrid)!@#&	local function draw(sel)!@#&		for i, v in ipairs(list) do!@#&			if i == sel then term.setBackgroundColor(v.highlight or colors[theme.promptHighlight])!@#&			else term.setBackgroundColor(v.bg or colors[theme.prompt]) end!@#&			term.setTextColor(v.tc or colors[theme.textColor])!@#&			for i = -1, 1 do!@#&				term.setCursorPos(v[2], v[3] + i)!@#&				term.write(string.rep(\" \", v[1]:len() + 4))!@#&			end!@#&!@#&			term.setCursorPos(v[2], v[3])!@#&			if i == sel then!@#&				term.setBackgroundColor(v.highlight or colors[theme.promptHighlight])!@#&				term.write(\" > \")!@#&			else term.write(\" - \") end!@#&			term.write(v[1] .. \" \")!@#&		end!@#&	end!@#&!@#&	local key1 = dir == \"horizontal\" and 203 or 200!@#&	local key2 = dir == \"horizontal\" and 205 or 208!@#&	local sel = 1!@#&	draw(sel)!@#&!@#&	while true do!@#&		local e, but, x, y = os.pullEvent()!@#&		if e == \"key\" and but == 28 then!@#&			return list[sel][1]!@#&		elseif e == \"key\" and but == key1 and sel > 1 then!@#&			sel = sel - 1!@#&			draw(sel)!@#&		elseif e == \"key\" and but == key2 and ((err == true and sel < #list - 1) or (sel < #list)) then!@#&			sel = sel + 1!@#&			draw(sel)!@#&		elseif isGrid and e == \"key\" and but == 203 and sel > 2 then!@#&			sel = sel - 2!@#&			draw(sel)!@#&		elseif isGrid and e == \"key\" and but == 205 and sel < 3 then!@#&			sel = sel + 2!@#&			draw(sel)!@#&		elseif e == \"mouse_click\" then!@#&			for i, v in ipairs(list) do!@#&				if x >= v[2] - 1 and x <= v[2] + v[1]:len() + 3 and y >= v[3] - 1 and y <= v[3] + 1 then!@#&					return list[i][1]!@#&				end!@#&			end!@#&		end!@#&	end!@#&end!@#&!@#&local function scrollingPrompt(list)!@#&	local function draw(items, sel, loc)!@#&		for i, v in ipairs(items) do!@#&			local bg = colors[theme.prompt]!@#&			local bghigh = colors[theme.promptHighlight]!@#&			if v:find(\"Back\") or v:find(\"Return\") then!@#&				bg = colors[theme.err]!@#&				bghigh = colors[theme.errHighlight]!@#&			end!@#&!@#&			if i == sel then term.setBackgroundColor(bghigh)!@#&			else term.setBackgroundColor(bg) end!@#&			term.setTextColor(colors[theme.textColor])!@#&			for x = -1, 1 do!@#&				term.setCursorPos(3, (i * 4) + x + 4)!@#&				term.write(string.rep(\" \", w - 13))!@#&			end!@#&!@#&			term.setCursorPos(3, i * 4 + 4)!@#&			if i == sel then!@#&				term.setBackgroundColor(bghigh)!@#&				term.write(\" > \")!@#&			else term.write(\" - \") end!@#&			term.write(v .. \" \")!@#&		end!@#&	end!@#&!@#&	local function updateDisplayList(items, loc, len)!@#&		local ret = {}!@#&		for i = 1, len do!@#&			local item = items[i + loc - 1]!@#&			if item then table.insert(ret, item) end!@#&		end!@#&		return ret!@#&	end!@#&!@#&	-- Variables!@#&	local sel = 1!@#&	local loc = 1!@#&	local len = 3!@#&	local disList = updateDisplayList(list, loc, len)!@#&	draw(disList, sel, loc)!@#&!@#&	-- Loop!@#&	while true do!@#&		local e, key, x, y = os.pullEvent()!@#&!@#&		if e == \"mouse_click\" then!@#&			for i, v in ipairs(disList) do!@#&				if x >= 3 and x <= w - 11 and y >= i * 4 + 3 and y <= i * 4 + 5 then return v end!@#&			end!@#&		elseif e == \"key\" and key == 200 then!@#&			if sel > 1 then!@#&				sel = sel - 1!@#&				draw(disList, sel, loc)!@#&			elseif loc > 1 then!@#&				loc = loc - 1!@#&				disList = updateDisplayList(list, loc, len)!@#&				draw(disList, sel, loc)!@#&			end!@#&		elseif e == \"key\" and key == 208 then!@#&			if sel < len then!@#&				sel = sel + 1!@#&				draw(disList, sel, loc)!@#&			elseif loc + len - 1 < #list then!@#&				loc = loc + 1!@#&				disList = updateDisplayList(list, loc, len)!@#&				draw(disList, sel, loc)!@#&			end!@#&		elseif e == \"mouse_scroll\" then!@#&			os.queueEvent(\"key\", key == -1 and 200 or 208)!@#&		elseif e == \"key\" and key == 28 then!@#&			return disList[sel]!@#&		end!@#&	end!@#&end!@#&!@#&function monitorKeyboardShortcuts()!@#&	local ta, tb = nil, nil!@#&	local allowChar = false!@#&	local shiftPressed = false!@#&	while true do!@#&		local event, char = os.pullEvent()!@#&		if event == \"key\" and (char == 42 or char == 52) then!@#&			shiftPressed = true!@#&			tb = os.startTimer(keyboardShortcutTimeout)!@#&		elseif event == \"key\" and (char == 29 or char == 157 or char == 219 or char == 220) then!@#&			allowEditorEvent = false!@#&			allowChar = true!@#&			ta = os.startTimer(keyboardShortcutTimeout)!@#&		elseif event == \"key\" and allowChar then!@#&			local name = nil!@#&			for k, v in pairs(keys) do!@#&				if v == char then!@#&					if shiftPressed then os.queueEvent(\"shortcut\", \"ctrl shift\", k:lower())!@#&					else os.queueEvent(\"shortcut\", \"ctrl\", k:lower()) end!@#&					sleep(0.005)!@#&					allowEditorEvent = true!@#&				end!@#&			end!@#&			if shiftPressed then os.queueEvent(\"shortcut\", \"ctrl shift\", char)!@#&			else os.queueEvent(\"shortcut\", \"ctrl\", char) end!@#&		elseif event == \"timer\" and char == ta then!@#&			allowEditorEvent = true!@#&			allowChar = false!@#&		elseif event == \"timer\" and char == tb then!@#&			shiftPressed = false!@#&		end!@#&	end!@#&end!@#&!@#&!@#&--  -------- Saving and Loading!@#&!@#&local function download(url, path)!@#&	for i = 1, 3 do!@#&		local response = http.get(url)!@#&		if response then!@#&			local data = response.readAll()!@#&			response.close()!@#&			if path then!@#&				local f = io.open(path, \"w\")!@#&				f:write(data)!@#&				f:close()!@#&			end!@#&			return true!@#&		end!@#&	end!@#&!@#&	return false!@#&end!@#&!@#&local function saveFile(path, lines)!@#&	local dir = path:sub(1, path:len() - fs.getName(path):len())!@#&	if not fs.exists(dir) then fs.makeDir(dir) end!@#&	if not fs.isDir(path) and not fs.isReadOnly(path) then!@#&		local a = \"\"!@#&		for _, v in pairs(lines) do a = a .. v .. \"\\n\" end!@#&!@#&		local f = io.open(path, \"w\")!@#&		f:write(a)!@#&		f:close()!@#&		return true!@#&	else return false end!@#&end!@#&!@#&local function loadFile(path)!@#&	if not fs.exists(path) then!@#&		local dir = path:sub(1, path:len() - fs.getName(path):len())!@#&		if not fs.exists(dir) then fs.makeDir(dir) end!@#&		local f = io.open(path, \"w\")!@#&		f:write(\"\")!@#&		f:close()!@#&	end!@#&!@#&	local l = {}!@#&	if fs.exists(path) and not fs.isDir(path) then!@#&		local f = io.open(path, \"r\")!@#&		if f then!@#&			local a = f:read(\"*l\")!@#&			while a do!@#&				table.insert(l, a)!@#&				a = f:read(\"*l\")!@#&			end!@#&			f:close()!@#&		end!@#&	else return nil end!@#&!@#&	if #l < 1 then table.insert(l, \"\") end!@#&	return l!@#&end!@#&!@#&!@#&--  -------- Languages!@#&!@#&languages.lua = {}!@#&languages.brainfuck = {}!@#&languages.none = {}!@#&!@#&--  Lua!@#&!@#&languages.lua.helpTips = {!@#&	\"A function you tried to call doesn't exist.\",!@#&	\"You made a typo.\",!@#&	\"The index of an array is nil.\",!@#&	\"The wrong variable type was passed.\",!@#&	\"A function/variable doesn't exist.\",!@#&	\"You missed an 'end'.\",!@#&	\"You missed a 'then'.\",!@#&	\"You declared a variable incorrectly.\",!@#&	\"One of your variables is mysteriously nil.\"!@#&}!@#&!@#&languages.lua.defaultHelpTips = {!@#&	2, 5!@#&}!@#&!@#&languages.lua.errors = {!@#&	[\"Attempt to call nil.\"] = {1, 2},!@#&	[\"Attempt to index nil.\"] = {3, 2},!@#&	[\".+ expected, got .+\"] = {4, 2, 9},!@#&	[\"'end' expected\"] = {6, 2},!@#&	[\"'then' expected\"] = {7, 2},!@#&	[\"'=' expected\"] = {8, 2}!@#&}!@#&!@#&languages.lua.keywords = {!@#&	[\"and\"] = \"conditional\",!@#&	[\"break\"] = \"conditional\",!@#&	[\"do\"] = \"conditional\",!@#&	[\"else\"] = \"conditional\",!@#&	[\"elseif\"] = \"conditional\",!@#&	[\"end\"] = \"conditional\",!@#&	[\"for\"] = \"conditional\",!@#&	[\"function\"] = \"conditional\",!@#&	[\"if\"] = \"conditional\",!@#&	[\"in\"] = \"conditional\",!@#&	[\"local\"] = \"conditional\",!@#&	[\"not\"] = \"conditional\",!@#&	[\"or\"] = \"conditional\",!@#&	[\"repeat\"] = \"conditional\",!@#&	[\"return\"] = \"conditional\",!@#&	[\"then\"] = \"conditional\",!@#&	[\"until\"] = \"conditional\",!@#&	[\"while\"] = \"conditional\",!@#&!@#&	[\"true\"] = \"constant\",!@#&	[\"false\"] = \"constant\",!@#&	[\"nil\"] = \"constant\",!@#&!@#&	[\"print\"] = \"function\",!@#&	[\"write\"] = \"function\",!@#&	[\"sleep\"] = \"function\",!@#&	[\"pairs\"] = \"function\",!@#&	[\"ipairs\"] = \"function\",!@#&	[\"loadstring\"] = \"function\",!@#&	[\"loadfile\"] = \"function\",!@#&	[\"dofile\"] = \"function\",!@#&	[\"rawset\"] = \"function\",!@#&	[\"rawget\"] = \"function\",!@#&	[\"setfenv\"] = \"function\",!@#&	[\"getfenv\"] = \"function\",!@#&}!@#&!@#&languages.lua.parseError = function(e)!@#&	local ret = {filename = \"unknown\", line = -1, display = \"Unknown!\", err = \"\"}!@#&	if e and e ~= \"\" then!@#&		ret.err = e!@#&		if e:find(\":\") then!@#&			ret.filename = e:sub(1, e:find(\":\") - 1):gsub(\"^%s*(.-)%s*$\", \"%1\")!@#&			-- The \"\" is needed to circumvent a CC bug!@#&			e = (e:sub(e:find(\":\") + 1) .. \"\"):gsub(\"^%s*(.-)%s*$\", \"%1\")!@#&			if e:find(\":\") then!@#&				ret.line = e:sub(1, e:find(\":\") - 1)!@#&				e = e:sub(e:find(\":\") + 2):gsub(\"^%s*(.-)%s*$\", \"%1\") .. \"\"!@#&			end!@#&		end!@#&		ret.display = e:sub(1, 1):upper() .. e:sub(2, -1) .. \".\"!@#&	end!@#&!@#&	return ret!@#&end!@#&!@#&languages.lua.getCompilerErrors = function(code)!@#&	code = \"local function ee65da6af1cb6f63fee9a081246f2fd92b36ef2(...)\\n\\n\" .. code .. \"\\n\\nend\"!@#&	local fn, err = loadstring(code)!@#&	if not err then!@#&		local _, e = pcall(fn)!@#&		if e then err = e end!@#&	end!@#&!@#&	if err then!@#&		local a = err:find(\"]\", 1, true)!@#&		if a then err = \"string\" .. err:sub(a + 1, -1) end!@#&		local ret = languages.lua.parseError(err)!@#&		if tonumber(ret.line) then ret.line = tonumber(ret.line) end!@#&		return ret!@#&	else return languages.lua.parseError(nil) end!@#&end!@#&!@#&languages.lua.run = function(path, ar)!@#&	local fn, err = loadfile(path)!@#&	setfenv(fn, getfenv())!@#&	if not err then!@#&		_, err = pcall(function() fn(unpack(ar)) end)!@#&	end!@#&	return err!@#&end!@#&!@#&!@#&--  Brainfuck!@#&!@#&languages.brainfuck.helpTips = {!@#&	\"Well idk...\",!@#&	\"Isn't this the whole point of the language?\",!@#&	\"Ya know... Not being able to debug it?\",!@#&	\"You made a typo.\"!@#&}!@#&!@#&languages.brainfuck.defaultHelpTips = {!@#&	1, 2, 3!@#&}!@#&!@#&languages.brainfuck.errors = {!@#&	[\"No matching '['\"] = {1, 2, 3, 4}!@#&}!@#&!@#&languages.brainfuck.keywords = {}!@#&!@#&languages.brainfuck.parseError = function(e)!@#&	local ret = {filename = \"unknown\", line = -1, display = \"Unknown!\", err = \"\"}!@#&	if e and e ~= \"\" then!@#&		ret.err = e!@#&		ret.line = e:sub(1, e:find(\":\") - 1)!@#&		e = e:sub(e:find(\":\") + 2):gsub(\"^%s*(.-)%s*$\", \"%1\") .. \"\"!@#&		ret.display = e:sub(1, 1):upper() .. e:sub(2, -1) .. \".\"!@#&	end!@#&!@#&	return ret!@#&end!@#&!@#&languages.brainfuck.mapLoops = function(code)!@#&	-- Map loops!@#&	local loopLocations = {}!@#&	local loc = 1!@#&	local line = 1!@#&	for let in string.gmatch(code, \".\") do!@#&		if let == \"[\" then!@#&			loopLocations[loc] = true!@#&		elseif let == \"]\" then!@#&			local found = false!@#&			for i = loc, 1, -1 do !@#&				if loopLocations[i] == true then!@#&					loopLocations[i] = loc!@#&					found = true!@#&				end!@#&			end!@#&!@#&			if not found then!@#&				return line .. \": No matching '['\"!@#&			end!@#&		end!@#&!@#&		if let == \"\\n\" then line = line + 1 end!@#&		loc = loc + 1!@#&	end!@#&	return loopLocations!@#&end!@#&!@#&languages.brainfuck.getCompilerErrors = function(code)!@#&	local a = languages.brainfuck.mapLoops(code)!@#&	if type(a) == \"string\" then return languages.brainfuck.parseError(a)!@#&	else return languages.brainfuck.parseError(nil) end!@#&end!@#&!@#&languages.brainfuck.run = function(path)!@#&	-- Read from file!@#&	local f = io.open(path, \"r\")!@#&	local content = f:read(\"*a\")!@#&	f:close()!@#&!@#&	-- Define environment!@#&	local dataCells = {}!@#&	local dataPointer = 1!@#&	local instructionPointer = 1!@#&!@#&	-- Map loops!@#&	local loopLocations = languages.brainfuck.mapLoops(content)!@#&	if type(loopLocations) == \"string\" then return loopLocations end!@#&!@#&	-- Execute code!@#&	while true do!@#&		local let = content:sub(instructionPointer, instructionPointer)!@#&!@#&		if let == \">\" then!@#&			dataPointer = dataPointer + 1!@#&			if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end!@#&		elseif let == \"<\" then!@#&			if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end!@#&			dataPointer = dataPointer - 1!@#&			if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end!@#&		elseif let == \"+\" then!@#&			if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end!@#&			dataCells[tostring(dataPointer)] = dataCells[tostring(dataPointer)] + 1!@#&		elseif let == \"-\" then!@#&			if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end!@#&			dataCells[tostring(dataPointer)] = dataCells[tostring(dataPointer)] - 1!@#&		elseif let == \".\" then!@#&			if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end!@#&			if term.getCursorPos() >= w then print(\"\") end!@#&			write(string.char(math.max(1, dataCells[tostring(dataPointer)])))!@#&		elseif let == \",\" then!@#&			if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end!@#&			term.setCursorBlink(true)!@#&			local e, but = os.pullEvent(\"char\")!@#&			term.setCursorBlink(false)!@#&			dataCells[tostring(dataPointer)] = string.byte(but)!@#&			if term.getCursorPos() >= w then print(\"\") end!@#&			write(but)!@#&		elseif let == \"/\" then!@#&			if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end!@#&			if term.getCursorPos() >= w then print(\"\") end!@#&			write(dataCells[tostring(dataPointer)])!@#&		elseif let == \"[\" then!@#&			if dataCells[tostring(dataPointer)] == 0 then!@#&				for k, v in pairs(loopLocations) do!@#&					if k == instructionPointer then instructionPointer = v end!@#&				end!@#&			end!@#&		elseif let == \"]\" then!@#&			for k, v in pairs(loopLocations) do!@#&				if v == instructionPointer then instructionPointer = k - 1 end!@#&			end!@#&		end!@#&!@#&		instructionPointer = instructionPointer + 1!@#&		if instructionPointer > content:len() then print(\"\") break end!@#&	end!@#&end!@#&!@#&--  None!@#&!@#&languages.none.helpTips = {}!@#&languages.none.defaultHelpTips = {}!@#&languages.none.errors = {}!@#&languages.none.keywords = {}!@#&!@#&languages.none.parseError = function(err)!@#&	return {filename = \"\", line = -1, display = \"\", err = \"\"}!@#&end!@#&!@#&languages.none.getCompilerErrors = function(code)!@#&	return languages.none.parseError(nil)!@#&end!@#&!@#&languages.none.run = function(path) end!@#&!@#&!@#&-- Load language!@#&curLanguage = languages.lua!@#&!@#&!@#&--  -------- Run GUI!@#&!@#&local function viewErrorHelp(e)!@#&	title(\"LuaIDE - Error Help\")!@#&!@#&	local tips = nil!@#&	for k, v in pairs(curLanguage.errors) do!@#&		if e.display:find(k) then tips = v break end!@#&	end!@#&!@#&	term.setBackgroundColor(colors[theme.err])!@#&	for i = 6, 8 do!@#&		term.setCursorPos(5, i)!@#&		term.write(string.rep(\" \", 35))!@#&	end!@#&!@#&	term.setBackgroundColor(colors[theme.prompt])!@#&	for i = 10, 18 do!@#&		term.setCursorPos(5, i)!@#&		term.write(string.rep(\" \", 46))!@#&	end!@#&!@#&	if tips then!@#&		term.setBackgroundColor(colors[theme.err])!@#&		term.setCursorPos(6, 7)!@#&		term.write(\"Error Help\")!@#&!@#&		term.setBackgroundColor(colors[theme.prompt])!@#&		for i, v in ipairs(tips) do!@#&			term.setCursorPos(7, i + 10)!@#&			term.write(\"- \" .. curLanguage.helpTips[v])!@#&		end!@#&	else!@#&		term.setBackgroundColor(colors[theme.err])!@#&		term.setCursorPos(6, 7)!@#&		term.write(\"No Error Tips Available!\")!@#&!@#&		term.setBackgroundColor(colors[theme.prompt])!@#&		term.setCursorPos(6, 11)!@#&		term.write(\"There are no error tips available, but\")!@#&		term.setCursorPos(6, 12)!@#&		term.write(\"you could see if it was any of these:\")!@#&!@#&		for i, v in ipairs(curLanguage.defaultHelpTips) do!@#&			term.setCursorPos(7, i + 12)!@#&			term.write(\"- \" .. curLanguage.helpTips[v])!@#&		end!@#&	end!@#&!@#&	prompt({{\"Back\", w - 8, 7}}, \"horizontal\")!@#&end!@#&!@#&local function run(path, lines, useArgs)!@#&	local ar = {}!@#&	if useArgs then!@#&		title(\"LuaIDE - Run \" .. fs.getName(path))!@#&		local s = centerRead(w - 13, fs.getName(path) .. \" \")!@#&		for m in string.gmatch(s, \"[^ \\t]+\") do ar[#ar + 1] = m:gsub(\"^%s*(.-)%s*$\", \"%1\") end!@#&	end!@#&	!@#&	saveFile(path, lines)!@#&	term.setCursorBlink(false)!@#&	term.setBackgroundColor(colors.black)!@#&	term.setTextColor(colors.white)!@#&	term.clear()!@#&	term.setCursorPos(1, 1)!@#&	local err = curLanguage.run(path, ar)!@#&!@#&	term.setBackgroundColor(colors.black)!@#&	print(\"\\n\")!@#&	if err then!@#&		if isAdvanced() then term.setTextColor(colors.red) end!@#&		centerPrint(\"The program has crashed!\")!@#&	end!@#&	term.setTextColor(colors.white)!@#&	centerPrint(\"Press any key to return to LuaIDE...\")!@#&	while true do!@#&		local e = os.pullEvent()!@#&		if e == \"key\" then break end!@#&	end!@#&!@#&	-- To prevent key from showing up in editor!@#&	os.queueEvent(event_distract)!@#&	os.pullEvent()!@#&!@#&	if err then!@#&		if curLanguage == languages.lua and err:find(\"]\") then!@#&			err = fs.getName(path) .. err:sub(err:find(\"]\", 1, true) + 1, -1)!@#&		end!@#&!@#&		while true do!@#&			title(\"LuaIDE - Error!\")!@#&!@#&			term.setBackgroundColor(colors[theme.err])!@#&			for i = 6, 8 do!@#&				term.setCursorPos(3, i)!@#&				term.write(string.rep(\" \", w - 5))!@#&			end!@#&			term.setCursorPos(4, 7)!@#&			term.write(\"The program has crashed!\")!@#&!@#&			term.setBackgroundColor(colors[theme.prompt])!@#&			for i = 10, 14 do!@#&				term.setCursorPos(3, i)!@#&				term.write(string.rep(\" \", w - 5))!@#&			end!@#&!@#&			local formattedErr = curLanguage.parseError(err)!@#&			term.setCursorPos(4, 11)!@#&			term.write(\"Line: \" .. formattedErr.line)!@#&			term.setCursorPos(4, 12)!@#&			term.write(\"Error:\")!@#&			term.setCursorPos(5, 13)!@#&!@#&			local a = formattedErr.display!@#&			local b = nil!@#&			if a:len() > w - 8 then!@#&				for i = a:len(), 1, -1 do!@#&					if a:sub(i, i) == \" \" then!@#&						b = a:sub(i + 1, -1)!@#&						a = a:sub(1, i)!@#&						break!@#&					end!@#&				end!@#&			end!@#&!@#&			term.write(a)!@#&			if b then!@#&				term.setCursorPos(5, 14)!@#&				term.write(b)!@#&			end!@#&			!@#&			local opt = prompt({{\"Error Help\", w/2 - 15, 17}, {\"Go To Line\", w/2 + 2, 17}},!@#&				\"horizontal\")!@#&			if opt == \"Error Help\" then!@#&				viewErrorHelp(formattedErr)!@#&			elseif opt == \"Go To Line\" then!@#&				-- To prevent key from showing up in editor!@#&				os.queueEvent(event_distract)!@#&				os.pullEvent()!@#&!@#&				return \"go to\", tonumber(formattedErr.line)!@#&			end!@#&		end!@#&	end!@#&end!@#&!@#&!@#&--  -------- Functions!@#&!@#&local function goto()!@#&	term.setBackgroundColor(colors[theme.backgroundHighlight])!@#&	term.setCursorPos(2, 1)!@#&	term.clearLine()!@#&	term.write(\"Line: \")!@#&	local line = modRead({visibleLength = w - 2})!@#&!@#&	local num = tonumber(line)!@#&	if num and num > 0 then return num!@#&	else!@#&		term.setCursorPos(2, 1)!@#&		term.clearLine()!@#&		term.write(\"Not a line number!\")!@#&		sleep(1.6)!@#&		return nil!@#&	end!@#&end!@#&!@#&local function setsyntax()!@#&	local opts = {!@#&		\"[Lua]   Brainfuck    None \",!@#&		\" Lua   [Brainfuck]   None \",!@#&		\" Lua    Brainfuck   [None]\"!@#&	}!@#&	local sel = 1!@#&!@#&	term.setCursorBlink(false)!@#&	term.setBackgroundColor(colors[theme.backgroundHighlight])!@#&	term.setCursorPos(2, 1)!@#&	term.clearLine()!@#&	term.write(opts[sel])!@#&	while true do!@#&		local e, but, x, y = os.pullEvent(\"key\")!@#&		if but == 203 then!@#&			sel = math.max(1, sel - 1)!@#&			term.setCursorPos(2, 1)!@#&			term.clearLine()!@#&			term.write(opts[sel])!@#&		elseif but == 205 then!@#&			sel = math.min(#opts, sel + 1)!@#&			term.setCursorPos(2, 1)!@#&			term.clearLine()!@#&			term.write(opts[sel])!@#&		elseif but == 28 then!@#&			if sel == 1 then curLanguage = languages.lua!@#&			elseif sel == 2 then curLanguage = languages.brainfuck!@#&			elseif sel == 3 then curLanguage = languages.none end!@#&			term.setCursorBlink(true)!@#&			return!@#&		end!@#&	end!@#&end!@#&!@#&!@#&--  -------- Re-Indenting!@#&!@#&local tabWidth = 2!@#&!@#&local comments = {}!@#&local strings = {}!@#&!@#&local increment = {!@#&	\"if%s+.+%s+then%s*$\",!@#&	\"for%s+.+%s+do%s*$\",!@#&	\"while%s+.+%s+do%s*$\",!@#&	\"repeat%s*$\",!@#&	\"function%s+[a-zA-Z_0-9]\\(.*\\)%s*$\"!@#&}!@#&!@#&local decrement = {!@#&	\"end\",!@#&	\"until%s+.+\"!@#&}!@#&!@#&local special = {!@#&	\"else%s*$\",!@#&	\"elseif%s+.+%s+then%s*$\"!@#&}!@#&!@#&local function check(func)!@#&	for _, v in pairs(func) do!@#&		local cLineStart = v[\"lineStart\"]!@#&		local cLineEnd = v[\"lineEnd\"]!@#&		local cCharStart = v[\"charStart\"]!@#&		local cCharEnd = v[\"charEnd\"]!@#&!@#&		if line >= cLineStart and line <= cLineEnd then!@#&			if line == cLineStart then return cCharStart < charNumb!@#&			elseif line == cLineEnd then return cCharEnd > charNumb!@#&			else return true end!@#&		end!@#&	end!@#&end!@#&!@#&local function isIn(line, loc)!@#&	if check(comments) then return true end!@#&	if check(strings) then return true end!@#&	return false!@#&end!@#&!@#&local function setComment(ls, le, cs, ce)!@#&	comments[#comments + 1] = {}!@#&	comments[#comments].lineStart = ls!@#&	comments[#comments].lineEnd = le!@#&	comments[#comments].charStart = cs!@#&	comments[#comments].charEnd = ce!@#&end!@#&!@#&local function setString(ls, le, cs, ce)!@#&	strings[#strings + 1] = {}!@#&	strings[#strings].lineStart = ls!@#&	strings[#strings].lineEnd = le!@#&	strings[#strings].charStart = cs!@#&	strings[#strings].charEnd = ce!@#&end!@#&!@#&local function map(contents)!@#&	local inCom = false!@#&	local inStr = false!@#&!@#&	for i = 1, #contents do!@#&		if content[i]:find(\"%-%-%[%[\") and not inStr and not inCom then!@#&			local cStart = content[i]:find(\"%-%-%[%[\")!@#&			setComment(i, nil, cStart, nil)!@#&			inCom = true!@#&		elseif content[i]:find(\"%-%-%[=%[\") and not inStr and not inCom then!@#&			local cStart = content[i]:find(\"%-%-%[=%[\")!@#&			setComment(i, nil, cStart, nil)!@#&			inCom = true!@#&		elseif content[i]:find(\"%[%[\") and not inStr and not inCom then!@#&			local cStart = content[i]:find(\"%[%[\")!@#&			setString(i, nil, cStart, nil)!@#&			inStr = true!@#&		elseif content[i]:find(\"%[=%[\") and not inStr and not inCom then!@#&			local cStart = content[i]:find(\"%[=%[\")!@#&			setString(i, nil, cStart, nil)!@#&			inStr = true!@#&		end!@#&!@#&		if content[i]:find(\"%]%]\") and inStr and not inCom then!@#&			local cStart, cEnd = content[i]:find(\"%]%]\")!@#&			strings[#strings].lineEnd = i!@#&			strings[#strings].charEnd = cEnd!@#&			inStr = false!@#&		elseif content[i]:find(\"%]=%]\") and inStr and not inCom then!@#&			local cStart, cEnd = content[i]:find(\"%]=%]\")!@#&			strings[#strings].lineEnd = i!@#&			strings[#strings].charEnd = cEnd!@#&			inStr = false!@#&		end!@#&!@#&		if content[i]:find(\"%]%]\") and not inStr and inCom then!@#&			local cStart, cEnd = content[i]:find(\"%]%]\")!@#&			comments[#comments].lineEnd = i!@#&			comments[#comments].charEnd = cEnd!@#&			inCom = false!@#&		elseif content[i]:find(\"%]=%]\") and not inStr and inCom then!@#&			local cStart, cEnd = content[i]:find(\"%]=%]\")!@#&			comments[#comments].lineEnd = i!@#&			comments[#comments].charEnd = cEnd!@#&			inCom = false!@#&		end!@#&!@#&		if content[i]:find(\"%-%-\") and not inStr and not inCom then!@#&			local cStart = content[i]:find(\"%-%-\")!@#&			setComment(i, i, cStart, -1)!@#&		elseif content[i]:find(\"'\") and not inStr and not inCom then!@#&			local cStart, cEnd = content[i]:find(\"'\")!@#&			local nextChar = content[i]:sub(cEnd + 1, string.len(content[i]))!@#&			local _, cEnd = nextChar:find(\"'\")!@#&			setString(i, i, cStart, cEnd)!@#&		elseif content[i]:find('\"') and not inStr and not inCom then!@#&			local cStart, cEnd = content[i]:find('\"')!@#&			local nextChar = content[i]:sub(cEnd + 1, string.len(content[i]))!@#&			local _, cEnd = nextChar:find('\"')!@#&			setString(i, i, cStart, cEnd)!@#&		end!@#&	end!@#&end!@#&!@#&local function reindent(contents)!@#&	local err = nil!@#&	if curLanguage ~= languages.lua then!@#&		err = \"Cannot indent languages other than Lua!\"!@#&	elseif curLanguage.getCompilerErrors(table.concat(contents, \"\\n\")).line ~= -1 then!@#&		err = \"Cannot indent a program with errors!\"!@#&	end!@#&!@#&	if err then!@#&		term.setCursorBlink(false)!@#&		term.setCursorPos(2, 1)!@#&		term.setBackgroundColor(colors[theme.backgroundHighlight])!@#&		term.clearLine()!@#&		term.write(err)!@#&		sleep(1.6)!@#&		return contents!@#&	end!@#&!@#&	local new = {}!@#&	local level = 0!@#&	for k, v in pairs(contents) do!@#&		local incrLevel = false!@#&		local foundIncr = false!@#&		for _, incr in pairs(increment) do!@#&			if v:find(incr) and not isIn(k, v:find(incr)) then!@#&				incrLevel = true!@#&			end!@#&			if v:find(incr:sub(1, -2)) and not isIn(k, v:find(incr)) then!@#&				foundIncr = true!@#&			end!@#&		end!@#&!@#&		local decrLevel = false!@#&		if not incrLevel then!@#&			for _, decr in pairs(decrement) do!@#&				if v:find(decr) and not isIn(k, v:find(decr)) and not foundIncr then!@#&					level = math.max(0, level - 1)!@#&					decrLevel = true!@#&				end!@#&			end!@#&		end!@#&!@#&		if not decrLevel then!@#&			for _, sp in pairs(special) do!@#&				if v:find(sp) and not isIn(k, v:find(sp)) then!@#&					incrLevel = true!@#&					level = math.max(0, level - 1)!@#&				end!@#&			end!@#&		end!@#&!@#&		new[k] = string.rep(\" \", level * tabWidth) .. v!@#&		if incrLevel then level = level + 1 end!@#&	end!@#&!@#&	return new!@#&end!@#&!@#&!@#&--  -------- Menu!@#&!@#&local menu = {!@#&	[1] = {\"File\",!@#&--		\"About\",!@#&--		\"Settings\",!@#&--		\"\",!@#&		\"New File  ^+N\",!@#&		\"Open File ^+O\",!@#&		\"Save File ^+S\",!@#&		\"Close     ^+W\",!@#&		\"Print     ^+P\",!@#&		\"Quit      ^+Q\"!@#&	}, [2] = {\"Edit\",!@#&		\"Cut Line   ^+X\",!@#&		\"Copy Line  ^+C\",!@#&		\"Paste Line ^+V\",!@#&		\"Delete Line\",!@#&		\"Clear Line\"!@#&	}, [3] = {\"Functions\",!@#&		\"Go To Line    ^+G\",!@#&		\"Re-Indent     ^+I\",!@#&		\"Set Syntax    ^+E\",!@#&		\"Start of Line ^+<\",!@#&		\"End of Line   ^+>\"!@#&	}, [4] = {\"Run\",!@#&		\"Run Program       ^+R\",!@#&		\"Run w/ Args ^+Shift+R\"!@#&	}!@#&}!@#&!@#&local shortcuts = {!@#&	-- File!@#&	[\"ctrl n\"] = \"New File  ^+N\",!@#&	[\"ctrl o\"] = \"Open File ^+O\",!@#&	[\"ctrl s\"] = \"Save File ^+S\",!@#&	[\"ctrl w\"] = \"Close     ^+W\",!@#&	[\"ctrl p\"] = \"Print     ^+P\",!@#&	[\"ctrl q\"] = \"Quit      ^+Q\",!@#&!@#&	-- Edit!@#&	[\"ctrl x\"] = \"Cut Line   ^+X\",!@#&	[\"ctrl c\"] = \"Copy Line  ^+C\",!@#&	[\"ctrl v\"] = \"Paste Line ^+V\",!@#&!@#&	-- Functions!@#&	[\"ctrl g\"] = \"Go To Line    ^+G\",!@#&	[\"ctrl i\"] = \"Re-Indent     ^+I\",!@#&	[\"ctrl e\"] = \"Set Syntax    ^+E\",!@#&	[\"ctrl 203\"] = \"Start of Line ^+<\",!@#&	[\"ctrl 205\"] = \"End of Line   ^+>\",!@#&!@#&	-- Run!@#&	[\"ctrl r\"] = \"Run Program       ^+R\",!@#&	[\"ctrl shift r\"] = \"Run w/ Args ^+Shift+R\"!@#&}!@#&!@#&local menuFunctions = {!@#&	-- File!@#&--	[\"About\"] = function() end,!@#&--	[\"Settings\"] = function() end,!@#&	[\"New File  ^+N\"] = function(path, lines) saveFile(path, lines) return \"new\" end,!@#&	[\"Open File ^+O\"] = function(path, lines) saveFile(path, lines) return \"open\" end,!@#&	[\"Save File ^+S\"] = function(path, lines) saveFile(path, lines) end,!@#&	[\"Close     ^+W\"] = function(path, lines) saveFile(path, lines) return \"menu\" end,!@#&	[\"Print     ^+P\"] = function(path, lines) saveFile(path, lines) return nil end,!@#&	[\"Quit      ^+Q\"] = function(path, lines) saveFile(path, lines) return \"exit\" end,!@#&!@#&	-- Edit!@#&	[\"Cut Line   ^+X\"] = function(path, lines, y)!@#&		clipboard = lines[y] table.remove(lines, y) return nil, lines end,!@#&	[\"Copy Line  ^+C\"] = function(path, lines, y) clipboard = lines[y] end,!@#&	[\"Paste Line ^+V\"] = function(path, lines, y)!@#&		if clipboard then table.insert(lines, y, clipboard) end return nil, lines end,!@#&	[\"Delete Line\"] = function(path, lines, y) table.remove(lines, y) return nil, lines end,!@#&	[\"Clear Line\"] = function(path, lines, y) lines[y] = \"\" return nil, lines, \"cursor\" end,!@#&!@#&	-- Functions!@#&	[\"Go To Line    ^+G\"] = function() return nil, \"go to\", goto() end,!@#&	[\"Re-Indent     ^+I\"] = function(path, lines)!@#&		local a = reindent(lines) saveFile(path, lines) return nil, a!@#&	end,!@#&	[\"Set Syntax    ^+E\"] = function(path, lines)!@#&		setsyntax()!@#&		if curLanguage == languages.brainfuck and lines[1] ~= \"-- Syntax: Brainfuck\" then!@#&			table.insert(lines, 1, \"-- Syntax: Brainfuck\")!@#&			return nil, lines!@#&		end!@#&	end,!@#&	[\"Start of Line ^+<\"] = function() os.queueEvent(\"key\", 199) end,!@#&	[\"End of Line   ^+>\"] = function() os.queueEvent(\"key\", 207) end,!@#&!@#&	-- Run!@#&	[\"Run Program       ^+R\"] = function(path, lines)!@#&		saveFile(path, lines)!@#&		return nil, run(path, lines, false)!@#&	end,!@#&	[\"Run w/ Args ^+Shift+R\"] = function(path, lines)!@#&		saveFile(path, lines)!@#&		return nil, run(path, lines, true)!@#&	end,!@#&}!@#&!@#&local function drawMenu(open)!@#&	term.setCursorPos(1, 1)!@#&	term.setTextColor(colors[theme.textColor])!@#&	term.setBackgroundColor(colors[theme.backgroundHighlight])!@#&	term.clearLine()!@#&	local curX = 0!@#&	for _, v in pairs(menu) do!@#&		term.setCursorPos(3 + curX, 1)!@#&		term.write(v[1])!@#&		curX = curX + v[1]:len() + 3!@#&	end!@#&!@#&	if open then!@#&		local it = {}!@#&		local x = 1!@#&		for _, v in pairs(menu) do!@#&			if open == v[1] then!@#&				it = v!@#&				break!@#&			end!@#&			x = x + v[1]:len() + 3!@#&		end!@#&		x = x + 1!@#&!@#&		local items = {}!@#&		for i = 2, #it do!@#&			table.insert(items, it[i])!@#&		end!@#&!@#&		local len = 1!@#&		for _, v in pairs(items) do if v:len() + 2 > len then len = v:len() + 2 end end!@#&!@#&		for i, v in ipairs(items) do!@#&			term.setCursorPos(x, i + 1)!@#&			term.write(string.rep(\" \", len))!@#&			term.setCursorPos(x + 1, i + 1)!@#&			term.write(v)!@#&		end!@#&		term.setCursorPos(x, #items + 2)!@#&		term.write(string.rep(\" \", len))!@#&		return items, len!@#&	end!@#&end!@#&!@#&local function triggerMenu(cx, cy)!@#&	-- Determine clicked menu!@#&	local curX = 0!@#&	local open = nil!@#&	for _, v in pairs(menu) do!@#&		if cx >= curX + 3 and cx <= curX + v[1]:len() + 2 then!@#&			open = v[1]!@#&			break!@#&		end!@#&		curX = curX + v[1]:len() + 3!@#&	end!@#&	local menux = curX + 2!@#&	if not open then return false end!@#&!@#&	-- Flash menu item!@#&	term.setCursorBlink(false)!@#&	term.setCursorPos(menux, 1)!@#&	term.setBackgroundColor(colors[theme.background])!@#&	term.write(string.rep(\" \", open:len() + 2))!@#&	term.setCursorPos(menux + 1, 1)!@#&	term.write(open)!@#&	sleep(0.1)!@#&	local items, len = drawMenu(open)!@#&!@#&	local ret = true!@#&!@#&	-- Pull events on menu!@#&	local ox, oy = term.getCursorPos()!@#&	while type(ret) ~= \"string\" do!@#&		local e, but, x, y = os.pullEvent()!@#&		if e == \"mouse_click\" then!@#&			-- If clicked outside menu!@#&			if x < menux - 1 or x > menux + len - 1 then break!@#&			elseif y > #items + 2 then break!@#&			elseif y == 1 then break end!@#&!@#&			for i, v in ipairs(items) do!@#&				if y == i + 1 and x >= menux and x <= menux + len - 2 then!@#&					-- Flash when clicked!@#&					term.setCursorPos(menux, y)!@#&					term.setBackgroundColor(colors[theme.background])!@#&					term.write(string.rep(\" \", len))!@#&					term.setCursorPos(menux + 1, y)!@#&					term.write(v)!@#&					sleep(0.1)!@#&					drawMenu(open)!@#&!@#&					-- Return item!@#&					ret = v!@#&					break!@#&				end!@#&			end!@#&		end!@#&	end!@#&!@#&	term.setCursorPos(ox, oy)!@#&	term.setCursorBlink(true)!@#&	return ret!@#&end!@#&!@#&!@#&--  -------- Editing!@#&!@#&local standardsCompletions = {!@#&	\"if%s+.+%s+then%s*$\",!@#&	\"for%s+.+%s+do%s*$\",!@#&	\"while%s+.+%s+do%s*$\",!@#&	\"repeat%s*$\",!@#&	\"function%s+[a-zA-Z_0-9]?\\(.*\\)%s*$\",!@#&	\"=%s*function%s*\\(.*\\)%s*$\",!@#&	\"else%s*$\",!@#&	\"elseif%s+.+%s+then%s*$\"!@#&}!@#&!@#&local liveCompletions = {!@#&	[\"(\"] = \")\",!@#&	[\"{\"] = \"}\",!@#&	[\"[\"] = \"]\",!@#&	[\"\\\"\"] = \"\\\"\",!@#&	[\"'\"] = \"'\",!@#&}!@#&!@#&local x, y = 0, 0!@#&local edw, edh = 0, h - 1!@#&local offx, offy = 0, 1!@#&local scrollx, scrolly = 0, 0!@#&local lines = {}!@#&local liveErr = curLanguage.parseError(nil)!@#&local displayCode = true!@#&local lastEventClock = os.clock()!@#&!@#&local function attemptToHighlight(line, regex, col)!@#&	local match = string.match(line, regex)!@#&	if match then!@#&		if type(col) == \"number\" then term.setTextColor(col)!@#&		elseif type(col) == \"function\" then term.setTextColor(col(match)) end!@#&		term.write(match)!@#&		term.setTextColor(colors[theme.textColor])!@#&		return line:sub(match:len() + 1, -1)!@#&	end!@#&	return nil!@#&end!@#&!@#&local function writeHighlighted(line)!@#&	if curLanguage == languages.lua then!@#&		while line:len() > 0 do	!@#&			line = attemptToHighlight(line, \"^%-%-%[%[.-%]%]\", colors[theme.comment]) or!@#&				attemptToHighlight(line, \"^%-%-.*\", colors[theme.comment]) or!@#&				attemptToHighlight(line, \"^\\\".*[^\\\\]\\\"\", colors[theme.string]) or!@#&				attemptToHighlight(line, \"^\\'.*[^\\\\]\\'\", colors[theme.string]) or!@#&				attemptToHighlight(line, \"^%[%[.-%]%]\", colors[theme.string]) or!@#&				attemptToHighlight(line, \"^[%w_]+\", function(match)!@#&					if curLanguage.keywords[match] then!@#&						return colors[theme[curLanguage.keywords[match]]]!@#&					end!@#&					return colors[theme.textColor]!@#&				end) or!@#&				attemptToHighlight(line, \"^[^%w_]\", colors[theme.textColor])!@#&		end!@#&	else term.write(line) end!@#&end!@#&!@#&local function draw()!@#&	-- Menu!@#&	term.setTextColor(colors[theme.textColor])!@#&	term.setBackgroundColor(colors[theme.editorBackground])!@#&	term.clear()!@#&	drawMenu()!@#&!@#&	-- Line numbers!@#&	offx, offy = tostring(#lines):len() + 1, 1!@#&	edw, edh = w - offx, h - 1!@#&!@#&	-- Draw text!@#&	for i = 1, edh do!@#&		local a = lines[scrolly + i]!@#&		if a then!@#&			local ln = string.rep(\" \", offx - 1 - tostring(scrolly + i):len()) .. tostring(scrolly + i) !@#&			local l = a:sub(scrollx + 1, edw + scrollx + 1)!@#&			ln = ln .. \":\"!@#&!@#&			if liveErr.line == scrolly + i then ln = string.rep(\" \", offx - 2) .. \"!:\" end!@#&!@#&			term.setCursorPos(1, i + offy)!@#&			term.setBackgroundColor(colors[theme.editorBackground])!@#&			if scrolly + i == y then!@#&				if scrolly + i == liveErr.line and os.clock() - lastEventClock > 3 then!@#&					term.setBackgroundColor(colors[theme.editorErrorHighlight])!@#&				else term.setBackgroundColor(colors[theme.editorLineHightlight]) end!@#&				term.clearLine()!@#&			elseif scrolly + i == liveErr.line then!@#&				term.setBackgroundColor(colors[theme.editorError])!@#&				term.clearLine()!@#&			end!@#&!@#&			term.setCursorPos(1 - scrollx + offx, i + offy)!@#&			if scrolly + i == y then!@#&				if scrolly + i == liveErr.line and os.clock() - lastEventClock > 3 then!@#&					term.setBackgroundColor(colors[theme.editorErrorHighlight])!@#&				else term.setBackgroundColor(colors[theme.editorLineHightlight]) end!@#&			elseif scrolly + i == liveErr.line then term.setBackgroundColor(colors[theme.editorError])!@#&			else term.setBackgroundColor(colors[theme.editorBackground]) end!@#&			if scrolly + i == liveErr.line then!@#&				if displayCode then term.write(a)!@#&				else term.write(liveErr.display) end!@#&			else writeHighlighted(a) end!@#&!@#&			term.setCursorPos(1, i + offy)!@#&			if scrolly + i == y then!@#&				if scrolly + i == liveErr.line and os.clock() - lastEventClock > 3 then!@#&					term.setBackgroundColor(colors[theme.editorError])!@#&				else term.setBackgroundColor(colors[theme.editorLineNumbersHighlight]) end!@#&			elseif scrolly + i == liveErr.line then!@#&				term.setBackgroundColor(colors[theme.editorErrorHighlight])!@#&			else term.setBackgroundColor(colors[theme.editorLineNumbers]) end!@#&			term.write(ln)!@#&		end!@#&	end!@#&	term.setCursorPos(x - scrollx + offx, y - scrolly + offy)!@#&end!@#&!@#&local function drawLine(...)!@#&	local ls = {...}!@#&	offx = tostring(#lines):len() + 1!@#&	for _, ly in pairs(ls) do!@#&		local a = lines[ly]!@#&		if a then!@#&			local ln = string.rep(\" \", offx - 1 - tostring(ly):len()) .. tostring(ly) !@#&			local l = a:sub(scrollx + 1, edw + scrollx + 1)!@#&			ln = ln .. \":\"!@#&!@#&			if liveErr.line == ly then ln = string.rep(\" \", offx - 2) .. \"!:\" end!@#&!@#&			term.setCursorPos(1, (ly - scrolly) + offy)!@#&			term.setBackgroundColor(colors[theme.editorBackground])!@#&			if ly == y then!@#&				if ly == liveErr.line and os.clock() - lastEventClock > 3 then!@#&					term.setBackgroundColor(colors[theme.editorErrorHighlight])!@#&				else term.setBackgroundColor(colors[theme.editorLineHightlight]) end!@#&			elseif ly == liveErr.line then!@#&				term.setBackgroundColor(colors[theme.editorError])!@#&			end!@#&			term.clearLine()!@#&!@#&			term.setCursorPos(1 - scrollx + offx, (ly - scrolly) + offy)!@#&			if ly == y then!@#&				if ly == liveErr.line and os.clock() - lastEventClock > 3 then!@#&					term.setBackgroundColor(colors[theme.editorErrorHighlight])!@#&				else term.setBackgroundColor(colors[theme.editorLineHightlight]) end!@#&			elseif ly == liveErr.line then term.setBackgroundColor(colors[theme.editorError])!@#&			else term.setBackgroundColor(colors[theme.editorBackground]) end!@#&			if ly == liveErr.line then!@#&				if displayCode then term.write(a)!@#&				else term.write(liveErr.display) end!@#&			else writeHighlighted(a) end!@#&!@#&			term.setCursorPos(1, (ly - scrolly) + offy)!@#&			if ly == y then!@#&				if ly == liveErr.line and os.clock() - lastEventClock > 3 then!@#&					term.setBackgroundColor(colors[theme.editorError])!@#&				else term.setBackgroundColor(colors[theme.editorLineNumbersHighlight]) end!@#&			elseif ly == liveErr.line then!@#&				term.setBackgroundColor(colors[theme.editorErrorHighlight])!@#&			else term.setBackgroundColor(colors[theme.editorLineNumbers]) end!@#&			term.write(ln)!@#&		end!@#&	end!@#&	term.setCursorPos(x - scrollx + offx, y - scrolly + offy)!@#&end!@#&!@#&local function cursorLoc(x, y, force)!@#&	local sx, sy = x - scrollx, y - scrolly!@#&	local redraw = false!@#&	if sx < 1 then!@#&		scrollx = x - 1!@#&		sx = 1!@#&		redraw = true!@#&	elseif sx > edw then!@#&		scrollx = x - edw!@#&		sx = edw!@#&		redraw = true!@#&	end if sy < 1 then!@#&		scrolly = y - 1!@#&		sy = 1!@#&		redraw = true!@#&	elseif sy > edh then!@#&		scrolly = y - edh!@#&		sy = edh!@#&		redraw = true!@#&	end if redraw or force then draw() end!@#&	term.setCursorPos(sx + offx, sy + offy)!@#&end!@#&!@#&local function executeMenuItem(a, path)!@#&	if type(a) == \"string\" and menuFunctions[a] then!@#&		local opt, nl, gtln = menuFunctions[a](path, lines, y)!@#&		if type(opt) == \"string\" then term.setCursorBlink(false) return opt end!@#&		if type(nl) == \"table\" then!@#&			if #lines < 1 then table.insert(lines, \"\") end!@#&			y = math.min(y, #lines)!@#&			x = math.min(x, lines[y]:len() + 1)!@#&			lines = nl!@#&		elseif type(nl) == \"string\" then!@#&			if nl == \"go to\" and gtln then!@#&				x, y = 1, math.min(#lines, gtln)!@#&				cursorLoc(x, y)!@#&			end!@#&		end!@#&	end!@#&	term.setCursorBlink(true)!@#&	draw()!@#&	term.setCursorPos(x - scrollx + offx, y - scrolly + offy)!@#&end!@#&!@#&local function edit(path)!@#&	-- Variables!@#&	x, y = 1, 1!@#&	offx, offy = 0, 1!@#&	scrollx, scrolly = 0, 0!@#&	lines = loadFile(path)!@#&	if not lines then return \"menu\" end!@#&!@#&	-- Enable brainfuck!@#&	if lines[1] == \"-- Syntax: Brainfuck\" then!@#&		curLanguage = languages.brainfuck!@#&	end!@#&!@#&	-- Clocks!@#&	local autosaveClock = os.clock()!@#&	local scrollClock = os.clock() -- To prevent redraw flicker!@#&	local liveErrorClock = os.clock()!@#&	local hasScrolled = false!@#&!@#&	-- Draw!@#&	draw()!@#&	term.setCursorPos(x + offx, y + offy)!@#&	term.setCursorBlink(true)!@#&	!@#&	-- Main loop!@#&	local tid = os.startTimer(3)!@#&	while true do!@#&		local e, key, cx, cy = os.pullEvent()!@#&		if e == \"key\" and allowEditorEvent then!@#&			if key == 200 and y > 1 then!@#&				-- Up!@#&				x, y = math.min(x, lines[y - 1]:len() + 1), y - 1!@#&				drawLine(y, y + 1)!@#&				cursorLoc(x, y)!@#&			elseif key == 208 and y < #lines then!@#&				-- Down!@#&				x, y = math.min(x, lines[y + 1]:len() + 1), y + 1!@#&				drawLine(y, y - 1)!@#&				cursorLoc(x, y)!@#&			elseif key == 203 and x > 1 then!@#&				-- Left!@#&				x = x - 1!@#&				local force = false!@#&				if y - scrolly + offy < offy + 1 then force = true end!@#&				cursorLoc(x, y, force)!@#&			elseif key == 205 and x < lines[y]:len() + 1 then!@#&				-- Right!@#&				x = x + 1!@#&				local force = false!@#&				if y - scrolly + offy < offy + 1 then force = true end!@#&				cursorLoc(x, y, force)!@#&			elseif (key == 28 or key == 156) and (displayCode and true or y + scrolly - 1 ==!@#&					liveErr.line) then!@#&				-- Enter!@#&				local f = nil!@#&				for _, v in pairs(standardsCompletions) do!@#&					if lines[y]:find(v) then f = v end!@#&				end!@#&!@#&				local _, spaces = lines[y]:find(\"^[ ]+\")!@#&				if not spaces then spaces = 0 end!@#&				if f then!@#&					table.insert(lines, y + 1, string.rep(\" \", spaces + 2))!@#&					if not f:find(\"else\", 1, true) and not f:find(\"elseif\", 1, true) then!@#&						table.insert(lines, y + 2, string.rep(\" \", spaces) .. !@#&							(f:find(\"repeat\", 1, true) and \"until \" or f:find(\"{\", 1, true) and \"}\" or !@#&							\"end\"))!@#&					end!@#&					x, y = spaces + 3, y + 1!@#&					cursorLoc(x, y, true)!@#&				else!@#&					local oldLine = lines[y]!@#&!@#&					lines[y] = lines[y]:sub(1, x - 1)!@#&					table.insert(lines, y + 1, string.rep(\" \", spaces) .. oldLine:sub(x, -1))!@#&!@#&					x, y = spaces + 1, y + 1!@#&					cursorLoc(x, y, true)!@#&				end!@#&			elseif key == 14 and (displayCode and true or y + scrolly - 1 == liveErr.line) then!@#&				-- Backspace!@#&				if x > 1 then!@#&					local f = false!@#&					for k, v in pairs(liveCompletions) do!@#&						if lines[y]:sub(x - 1, x - 1) == k then f = true end!@#&					end!@#&!@#&					lines[y] = lines[y]:sub(1, x - 2) .. lines[y]:sub(x + (f and 1 or 0), -1)!@#&					drawLine(y)!@#&					x = x - 1!@#&					cursorLoc(x, y)!@#&				elseif y > 1 then!@#&					local prevLen = lines[y - 1]:len() + 1!@#&					lines[y - 1] = lines[y - 1] .. lines[y]!@#&					table.remove(lines, y)!@#&					x, y = prevLen, y - 1!@#&					cursorLoc(x, y, true)!@#&				end!@#&			elseif key == 199 then!@#&				-- Home!@#&				x = 1!@#&				local force = false!@#&				if y - scrolly + offy < offy + 1 then force = true end!@#&				cursorLoc(x, y, force)!@#&			elseif key == 207 then!@#&				-- End!@#&				x = lines[y]:len() + 1!@#&				local force = false!@#&				if y - scrolly + offy < offy + 1 then force = true end!@#&				cursorLoc(x, y, force)!@#&			elseif key == 211 and (displayCode and true or y + scrolly - 1 == liveErr.line) then!@#&				-- Forward Delete!@#&				if x < lines[y]:len() + 1 then!@#&					lines[y] = lines[y]:sub(1, x - 1) .. lines[y]:sub(x + 1)!@#&					local force = false!@#&					if y - scrolly + offy < offy + 1 then force = true end!@#&					drawLine(y)!@#&					cursorLoc(x, y, force)!@#&				elseif y < #lines then!@#&					lines[y] = lines[y] .. lines[y + 1]!@#&					table.remove(lines, y + 1)!@#&					draw()!@#&					cursorLoc(x, y)!@#&				end!@#&			elseif key == 15 and (displayCode and true or y + scrolly - 1 == liveErr.line) then!@#&				-- Tab!@#&				lines[y] = string.rep(\" \", tabWidth) .. lines[y]!@#&				x = x + 2!@#&				local force = false!@#&				if y - scrolly + offy < offy + 1 then force = true end!@#&				drawLine(y)!@#&				cursorLoc(x, y, force)!@#&			elseif key == 201 then!@#&				-- Page up!@#&				y = math.min(math.max(y - edh, 1), #lines)!@#&				x = math.min(lines[y]:len() + 1, x)!@#&				cursorLoc(x, y, true)!@#&			elseif key == 209 then!@#&				-- Page down!@#&				y = math.min(math.max(y + edh, 1), #lines)!@#&				x = math.min(lines[y]:len() + 1, x)!@#&				cursorLoc(x, y, true)!@#&			end!@#&		elseif e == \"char\" and allowEditorEvent and (displayCode and true or !@#&				y + scrolly - 1 == liveErr.line) then!@#&			local shouldIgnore = false!@#&			for k, v in pairs(liveCompletions) do!@#&				if key == v and lines[y]:find(k, 1, true) and lines[y]:sub(x, x) == v then!@#&					shouldIgnore = true!@#&				end!@#&			end!@#&!@#&			local addOne = false!@#&			if not shouldIgnore then!@#&				for k, v in pairs(liveCompletions) do!@#&					if key == k and lines[y]:sub(x, x) ~= k then key = key .. v addOne = true end!@#&				end!@#&				lines[y] = lines[y]:sub(1, x - 1) .. key .. lines[y]:sub(x, -1)!@#&			end!@#&!@#&			x = x + (addOne and 1 or key:len())!@#&			local force = false!@#&			if y - scrolly + offy < offy + 1 then force = true end!@#&			drawLine(y)!@#&			cursorLoc(x, y, force)!@#&		elseif e == \"mouse_click\" and key == 1 then!@#&			if cy > 1 then!@#&				if cx <= offx and cy - offy == liveErr.line - scrolly then!@#&					displayCode = not displayCode!@#&					drawLine(liveErr.line)!@#&				else!@#&					local oldy = y!@#&					y = math.min(math.max(scrolly + cy - offy, 1), #lines)!@#&					x = math.min(math.max(scrollx + cx - offx, 1), lines[y]:len() + 1)!@#&					if oldy ~= y then drawLine(oldy, y) end!@#&					cursorLoc(x, y)!@#&				end!@#&			else!@#&				local a = triggerMenu(cx, cy)!@#&				if a then!@#&					local opt = executeMenuItem(a, path)!@#&					if opt then return opt end!@#&				end!@#&			end!@#&		elseif e == \"shortcut\" then!@#&			local a = shortcuts[key .. \" \" .. cx]!@#&			if a then!@#&				local parent = nil!@#&				local curx = 0!@#&				for i, mv in ipairs(menu) do!@#&					for _, iv in pairs(mv) do!@#&						if iv == a then!@#&							parent = menu[i][1]!@#&							break!@#&						end!@#&					end!@#&					if parent then break end!@#&					curx = curx + mv[1]:len() + 3!@#&				end!@#&				local menux = curx + 2!@#&!@#&				-- Flash menu item!@#&				term.setCursorBlink(false)!@#&				term.setCursorPos(menux, 1)!@#&				term.setBackgroundColor(colors[theme.background])!@#&				term.write(string.rep(\" \", parent:len() + 2))!@#&				term.setCursorPos(menux + 1, 1)!@#&				term.write(parent)!@#&				sleep(0.1)!@#&				drawMenu()!@#&!@#&				-- Execute item!@#&				local opt = executeMenuItem(a, path)!@#&				if opt then return opt end!@#&			end!@#&		elseif e == \"mouse_scroll\" then!@#&			if key == -1 and scrolly > 0 then!@#&				scrolly = scrolly - 1!@#&				if os.clock() - scrollClock > 0.0005 then!@#&					draw()!@#&					term.setCursorPos(x - scrollx + offx, y - scrolly + offy)!@#&				end!@#&				scrollClock = os.clock()!@#&				hasScrolled = true!@#&			elseif key == 1 and scrolly < #lines - edh then!@#&				scrolly = scrolly + 1!@#&				if os.clock() - scrollClock > 0.0005 then!@#&					draw()!@#&					term.setCursorPos(x - scrollx + offx, y - scrolly + offy)!@#&				end!@#&				scrollClock = os.clock()!@#&				hasScrolled = true!@#&			end!@#&		elseif e == \"timer\" and key == tid then!@#&			drawLine(y)!@#&			tid = os.startTimer(3)!@#&		end!@#&!@#&		-- Draw!@#&		if hasScrolled and os.clock() - scrollClock > 0.1 then!@#&			draw()!@#&			term.setCursorPos(x - scrollx + offx, y - scrolly + offy)!@#&			hasScrolled = false!@#&		end!@#&!@#&		-- Autosave!@#&		if os.clock() - autosaveClock > autosaveInterval then!@#&			saveFile(path, lines)!@#&			autosaveClock = os.clock()!@#&		end!@#&!@#&		-- Errors!@#&		if os.clock() - liveErrorClock > 1 then!@#&			local prevLiveErr = liveErr!@#&			liveErr = curLanguage.parseError(nil)!@#&			local code = \"\"!@#&			for _, v in pairs(lines) do code = code .. v .. \"\\n\" end!@#&!@#&			liveErr = curLanguage.getCompilerErrors(code)!@#&			liveErr.line = math.min(liveErr.line - 2, #lines)!@#&			if liveErr ~= prevLiveErr then draw() end!@#&			liveErrorClock = os.clock()!@#&		end!@#&	end!@#&!@#&	return \"menu\"!@#&end!@#&!@#&!@#&--  -------- Open File!@#&!@#&local function newFile()!@#&	local wid = w - 13!@#&!@#&	-- Get name!@#&	title(\"Lua IDE - New File\")!@#&	local name = centerRead(wid, \"/\")!@#&	if not name or name == \"\" then return \"menu\" end!@#&	name = \"/\" .. name!@#&!@#&	-- Clear!@#&	title(\"Lua IDE - New File\")!@#&	term.setTextColor(colors[theme.textColor])!@#&	term.setBackgroundColor(colors[theme.promptHighlight])!@#&	for i = 8, 10 do!@#&		term.setCursorPos(w/2 - wid/2, i)!@#&		term.write(string.rep(\" \", wid))!@#&	end!@#&	term.setCursorPos(1, 9)!@#&	if fs.isDir(name) then!@#&		centerPrint(\"Cannot Edit a Directory!\")!@#&		sleep(1.6)!@#&		return \"menu\"!@#&	elseif fs.exists(name) then!@#&		centerPrint(\"File Already Exists!\")!@#&		local opt = prompt({{\"Open\", w/2 - 9, 14}, {\"Cancel\", w/2 + 2, 14}}, \"horizontal\")!@#&		if opt == \"Open\" then return \"edit\", name!@#&		elseif opt == \"Cancel\" then return \"menu\" end!@#&	else return \"edit\", name end!@#&end!@#&!@#&local function openFile()!@#&	local wid = w - 13!@#&!@#&	-- Get name!@#&	title(\"Lua IDE - Open File\")!@#&	local name = centerRead(wid, \"/\")!@#&	if not name or name == \"\" then return \"menu\" end!@#&	name = \"/\" .. name!@#&!@#&	-- Clear!@#&	title(\"Lua IDE - New File\")!@#&	term.setTextColor(colors[theme.textColor])!@#&	term.setBackgroundColor(colors[theme.promptHighlight])!@#&	for i = 8, 10 do!@#&		term.setCursorPos(w/2 - wid/2, i)!@#&		term.write(string.rep(\" \", wid))!@#&	end!@#&	term.setCursorPos(1, 9)!@#&	if fs.isDir(name) then!@#&		centerPrint(\"Cannot Open a Directory!\")!@#&		sleep(1.6)!@#&		return \"menu\"!@#&	elseif not fs.exists(name) then!@#&		centerPrint(\"File Doesn't Exist!\")!@#&		local opt = prompt({{\"Create\", w/2 - 11, 14}, {\"Cancel\", w/2 + 2, 14}}, \"horizontal\")!@#&		if opt == \"Create\" then return \"edit\", name!@#&		elseif opt == \"Cancel\" then return \"menu\" end!@#&	else return \"edit\", name end!@#&end!@#&!@#&!@#&--  -------- Settings!@#&!@#&local function update()!@#&	local function draw(status)!@#&		title(\"LuaIDE - Update\")!@#&		term.setBackgroundColor(colors[theme.prompt])!@#&		term.setTextColor(colors[theme.textColor])!@#&		for i = 8, 10 do!@#&			term.setCursorPos(w/2 - (status:len() + 4), i)!@#&			write(string.rep(\" \", status:len() + 4))!@#&		end!@#&		term.setCursorPos(w/2 - (status:len() + 4), 9)!@#&		term.write(\" - \" .. status .. \" \")!@#&!@#&		term.setBackgroundColor(colors[theme.errHighlight])!@#&		for i = 8, 10 do!@#&			term.setCursorPos(w/2 + 2, i)!@#&			term.write(string.rep(\" \", 10))!@#&		end!@#&		term.setCursorPos(w/2 + 2, 9)!@#&		term.write(\" > Cancel \")!@#&	end!@#&!@#&	if not http then!@#&		draw(\"HTTP API Disabled!\")!@#&		sleep(1.6)!@#&		return \"settings\"!@#&	end!@#&!@#&	draw(\"Updating...\")!@#&	local tID = os.startTimer(10)!@#&	http.request(updateURL)!@#&	while true do!@#&		local e, but, x, y = os.pullEvent()!@#&		if (e == \"key\" and but == 28) or!@#&				(e == \"mouse_click\" and x >= w/2 + 2 and x <= w/2 + 12 and y == 9) then!@#&			draw(\"Cancelled\")!@#&			sleep(1.6)!@#&			break!@#&		elseif e == \"http_success\" and but == updateURL then!@#&			local new = x.readAll()!@#&			local curf = io.open(ideLocation, \"r\")!@#&			local cur = curf:read(\"*a\")!@#&			curf:close()!@#&!@#&			if cur ~= new then!@#&				draw(\"Update Found\")!@#&				sleep(1.6)!@#&				local f = io.open(ideLocation, \"w\")!@#&				f:write(new)!@#&				f:close()!@#&!@#&				draw(\"Click to Exit\")!@#&				while true do!@#&					local e = os.pullEvent()!@#&					if e == \"mouse_click\" or (not isAdvanced() and e == \"key\") then break end!@#&				end!@#&				return \"exit\"!@#&			else!@#&				draw(\"No Updates Found!\")!@#&				sleep(1.6)!@#&				break!@#&			end!@#&		elseif e == \"http_failure\" or (e == \"timer\" and but == tID) then!@#&			draw(\"Update Failed!\")!@#&			sleep(1.6)!@#&			break!@#&		end!@#&	end!@#&!@#&	return \"settings\"!@#&end!@#&!@#&local function changeTheme()!@#&	title(\"LuaIDE - Theme\")!@#&!@#&	if isAdvanced() then!@#&		local disThemes = {\"Back\"}!@#&		for _, v in pairs(availableThemes) do table.insert(disThemes, v[1]) end!@#&		local t = scrollingPrompt(disThemes)!@#&		local url = nil!@#&		for _, v in pairs(availableThemes) do if v[1] == t then url = v[2] end end!@#&!@#&		if not url then return \"settings\" end!@#&		if t == \"Dawn (Default)\" then!@#&			term.setBackgroundColor(colors[theme.backgroundHighlight])!@#&			term.setCursorPos(3, 3)!@#&			term.clearLine()!@#&			term.write(\"LuaIDE - Loaded Theme!\")!@#&			sleep(1.6)!@#&!@#&			fs.delete(themeLocation)!@#&			theme = defaultTheme!@#&			return \"menu\"!@#&		end!@#&!@#&		term.setBackgroundColor(colors[theme.backgroundHighlight])!@#&		term.setCursorPos(3, 3)!@#&		term.clearLine()!@#&		term.write(\"LuaIDE - Downloading...\")!@#&!@#&		fs.delete(\"/.LuaIDE_temp_theme_file\")!@#&		download(url, \"/.LuaIDE_temp_theme_file\")!@#&		local a = loadTheme(\"/.LuaIDE_temp_theme_file\")!@#&!@#&		term.setCursorPos(3, 3)!@#&		term.clearLine()!@#&		if a then!@#&			term.write(\"LuaIDE - Loaded Theme!\")!@#&			fs.delete(themeLocation)!@#&			fs.move(\"/.LuaIDE_temp_theme_file\", themeLocation)!@#&			theme = a!@#&			sleep(1.6)!@#&			return \"menu\"!@#&		end!@#&		!@#&		term.write(\"LuaIDE - Could Not Load Theme!\")!@#&		fs.delete(\"/.LuaIDE_temp_theme_file\")!@#&		sleep(1.6)!@#&		return \"settings\"!@#&	else!@#&		term.setCursorPos(1, 8)!@#&		centerPrint(\"Themes are not available on\")!@#&		centerPrint(\"normal computers!\")!@#&	end!@#&end!@#&!@#&local function settings()!@#&	title(\"LuaIDE - Settings\")!@#&!@#&	local opt = prompt({{\"Change Theme\", w/2 - 17, 8}, {\"Return to Menu\", w/2 - 22, 13},!@#&		{\"Check for Updates\", w/2 + 2, 8}, {\"Exit IDE\", w/2 + 2, 13, bg = colors[theme.err], !@#&		highlight = colors[theme.errHighlight]}}, \"vertical\", true)!@#&	if opt == \"Change Theme\" then return changeTheme()!@#&	elseif opt == \"Check for Updates\" then return update()!@#&	elseif opt == \"Return to Menu\" then return \"menu\"!@#&	elseif opt == \"Exit IDE\" then return \"exit\" end!@#&end!@#&!@#&!@#&--  -------- Menu!@#&!@#&local function menu()!@#&	title(\"Welcome to LuaIDE \" .. version)!@#&!@#&	local opt = prompt({{\"New File\", w/2 - 13, 8}, {\"Open File\", w/2 - 14, 13},!@#&		{\"Settings\", w/2 + 2, 8}, {\"Exit IDE\", w/2 + 2, 13, bg = colors[theme.err],!@#&		highlight = colors[theme.errHighlight]}}, \"vertical\", true)!@#&	if opt == \"New File\" then return \"new\"!@#&	elseif opt == \"Open File\" then return \"open\"!@#&	elseif opt == \"Settings\" then return \"settings\"!@#&	elseif opt == \"Exit IDE\" then return \"exit\" end!@#&end!@#&!@#&!@#&--  -------- Main!@#&!@#&local function main(arguments)!@#&	local opt, data = \"menu\", nil!@#&!@#&	-- Check arguments!@#&	if type(arguments) == \"table\" and #arguments > 0 then!@#&		local f = \"/\" .. shell.resolve(arguments[1])!@#&		if fs.isDir(f) then print(\"Cannot edit a directory.\") end!@#&		opt, data = \"edit\", f!@#&	end!@#&!@#&	-- Main run loop!@#&	while true do!@#&		-- Menu!@#&		if opt == \"menu\" then opt = menu() end!@#&!@#&		-- Other!@#&		if opt == \"new\" then opt, data = newFile()!@#&		elseif opt == \"open\" then opt, data = openFile()!@#&		elseif opt == \"settings\" then opt = settings()!@#&		end if opt == \"exit\" then break end!@#&!@#&		-- Edit!@#&		if opt == \"edit\" and data then opt = edit(data) end!@#&	end!@#&end!@#&!@#&-- Load Theme!@#&if fs.exists(themeLocation) then theme = loadTheme(themeLocation) end!@#&if not theme and isAdvanced() then theme = defaultTheme!@#&elseif not theme then theme = normalTheme end!@#&!@#&-- Run!@#&local _, err = pcall(function()!@#&	parallel.waitForAny(function() main(args) end, monitorKeyboardShortcuts)!@#&end)!@#&!@#&-- Catch errors!@#&if err and not err:find(\"Terminated\") then!@#&	term.setCursorBlink(false)!@#&	title(\"LuaIDE - Crash! D:\")!@#&!@#&	term.setBackgroundColor(colors[theme.err])!@#&	for i = 6, 8 do!@#&		term.setCursorPos(5, i)!@#&		term.write(string.rep(\" \", 36))!@#&	end!@#&	term.setCursorPos(6, 7)!@#&	term.write(\"LuaIDE Has Crashed! D:\")!@#&!@#&	term.setBackgroundColor(colors[theme.background])!@#&	term.setCursorPos(2, 10)!@#&	print(err)!@#&!@#&	term.setBackgroundColor(colors[theme.prompt])!@#&	local _, cy = term.getCursorPos()!@#&	for i = cy + 1, cy + 4 do!@#&		term.setCursorPos(5, i)!@#&		term.write(string.rep(\" \", 36))!@#&	end!@#&	term.setCursorPos(6, cy + 2)!@#&	term.write(\"Please report this error to\")!@#&	term.setCursorPos(6, cy + 3)!@#&	term.write(\"GravityScore! \")!@#&	!@#&	term.setBackgroundColor(colors[theme.background])!@#&	if isAdvanced() then centerPrint(\"Click to Exit...\", h - 1)!@#&	else centerPrint(\"Press Any Key to Exit...\", h - 1) end!@#&	while true do!@#&		local e = os.pullEvent()!@#&		if e == \"mouse_click\" or (not isAdvanced() and e == \"key\") then break end!@#&	end!@#&!@#&	-- Prevent key from being shown!@#&	os.queueEvent(event_distract)!@#&	os.pullEvent()!@#&end!@#&!@#&-- Exit!@#&term.setBackgroundColor(colors.black)!@#&term.setTextColor(colors.white)!@#&term.clear()!@#&term.setCursorPos(1, 1)!@#&centerPrint(\"Thank You for Using Lua IDE \" .. version)!@#&centerPrint(\"Made by GravityScore\")",["filebrowser"]="--[[!@#&		Mouse File Browser!@#&		by:!@#&			Stiepen irc(Kilobyte)!@#&			Cruor!@#&			BigSHinyToys!@#&		!@#&		note: send link to nightin9ale on CC forums!@#&--]]!@#&!@#&local tArgs = {...}!@#&local ver = \"1.4\"!@#&local sTitle = \"File Browser\"!@#&local bugTest, norun, dir, showAll!@#&local _tArgs = {}!@#&local config = \"mouse.cfg\"!@#&!@#&local temp!@#&if shell and shell.getRunningProgram then!@#&	temp = shell.getRunningProgram()!@#&end!@#&!@#&temp = temp or \"/bla\"!@#&local localPath = string.sub(temp,1,#temp-string.len(fs.getName(temp)))!@#&temp = nil -- just because not needed!@#&!@#&-- load config file!@#&!@#&local configSet = {}!@#&local cnf = {}!@#&!@#&if fs.exists(localPath..\"/\"..config) then!@#&	local file = fs.open(localPath..\"/\"..config,\"r\")!@#&	if file then!@#&		local item = file.readLine()!@#&		while item do!@#&			table.insert(cnf,item)!@#&			item = file.readLine()!@#&		end!@#&		file.close()!@#&	end	!@#&end!@#&!@#&for i = 1,10 do!@#&	local test,data = pcall(textutils.unserialize,cnf[i])!@#&	if test then!@#&		configSet[i] = data!@#&	else!@#&		configSet[i] = nil!@#&	end!@#&end!@#&cnf = nil!@#&!@#&-- color configuration work in progress!@#&local titleBar = configSet[1] or {txt = colors.black,back = colors.blue}!@#&local addressBar = configSet[2] or {txt = colors.black,back = colors.lightGray}!@#&local itemWindo = configSet[3] or {txt = colors.black,back = colors.cyan}!@#&local rcmList = configSet[4] or {txt = colors.black,back = colors.lightGray} -- rcm = Right Click Menu List!@#&local rcmTitle = configSet[5] or {txt = colors.black,back = colors.blue}!@#&local dialogTitle = configSet[6] or {txt = colors.black,back = colors.blue}!@#&local dialogWindo = configSet[7] or {txt = colors.black,back = colors.white}!@#&local scrollCol = configSet[8] or {off = colors.gray, button = colors.gray,back = colors.lightGray}!@#&!@#&local tIcons = configSet[9] or {!@#&	back = {tCol = \"lightGray\",bCol = \"blue\",txt = \" < \"},!@#&	disk = {tCol = \"lime\",bCol = \"green\",txt = \"[*]\"},!@#&	audio = {tCol = \"yellow\",bCol = \"red\",txt = \"(o)\"},!@#&	folder = {tCol = \"lightGray\",bCol = \"blue\",txt = \"[=]\"},!@#&	file = {tCol = nil ,bCol = nil ,txt = nil}!@#&}!@#&!@#&local customLaunch = configSet[10] or {!@#&	[\"Edit\"] = \"rom/programs/edit\",!@#&	[\"Paint\"] = \"rom/programs/color/paint\"!@#&}!@#&!@#&local function saveCFG(overWrite)!@#&	if not fs.exists(localPath..\"/\"..config) or overWrite then!@#&		local cnf = {}!@#&		local file = fs.open(localPath..\"/\"..config,\"w\")!@#&		if file then!@#&			file.write(textutils.serialize(titleBar)..\"\\n\")!@#&			file.write(textutils.serialize(addressBar)..\"\\n\")!@#&			file.write(textutils.serialize(itemWindo)..\"\\n\")!@#&			file.write(textutils.serialize(rcmList)..\"\\n\")!@#&			file.write(textutils.serialize(rcmTitle)..\"\\n\")!@#&			file.write(textutils.serialize(dialogTitle)..\"\\n\")!@#&			file.write(textutils.serialize(dialogWindo)..\"\\n\")!@#&			file.write(textutils.serialize(scrollCol)..\"\\n\")!@#&			file.write(textutils.serialize(tIcons)..\"\\n\")!@#&			file.write(textutils.serialize(customLaunch)..\"\\n\")!@#&			file.close()!@#&		elseif overWrite then!@#&		end!@#&	end!@#&end!@#&!@#&saveCFG()!@#&!@#&-- end configuration!@#&!@#&local function help()!@#&	print([[Usage: browser [-d] [-h] [-a] [-u] [--debug] [--help] [--dir <dir>] [--all] [--update]!@#&--debug or -d: enable debug mode!@#&--help or -h: display this screen!@#&--dir: define initial directory!@#&--all or -a: show hidden files!@#&--update -u: update]])!@#&end!@#&!@#&local function inBouwndry(clickX,clickY,boxX,boxY,width,hight)!@#&	return ( clickX >= boxX and clickX < boxX + width and clickY >= boxY and clickY < boxY + hight )!@#&end!@#&!@#&local function update()!@#&	print(\"Checking for Updates\")!@#&	local isHTTP = false!@#&	local response!@#&	if http then!@#&		isHTTP = true!@#&		print(\"http on\")!@#&		response = http.get(\"http://pastebin.com/raw.php?i=rLbnyM1U\")!@#&	end!@#&	local flag = false!@#&	local isNewFlag = false!@#&	local newVerID!@#&	if response and isHTTP then!@#&		print(\"recived\")!@#&		local sInfo = response.readLine()!@#&		print(sInfo)!@#&		while sInfo do!@#&			print(sInfo)!@#&			if flag then!@#&				if sInfo == ver then!@#&					print(\"Mouse File Browser is up to date\")!@#&					break!@#&				else!@#&					newVerID = sInfo!@#&					flag = false!@#&					isNewFlag = true!@#&				end!@#&			elseif sInfo == sTitle then!@#&				flag = true!@#&			elseif isNewFlag then!@#&				isNewFlag = sInfo!@#&				response.close()!@#&				break!@#&			end!@#&			sInfo = response.readLine()!@#&		end!@#&		if isNewFlag then!@#&			print(\"New vershion avalible \"..newVerID)!@#&			print('downloading to \\Browser')!@#&			if fs.exists(\"Browser\") then!@#&				write(\"Browser exists OverWrite Browser Y/N : \")!@#&				local input = string.lower(read())!@#&				while input ~= \"y\" and input ~= \"n\" do!@#&					print(\"y or n required\")!@#&					input = string.lower(read())!@#&				end!@#&				if input == \"y\" then!@#&					print(\"Over Writeing Browser\")!@#&					print(\"Downloading new File\")!@#&					local response = http.get(\"http://pastebin.com/raw.php?i=\"..isNewFlag)!@#&					if response then!@#&						print(\"file downloaded\")!@#&						print(\"installing\")!@#&						fs.delete(\"Browser\")!@#&						local handel = fs.open(\"Browser\",\"w\")!@#&						if handel then!@#&							handel.write(response.readAll())!@#&							handel.close()!@#&							print(\"Update Complete\")!@#&						end!@#&						response.close()!@#&					end!@#&				else!@#&					print(\"Update aborted\")!@#&				end!@#&			else!@#&				print(\"Downloading new File\")!@#&				local response = http.get(\"http://pastebin.com/raw.php?i=\"..isNewFlag)!@#&				if response then!@#&					print(\"file downloaded\")!@#&					print(\"installing\")!@#&					local handel = fs.open(\"Browser\",\"w\")!@#&					if handel then!@#&						handel.write(response.readAll())!@#&						handel.close()!@#&						print(\"Update Complete\")!@#&					end!@#&					response.close()!@#&				end!@#&			end!@#&		end!@#&	elseif isHTTP then!@#&		print(\"Error downloading update file Please contact BigSHinyToys on the CC forums\")!@#&		print(\"http://www.computercraft.info/forums2/index.php?/topic/5509-advanced-computer-mouse-file-browser/\")!@#&	elseif not isHTTP then!@#&		print(\"HTTP API is turned off\")!@#&		print(\"Access Computer Craft Configer and change line\")!@#&		print([[enableapi_http {!@#&# Enable the \"http\" API on Computers!@#&general=false!@#&}!@#&TO THIS :!@#&enableapi_http {!@#&# Enable the \"http\" API on Computers!@#&general=true!@#&}]])!@#&	end!@#&	notCMD = false!@#&	norun = true!@#&end!@#&!@#&for a = 1, #tArgs do!@#&	if tArgs[a]:sub(1,2) == \"--\" then!@#&		local cmd = tArgs[a]:sub(3):lower()!@#&		if cmd == \"debug\" then!@#&			bugTest = true!@#&		elseif cmd == \"help\" then!@#&			help()!@#&			norun = true!@#&		elseif cmd == \"dir\" then!@#&			dir = tArgs[a+1]!@#&			a = a + 1!@#&		elseif cmd == \"all\" then!@#&			showAll = true!@#&		elseif cmd == \"update\" then!@#&			update()!@#&		end!@#&	elseif tArgs[a]:sub(1,1) == \"-\" then!@#&		for b = 2, #tArgs[a] do!@#&			cmd = tArgs[a]:sub(b, b)!@#&			if cmd == \"d\" then!@#&				bugTest = true!@#&			elseif cmd == \"h\" then!@#&				help()!@#&				norun = true!@#&			elseif cmd == \"p\" then!@#&				dir = tArgs[a+1]!@#&				a = a + 1!@#&			elseif cmd == \"a\" then!@#&				showAll = true!@#&			elseif cmd == \"u\" then!@#&				update()!@#&			end!@#&		end!@#&	else!@#&		table.insert(_tArgs, tArgs[a])!@#&	end!@#&end!@#&!@#&if (not dir) and shell and shell.dir then!@#&	dir = shell.dir()!@#&end!@#&!@#&if dir and shell and shell.resolve then!@#&	dir = shell.resolve(dir)!@#&end!@#&!@#&dir = dir or \"/\"!@#&!@#&if bugTest then -- this is that the var is for testing!@#&	print(\"Dir: \"..dir)!@#&	os.startTimer(4)!@#&	os.pullEvent()!@#&end!@#&!@#&local function clear()!@#&	term.setBackgroundColor(colors.black)!@#&	term.setTextColor(colors.white)!@#&	term.clear()!@#&	term.setCursorBlink(false)!@#&	term.setCursorPos(1,1)!@#&end!@#&!@#&--[[!@#&		Code thanks to Cruor !@#&		http://www.computercraft.info/forums2/index.php?/topic/5802-support-for-shell/!@#&]]--!@#&!@#&local function fixArgs(...)!@#&	local tReturn={}!@#&	local str=table.concat({...},\" \")!@#&	local sMatch!@#&	while str and #str>0 do!@#&		if string.sub(str,1,1)==\"\\\"\" then!@#&			sMatch, str=string.match(str, \"\\\"(.-)\\\"%s*(.*)\")!@#&		else!@#&			sMatch, str=string.match(str, \"(%S+)%s*(.*)\")!@#&		end!@#&		table.insert(tReturn,sMatch)!@#&	end!@#&	return tReturn!@#&end!@#&!@#&--[[ end Cruor function ]]--!@#&!@#&!@#&-- modified read made to play nice with coroutines!@#&!@#&local function readMOD( _sReplaceChar, _tHistory,_wdth)!@#&	local sLine = \"\"!@#&	term.setCursorBlink( true )!@#&!@#&	local nHistoryPos = nil!@#&	local nPos = 0!@#&    if _sReplaceChar then!@#&		_sReplaceChar = string.sub( _sReplaceChar, 1, 1 )!@#&	end!@#&	!@#&	local sx, sy = term.getCursorPos()	!@#&!@#&	local w, h = term.getSize()!@#&	if _wdth and type(_wdth) == \"number\" then!@#&		w = sx + _wdth - 1!@#&	end!@#&	!@#&	local function redraw( _sCustomReplaceChar )!@#&		local nScroll = 0!@#&		if sx + nPos >= w then!@#&			nScroll = (sx + nPos) - w!@#&		end!@#&			!@#&		term.setCursorPos( sx + _wdth - 1, sy )!@#&		term.write(\" \")!@#&		term.setCursorPos( sx, sy )!@#&		local sReplace = _sCustomReplaceChar or _sReplaceChar!@#&		if sReplace then!@#&			term.write( string.rep(sReplace,_wdth) )!@#&		else!@#&			term.write( string.sub( sLine, nScroll + 1 ,nScroll + _wdth) )!@#&		end!@#&		term.setCursorPos( sx + nPos - nScroll, sy )!@#&	end!@#&	!@#&	while true do!@#&		local sEvent, param = os.pullEvent()!@#&		if sEvent == \"char\" then!@#&			sLine = string.sub( sLine, 1, nPos ) .. param .. string.sub( sLine, nPos + 1 )!@#&			nPos = nPos + 1!@#&			redraw()!@#&			!@#&		elseif sEvent == \"key\" then!@#&			!@#&			if param == keys.left then!@#&				-- Left!@#&				if nPos > 0 then!@#&					nPos = nPos - 1!@#&					redraw()!@#&				end!@#&				!@#&			elseif param == keys.right then!@#&				-- Right				!@#&				if nPos < string.len(sLine) then!@#&					nPos = nPos + 1!@#&					redraw()!@#&				end!@#&			!@#&			elseif param == keys.up or param == keys.down then!@#&                -- Up or down!@#&				if _tHistory then!@#&					redraw(\" \");!@#&					if param == keys.up then!@#&						-- Up!@#&						if nHistoryPos == nil then!@#&							if #_tHistory > 0 then!@#&								nHistoryPos = #_tHistory!@#&							end!@#&						elseif nHistoryPos > 1 then!@#&							nHistoryPos = nHistoryPos - 1!@#&						end!@#&					else!@#&						-- Down!@#&						if nHistoryPos == #_tHistory then!@#&							nHistoryPos = nil!@#&						elseif nHistoryPos ~= nil then!@#&							nHistoryPos = nHistoryPos + 1!@#&						end						!@#&					end!@#&					!@#&					if nHistoryPos then!@#&                    	sLine = _tHistory[nHistoryPos]!@#&                    	nPos = string.len( sLine ) !@#&                    else!@#&						sLine = \"\"!@#&						nPos = 0!@#&					end!@#&					redraw()!@#&                end!@#&			elseif param == keys.backspace then!@#&				-- Backspace!@#&				if nPos > 0 then!@#&					redraw(\" \");!@#&					sLine = string.sub( sLine, 1, nPos - 1 ) .. string.sub( sLine, nPos + 1 )!@#&					nPos = nPos - 1					!@#&					redraw()!@#&				end!@#&			elseif param == keys.home then!@#&				-- Home!@#&				nPos = 0!@#&				redraw()		!@#&			elseif param == keys.delete then!@#&				if nPos < string.len(sLine) then!@#&					redraw(\" \");!@#&					sLine = string.sub( sLine, 1, nPos ) .. string.sub( sLine, nPos + 2 )				!@#&					redraw()!@#&				end!@#&			elseif param == keys[\"end\"] then!@#&				-- End!@#&				nPos = string.len(sLine)!@#&				redraw()!@#&			end!@#&		elseif sEvent == \"redraw\" then!@#&			redraw()!@#&		elseif sEvent == \"return\" then!@#&			term.setCursorBlink( false )!@#&			return sLine!@#&		end!@#&	end!@#&	!@#&	term.setCursorBlink( false )!@#&	!@#&	return sLine!@#&end!@#&!@#&-- end modified read!@#&!@#&local function printC(posX,posY,textCol,backCol,text)!@#&	term.setCursorPos(posX,posY)!@#&	term.setTextColor(colors[textCol] or textCol)!@#&	term.setBackgroundColor(colors[backCol] or backCol)!@#&	term.write(text)!@#&end!@#&!@#&local function InputBox(title)!@#&	local boxW,boxH = 26,3!@#&	local termX,termY = term.getSize()!@#&	local ofsX,ofsY = math.ceil((termX/2) - (boxW/2)) , math.ceil((termY/2) - (boxH/2)) -- offset from top left!@#&	local options = {\"ok\",\"cancel\"}!@#&	!@#&	local selected = 1!@#&	local space = 0!@#&	local range = {}!@#&	for i = 1,#options do!@#&		range[i] = {s = space,f = space + string.len(options[i])}!@#&		space = space + string.len(options[i])+3!@#&	end!@#&	local ofC = (boxW/2) - (space/2)!@#&	!@#&	local function drawBox()!@#&		printC(ofsX,ofsY,colors.black,colors.blue,string.rep(\" \",boxW))!@#&		printC(ofsX+1,ofsY,colors.black,colors.blue,(title or \"User Input\"))!@#&		printC(ofsX,ofsY+1,colors.black,colors.white,string.rep(\" \",boxW))!@#&		printC(ofsX,ofsY+2,colors.black,colors.white,string.rep(\" \",boxW))!@#&		printC(ofsX,ofsY+3,colors.black,colors.white,string.rep(\" \",boxW))!@#&		!@#&		for i = 1,#options do!@#&			if i == selected then!@#&				term.setBackgroundColor(colors.lightGray)!@#&				term.setCursorPos(range[i].s + ofC + ofsX - 1,ofsY + 3)!@#&				term.write(\"[\"..options[i]..\"]\")!@#&				term.setBackgroundColor(colors.white)!@#&				term.write(\" \")!@#&			else!@#&				term.setCursorPos(range[i].s + ofC + ofsX - 1,ofsY + 3)!@#&				term.write(\" \"..options[i]..\" \")!@#&			end!@#&		end!@#&		!@#&		printC(ofsX+2,ofsY+2,colors.black,colors.lightGray,string.rep(\" \",boxW-4))!@#&	end!@#&	drawBox()!@#&	term.setCursorPos(ofsX+2,ofsY+2)!@#&	local co = coroutine.create(function() return readMOD(nil,nil,boxW - 4) end)!@#&	while true do!@#&		local event = {os.pullEvent()}!@#&		if event[1] == \"key\" or event[1] == \"char\" then!@#&			if event[2] == 28 then!@#&				local test,data = coroutine.resume(co,\"return\")!@#&				return data!@#&			else!@#&				coroutine.resume(co,unpack(event))!@#&			end!@#&		elseif event[1] == \"mouse_click\" then!@#&			if event[4] == ofsY + 3 then!@#&				for i = 1,#options do!@#&					if event[3] >= range[i].s + ofC + ofsX - 1 and event[3] <= range[i].f + ofC + ofsX then!@#&						if options[i] == \"ok\" then!@#&							local test,data = coroutine.resume(co,\"return\")!@#&							return data!@#&						elseif options[i] == \"cancel\" then!@#&							return false!@#&						end!@#&					end!@#&				end!@#&			end!@#&		end!@#&	end!@#&end!@#&!@#&local function dialogBox(title,message,options, h, w)!@#&	term.setCursorBlink(false)!@#&	local selected = 1!@#&	title = title or \"\"!@#&	message = message or \"\"!@#&	options = options or {}!@#&	local boxW,boxH = (w or 26), (h or 3)!@#&	local termX,termY = term.getSize()!@#&	local ofsX,ofsY = math.ceil((termX/2) - (boxW/2)) , math.ceil((termY/2) - (boxH/2)) -- offset from top left!@#&	!@#&	local space = 0!@#&	local range = {}!@#&	for i = 1,#options do!@#&		range[i] = {s = space,f = space + string.len(options[i])}!@#&		space = space + string.len(options[i])+3!@#&	end!@#&	local ofC = math.ceil((boxW/2)) - math.ceil((space/2))!@#&	!@#&	local function drawBox()!@#&		printC(ofsX,ofsY,dialogTitle.txt,dialogTitle.back,\" \"..title..string.rep(\" \",boxW-#title-5)..\"_[]\")!@#&		term.setBackgroundColor(colors.red)!@#&		term.setTextColor(colors.white)!@#&		term.write(\"X\")!@#&		printC(ofsX,ofsY+1,dialogWindo.txt,dialogWindo.back,string.sub(\" \"..message..string.rep(\" \",boxW),1,boxW))!@#&		term.setCursorPos(ofsX,ofsY+2)!@#&		term.write(string.rep(\" \",boxW))!@#&		term.setCursorPos(ofsX,ofsY+3)!@#&		term.write(string.rep(\" \",boxW))!@#&		for i = 1,#options do!@#&			if i == selected then!@#&				printC(range[i].s + ofC + ofsX - 1,ofsY + 3,\"black\",\"lightGray\",\"[\"..options[i]..\"]\")!@#&				term.setBackgroundColor(dialogWindo.back)!@#&				term.setTextColor(dialogWindo.txt)!@#&				term.write(\" \")!@#&			else!@#&				term.setCursorPos(range[i].s + ofC + ofsX - 1,ofsY + 3)!@#&				term.write(\" \"..options[i]..\" \")!@#&			end!@#&		end!@#&		term.setCursorPos(ofsX + ofC + space,ofsY + 3)!@#&		term.write(string.rep(\" \",boxW - (ofC + space)))!@#&		term.setBackgroundColor(colors.black)!@#&		term.setTextColor(colors.white)			!@#&	end!@#&	while true do!@#&		drawBox()!@#&		event = {os.pullEvent()}!@#&		if event[1] == \"key\" then!@#&			if event[2] == 203 then -- left!@#&				selected = selected - 1!@#&				if selected < 1 then!@#&					selected = #options!@#&				end!@#&			elseif event[2] == 205 then -- right!@#&				selected = selected + 1!@#&				if selected > #options then!@#&					selected = 1!@#&				end!@#&			elseif event[2] == 28 then -- enter!@#&				return selected , options[selected]!@#&			end!@#&		elseif event[1] == \"mouse_click\" then!@#&			!@#&			if bugTest then term.write(\"M \"..event[2]..\" X \"..event[3]..\" Y \"..event[4]..\"    \") end!@#&			!@#&			if event[2] == 1 then!@#&				if event[4] == ofsY + 3 then!@#&					for i = 1,#options do!@#&						if event[3] >= range[i].s + ofC + ofsX - 1 and event[3] <= range[i].f + ofC + ofsX then!@#&							return i , options[i]!@#&						end!@#&					end!@#&				end!@#&			end!@#&		end!@#&	end!@#&end!@#&!@#&local flag = true!@#&local fSlash = \"/\"!@#&local path = {dir:match(\"[^/]+\")}!@#&local function stringPath() -- compacted this a lot!@#&	return fSlash..table.concat(path,fSlash)!@#&end!@#&!@#&local function osRunSpaces(sFileLocation,...) -- getRunningProgram() [\"shell\"] = shell!@#&	clear()!@#&	if os.newThread then!@#&		os.newThread(false,...)!@#&	else!@#&	local fProg,probblem = loadfile(sFileLocation)!@#&		if fProg then!@#&			local tEnv = {[\"shell\"] = {}}!@#&			setmetatable(tEnv.shell,{ __index = shell})!@#&			tEnv.shell.getRunningProgram = function()!@#&				return sFileLocation!@#&			end!@#&			setmetatable(tEnv,{ __index = _G})!@#&			setfenv(fProg,tEnv)!@#&			local test,probblem = pcall(fProg,...)!@#&			if not test then!@#&				print(probblem)!@#&				dialogBox(\"ERROR\",tostring(probblem),{\"ok\"},3,30)!@#&			else!@#&				return true!@#&			end!@#&		else!@#&			print(probblem)!@#&			dialogBox(\"ERROR\",tostring(probblem),{\"ok\"},3,30)!@#&		end!@#&	end!@#&end!@#&!@#&local function rClickMenu(title,tList,tItem,posX,posY)!@#&!@#&	term.setCursorBlink(false)!@#&	local BoxTitle = title!@#&	local choices = {}!@#&	local termX,termY = term.getSize()!@#&	local offX,offY!@#&	!@#&	local width = #BoxTitle + 2!@#&	local hight!@#&	!@#&	for k,v in pairs(tList) do!@#&		if v ~= nil then!@#&			table.insert(choices,k)!@#&		end!@#&		if width < #k + 2 then!@#&			width = #k + 2!@#&		end!@#&	end!@#&	!@#&	if #choices == 0 then!@#&		return!@#&	end!@#&	!@#&	hight = #choices + 1!@#&	table.sort(choices)!@#&	!@#&	offX,offY = math.ceil((termX/2) - (width/2)),math.ceil((termY/2) - (hight/2))!@#&	!@#&	if posX and posY then -- offX,offY = posX,posY!@#&		if posX >= termX - width - 1 then!@#&			offX = termX - width - 1!@#&		else!@#&			offX = posX!@#&		end!@#&		if posY >= termY - hight then!@#&			offY = termY - hight!@#&		else!@#&			offY = posY!@#&		end!@#&	end!@#&	!@#&	local function reDrawer()!@#&		printC(offX,offY,rcmTitle.txt,rcmTitle.back,\" \"..BoxTitle..string.rep(\" \",width - #BoxTitle - 1))!@#&		for i = 1,#choices do!@#&			printC(offX,offY + i,rcmList.txt,rcmList.back,\" \"..choices[i]..string.rep(\" \",width - #choices[i] - 1))!@#&		end!@#&	end!@#&	!@#&	while true do!@#&		reDrawer()!@#&		local event = {os.pullEvent()}!@#&		if event[1] == \"mouse_click\" then!@#&			if event[2] == 1 then -- event[3] = x event[4] = y!@#&				if event[4] > offY and event[4] < hight + offY and event[3] >= offX and event[3] < width + offX then!@#&					--dialogBox(\"ERROR:\",type(tList[choices[event[4] - offY]]),{\"ok\"})!@#&					if type(tList[choices[event[4] - offY]]) == \"function\" then!@#&						return tList[choices[event[4] - offY]](tItem)!@#&					elseif type(tList[choices[event[4] - offY]]) == \"table\" then!@#&						return rClickMenu(\"Options\",tList[choices[event[4] - offY]],tItem,event[3],event[4])!@#&					elseif type(tList[choices[event[4] - offY]]) == \"string\" then!@#&						return osRunSpaces(!@#&								unpack(!@#&									fixArgs(!@#&										tList[choices[event[4] - offY]]..\" \\\"\"..stringPath()..fSlash..tItem.n..\"\\\"\"!@#&									)!@#&								)!@#&							)!@#&					else!@#&						dialogBox(\"ERROR:\",\"somthing up with new rMenu\",{\"ok\"})!@#&					end!@#&				else!@#&					return!@#&				end!@#&			elseif event[2] == 2 then!@#&				return!@#&			end!@#&		end!@#&	end!@#&	!@#&end!@#&!@#&local function preferences()!@#&	local tItem = {!@#&		{txt = \"Title Bar\",it = titleBar},!@#&		{txt = \"Address Bar\",it = addressBar},!@#&		{txt = \"Item Windo\", it = itemWindo},!@#&		{txt = \"Title Right Click Title\",it = rcmTitle},!@#&		{txt = \"Right Click Menu\",it = rcmList},!@#&		{txt = \"Title Dialog Box\",it = dialogTitle},!@#&		{txt = \"Dialog Box\",it = dialogWindo},!@#&		{txt = \"Scroll Bar\",it = scrollCol}!@#&	}!@#&	local topL,topR = 13,5!@#&	local width,hight = 23,6!@#&	local bottomL,bottomR = topL + width,topR + hight!@#&	!@#&	local listOffset = 0!@#&	local sel = 1!@#&	local otherSel = 1!@#&	local otherItems = {}!@#&	!@#&	if tItem[sel] then!@#&		for k,v in pairs(tItem[sel].it) do!@#&			table.insert(otherItems,{txt = k,it = v})!@#&		end!@#&	end!@#&	!@#&	local function draw()!@#&		printC(topL,topR,titleBar.txt,titleBar.back,string.sub(\" Preferences \"..string.rep(\" \",width),1,width))!@#&		for i = 0,12,4 do!@#&			for a = 1,4 do!@#&				--printC(topL + (a*12)-12 ,topR + ((i+4)/4),4,2^(a+i-1),\" \"..tostring(2^(a+i-1)))!@#&				printC(topL + a-1 ,topR + ((i+4)/4),4,2^(a+i-1),\" \")!@#&			end!@#&		end!@#&		local sSel = \" \"!@#&		for i = 1,hight - 2 do!@#&			if i == sel - listOffset then!@#&				sSel = \">\"!@#&			end!@#&			if tItem[i+listOffset] then!@#&				printC(topL + 4 ,topR + i,colors.black,colors.white,string.sub(sSel..tItem[i+listOffset].txt..string.rep(\" \",width),1,width - 4))!@#&			else!@#&				printC(topL + 4 ,topR + i,colors.black,colors.white,sSel..string.rep(\" \",width-5))!@#&			end!@#&			if i == sel - listOffset then!@#&				sSel = \" \"!@#&			end!@#&		end!@#&		term.setCursorPos(topL,topR + hight - 1)!@#&		local loop = 1!@#&		local length = 0!@#&			for i = 1,#otherItems do!@#&				if otherSel == i then!@#&					sSel = \">\"!@#&				end!@#&				if colors.black == otherItems[i].it or colors.gray == otherItems[i].it then!@#&					term.setTextColor(colors.white)!@#&				else!@#&					term.setTextColor(colors.black)!@#&				end!@#&				term.setBackgroundColor(otherItems[i].it)!@#&				term.write(sSel..tostring(otherItems[i].txt)..\" \")!@#&				length = length + #otherItems[i].txt + 2!@#&				if otherSel == i then!@#&					sSel = \" \"!@#&				end!@#&				loop = loop+1!@#&			end!@#&		term.setBackgroundColor(colors.white)!@#&		term.write(string.rep(\" \",width - length))!@#&	end!@#&	while true do!@#&		draw()!@#&		local event = {os.pullEvent()}!@#&		if event[1] == \"mouse_click\" and event[2] == 1 then!@#&			if inBouwndry(event[3],event[4],topL,topR,width,hight) then!@#&				local inSideX,inSideY = event[3] - topL,event[4] - topR!@#&				if inBouwndry(inSideX+1,inSideY,1,1,4,4) and tItem[sel] then!@#&					--[[!@#&					term.setCursorPos(1,1)!@#&					term.setBackgroundColor(2^(inSideX + ((inSideY*4)-4)))!@#&					print(2^(inSideX + ((inSideY*4)-4)),\" \",inSideX + ((inSideY*4)-4),\"     \")!@#&					]]--!@#&					tItem[sel][\"it\"][otherItems[otherSel].txt] = (2^(inSideX + ((inSideY*4)-4)))!@#&				end!@#&			end!@#&		elseif event[1] == \"key\" then!@#&			if event[2] == 200 then!@#&				sel = sel - 1!@#&			elseif event[2] == 208 then!@#&				sel = sel + 1!@#&			elseif event[2] == 203 then!@#&				otherSel = otherSel - 1!@#&			elseif event[2] == 205 then!@#&				otherSel = otherSel + 1!@#&			elseif event[2] == 28 then!@#&				if dialogBox(\"Confirm\",\"Save prefrences?\",{\"Yes\",\"No\"}) == 1 then!@#&					saveCFG(true)!@#&				end!@#&				return!@#&			end!@#&		end!@#&		if sel < 1 then!@#&			sel = 1!@#&		elseif sel > #tItem then!@#&			sel = #tItem!@#&		end!@#&		if sel > listOffset + hight - 2 then!@#&			listOffset = listOffset + 1!@#&		elseif sel - listOffset < 1 then!@#&			listOffset = listOffset - 1!@#&		end!@#&		!@#&		otherItems = {}!@#&		if tItem[sel] then!@#&			for k,v in pairs(tItem[sel].it) do!@#&				table.insert(otherItems,{txt = k,it = v})!@#&			end!@#&		end!@#&		!@#&		if otherSel < 1 then!@#&			otherSel = 1!@#&		elseif otherSel > #otherItems then!@#&			otherSel = #otherItems!@#&		end!@#&		!@#&		if bugTest then!@#&			term.setBackgroundColor(colors.black)!@#&			term.setTextColor(colors.white)!@#&			term.setCursorPos(1,1)!@#&			term.clearLine()!@#&			term.write(\"sel \"..sel..\" offset \"..listOffset)!@#&		end!@#&	end!@#&end!@#&!@#&local function fileSelect(mode) -- save_file open_file browse < not yet implemented!@#&	!@#&	local title = sTitle..\" \"..ver!@#&	local bRun = true!@#&	local clipboard = nil!@#&	local cut = false!@#&	!@#&	local termX,termY = term.getSize()!@#&	local offsetX,offsetY = 1,1!@#&	local hight,width = math.ceil(termY-2),math.ceil(termX-2)!@#&	local oldHight,oldWidth!@#&	!@#&	-- offsets!@#&	local boxOffX,boxOffY = offsetX,offsetY + 2!@#&	local boxH,boxW = hight - 2 ,width - 2!@#&	!@#&	local barX,barY = offsetX + 1,offsetY + 2!@#&	local barH,barW = 1,width - 1!@#&	!@#&	local tbarX,tbarY = offsetX + 1,offsetY + 1!@#&	local tbarH,tbarW = 1,width - 1!@#&	!@#&	local exitX,exitY = offsetX + width - 1 ,offsetY + 1!@#&	!@#&	local pading = string.rep(\" \",boxW)!@#&	local list!@#&	!@#&	local listOff = 0!@#&	!@#&	local sPath!@#&	local tItemList = {}!@#&	!@#&	local function newList()!@#&		listOff = 0!@#&		flag = true!@#&		tItemList = {{n = \"..\", id = \"back\"}} -- adds a back item at top of list!@#&		sPath = stringPath()!@#&		local folders = {}!@#&		local files = {}!@#&		local disks = {}!@#&		if not fs.exists(sPath) then!@#&			path = {}!@#&			sPath = stringPath()!@#&			dialogBox(\"ERROR:\",\"Path no longer exists\",{\"ok\"})!@#&		end!@#&		local test,list = pcall(fs.list,sPath) -- stopes fs.list crash!@#&		if list == nil then!@#&			list = {}!@#&			dialogBox(\"ERROR : \",\"fs.list crashed\",{\"ok\"})!@#&		end!@#&		if #path == 0 then!@#&			for i,v in pairs(rs.getSides()) do!@#&				if disk.isPresent(v) then!@#&					if disk.hasData(v) then!@#&						table.insert(tItemList,{n = disk.getMountPath(v), id = \"disk\",s = v})!@#&						disks[disk.getMountPath(v)] = true!@#&					elseif disk.hasAudio(v) then!@#&						table.insert(tItemList,{n = disk.getAudioTitle(v), id = \"audio\",s = v})!@#&					end!@#&				end!@#&			end!@#&		end!@#&		for i,v in pairs(list) do!@#&			if fs.isDir(sPath..fSlash..v) then!@#&				table.insert(folders,v)!@#&			else!@#&				table.insert(files,v)!@#&			end!@#&		end!@#&		table.sort(folders)!@#&		table.sort(files)!@#&		for i,v in pairs(folders) do!@#&			if disks[v] == nil then!@#&				table.insert(tItemList,{n = v, id = \"folder\"})!@#&			end!@#&		end!@#&		for i,v in pairs(files) do!@#&			table.insert(tItemList,{n = v, id = \"file\"})!@#&		end!@#&	end!@#&	!@#&	local function paste()!@#&		if cut then!@#&			local s, m = pcall(!@#&				function()!@#&					fs.move(clipboard[1]..fSlash..clipboard[2], stringPath()..fSlash..clipboard[2])!@#&					cut = false!@#&					clipboard = nil!@#&				end)!@#&			if not s then!@#&				dialogBox(\"Error\", (m or \"Couldn't move\"), {\"ok\"}, 4, 30)!@#&			end!@#&			if bugTest then!@#&				local x, y = term.getCursorPos()!@#&				term.setCursorPos(1, ({term.getSize()})[2])!@#&				write(\"from \"..clipboard[1]..fSlash..clipboard[2]..\" to \"..stringPath()..fSlash..clipboard[2])!@#&			end!@#&		else!@#&			local s, m = pcall(function()!@#&				if fs.exists(stringPath()..fSlash..clipboard[2]) then!@#&					fs.copy(clipboard[1]..fSlash..clipboard[2], stringPath()..fSlash..\"copy-\"..clipboard[2])!@#&				else!@#&					fs.copy(clipboard[1]..fSlash..clipboard[2], stringPath()..fSlash..clipboard[2])!@#&				end!@#&			end)!@#&			if not s then!@#&				dialogBox(\"Error\", (m or \"Couldn't copy\"), {\"ok\"}, 4, 30)!@#&			end!@#&			if bugTest then!@#&				local x, y = term.getCursorPos()!@#&				term.setCursorPos(1, ({term.getSize()})[2])!@#&				write(\"from \"..clipboard[1]..fSlash..clipboard[2]..\" to \"..stringPath()..fSlash..clipboard[2])!@#&			end!@#&		end!@#&		newList()!@#&	end!@#&	!@#&	-- this section bellow handles the right click menu!@#&	!@#&	local tmenu = {!@#&		disk = {!@#&			[\"Open\"] = function(tItem)!@#&				table.insert(path,tItem.n)!@#&				newList()!@#&			end,!@#&			[\"Copy\"] = function(tItem)!@#&				clipboard = {stringPath(), tItem.n}!@#&				cut = false!@#&			end,!@#&			[\"Eject\"] = function(tItem)!@#&				if dialogBox(\"Confirm\",\"Eject \"..fSlash..tItem.n..\" \"..tItem.s,{\"yes\",\"no\"}) == 1 then!@#&					disk.eject(tItem.s)!@#&					newList()!@#&				end!@#&			end,!@#&			[\"ID label\"] = function(tItem)!@#&				dialogBox(\"ID label\",disk.getDiskID(tItem.s)..\" \"..tostring(disk.getLabel(tItem.s)),{\"ok\"})!@#&			end,!@#&			[\"Set label\"] = function(tItem)!@#&				local name = InputBox(\"Label?\")!@#&				if name then!@#&					disk.setLabel(tItem.s,name)!@#&				end!@#&			end,!@#&			[\"Clear label\"] = function(tItem)!@#&				if dialogBox(\"Confirm\",\"Cleal Label from \"..tItem.s,{\"yes\",\"no\"}) == 1 then!@#&					disk.setLabel(tItem.s)!@#&				end!@#&			end!@#&		},!@#&		folder = {!@#&			[\"Open\"] = function(temp)!@#&				table.insert(path,temp.n)!@#&				newList()!@#&			end,!@#&			[\"Copy\"] = function(tItem)!@#&				clipboard = {stringPath(), tItem.n}!@#&				cut = false!@#&			end,!@#&			[\"Cut\"] = function(tItem)!@#&				clipboard = {stringPath(), tItem.n}!@#&				cut = true!@#&			end,!@#&			[\"Delete\"] = function(tItem)!@#&				if dialogBox(\"Confirm\",\"Delete \"..tItem.id..\" \"..tItem.n,{\"yes\",\"no\"}) == 1 then!@#&					if fs.isReadOnly(stringPath()..fSlash..tItem.n) then!@#&						dialogBox(\"ERROR\",tItem.id..\" Is read Only\",{\"ok\"})!@#&					else!@#&						fs.delete(stringPath()..fSlash..tItem.n)!@#&						newList()!@#&					end!@#&				end!@#&			end,!@#&			[\"Rename\"] = function(tItem)!@#&				local sName = InputBox(\"New Name\")!@#&				if type(sName) == \"string\" and sName ~= \"\" then!@#&					local s, m = pcall(function()!@#&						fs.move(stringPath()..fSlash..tItem.n,stringPath()..fSlash..sName)!@#&					end)!@#&					if not s then!@#&						dialogBox(\"Error\", (m or \"Rename failed\"), {\"ok\"})!@#&					end!@#&				end!@#&				newList()!@#&			end!@#&		},!@#&		file = {!@#&			[\"Run\"] = {!@#&				[\"Run\"] = function(tItem)!@#&					osRunSpaces(stringPath()..fSlash..tItem.n)!@#&				end,!@#&				[\"Run CMD\"] = function(tItem)!@#&					local cmd = InputBox(\"Commands\")!@#&					if cmd then!@#&						osRunSpaces(stringPath()..fSlash..tItem.n,unpack(fixArgs(cmd)))!@#&					end!@#&				end,!@#&			},!@#&			[\"Open With\"] = customLaunch,!@#&			[\"Rename\"] = function(tItem)!@#&				local sName = InputBox(\"New Name\")!@#&				if type(sName) == \"string\" and sName ~= \"\" then!@#&					local s, m = pcall(function()!@#&						fs.move(stringPath()..fSlash..tItem.n,stringPath()..fSlash..sName)!@#&					end)!@#&					if not s then!@#&						dialogBox(\"Error\", (m or \"Rename failed\"), {\"ok\"})!@#&					end!@#&				end!@#&				newList()!@#&			end,!@#&			[\"Delete\"] = function(tItem)!@#&				if dialogBox(\"Confirm\",\"Delete \"..tItem.id..\" \"..tItem.n,{\"yes\",\"no\"}) == 1 then!@#&					if fs.isReadOnly(stringPath()..fSlash..tItem.n) then!@#&						dialogBox(\"ERROR\",tItem.id..\" Is read Only\",{\"ok\"})!@#&					else!@#&						fs.delete(stringPath()..fSlash..tItem.n)!@#&						newList()!@#&					end!@#&				end!@#&			end,!@#&			[\"Cut\"] = function(tItem)!@#&				clipboard = {stringPath(), tItem.n}!@#&				cut = true!@#&			end,!@#&			[\"Copy\"] = function(tItem)!@#&				clipboard = {stringPath(), tItem.n}!@#&				cut = false!@#&			end!@#&		},!@#&		audio = {!@#&			[\"Play\"] = 1,!@#&			[\"Eject\"] = 1!@#&		},!@#&		back = {!@#&		},!@#&		blank = { -- tmenu.blank.Paste = !@#&			[\"Paste\"] = nil,!@#&			[\"New File\"] = function()!@#&				local name = InputBox()!@#&				if name then!@#&					if fs.exists(stringPath()..fSlash..name) then!@#&						dialogBox(\"ERROR\",\"Name exists\",{\"ok\"})!@#&					else!@#&						local file = fs.open(stringPath()..fSlash..name,\"w\")!@#&						if file then!@#&							file.write(\"\")!@#&							file.close()!@#&							newList()!@#&						else!@#&							dialogBox(\"ERROR\",\"File not created\",{\"ok\"})!@#&						end!@#&					end!@#&				end!@#&			end,!@#&			[\"New Folder\"] = function()!@#&				local name = InputBox()!@#&				if name then!@#&					if fs.exists(stringPath()..fSlash..name) then!@#&						dialogBox(\"ERROR\",\"Name exists\",{\"ok\"})!@#&					else!@#&						if pcall(fs.makeDir,stringPath()..fSlash..name) then!@#&							newList()!@#&						else!@#&							dialogBox(\"ERROR\",\"Access Denied\",{\"ok\"})!@#&						end!@#&					end!@#&				end!@#&			end,!@#&			[\"Preferences\"] = preferences!@#&		},!@#&	}!@#&	!@#&	-- end right click menu!@#&	!@#&	local function scrollBar(posX,posY)!@#&		if posX == boxOffX+boxW+1 and posY > boxOffY and posY <= boxOffY+boxH then!@#&			if #tItemList > boxH then!@#&				if posY == boxOffY + 1 then!@#&					listOff = 0!@#&				elseif posY == boxOffY+boxH then!@#&					listOff = #tItemList + 1 - boxH!@#&				else!@#&					listOff = math.ceil((posY - boxOffY - 1 )*(((#tItemList - boxH+2)/boxH)))!@#&				end!@#&				flag = true!@#&			end!@#&		end!@#&	end!@#&	!@#&	newList()!@#&	!@#&	while bRun do!@#&		if flag then!@#&			flag = false!@#&			-- clear!@#&			if oldHight ~= hight and oldWidth ~= width then!@#&				term.setBackgroundColor(colors.black)!@#&				term.clear()!@#&				oldHight,oldWidth = hight,width!@#&			end!@#&			-- draw top title bar!@#&			local b = tbarW - #title -2!@#&			if b < 0 then!@#&				b = 0!@#&			end!@#&			printC(tbarX,tbarY,titleBar.txt,titleBar.back,string.sub(\" \"..title,1,tbarW)..string.rep(\" \",b))!@#&			term.setTextColor(colors.white)!@#&			term.setBackgroundColor(colors.red)!@#&			term.write(\"X\")!@#&			!@#&			-- draw location bar!@#&			local a = barW - #sPath - 1!@#&			if a < 0 then!@#&				a = 0!@#&			end!@#&			local tmppath = sPath!@#&			if shell and shell.getDisplayName then!@#&				tmppath = shell.getDisplayName(sPath)!@#&				--dialogBox(\"yay\")!@#&			else!@#&				--dialogBox(\"moop\")!@#&			end!@#&			tmppath = tmppath or sPath!@#&			local a = barW - #tmppath - 1!@#&			if a < 0 then!@#&				a = 0!@#&			end!@#&			printC(barX,barY,addressBar.txt,addressBar.back,string.sub(\" \"..tmppath,1,barW)..string.rep(\" \",a))!@#&			!@#&			-- draw scroll bar!@#&			if #tItemList > boxH then!@#&				term.setBackgroundColor(scrollCol.back)!@#&				for i = 1,boxH do!@#&					term.setCursorPos(boxOffX+boxW+1,i + boxOffY)!@#&					local scroll = math.floor( boxH* (listOff/(#tItemList-boxH+2)) )+1!@#&					if i == scroll then!@#&						term.setBackgroundColor(scrollCol.button)!@#&						term.write(\" \")!@#&						term.setBackgroundColor(scrollCol.back)!@#&					else!@#&						term.write(\" \")!@#&					end!@#&				end!@#&			else!@#&				term.setBackgroundColor(scrollCol.off)!@#&				for i = 1,boxH do!@#&					term.setCursorPos(boxOffX+boxW+1,i + boxOffY)!@#&					term.write(\" \")!@#&				end!@#&			end!@#&			!@#&			-- draw main section!@#&!@#&			for i = 1,boxH do -- listOff!@#&				local sel = i+listOff!@#&				if tItemList[sel] then!@#&					printC(1+boxOffX,i+boxOffY,(tIcons[tItemList[sel].id].tCol or itemWindo.txt),(tIcons[tItemList[sel].id].bCol or itemWindo.back),( tIcons[tItemList[sel].id].txt or \"   \"))!@#&					printC(4+boxOffX,i+boxOffY,itemWindo.txt,itemWindo.back,string.sub(\" \"..tItemList[sel].n..pading,1,boxW-3))!@#&				else!@#&					printC(1+boxOffX,i+boxOffY,itemWindo.txt,itemWindo.back,pading)!@#&				end!@#&			end!@#&			!@#&			if bugTest then!@#&				printC(1,1,\"black\",\"white\",listOff..\" \"..boxOffY..\" \"..boxH)!@#&			end!@#&			!@#&		end!@#&		!@#&		-- react to events!@#&		local event = {os.pullEvent()}!@#&		!@#&		if event[1] == \"mouse_click\" then!@#&			if inBouwndry(event[3],event[4],boxOffX+1,boxOffY+1,boxW,boxH) then!@#&				local selected = tItemList[event[4]+listOff-boxOffY]!@#&				if selected and inBouwndry(event[3],event[4],boxOffX+1,event[4],#selected.n + 4,1) then!@#&					if event[2] == 1 then -- left mouse!@#&						if selected.id == \"back\" then!@#&							table.remove(path,#path)!@#&							newList()!@#&						elseif selected.id == \"folder\" or selected.id == \"disk\" then!@#&							table.insert(path,selected.n)!@#&							newList()!@#&						elseif selected.id == \"file\" then!@#&							if dialogBox(\"Run file ?\",selected.n,{\"yes\",\"no\"}) == 1 then!@#&								osRunSpaces(stringPath()..fSlash..selected.n)!@#&							end!@#&						flag = true!@#&						end!@#&					elseif event[2] == 2 then -- right mouse!@#&						rClickMenu(\"Options\",tmenu[selected.id],selected,event[3],event[4])!@#&						flag = true!@#&					end!@#&				elseif event[2] == 2 then -- right clicking not on object!@#&					if clipboard then!@#&						tmenu.blank.Paste = paste!@#&					else!@#&						tmenu.blank.Paste = nil!@#&					end!@#&					rClickMenu(\"Options\",tmenu[\"blank\"],selected,event[3],event[4])!@#&					flag = true!@#&				end!@#&			elseif event[2] == 1 and event[3] == exitX and event[4] == exitY then!@#&				if dialogBox(\"Confirm\",\"Exit application\",{\"yes\",\"no\"}) == 1 then!@#&					bRun = false!@#&				end!@#&				flag = true!@#&			elseif event[2] == 1 then!@#&				scrollBar(event[3],event[4])!@#&			end!@#&		elseif event[1] == \"mouse_scroll\" then -- flag this needs new math!@#&			local old = listOff!@#&			listOff = listOff + event[2]!@#&			if listOff < 0 then!@#&				listOff = 0!@#&			end!@#&			if #tItemList + 1 - boxH > 0 and listOff > #tItemList + 1 - boxH then!@#&				listOff = #tItemList + 1 - boxH!@#&			elseif listOff > 0 and #tItemList + 1 - boxH < 0 then!@#&				listOff = 0!@#&			end!@#&			if listOff ~= old then!@#&				flag = true!@#&			end!@#&		!@#&		elseif event[1] == \"mouse_drag\" then -- scroll bar!@#&			scrollBar(event[3],event[4])!@#&		elseif event[1] == \"disk\" or event[1] == \"disk_eject\" then!@#&			newList()!@#&		elseif event[1] == \"window_resize\" then!@#&			termX,termY = term.getSize()!@#&			offsetX,offsetY = 1,1!@#&			hight,width = math.ceil(termY-2),math.ceil(termX-2)!@#&			!@#&			boxOffX,boxOffY = offsetX,offsetY + 2!@#&			boxH,boxW = hight - 2 ,width - 2!@#&			!@#&			barX,barY = offsetX + 1,offsetY + 2!@#&			barH,barW = 1,width - 1!@#&			!@#&			tbarX,tbarY = offsetX + 1,offsetY + 1!@#&			tbarH,tbarW = 1,width - 1!@#&			!@#&			exitX,exitY = offsetX + width - 1 ,offsetY + 1!@#&			pading = string.rep(\" \",boxW)!@#&			!@#&			flag = true!@#&		elseif event[1] == \"redraw\" then!@#&			flag = true!@#&		end!@#&	end!@#&end!@#&!@#&local function main()!@#&	if term.isColor() then!@#&		clear()!@#&		fileSelect()!@#&		clear()!@#&	else!@#&		error(\"Not an Advanced Computer (gold) \")!@#&	end!@#&end!@#&!@#&local trash = (norun or main())",["firewolf"]="!@#&--!@#&--  Firewolf Website Browser!@#&--  Made by GravityScore and 1lann!@#&--  License found here: https://raw.github.com/1lann/Firewolf/master/LICENSE!@#&--!@#&--  Original Concept From RednetExplorer 2.4.1!@#&--  RednetExplorer Made by ComputerCraftFan11!@#&--!@#&!@#&!@#&--  -------- Variables!@#&!@#&-- Version!@#&local version = \"2.5\"!@#&local build = 36!@#&local browserAgent = \"Firewolf \" .. version!@#&local tArgs = {...}!@#&!@#&-- Server Identification!@#&local serverID = \"other\"!@#&local serverList = {experimental = \"Experimental\", other = \"Other\"}!@#&!@#&-- Updating!@#&local autoupdate = \"true\"!@#&local noInternet = false!@#&!@#&-- Resources!@#&local graphics = {}!@#&local files = {}!@#&local w, h = term.getSize()!@#&!@#&-- Debugging!@#&local debugFile = nil!@#&!@#&-- Environment!@#&local oldEnv = {}!@#&local env = {}!@#&local api = {}!@#&local override = {}!@#&local antivirus = {}!@#&!@#&-- Themes!@#&local theme = {}!@#&!@#&-- Databases!@#&local blacklist = {}!@#&local whitelist = {}!@#&local dnsDatabase = {{}, {}}!@#&!@#&-- Website Loading!@#&local pages = {}!@#&local errorPages = {}!@#&!@#&local website = \"\"!@#&local homepage = \"\"!@#&local timeout = 0.2!@#&local loadingRate, loadingClock = 0, nil!@#&local openAddressBar, clickableAddressBar = true, true!@#&local menuBarOpen = false!@#&local offsetclick = true!@#&local websiteerror = nil!@#&!@#&-- Tabs!@#&local tabs = {}!@#&local filters = {}!@#&local currentTab = 1!@#&!@#&-- Protocols!@#&local curProtocol = {}!@#&local protocols = {}!@#&!@#&-- History!@#&local addressBarHistory = {}!@#&!@#&-- Events!@#&local event_load = \"firewolf_websiteLoadEvent\"!@#&local event_redirect = \"firewolf_redirectEvent\"!@#&local event_error = \"firewolf_siteErrorEvent\"!@#&local event_exit = \"firewolf_exitEvent\"!@#&!@#&-- Download URLs!@#&local firewolfURL = \"https://raw.github.com/1lann/Firewolf/master/entities/other.lua\"!@#&local serverURL = \"https://raw.github.com/1lann/Firewolf/master/server/server-release.lua\"!@#&local buildURL = \"https://raw.github.com/1lann/Firewolf/master/build\"!@#&!@#&-- Data Locations!@#&local rootFolder = \"/.Firewolf_Data\"!@#&local cacheFolder = rootFolder .. \"/cache\"!@#&local serverFolder = rootFolder .. \"/servers\"!@#&local websiteDataFolder = rootFolder .. \"/website_data\"!@#&local themeLocation = rootFolder .. \"/theme\"!@#&local serverLocation = rootFolder .. \"/server_software\"!@#&local settingsLocation = rootFolder .. \"/settings\"!@#&local debugLogLocation = \"/firewolf-log\"!@#&local firewolfLocation = \"/\" .. shell.getRunningProgram()!@#&!@#&local userBlacklist = rootFolder .. \"/user_blacklist\"!@#&local userWhitelist = rootFolder .. \"/user_whitelist\"!@#&!@#&local function isAdvanced() return term.isColor and term.isColor() end!@#&!@#&local function modemPresent()!@#&	if curProtocol == protocols.rdnt then!@#&		for _, v in pairs(rs.getSides()) do!@#&			if peripheral.getType(v) == \"modem\" then rednet.open(v) return true end!@#&		end!@#&	else return true end!@#&	return false!@#&end!@#&!@#&!@#&--  -------- Utilities!@#&!@#&local function debugLog(n, ...)!@#&	local lArgs = {...}!@#&	if debugFile then!@#&		if not n then return end!@#&		debugFile:write(\"\\n\" .. tostring(n) .. \" : \")!@#&		for k, v in pairs(lArgs) do!@#&			if type(v) == \"string\" or type(v) == \"number\" or not type(v) or type(v) == \"boolean\" then!@#&				debugFile:write(tostring(v) .. \", \")!@#&			else debugFile:write(\"type-\" .. type(v) .. \", \") end!@#&		end!@#&	end!@#&end!@#&!@#&local function clear(site, background, drawmenu)!@#&	local titles = {!@#&		[\"firewolf\"] = \"Firewolf\",!@#&		[\"server/rdnt\"] = \"Server Management\",!@#&		[\"server/http\"] = \"Server Management\",!@#&		[\"help\"] = \"Help\",!@#&		[\"settings\"] = \"Settings\",!@#&		[\"credits\"] = \"Credits\",!@#&		[\"crash\"] = \"Crashed!\",!@#&		[\"overspeed\"] = \"Too Fast!\"!@#&	}!@#&!@#&	local title = titles[site] or \"\"!@#&	term.setBackgroundColor(background or colors.black)!@#&	term.setTextColor(colors[theme[\"address-bar-text\"]])!@#&	if drawmenu ~= true then term.clear() end!@#&!@#&	if not menuBarOpen then!@#&		term.setBackgroundColor(colors[theme[\"address-bar-background\"]])!@#&		term.setCursorPos(2, 1)!@#&		term.clearLine()!@#&		if site:len() > w - 10 then site = site:sub(1, 38) .. \"...\" end!@#&		if curProtocol == protocols.http then write(\"http://\" .. site)!@#&		else write(\"rdnt://\" .. site) end!@#&		term.setCursorPos(w - title:len() - 1, 1)!@#&		write(title)!@#&!@#&		if isAdvanced() then!@#&			term.setCursorPos(w, 1)!@#&			term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&			term.setTextColor(colors[theme[\"text-color\"]])!@#&			write(\"<\")!@#&		end!@#&!@#&		term.setBackgroundColor(background or colors.black)!@#&		term.setTextColor(colors.white)!@#&	else!@#&		term.setCursorPos(1, 1)!@#&		term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&		term.setTextColor(colors[theme[\"text-color\"]])!@#&		term.clearLine()!@#&		write(\"> [- Exit Firewolf -]                              \")!@#&	end!@#&!@#&	print(\"\")!@#&end!@#&!@#&local function modRead(properties)!@#&	local w, h = term.getSize()!@#&	local defaults = {replaceChar = nil, history = nil, visibleLength = nil, textLength = nil,!@#&		liveUpdates = nil, exitOnKey = nil}!@#&	if not properties then properties = {} end!@#&	for k, v in pairs(defaults) do if not properties[k] then properties[k] = v end end!@#&	if properties.replaceChar then properties.replaceChar = properties.replaceChar:sub(1, 1) end!@#&	if not properties.visibleLength then properties.visibleLength = w end!@#&!@#&	local sx, sy = term.getCursorPos()!@#&	local line = \"\"!@#&	local pos = 0!@#&	local historyPos = nil!@#&!@#&	local function redraw(repl)!@#&		local scroll = 0!@#&		if properties.visibleLength and sx + pos > properties.visibleLength + 1 then!@#&			scroll = (sx + pos) - (properties.visibleLength + 1)!@#&		end!@#&!@#&		term.setCursorPos(sx, sy)!@#&		local a = repl or properties.replaceChar!@#&		if a then term.write(string.rep(a, line:len() - scroll))!@#&		else term.write(line:sub(scroll + 1, -1)) end!@#&		term.setCursorPos(sx + pos - scroll, sy)!@#&	end!@#&!@#&	local function sendLiveUpdates(event, ...)!@#&		if type(properties.liveUpdates) == \"function\" then!@#&			local ox, oy = term.getCursorPos()!@#&			local a, data = properties.liveUpdates(line, event, ...)!@#&			if a == true and not data then!@#&				term.setCursorBlink(false)!@#&				return line!@#&			elseif a == true and data then!@#&				term.setCursorBlink(false)!@#&				return data!@#&			end!@#&			term.setCursorPos(ox, oy)!@#&		end!@#&	end!@#&!@#&	local a = sendLiveUpdates(\"delete\")!@#&	if a then return a end!@#&	term.setCursorBlink(true)!@#&	while true do!@#&		local e, but, x, y, p4, p5 = os.pullEvent()!@#&		if e == \"char\" then!@#&			local s = false!@#&			if properties.textLength and line:len() < properties.textLength then s = true!@#&			elseif not properties.textLength then s = true end!@#&!@#&			local canType = true!@#&			if not properties.grantPrint and properties.refusePrint then!@#&				local canTypeKeys = {}!@#&				if type(properties.refusePrint) == \"table\" then!@#&					for _, v in pairs(properties.refusePrint) do!@#&						table.insert(canTypeKeys, tostring(v):sub(1, 1))!@#&					end!@#&				elseif type(properties.refusePrint) == \"string\" then!@#&					for char in properties.refusePrint:gmatch(\".\") do!@#&						table.insert(canTypeKeys, char)!@#&					end!@#&				end!@#&				for _, v in pairs(canTypeKeys) do if but == v then canType = false end end!@#&			elseif properties.grantPrint then!@#&				canType = false!@#&				local canTypeKeys = {}!@#&				if type(properties.grantPrint) == \"table\" then!@#&					for _, v in pairs(properties.grantPrint) do!@#&						table.insert(canTypeKeys, tostring(v):sub(1, 1))!@#&					end!@#&				elseif type(properties.grantPrint) == \"string\" then!@#&					for char in properties.grantPrint:gmatch(\".\") do table.insert(canTypeKeys, char) end!@#&				end!@#&				for _, v in pairs(canTypeKeys) do if but == v then canType = true end end!@#&			end!@#&!@#&			if s and canType then!@#&				line = line:sub(1, pos) .. but .. line:sub(pos + 1, -1)!@#&				pos = pos + 1!@#&				redraw()!@#&			end!@#&		elseif e == \"key\" then!@#&			if but == keys.enter then break!@#&			elseif but == keys.left then if pos > 0 then pos = pos - 1 redraw() end!@#&			elseif but == keys.right then if pos < line:len() then pos = pos + 1 redraw() end!@#&			elseif (but == keys.up or but == keys.down) and properties.history and!@#&					#properties.history > 0 then!@#&				redraw(\" \")!@#&				if but == keys.up then!@#&					if not historyPos and #properties.history > 0 then!@#&						historyPos = #properties.history!@#&					elseif historyPos > 1 then historyPos = historyPos - 1 end!@#&				elseif but == keys.down then!@#&					if historyPos == #properties.history then historyPos = nil!@#&					elseif historyPos then historyPos = historyPos + 1 end!@#&				end!@#&!@#&				if properties.history and historyPos then!@#&					line = properties.history[historyPos]!@#&					pos = line:len()!@#&				else!@#&					line = \"\"!@#&					pos = 0!@#&				end!@#&!@#&				redraw()!@#&				local a = sendLiveUpdates(\"history\")!@#&				if a then return a end!@#&			elseif but == keys.backspace and pos > 0 then!@#&				redraw(\" \")!@#&				line = line:sub(1, pos - 1) .. line:sub(pos + 1, -1)!@#&				pos = pos - 1!@#&				redraw()!@#&				local a = sendLiveUpdates(\"delete\")!@#&				if a then return a end!@#&			elseif but == keys.home then!@#&				pos = 0!@#&				redraw()!@#&			elseif but == keys.delete and pos < line:len() then!@#&				redraw(\" \")!@#&				line = line:sub(1, pos) .. line:sub(pos + 2, -1)!@#&				redraw()!@#&				local a = sendLiveUpdates(\"delete\")!@#&				if a then return a end!@#&			elseif but == keys[\"end\"] then!@#&				pos = line:len()!@#&				redraw()!@#&			elseif properties.exitOnKey then!@#&				if but == properties.exitOnKey or (properties.exitOnKey == \"control\" and!@#&						(but == 29 or but == 157)) then!@#&					term.setCursorBlink(false)!@#&					return nil!@#&				end!@#&			end!@#&		end!@#&!@#&		local a = sendLiveUpdates(e, but, x, y, p4, p5)!@#&		if a then return a end!@#&	end!@#&!@#&	term.setCursorBlink(false)!@#&	if line then line = line:gsub(\"^%s*(.-)%s*$\", \"%1\") end!@#&	return line!@#&end!@#&!@#&!@#&--  -------- API!@#&!@#&--  Drawing!@#&!@#&local function printWithType(t, func)!@#&	if type(t) == \"table\" then!@#&		for _, v in pairs(t) do env.pcall(function() printWithType(v, func) end) end!@#&	else func(tostring(t)) end!@#&end!@#&!@#&api.centerWrite = function(text)!@#&	printWithType(text, function(t)!@#&		local x, y = term.getCursorPos()!@#&		term.setCursorPos(math.ceil((w + 1)/2 - t:len()/2), y)!@#&		write(t)!@#&	end)!@#&end!@#&!@#&api.centerPrint = function(text)!@#&	printWithType(text, function(t)!@#&		local x, y = term.getCursorPos()!@#&		term.setCursorPos(math.ceil((w + 2)/2 - t:len()/2), y)!@#&		print(t)!@#&	end)!@#&end!@#&!@#&api.leftWrite = function(text)!@#&	printWithType(text, function(t)!@#&		local x, y = term.getCursorPos()!@#&		term.setCursorPos(1, y)!@#&		write(t)!@#&	end)!@#&end!@#&!@#&api.leftPrint = function(text)!@#&	printWithType(text, function(t)!@#&		local x, y = term.getCursorPos()!@#&		term.setCursorPos(1, y)!@#&		print(t)!@#&	end)!@#&end!@#&!@#&api.rightWrite = function(text)!@#&	printWithType(text, function(t)!@#&		local x, y = term.getCursorPos()!@#&		term.setCursorPos(w - t:len() + 1, y)!@#&		write(t)!@#&	end)!@#&end!@#&!@#&api.rightPrint = function(text)!@#&	printWithType(text, function(t)!@#&		local x, y = term.getCursorPos()!@#&		term.setCursorPos(w - t:len() + 1, y)!@#&		print(t)!@#&	end)!@#&end!@#&!@#&api.clearArea = function() term.clear() term.setCursorPos(1, 1) end!@#&api.cPrint = function(text) api.centerPrint(text) end!@#&api.cWrite = function(text) api.centerWrite(text) end!@#&api.lPrint = function(text) api.leftPrint(text) end!@#&api.lWrite = function(text) api.leftWrite(text) end!@#&api.rPrint = function(text) api.rightPrint(text) end!@#&api.rWrite = function(text) api.rightWrite(text) end!@#&!@#&!@#&--  Server Interation!@#&!@#&api.loadFileFromServer = function(path)!@#&	if type(path) ~= \"string\" then error(\"expected string\", 2) end!@#&	sleep(0.05)!@#&	if path:sub(1, 1) == \"/\" then path = path:sub(2, -1) end!@#&	local id, content = curProtocol.getWebsite(website .. \"/\" .. path)!@#&	if id then return content end!@#&	return nil!@#&end!@#&!@#&api.ioReadFileFromServer = function(path)!@#&	local content = api.loadFileFromServer(path)!@#&	if content then!@#&		local f = env.io.open(rootFolder .. \"/temp_file\", \"w\")!@#&		f:write(content)!@#&		f:close()!@#&		return env.io.open(rootFolder .. \"/temp_file\", \"r\")!@#&	end!@#&	return nil!@#&end!@#&!@#&api.loadImageFromServer = function(path)!@#&	local content = api.loadFileFromServer(path)!@#&	if content then!@#&		local f = env.io.open(rootFolder .. \"/temp_file\", \"w\")!@#&		f:write(content)!@#&		f:close()!@#&!@#&		local image = paintutils.loadImage(rootFolder .. \"/temp_file\")!@#&		env.fs.delete(\"/temp_file\")!@#&		return image!@#&	end!@#&	return nil!@#&end!@#&!@#&api.writeDataFile = function(path, content)!@#&	if type(path) ~= \"string\" or type(content) ~= \"string\" then!@#&		error(\"expected string, string\", 2) end!@#&	if path:sub(1, 1) == \"/\" then path = path:sub(2, -1) end!@#&	local dataPath = websiteDataFolder .. \"/\" .. path:gsub(\"/\", \"$slazh$\")!@#&!@#&	if env.fs.isReadOnly(dataPath) then return false end!@#&	if env.fs.exists(dataPath) then env.fs.delete(dataPath) end!@#&	local f = env.io.open(dataPath, \"w\")!@#&	if not f then return false end!@#&	f:write(content)!@#&	f:close()!@#&	return true!@#&end!@#&!@#&api.readDataFile = function(path)!@#&	if type(path) ~= \"string\" then error(\"readDataFile: expected string\") end!@#&	if path:sub(1, 1) == \"/\" then path = path:sub(2, -1) end!@#&	local dataPath = websiteDataFolder .. \"/\" .. path:gsub(\"/\", \"$slazh$\")!@#&!@#&	if env.fs.isDir(dataPath) then env.fs.delete(dataPath) end!@#&	if env.fs.exists(dataPath) then!@#&		local f = env.io.open(dataPath, \"r\")!@#&		local cont = f:read(\"*a\")!@#&		f:close()!@#&		return cont!@#&	end!@#&	return nil!@#&end!@#&!@#&api.saveFileToUserComputer = function(content)!@#&	if type(content) ~= \"string\" then error(\"expected string\", 2) end!@#&	local oldback, oldtext = override.term.getBackgroundColor(), override.term.getTextColor()!@#&	local ox, oy = term.getCursorPos()!@#&!@#&	term.setTextColor(colors[theme[\"text-color\"]])!@#&	term.setBackgroundColor(colors[theme[\"background\"]])!@#&	term.clear()!@#&	term.setCursorPos(1, 1)!@#&	term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&	print(\"\")!@#&	leftPrint(string.rep(\" \", 20))!@#&	leftPrint(\" Save File Request  \")!@#&	leftPrint(string.rep(\" \", 20))!@#&	print(\"\")!@#&!@#&	term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&	for i = 1, 11 do rightPrint(string.rep(\" \", 36)) end!@#&	term.setCursorPos(1, 7)!@#&	rightPrint(\"The website: \")!@#&	rightPrint(website .. \"  \")!@#&	rightPrint(\"Is requesting to save a file \")!@#&	rightPrint(\"to your computer. \")!@#&!@#&	local ret = nil!@#&	local opt = prompt({{\"Save File\", w - 16, 12}, {\"Cancel\", w - 13, 13}}, \"vertical\")!@#&	if opt == \"Save File\" then!@#&		while not ret do!@#&			term.setCursorPos(1, 15)!@#&			rightWrite(string.rep(\" \", 36))!@#&			term.setCursorPos(w - 34, 15)!@#&			write(\"Path: /\")!@#&			local p = read()!@#&!@#&			term.setCursorPos(1, 15)!@#&			rightWrite(string.rep(\" \", 36))!@#&			if p == \"\" then!@#&				rightWrite(\"Cancelled \")!@#&				break!@#&			elseif fs.exists(\"/\" .. p) then!@#&				rightWrite(\"File Already Exists! \")!@#&			else!@#&				rightWrite(\"File Saved! \")!@#&				ret = \"/\" .. p!@#&				local f = env.io.open(ret, \"w\")!@#&				f:write(content)!@#&				f:close()!@#&			end!@#&!@#&			openAddressBar = false!@#&			sleep(1.3)!@#&			openAddressBar = true!@#&		end!@#&	elseif opt == \"Cancel\" then!@#&		term.setCursorPos(1, 15)!@#&		rightWrite(\"Saving Cancelled! \")!@#&	end!@#&!@#&	openAddressBar = false!@#&	sleep(1.3)!@#&	openAddressBar = true!@#&!@#&	term.setBackgroundColor(oldback or colors.black)!@#&	term.setTextColor(oldtext or colors.white)!@#&	term.clear()!@#&	term.setCursorPos(ox, oy)!@#&	return ret!@#&end!@#&!@#&api.urlDownload = function(url)!@#&	if type(url) ~= \"string\" then error(\"expected string\", 2) end!@#&	local source = nil!@#&	http.request(url)!@#&	local a = os.startTimer(10)!@#&	while true do!@#&		local e, surl, handle = os.pullEvent()!@#&		if e == \"http_success\" then!@#&			source = handle.readAll()!@#&			break!@#&		elseif e == \"http_failure\" or (e == \"timer\" and surl == a) then!@#&			break!@#&		end!@#&	end!@#&!@#&	if type(source) == \"string\" then!@#&		return api.saveFileToUserComputer(source)!@#&	else return nil end!@#&end!@#&!@#&api.pastebinDownload = function(code)!@#&	return api.urlDownload(\"http://pastebin.com/raw.php?i=\" .. tostring(code))!@#&end!@#&!@#&!@#&--  Redirection!@#&!@#&api.redirect = function(url)!@#&	if type(url) ~= \"string\" then url = \"home\" end!@#&	os.queueEvent(event_redirect, url:gsub(\"rdnt://\"):gsub(\"http://\"))!@#&	error()!@#&end!@#&!@#&!@#&--  Theme!@#&!@#&api.themeColor = function(tag)!@#&	if type(tag) ~= \"string\" then error(\"themeColor: expected string\") end!@#&	return colors[theme[tag] or defaultTheme[tag] or \"white\"]!@#&end!@#&!@#&api.themeColour = function(tag) return api.themeColor(tag) end!@#&!@#&!@#&--  Prompt!@#&!@#&api.prompt = function(list, dir)!@#&	if isAdvanced() then!@#&		for _, v in pairs(list) do!@#&			if v.bg then term.setBackgroundColor(v.bg) end!@#&			if v.tc then term.setTextColor(v.tc) end!@#&			if v[2] == -1 then v[2] = math.ceil((w + 1)/2 - (v[1]:len() + 6)/2) end!@#&!@#&			term.setCursorPos(v[2], v[3])!@#&			write(\"[- \" .. v[1])!@#&			term.setCursorPos(v[2] + v[1]:len() + 3, v[3])!@#&			write(\" -]\")!@#&		end!@#&!@#&		while true do!@#&			local e, but, x, y = os.pullEvent()!@#&			if e == \"mouse_click\" then!@#&				for _, v in pairs(list) do!@#&					if x >= v[2] and x <= v[2] + v[1]:len() + 5 and y + (v.coffset or 0) == v[3] then!@#&						return v[1]!@#&					end!@#&				end!@#&			end!@#&		end!@#&	else!@#&		for _, v in pairs(list) do!@#&			term.setBackgroundColor(colors.black)!@#&			term.setTextColor(colors.white)!@#&			if v[2] == -1 then v[2] = math.ceil((w + 1)/2 - (v[1]:len() + 4)/2) end!@#&!@#&			term.setCursorPos(v[2], v[3])!@#&			write(\"  \" .. v[1])!@#&			term.setCursorPos(v[2] + v[1]:len() + 2, v[3])!@#&			write(\"  \")!@#&		end!@#&!@#&		local key1 = dir == \"horizontal\" and 203 or 200!@#&		local key2 = dir == \"horizontal\" and 205 or 208!@#&!@#&		local curSel = 1!@#&		term.setCursorPos(list[curSel][2], list[curSel][3])!@#&		write(\"[\")!@#&		term.setCursorPos(list[curSel][2] + list[curSel][1]:len() + 3, list[curSel][3])!@#&		write(\"]\")!@#&		while true do!@#&			local e, key = os.pullEvent(\"key\")!@#&			term.setCursorPos(list[curSel][2], list[curSel][3])!@#&			write(\" \")!@#&			term.setCursorPos(list[curSel][2] + list[curSel][1]:len() + 3, list[curSel][3])!@#&			write(\" \")!@#&			if key == key1 and curSel > 1 then curSel = curSel - 1!@#&			elseif key == key2 and curSel < #list then curSel = curSel + 1!@#&			elseif key == 28 then return list[curSel][1] end!@#&			term.setCursorPos(list[curSel][2], list[curSel][3])!@#&			write(\"[\")!@#&			term.setCursorPos(list[curSel][2] + list[curSel][1]:len() + 3, list[curSel][3])!@#&			write(\"]\")!@#&		end!@#&	end!@#&end!@#&!@#&api.scrollingPrompt = function(list, x, y, len, width, coffset)!@#&	local wid = width!@#&	if not wid then wid = w - 3 end!@#&!@#&	local function updateDisplayList(items, loc, len)!@#&		local ret = {}!@#&		for i = 1, len do!@#&			local item = items[i + loc - 1]!@#&			if item then table.insert(ret, item) end!@#&		end!@#&		return ret!@#&	end!@#&!@#&	if isAdvanced() then!@#&		local function draw(a)!@#&			for i, v in ipairs(a) do!@#&				term.setCursorPos(x, y + i - 1)!@#&				write(string.rep(\" \", wid))!@#&				term.setCursorPos(x, y + i - 1)!@#&				write(\"[ \" .. v:sub(1, wid - 5))!@#&				term.setCursorPos(wid + x - 2, y + i - 1)!@#&				write(\"  ]\")!@#&			end!@#&		end!@#&!@#&		local loc = 1!@#&		local disList = updateDisplayList(list, loc, len)!@#&		draw(disList)!@#&		!@#&		while true do!@#&			local e, but, clx, cly = os.pullEvent()!@#&			if e == \"key\" and but == 200 and loc > 1 then!@#&				loc = loc - 1!@#&				disList = updateDisplayList(list, loc, len)!@#&				draw(disList)!@#&			elseif e == \"key\" and but == 208 and loc + len - 1 < #list then!@#&				loc = loc + 1!@#&				disList = updateDisplayList(list, loc, len)!@#&				draw(disList)!@#&			elseif e == \"mouse_scroll\" and but > 0 and loc + len - 1 < #list then!@#&				loc = loc + but!@#&				disList = updateDisplayList(list, loc, len)!@#&				draw(disList)!@#&			elseif e == \"mouse_scroll\" and but < 0 and loc > 1 then!@#&				loc = loc + but!@#&				disList = updateDisplayList(list, loc, len)!@#&				draw(disList)!@#&			elseif e == \"mouse_click\" then!@#&				for i, v in ipairs(disList) do!@#&					if clx >= x and clx <= x + wid and cly + coffset == i + y - 1 then return v end!@#&				end!@#&			end!@#&		end!@#&	else!@#&		local function draw(a)!@#&			for i, v in ipairs(a) do!@#&				term.setCursorPos(x, y + i - 1)!@#&				write(string.rep(\" \", wid))!@#&				term.setCursorPos(x, y + i - 1)!@#&				write(\"[ ] \" .. v:sub(1, wid - 5))!@#&			end!@#&		end!@#&!@#&		local loc = 1!@#&		local curSel = 1!@#&		local disList = updateDisplayList(list, loc, len)!@#&		draw(disList)!@#&		term.setCursorPos(x + 1, y + curSel - 1)!@#&		write(\"x\")!@#&!@#&		while true do!@#&			local e, key = os.pullEvent()!@#&			term.setCursorPos(x + 1, y + curSel - 1)!@#&			write(\" \")!@#&			if e == \"key\" and key == 200 then!@#&				if curSel > 1 then curSel = curSel - 1!@#&				elseif loc > 1 then!@#&					loc = loc - 1!@#&					disList = updateDisplayList(list, loc, len)!@#&					draw(disList)!@#&				end!@#&			elseif e == \"key\" and key == 208 then!@#&				if curSel < #disList then curSel = curSel + 1!@#&				elseif loc + len - 1 < #list then!@#&					loc = loc + 1!@#&					disList = updateDisplayList(list, loc, len)!@#&					draw(disList)!@#&				end!@#&			elseif e == \"key\" and key == 28 then return list[curSel + loc - 1] end!@#&			term.setCursorPos(x + 1, y + curSel - 1)!@#&			write(\"x\")!@#&		end!@#&	end!@#&end!@#&!@#&-- Set Environment!@#&for k, v in pairs(getfenv(0)) do env[k] = v end!@#&for k, v in pairs(getfenv(1)) do env[k] = v end!@#&for k, v in pairs(env) do oldEnv[k] = v end!@#&for k, v in pairs(api) do env[k] = v end!@#&!@#&!@#&--  -------- Override!@#&!@#&for k, v in pairs(env) do override[k] = v end!@#&local curtext, curbackground = colors.white, colors.black!@#&override.term = {}!@#&for k, v in pairs(env.term) do override.term[k] = v end!@#&override.os = {}!@#&for k, v in pairs(env.os) do override.os[k] = v end!@#&!@#&override.term.getSize = function()!@#&	local a, b = env.term.getSize()!@#&	return a, b - 2!@#&end!@#&!@#&override.term.setCursorPos = function(x, y)!@#&	if y < 1 then return env.term.setCursorPos(x, 2)!@#&	else return env.term.setCursorPos(x, y + 1) end!@#&end!@#&!@#&override.term.getCursorPos = function()!@#&	local x, y = env.term.getCursorPos()!@#&	return x, y - 1!@#&end!@#&!@#&override.term.getBackgroundColor = function() return curbackground end!@#&override.term.getBackgroundColour = function() return override.term.getBackgroundColor() end!@#&!@#&override.term.setBackgroundColor = function(col)!@#&	curbackground = col!@#&	return env.term.setBackgroundColor(col)!@#&end!@#&!@#&override.term.setBackgroundColour = function(col) return override.term.setBackgroundColor(col) end!@#&!@#&override.term.getTextColor = function() return curtext end!@#&override.term.getTextColour = function() return override.term.getTextColor() end!@#&!@#&override.term.setTextColor = function(col)!@#&	curtext = col!@#&	return env.term.setTextColor(col)!@#&end!@#&!@#&override.term.setTextColour = function(col) return override.term.setTextColor(col) end!@#&!@#&override.term.clear = function()!@#&	local x, y = term.getCursorPos()!@#&	local oldbackground = override.term.getBackgroundColor()!@#&	local oldtext = override.term.getTextColor()!@#&	clear(website, curbackground)!@#&!@#&	term.setBackgroundColor(oldbackground)!@#&	term.setTextColor(oldtext)!@#&	term.setCursorPos(x, y)!@#&end!@#&!@#&override.term.scroll = function(n)!@#&	local x, y = term.getCursorPos()!@#&	local oldbackground = override.term.getBackgroundColor()!@#&	local oldtext = override.term.getTextColor()!@#&!@#&	env.term.scroll(n)!@#&	clear(website, curbackground, true)!@#&	term.setBackgroundColor(oldbackground)!@#&	term.setTextColor(oldtext)!@#&	term.setCursorPos(x, y)!@#&end!@#&!@#&override.term.isColor = function() return isAdvanced() end!@#&override.term.isColour = function() return override.term.isColor() end!@#&!@#&override.os.queueEvent = function(event, ...)!@#&	if event == \"terminate\" or event == event_exit then return end!@#&	if event == event_error and not websiteerror then return end!@#&	env.os.queueEvent(event, ...)!@#&end!@#&!@#&override.prompt = function(list, dir)!@#&	local a = {}!@#&	for k, v in pairs(list) do!@#&		table.insert(a, {v[1], v[2], v[3] + 1, tc = v.tc or curtext,!@#&			bg = v.bg or curbackground, coffset = 1})!@#&	end!@#&	return env.prompt(a, dir)!@#&end!@#&!@#&override.scrollingPrompt = function(list, x, y, len, width)!@#&	return env.scrollingPrompt(list, x, y + 1, len, width, 1)!@#&end!@#&!@#&local barTerm = {}!@#&for k, v in pairs(override.term) do barTerm[k] = v end!@#&barTerm.clear = override.term.clear!@#&barTerm.scroll = override.term.scroll!@#&!@#&local safeTerm = {}!@#&for k, v in pairs(term) do safeTerm[k] = v end!@#&!@#&override.showBar = function()!@#&	offsetclick, clickableAddressBar = true, true!@#&	return os.pullEvent, barTerm!@#&end!@#&!@#&override.hideBar = function()!@#&	offsetclick, clickableAddressBar = false, false!@#&	return os.pullEvent, safeTerm!@#&end!@#&!@#&setfenv(api.saveFileToUserComputer, override)!@#&!@#&!@#&--  -------- Antivirus!@#&!@#&local antivirusOverrides = {!@#&	[\"Run Files\"] = {\"shell.run\", \"os.run\"},!@#&	[\"Modify System\"] = {\"shell.setAlias\", \"shell.clearAlias\", \"os.setComputerLabel\", !@#&		\"shell.setDir\", \"shell.setPath\"},!@#&	[\"Modify Files\"] = {\"fs.makeDir\", \"fs.move\", \"fs.copy\", \"fs.delete\", \"fs.open\",!@#&		\"io.open\", \"io.write\", \"io.read\", \"io.close\"},!@#&	[\"Shutdown Computer\"] = {\"os.shutdown\", \"os.reboot\", \"shell.exit\"}!@#&}!@#&!@#&local antivirusDestroy = {!@#&	\"rawset\", \"rawget\", \"setfenv\", \"loadfile\", \"loadstring\", \"dofile\", \"getfenv\"!@#&}!@#&!@#&local function triggerAntivirus(offence, onlyCancel)!@#&	local oldback, oldtext = curbackground, curtext!@#&	local ox, oy = term.getCursorPos()!@#&	openAddressBar = false!@#&	term.setBackgroundColor(colors[theme[\"address-bar-background\"]])!@#&	term.setTextColor(colors[theme[\"address-bar-text\"]])!@#&	term.setCursorPos(2, 1)!@#&	term.clearLine()!@#&	write(\"Request: \" .. offence)!@#&	term.setCursorPos(w - 8, 1)!@#&	write(\"[C]ancel\")!@#&	if not onlyCancel then!@#&		term.setCursorPos(w - 16, 1)!@#&		write(\"[A]llow\")!@#&	end!@#&!@#&	offsetclick = false!@#&	local stat = \"\"!@#&	while true do!@#&		local e, but, x, y = env.os.pullEvent()!@#&		if e == \"mouse_click\" and y == 1 then!@#&			if x >= w - 8 and x <= w - 1 then stat = \"cancel\"!@#&			elseif not onlyCancel and x >= w - 16 and x <= w - 9 then stat = \"allow\" end!@#&		elseif e == \"char\" and but == \"c\" then stat = \"cancel\"!@#&		elseif e == \"char\" and not onlyCancel and but == \"a\" then stat = \"allow\" end!@#&		if stat ~= \"\" then break end!@#&	end!@#&	offsetclick = true!@#&!@#&	clear(website, nil, true)!@#&	term.setTextColor(colors.white)!@#&	term.setBackgroundColor(colors.black)!@#&	term.setCursorPos(ox, oy)!@#&	term.setBackgroundColor(oldback)!@#&	term.setTextColor(oldtext)!@#&	if not onlyCancel and stat == \"allow\" then!@#&		-- To prevent the menu bar from opening!@#&		os.queueEvent(\"firewolf_requiredEvent\")!@#&		os.pullEvent()!@#&!@#&		openAddressBar = true!@#&		return true!@#&	elseif stat == \"cancel\" then!@#&		openAddressBar = true!@#&		redirect(\"home\")!@#&	end!@#&end!@#&!@#&for k, v in pairs(override) do antivirus[k] = v end!@#&!@#&antivirus.shell = {}!@#&for k, v in pairs(override.shell) do antivirus.shell[k] = v end!@#&antivirus.os = {}!@#&for k, v in pairs(override.os) do antivirus.os[k] = v end!@#&antivirus.fs = {}!@#&for k, v in pairs(override.fs) do antivirus.fs[k] = v end!@#&antivirus.io = {}!@#&for k, v in pairs(override.io) do antivirus.io[k] = v end!@#&!@#&for warning, v in pairs(antivirusOverrides) do!@#&	for k, func in pairs(v) do!@#&		if func:find(\".\", 1, true) then!@#&			-- Functions in another table!@#&			local table = func:sub(1, func:find(\".\", 1, true) - 1)!@#&			local funcname = func:sub(func:find(\".\", 1, true) + 1, -1)!@#&!@#&			antivirus[table][funcname] = function(...)!@#&				env.setfenv(triggerAntivirus, env)!@#&				if triggerAntivirus(warning) then!@#&					return override[table][funcname](...)!@#&				end!@#&			end!@#&		else!@#&			-- Plain functions!@#&			antivirus[func] = function(...)!@#&				env.setfenv(triggerAntivirus, env)!@#&				if triggerAntivirus(warning) then!@#&					return override[func](...)!@#&				end!@#&			end!@#&		end!@#&	end!@#&end!@#&!@#&for k, v in pairs(antivirusDestroy) do!@#&	antivirus[v] = function(...)!@#&		env.setfenv(triggerAntivirus, env)!@#&		triggerAntivirus(\"Destory your System! D:\", true)!@#&		return nil!@#&	end!@#&end!@#&!@#&antivirus.pcall = function(...)!@#&	local suc, err = env.pcall(...)!@#&	if err:lower():find(\"terminate\") then error(\"terminate\") end!@#&	return suc, err!@#&end!@#&!@#&!@#&--  -------- Themes!@#&!@#&local defaultTheme = {!@#&	[\"address-bar-text\"] = \"white\",!@#&	[\"address-bar-background\"] = \"gray\",!@#&	[\"address-bar-base\"] = \"lightGray\",!@#&	[\"top-box\"] = \"red\",!@#&	[\"bottom-box\"] = \"orange\",!@#&	[\"text-color\"] = \"white\",!@#&	[\"background\"] = \"gray\"!@#&} local originalTheme = {!@#&	[\"address-bar-text\"] = \"white\",!@#&	[\"address-bar-background\"] = \"black\",!@#&	[\"address-bar-base\"] = \"black\",!@#&	[\"top-box\"] = \"black\",!@#&	[\"bottom-box\"] = \"black\",!@#&	[\"text-color\"] = \"white\",!@#&	[\"background\"] = \"black\"!@#&}!@#&!@#&local function loadTheme(path)!@#&	if fs.exists(path) and not fs.isDir(path) then!@#&		local a = {}!@#&		local f = io.open(path, \"r\")!@#&		local l = f:read(\"*l\")!@#&		while l do!@#&			l = l:gsub(\"^%s*(.-)%s*$\", \"%1\")!@#&			if l and l ~= \"\" and l ~= \"\\n\" and l:sub(1, 2) ~= \"--\" then!@#&				local k, v = string.match(l, \"^(%a+)=(%a+)\")!@#&				if k and v then a[k] = v!@#&				else return nil end!@#&			end!@#&			l = f:read(\"*l\")!@#&		end!@#&		f:close()!@#&		return a!@#&	end!@#&	return nil!@#&end!@#&!@#&!@#&--  -------- Filesystem!@#&!@#&local function download(url, path)!@#&	for i = 1, 3 do!@#&		local response = http.get(url)!@#&		if response then!@#&			local data = response.readAll()!@#&			response.close()!@#&			if path then!@#&				local f = io.open(path, \"w\")!@#&				f:write(data)!@#&				f:close()!@#&			end!@#&			return true!@#&		end!@#&	end!@#&!@#&	return false!@#&end!@#&!@#&local function updateClient()!@#&	local skipNormal = false!@#&	if serverID ~= \"experimental\" then!@#&		http.request(buildURL)!@#&		local a = os.startTimer(10)!@#&		while true do!@#&			local e, url, handle = os.pullEvent()!@#&			if e == \"http_success\" then!@#&				local b = handle.readAll():gsub(\"^%s*(.-)%s*$\", \"%1\")!@#&				if not tonumber(b) or tonumber(b) > build then break!@#&				else return false end!@#&			elseif e == \"http_failure\" or (e == \"timer\" and url == a) then!@#&				skipNormal = true!@#&				break!@#&			end!@#&		end!@#&	end!@#&!@#&	local source = nil!@#&	if not skipNormal then!@#&		local _, y = term.getCursorPos()!@#&		term.setCursorPos(1, y - 2)!@#&		rightWrite(string.rep(\" \", 32))!@#&		rightWrite(\"Updating Firewolf... \")!@#&!@#&		http.request(firewolfURL)!@#&		local a = os.startTimer(10)!@#&		while true do!@#&			local e, url, handle = os.pullEvent()!@#&			if e == \"http_success\" then!@#&				source = handle!@#&				break!@#&			elseif e == \"http_failure\" or (e == \"timer\" and url == a) then!@#&				break!@#&			end!@#&		end!@#&	end!@#&!@#&	if not source then!@#&		if isAdvanced() then!@#&			term.setTextColor(colors[theme[\"text-color\"]])!@#&			term.setBackgroundColor(colors[theme[\"background\"]])!@#&			term.clear()!@#&			if not fs.exists(rootFolder) then fs.makeDir(rootFolder) end!@#&			local f = io.open(rootFolder .. \"/temp_file\", \"w\")!@#&			f:write(graphics.githubImage)!@#&			f:close()!@#&			local a = paintutils.loadImage(rootFolder .. \"/temp_file\")!@#&			paintutils.drawImage(a, 5, 5)!@#&			sleep(0.2)!@#&			fs.delete(rootFolder .. \"/temp_file\")!@#&!@#&			term.setCursorPos(19, 4)!@#&			term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&			write(string.rep(\" \", 32))!@#&			term.setCursorPos(19, 5)!@#&			write(\"  Could Not Connect to GitHub!  \")!@#&			term.setCursorPos(19, 6)!@#&			write(string.rep(\" \", 32))!@#&			term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&			term.setCursorPos(19, 8)!@#&			write(string.rep(\" \", 32))!@#&			term.setCursorPos(19, 9)!@#&			write(\"    Sorry, Firewolf could not   \")!@#&			term.setCursorPos(19, 10)!@#&			write(\" connect to GitHub to download  \")!@#&			term.setCursorPos(19, 11)!@#&			write(\" necessary files. Please check: \")!@#&			term.setCursorPos(19, 12)!@#&			write(\"    http://status.github.com    \")!@#&			term.setCursorPos(19, 13)!@#&			write(string.rep(\" \", 32))!@#&			term.setCursorPos(19, 14)!@#&			write(\"        Click to exit...        \")!@#&			term.setCursorPos(19, 15)!@#&			write(string.rep(\" \", 32))!@#&		else!@#&			term.clear()!@#&			term.setCursorPos(1, 1)!@#&			term.setBackgroundColor(colors.black)!@#&			term.setTextColor(colors.white)!@#&			print(\"\\n\")!@#&			centerPrint(\"Could not connect to GitHub!\")!@#&			print(\"\")!@#&			centerPrint(\"Sorry, Firewolf could not connect to\")!@#&			centerPrint(\"GitHub to download necessary files.\")!@#&			centerPrint(\"Please check:\")!@#&			centerPrint(\"http://status.github.com\")!@#&			print(\"\")!@#&			centerPrint(\"Press any key to exit...\")!@#&		end!@#&!@#&		while true do!@#&			local e = os.pullEvent()!@#&			if e == \"mouse_click\" or e == \"key\" then break end!@#&		end!@#&!@#&		return false!@#&	elseif source and autoupdate == \"true\" then!@#&		local b = io.open(firewolfLocation, \"r\")!@#&		local new = source.readAll()!@#&		local cur = b:read(\"*a\")!@#&		source.close()!@#&		b:close()!@#&!@#&		if cur ~= new then!@#&			fs.delete(firewolfLocation)!@#&			local f = io.open(firewolfLocation, \"w\")!@#&			f:write(new)!@#&			f:close()!@#&			return true!@#&		else!@#&			return false!@#&		end!@#&	end!@#&end!@#&!@#&local function resetFilesystem()!@#&	-- Migrate!@#&	fs.delete(rootFolder .. \"/available_themes\")!@#&	fs.delete(rootFolder .. \"/default_theme\")!@#&!@#&	-- Reset!@#&	if not fs.exists(rootFolder) then fs.makeDir(rootFolder)!@#&	elseif not fs.isDir(rootFolder) then fs.move(rootFolder, \"/Firewolf_Data.old\") end!@#&!@#&	for _, v in pairs({serverFolder, cacheFolder, websiteDataFolder}) do!@#&		if not fs.isDir(v) then fs.delete(v) end!@#&		if not fs.exists(v) then fs.makeDir(v) end!@#&	end!@#&!@#&	if fs.isDir(settingsLocation) then fs.delete(settingsLocation) end!@#&	if fs.isDir(serverLocation) then fs.delete(serverLocation) end!@#&!@#&	if not fs.exists(settingsLocation) then!@#&		local f = io.open(settingsLocation, \"w\")!@#&		f:write(textutils.serialize({auto = \"true\", incog = \"false\", home = \"firewolf\"}))!@#&		f:close()!@#&	end!@#&!@#&	if not fs.exists(serverLocation) then download(serverURL, serverLocation) end!@#&	fs.delete(rootFolder .. \"/temp_file\")!@#&!@#&	for _, v in pairs({userWhitelist, userBlacklist}) do!@#&		if fs.isDir(v) then fs.delete(v) end!@#&		if not fs.exists(v) then!@#&			local f = io.open(v, \"w\")!@#&			f:write(\"\")!@#&			f:close()!@#&		end!@#&	end!@#&end!@#&!@#&local function checkForModem(display)!@#&	while true do!@#&		local present = false!@#&		for _, v in pairs(rs.getSides()) do!@#&			if peripheral.getType(v) == \"modem\" then rednet.open(v) present = true break end!@#&		end!@#&!@#&		if not present and type(display) == \"function\" then display() os.pullEvent(\"peripheral\")!@#&		else return true end!@#&	end!@#&end!@#&!@#&!@#&--  -------- Databases!@#&!@#&local function loadDatabases()!@#&	if fs.exists(userBlacklist) and not fs.isDir(userBlacklist) then!@#&		local bf = io.open(userBlacklist, \"r\")!@#&		local l = bf:read(\"*l\")!@#&		while l do!@#&			if l and l ~= \"\" and l ~= \"\\n\" then!@#&				l = l:gsub(\"^%s*(.-)%s*$\", \"%1\")!@#&				table.insert(blacklist, l)!@#&			end!@#&			l = bf:read(\"*l\")!@#&		end!@#&		bf:close()!@#&	end!@#&!@#&	if fs.exists(userWhitelist) and not fs.isDir(userWhitelist) then!@#&		local wf = io.open(userWhitelist, \"r\")!@#&		local l = wf:read(\"*l\")!@#&		while l do!@#&			if l and l ~= \"\" and l ~= \"\\n\" then!@#&				l = l:gsub(\"^%s*(.-)%s*$\", \"%1\")!@#&				local a, b = l:find(\"| |\")!@#&				table.insert(whitelist, {l:sub(1, a - 1), l:sub(b + 1, -1)})!@#&			end!@#&			l = wf:read(\"*l\")!@#&		end!@#&		wf:close()!@#&	end!@#&end!@#&!@#&local function verifyBlacklist(id)!@#&	for _, v in pairs(blacklist) do if tostring(id) == v then return true end end!@#&	return false!@#&end!@#&!@#&local function verifyWhitelist(id, url)!@#&	for _, v in pairs(whitelist) do!@#&		if v[2] == tostring(id) and v[1] == tostring(url) then return true end!@#&	end!@#&	return false!@#&end!@#&!@#&!@#&--  -------- Graphics and Files!@#&!@#&graphics.githubImage = [[!@#&f       f!@#&fffffffff!@#&fffffffff!@#&f4244424f!@#&f4444444f!@#&fffffefffe!@#&   fffe e!@#& fffff e!@#&ff f fe e!@#&     e   e!@#&]]!@#&!@#&graphics.nomodem = function()!@#&	term.setTextColor(colors[theme[\"text-color\"]])!@#&	term.setBackgroundColor(colors[theme[\"background\"]])!@#&	term.clear()!@#&	term.setCursorPos(1, 1)!@#&	print(\"\\n\")!@#&	term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&	api.leftPrint(string.rep(\" \", 24))!@#&	api.leftPrint(\" No Modem Attached! D:  \")!@#&	api.leftPrint(string.rep(\" \", 24))!@#&	print(\"\\n\")!@#&!@#&	term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&	api.rightPrint(string.rep(\" \", 40))!@#&	api.rightPrint(\"    No wireless modem was found on this \")!@#&	api.rightPrint(\"  computer, and Firewolf cannot use the \")!@#&	api.rightPrint(\"             RDNT protocol without one! \")!@#&	api.rightPrint(string.rep(\" \", 40))!@#&	api.rightPrint(\"  Waiting for a modem to be attached... \")!@#&	api.rightPrint(string.rep(\" \", 40))!@#&end!@#&!@#&graphics.nonexistantwebpage = function()!@#&	term.setBackgroundColor(colors[theme[\"background\"]])!@#&	term.clear()!@#&	term.setCursorPos(1, 2)!@#&	term.setTextColor(colors[theme[\"text-color\"]])!@#&	term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&	leftPrint(string.rep(\" \", 11))!@#&	leftPrint(\" Oh Noes!  \")!@#&	leftPrint(string.rep(\" \", 11))!@#&	print(\"\\n\")!@#&!@#&	term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&	rightPrint(string.rep(\" \", 43))!@#&	rightPrint([[       ______                          __  ]])!@#&	rightPrint([[      / ____/_____ _____ ____   _____ / /  ]])!@#&	rightPrint([[     / __/  / ___// ___// __ \\ / ___// /   ]])!@#&	rightPrint([[    / /___ / /   / /   / /_/ // /   /_/    ]])!@#&	rightPrint([[   /_____//_/   /_/    \\____//_/   (_)     ]])!@#&	rightPrint(string.rep(\" \", 43))!@#&	rightPrint(\"  Could not connect to the website! It may \")!@#&	rightPrint(\"  be down, or not exist!                   \")!@#&	rightPrint(string.rep(\" \", 43))!@#&end!@#&!@#&graphics.nosearchresults = function()!@#&	term.setBackgroundColor(colors[theme[\"background\"]])!@#&	term.clear()!@#&	term.setCursorPos(1, 5)!@#&	term.setTextColor(colors[theme[\"text-color\"]])!@#&	term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&	centerPrint(string.rep(\" \", 40))!@#&	centerPrint(\"  No Websites are Currently Online! D:  \")!@#&	centerPrint(string.rep(\" \", 40))!@#&	centerPrint(\"       Why not make one yourself?       \")!@#&	centerPrint(\"          Visit rdnt://server!          \")!@#&	centerPrint(string.rep(\" \", 40))!@#&end!@#&!@#&files.availableThemes = [[!@#&https://raw.github.com/1lann/firewolf/master/themes/default.txt| |Fire (default)!@#&https://raw.github.com/1lann/firewolf/master/themes/ice.txt| |Ice!@#&https://raw.github.com/1lann/firewolf/master/themes/carbon.txt| |Carbon!@#&https://raw.github.com/1lann/firewolf/master/themes/christmas.txt| |Christmas!@#&https://raw.github.com/1lann/firewolf/master/themes/original.txt| |Original!@#&https://raw.github.com/1lann/firewolf/master/themes/ocean.txt| |Ocean!@#&https://raw.github.com/1lann/firewolf/master/themes/forest.txt| |Forest!@#&https://raw.github.com/1lann/firewolf/master/themes/pinky.txt| |Pinky!@#&https://raw.github.com/1lann/firewolf/master/themes/azhftech.txt| |AzhfTech!@#&]]!@#&!@#&files.newTheme = [[!@#&-- Address bar text color!@#&address-bar-text=!@#&!@#&-- Address bar background color!@#&address-bar-background=!@#&!@#&-- Color of separator bar on live search dropdown!@#&address-bar-base=!@#&!@#&-- Top box background color!@#&top-box=!@#&!@#&-- Bottom box background color!@#&bottom-box=!@#&!@#&-- Main background color!@#&background=!@#&!@#&-- Main text color!@#&text-color=!@#&!@#&]]!@#&!@#&!@#&--  -------- Protocols!@#&!@#&protocols.rdnt = {}!@#&protocols.http = {}!@#&!@#&protocols.rdnt.getSearchResults = function()!@#&	dnsDatabase = {[1] = {}, [2] = {}}!@#&	local resultIDs = {}!@#&	local conflict = {}!@#&!@#&	rednet.broadcast(\"firewolf.broadcast.dns.list\")!@#&	local startClock = os.clock()!@#&	while os.clock() - startClock < timeout do!@#&		local id, i = rednet.receive(timeout)!@#&		if id then!@#&			if i:sub(1, 14) == \"firewolf-site:\" then!@#&				i = i:sub(15, -1)!@#&				local bl, wl = verifyBlacklist(id), verifyWhitelist(id, i)!@#&				if not i:find(\" \") and i:len() < 40 and (not bl or (bl and wl)) then!@#&					if not resultIDs[tostring(id)] then resultIDs[tostring(id)] = 1!@#&					else resultIDs[tostring(id)] = resultIDs[tostring(id)] + 1 end!@#&					!@#&					if not i:find(\"rdnt://\") then i = (\"rdnt://\" .. i) end!@#&					local x = false!@#&					if conflict[i] then!@#&						x = true!@#&						table.insert(conflict[i], id)!@#&					else!@#&						for m, n in pairs(dnsDatabase[1]) do!@#&							if n:lower() == i:lower() then!@#&								x = true!@#&								table.remove(dnsDatabase[1], m)!@#&								table.remove(dnsDatabase[2], m)!@#&								if conflict[i] then table.insert(conflict[i], id)!@#&								else conflict[i] = {} table.insert(conflict[i], id) end!@#&								break!@#&							end!@#&						end!@#&					end!@#&!@#&					if not x and resultIDs[tostring(id)] <= 3 then!@#&						table.insert(dnsDatabase[1], i)!@#&						table.insert(dnsDatabase[2], id)!@#&					end!@#&				end!@#&			end!@#&		else break end!@#&	end!@#&!@#&	for k, v in pairs(conflict) do!@#&		table.sort(v)!@#&		table.insert(dnsDatabase[1], k)!@#&		table.insert(dnsDatabase[2], v[1])!@#&	end!@#&end!@#&!@#&protocols.rdnt.getWebsite = function(site)!@#&	local id, content, status = nil, nil, nil!@#&	local clock = os.clock()!@#&	local websiteID = nil!@#&	for k, v in pairs(dnsDatabase[1]) do!@#&		local web = site:gsub(\"rdnt://\", \"\")!@#&		if web:find(\"/\") then web = web:sub(1, web:find(\"/\") - 1) end!@#&		if web == v:gsub(\"rdnt://\", \"\") then websiteID = dnsDatabase[2][k] break end!@#&	end!@#&	if not websiteID then return nil, nil, nil end!@#&!@#&	sleep(timeout)!@#&	rednet.send(websiteID, site)!@#&	clock = os.clock()!@#&	while os.clock() - clock < timeout do!@#&		id, content = rednet.receive(timeout)!@#&		if id and id == websiteID then!@#&			local bl, wl = verifyBlacklist(id), verifyWhitelist(id, site)!@#&			status = nil!@#&			if (bl and not wl) or site == \"\" or site == \".\" or site == \"..\" then!@#&				-- Ignore!@#&			elseif wl then status = \"whitelist\" break!@#&			else status = \"safe\" break end!@#&		end!@#&	end!@#&!@#&	return id, content, status!@#&end!@#&!@#&protocols.http.getSearchResults = function()!@#&	dnsDatabase = {[1] = {}, [2] = {}}!@#&end!@#&!@#&protocols.http.getWebsite = function(site)!@#&	return nil, nil, nil!@#&end!@#&!@#&!@#&--  -------- Homepage!@#&!@#&pages[\"firewolf\"] = function()!@#&	term.setBackgroundColor(colors[theme[\"background\"]])!@#&	term.clear()!@#&	term.setTextColor(colors[theme[\"text-color\"]])!@#&	term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&	print(\"\")!@#&	leftPrint(string.rep(\" \", 42))!@#&	leftPrint([[        _,-='\"-.__               /\\_/\\    ]])!@#&	leftPrint([[         -.}        =._,.-==-._.,  @ @._, ]])!@#&	leftPrint([[            -.__  __,-.   )       _,.-'   ]])!@#&	leftPrint([[ Firewolf ]] .. version .. string.rep(\" \", 8 - version:len()) ..!@#&		[[\"    G..m-\"^m m'        ]])!@#&	leftPrint(string.rep(\" \", 42))!@#&	print(\"\\n\")!@#&!@#&	term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&	rightPrint(string.rep(\" \", 42))!@#&	if isAdvanced() then rightPrint(\"  News:                       [- Sites -] \")!@#&	else rightPrint(\"  News:                                   \") end!@#&	rightPrint(\"     Firewolf 2.5 is out! It rewrites the \")!@#&	rightPrint(\"    whole Firewolf's internals (again :P) \")!@#&	rightPrint(string.rep(\" \", 42))!@#&	rightPrint(\"   Firewolf 3.0 will be out soon! It will \")!@#&	rightPrint(\"     bring the long awaited HTTP support! \")!@#&	rightPrint(string.rep(\" \", 42))!@#&!@#&	while true do!@#&		local e, but, x, y = os.pullEvent()!@#&		if e == \"mouse_click\" and x >= 40 and x <= 50 and y == 11 then redirect(\"sites\") end!@#&	end!@#&end!@#&!@#&pages[\"sites\"] = function()!@#&	term.setBackgroundColor(colors[theme[\"background\"]])!@#&	term.clear()!@#&	term.setTextColor(colors[theme[\"text-color\"]])!@#&	term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&	print(\"\\n\")!@#&	leftPrint(string.rep(\" \", 17))!@#&	leftPrint(\" Built-In Sites  \")!@#&	leftPrint(string.rep(\" \", 17))!@#&!@#&	local sx = 8!@#&	term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&	term.setCursorPos(1, sx)!@#&	rightPrint(string.rep(\" \", 40))!@#&	rightPrint(\"  rdnt://firewolf              Homepage \")!@#&	rightPrint(\"  rdnt://sites                    Sites \")!@#&	rightPrint(\"  rdnt://server       Server Management \")!@#&	rightPrint(\"  rdnt://help                 Help Page \")!@#&	rightPrint(\"  rdnt://settings              Settings \")!@#&	rightPrint(\"  rdnt://credits                Credits \")!@#&	rightPrint(\"  rdnt://exit                      Exit \")!@#&	rightPrint(string.rep(\" \", 40))!@#&!@#&	local a = {\"firewolf\", \"sites\", \"server\", \"help\", \"settings\", \"credits\", \"exit\"}!@#&	while true do!@#&		local e, but, x, y = os.pullEvent()!@#&		if e == \"mouse_click\" and x >= 14 and x <= 50 then!@#&			for i, v in ipairs(a) do if y == sx + i and v ~= \"exit\" then redirect(v) end end!@#&		end!@#&	end!@#&end!@#&!@#&!@#&--  -------- Server Management!@#&!@#&local function manageServers(site, protocol, functionList, startServerName)!@#&	local servers = functionList[\"reload servers\"]()!@#&	local sy = 7!@#&!@#&	if not startServerName then startServerName = \"Start\" end!@#&	if isAdvanced() then!@#&		local function draw(l, sel)!@#&			term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&			term.setCursorPos(4, sy)!@#&			write(\"[- New Server -]\")!@#&			for i, v in ipairs(l) do!@#&				term.setCursorPos(3, i + sy)!@#&				write(string.rep(\" \", 24))!@#&				term.setCursorPos(4, i + sy)!@#&				local nv = v!@#&				if nv:len() > 18 then nv = nv:sub(1, 15) .. \"...\" end!@#&				if i == sel then write(\"[ \" .. nv .. \" ]\")!@#&				else write(\"  \" .. nv) end!@#&			end!@#&!@#&			if #l < 1 then!@#&				term.setCursorPos(4, sy + 2)!@#&				write(\"A website is literally\")!@#&				term.setCursorPos(4, sy + 3)!@#&				write(\"just a lua script!\")!@#&				term.setCursorPos(4, sy + 4)!@#&				write(\"Go ahead and make one!\")!@#&				term.setCursorPos(4, sy + 6)!@#&				write(\"Also, be sure to check\")!@#&				term.setCursorPos(4, sy + 7)!@#&				write(\"out Firewolf's APIs to\")!@#&				term.setCursorPos(4, sy + 8)!@#&				write(\"help you make your\")!@#&				term.setCursorPos(4, sy + 9)!@#&				write(\"site, at rdnt://help\")!@#&			end!@#&!@#&			term.setCursorPos(30, sy)!@#&			write(string.rep(\" \", 19))!@#&			term.setCursorPos(30, sy)!@#&			if l[sel] then!@#&				local nl = l[sel]!@#&				if nl:len() > 19 then nl = nl:sub(1, 16) .. \"...\" end!@#&				write(nl)!@#&			else write(\"No Server Selected!\") end!@#&			term.setCursorPos(30, sy + 2)!@#&			write(\"[- \" .. startServerName .. \" -]\")!@#&			term.setCursorPos(30, sy + 4)!@#&			write(\"[- Edit -]\")!@#&			term.setCursorPos(30, sy + 6)!@#&			if functionList[\"run on boot\"] then write(\"[- Run on Boot -]\") end!@#&			term.setCursorPos(30, sy + 8)!@#&			write(\"[- Delete -]\")!@#&		end!@#&!@#&		local function updateDisplayList(items, loc, len)!@#&			local ret = {}!@#&			for i = 1, len do!@#&				if items[i + loc - 1] then table.insert(ret, items[i + loc - 1]) end!@#&			end!@#&			return ret!@#&		end!@#&!@#&		while true do!@#&			term.setBackgroundColor(colors[theme[\"background\"]])!@#&			term.clear()!@#&			term.setCursorPos(1, 1)!@#&			term.setTextColor(colors[theme[\"text-color\"]])!@#&			term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&			print(\"\")!@#&			leftPrint(string.rep(\" \", 27))!@#&			leftPrint(\" Server Management - \" .. protocol:upper() .. \"  \")!@#&			leftPrint(string.rep(\" \", 27))!@#&			print(\"\")!@#&!@#&			term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&			for i = 1, 12 do!@#&				term.setCursorPos(3, i + sy - 2)!@#&				write(string.rep(\" \", 24))!@#&				term.setCursorPos(29, i + sy - 2)!@#&				write(string.rep(\" \", 21))!@#&			end!@#&!@#&			local sel, loc, len = 1, 1, 10!@#&			local disList = updateDisplayList(servers, loc, len)!@#&			draw(disList, sel)!@#&!@#&			while true do!@#&				local e, but, x, y = os.pullEvent()!@#&				if e == \"key\" and but == 200 and #servers > 0 and loc > 1 then!@#&					loc = loc - 1!@#&					disList = updateDisplayList(servers, loc, len)!@#&					draw(disList, sel)!@#&				elseif e == \"key\" and but == 208 and #servers > 0 and loc + len - 1 < #servers then!@#&					loc = loc + 1!@#&					disList = updateDisplayList(servers, loc, len)!@#&					draw(disList, sel)!@#&				elseif e == \"mouse_click\" then!@#&					if x >= 4 and x <= 25 then!@#&						if y == 7 then!@#&							functionList[\"new server\"]()!@#&							servers = functionList[\"reload servers\"]()!@#&							break!@#&						elseif #servers > 0 then!@#&							for i, v in ipairs(disList) do!@#&								if y == i + 7 then!@#&									sel = i!@#&									draw(disList, sel)!@#&								end!@#&							end!@#&						end!@#&					elseif x >= 30 and x <= 40 and y == 9 and #servers > 0 then!@#&						functionList[\"start\"](disList[sel])!@#&						servers = functionList[\"reload servers\"]()!@#&						break!@#&					elseif x >= 30 and x <= 39 and y == 11 and #servers > 0 then!@#&						functionList[\"edit\"](disList[sel])!@#&						servers = functionList[\"reload servers\"]()!@#&						break!@#&					elseif x >= 30 and x <= 46 and y == 13 and #servers > 0 and!@#&							functionList[\"run on boot\"] then!@#&						functionList[\"run on boot\"](disList[sel])!@#&						term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&						term.setCursorPos(32, 15)!@#&						write(\"Will Run on Boot!\")!@#&						openAddressBar = false!@#&						sleep(1.3)!@#&						openAddressBar = true!@#&						term.setCursorPos(32, 15)!@#&						write(string.rep(\" \", 18))!@#&						break!@#&					elseif x >= 30 and x <= 41 and y == 15 and #servers > 0 then!@#&						functionList[\"delete\"](disList[sel])!@#&						servers = functionList[\"reload servers\"]()!@#&						break!@#&					end!@#&				end!@#&			end!@#&		end!@#&	else!@#&		while true do!@#&			term.setBackgroundColor(colors[theme[\"background\"]])!@#&			term.clear()!@#&			term.setCursorPos(1, 1)!@#&			term.setTextColor(colors[theme[\"text-color\"]])!@#&			term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&			print(\"\")!@#&			centerPrint(string.rep(\" \", 27))!@#&			centerPrint(\" Server Management - \" .. protocol:upper() .. \"  \")!@#&			centerPrint(string.rep(\" \", 27))!@#&			print(\"\")!@#&!@#&			local a = {\"New Server\"}!@#&			for _, v in pairs(servers) do table.insert(a, v) end!@#&			local server = scrollingPrompt(a, 4, 7, 10)!@#&			if server == \"New Server\" then!@#&				functionList[\"new server\"]()!@#&				servers = functionList[\"reload servers\"]()!@#&			else!@#&				term.setCursorPos(30, 8)!@#&				write(server)!@#&				local a = {{\"Start\", 30, 9}, {\"Edit\", 30, 11}, {\"Run on Boot\", 30, 12},!@#&					{\"Delete\", 30, 13}, {\"Back\", 30, 15}}!@#&				if not functionList[\"run on boot\"] then!@#&					a = {{\"Start\", 30, 9}, {\"Edit\", 30, 11}, {\"Delete\", 30, 13}, {\"Back\", 30, 15}}!@#&				end!@#&				local opt = prompt(a, \"vertical\")!@#&				if opt == \"Start\" then!@#&					functionList[\"start\"](server)!@#&					servers = functionList[\"reload servers\"]()!@#&				elseif opt == \"Edit\" then!@#&					functionList[\"edit\"](server)!@#&					servers = functionList[\"reload servers\"](server)!@#&				elseif opt == \"Run on Boot\" and functionList[\"run on boot\"] then!@#&					functionList[\"run on boot\"](server)!@#&					term.setCursorPos(32, 16)!@#&					write(\"Will Run on Boot!\")!@#&					openAddressBar = false!@#&					sleep(1.3)!@#&					openAddressBar = true!@#&				elseif opt == \"Delete\" then!@#&					functionList[\"delete\"](server)!@#&					servers = functionList[\"reload servers\"]()!@#&				end!@#&			end!@#&		end!@#&	end!@#&end!@#&!@#&local function editPages(dir)!@#&	local oldLoc = shell.dir()!@#&	local commandHis = {}!@#&	term.setBackgroundColor(colors.black)!@#&	term.setTextColor(colors.white)!@#&	term.clear()!@#&	term.setCursorPos(1, 1)!@#&	print(\"\")!@#&	print(\" Server Shell Editing\")!@#&	print(\" Type 'exit' to return to Firewolf.\")!@#&	print(\" The 'home' file is the index of your site.\")!@#&	print(\"\")!@#&!@#&	local allowed = {\"move\", \"mv\", \"cp\", \"copy\", \"drive\", \"delete\", \"rm\", \"edit\",!@#&		\"eject\", \"exit\", \"help\", \"id\", \"monitor\", \"rename\", \"alias\", \"clear\",!@#&		\"paint\", \"lua\", \"redstone\", \"rs\", \"redprobe\", \"redpulse\", \"programs\",!@#&		\"redset\", \"reboot\", \"hello\", \"label\", \"list\", \"ls\", \"easter\", \"pastebin\", \"dir\"}!@#&	!@#&	while true do!@#&		shell.setDir(dir)!@#&		term.setBackgroundColor(colors.black)!@#&		if isAdvanced() then term.setTextColor(colors.yellow)!@#&		else term.setTextColor(colors.white) end!@#&		write(\"> \")!@#&		term.setTextColor(colors.white)!@#&		local line = read(nil, commandHis)!@#&		table.insert(commandHis, line)!@#&!@#&		local words = {}!@#&		for m in string.gmatch(line, \"[^ \\t]+\") do!@#&			local a = m:gsub(\"^%s*(.-)%s*$\", \"%1\")!@#&			table.insert(words, a)!@#&		end!@#&!@#&		local com = words[1]!@#&		if com == \"exit\" then break!@#&		elseif com then!@#&			local a = false!@#&			for _, v in pairs(allowed) do if com == v then a = true break end end!@#&!@#&			if a then!@#&				term.setBackgroundColor(colors.black)!@#&				term.setTextColor(colors.white)!@#&				shell.run(com, unpack(words, 2))!@#&			else!@#&				term.setTextColor(colors.red)!@#&				print(\"Program Not Allowed!\")!@#&			end!@#&		end!@#&	end!@#&	shell.setDir(oldLoc)!@#&end!@#&!@#&local function newServer(onCreate)!@#&	term.setBackgroundColor(colors[theme[\"background\"]])!@#&	for i = 1, 12 do!@#&		term.setCursorPos(3, i + 5)!@#&		term.clearLine()!@#&	end!@#&!@#&	term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&	term.setCursorPos(1, 7)!@#&	for i = 1, 8 do centerPrint(string.rep(\" \", 47)) end!@#&	term.setCursorPos(5, 8)!@#&	write(\"Name: \")!@#&	local name = modRead({refusePrint = \"`\", visibleLength = w - 4, textLength = 200})!@#&	term.setCursorPos(5, 10)!@#&	write(\"URL:\")!@#&	term.setCursorPos(8, 11)!@#&	write(\"rdnt://\")!@#&	local url = modRead({grantPrint = \"abcdefghijklmnopqrstuvwxyz1234567890-_.+\",!@#&		visibleLength = w - 4, textLength = 200})!@#&	url = url:gsub(\" \", \"\")!@#&	if name == \"\" or url == \"\" then!@#&		term.setCursorPos(5, 13)!@#&		write(\"URL or Name is Empty!\")!@#&		openAddressBar = false!@#&		sleep(1.3)!@#&		openAddressBar = true!@#&	else!@#&		local c = onCreate(name, url)!@#&!@#&		term.setCursorPos(5, 13)!@#&		if c and c == \"true\" then write(\"Successfully Created Server!\")!@#&		elseif c == \"false\" or not c then write(\"Server Creation Failed!\")!@#&		else write(c) end!@#&		openAddressBar = false!@#&		sleep(1.3)!@#&		openAddressBar = true!@#&	end!@#&end!@#&!@#&pages[\"server/rdnt\"] = function(site)!@#&	manageServers(site, \"rdnt\", {[\"reload servers\"] = function()!@#&		local servers = {}!@#&		for _, v in pairs(fs.list(serverFolder)) do!@#&			if fs.isDir(serverFolder .. \"/\" .. v) then table.insert(servers, v) end!@#&		end!@#&		return servers!@#&	end, [\"new server\"] = function()!@#&		newServer(function(name, url)!@#&			if fs.exists(serverFolder .. \"/\" .. url) then return \"Server Already Exists!\" end!@#&			fs.makeDir(serverFolder .. \"/\" .. url)!@#&			local f = io.open(serverFolder .. \"/\" .. url .. \"/home\", \"w\")!@#&			f:write(\"print(\\\"\\\")\\ncenterPrint(\\\"Welcome To \" .. name .. \"!\\\")\\n\\n\")!@#&			f:close()!@#&			return \"true\"!@#&		end)!@#&	end, [\"start\"] = function(server)!@#&		term.clear()!@#&		term.setCursorPos(1, 1)!@#&		term.setBackgroundColor(colors.black)!@#&		term.setTextColor(colors.white)!@#&		openAddressBar, offsetclick = false, false!@#&		setfenv(1, oldEnv)!@#&		shell.run(serverLocation, server, serverFolder .. \"/\" .. server)!@#&		setfenv(1, override)!@#&		openAddressBar, offsetclick = true, true!@#&		checkForModem()!@#&	end, [\"edit\"] = function(server)!@#&		openAddressBar, offsetclick = false, false!@#&		editPages(serverFolder .. \"/\" .. server)!@#&		openAddressBar, offsetclick = true, true!@#&		if not fs.exists(serverFolder .. \"/\" .. server .. \"/home\") then!@#&			local f = io.open(serverFolder .. \"/\" .. server .. \"/home\", \"w\")!@#&			f:write(\"print(\\\"\\\")\\ncenterPrint(\\\"Welcome To \" .. server .. \"!\\\")\\n\\n\")!@#&			f:close()!@#&		end!@#&	end, [\"run on boot\"] = function(server)!@#&		fs.delete(\"/old-startup\")!@#&		if fs.exists(\"/startup\") then fs.move(\"/startup\", \"/old-startup\") end!@#&		local f = io.open(\"/startup\", \"w\")!@#&		f:write(\"shell.run(\\\"\" .. serverLocation .. \"\\\", \\\"\" .. server .. \"\\\", \\\"\" ..!@#&			serverFolder .. \"/\" .. server .. \"\\\")\")!@#&		f:close()!@#&	end, [\"delete\"] = function(server)!@#&		fs.delete(serverFolder .. \"/\" .. server)!@#&	end})!@#&end!@#&!@#&pages[\"server/http\"] = function()!@#&	term.setTextColor(colors[theme[\"text-color\"]])!@#&	term.setBackgroundColor(colors[theme[\"background\"]])!@#&	term.clear()!@#&	print(\"\\n\\n\")!@#&	term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&	centerPrint(string.rep(\" \", 17))!@#&	centerPrint(\"  Comming Soon!  \")!@#&	centerPrint(string.rep(\" \", 17))!@#&end!@#&!@#&pages[\"server\"] = function()!@#&	setfenv(manageServers, override)!@#&	setfenv(newServer, override)!@#&	setfenv(editPages, env)!@#&	if curProtocol == protocols.rdnt then redirect(\"server/rdnt\")!@#&	elseif curProtocol == protocols.http then redirect(\"server/http\") end!@#&end!@#&!@#&!@#&--  -------- Help!@#&!@#&pages[\"help\"] = function()!@#&	term.setBackgroundColor(colors[theme[\"background\"]])!@#&	term.clear()!@#&	term.setTextColor(colors[theme[\"text-color\"]])!@#&	term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&	print(\"\")!@#&	leftPrint(string.rep(\" \", 16))!@#&	leftPrint(\" Firewolf Help  \")!@#&	leftPrint(string.rep(\" \", 16))!@#&	print(\"\\n\")!@#&!@#&	term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&	for i = 1, 11 do rightPrint(string.rep(\" \", 41)) end!@#&	term.setCursorPos(1, 15)!@#&	rightPrint(\"         View the full documentation at: \")!@#&	rightPrint(\"  https://github.com/1lann/Firewolf/wiki \")!@#&!@#&	local opt = prompt({{\"Getting Started\", w - 21, 8}, {\"Making a Theme\", w - 20, 10},!@#&		{\"API Documentation\", w - 23, 12}}, \"vertical\")!@#&	local pages = {}!@#&	if opt == \"Getting Started\" then!@#&		pages[1] = {title = \"Getting Started - Intoduction\", content = {!@#&			\"Hey there!\",!@#&			\"\",!@#&			\"Firewolf is an app that allows you to create\",!@#&			\"and visit websites! Each site has an address\",!@#&			\"(the URL) which you can type into the address\",!@#&			\"bar above, and then visit the site.\",!@#&			\"\",!@#&			\"You can open the address bar by clicking on\",!@#&			\"it, or by pressing control.\"!@#&		}} pages[2] = {title = \"Getting Started - Searching\", content = {!@#&			\"The address bar can be also be used to\",!@#&			\"search for sites, by simply typing in the\",!@#&			\"search term.\",!@#&			\"\",!@#&			\"To view all sites, just open it and hit\",!@#&			\"enter (leave the field blank).\"!@#&		}} pages[3] = {title = \"Getting Started - Built-In Websites\", content = {!@#&			\"Firewolf has a set of built-in websites\",!@#&			\"available for use:\",!@#&			\"\",!@#&			\"rdnt://firewolf   Normal hompage\",!@#&			\"rdnt://sites      Built-In Site\",!@#&			\"rdnt://server     Create websites\",!@#&			\"rdnt://help       Help and documentation\"!@#&		}} pages[4] = {title = \"Getting Started - Built-In Websites\", content = {!@#&			\"More built-in websites:\",!@#&			\"\",!@#&			\"rdnt://settings   Firewolf settings\",!@#&			\"rdnt://credits    View the credits\",!@#&			\"rdnt://exit       Exit the app\"!@#&		}}!@#&	elseif opt == \"Making a Theme\" then!@#&		pages[1] = {title = \"Making a Theme - Introduction\", content = {!@#&			\"Firewolf themes are files that tell Firewolf\",!@#&			\"to color which things what.\",!@#&			\"Several themes can already be downloaded for\",!@#&			\"Firewolf from rdnt://settings/themes.\",!@#&			\"\",!@#&			\"You can also make your own theme, use it in\",!@#&			\"your copy of Firewolf.Your theme can also be\",!@#&			\"submitted it to the themes list!\"!@#&		}} pages[2] = {title = \"Making a Theme - Example\", content = {!@#&			\"A theme file consists of several lines of\",!@#&			\"text. Here is the default theme file:\",!@#&			\"address-bar-text=white\",!@#&			\"address-bar-background=gray\",!@#&			\"address-bar-base=lightGray\",!@#&			\"top-box=red\",!@#&			\"bottom-box=orange\",!@#&			\"background=gray\",!@#&			\"text-color=white\"!@#&		}} pages[3] = {title = \"Making a Theme - Explanation\", content = {!@#&			\"On each line of the example, something is\",!@#&			\"given a color, like on the last line, the\",!@#&			\"text of the page is told to be white.\",!@#&			\"\",!@#&			\"The color specified after the = is the same\",!@#&			\"as when you call colors.[color name].\",!@#&			\"For example, specifying 'red' after the =\",!@#&			\"colors that object red.\"!@#&		}} pages[4] = {title = \"Making a Theme - Have a Go\", content = {!@#&			\"Themes can be made at rdnt://settings/themes,\",!@#&			\"click on 'Change Theme' button, and click on\",!@#&			\"'New Theme'.\",!@#&			\"\",!@#&			\"Enter a theme name, then exit Firewolf and\",!@#&			\"edit the newly created file\",!@#&			\"Specify the colors for each of the keys,\",!@#&			\"and return to the themes section of the\",!@#&			\"downloads center. Click 'Load Theme'.\"!@#&		}} pages[5] = {title = \"Making a Theme - Submitting\", content = {!@#&			\"To submit a theme to the theme list,\",!@#&			\"send GravityScore a message on the CCForums\",!@#&			\"that contains your theme file and name.\",!@#&			\"\",!@#&			\"He will message you back saying whether your\",!@#&			\"theme has been added, or if anything needs to\",!@#&			\"be changed before it is added.\"!@#&		}}!@#&	elseif opt == \"API Documentation\" then!@#&		pages[1] = {title = \"API Documentation - 1\", content = {!@#&			\"The Firewolf API is a bunch of global\",!@#&			\"functions that aim to simplify your life when\",!@#&			\"designing and coding websites.\",!@#&			\"\",!@#&			\"For a full documentation on these functions,\",!@#&			\"visit the Firewolf Wiki Page here:\",!@#&			\"https://github.com/1lann/Firewolf/wiki\"!@#&		}} pages[2] = {title = \"API Documentation - 2\", content = {!@#&			\"centerPrint(string text)\",!@#&			\"cPrint(string text)\",!@#&			\"centerWrite(string text)\",!@#&			\"cWrite(string text)\",!@#&			\"\",!@#&			\"leftPrint(string text)\",!@#&			\"lPrint(string text)\",!@#&		}} pages[3] = {title = \"API Documentation - 3\", content = {!@#&			\"leftWrite(string text)\",!@#&			\"lWrite(string text)\",!@#&			\"\",!@#&			\"rightPrint(string text)\",!@#&			\"rPrint(string text)\",!@#&			\"rightWrite(string text)\",!@#&			\"rWrite(string text)\"!@#&		}} pages[4] = {title = \"API Documentation - 4\", content = {!@#&			\"prompt(table list, string direction)\",!@#&			\"scrollingPrompt(table list, integer x,\",!@#&			\"   integer y, integer length[,\",!@#&			\"   integer width])\",!@#&			\"\",!@#&			\"urlDownload(string url)\",!@#&			\"pastebinDownload(string code)\",!@#&			\"redirect(string site)\",!@#&		}} pages[5] = {title = \"API Documentation - 5\", content = {!@#&			\"loadImageFromServer(string imagePath)\",!@#&			\"ioReadFileFromServer(string filePath)\",!@#&			\"fileFileFromServer(string filePath)\",!@#&			\"saveFileToUserComputer(string content)\",!@#&			\"\",!@#&			\"writeDataFile(string path, string contents)\",!@#&			\"readDataFile(string path)\"!@#&		}} pages[6] = {title = \"API Documentation - 6\", content = {!@#&			\"themeColor(string tag)\",!@#&			\"themeColour(string tag)\"!@#&		}}!@#&	end!@#&!@#&	local function drawPage(page)!@#&		term.setBackgroundColor(colors[theme[\"background\"]])!@#&		term.clear()!@#&		term.setCursorPos(1, 1)!@#&		term.setTextColor(colors[theme[\"text-color\"]])!@#&		term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&		print(\"\")!@#&		leftPrint(string.rep(\" \", page.title:len() + 3))!@#&		leftPrint(\" \" .. page.title .. \"  \")!@#&		leftPrint(string.rep(\" \", page.title:len() + 3))!@#&		print(\"\")!@#&!@#&		term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&		for i = 1, 12 do print(string.rep(\" \", w)) end!@#&		for i, v in ipairs(page.content) do!@#&			term.setCursorPos(4, i + 6)!@#&			write(v)!@#&		end!@#&	end!@#&!@#&	local curPage = 1!@#&	local a = {{\"Prev\", 26, 17}, {\"Next\", 38, 17}, {\"Back\",  14, 17}}!@#&	drawPage(pages[curPage])!@#&	while true do!@#&		local b = {a[3]}!@#&		if curPage == 1 then table.insert(b, a[2])!@#&		elseif curPage == #pages then table.insert(b, a[1])!@#&		else table.insert(b, a[1]) table.insert(b, a[2]) end!@#&!@#&		local opt = prompt(b, \"horizontal\")!@#&		if opt == \"Prev\" then curPage = curPage - 1!@#&		elseif opt == \"Next\" then curPage = curPage + 1!@#&		elseif opt == \"Back\" then break end!@#&		drawPage(pages[curPage])!@#&	end!@#&!@#&	redirect(\"help\")!@#&end!@#&!@#&!@#&--  -------- Settings!@#&!@#&pages[\"settings/themes\"] = function()!@#&	term.setBackgroundColor(colors[theme[\"background\"]])!@#&	term.clear()!@#&	term.setTextColor(colors[theme[\"text-color\"]])!@#&	term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&	print(\"\")!@#&	leftPrint(string.rep(\" \", 17))!@#&	leftPrint(\" Theme Settings  \")!@#&	leftPrint(string.rep(\" \", 17))!@#&	print(\"\")!@#&!@#&	if isAdvanced() then!@#&		term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&		for i = 1, 12 do rightPrint(string.rep(\" \", 36)) end!@#&!@#&		local themes = {}!@#&		local themenames = {\"Back\", \"New Theme\", \"Load Theme\"}!@#&		local f = io.open(rootFolder .. \"/temp_file\", \"w\")!@#&		f:write(files.availableThemes)!@#&		f:close()!@#&		local f = io.open(rootFolder .. \"/temp_file\", \"r\")!@#&		local l = f:read(\"*l\")!@#&		while l do!@#&			l = l:gsub(\"^%s*(.-)%s*$\", \"%1\")!@#&			local a, b = l:find(\"| |\")!@#&			table.insert(themenames, l:sub(b + 1, -1))!@#&			table.insert(themes, {name = l:sub(b + 1, -1), url = l:sub(1, a - 1)})!@#&			l = f:read(\"*l\")!@#&		end!@#&		f:close()!@#&		fs.delete(rootFolder .. \"/temp_file\")!@#&!@#&		local t = scrollingPrompt(themenames, w - 33, 7, 10, 32)!@#&		if t == \"Back\" then redirect(\"settings\")!@#&		elseif t == \"New Theme\" then!@#&			term.setCursorPos(w - 33, 17)!@#&			write(\"Path: /\")!@#&			local n = modRead({visibleLength = w - 2, textLength = 100})!@#&			if n ~= \"\" and n then!@#&				n = \"/\" .. n!@#&				local f = io.open(n, \"w\")!@#&				f:write(files.newTheme)!@#&				f:close()!@#&!@#&				term.setCursorPos(1, 17)!@#&				rightWrite(string.rep(\" \", 36))!@#&				term.setCursorPos(1, 17)!@#&				rightWrite(\"File Created! \")!@#&				openAddressBar = false!@#&				sleep(1.1)!@#&				openAddressBar = true!@#&				redirect(\"settings/themes\")!@#&			end!@#&		elseif t == \"Load Theme\" then!@#&			term.setCursorPos(w - 33, 17)!@#&			write(\"Path: /\")!@#&			local n = modRead({visibleLength = w - 2, textLength = 100})!@#&			if n ~= \"\" and n then!@#&				n = \"/\" .. n!@#&				term.setCursorPos(1, 17)!@#&				rightWrite(string.rep(\" \", 36))!@#&				!@#&				term.setCursorPos(1, 17)!@#&				if fs.exists(n) and not fs.isDir(n) then!@#&					local a = loadTheme(n)!@#&					if a then!@#&						fs.delete(themeLocation)!@#&						fs.copy(n, themeLocation)!@#&						theme = a!@#&						rightWrite(\"Theme File Loaded! :D \")!@#&					else rightWrite(\"Theme File is Corrupt! D: \") end!@#&				elseif not fs.exists(n) then rightWrite(\"File does not exist! \")!@#&				elseif fs.isDir(n) then rightWrite(\"File is a directory! \") end!@#&!@#&				openAddressBar = false!@#&				sleep(1.1)!@#&				openAddressBar = true!@#&				redirect(\"settings/themes\")!@#&			end!@#&		else!@#&			local url = \"\"!@#&			for _, v in pairs(themes) do if v.name == t then url = v.url break end end!@#&			term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&			term.setCursorPos(1, 3)!@#&			leftWrite(string.rep(\" \", 17))!@#&			leftWrite(\" Downloading...  \")!@#&!@#&			fs.delete(rootFolder .. \"/temp_file\")!@#&			download(url, rootFolder .. \"/temp_file\")!@#&			local th = loadTheme(rootFolder .. \"/temp_file\")!@#&			if not th then!@#&				term.setCursorPos(1, 3)!@#&				leftWrite(string.rep(\" \", 17))!@#&				leftWrite(\" Theme Corrupt!  \")!@#&				openAddressBar = false!@#&				sleep(1.3)!@#&				openAddressBar = true!@#&!@#&				fs.delete(rootFolder .. \"/temp_file\")!@#&				redirect(\"settings/themes\")!@#&			else!@#&				term.setCursorPos(1, 3)!@#&				leftWrite(string.rep(\" \", 17))!@#&				leftWrite(\" Theme Loaded!   \")!@#&				openAddressBar = false!@#&				sleep(1.3)!@#&				openAddressBar = true!@#&!@#&				fs.delete(themeLocation)!@#&				fs.move(rootFolder .. \"/temp_file\", themeLocation)!@#&				theme = th!@#&				redirect(\"home\")!@#&			end!@#&		end!@#&	else!@#&		print(\"\")!@#&		rightPrint(string.rep(\" \", 30))!@#&		rightPrint(\"  Themes are not available on \")!@#&		rightPrint(\"         normal computers! :( \")!@#&		rightPrint(string.rep(\" \", 30))!@#&	end!@#&end!@#&!@#&pages[\"settings\"] = function()!@#&	term.setBackgroundColor(colors[theme[\"background\"]])!@#&	term.clear()!@#&	term.setTextColor(colors[theme[\"text-color\"]])!@#&	term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&	print(\"\")!@#&	leftPrint(string.rep(\" \", 17 + serverList[serverID]:len()))!@#&	leftPrint(\" Firewolf Settings  \" .. string.rep(\" \", serverList[serverID]:len() - 3))!@#&	leftPrint(\" Designed For: \" .. serverList[serverID] .. \"  \")!@#&	leftPrint(string.rep(\" \", 17 + serverList[serverID]:len()))!@#&	print(\"\\n\")!@#&!@#&	local a = \"Automatic Updating - On\"!@#&	if autoupdate == \"false\" then a = \"Automatic Updating - Off\" end!@#&	local b = \"Home - rdnt://\" .. homepage!@#&	if b:len() >= 28 then b = b:sub(1, 24) .. \"...\" end!@#&!@#&	term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&	for i = 1, 9 do rightPrint(string.rep(\" \", 36)) end!@#&	local c = {{a, w - a:len() - 6, 9}, {\"Change Theme\", w - 18, 11}, {b, w - b:len() - 6, 13},!@#&		{\"Reset Firewolf\", w - 20, 15}}!@#&	if not isAdvanced() then!@#&		c = {{a, w - a:len(), 9}, {b, w - b:len(), 11}, {\"Reset Firewolf\", w - 14, 13}}!@#&	end!@#&!@#&	local opt = prompt(c, \"vertical\")!@#&	if opt == a then!@#&		if autoupdate == \"true\" then autoupdate = \"false\"!@#&		elseif autoupdate == \"false\" then autoupdate = \"true\" end!@#&	elseif opt == \"Change Theme\" and isAdvanced() then!@#&		redirect(\"settings/themes\")!@#&	elseif opt == b then!@#&		if isAdvanced() then term.setCursorPos(w - 30, 14)!@#&		else term.setCursorPos(w - 30, 12) end!@#&		write(\"rdnt://\")!@#&		local a = read()!@#&		if a ~= \"\" then homepage = a end!@#&	elseif opt == \"Reset Firewolf\" then!@#&		term.setBackgroundColor(colors[theme[\"background\"]])!@#&		term.clear()!@#&		term.setCursorPos(1, 1)!@#&		term.setTextColor(colors[theme[\"text-color\"]])!@#&		term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&		print(\"\")!@#&		leftPrint(string.rep(\" \", 17))!@#&		leftPrint(\" Reset Firewolf  \")!@#&		leftPrint(string.rep(\" \", 17))!@#&		print(\"\\n\")!@#&		term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&		for i = 1, 11 do rightPrint(string.rep(\" \", 26)) end!@#&		local opt = prompt({{\"Reset History\", w - 19, 8}, {\"Reset Servers\", w - 19, 9},!@#&			{\"Reset Theme\", w - 17, 10}, {\"Reset Cache\", w - 17, 11}, !@#&			{\"Reset Databases\", w - 21, 12},!@#&			{\"Reset Settings\", w - 20, 13}, {\"Back\", w - 10, 14}, {\"Reset All\", w - 15, 16}},!@#&			\"vertical\")!@#&!@#&		openAddressBar = false!@#&		if opt == \"Reset All\" then!@#&			fs.delete(rootFolder)!@#&		elseif opt == \"Reset History\" then!@#&			fs.delete(historyLocation)!@#&		elseif opt == \"Reset Servers\" then!@#&			fs.delete(serverFolder)!@#&			fs.delete(serverLocation)!@#&		elseif opt == \"Reset Cache\" then!@#&			fs.delete(cacheFolder)!@#&		elseif opt == \"Reset Databases\" then!@#&			fs.delete(userWhitelist)!@#&			fs.delete(userBlacklist)!@#&		elseif opt == \"Reset Settings\" then!@#&			fs.delete(settingsLocation)!@#&		elseif opt == \"Reset Theme\" then!@#&			fs.delete(themeLocation)!@#&		elseif opt == \"Back\" then!@#&			openAddressBar = true!@#&			redirect(\"settings\")!@#&		end!@#&!@#&		term.setBackgroundColor(colors[theme[\"background\"]])!@#&		term.clear()!@#&		term.setCursorPos(1, 1)!@#&		term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&		print(\"\\n\\n\")!@#&		leftPrint(string.rep(\" \", 17))!@#&		leftPrint(\" Reset Firewolf  \")!@#&		leftPrint(string.rep(\" \", 17))!@#&		print(\"\")!@#&!@#&		term.setCursorPos(1, 10)!@#&		term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&		rightPrint(string.rep(\" \", 27))!@#&		rightPrint(\"  Firewolf has been reset! \")!@#&		rightWrite(string.rep(\" \", 27))!@#&		if isAdvanced() then rightPrint(\"          Click to exit... \")!@#&		else rightPrint(\"  Press any key to exit... \") end!@#&		rightPrint(string.rep(\" \", 27))!@#&!@#&		while true do!@#&			local e = os.pullEvent()!@#&			if e == \"mouse_click\" or e == \"key\" then return true end!@#&		end!@#&	end!@#&!@#&	-- Save!@#&	local f = io.open(settingsLocation, \"w\")!@#&	f:write(textutils.serialize({auto = autoupdate, incog = incognito, home = homepage}))!@#&	f:close()!@#&!@#&	redirect(\"settings\")!@#&end!@#&!@#&!@#&--  -------- Credits!@#&!@#&pages[\"credits\"] = function()!@#&	term.setTextColor(colors[theme[\"text-color\"]])!@#&	term.setBackgroundColor(colors[theme[\"background\"]])!@#&	term.clear()!@#&	print(\"\\n\")!@#&	term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&	leftPrint(string.rep(\" \", 19))!@#&	leftPrint(\" Firewolf Credits  \")!@#&	leftPrint(string.rep(\" \", 19))!@#&	print(\"\\n\")!@#&!@#&	term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&	rightPrint(string.rep(\" \", 38))!@#&	rightPrint(\"  Coded by:              GravityScore \")!@#&	rightPrint(\"                            and 1lann \")!@#&	rightPrint(string.rep(\" \", 38))!@#&	rightPrint(\"  Based off:     RednetExplorer 2.4.1 \")!@#&	rightPrint(\"           Made by ComputerCraftFan11 \")!@#&	rightPrint(string.rep(\" \", 38))!@#&end!@#&!@#&!@#&--  -------- Error Pages!@#&!@#&errorPages[\"overspeed\"] = function()!@#&	clear(\"overspeed\", colors[theme[\"background\"]])!@#&	print(\"\")!@#&	term.setTextColor(colors[theme[\"text-color\"]])!@#&	term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&	leftPrint(string.rep(\" \", 14))!@#&	leftPrint(\" Warning! D:  \")!@#&	leftPrint(string.rep(\" \", 14))!@#&	print(\"\")!@#&!@#&	term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&	rightPrint(string.rep(\" \", 40))!@#&	rightPrint(\"  Website browsing sleep limit reached! \")!@#&	rightPrint(string.rep(\" \", 40))!@#&	rightPrint(\"      To prevent Firewolf from spamming \")!@#&	rightPrint(\"   rednet, Firewolf has stopped loading \")!@#&	rightPrint(\"                              the page. \")!@#&	for i = 1, 3 do rightPrint(string.rep(\" \", 40)) end!@#&!@#&	openAddressBar = false!@#&	for i = 1, 5 do!@#&		term.setCursorPos(1, 14)!@#&		rightWrite(string.rep(\" \", 43))!@#&		if 6 - i == 1 then rightWrite(\"                Please wait 1 second... \")!@#&		else rightWrite(\"                Please wait \" .. tostring(6 - i) .. \" seconds... \") end!@#&		sleep(1)!@#&	end!@#&	openAddressBar = true!@#&!@#&	term.setCursorPos(1, 14)!@#&	rightWrite(string.rep(\" \", 43))!@#&	rightWrite(\"            You may now browse normally \")!@#&end!@#&!@#&errorPages[\"crash\"] = function(error)!@#&	clear(\"crash\", colors[theme[\"background\"]])!@#&	print(\"\")!@#&	term.setTextColor(colors[theme[\"text-color\"]])!@#&	term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&	leftPrint(string.rep(\" \", 30))!@#&	leftPrint(\" The Website Has Crashed! D:  \")!@#&	leftPrint(string.rep(\" \", 30))!@#&	print(\"\")!@#&!@#&	term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&	rightPrint(string.rep(\" \", 31))!@#&	rightPrint(\"      The website has crashed! \")!@#&	rightPrint(\"  Report this to the operator: \")!@#&	rightPrint(string.rep(\" \", 31))!@#&	term.setBackgroundColor(colors[theme[\"background\"]])!@#&	print(\"\")!@#&	print(\" \" .. tostring(error))!@#&	print(\"\")!@#&!@#&	term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&	rightPrint(string.rep(\" \", 31))!@#&	rightPrint(\"   You may now browse normally \")!@#&	rightPrint(string.rep(\" \", 31))!@#&end!@#&!@#&!@#&--  -------- External!@#&!@#&local function validateexternal(site)!@#&	-- Modem!@#&	if not modemPresent() then return \"modem\" end!@#&!@#&	-- Website!@#&	local id, content, status = curProtocol.getWebsite(site)!@#&	if id and status then return \"exists\", id, content, status end!@#&!@#&	-- Cache!@#&	local cacheLoc = cacheFolder .. \"/\" .. site:gsub(\"/\", \"$slazh$\")!@#&	if fs.exists(cacheLoc) and not fs.isDir(cacheLoc) then return \"cache\" end!@#&!@#&	-- Search results!@#&	local res = {}!@#&	if site ~= \"\" then!@#&		for _, v in pairs(dnsDatabase[1]) do!@#&			if v:find(site:lower(), 1, true) then table.insert(res, v) end!@#&		end!@#&	else for _, v in pairs(dnsDatabase[1]) do table.insert(res, v) end end!@#&	table.sort(res)!@#&	table.sort(res, function(a, b)!@#&		local _, ac = a:gsub(\"rdnt://\", \"\"):gsub(\"http://\", \"\"):gsub(site:lower(), \"\")!@#&		local _, bc = b:gsub(\"rdnt://\", \"\"):gsub(\"http://\", \"\"):gsub(site:lower(), \"\")!@#&		return ac > bc!@#&	end)!@#&!@#&	if #res > 0 then return \"search\", res!@#&	elseif site == \"\" then return \"search\", res end!@#&!@#&	-- Doesn't exist!@#&	return \"false\"!@#&end!@#&!@#&local function loadexternal(site)!@#&	local a, res, content, status = validateexternal(site)!@#&	local func = nil!@#&!@#&	if a == \"exists\" then!@#&		local cacheLoc = cacheFolder .. \"/\" .. site:gsub(\"/\", \"$slazh$\")!@#&		local f = io.open(cacheLoc, \"w\")!@#&		f:write(content)!@#&		f:close()!@#&!@#&		local fn, err = loadfile(cacheLoc)!@#&		if not err then!@#&			setfenv(fn, antivirus)!@#&			if status == \"whitelist\" then setfenv(fn, override) end!@#&!@#&			func = function()!@#&				local _, err = pcall(fn)!@#&				if err then!@#&					websiteerror = err!@#&					os.queueEvent(event_error)!@#&				end!@#&			end!@#&		else!@#&			func = function()!@#&				local errf = errorPages[\"crash\"]!@#&				setfenv(errf, override)!@#&				pcall(function() errf(err) end)!@#&			end!@#&		end!@#&	elseif a == \"modem\" then!@#&		func = function() checkForModem(graphics.nomodem) end!@#&	elseif a == \"search\" then!@#&		if #res > 0 then!@#&			func = function()!@#&				term.setBackgroundColor(colors[theme[\"background\"]])!@#&				term.clear()!@#&				term.setCursorPos(1, 2)!@#&				term.setTextColor(colors[theme[\"text-color\"]])!@#&				term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&				local t = \"1 Search Result\"!@#&				if #res > 1 then t = #res .. \" Search Results\" end!@#&				leftPrint(string.rep(\" \", t:len() + 3))!@#&				leftPrint(\" \" .. t .. \"  \")!@#&				leftPrint(string.rep(\" \", t:len() + 3))!@#&				print(\"\")!@#&!@#&				term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&				for i = 1, 12 do rightPrint(string.rep(\" \", 42)) end!@#&				local opt = scrollingPrompt(res, w - 39, 7, 10, 38)!@#&				if opt then redirect(opt:gsub(\"rdnt://\", \"\"):gsub(\"http://\", \"\")) end!@#&			end!@#&		else!@#&			func = graphics.nosearchresults!@#&		end!@#&	elseif a == \"false\" or a == \"cache\" then!@#&		func = graphics.nonexistantwebpage!@#&	end!@#&!@#&	term.setBackgroundColor(colors.black)!@#&	term.setTextColor(colors.white)!@#&	term.clear()!@#&	term.setCursorPos(1, 1)!@#&!@#&	local a = override!@#&	a[\"browserAgent\"] = browserAgent!@#&	setfenv(func, a)!@#&	curtext, curbackground = colors.white, colors.black!@#&	tabs[currentTab] = coroutine.create(func)!@#&end!@#&!@#&!@#&--  -------- Website!@#&!@#&local function loadinternal(site)!@#&	if pages[site] then!@#&		local func = pages[site]!@#&		setfenv(func, override)!@#&		tabs[currentTab] = coroutine.create(function()!@#&			local _, err = pcall(function() func() end)!@#&			if err then!@#&				websiteerror = err!@#&				os.queueEvent(event_error)!@#&			end!@#&		end)!@#&!@#&		return true!@#&	else return false end!@#&end!@#&!@#&local function loadsite(site)!@#&	w, h = term.getSize()!@#&	clear(site)!@#&	term.setBackgroundColor(colors.black)!@#&	term.setTextColor(colors.white)!@#&	fs.delete(websiteDataFolder)!@#&	fs.makeDir(websiteDataFolder)!@#&!@#&	if site ~= \"exit\" and site ~= addressBarHistory[#addressBarHistory] then!@#&		table.insert(addressBarHistory, site)!@#&	end!@#&!@#&	checkForModem()!@#&	if os.clock() - loadingClock > 5 then loadingRate, loadingClock = 0, os.clock() end!@#&	if loadingRate >= 8 then!@#&		local overspeedFunc = errorPages[\"overspeed\"]!@#&		setfenv(overspeedFunc, override)!@#&		overspeedFunc()!@#&		loadingRate, loadingClock = 0, os.clock()!@#&	end!@#&!@#&	-- Load!@#&	os.queueEvent(event_load)!@#&	website = site!@#&	setfenv(loadinternal, override)!@#&	setfenv(loadexternal, override)!@#&	if not loadinternal(site) then loadexternal(site) end!@#&	if tabs[currentTab] then _, filters[currentTab] = coroutine.resume(tabs[currentTab]) end!@#&end!@#&!@#&!@#&--  -------- Address Bar!@#&!@#&local function addressbarread()!@#&	local len, list = 4, {}!@#&!@#&	local function draw(l)!@#&		local ox, oy = term.getCursorPos()!@#&		for i = 1, len do!@#&			term.setTextColor(colors[theme[\"address-bar-text\"]])!@#&			term.setBackgroundColor(colors[theme[\"address-bar-background\"]])!@#&			term.setCursorPos(1, i + 1)!@#&			write(string.rep(\" \", w))!@#&		end!@#&!@#&		term.setBackgroundColor(colors[theme[\"address-bar-base\"] or theme[\"bottom-box\"]])!@#&		term.setCursorPos(1, len + 2)!@#&		write(string.rep(\" \", w))!@#&		term.setBackgroundColor(colors[theme[\"address-bar-background\"]])!@#&		for i, v in ipairs(l) do term.setCursorPos(2, i + 1) write(v) end!@#&		term.setCursorPos(ox, oy)!@#&	end!@#&!@#&	local function update(line, event, ...)!@#&		local params = {...}!@#&		local y = params[3]!@#&		if event == \"char\" or event == \"history\" or event == \"delete\" then!@#&			list = {}!@#&			for _, v in pairs(dnsDatabase[1]) do!@#&				if #list < len and!@#&						v:gsub(\"rdnt://\", \"\"):gsub(\"http://\", \"\"):find(line:lower(), 1, true) then!@#&					table.insert(list, v)!@#&				end!@#&			end!@#&!@#&			table.sort(list)!@#&			table.sort(list, function(a, b)!@#&				local _, ac = a:gsub(\"rdnt://\", \"\"):gsub(\"http://\", \"\"):gsub(line:lower(), \"\")!@#&				local _, bc = b:gsub(\"rdnt://\", \"\"):gsub(\"http://\", \"\"):gsub(line:lower(), \"\")!@#&				return ac > bc!@#&			end)!@#&			draw(list)!@#&			return false!@#&		elseif event == \"mouse_click\" then!@#&			for i = 1, #list do!@#&				if y == i + 1 then return true, list[i]:gsub(\"rdnt://\", \"\"):gsub(\"http://\", \"\") end!@#&			end!@#&		end!@#&	end!@#&!@#&	if isAdvanced() and modemPresent() then!@#&		return modRead({history = addressBarHistory, visibleLength = w - 2, textLength = 300, !@#&			liveUpdates = update, exitOnKey = \"control\"})!@#&	else!@#&		return modRead({history = addressBarHistory, visibleLength = w - 2, textLength = 300,!@#&			exitOnKey = \"control\"})!@#&	end!@#&end!@#&!@#&!@#&--  -------- Main!@#&!@#&local function searchresults()!@#&	if modemPresent() then curProtocol.getSearchResults() end!@#&	local lastCheck = os.clock()!@#&	while true do!@#&		local e = os.pullEvent()!@#&		if e == event_load and modemPresent() and os.clock() - lastCheck > 5 then!@#&			curProtocol.getSearchResults()!@#&			lastCheck = os.clock()!@#&		end!@#&	end!@#&end!@#&!@#&local function run()!@#&	loadingClock = os.clock()!@#&	loadsite(homepage)!@#&	while true do!@#&		local e, but, x, y, p4, p5 = os.pullEvent()!@#&		if ((e == \"mouse_click\" and y == 1 and clickableAddressBar) or!@#&				(e == \"key\" and (but == 29 or but == 157))) and openAddressBar then!@#&			if e == \"key\" then x = -1 end!@#&			if not menuBarOpen and x == w then!@#&				-- Open menu bar!@#&				menuBarOpen = true!@#&				term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&				term.setTextColor(colors[theme[\"address-bar-text\"]])!@#&				term.setCursorPos(1, 1)!@#&				write(\"> [- Exit Firewolf -]                              \")!@#&			elseif menuBarOpen and (x == 1 or (but == 29 or but == 157)) then!@#&				-- Close menu bar!@#&				menuBarOpen = false!@#&				clear(website, nil, true)!@#&			elseif menuBarOpen and x > 2 and x < 22 then!@#&				return!@#&			elseif not menuBarOpen then!@#&				-- Stop!@#&				if tabs[currentTab] then tabs[currentTab] = nil end!@#&!@#&				-- Clear!@#&				term.setBackgroundColor(colors[theme[\"address-bar-background\"]])!@#&				term.setTextColor(colors[theme[\"address-bar-text\"]])!@#&				term.setCursorPos(2, 1)!@#&				term.clearLine()!@#&				if curProtocol == protocols.rdnt then write(\"rdnt://\")!@#&				elseif curProtocol == protocols.http then write(\"http://\") end!@#&!@#&				-- Read!@#&				local osite = website!@#&				local site = addressbarread()!@#&				if not site then site = osite!@#&				elseif site == \"home\" or site == \"homepage\" then site = homepage!@#&				elseif site == \"exit\" then return end!@#&!@#&				-- Load!@#&				loadsite(site)!@#&			end!@#&		elseif e == event_error and websiteerror then!@#&			-- Display!@#&			if tabs[currentTab] then tabs[currentTab] = nil end!@#&!@#&			local errf = errorPages[\"crash\"]!@#&			setfenv(errf, override)!@#&			errf(websiteerror)!@#&			websiteerror = nil!@#&		elseif e == event_redirect and openAddressBar then!@#&			-- Stop!@#&			if tabs[currentTab] then tabs[currentTab] = nil end!@#&!@#&			-- Load!@#&			if not but or but == \"exit\" then but = website!@#&			elseif but == \"home\" or but == \"homepage\" then but = homepage end!@#&			loadsite(but)!@#&		elseif tabs[currentTab] then!@#&			if coroutine.status(tabs[currentTab]) == \"suspended\" then!@#&				if e == \"mouse_click\" and offsetclick then y = y - 1 end!@#&				if (filters[currentTab] or e) == e then!@#&					_, filters[currentTab] = coroutine.resume(tabs[currentTab], e, but, x, y, !@#&						p4, p5)!@#&				end!@#&			end!@#&!@#&			for i = 1, #tabs do!@#&				if tabs[i] and coroutine.status(tabs[i]) == \"dead\" then!@#&					tabs[i] = nil!@#&				end!@#&			end!@#&		end!@#&	end!@#&end!@#&!@#&!@#&--  -------- Startup!@#&!@#&local function main()!@#&	-- Logo!@#&	term.setBackgroundColor(colors[theme[\"background\"]])!@#&	term.setTextColor(colors[theme[\"text-color\"]])!@#&	term.clear()!@#&	term.setCursorPos(1, 2)!@#&	term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&	leftPrint(string.rep(\" \", 47))!@#&	leftPrint([[          ______ ____ ____   ______            ]])!@#&	leftPrint([[ ------- / ____//  _// __ \\ / ____/            ]])!@#&	leftPrint([[ ------ / /_    / / / /_/ // __/               ]])!@#&	leftPrint([[ ----- / __/  _/ / / _  _// /___               ]])!@#&	leftPrint([[ ---- / /    /___//_/ |_|/_____/               ]])!@#&	leftPrint([[ --- / /       _       __ ____   __     ______ ]])!@#&	leftPrint([[ -- /_/       | |     / // __ \\ / /    / ____/ ]])!@#&	leftPrint([[              | | /| / // / / // /    / /_     ]])!@#&	leftPrint([[              | |/ |/ // /_/ // /___ / __/     ]])!@#&	leftPrint([[              |__/|__/ \\____//_____//_/        ]])!@#&	leftPrint(string.rep(\" \", 47))!@#&	print(\"\\n\")!@#&	term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&!@#&	-- Load Settings!@#&	if fs.exists(settingsLocation) and not fs.isDir(settingsLocation) then!@#&		local f = io.open(settingsLocation, \"r\")!@#&		local a = textutils.unserialize(f:read(\"*l\"))!@#&		if type(a) == \"table\" then autoupdate, incognito, homepage = a.auto, a.incog, a.home end!@#&		f:close()!@#&	else autoupdate, incognito, homepage = \"true\", \"false\", \"firewolf\" end!@#&	curProtocol = protocols.rdnt!@#&!@#&	-- Update!@#&	rightPrint(string.rep(\" \", 32))!@#&	rightPrint(\"        Checking for Updates... \")!@#&	rightPrint(string.rep(\" \", 32))!@#&	setfenv(updateClient, env)!@#&	if not noInternet then!@#&		if updateClient() then!@#&			if debugFile then debugFile:close() end!@#&			shell.run(firewolfLocation)!@#&			error()!@#&		end!@#&	end!@#&!@#&	-- Download Files!@#&	local x, y = term.getCursorPos()!@#&	term.setCursorPos(1, y - 2)!@#&	rightWrite(string.rep(\" \", 32))!@#&	rightWrite(\"  Downloading Required Files... \")!@#&	if not noInternet then resetFilesystem() end!@#&	loadDatabases()!@#&	checkForModem()!@#&!@#&	-- Run!@#&	setfenv(run, env)!@#&	parallel.waitForAny(run, searchresults)!@#&end!@#&!@#&local function startup()!@#&	-- HTTP!@#&	if not http and not noInternet then!@#&		term.setTextColor(colors[theme[\"text-color\"]])!@#&		term.setBackgroundColor(colors[theme[\"background\"]])!@#&		term.clear()!@#&		term.setCursorPos(1, 2)!@#&		term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&		api.leftPrint(string.rep(\" \", 24))!@#&		api.leftPrint(\" HTTP API Not Enabled!  \")!@#&		api.leftPrint(string.rep(\" \", 24))!@#&		print(\"\")!@#&!@#&		term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&		api.rightPrint(string.rep(\" \", 36))!@#&		api.rightPrint(\"  Firewolf is unable to run without \")!@#&		api.rightPrint(\"       the HTTP API Enabled! Please \")!@#&		api.rightPrint(\"    enable it in your ComputerCraft \")!@#&		api.rightPrint(\"                            Config! \")!@#&		api.rightPrint(string.rep(\" \", 36))!@#&!@#&		if isAdvanced() then api.rightPrint(\"                   Click to exit... \")!@#&		else api.rightPrint(\"           Press any key to exit... \") end!@#&		api.rightPrint(string.rep(\" \", 36))!@#&!@#&		while true do!@#&			local e, but, x, y = os.pullEvent()!@#&			if e == \"mouse_click\" or e == \"key\" then break end!@#&		end!@#&!@#&		return false!@#&	end!@#&!@#&	-- Turtle!@#&	if turtle then!@#&		term.clear()!@#&		term.setCursorPos(1, 2)!@#&		api.centerPrint(\"Advanced computer Required!\")!@#&		print(\"\\n\")!@#&		api.centerPrint(\"  This version of Firewolf requires  \")!@#&		api.centerPrint(\"  an Advanced computer to run!       \")!@#&		print(\"\")!@#&		api.centerPrint(\"  Turtles may not be used to run     \")!@#&		api.centerPrint(\"  Firewolf! :(                       \")!@#&		print(\"\")!@#&		api.centerPrint(\"Press any key to exit...\")!@#&!@#&		os.pullEvent(\"key\")!@#&		return false!@#&	end!@#&!@#&	-- Run!@#&	setfenv(main, env)!@#&	local _, err = pcall(main)!@#&	if err and not err:lower():find(\"terminated\") then!@#&		term.setTextColor(colors[theme[\"text-color\"]])!@#&		term.setBackgroundColor(colors[theme[\"background\"]])!@#&		term.clear()!@#&		term.setCursorPos(1, 2)!@#&		term.setCursorBlink(false)!@#&		term.setBackgroundColor(colors[theme[\"top-box\"]])!@#&		api.leftPrint(string.rep(\" \", 27))!@#&		api.leftPrint(\" Firewolf has Crashed! D:  \")!@#&		api.leftPrint(string.rep(\" \", 27))!@#&		print(\"\")!@#&		term.setBackgroundColor(colors[theme[\"background\"]])!@#&		print(\"\")!@#&		print(\"  \" .. err)!@#&		print(\"\")!@#&!@#&		term.setBackgroundColor(colors[theme[\"bottom-box\"]])!@#&		api.rightPrint(string.rep(\" \", 41))!@#&		if autoupdate == \"true\" then!@#&			api.rightPrint(\"    Please report this error to 1lann or \")!@#&			api.rightPrint(\"  GravityScore so we are able to fix it! \")!@#&			api.rightPrint(\"  If this problem persists, try deleting \")!@#&			api.rightPrint(\"                         \" .. rootFolder .. \" \")!@#&		else!@#&			api.rightPrint(\"        Automatic updating is off! A new \")!@#&			api.rightPrint(\"     version may have have been released \")!@#&			api.rightPrint(\"                that may fix this error! \")!@#&			api.rightPrint(\"        If you didn't turn auto updating \")!@#&			api.rightPrint(\"             off, delete \" .. rootFolder .. \" \")!@#&		end!@#&!@#&		api.rightPrint(string.rep(\" \", 41))!@#&		if isAdvanced() then api.rightPrint(\"                        Click to exit... \")!@#&		else api.rightPrint(\"                Press any key to exit... \") end!@#&		api.rightPrint(string.rep(\" \", 41))!@#&!@#&		while true do!@#&			local e, but, x, y = os.pullEvent()!@#&			if e == \"mouse_click\" or e == \"key\" then break end!@#&		end!@#&!@#&		return false!@#&	end!@#&end!@#&!@#&-- Check If Read Only!@#&if fs.isReadOnly(firewolfLocation) or fs.isReadOnly(rootFolder) then!@#&	print(\"Firewolf cannot modify itself or its root folder!\")!@#&	print(\"\")!@#&	print(\"This cold be caused by Firewolf being placed in\")!@#&	print(\"the rom folder, or another program may be\")!@#&	print(\"preventing the modification of Firewolf.\")!@#&	error()!@#&end!@#&!@#&-- Theme!@#&if not isAdvanced() then theme = originalTheme!@#&else theme = loadTheme(themeLocation) or defaultTheme end!@#&!@#&-- Debug File!@#&if #tArgs > 0 and tArgs[1] == \"debug\" then!@#&	print(\"Debug Mode Enabled\")!@#&	if fs.exists(debugLogLocation) then debugFile = io.open(debugLogLocation, \"a\")!@#&	else debugFile = io.open(debugLogLocation, \"w\") end!@#&	debugFile:write(\"\\n-- [\" .. textutils.formatTime(os.time()) .. \"] New Log --\")!@#&	sleep(1)!@#&end!@#&!@#&-- Start!@#&startup()!@#&!@#&-- Exit Message!@#&term.setBackgroundColor(colors.black)!@#&term.setTextColor(colors.white)!@#&term.setCursorBlink(false)!@#&term.clear()!@#&term.setCursorPos(1, 1)!@#&api.centerPrint(\"Thank You for Using Firewolf \" .. version)!@#&api.centerPrint(\"Made by 1lann and GravityScore\")!@#&!@#&-- Close!@#&for _, v in pairs(rs.getSides()) do !@#&	if peripheral.getType(v) == \"modem\" then rednet.close(v) end!@#&end!@#&if debugFile then debugFile:close() end",["mouse.cfg"]="{[\"txt\"]=32768,[\"back\"]=2048,}!@#&{[\"txt\"]=32768,[\"back\"]=256,}!@#&{[\"txt\"]=32768,[\"back\"]=512,}!@#&{[\"txt\"]=32768,[\"back\"]=256,}!@#&{[\"txt\"]=32768,[\"back\"]=2048,}!@#&{[\"txt\"]=32768,[\"back\"]=2048,}!@#&{[\"txt\"]=32768,[\"back\"]=1,}!@#&{[\"back\"]=256,[\"button\"]=128,[\"off\"]=128,}!@#&{[\"folder\"]={[\"txt\"]=\"[=]\",[\"bCol\"]=\"blue\",[\"tCol\"]=\"lightGray\",},[\"audio\"]={[\"txt\"]=\"(o)\",[\"bCol\"]=\"red\",[\"tCol\"]=\"yellow\",},[\"disk\"]={[\"txt\"]=\"[*]\",[\"bCol\"]=\"green\",[\"tCol\"]=\"lime\",},[\"file\"]={},[\"back\"]={[\"txt\"]=\" < \",[\"bCol\"]=\"blue\",[\"tCol\"]=\"lightGray\",},}!@#&{[\"Paint\"]=\"rom/programs/color/paint\",[\"Edit\"]=\"rom/programs/edit\",}",["games"]="local running = true!@#&!@#&function clear()!@#&  term.clear()!@#&  term.setCursorPos(1,1)!@#&end!@#&!@#&term.setBackgroundColour(colors.white)!@#&clear()!@#&local A = 0!@#&local games = {}!@#&term.setTextColour(colors.white)!@#&!@#&for i,v in ipairs(fs.list(\"/\"..root..\"/games/\")) do!@#&  if A == 0 then!@#&    term.setBackgroundColour(colors.gray)!@#&    term.setTextColour(colors.lightGray)!@#&    A = 1!@#&  elseif A == 1 then  !@#&    term.setBackgroundColour(colors.lightGray)!@#&    term.setTextColour(colors.gray)!@#&    A = 0!@#&  end!@#&  term.clearLine()!@#&  local str = string.upper(v:sub(1,1)) .. v:sub(2)!@#&  print(str)!@#&  table.insert(games, v)!@#&end!@#&!@#&local maxX, maxY = term.getSize()!@#&term.setCursorPos(1, maxY)!@#&term.setCursorPos((maxX/2), maxY)!@#&term.setBackgroundColour(colors.gray)!@#&term.clearLine()!@#&term.setTextColour(colors.lightGray)!@#&write(\"Exit\")!@#&!@#&while running do!@#&  ev, button, x, y = os.pullEvent(\"mouse_click\")!@#&!@#&  for i=1, #games do!@#&    if y == i then!@#&      term.setBackgroundColour(colors.black)!@#&      clear()!@#&      running = false!@#&      shell.run(\"/\"..root..\"/games/\"..games[i])!@#&    end!@#&  end!@#&!@#&  if y == maxY then!@#&    running = false!@#&    clear()!@#&  end!@#&end",},["system"]={["delUser"]="function clear()!@#& term.clear()!@#& term.setCursorPos(1,1)!@#&end!@#&!@#&function succesBox(text)!@#& local maxX, maxY = term.getSize()!@#& term.setTextColour(colors.white)!@#& term.setBackgroundColour(colors.green)!@#& term.setCursorPos(1, maxY/2-1)!@#& term.clearLine()!@#& term.setCursorPos(maxX/2-#text/2, maxY/2)!@#& term.clearLine()!@#& write(text)!@#& term.setCursorPos(1, maxY/2+1)!@#& term.clearLine()!@#& sleep(2)!@#&end!@#&!@#&function errorBox(text)!@#& local maxX, maxY = term.getSize()!@#& term.setTextColour(colors.white)!@#& term.setBackgroundColour(colors.red)!@#& term.setCursorPos(1, maxY/2-1)!@#& term.clearLine()!@#& term.setCursorPos(maxX/2-#text/2, maxY/2)!@#& term.clearLine()!@#& write(text)!@#& term.setCursorPos(1,maxY/2+1)!@#& term.clearLine()!@#& sleep(2)!@#&end!@#&!@#&function delUser(name, pwd)!@#& if name == \"\" or pwd == \"\" then!@#&  errorBox(\"Username or password cannot be empty!\")!@#& else!@#&  A = fs.open(\"/\"..root..\"/system/.users\", \"r\")!@#&  local usrTable = textutils.unserialize(A.readAll())!@#&  A.close()!@#&  !@#&  for i,v in ipairs(usrTable) do!@#&   if name == usrTable[i][\"username\"] and pwd == usrTable[i][\"password\"] then!@#&    table.remove(usrTable, i)!@#&    A = fs.open(\"/\"..root..\"/system/.users\", \"w\")!@#&    A.write(textutils.serialize(usrTable))!@#&    A.close()!@#&    succesBox(\"User succesfully removed!\")!@#&    return true!@#&   elseif name == usrTable[i][\"username\"] and pwd ~= usrTable[i][\"password\"] then!@#&    errorBox(\"Password does not match!\")!@#&    return false!@#&   end!@#&  end!@#& end!@#&end!@#&!@#&term.setBackgroundColour(colors.white)!@#&clear()!@#&term.setBackgroundColour(colors.lightGray)!@#&term.setCursorPos(1, 2)!@#&term.clearLine()!@#&write(\"Username: \")!@#&term.setCursorPos(1, 4)!@#&term.clearLine()!@#&write(\"Password: \")!@#&!@#&term.setCursorPos(11 , 2)!@#&input = read()!@#&term.setCursorPos(11, 4)!@#&pwd = read(\"*\")!@#&!@#&delUser(input, pwd)",["addUser"]="if not fs.exists(\"/\"..root..\"/system/.users\") then!@#& A = fs.open(\"/\"..root..\"/system/.users\", \"w\")!@#& local tbl = { [1] = {username = \"admin\", password = \"admin\" }}!@#& A.write(textutils.serialize(tbl))!@#& A.close()!@#& !@#& if not fs.exists(\"/\"..root..\"/users\") then!@#&  fs.makeDir(\"/\"..root..\"/users\")!@#&  fs.makeDir(\"/\"..root..\"/users/admin\")!@#& end!@#&!@#&end!@#&!@#&A = fs.open(\"/\"..root..\"/system/.users\", \"r\")!@#&local usrTable = textutils.unserialize(A.readAll())!@#&A.close()!@#&!@#&function clear()!@#& term.clear()!@#& term.setCursorPos(1,1)!@#&end!@#&!@#&function activate()!@#&term.setBackgroundColour(colors.white)!@#&clear()!@#&term.setTextColour(colors.gray)!@#&term.setCursorPos(1, 2)!@#&term.setBackgroundColour(colors.lightGray)!@#&term.clearLine()!@#&write(\"Username: \")!@#&!@#&term.setCursorPos(1, 4)!@#&term.clearLine()!@#&write(\"Password: \")!@#&!@#&term.setCursorPos(1, 6)!@#&term.clearLine()!@#&write(\"Re-type password: \")!@#&!@#&term.setCursorPos(11, 2)!@#&input = read()!@#&if input ~= \"\" then!@#& term.setCursorPos(11, 4)!@#& pw1 = read(\"*\")!@#& term.setCursorPos(19, 6)!@#& pw2 = read(\"*\")!@#& doUser()!@#&else!@#& errorBox(\"Username cannot be empty!\")!@#& return!@#&end!@#&end!@#&!@#&function errorBox(text)!@#& local maxX, maxY = term.getSize()!@#& term.setBackgroundColour(colors.red)!@#& term.setCursorPos(1, maxY/2-1)!@#& term.clearLine()!@#& term.setCursorPos(maxX/2-#text/2, maxY/2)!@#& term.clearLine()!@#& term.setTextColour(colors.white)!@#& write(text)!@#& term.setCursorPos(1, maxY/2+1)!@#& term.clearLine()!@#& sleep(2)!@#&end!@#&!@#&function succesBox(text)!@#& local maxX, maxY = term.getSize()!@#& term.setBackgroundColour(colors.green)!@#& term.setCursorPos(1, maxY/2-1)!@#& term.clearLine()!@#& term.setCursorPos(maxX/2-#text/2, maxY/2)!@#& term.clearLine()!@#& term.setTextColour(colors.white)!@#& write(text)!@#& term.setCursorPos(1, maxY/2+1)!@#& term.clearLine()!@#& sleep(2)!@#&end!@#&!@#&function addName(name, pwd)!@#& table.insert(usrTable, {username = name, password = pwd})!@#& A = fs.open(\"/\"..root..\"/system/.users\", \"w\")!@#& A.write(textutils.serialize(usrTable))!@#& A.close()!@#& fs.makeDir(\"/\"..root..\"/users/\"..name)!@#& succesBox(\"User succesfully added!\")!@#& return!@#&end!@#&!@#&function doUser()!@#& if pw1 ~= pw2 then!@#&  errorBox(\"Passwords do not match!\")!@#& else!@#&  for i,v in ipairs(usrTable) do!@#&   if input == usrTable[i][\"username\"] then!@#&    errorBox(\"User already exists!\")!@#&   end!@#&  end!@#&   addName(input, pw1)!@#&   --succesBox(\"User succesfully added!\")!@#& end!@#&end!@#&!@#&activate()",["listUsers"]="local file = \"/\"..root..\"/system/.users\"!@#&!@#&A = fs.open(file, \"r\")!@#&local usrTable = textutils.unserialize(A.readAll())!@#&A.close()!@#&!@#&local tbl = {}!@#&!@#&for i,v in ipairs(usrTable) do!@#& table.insert(tbl, usrTable[i][\"username\"])!@#&end!@#&!@#&table.sort(tbl)!@#&term.setBackgroundColour(colors.white)!@#&term.clear()!@#&term.setCursorPos(1,1)!@#&term.setTextColour(colors.gray)!@#&term.setBackgroundColour(colors.lightGray)!@#&textutils.pagedTabulate(tbl)!@#&!@#&local maxX, maxY = term.getSize()!@#&local text = \"Press any key to continue...\"!@#&term.setCursorPos(maxX/2-#text/2, maxY)!@#&term.clearLine()!@#&write(text)!@#&os.pullEvent(\"key\")",},["users"]={["admin"]={},},["images"]={["files"]="8888                                             !@#&8ff88                                            !@#&88888                                            !@#&8fff8                                            !@#&88888                                            !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 ",["luaide"]="fffff                                            !@#&fffff                                            !@#&fffff                                            !@#&fffff                                            !@#&fffff                                            !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 ",["firewolf"]=" 1  1                                            !@#&1e11e                                            !@#&eeeee                                            !@#&33e33                                            !@#&b333b                                            !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 ",["npaintpro"]="                                                 !@#&3                                                !@#& c  7                                            !@#&  c1                                             !@#& 1 c                                             !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 ",["snake"]="ddddd!@#&d   d!@#&d d!@#&d d e!@#&ddd  ",["wallpaper"]="                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                  1   5  9993                    !@#&                  1   5  9  33                   !@#&                  11155  9   3                   !@#&                  1   5  9   3                   !@#&                  1   5  9  33                   !@#&                  1   5  9993                    !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 !@#&                                                 ",},},["PkgMake"]="sPackage = \"local pkg = %@1 local function makeFile(_path, _content) local file = fs.open(_path, \\\"w\\\") _content = _content:gsub(\\\"\\!@\\\"..\\\"#&\\\", \\\"%\\\\n\\\") _content = textutils.unserialize(_content) file.write(_content) file.close() end local function makeFolder(_path, _content) fs.makeDir(_path) for k,v in pairs(_content) do if type(v) == \\\"table\\\" then makeFolder(_path .. \\\"/\\\" .. k, v) else makeFile(_path .. \\\"/\\\" .. k, v) end end end local sDest = shell.resolve( \\\"%@2\\\" ) or \\\"/\\\" if sDest == \\\"root\\\" then sDest = \\\"/\\\" end local tPackage = pkg makeFolder(sDest, tPackage) print(\\\"Package Extracted to '\\\" .. sDest .. \\\"'!\\\")\"!@#&!@#&function addFile(_package, _path)!@#&	if fs.getName(_path) == \".DS_Store\" then!@#&		return _package!@#&	end!@#&	local file, err = fs.open(_path, \"r\")!@#&	local content = file.readAll()!@#&	content = content:gsub(\"%\\n\", \"\\!@\"..\"#&\")!@#&	content = content:gsub(\"%%\", \"%%%%\")!@#&	_package[fs.getName(_path)] = content!@#&	file.close()!@#&	print(\"Added file '\".._path..\"'\")!@#&	return _package!@#&end!@#&!@#&function addFolder(_package, _path)!@#&	if string.sub(_path,1,string.len(\"rom\"))==\"rom\" or string.sub(_path,1,string.len(\"/rom\"))==\"/rom\" then!@#&		print(\"Ignored 'rom' folder. (\".._path..\")\")!@#&		return!@#&	end!@#&	_package = _package or {}!@#&	for _,f in ipairs(fs.list(_path)) do!@#&		local path = _path..\"/\"..f!@#&		if fs.isDir(path) then!@#&			_package[fs.getName(f)] = addFolder(_package[fs.getName(f)], path)!@#&		else!@#&			_package =  addFile(_package, path)!@#&		end!@#&	end!@#&	return _package!@#&end!@#&!@#&local tArgs = { ... }!@#&if #tArgs < 2 then!@#&	print( \"Usage: PkgMake <source> <destination>\" )!@#&	return!@#&end!@#&!@#&local sSource = shell.resolve( tArgs[1] )!@#&local sDest = shell.resolve( tArgs[2] )!@#&!@#&if fs.isDir( sDest ) then!@#&	error(\"Destination must not be a folder.\")!@#&end!@#&!@#&if sSource == sDest then!@#&	error(\"Source can not be equal to destination.\")!@#&end!@#&!@#&if fs.exists( sSource ) and fs.isDir( sSource ) then!@#&	tPackage = {}!@#&	tPackage = addFolder(tPackage, sSource)!@#&	fPackage = fs.open(sDest,\"w\")!@#&!@#&	sPackage = string.gsub(sPackage, \"%%@2\", fs.getName(sSource))!@#&	sPackage = string.gsub(sPackage, \"%%@1\", textutils.serialize(tPackage))!@#&	fPackage.write(sPackage)!@#&	fPackage.close()!@#&	print(\"Package Done! ('\" .. sDest .. \"')\")!@#&	print(\"Type '\" .. sDest .. \"' to run it.\")!@#&else!@#&	error(\"Source does not exist or is not a folder.\")!@#&end",} local function makeFile(_path, _content) local file = fs.open(_path, "w") _content = _content:gsub("!@".."#&", "%\n") _content = textutils.unserialize(_content) file.write(_content) file.close() end local function makeFolder(_path, _content) fs.makeDir(_path) for k,v in pairs(_content) do if type(v) == "table" then makeFolder(_path .. "/" .. k, v) else makeFile(_path .. "/" .. k, v) end end end local sDest = shell.resolve( "root" ) or "/" if sDest == "root" then sDest = "/" end local tPackage = pkg makeFolder(sDest, tPackage) print("Package Extracted to '" .. sDest .. "'!") fs.delete("/"..shell.getRunningProgram())