View difference between Paste ID: KJ4t2DM9 and G7SmdMKD
SHOW: | | - or go back to the newest paste.
1-
-- 'Map' by EldidiStroyrr (LDDestroier)
1+
--[[
2-
-- This program can be copied, and it can be modified, but it
2+
   'Map' (GPS Minimap) by EldidiStroyrr (LDDestroier)
3-
-- can NOT be copied, modified slightly, and then claimed as your own.
3+
4-
-- You must give me, EldidiStroyrr, credit for the creation and
4+
    Get with
5-
-- only reference yourself as some guy who changed a bit.
5+
   pastebin get KJ4t2DM9 map
6
     or
7-
parentDir = "/" .. fs.getDir(shell.getRunningProgram())
7+
    std pb KJ4t2DM9 map
8-
waypointFile = "/" .. fs.combine(parentDir, ".waypoints")
8+
    std ld map map
9-
mapConfigFile = "/" .. fs.combine(parentDir, "/.map_conf")
9+
10
	This is a beta release. You fool!
11-
function updateMapProgram()
11+
--]]
12-
	local mapName = shell.getRunningProgram()
12+
13-
	local updateFile = http.get("http://pastebin.com/raw.php?i=G7SmdMKD").readAll()
13+
local mapRelease = "beta"
14
local pastebinIDList = {
15
	main = "x9ajKSc0",
16
	beta = "KJ4t2DM9",
17
}
18
mapVersion = "1.3.9 Beta" --Version of Map. Must be string.
19
20-
scr_x, scr_y = term.getSize()
20+
os.pullEvent = os.pullEventRaw
21
local parentDir = fs.combine("",fs.getDir(shell.getRunningProgram()))
22
local configDir = fs.combine(parentDir,".map")
23
if not fs.isDir(configDir) then
24
	if fs.exists(configDir) then fs.delete(configDir) end
25
	fs.makeDir(configDir)
26
end
27
if fs.isReadOnly(shell.resolve(shell.getRunningProgram())) then --In case Map is located in a write-protected directory.
28
	waypointDir = fs.combine(fs.getName(configDir),"waypoints")
29
	mapConfigFile = fs.combine(fs.getName(configDir),"config")
30
	pathDir = fs.combine(fs.getName(configDir),"paths")
31
else
32-
		if fs.exists(waypointFile) then
32+
	waypointDir = "/" .. fs.combine(configDir, "waypoints")
33-
			fs.delete(waypointFile)
33+
	mapConfigFile = "/" .. fs.combine(configDir, "config")
34
	pathDir = fs.combine(configDir,"paths")
35
end
36
if not fs.exists(waypointDir) then fs.makeDir(waypointDir) end
37
if not fs.exists(pathDir) then fs.makeDir(pathDir) end
38
defaultWaypointFile = "waypoints" --The name of the waypoint file that is written to.
39
mapNetworkWaypointsFile = fs.combine(waypointDir,"networkPoints")
40
local mapName
41-
		write("Updating " .. mapName .. "...")
41+
function updateMapProgram(url)
42-
		local fileSize = updateMapProgram()
42+
	if not fs.isReadOnly(shell.resolve(shell.getRunningProgram())) then
43
		mapName = fs.combine("",shell.getRunningProgram())
44
	else
45
		mapName = shell.getRunningProgram()
46-
	if tArg[1] ~= "mon" then
46+
47
	local updateFile
48
	if url then
49
		updateFile = http.get(url)
50-
mapColors = {
50+
51-
	colors.gray, --Background color
51+
		updateFile = http.get("http://pastebin.com/raw.php?i=" .. pastebinIDList[mapRelease])
52-
	colors.white, --Border color
52+
53-
	colors.yellow, --Waypoint color
53+
	if updateFile then
54-
	colors.red, --Off-screen waypoint text color
54+
		updateFile = updateFile.readAll()
55-
	colors.lightBlue, --Player color
55+
56-
	colors.black, --Command screen text color
56+
		error("Could not connect.")
57-
	colors.lightGray, --Command screen background color
57+
58-
	colors.red --Background color if not connected to a GPS server
58+
59
	file.write(updateFile)
60
	file.close()
61-
directionSensitivity = 0.6
61+
62-
mapCorners = { --Top left corner, bottom right corner
62+
63-
	{
63+
64-
		2,
64+
function setColormode()
65-
		2,
65+
	if term.isColor() and colorLimit >= 2 then
66-
	},
66+
		colormode = true
67-
	{
67+
		grayAllowed = true
68-
		scr_x - 1,
68+
69-
		scr_y - 6,
69+
		colormode = false
70
		if _VERSION and colorLimit == 1 then
71
			grayAllowed = true
72-
corner1 = mapCorners[1]
72+
73-
corner2 = mapCorners[2]
73+
			grayAllowed = false
74-
midPoint = {
74+
75-
	math.floor((corner1[1] + corner2[1]) / 2),
75+
76-
	math.floor((corner1[2] + corner2[2]) / 2)
76+
77
78-
mapDimensions = {
78+
local nothing = false
79-
	corner2[1] - corner1[1],
79+
80-
	corner2[2] - corner1[2]
80+
81
	if tArg[1] == "cc" then
82
		if fs.exists(mapConfigFile) then
83-
if term.isColor() then
83+
84-
	colormode = true
84+
85
		else
86-
	colormode = false
86+
87
		end
88
		fakeX = nil
89-
isConnected = true
89+
		fakeY = nil
90
		fakeZ = nil
91
		fakeDir = nil
92
		return
93
	elseif tArg[1] == "cw" then
94
		if fs.exists(waypointDir) then
95
			fs.delete(waypointDir)
96
			print("Waypoints cleared.")
97
		else
98
			print("No waypoints to clear.")
99-
function getConfig()
99+
100-
	if not fs.exists(waypointFile) then
100+
101-
		file = fs.open(waypointFile, "w")
101+
	elseif tArg[1] == "oc" then
102-
		file.write({})
102+
		shell.run("edit "..mapConfigFile)
103
		print("Config updated.")
104
		return
105-
	file = fs.open(waypointFile, "r")
105+
	elseif tArg[1] == "nothing" then
106-
	contents = file.readAll()
106+
		nothing = true
107-
	contents = textutils.unserialize(contents)
107+
108
		local file = tArg[2]
109
		local updateURL
110-
	for a = 1, #contents do
110+
		if not tArg[2] then
111-
		table.insert(waypoints, contents[a])
111+
			file = "beta"
112
			updateURL = pastebinIDList[file]
113
		else
114-
	if not fs.exists(mapConfigFile) then
114+
			if pastebinIDList[file] then
115-
		file = fs.open(mapConfigFile, "w")
115+
				updateURL = pastebinIDList[file]
116-
		file.writeLine("-" .. "- Do not break the format of this config.")
116+
117-
		file.writeLine("-" .. "- This is for Eldidi's Map. Do 'map cc' to fix broken config.")
117+
				print("Invalid update source.")
118-
		file.writeLine("spoofMode = false -" .. "-boolean, set true if testing program in emulator. Replaces gps movement detection with arrow keys. Default: false")
118+
				return false
119-
		file.writeLine("scaleFactor = 0.25 -" .. "-number, the zoom factor for the minimap. Lower means wider range. Does not affect GPS range. Default: 0.25")
119+
120-
		file.writeLine("labelMode = true -" .. "-boolean, true if waypoint labels are their names, false if their distances. Default: true")
120+
121-
		file.writeLine("youChar = 'O' -" .. "-string, the character which defaultly represents you in the map. is overwritten by arrows, so this is useless come to think of it. Default: 'O'")
121+
		write("Updating " .. shell.getRunningProgram() .. "...")
122-
		file.writeLine("waypointChar = '*' -" .. "-string, the character that waypoints on the map are represented by. Default: '*'")
122+
123-
		file.writeLine("blankChar = ' ' -" .. "-string, the blank character that the inside of the map is made of. Default: ' '")
123+
		local fileSize = updateMapProgram("http://pastebin.com/raw.php?i=" .. updateURL)
124-
		file.writeLine("refreshSleep = 0.4 -" .. "-number, the delay between each GPS request. Default: 0.4")
124+
125-
		file.writeLine("autoUpdate = false -" .. "-boolean, whether or not Map automatically updates to the latest version. this is reccommended FALSE because new updates could break the program into a state where it can't update again.")
125+
		write("Updated from "..mapVersion)
126
		shell.run(fs.getName(shell.getRunningProgram()),"nothing")
127
		if mapVersion then
128-
	shell.run(mapConfigFile)	
128+
			print(" to "..mapVersion)
129-
	return contents
129+
130
			print("...whatever.")
131
		end
132-
function setConfig(pointname, mode, x, y, z)
132+
133-
	config = getConfig()
133+
	elseif tArg[1] == "help" then
134-
	file = fs.open(waypointFile, "w")
134+
		local helpText = [[
135
'map update' Updates program.
136
'map fast' Runs term.redirect(term.native()).
137
'map cw' Deletes waypoints.
138
'map cc' Deletes config.
139
'map oc' Opens config.
140
'map nothing' gets config, but doesn't run
141
Config path: ']]..mapConfigFile..[['
142
Waypoint directory: ']]..waypointDir..[[']]
143
		print(helpText)
144
		return true
145
	elseif tArg[1] == "fast" then
146
		term.redirect(term.native())
147
	end
148
end
149
local sides = {"up","down","left","right","front","back"}
150
for a = 1, #sides do
151
	if peripheral.getType(sides[a]) == "modem" then
152
		rednet.open(sides[a])
153-
		table.insert(config, {pointname, x, y, z})
153+
		break
154
	end
155
end
156
local function runMapProgramAlready() --This is to allow me to run pcall on the program.
157
function numberToColor(input)
158
	if type(input) == "number" then
159
		for k,v in pairs(colors) do
160
			if input == v then
161
				return "colors."..k
162-
	file = fs.open(mapConfigFile, "r")
162+
163-
	configFile = file.readAll()
163+
164-
	configFile = textutils.unserialize(configFile)
164+
	elseif type(input) == "table" then
165
		local output = {}
166
		for a = 1, #input do
167-
	file = fs.open(mapConfigFile, "w")
167+
			for k,v in pairs(colors) do
168-
	settings = {
168+
				if input[a] == v then
169-
		"spoofMode = " .. tostring(spoofMode),
169+
					table.insert(output,"colors."..k)
170-
		"scaleFactor = " .. tostring(scaleFactor),
170+
171-
		"labelMode = " .. tostring(labelMode),
171+
172-
		"youChar = '" .. tostring(youChar) .. "'",
172+
173-
		"waypointChar = '" .. tostring(waypointChar) .. "'",
173+
		return output
174-
		"blankChar = '" .. tostring(blankChar) .. "'",
174+
175-
		"refreshSleep = " .. tostring(refreshSleep)
175+
176
end
177-
	for a = 1, #settings do
177+
function yield()
178-
		file.writeLine(settings[a])
178+
	os.queueEvent("yield")
179
	os.pullEvent("yield")
180
end
181
function seperateMethods(input)
182
	local output={}
183
	for key,value in pairs(input) do
184-
function setDefaultConfig()
184+
		table.insert(output, {key,value})
185-
	if not fs.exists(waypointFile) then
185+
186-
		waypoints = {
186+
	return output
187
end
188-
				"Test 1",
188+
function defineMapBorders()
189
	scr_x, scr_y = term.getSize()
190-
				62,
190+
	local mapCorners
191-
				6
191+
	if not monitorMode then
192
		mapCorners = { --Top left corner, bottom right corner
193
			{
194-
				"Test 2",
194+
195-
				5,
195+
196-
				70,
196+
197-
				3
197+
198
				scr_x - 1,
199
				scr_y - 6,
200-
		file = fs.open(waypointFile, "w")
200+
201-
		file.writeLine(textutils.serialize(waypoints))
201+
202
	else
203
		mapCorners = {
204
			{
205
				1,
206
				1,
207
			},
208
			{
209
				scr_x,
210
				scr_y - 3,
211
			}
212
		}
213
	end
214
	corner1 = mapCorners[1]
215
	corner2 = mapCorners[2]
216-
			term.setBackgroundColor(colors.black)
216+
	midPoint = {
217
		math.floor((corner1[1] + corner2[1]) / 2),
218
		math.floor((corner1[2] + corner2[2]) / 2)
219
	}
220
	mapDimensions = {
221
		corner2[1] - corner1[1],
222
		corner2[2] - corner1[2]
223
	}
224
end
225
--[[ In case adding this to the config messes something up, I want to easily fix it.
226
	mapColors = { --This controls most of the colors in the program, except for some hardcoded colors. If you are using a normal computer, grayscale or not, colors will not be pulled from this list.
227
		colors.gray,      --Background color (default: colors.gray)
228
		colors.white,     --Border color (default: colors.white)
229
		colors.yellow,    --Waypoint color (default: colors.yellow)
230
		colors.red,       --Offscreen waypoint arrow color (default: colors.red)
231
		colors.lightBlue, --Direction indicator color (default: colors.lightBlue)
232
		colors.black,     --Command list text color (default: colors.black)
233
		colors.lightGray, --Command list background color (default: colors.lightGray)
234-
			term.setTextColor(colors.white)term.setTextColor(colors.black)
234+
		colors.red,       --Background color if not connected to GPS server (default: colors.red)
235
		colors.black,     --Map background color (default: colors.black)
236
	}
237
	
238
	directionSensitivity = 0.15 --This is used to prevent the arrow on the middle of the screen from going crazy.
239
--]]
240
displayStuffs = true
241
currentlyConnected = false --We don't know, so assume false because of glitch with numpad
242
isConnected = true --We still don't know, and it's just safer to assume false because of visual bugs
243
arrows = {
244
	">",
245
	"v",
246
	"<",
247
	"^"
248
}
249-
		local coord_x, coord_y, coord_z = gps.locate(1)
249+
youChar = "O" --This used to be a config item, too bad it was useless. Luckily, it was replaced with many, much more useful options for you to screw up.
250
playerChar = youChar
251
function displayTitleScreen()
252
	term.clear()
253
	term.setCursorPos(1,1)
254
	if colormode then
255
		paintutils.drawImage(mapTitleScreen_adv, 1, 1)
256
	else
257
		if grayAllowed then
258
			paintutils.drawImage(mapTitleScreen_gray, 1, 1)
259
		else
260
			paintutils.drawImage(mapTitleScreen_norm, 1, 1)
261
		end
262
	end
263-
				local coord_x, coord_y, coord_z = gps.locate(3)
263+
	term.setTextColor(colors.white)
264
	if colormode then
265
		term.setBackgroundColor(colors.lightBlue)
266
	else
267
		if grayAllowed then
268
			term.setBackgroundColor(colors.white)
269
		else
270
			term.setBackgroundColor(colors.gray)
271
		end
272
	end
273-
			return {0, 0, 0}
273+
	term.setCursorPos(5,4)
274
	print("Version " .. mapVersion)
275-
			term.setCursorPos(1,1)
275+
	term.setCursorPos(5,3)
276
	print("Made by EldidiStroyrr")
277
	sleep(0.1)
278
	repeat
279
		event, param1 = os.pullEvent()
280
	until event == "key" or event == "mouse_click" or event == "monitor_touch"
281
end
282
function getConfig(mode)
283
	if not fs.exists(fs.combine(waypointDir, defaultWaypointFile)) or (not fs.isDir(waypointDir)) then
284
		if fs.exists("/.waypoints") and (not fs.isDir("/.waypoints")) then
285
			fs.move("/.waypoints", "/waypoints")
286-
		local buffX = corner1[1] + 1
286+
			fs.makeDir(waypointDir)
287-
		local mapLengthInner = (corner2[1]) - (corner1[1]) - 1
287+
			fs.move("/waypoints", fs.combine(waypointDir, defaultWaypointFile))
288-
		local longBlankChar1 = string.rep(blankChar, mapLengthInner)
288+
289-
		for y = corner1[2] + 1, corner2[2] - 1 do
289+
			fs.makeDir(waypointDir)
290-
			term.setCursorPos(buffX,y)
290+
			file = fs.open(fs.combine(waypointDir, defaultWaypointFile), "w")
291-
			write(longBlankChar1)
291+
			file.write({})
292
			file.close()
293-
		local buffX = corner1[1] - 1
293+
294-
		for y = corner1[2], corner2[2] do
294+
295-
			term.setCursorPos(buffX,y)
295+
	local wayFiles = fs.list(waypointDir)
296-
			write(" ") --I do " " because 'blankChar' is for the inside of the map.
296+
297
	fileWaypoints = {}
298-
		local buffX = corner2[1] + 1
298+
	for a = 1, #wayFiles do
299-
		for y = corner1[2], corner2[2] do
299+
		if not fs.isDir(fs.combine(waypointDir, wayFiles[a])) then
300-
			term.setCursorPos(buffX,y)
300+
			file = fs.open(fs.combine(waypointDir, wayFiles[a]), "r")
301-
			write(" ") --Same here.
301+
			contents = file.readAll()
302
			contents = textutils.unserialize(contents)
303
			file.close()
304-
			buffY = corner1[2] - 1
304+
			for b = 1, #contents do
305-
			term.setCursorPos(1,buffY)
305+
				table.insert(waypoints, contents[b])
306
				if wayFiles[a] == defaultWaypointFile then
307
					table.insert(fileWaypoints, contents[b])
308
				end
309
			end
310
		end
311
	end
312
	
313-
	--Drawing border. Always is drawn first.
313+
	--This part has been modified to automatically fix missing config options, at the cost of the inability to add custom ones. Sorry, but this is more useful.
314-
	if displayStuffs and isConnected then
314+
	local modem = peripheral.find("modem")
315
	if modem and mapProtocol then
316-
			term.setTextColor(mapColors[2])
316+
		for a = 1, #mapProtocol do
317
			modem.close(mapProtocol[a])
318
		end
319
	end
320
	spoofMode = false
321
	broadcastData = true
322
	scaleFactor = 0.25
323
	networkName = "mapuser"..math.random(1,9999)
324
	mapProtocol = {10666}
325
	displayTitle = false
326
	labelMode = true
327
	waypointChar = '*'
328-
		local longMapChar = string.rep("#", mapLength)
328+
	blankChar = ' '
329
	refreshSleep = 0.4
330
	autoUpdate = false
331
	if turtle then
332
		turtleMode = true
333
	else
334
		turtleMode = false
335-
			write("#")
335+
336
	keyAgoesRight = false --Useless and probably cauyses problems..but whatever
337
	spoofStep = 1
338
	mapColors = { --This controls most of the colors in the program, except for some hardcoded colors. If you are using a normal computer, grayscale or not, colors will not be pulled from this list.
339-
				term.setCursorPos(corner2[1],b)
339+
		colors.gray, --Background color outside map square
340-
				write("#")
340+
		colors.white, --Border color
341
		colors.yellow, --Default waypoint color
342
		colors.red, --Off-screen waypoint text color
343
		colors.lightBlue, --Player color
344-
			term.setTextColor(mapColors[7])
344+
		colors.black, --Command screen text color
345
		colors.lightGray, --Command screen background color
346
		colors.red, --Background color if not connected to a GPS server
347
		colors.black, --Background color inside map square
348
	}
349
	directionSensitivity = 0.15 --This is used to prevent the arrow on the middle of the screen from going crazy.
350
	monitorTextScale = 0.5 --This determines what scale factor the text has if Map is being ran on a monitor.
351
	fakeX = 0
352
	fakeY = 66
353
	fakeZ = 0
354
	fakeDir = 0
355
	doFlash = fals
356
	colorLimit = 2
357-
		term.setCursorPos(corner2[1],midPoint[2])
357+
358-
		write("X")
358+
	shell.run(mapConfigFile) --Get the existing config options.
359
	setColormode()
360
	
361
	if not type(networkName) == "string" then networkName = "mapuser"..math.random(1,9999) end
362
	if not type(mapProtocol) == "table" then mapProtocol = {10666} end
363
	
364-
	isConnected = true
364+
	refreshOtherConfig() --Set the config file to what the variables are.
365
	
366
	scr_x, scr_y = term.getSize()
367
	if scr_x > 16 or scr_y > 10 then --Determines if Map is being ran on a single monitor block.
368
		monitorMode = false
369
	else
370
		monitorMode = true
371
	end
372
	if not monitorTextScale then --This whole bit is for monitors, should you be arsed to use them with this.
373
		monitorTextScale = 0.5
374
	end
375
	if monitorTextScale < 0.5 then
376-
					wasConnected = false
376+
		monitorTextScale = 0.5
377
	elseif monitorTextScale > 5 then
378
		monitorTextScale = 5
379-
							term.setBackgroundColor(colors.red)
379+
380
	if type(monitorTextScale) ~= "number" then
381
		monitorTextScale = 0.5
382
	end
383
384
	local mon = peripheral.find("monitor")
385-
						repeat
385+
	if mon then
386-
							poses = getCoordinates()
386+
		if not monitorMode then
387-
							sleep(0)
387+
			mon.setTextScale(monitorTextScale)
388-
						until isConnected == true
388+
389
			mon.setTextScale(0.5)
390
		end
391-
			until isConnected == true
391+
392
	if mode == "waypoint" then
393
		return fileWaypoints
394-
				if not wasConnected then
394+
395-
					wasConnected = true
395+
		return contents
396-
					term.clear()
396+
397-
					renderCommands()
397+
398
function set(list) --Used to check if a phrase is in a table. Straight from StackOverflow, by Jon Ericson.
399
	local set = {}
400
	for _, l in ipairs(list) do
401
		set[l] = true
402
	end
403
	return set
404
end
405
function stringToColor(color)
406
	local stringColors = {"white","orange","magneta","lightBlue","yellow","lime","pink","gray","lightGray","cyan","purple","blue","brown","green","red","black"}
407
	local numberColors = {colors.white,colors.orange,colors.magneta,colors.lightBlue,colors.yellow,colors.lime,colors.pink,colors.gray,colors.lightGray,colors.cyan,colors.purple,colors.blue,colors.brown,colors.green,colors.red,colors.black}
408-
			if math.abs(oldCoord_x - posX) > directionSensitivity or math.abs(oldCoord_z - posZ) > directionSensitivity then
408+
	if string.sub(color, 1, 7) == "colors." then
409
		color = string.sub(color, 8)
410
	end
411
	for a = 1, #stringColors do
412
		if string.lower(color) == string.lower(stringColors[a]) then
413
			return numberColors[a]
414
		end
415
	end
416
	return false
417
end
418
function setConfig(pointname, mode, x, y, z, derf)
419
	config = getConfig("waypoint")
420
	file = fs.open(fs.combine(waypointDir, defaultWaypointFile), "w")
421
	if mode == "delete" then
422
		for a = 1, #config do
423
			point = config[a]
424
			if point[1] == pointname then
425
				table.remove(config, a)
426-
			if (oldCoord_x ~= posX or oldCoord_z ~= posZ) then
426+
427
				file.close()
428
				getConfig()
429
				return true
430-
			if hadCleared then
430+
431
		end
432
		file.close()
433
		return false
434-
			hadCleared = false
434+
435
		if x == nil or y == nil or z == nil then
436
			file.close()
437
			return false
438
		end
439
		table.insert(config, {pointname, x, y, z, derf})
440
		file.writeLine(textutils.serialize(config))
441
		file.close()
442
		getConfig()
443
		return true
444-
				itemX = math.ceil((midPoint[1] + (wayX - posX) * scaleFactor))
444+
	elseif mode == "rename" then
445-
				itemZ = math.floor((midPoint[2] + (posZ - wayZ) * scaleFactor))
445+
446
			point = config[a]
447
			if point[1] == pointname then
448-
				if itemX > corner1[1] and itemX < corner2[1] and itemZ < corner2[2] and itemZ > corner1[2] then
448+
				table.remove(point, 1)
449
				table.insert(point, 1, x)
450
				file.writeLine(textutils.serialize(config))
451-
							term.setTextColor(mapColors[3])
451+
452
				getConfig()
453-
							term.setTextColor(colors.white)
453+
454-
							term.setBackgroundColor(colors.black)
454+
455
		end
456-
						write(waypointChar)
456+
457
		return false
458
	end
459-
							term.setTextColor(mapColors[8])
459+
460
end
461-
							term.setTextColor(colors.black)
461+
462
	local file = fs.open(mapConfigFile, "w")
463
	local mapSettings = {
464
		{
465
			"spoofMode = " .. tostring(spoofMode),
466-
						term.setTextColor(mapColors[4])
466+
			"boolean, set true if testing program in emulator. Replaces gps movement detection with arrow keys. Default: false",
467
		},
468
		{
469
			"broadcastData = " .. tostring(broadcastData),
470
			"boolean, set true if you want other people to see your location. Default: true",
471
		},
472
		{
473
			"networkName = '" .. tostring(networkName) .. "'",
474
			"string, what your name appears as for other Map clients. Default: 'mapuser'..math.random(1,9999)",
475
		},
476
		{
477-
						if itemX * -1 >= itemZ * -1 then
477+
			"mapProtocol = " .. textutils.serialize(mapProtocol),
478
			"table, list of modem protocols of the data broadcasted to other clients. Default: {10666}",
479
		},
480
		{
481
			"scaleFactor = " .. tostring(scaleFactor),
482
			"number, the zoom factor for the minimap. Lower means wider range. Does not affect GPS range. Default: 0.25",
483
		},
484-
						if itemX * -1 >= itemZ then
484+
		{
485
			"displayTitle = " .. tostring(displayTitle),
486
			"boolean, whether or not to display the title screen. I find it kind of garish, but I already did the work. Default: false",
487
		},
488
		{
489
			"labelMode = " .. tostring(labelMode),
490
			"boolean, true if waypoint labels are their names, false if their distances. Default: true",
491
		},
492
		{
493
			"waypointChar = '" .. tostring(waypointChar) .. "'",
494-
						if itemX >= itemZ * -1 then
494+
			"string, the character that waypoints on the map are represented by. Default: '*'",
495
		},
496
		{
497
			"blankChar = '" .. tostring(blankChar) .. "'",
498
			"string, the blank character that the inside of the map is made of. Default: ' '",
499
		},
500
		{
501-
						if itemX >= itemZ then
501+
			"refreshSleep = " .. tostring(refreshSleep),
502
			"number, the delay between each GPS request. Default: 0.4",
503
		},
504
		{
505
			"autoUpdate = " .. tostring(autoUpdate),
506
			"boolean, whether or not Map automatically updates to the latest version. this is reccommended FALSE because new updates could break the program into a state where it can't update again. Default: false",
507
		},
508
		{
509
			"turtleMode = " .. tostring(turtleMode),
510
			"boolean, whether Map should be tuned to turtle controlling. Especially useful if used in conjunction with Lyqyd's NSH. Default: false",
511
		},
512
		{
513-
					setDefaultColors()
513+
			"keyAgoesRight = " .. tostring(keyAgoesRight),
514
			"boolean, determines whether to invert the left/right turtle turning controls. Requires turtleMode=true. This option exists because the 'A' button turns the turtle left on the map, but not in minecraft world. Default: false",
515
		},
516-
					term.setTextColor(mapColors[3])
516+
		{
517
			"spoofStep = " .. tostring(spoofStep),
518
			"number, amount you move in one keypress in spoof mode. Used to move faster. Default: 1",
519
		},
520
		{
521
			"mapColors = " .. string.gsub( textutils.serialize(numberToColor(mapColors)), "\"", "" ),
522
			"table, there are 9 items in this array, and this controls most of the colors in the program, except for some hardcoded colors and for normal computers. The colors are, in sequence: background color outside, border color, waypoint color, offscreen waypoint arrow color, direction indicator color, command screen text color, command screen background color, background color if not connected to GPS, background color inside. Do not input any values into this config option that isn't a color, or the program will crash. Default: {colors.gray, colors.white, colors.yellow, colors.red, colors.lightBlue, colors.black, colors.lightGray, colors.red, colors.black}",
523
		},
524-
						pointMidX = math.ceil(itemX - (string.len(pointName) / 2))
524+
		{
525
			"directionSensitivity = " .. tostring(directionSensitivity),
526
			"number, this is used to prevent the arrow on the middle of the screen from going crazy. it will only change the middle indicator if you move that amount of meters. Default: 0.15",
527
		},
528
		{
529-
						pointMidX = itemX - math.floor(string.len(pointName) / 2)
529+
			"monitorTextScale = " .. tostring(monitorTextScale), 
530
			"number, this determines what scale factor the text has if Map is being ran on a monitor. Default: 0.5",
531
		},
532
		{
533-
					if pointMidX + string.len(pointName) > scr_x then
533+
			"fakeX = " .. tostring(fakeX),
534-
						subLength = (scr_x - pointMidX)
534+
			"number, this is the last recorded X position of the turtle/PDA. Is used in spoofMode, and updates when using turtleMode. Default: 0",
535
		},
536-
						if pointMidX <= scr_x then
536+
		{
537-
							write(subName)
537+
			"fakeY = " .. tostring(fakeY),
538
			"number, same as fakeX but for Y. Default: 66",
539
		},
540-
						write(pointName)
540+
		{
541
			"fakeZ = " .. tostring(fakeZ),
542
			"number, same as fakeX but for Z. Default: 0",
543
		},
544-
			term.setCursorPos(midPoint[1],midPoint[2])			
544+
		{
545
			"fakeDir = " .. tostring(fakeDir),
546-
				term.setTextColor(mapColors[5])
546+
			"number, equal to 'f' in Debug mode in Minecraft (F3), range=0-3. Default: nil",
547
		},
548
		{
549
			"doFlash = " .. tostring(doFlash),
550
			"boolean, whether or not to do the flash animation when starting map up or exiting a menu. Default: false",
551
		},
552
		{
553
			"colorLimit = " .. tostring(colorLimit),
554
			"number, artificially limits the color palate. (0=monochrome,1=grayscale,2=colors). Default: 2",
555
		},
556-
			if direction == "east" then
556+
557-
				playerChar = ">"
557+
	file.writeLine("-" .. "- Do not break the format of this config.")
558-
			elseif direction == "west" then
558+
	file.writeLine("-" .. "- This is for EldidiStroyrr/LDDestroier's 'Map' (GPS Minimap). Do 'map cc' to fix broken config.")
559-
				playerChar = "<"
559+
	file.writeLine("-" .. "- This config has been last used on version " .. mapVersion .. ", for reference.")
560-
			elseif direction == "south" then
560+
	for a = 1, #mapSettings do
561-
				playerChar = "v"
561+
		file.writeLine(mapSettings[a][1] .. "  -" .. "-" .. mapSettings[a][2])
562-
			elseif direction == "north" then
562+
563-
				playerChar = "^"
563+
	file.writeLine("")
564
	file.close()
565-
				playerChar = "O"
565+
566
function round(num, idp)
567
	local mult=10^(idp or 0)
568
	return math.floor(num * mult + 0.5 ) / mult
569
end
570-
			itemX = corner1[1] + 1
570+
571-
			itemY = corner2[2] + 1
571+
572-
			term.setCursorPos(itemX,itemY)
572+
573
			term.setBackgroundColor(mapColors[1])
574
		else
575
			if grayAllowed then
576
				term.setBackgroundColor(colors.gray)
577-
			write("Scale: ")
577+
578
				term.setBackgroundColor(colors.black)
579
			end
580
		end
581-
			write(scaleFactor .. "x")
581+
582
		if colormode then
583
			term.setBackgroundColor(mapColors[8])
584
		else
585
			term.setBackgroundColor(colors.white)
586
		end
587
	end
588
end
589
function setDefaultTextColor()
590
	if colormode then
591
		term.setTextColor(mapColors[2])
592
	else
593-
		"(S)et scale",
593+
594-
		"(L)abel/distance",
594+
595-
		"(C)reate waypoint",
595+
596-
		"(D)elete waypoint",
596+
597
		end
598-
		"C(o)nf",
598+
599-
		"(H)elp"
599+
600
function setDefaultColors()
601-
	if not isConnected then
601+
602
	setDefaultBackgroundColor()
603
end
604
recordBuffer = {}
605
if not oldCoord_x then
606
	oldCoord_x, oldCoord_y, oldCoord_z = 0,0,0
607
	posX, posY, posZ = 0,0,0
608
end
609-
		print(gpsNotFoundString .. string.rep(" ", scr_x-string.len(gpsNotFoundString)-2))
609+
local function savePath(path)
610
	if not path then return false, "you need a table." end
611
	local pathpath
612-
	startY = corner2[2] + 1
612+
613
	term.clear()
614
	term.setCursorPos(1,2)
615
	print("Save path as: (blank for cancel)")
616-
		term.setCursorPos(startX,startY)
616+
617
		write(">")
618
		pathpath = read()
619
		if pathpath == "" then
620
			print("Cancelling.")
621
			sleep(0.2)
622
			return false
623
		end
624-
			term.setBackgroundColor(colors.black)
624+
		if fs.exists(fs.combine(pathDir,pathpath)) then
625
			pathpath = ""
626
			print("That already exists.")
627
		end
628-
			comPosX, comPosZ = term.getCursorPos()
628+
	until pathpath ~= ""
629
	pathpath = fs.combine(pathDir,pathpath)
630
	local file = fs.open(pathpath,"w")
631-
				startY = startY + 1
631+
	file.writeLine(textutils.serialize(path))
632-
				term.setCursorPos(startX,startY)
632+
633
	print("Okay!")
634
	sleep(0.2)
635
	return true
636-
			if f ~= #commands then
636+
637-
				write(", ")
637+
638
	if spoofMode then
639
		isConnected = true
640
		currentlyConnected = true
641
		os.queueEvent("gpsRequest", true)
642
		return {fakeX, fakeY, fakeZ}
643
	else
644
		oldCoord_x, oldCoord_y, oldCoord_z = coord_x, coord_y, coord_z
645
		coord_x, coord_y, coord_z = gps.locate(0.75)
646
		if (coord_x == nil) and isConnected then
647
			currentlyConnected = false
648
			os.queueEvent("gpsRequest", false)
649-
	print(" 'Map' is a GPS minimap program made by EldidiStroyrr (LDDestroier).")
649+
650
				term.setCursorPos(2,1)
651-
	print("* 'map cc' clears config.")
651+
652-
	print("* 'map cw' clears waypoints.")
652+
653-
	print("* A red screen means no access to a GPS server.")
653+
654-
	print("* Deleting waypoints deletes the earliest waypoint made of that name.")
654+
655-
	print("* Pressing numpad '+' or '-' will zoom in and out without a prompt.")
655+
656-
	print("* Pressing 'S' will prompt you to change scale.")
656+
657
			if isConnected then
658
				if displayStuffs then
659
					term.clearLine()
660
					print("GPS not found...searching")
661
				end
662
				for a = 1, 5 do
663
					coord_x, coord_y, coord_z = gps.locate(1)
664
					if coord_x == nil then os.queueEvent("gpsRequest", false) end
665
				end
666
				if displayStuffs then
667
					if coord_x == nil then
668
						term.clearLine()
669
					end
670
				end
671
			end
672
		end
673
		if coord_x == nil then
674
			isConnected = false
675
			os.queueEvent("gpsRequest", false)
676
			return nil
677
		else
678
			isConnected = true
679-
	print("What X? (default: here)")
679+
			currentlyConnected = true
680
			os.queueEvent("gpsRequest", true)
681
			fakeX, fakeY, fakeZ = coord_x, coord_y, coord_z
682
			if recording then
683-
		newX = math.floor(posX)
683+
				if (math.floor(coord_x) ~= math.floor(oldCoord_x)) or (math.floor(coord_y) ~= math.floor(oldCoord_y)) or (math.floor(coord_z) ~= math.floor(oldCoord_z)) then
684
					table.insert(recordBuffer,{math.floor(coord_x),math.floor(coord_y),math.floor(coord_z)})
685-
	print("What Y? (default: here)")
685+
686
			else
687-
	newY = tonumber(read())
687+
				if #recordBuffer > 0 then
688-
	if newY == nil then
688+
					currentLocation = "savePath"
689-
		newY = math.floor(posY)
689+
					displayStuffs = false
690
					savePath(recordBuffer)
691-
	print("What Z? (default: here)")
691+
					displayStuffs = true
692
					currentLocation = "renderMap"
693-
	newZ = tonumber(read())
693+
694-
	if newZ == nil then
694+
				recordBuffer = {}
695-
		newZ = math.floor(posZ)
695+
696
			return {coord_x, coord_y, coord_z}
697-
	setConfig(newName, "add", newX, newY, newZ)
697+
698
	end
699
end
700
701
function rollOver(input, max)
702
	return math.floor(input % max)
703
end
704
705
function drawMovingLine(ypos, size, speed, spacesize)
706
	for a = 1, size do
707
		if currentLocation == "waypointSettings" then
708
			term.setCursorPos(1,ypos)
709
			if colormode then
710
				term.setTextColor(colors.orange)
711
			else
712
				if grayAllowed then
713
					term.setTextColor(colors.lightGray)
714
				else
715
					if isConnected then
716
						term.setTextColor(colors.white)
717
					else
718
						term.setTextColor(colors.black)
719
					end
720
				end
721
			end
722
			for x = 1, scr_x do
723
				if rollOver(x - a, size) < spacesize then
724
					write(" ")
725
				else
726
					write("-")
727
				end
728
			end
729
			sleep(speed)
730
		end
731
	end
732
end
733
734
function flashScreen(times)
735
	if (not times) or (type(times) ~= "number") then
736
		times = 1
737
	end
738
	if colormode or grayAllowed then
739
		flashes = {
740
			colors.black,
741
			colors.gray,
742
			colors.lightGray,
743
			colors.white,
744
			colors.lightGray,
745
			colors.black,
746
		}
747
	else
748
		flashes = {
749
			colors.black,
750
			colors.white,
751
		}
752
	end
753
	if doFlash then
754-
function keyPress()
754+
		for a = 1, times do
755
			for b = 1, #flashes do
756
				term.setBackgroundColor(flashes[b])
757
				term.clear()
758-
		key = tostring(keys.getName(key))
758+
				sleep(0)
759-
		displayStuffs = false
759+
760-
		if key == "c" then
760+
761-
			displayStuffs = false
761+
762
	flashes = nil
763
	setDefaultColors()
764
end
765-
			setWaypoint()
765+
766
--The badly whitespaced function were made by PhyscoKillerMonkey. Beta.
767
local function forward()
768-
			displayStuffs = true
768+
 while not mapturt.forward() do
769
 --print("Can't move, checking fuel")
770
  if turtle.getFuelLevel() == 0 then
771
   turtle.select(1)
772
   turtle.refuel(1)
773-
		if key == "l" then
773+
  end
774-
			if labelMode == true then
774+
  if digBlocks then
775-
				labelMode = false
775+
   turtle.dig()
776-
			elseif labelMode == false then
776+
  else
777-
				labelMode = true
777+
   mapturt.up()
778
   goneUp = goneUp + 1
779
   cy = cy + 1
780
  end
781
 end
782
 if dir == 0 then cz = cz + 1
783-
		if key == "s" then
783+
 elseif dir == 1 then cx = cx - 1
784-
			displayStuffs = false
784+
 elseif dir == 2 then cz = cz - 1
785
 elseif dir == 3 then cx = cx + 1 end
786
 while goneUp > 0 and not turtle.detectDown() do
787
  mapturt.down()
788-
			setScale()
788+
  goneUp = goneUp - 1
789
  cy = cy - 1
790
 end
791-
			displayStuffs = true
791+
792
local function up()
793
 while not mapturt.up() do
794
 --print("Can't move, checking fuel")
795
  if turtle.getFuelLevel() == 0 then
796-
		if key == "d" then
796+
   turtle.select(1)
797-
			displayStuffs = false
797+
   turtle.refuel(1)
798
  end
799
  if digBlocks then
800
   turtle.digUp()
801-
			deleteWaypoint()
801+
  end
802
 end
803
 cy = cy + 1
804-
			displayStuffs = true
804+
805
local function down()
806
 while not mapturt.down() do
807
 --print("Can't move, checking fuel")
808
  if turtle.getFuelLevel() == 0 then
809-
		if spoofMode then
809+
   turtle.select(1)
810
   turtle.refuel(1)
811-
				fakeX = fakeX - 1
811+
  end
812-
				sleep(0.07)
812+
  if digBlocks then
813
   turtle.digDown()
814
  end
815-
				fakeX = fakeX + 1
815+
 end
816-
				sleep(0.07)
816+
 cy = cy - 1
817
end
818
local function getPos()
819-
				fakeZ = fakeZ - 1
819+
 --print("Getting position")
820-
				sleep(0.07)
820+
 cx, cy, cz = gps.locate(5)
821
 --print(cx, cy, cz)
822
end
823-
				fakeZ = fakeZ + 1
823+
local function getDir()
824-
				sleep(0.07)
824+
 --print("Getting direction")
825
 getPos()
826
 ox, oy, oz = cx, cy, cz
827-
		if key == "h" then
827+
 forward()
828-
			displayStuffs = false
828+
 getPos()
829
 if oz > cz then dir = 0
830
 elseif oz < cz then dir = 2
831
 elseif ox < cx then dir = 1
832-
			displayHelp()
832+
 elseif ox > cx then dir = 3 end
833
 --print(dir)
834
 mapturt.back()
835-
			displayStuffs = true
835+
 getPos()
836
end
837
local function turn(d)
838
 --getDir()
839
 --print("Aligning")
840-
		if key == "o" then
840+
 --print(dir, d)
841-
			displayStuffs = false
841+
 while dir ~= d do
842-
			setDefaultBackgroundColor()
842+
  mapturt.turnRight()
843
  dir = dir + 1
844
  if dir == 4 then dir = 0 end
845-
			shell.run("edit " .. mapConfigFile)
845+
 end
846
end
847-
			displayStuffs = true
847+
local function moveX()
848
 --print("Moving X")
849
 --getPos()
850
 if gox > cx then
851
  turn(1)
852
  for x = 1, gox - cx do
853
   forward()
854
   cx = cx + 1
855-
		if key == "numPadAdd" or key == "add" then
855+
  end
856-
			scaleFactor = scaleFactor * 1.1
856+
 elseif gox < cx then
857-
			displayStuffs = true
857+
  turn(3)
858
  for x = 1, cx - gox do
859
   forward()
860
   cx = cx - 1
861-
		elseif key == "minus" or key == "numPadSubtract" then
861+
  end
862-
			scaleFactor = scaleFactor / 1.1
862+
 end
863-
			displayStuffs = true
863+
864
local function moveZ()
865
 --print("Moving Z")
866
 --getPos()
867
 if goz > cz then
868
  turn(2)
869
  for z = 1, goz - cz do
870
   forward()
871
   cz = cz + 1
872
  end
873
 elseif goz < cz then
874
  turn(0)
875
  for z = 1, cz - goz do
876
   forward()
877-
fakeX = 3 --Used if spoofMode == true, if not then these are set in the event that it is later set true.
877+
   cz = cz - 1
878-
fakeY = 62
878+
  end
879-
fakeZ = 5
879+
 end
880
end
881
local function moveY()
882-
	write("Automatically updating Map...")
882+
 --print("Moving Y")
883
 --getPos()
884
 if goy > cy then
885
  for z = 1, goy - cy do
886
   up()
887-
parallel.waitForAny(renderMap, keyPress)
887+
   cy = cy + 1
888
  end
889
 elseif goy < cy then
890
  for z = 1, cy - goy do
891
   down()
892
   cy = cy - 1
893-
print("Thanks for using Map!")
893+
  end
894-
print("(code: G7SmdMKD)")
894+
 end
895
end
896
897
function clearMap()
898
	if displayStuffs then
899
		if not doGrid then
900
			setDefaultTextColor()
901
			if colormode then
902
				term.setBackgroundColor(mapColors[9])
903
			else
904
				term.setBackgroundColor(colors.black)
905
			end
906
			local mapLengthInner = (corner2[1]) - (corner1[1]) - 1
907
			local longBlankChar1 = string.rep(blankChar, mapLengthInner)
908
			for y = corner1[2] + 1, corner2[2] - 1 do
909
				term.setCursorPos(corner1[1]+1,y)
910
				if y == math.floor(midPoint[2]) then
911
					write(string.rep(blankChar, math.ceil(mapLengthInner/2)-1))
912
					term.setCursorPos(midPoint[1]+1,y)
913
					write(string.rep(blankChar, math.floor(mapLengthInner/2)))
914
				else
915
					write(longBlankChar1)
916
				end
917
			end
918
			setDefaultColors()
919
			for y = corner1[2], corner2[2] do
920
				term.setCursorPos(corner1[1]-1,y)
921
				write(" ") --I do " " because 'blankChar' is for the inside of the map.
922
			end
923
			for y = corner1[2], corner2[2] do
924
				term.setCursorPos(corner2[1]+1,y)
925
				write(" ") --Same here.
926
			end
927
			if isConnected then
928
				term.setCursorPos(1,corner1[2]-1)
929
				term.clearLine()
930
			end
931
		end
932
	end
933
	return
934
end
935
936
function drawBorder()
937
	defineMapBorders()
938
	if displayStuffs then
939
		if colormode then
940
			term.setTextColor(colors.lightGray)
941
			term.setBackgroundColor(mapColors[2])
942
		else
943
			if isConnected then
944
				term.setTextColor(colors.white)
945
				term.setBackgroundColor(colors.white)
946
			else
947
				if grayAllowed then
948
					term.setTextColor(colors.white)
949
					term.setBackgroundColor(colors.gray)
950
				else
951
					term.setTextColor(colors.white)
952
					term.setBackgroundColor(colors.black)
953
				end
954
			end
955
		end
956
		local mapLength = corner2[1] - corner1[1]
957
		local mapHeight = corner2[2] - corner1[2]
958
		local longMapChar = string.rep(" ", mapLength)
959
		local longMapCharHalf = string.rep(" ", math.floor(mapLength/2))
960
		term.setCursorPos(corner1[1],corner1[2])
961
		write(longMapCharHalf)
962
		term.setCursorPos(midPoint[1]+1,corner1[2])
963
		write(longMapCharHalf)
964
		term.setCursorPos(corner1[1],corner2[2])
965
		write(longMapChar)
966
		for b = corner1[2], corner2[2] do
967
			term.setCursorPos(corner1[1],b)
968
			if b ~= midPoint[2] then
969
				write(" ")
970
			else
971
				write("X")
972
			end
973
		end
974
		for b = corner1[2], corner2[2] do
975
			term.setCursorPos(corner2[1],b)
976
			write(" ")
977
		end
978
		
979
		term.setCursorPos(midPoint[1],corner1[2])
980
		write("Z")
981
--		term.setCursorPos(corner1[1],midPoint[2])
982
--		write("X")
983
		setDefaultColors()
984
	end
985
	return
986
end
987
988
function drawScaleIndicator()
989
	if displayStuffs then
990
		scaleX = corner1[1] + 1
991
		if not monitorMode then
992
			scaleY = corner2[2] + 1
993
		else
994
			scaleY = scr_y - 2
995
		end
996
		term.setCursorPos(scaleX,scaleY)
997
		setDefaultColors()
998
		term.clearLine()
999
		if isConnected then
1000
			term.setTextColor(colors.white)
1001
		else
1002
			if colormode then
1003
				term.setTextColor(colors.white)
1004
			else
1005
				if grayAllowed then
1006
					term.setTextColor(colors.gray)
1007
				else
1008
					term.setTextColor(colors.black)
1009
				end
1010
			end
1011
		end
1012
		write("Scale: ")
1013
		if colormode then
1014
			term.setTextColor(colors.orange)
1015
		else
1016
			if grayAllowed then
1017
				term.setTextColor(colors.lightGray)
1018
			else
1019
				if isConnected then
1020
					term.setTextColor(colors.white)
1021
				else
1022
					term.setTextColor(colors.black)
1023
				end
1024
			end
1025
		end
1026
		if not monitorMode then
1027
			write(string.sub(scaleFactor, 1, 12).. "x")
1028
		else
1029
			write(string.sub(scaleFactor, 1, 6) .. "x")
1030
		end
1031
	end
1032
end
1033
1034
local function printOutput(commie)
1035
	local oldCurX, oldCurY = term.getCursorPos()
1036
	if type(commie) == "table" then
1037
		for a = 1, #commie do
1038
			term.setCursorPos(2,scr_y-(#commie-a))
1039
			if colormode then
1040
				term.setTextColor(colors.gray)
1041
				term.setBackgroundColor(colors.lightGray)
1042
			else
1043
				term.setTextColor(colors.black)
1044
				term.setBackgroundColor(colors.white)
1045
			end
1046
			term.clearLine()
1047
			write(tostring(commie[a]))
1048
		end
1049
	else
1050
		setDefaultColors()
1051
		term.setCursorPos(1,scr_y-1)
1052
		term.clearLine()
1053
		term.setCursorPos(2,scr_y)
1054
		if colormode then
1055
			term.setTextColor(colors.gray)
1056
			term.setBackgroundColor(colors.lightGray)
1057
		else
1058
			term.setTextColor(colors.black)
1059
			term.setBackgroundColor(colors.white)
1060
		end
1061
		term.clearLine()
1062
		write(tostring(commie))
1063
		if turtle then
1064
			if type(turtle.getFuelLevel()) ~= "string" then
1065
				if turtle.getFuelLevel() < 1 then
1066
					write(" (out of fuel)")
1067
				else
1068
					write(" (fuel:" .. turtle.getFuelLevel() .. ")")
1069
				end
1070
			else
1071
				write(" (fuel:" .. turtle.getFuelLevel() .. ")")
1072
			end
1073
		end
1074
	end
1075
	term.setCursorPos(oldCurX,oldCurY)
1076
	setDefaultColors()
1077
	return commie
1078
end
1079
1080
function renderMap()
1081
	getCoordinates()
1082
	setDefaultColors()
1083
	term.clear()
1084
	drawBorder()
1085
	clearMap()
1086
	redrawMap = true
1087
	renderCommands()
1088
	changedDirection = false
1089
	if turtleMode then printOutput("turtleMode activated!") end
1090
	local poses
1091
	while true do
1092
		if displayStuffs then
1093
			wasConnected = true
1094
			repeat
1095
				poses = getCoordinates()
1096
				if not isConnected then
1097
					if displayStuffs then
1098
						if colormode then
1099
							term.setBackgroundColor(mapColors[8])
1100
						else
1101
							term.setBackgroundColor(colors.white)
1102
						end
1103
						term.clear()
1104
						drawBorder()
1105
						renderCommands()
1106
					end
1107
					repeat
1108
						poses = getCoordinates()
1109
						sleep(0)
1110
					until isConnected
1111
					if displayStuffs then
1112
						setDefaultColors()
1113
						term.clear()
1114
						renderCommands()
1115
						drawBorder()
1116
					end
1117
				end
1118
			until isConnected
1119
			if displayStuffs then
1120
				setDefaultColors()
1121
			end
1122
		end
1123
		oldCoord_x = posX
1124
		oldCoord_y = posY
1125
		oldCoord_z = posZ
1126
		posX = poses[1]
1127
		posY = poses[2]
1128
		posZ = poses[3]
1129
		if oldCoord_x ~= nil then
1130
			if math.abs(oldCoord_x - posX) > directionSensitivity or math.abs(oldCoord_z - posZ) > directionSensitivity and not (turtleMode and changedDirection and turtle) then
1131
				if math.abs(oldCoord_x - posX) > math.abs(oldCoord_z - posZ) and oldCoord_x - posX > 0 then
1132
					direction_long = "east"
1133
					direction = "east"
1134
					changedDirection = true
1135
				elseif math.abs(oldCoord_x - posX) > math.abs(oldCoord_z - posZ) and oldCoord_x - posX < 0 then
1136
					direction_long = "west"
1137
					direction = "west"
1138
					changedDirection = true
1139
				elseif math.abs(oldCoord_z - posZ) > math.abs(oldCoord_x - posX) and oldCoord_z - posZ > 0 then
1140
					direction_lat = "south"
1141
					direction = "south"
1142
					changedDirection = true
1143
				elseif math.abs(oldCoord_z - posZ) > math.abs(oldCoord_x - posX) and oldCoord_z - posZ < 0 then
1144
					direction_lat = "north"
1145
					direction = "north"
1146
					changedDirection = true
1147
				end
1148
			end
1149
		end
1150
		if displayStuffs then
1151
			setDefaultColors()
1152
			if ((oldCoord_x ~= posX or oldCoord_z ~= posZ) or hadCleared) and displayStuffs then
1153
				drawBorder()
1154
				clearMap()
1155
				hadCleared = false
1156
			end
1157
			if oldCoord_x ~= posX or oldCoord_z ~= posZ or oldCoord_y ~= posY or redrawMap == true then
1158
			redrawMap = false
1159
			for a = 1, #waypoints do
1160
				point = waypoints[a]
1161
				wayX = point[2]
1162
				wayY = point[3]
1163
				wayZ = point[4]
1164
				waypointColor = point[5]
1165
				waypointNewchar = point[6]
1166
				
1167
				oldItemX = itemX
1168
				oldItemZ = itemZ
1169
				
1170
				itemX = math.floor((midPoint[1] + (posX - math.floor(wayX)) * scaleFactor))
1171
				itemZ = math.floor((midPoint[2] + (posZ - math.floor(wayZ)) * scaleFactor))
1172
				term.setCursorPos(itemX,itemZ)
1173
				if itemX >= corner1[1] and itemX <= corner2[1] and itemZ <= corner2[2] and itemZ >= corner1[2] then
1174
					if not (itemX == math.floor(midPoint[1]) and itemZ == math.floor(midPoint[2])) then
1175
						if isConnected then
1176
							if ((itemZ == corner1[2] or itemZ == corner2[2]) or (itemX == corner1[1] or itemX == corner2[1])) and ((itemX >= corner1[1] and itemX <= corner2[1]) and (itemZ >= corner1[2] and itemZ <= corner2[2])) then
1177
								term.setCursorPos(itemX,itemZ)
1178
								if colormode then
1179
									if waypointColor then
1180
										term.setTextColor(waypointColor)
1181
									else
1182
										term.setTextColor(mapColors[3])
1183
									end
1184
									term.setBackgroundColor(mapColors[2])
1185
								else
1186
									if grayAllowed then
1187
										term.setTextColor(colors.gray)
1188
										term.setBackgroundColor(colors.white)
1189
									else
1190
										term.setTextColor(colors.black)
1191
										term.setBackgroundColor(colors.white)
1192
									end
1193
								end
1194
							else
1195
								if colormode then
1196
									if waypointColor then
1197
										term.setTextColor(waypointColor)
1198
									else
1199
										term.setTextColor(mapColors[3])
1200
									end
1201
									term.setBackgroundColor(mapColors[9])
1202
								else
1203
									term.setTextColor(colors.white)
1204
									term.setBackgroundColor(colors.black)
1205
								end
1206
							end
1207
							if not waypointNewchar then
1208
								write(waypointChar)
1209
							else
1210
								write(tostring(waypointNewchar))
1211
							end
1212
						else
1213
							if colormode then
1214
								term.setTextColor(mapColors[8])
1215
							else
1216
								term.setTextColor(colors.black)
1217
							end
1218
						end
1219
					end
1220
				else
1221
					if colormode then
1222
						if waypointColor then
1223
							term.setTextColor(waypointColor)
1224
						else
1225
							term.setTextColor(mapColors[4])
1226
						end
1227
						term.setBackgroundColor(mapColors[2])
1228
					else
1229
						term.setTextColor(colors.black)
1230
						term.setBackgroundColor(colors.white)
1231
					end
1232
					if itemX <= corner1[1] and itemZ <= corner2[2] and itemZ >= corner1[2] then
1233
						term.setCursorPos(corner1[1],itemZ)
1234
						write("<")
1235
					elseif itemX <= corner1[1] and itemZ <= corner1[2] then
1236
						term.setCursorPos(corner1[1],corner1[2])
1237
						if (itemX+corner1[1]) * -1 >= (itemZ+corner1[2]) * -1 then
1238
							write("<")
1239
						else
1240
							write("^")
1241
						end
1242
					elseif itemX <= corner1[1] and itemZ >= corner2[2] then
1243
						term.setCursorPos(corner1[1],corner2[2])
1244
						if (itemX+corner1[1]) * -1 >= (itemZ-corner2[2]) then
1245
							write("<")
1246
						else
1247
							write("v")
1248
						end
1249
					elseif itemX >= corner2[1] and itemZ <= corner2[2] and itemZ >= corner1[2] then
1250
						term.setCursorPos(corner2[1],itemZ)
1251
						write(">")
1252
					elseif itemX >= corner2[1] and itemZ <= corner1[2] then
1253
						term.setCursorPos(corner2[1],corner1[2])
1254
						if (itemX-corner1[1]) >= (itemZ+corner1[2]) * -1 then
1255
							write(">")
1256
						else
1257
							write("^")
1258
						end
1259
					elseif itemX >= corner2[1] and itemZ >= corner2[2] then
1260
						term.setCursorPos(corner2[1],corner2[2])
1261
						if (itemX-corner2[1]) >= (itemZ-corner2[2]) then
1262
							write(">")
1263
						else
1264
							write("v")
1265
						end
1266
					elseif itemX >= corner1[1] and itemX <= corner2[1] and itemZ <= corner1[2] then
1267
						term.setCursorPos(itemX,corner1[2])
1268
						write("^")
1269
					elseif itemX >= corner1[1] and itemX <= corner2[1] and itemZ >= corner2[2] then
1270
						term.setCursorPos(itemX,corner2[2])
1271
						write("v")
1272
					end
1273
					
1274
					if colormode then
1275
						term.setTextColor(mapColors[3])
1276
					else
1277
						term.setTextColor(colors.white)
1278
						term.setBackgroundColor(colors.black)
1279
					end
1280
				end
1281
				setDefaultColors()
1282
				if itemZ < corner2[2] + 2 then
1283
					if labelMode == true then
1284
						pointName = point[1]
1285
						pointMidX = math.ceil(itemX - (#pointName / 2))
1286
						pointMidZ = itemZ - 1
1287
						term.setCursorPos(pointMidX,pointMidZ)
1288
					elseif labelMode == false then
1289
						pointName = tostring(round(math.sqrt((point[2]-posX)^2 + (point[3]-posY)^2 + (point[4]-posZ)^2), 2))
1290
						pointMidX = itemX - math.floor(#pointName / 2)
1291
						pointMidZ = itemZ - 1
1292
						term.setCursorPos(pointMidX,pointMidZ)
1293
					end
1294
					if pointMidX + #pointName >= scr_x then
1295
						subLength = (scr_x - pointMidX) + 1
1296
						subName = string.sub(pointName, 1, subLength)
1297
						if pointMidX <= scr_x + 1 then
1298
							pointName = subName
1299
						end
1300
					end
1301
					if pointMidX <= scr_x then
1302
						for i = 1, #pointName do
1303
							labelPosX, labelPosY = term.getCursorPos()
1304
							term.setCursorPos(labelPosX,labelPosY)
1305
							if ((labelPosY == corner1[2] or labelPosY == corner2[2]) or (labelPosX == corner1[1] or labelPosX == corner2[1])) and ((labelPosX >= corner1[1] and labelPosX <= corner2[1]) and (labelPosY >= corner1[2] and labelPosY <= corner2[2])) then
1306
								if colormode then
1307
									term.setTextColor(mapColors[1])
1308
									term.setBackgroundColor(mapColors[2])
1309
								else
1310
									if grayAllowed then
1311
										term.setTextColor(colors.gray)
1312
										term.setBackgroundColor(colors.white)
1313
									else
1314
										term.setTextColor(colors.black)
1315
										term.setBackgroundColor(colors.white)
1316
									end
1317
								end
1318
							else
1319
								if colormode then
1320
									term.setBackgroundColor(mapColors[9])
1321
									if wayY >= posY then
1322
										term.setTextColor(mapColors[3])
1323
									else
1324
										term.setTextColor(colors.lightGray)
1325
									end
1326
								else
1327
									if grayAllowed then
1328
										term.setBackgroundColor(colors.black)							
1329
										if wayY >= posY then
1330
											term.setTextColor(colors.white)
1331
										else
1332
											term.setTextColor(colors.lightGray)
1333
										end
1334
									else
1335
										if wayY >= posY then
1336
											term.setTextColor(colors.white)
1337
											term.setBackgroundColor(colors.black)
1338
										else
1339
											term.setTextColor(colors.white)
1340
											term.setBackgroundColor(colors.black)
1341
										end
1342
									end
1343
								end
1344
							end
1345
							if (labelPosX == 1 or labelPosX == scr_x or labelPosY-1 % corner2[2] == 0) then
1346
								term.setBackgroundColor(mapColors[1])
1347
							end
1348
							write(string.sub(pointName, i, i))
1349
						end
1350
					end
1351
				end
1352
				setDefaultColors()
1353
			end
1354
			end --Do not remove this end.
1355
			term.setCursorPos(midPoint[1],midPoint[2])
1356
			if colormode then
1357
				if recording then
1358
					term.setTextColor(colors.white)
1359
				else
1360
					term.setTextColor(mapColors[5])
1361
				end
1362
				term.setBackgroundColor(mapColors[9])
1363
			else
1364
				if grayAllowed then
1365
					if recording then
1366
						term.setTextColor(colors.black)
1367
					else
1368
						term.setTextColor(colors.lightGray)
1369
					end
1370
					if isConnected then
1371
						term.setBackgroundColor(colors.black)
1372
					else
1373
						term.setBackgroundColor(colors.white)
1374
					end
1375
				else
1376
					if recording then
1377
						term.setTextColor(colors.black)
1378
					else
1379
						term.setTextColor(colors.white)
1380
					end
1381
					if isConnected then
1382
						term.setBackgroundColor(colors.black)
1383
					else
1384
						term.setBackgroundColor(colors.white)
1385
					end
1386
				end
1387
			end
1388
			if not turtleMode then
1389
				if direction == "east" then
1390
					playerChar = ">"
1391
				elseif direction == "west" then
1392
					playerChar = "<"
1393
				elseif direction == "south" then
1394
					playerChar = "v"
1395
				elseif direction == "north" then
1396
					playerChar = "^"
1397
				else
1398
					playerChar = "O"
1399
				end
1400
			else
1401
				if fakeDir == 0 then
1402
					playerChar = "^"
1403
				elseif fakeDir == 1 then
1404
					playerChar = ">"
1405
				elseif fakeDir == 2 then
1406
					playerChar = "v"
1407
				elseif fakeDir == 3 then
1408
					playerChar = "<"
1409
				else
1410
					playerChar = "O"
1411
				end
1412
			end
1413
			write(playerChar)
1414
		end
1415
		if not spoofMode then
1416
			sleep(refreshSleep)
1417
		else
1418
			sleep(0)
1419
		end
1420
	end
1421
end
1422
function renderCommands()
1423
	commands = {
1424
		"(L)abel/dist",
1425
		"Optio(n)s",
1426
		"E(x)it",
1427
	}
1428
	commandXYPoses = {} --Allows me to click on the commands with captureMouseInput()
1429
	scr_x, scr_y = term.getSize()
1430
	if not isConnected and not monitorMode then
1431
		term.setCursorPos(2,1)
1432
		if colormode then
1433
			term.setTextColor(colors.gray)
1434
		else
1435
			term.setTextColor(colors.black)
1436
		end
1437
		gpsNotFoundString = "GPS not found."
1438
		term.clearLine()
1439
		write(gpsNotFoundString)
1440
	end
1441
	startX = 2
1442
	if not monitorMode then
1443
		startY = corner2[2] + 1
1444
	else
1445
		startY = scr_y - 3
1446
	end
1447
	commandX = startX
1448
	commandY = startY + 1
1449
	if displayStuffs then
1450
		term.setCursorPos(commandX,commandY)
1451
		if colormode then
1452
			term.setTextColor(mapColors[6])
1453
			term.setBackgroundColor(mapColors[7])
1454
		else
1455
			term.setTextColor(colors.black)
1456
			if grayAllowed then
1457
				term.setBackgroundColor(colors.lightGray)
1458
			else
1459
				term.setBackgroundColor(colors.white)
1460
			end
1461
		end
1462
		term.clearLine()
1463
		for f = 1, #commands do
1464
			comPosX, comPosY = term.getCursorPos()
1465
			scr_x, scr_y = term.getSize()
1466
			if scr_x - comPosX <= string.len(commands[f]) + 1 then
1467
				term.setCursorPos(startX,comPosY+1)
1468
				term.clearLine()
1469
				comPosX, comPosY = term.getCursorPos()
1470
			end
1471
			write(commands[f])
1472
			table.insert(commandXYPoses, {comPosX, comPosY})
1473
			if not monitorMode then
1474
				if f ~= #commands then
1475
					write(", ")
1476
				end
1477
			else
1478
				if f < 2 then
1479
					write(", ")
1480
				end
1481
			end
1482
		end
1483
		drawScaleIndicator()
1484
	end
1485
	return
1486
end
1487
function displayHelp()
1488
	term.setCursorPos(1,2)
1489
	setDefaultColors()
1490
	if colormode then
1491
		term.setTextColor(colors.orange)
1492
	end
1493
	print("GPS Minimap program by EldidiStroyrr.")
1494
	setDefaultColors()
1495
	local helpItems = {
1496
		"'map cc' clears config.",
1497
		"'map cw' clears waypoints.",
1498
		"'map oc' opens config",
1499
		"Do 'map update <main/beta>' to update.",
1500
		"Do 'map help' for help. Duh.",
1501
		"Pressing numpad '+' or '-' will zoom by 0.1",
1502
	}
1503
	local starterX, starterY = term.getCursorPos()
1504
	local yOffset = 0
1505
	for a = 1, #helpItems do
1506
		term.setCursorPos(2,(a-1)+starterY+yOffset)
1507
		if colormode or grayAllowed then
1508
			term.setTextColor(colors.lightGray)
1509
		else
1510
			term.setTextColor(colors.white)
1511
		end
1512
		write("*")
1513
		setDefaultColors()
1514
		local curX1, curY1 = term.getCursorPos()
1515
		print(tostring(helpItems[a]))
1516
		local curX2, curY2 = term.getCursorPos()
1517
		yOffset = yOffset + ((curY2 - curY1) - 1)
1518
	end
1519
	sleep(0.1)
1520
	if colormode or grayAllowed then
1521
		term.setTextColor(colors.lightGray)
1522
	end
1523
	print("")
1524
	print("Press a key to continue.")
1525
	sleep(0)
1526
	local event, key = os.pullEvent("key")
1527
	return
1528
end
1529
function doesColorExist(color)
1530
	if type(color) == "string" then
1531
		local colors = set({"white","orange","magneta","lightBlue","yellow","lime","pink","gray","lightGray","cyan","purple","blue","brown","green","red","black"})
1532
		if string.sub(color, 1, 7) == "colors." then
1533
			if colors[string.sub(color, 8)] == true then
1534
				return true
1535
			else
1536
				return false
1537
			end
1538
		else
1539
			if colors[color] == true then
1540
				return true
1541
			else
1542
				return false
1543
			end
1544
		end
1545
	else
1546
		local colors = set({colors.white,colors.orange,colors.magneta,colors.lightBlue,colors.yellow,colors.lime,colors.pink,colors.gray,colors.lightGray,colors.cyan,colors.purple,colors.blue,colors.brown,colors.green,colors.red,colors.black})
1547
		if colors[color] == true then
1548
			return true
1549
		else
1550
			return false
1551
		end
1552
	end
1553
end
1554
function setWaypoint()
1555
	term.setCursorPos(1,2)
1556
	setDefaultColors()
1557
	defaultNewPointName = "way" --Not used, in favor of a way to cancel.
1558
	print("Set waypoint.")
1559
	print("Call it what?")
1560
	sleep(0)
1561
	write(">")
1562
	newName = tostring(read())
1563
	if newName == "" then
1564
		print("Cancelling.")
1565
		sleep(0.2)
1566
		return
1567
	end
1568
	print("What X? (default: current xyz)")
1569
	write(">")
1570
	newX = tonumber(read())
1571
	if newX == nil then
1572
		if isConnected then
1573
			newX = posX
1574
			newY = posY
1575
			newZ = posZ
1576
		else
1577
			print("Since you aren't connected to GPS, I can't set waypoints to where you are.")
1578
			yield()
1579
			os.pullEvent("key")
1580
			return
1581
		end
1582
	else
1583
		print("What Y? (default: here)")
1584
		write(">")
1585
		newY = tonumber(read())
1586
		if newY == nil then
1587
			newY = posY
1588
		end
1589
		print("What Z? (default: here)")
1590
		write(">")
1591
		newZ = tonumber(read())
1592
		if newZ == nil then
1593
			newZ = posZ
1594
		end
1595
	end
1596
	print("What color?")
1597
	write(">")
1598
	newColor = tostring(read())
1599
	if not doesColorExist(newColor) then
1600
		print("Not a color. Defaulting to 'yellow'")
1601
		sleep(0.2)
1602
		newColor = nil
1603
	else
1604
		newColor = stringToColor(newColor)
1605
	end
1606
	setConfig(newName, "add", newX, newY, newZ, newColor)
1607
	refreshOtherConfig()
1608
	print("Waypoint '" .. newName .. "' set!")
1609
	getConfig()
1610
	sleep(0.2)
1611
end
1612
function setScale()
1613
	term.setCursorPos(1,2)
1614
	setDefaultColors()
1615
	print("Set scale factor. Currently " .. scaleFactor .. ".")
1616
	repeat
1617
		yield()
1618
		newScale = nil
1619
		write(">")
1620
		newScaleRaw = read()
1621
		if tostring(newScaleRaw) == "" then
1622
			print("Cancelling.")
1623
			sleep(0.2)
1624
			return
1625
		end
1626
		newScale = tonumber(newScaleRaw)
1627
		if newScale == nil then
1628
			print("That's not a number!")
1629
		end
1630
	until type(newScale) == "number"
1631
	scaleFactor = newScale
1632
	print("Scale factor set to " .. scaleFactor .. ".")
1633
	refreshOtherConfig()
1634
	getConfig()
1635
	sleep(0.2)
1636
	return true
1637
end
1638
1639
function deleteWaypoint()
1640
	term.setCursorPos(1,2)
1641
	setDefaultColors()
1642
	print("Delete what waypoint?")
1643
	if colormode then
1644
		term.setTextColor(colors.orange)
1645
	end
1646
	for a = 1, #waypoints do
1647
		point = waypoints[a]
1648
		print(" -'" .. point[1] .. "'")
1649
	end
1650
	if colormode then
1651
		term.setTextColor(colors.white)
1652
	end
1653
	sleep(0)
1654
	write(">")
1655
	delName = tostring(read())
1656
	for a = 1, #waypoints do
1657
		point = waypoints[a]
1658
		if point[1] == delName then
1659
			setConfig(delName, "delete")
1660
			print("Deleted '" .. delName .. "'.")
1661
			refreshOtherConfig()
1662
			getConfig()
1663
			sleep(0.2)
1664
			return true
1665
		end
1666
	end
1667
	print("Invalid waypoint '" .. delName .. "'!")
1668
	sleep(0.2)
1669
	return false
1670
end
1671
function renameWaypoint()
1672
	term.setCursorPos(1,2)
1673
	setDefaultColors()
1674
	print("Rename which waypoint?")
1675
	if colormode then
1676
		term.setTextColor(colors.orange)
1677
	end
1678
	for a = 1, #fileWaypoints do
1679
		point = fileWaypoints[a]
1680
		print(" -'" .. point[1] .. "'")
1681
	end
1682
	if colormode then
1683
		term.setTextColor(colors.white)
1684
	end
1685
	write(">")
1686
	sleep(0)
1687
	local renName = tostring(read())
1688
	print("Rename to what?")
1689
	write(">")
1690
	renOutput = tostring(read())
1691
	for a = 1, #fileWaypoints do
1692
		local point = fileWaypoints[a]
1693
		if point[1] == renName then
1694
			setConfig(renName, "rename", renOutput)
1695
			print("Renamed '" .. renName .. "' to '" .. renOutput .. "'.")
1696
			refreshOtherConfig()
1697
			getConfig()
1698
			sleep(0.2)
1699
			return true
1700
		end
1701
	end
1702
	print("Invalid waypoint '" .. renName .. "'!")
1703
	sleep(0.2)
1704
	return false
1705
end
1706
function redrawSceen()
1707
	drawBorder()
1708
end
1709
function inspectWaypoint()
1710
	term.clear()
1711
	term.setCursorPos(1,2)
1712
	print("Inspect which waypoint?")
1713
	print("(get x,y,z,etc.):")
1714
	print(string.rep("-",scr_x))
1715
	if colormode then
1716
		term.setTextColor(colors.orange)
1717
	end
1718
	for a = 1, #waypoints do
1719
		point = waypoints[a]
1720
		print(" -'" .. point[1] .. "'")
1721
	end
1722
	if colormode then
1723
		term.setTextColor(colors.white)
1724
	end
1725
	sleep(0)
1726
	write(">")
1727
	local inspName = tostring(read())
1728
	for a = 1, #waypoints do
1729
		local point = waypoints[a]
1730
		if point[1] == inspName then
1731
			term.clear()
1732
			term.setCursorPos(1,2)
1733
			print("Info of '"..inspName.."':")
1734
			print(string.rep("-",scr_x))
1735
			print("X = "..point[2].." (you = "..posX..")")
1736
			print("Y = "..point[3].." (you = "..posY..")")
1737
			print("Z = "..point[4].." (you = "..posZ..")")
1738
			print("Distance = "..math.sqrt((point[2]-posX)^2+(point[3]-posY)^2+(point[4]-posZ)^2))
1739
			if type(point[7]) == "number" and point[7] ~= -1 then
1740
				write("Type = ")
1741
				if point[7] == 1 then
1742
					print("Pocket")
1743
				elseif point[7] == 2 then
1744
					print("Turtle")
1745
				elseif point[7] == 3 then
1746
					print("PC")
1747
				end
1748
				write("\n")
1749
			end
1750
			if point[3] < posY then
1751
				print("It is below you.")
1752
			elseif point[3] > posY then
1753
				print("It is above you.")
1754
			else
1755
				print("Your altitudes are equal.")
1756
			end
1757
			sleep(0.1)
1758
			os.pullEvent("key")
1759
			return true
1760
		end
1761
	end
1762
	print("No such waypoint! Cancelling.")
1763
	sleep(0.3)
1764
	return false
1765
end
1766
local function displayTurtleControls()
1767
	term.setCursorPos(1,2)
1768
	print("Turtle Control Scheme:")
1769
	for a = 1, scr_x do write("-") end
1770
	print("")
1771
	print(" Q W E  U I O P <up")
1772
	print(" A S D  J K L ; <front")
1773
	print(" TAB    M , . / <down")
1774
	print("")
1775
	print(" Q = down, E = up")
1776
	print(" WASD = move")
1777
	print(" U J M = hit   7 8 9 red")
1778
	print(" I K , = place 4 5 6 stone")
1779
	print(" O L . = dig   1 2 3 ctrl")
1780
	print(" P ; / = inspect")
1781
	write(" TAB = refuel")
1782
	sleep(0.1)
1783
	os.pullEvent("key")
1784
	return
1785
end
1786
function choice(input)
1787
	repeat
1788
		event, key = os.pullEvent("key")
1789
		if type(key) == "number" then key = keys.getName(key) end
1790
		if key == nil then key = " " end
1791
	until string.find(input, key)
1792
	return key
1793
end
1794
function waypointSettings()
1795
	displayStuffs = false
1796
	setDefaultColors()
1797
	sleep(0)
1798
	term.setCursorPos(1,2)
1799
	print(" Map Options:")
1800
	term.setCursorPos(1,4)
1801
	if colormode then
1802
		term.setTextColor(colors.orange)
1803
	end
1804
	print(" * (C)reate Waypoint")
1805
	print(" * (D)elete Waypoint")
1806
	print(" * (R)ename Waypoint")
1807
	print(" * Edit C(o)nfig")
1808
	print(" * (S)et Scale")
1809
	print(" * Show (H)elp")
1810
	if turtleMode then print(" * Show (t)urtle controls") end
1811
	if turtleMode then print(" * Send turtle to (p)oint") end
1812
	print(" * (I)nspect waypoint")
1813
	write(" * E(x)it")
1814
	if turtleMode then
1815
		key = choice("cdroshtpix")
1816
	else
1817
		key = choice("cdroshix")
1818
	end
1819
	if key == "d" then
1820
		currentLocation = "deleteWaypoint"
1821
		setDefaultColors()		displayStuffs = false
1822
		term.clear()
1823
		sleep(0)
1824
		deleteWaypoint()
1825
		term.clear()
1826
		currentLocation = "renderMap"
1827
		sleep(0)
1828
		flashScreen(1)
1829
		displayStuffs = true
1830
		redrawSceen()
1831
		return
1832
	end
1833
	if key == "r" then
1834
		currentLocation = "renameWaypoint"
1835
		setDefaultColors()
1836
		term.clear()
1837
		sleep(0)
1838
		renameWaypoint()
1839
		term.clear()
1840
		currentLocation = "renderMap"
1841
		sleep(0)
1842
		flashScreen(1)
1843
		displayStuffs = true
1844
		redrawSceen()
1845
		return
1846
	end
1847
	if key == "s" then
1848
		currentLocation = "setScale"
1849
		setDefaultColors()
1850
		term.clear()
1851
		sleep(0)
1852
		setScale()
1853
		term.clear()
1854
		currentLocation = "renderMap"
1855
		sleep(0)
1856
		flashScreen(1)
1857
		displayStuffs = true
1858
		redrawSceen()
1859
		drawScaleIndicator()
1860
		return
1861
	end
1862
	if key == "o" then
1863
		currentLocation = "editConfig"
1864
		setDefaultBackgroundColor()
1865
		term.clear()
1866
		sleep(0.1)
1867
		shell.run("edit " .. mapConfigFile)
1868
		currentLocation = "renderMap"
1869
		sleep(0)
1870
		flashScreen(1)
1871
		displayStuffs = true
1872
		getConfig()
1873
		setDefaultColors()
1874
		term.clear()
1875
		redrawSceen()
1876
		return
1877
	end
1878
	if key == "c" then
1879
		currentLocation = "setWaypoint"
1880
		setDefaultColors()
1881
		term.clear()
1882
		sleep(0)
1883
		setWaypoint()
1884
		term.clear()
1885
		currentLocation = "renderMap"
1886
		sleep(0)
1887
		flashScreen(1)
1888
		displayStuffs = true
1889
		redrawSceen()
1890
	end
1891
	if key == "h" then
1892
		currentLocation = "displayHelp"
1893
		setDefaultColors()
1894
		term.clear()
1895
		sleep(0)
1896
		displayHelp()
1897
		term.clear()
1898
		currentLocation = "renderMap"
1899
		sleep(0)
1900
		flashScreen(1)
1901
		displayStuffs = true
1902
		clearMap()
1903
		drawBorder()
1904
		renderCommands()
1905
	end
1906
	if key == "i" then
1907
		currentLocation = "inspectWaypoint"
1908
		setDefaultColors()
1909
		term.clear()
1910
		sleep(0)
1911
		inspectWaypoint()
1912
		term.clear()
1913
		currentLocation = "renderMap"
1914
		sleep(0)
1915
		flashScreen(1)
1916
		displayStuffs = true
1917
		clearMap()
1918
		drawBorder()
1919
		renderCommands()
1920
	end
1921
	if key == "t" and turtleMode then
1922
		currentLocation = "displayTurtleControls"
1923
		setDefaultColors()
1924
		term.clear()
1925
		sleep(0)
1926
		displayTurtleControls()
1927
		term.clear()
1928
		currentLocation = "renderMap"
1929
		sleep(0)
1930
		flashScreen(1)
1931
		displayStuffs = true
1932
		clearMap()
1933
		drawBorder()
1934
		renderCommands()
1935
	end
1936
	if key == "p" and turtleMode then
1937
		currentLocation = "turtleToPoint"
1938
		setDefaultColors()
1939
		term.clear()
1940
		term.setCursorPos(1,2)
1941
		if isConnected then
1942
			print("Go to coordinates or waypoint?")
1943
			print("[c/w/X]")
1944
			repeat
1945
				sleep(0)
1946
				event, key = os.pullEvent("key")
1947
				if type(key) == "number" then key = keys.getName(key) end
1948
				if key == nil then key = " " end
1949
			until string.find("cwx", key)
1950
			print("")
1951
			local destinationX, destinationY, destinationZ
1952
			if key == "c" then
1953
				print("Enter destination...")
1954
				print("...X:")
1955
				sleep(0)
1956
				destinationX = tonumber(read())
1957
				if destinationX == nil then
1958
					print("Not a number! Cancelling.")
1959
					sleep(0.2)
1960
					flashScreen(1)
1961
					return
1962
				end
1963
				print("...Y:")
1964
				sleep(0)
1965
				destinationY = tonumber(read())
1966
				if destinationY == nil then
1967
					print("Not a number! Cancelling.")
1968
					sleep(0.2)
1969
					flashScreen(1)
1970
					return
1971
				end
1972
				print("...Z:")
1973
				sleep(0)
1974
				destinationZ = tonumber(read())
1975
				if destinationZ == nil then
1976
					print("Not a number! Cancelling.")
1977
					sleep(0.2)
1978
					flashScreen(1)
1979
					return
1980
				end
1981
				term.clear()
1982
				term.setCursorPos(1,2)
1983
				write("Going...")
1984
				local result, bool = printOutput(goToCoordinates(destinationX, destinationY, destinationZ))
1985
				if not bool == false then
1986
					print("done!")
1987
					sleep(0.2)
1988
				else
1989
					sleep(0.1)
1990
					print("Press a key to continue")
1991
					os.pullEvent("key")
1992
				end
1993
			elseif key == "w" then
1994
				print("Which waypoint?")
1995
				if colormode then
1996
					term.setTextColor(colors.orange)
1997
				end
1998
				for a = 1, #waypoints do
1999
					point = waypoints[a]
2000
					print(" -'" .. point[1] .. "'")
2001
				end
2002
				if colormode then
2003
					term.setTextColor(colors.white)
2004
				end
2005
				sleep(0)
2006
				local destWaypoint = tostring(read())
2007
				if destWaypoint == "" then
2008
					print("Cancelling.")
2009
					sleep(0.1)
2010
					flashScreen(1)
2011
					return
2012
				end
2013
				write("Going...")
2014
				printOutput(goToCoordinates(tostring(destWaypoint)))
2015
				print("finished.")
2016
				sleep(0.2)
2017
			end
2018
		else
2019
			print("You are not connected to a GPS server, so you cannot send turtles.")
2020
			print("Press a key to continue")
2021
			sleep(0)
2022
			os.pullEvent("key")
2023
		end
2024
		currentLocation = "renderMap"
2025
		flashScreen(1)
2026
		term.clear()
2027
		sleep(0)
2028
		displayStuffs = true
2029
		clearMap()
2030
		drawBorder()
2031
		renderCommands()
2032
		redrawMap = true
2033
	end
2034
	if key == "x" then
2035
		currentLocation = "renderMap"
2036
		sleep(0)
2037
		flashScreen(1)
2038
		return
2039
	end
2040
	currentLocation = "renderMap"
2041
	return
2042
end
2043
function refuelTurtle(amount)
2044
	local originalSlot = turtle.getSelectedSlot()
2045
	for a = 1, 16 do
2046
		turtle.select(a)
2047
		if turtle.refuel(0) then
2048
			turtle.refuel(amount)
2049
			turtle.select(originalSlot)
2050
			return "refuelled " .. amount
2051
		end
2052
	end
2053
	turtle.select(originalSlot)
2054
	return "can't refuel " .. amount
2055
end
2056
function goToCoordinates(destX, destY, destZ)
2057
	if not turtleMode then
2058
		return "turtleMode is not true"
2059
	end
2060
	if destY == nil then
2061
		local pointName = destX
2062
		for a = 1, #waypoints do
2063
			point = waypoints[a]
2064
			if point[1] == pointName then
2065
				destX = tonumber(point[2])
2066
				destY = tonumber(point[3])
2067
				destZ = tonumber(point[4])
2068
			end
2069
		end
2070
		if destY == nil then
2071
			return "no such waypoint"
2072
		end
2073
		if turtle then
2074
			if type(turtle.getFuelLevel()) == "number" then
2075
				if math.abs(destX-posX)+math.abs(destY-posY)+math.abs(destZ-posZ) > turtle.getFuelLevel() then
2076
					return "insufficient fuel", false
2077
				end
2078
			end
2079
			printOutput("going to waypoint '" .. pointName .. "'")
2080
		end
2081
	else
2082
		if turtle then
2083
			if type(turtle.getFuelLevel()) == "number" then
2084
				if math.abs(destX-posX)+math.abs(destY-posY)+math.abs(destZ-posZ) > turtle.getFuelLevel() then
2085
					return "insufficient fuel", false
2086
				end
2087
			end
2088
			printOutput("going to " .. destX .. "," .. destY .. "," .. destZ .. "...")
2089
		end
2090
	end
2091
	--Credit to PhyscoKillerMonkey for the goto script.
2092
	gox = tonumber(destX)
2093
	goy = tonumber(destY)
2094
	goz = tonumber(destZ)
2095
	digBlocks = true
2096
	goneUp = 0 --dir and goneUp are used to keep track of position
2097
	dir = 0
2098
	getPos()
2099
	getDir()
2100
	if goy > cy then
2101
		moveY()
2102
		moveX()
2103
		moveZ()
2104
	else
2105
		moveX()
2106
		moveZ()
2107
		moveY()
2108
	end
2109
	--End of script by PhyscoKillerMonkey.
2110
	return "went to coordinates " .. destX .. "," .. destY .. "," .. destZ .. "."
2111
end
2112
local function turtleTurnLeft()
2113
	if direction == "north" then direction = "west"
2114
	elseif direction == "west" then direction = "south"
2115
	elseif direction == "south" then direction = "east"
2116
	elseif direction == "east" then direction = "north" end
2117
	printOutput(mapturt.turnLeft())
2118
end
2119
local function turtleTurnRight()
2120
	if direction == "north" then direction = "east"
2121
	elseif direction == "east" then direction = "south"
2122
	elseif direction == "south" then direction = "west"
2123
	elseif direction == "west" then direction = "north" end
2124
	printOutput(mapturt.turnRight())
2125
end
2126
local function textingPrompt()
2127
	local scr_x, scr_y = term.getSize()
2128
	term.setCursorPos(1,1)
2129
	write(">")
2130
	sleep(0)
2131
	local message = read()
2132
	if message == "" then
2133
		return false
2134
	else
2135
		local modem = peripheral.find("modem")
2136
		if not modem then
2137
			return false
2138
		end
2139
		local msg = {networkName,message}
2140
		for a = 1, #mapProtocol do
2141
			modem.transmit(mapProtocol[a],mapProtocol[a],msg)
2142
		end
2143
		return true
2144
	end
2145
end
2146
function keyPress() --Captures keypresses when normally viewing the map.
2147
	recording = false
2148
	displayStuffs = true
2149
	while true do
2150
		currentLocation = "renderMap"
2151
		local event, key = os.pullEvent("key")
2152
		if type(key) == "number" then key = tostring(keys.getName(key)) end
2153
		if spoofMode and not turtleMode then
2154
			if key == "left" then
2155
				fakeX = fakeX + spoofStep
2156
				refreshOtherConfig()
2157
				sleep(0)
2158
			end
2159
			if key == "right" then
2160
				fakeX = fakeX - spoofStep
2161
				refreshOtherConfig()
2162
				sleep(0)
2163
			end
2164
			if key == "down" then
2165
				fakeZ = fakeZ - spoofStep
2166
				refreshOtherConfig()
2167
				sleep(0)
2168
			end
2169
			if key == "up" then
2170
				fakeZ = fakeZ + spoofStep
2171
				refreshOtherConfig()
2172
				sleep(0)
2173
			end
2174
		end
2175
		if currentlyConnected or (currentlyConnected == false and isConnected == false) then
2176
			if key == "space" then
2177
				recording = not recording
2178
			end
2179
			if key == "l" then
2180
				if labelMode == true then
2181
					labelMode = false
2182
				elseif labelMode == false then
2183
					labelMode = true
2184
				end
2185
				refreshOtherConfig()
2186
				drawBorder()
2187
				clearMap()
2188
				redrawMap = true
2189
			end
2190
			if key == "t" then
2191
				currentLocation = "textingPrompt"
2192
				displayStuffs = false
2193
				setDefaultColors()
2194
				textingPrompt()
2195
				sleep(0)
2196
				displayStuffs = true
2197
				clearMap()
2198
				drawBorder()
2199
				renderCommands()
2200
				redrawMap = true
2201
			end
2202
			if key == "n" then
2203
				currentLocation = "waypointSettings"
2204
				displayStuffs = false
2205
				setDefaultColors()
2206
				term.clear()
2207
				sleep(0)
2208
				os.queueEvent("gpsRequest") --To make sure the line animation in the settings works.
2209
				waypointSettings()
2210
				currentLocation = "renderMap"
2211
				term.clear()
2212
				sleep(0)
2213
				displayStuffs = true
2214
				clearMap()
2215
				drawBorder()
2216
				renderCommands()
2217
				redrawMap = true
2218
				if turtleMode then printOutput("turtleMode activated!") end
2219
			end
2220
			if key == "numPadAdd" or key == "add" then
2221
				scaleFactor = scaleFactor + 0.1
2222
				refreshOtherConfig()
2223
				clearMap()
2224
				drawBorder()
2225
				drawScaleIndicator()
2226
				redrawMap = true
2227
			elseif (key == "minus" or key == "numPadSubtract") and scaleFactor > 0.1 then
2228
				scaleFactor = scaleFactor - 0.1
2229
				refreshOtherConfig()
2230
				clearMap()
2231
				drawBorder()
2232
				drawScaleIndicator()
2233
				redrawMap = true
2234
			end
2235
		
2236
			if turtleMode then --Used for turtle control, and is helpful with Lyqyd's NSH.
2237
				if turtle then
2238
					if key == "w" then printOutput(mapturt.forward()) end
2239
					if key == "s" then printOutput(mapturt.back()) end
2240
					if key == "a" then
2241
						if keyAgoesRight then
2242
							turtleTurnRight()
2243
						else
2244
							turtleTurnLeft()
2245
						end
2246
					end
2247
					if key == "d" then
2248
						if keyAgoesRight then
2249
							turtleTurnLeft()
2250
						else
2251
							turtleTurnRight()
2252
						end
2253
					end
2254
	
2255
					if key == "q" then printOutput(mapturt.down()) end
2256
					if key == "e" then printOutput(mapturt.up()) end
2257
					
2258
					if key == "i" then printOutput(turtle.placeUp()) end
2259
					if key == "k" then printOutput(turtle.place()) end
2260
					if key == "comma" then printOutput(turtle.placeDown()) end
2261
					
2262
					if key == "o" then printOutput(turtle.digUp()) end
2263
					if key == "l" then printOutput(turtle.dig()) end
2264
					if key == "period" then printOutput(turtle.digDown()) end
2265
					
2266
					if key == "p" then
2267
						bool, inspection = turtle.inspectUp()
2268
						inspection = {inspection["name"], inspection["metadata"]}
2269
						printOutput(inspection)
2270
					end
2271
					if key == "semiColon" then
2272
						bool, inspection = turtle.inspect()
2273
						inspection = {inspection["name"], inspection["metadata"]}
2274
						printOutput(inspection)
2275
					end
2276
					if key == "slash" then
2277
						bool, inspection = turtle.inspectDown()
2278
						inspection = {inspection["name"], inspection["metadata"]}
2279
						printOutput(inspection)
2280
					end
2281
					
2282
					if key == "u" then printOutput(turtle.attackUp()) end
2283
					if key == "j" then printOutput(turtle.attack()) end
2284
					if key == "m" then printOutput(turtle.attackDown()) end
2285
2286
					if key == "tab" then printOutput(refuelTurtle(1)) end
2287
					
2288
					if key == "numPad8" then
2289
						local rsSide = "front"
2290
						if redstone.getOutput(rsSide) == false then
2291
							redstone.setOutput(rsSide, true)
2292
							printOutput(rsSide .. " RS on")
2293
						else
2294
							redstone.setOutput(rsSide, false)
2295
							printOutput(rsSide .. " RS off")
2296
						end
2297
					end
2298
					if key == "numPad2" then
2299
						local rsSide = "back"
2300
						if redstone.getOutput(rsSide) == false then
2301
							redstone.setOutput(rsSide, true)
2302
							printOutput(rsSide .. " RS on")
2303
						else
2304
							redstone.setOutput(rsSide, false)
2305
							printOutput(rsSide .. " RS off")
2306
						end
2307
					end
2308
					if key == "numPad4" then
2309
						local rsSide = "left"
2310
						if redstone.getOutput(rsSide) == false then
2311
							redstone.setOutput(rsSide, true)
2312
							printOutput(rsSide .. " RS on")
2313
						else
2314
							redstone.setOutput(rsSide, false)
2315
							printOutput(rsSide .. " RS off")
2316
						end
2317
					end
2318
					if key == "numPad6" then
2319
						local rsSide = "right"
2320
						if redstone.getOutput(rsSide) == false then
2321
							redstone.setOutput(rsSide, true)
2322
							printOutput(rsSide .. " RS on")
2323
						else
2324
							redstone.setOutput(rsSide, false)
2325
							printOutput(rsSide .. " RS off")
2326
						end
2327
					end
2328
					if key == "numPad7" then
2329
						local rsSide = "top"
2330
						if redstone.getOutput(rsSide) == false then
2331
							redstone.setOutput(rsSide, true)
2332
							printOutput(rsSide .. " RS on")
2333
						else
2334
							redstone.setOutput(rsSide, false)
2335
							printOutput(rsSide .. " RS off")
2336
						end
2337
					end
2338
					if key == "numPad9" then
2339
						local rsSide = "bottom"
2340
						if redstone.getOutput(rsSide) == false then
2341
							redstone.setOutput(rsSide, true)
2342
							printOutput(rsSide .. " RS on")
2343
						else
2344
							redstone.setOutput(rsSide, false)
2345
							printOutput(rsSide .. " RS off")
2346
						end
2347
					end
2348
				else
2349
					printOutput("Not a turtle.")
2350
				end
2351
			end
2352
		end
2353
		if key == "x" then
2354
			yield()
2355
			return
2356
		end
2357
	end
2358
end
2359
function captureMouseInput()
2360
	while true do
2361
		event, param1, x, y = os.pullEvent()
2362
		if currentLocation == "renderMap" then --Very important.
2363
			if event == "mouse_scroll" and y == scaleY and (x >= scaleX and x <= (7+scaleX+#string.sub(scaleFactor, 1, 12))) then
2364
				if param1 == -1 then
2365
					scaleFactor = scaleFactor + 0.1
2366
				elseif param1 == 1 and scaleFactor > 0.1 then
2367
					scaleFactor = scaleFactor - 0.1
2368
				end
2369
				refreshOtherConfig()
2370
				clearMap()
2371
				drawBorder()
2372
				drawScaleIndicator()
2373
				redrawMap = true
2374
			elseif (event == "mouse_click" and param1 == 1) or (event == "monitor_touch") then
2375
				for a = 1, #commands do
2376
					if y == commandXYPoses[a][2] and (x >= commandXYPoses[a][1] and x <= (#commands[a]+commandXYPoses[a][1])) then
2377
						commandID = a
2378
						break
2379
					end
2380
				end
2381
				--I know the key event is supposed to return a number...
2382
				if commandID == 1 then os.queueEvent("key", "l") end
2383
				if commandID == 2 then os.queueEvent("key", "n") end
2384
				if commandID == 3 then os.queueEvent("key", "x") end
2385
				commandID = nil
2386
			end
2387
		elseif (currentLocation == "waypointSettings" and ((event == "mouse_click" and param1 == 1)) or (event == "monitor_touch")) then
2388
			if y == 4 then os.queueEvent("key", "c") end -- Create waypoint
2389
			if y == 5 then os.queueEvent("key", "d") end -- Delete waypoint
2390
			if y == 6 then os.queueEvent("key", "r") end -- Rename waypoint
2391
			if y == 7 then os.queueEvent("key", "o") end -- Edit config
2392
			if y == 8 then os.queueEvent("key", "s") end -- Set scale
2393
			if y == 9 then os.queueEvent("key", "h") end -- Show help
2394
			if turtleMode then
2395
				if y == 10 then os.queueEvent("key", "t") end -- Turtle controls
2396
				if y == 11 then os.queueEvent("key", "p") end -- Send turtle to point
2397
				if y == 12 then os.queueEvent("key", "i") end -- Inspect waypoint
2398
				if y == 13 then os.queueEvent("key", "x") end -- Exit
2399
			else
2400
				if y == 10 then os.queueEvent("key", "i") end -- Inspect waypoint
2401
				if y == 11 then os.queueEvent("key", "x") end -- Exit
2402
			end
2403
		end
2404
	end
2405
end
2406
function drawAnimations()
2407
	spinwheel = {"/","-","\\","|"}
2408
	while true do
2409
		if currentLocation == "waypointSettings" then
2410
			sleep(0.1)
2411
			repeat
2412
				term.setTextColor(colors.white)
2413
				drawMovingLine(3, 12, 0, 2)
2414
			until currentLocation ~= "waypointSettings"
2415
		end
2416
		if currentLocation == "renderMap" then
2417
			for a = 1, #spinwheel do
2418
				if currentLocation ~= "renderMap" then break end
2419
				event, status = os.pullEvent("gpsRequest")
2420
				if currentLocation == "renderMap" then
2421
					if colormode then
2422
						if turtleMode then term.setBackgroundColor(colors.lightGray) end
2423
						if status == true then
2424
							term.setTextColor(colors.green)
2425
						else
2426
							term.setTextColor(colors.orange)
2427
						end
2428
					else
2429
						if grayAllowed then
2430
							if turtleMode then term.setBackgroundColor(colors.lightGray) end
2431
							if status == true then
2432
								term.setTextColor(colors.lightGray)
2433
							else
2434
								term.setTextColor(colors.gray)
2435
							end
2436
						else
2437
							if status == true then
2438
								term.setTextColor(colors.black)
2439
							else
2440
								term.setTextColor(colors.white)
2441
							end
2442
						end
2443
					end
2444
					term.setCursorPos(scr_x,1)
2445
					setDefaultBackgroundColor()
2446
					write(spinwheel[a])
2447
				else
2448
					break
2449
				end
2450
			end
2451
		end
2452
		sleep(0)
2453
	end
2454
end
2455
function waitForResize()
2456
	while true do
2457
		scr_x, scr_y = term.getSize()
2458
		event = os.pullEvent()
2459
		if event == "monitor_resize" or event == "term_resize" and displayStuffs == true then
2460
			scr_x, scr_y = term.getSize()
2461
			if scr_x > 16 or scr_y > 10 then --Determines if Map is being ran on a single monitor block.
2462
				monitorMode = false
2463
			else
2464
				monitorMode = true
2465
			end
2466
			mon = peripheral.find("monitor")
2467
			if mon then
2468
				if monitorTextScale ~= 0.5 then
2469
					mon.setTextScale(0.5)
2470
				else
2471
					mon.setTextScale(1)
2472
				end
2473
				if not monitorMode then
2474
					mon.setTextScale(monitorTextScale)
2475
				else
2476
					mon.setTextScale(0.5)
2477
				end
2478
			end
2479
			setDefaultColors()
2480
			term.clear()
2481
			defineMapBorders()
2482
			drawBorder()
2483
			clearMap()
2484
			renderCommands()
2485
			redrawMap = true
2486
		end
2487
	end
2488
end
2489
function broadcastMapData()
2490
	local compType
2491
	if pocket then
2492
		compType = 1
2493
	elseif turtle then
2494
		compType = 2
2495
	else
2496
		compType = 3
2497
	end
2498
	while true do
2499
		if broadcastData then
2500
			local data = {
2501
				name = networkName,
2502
				x = posX,
2503
				y = posY,
2504
				z = posZ,
2505
				isFake = spoofMode,
2506
				comp = compType,
2507
				ver = mapVersion,
2508
				dirChar = playerChar,
2509
			}
2510
			local modem = peripheral.find("modem")
2511
			if modem then
2512
				for a = 1, #mapProtocol do
2513
					modem.open(mapProtocol[a])
2514
					modem.transmit(mapProtocol[a],mapProtocol[a],data)
2515
				end
2516
			end
2517
		end
2518
		sleep(0)
2519
	end
2520
end
2521
function _rawListenForMapData() --Thanks, Bomb Bloke!
2522
	otherWaypoints = {}
2523
	while true do
2524
		local scr_x, scr_y = term.getSize()
2525
		local modem = peripheral.find("modem")
2526
		if modem then
2527
			for a = 1, #mapProtocol do
2528
				modem.open(mapProtocol[a])
2529
			end
2530
		end
2531
		local event, side, sendChan, repChan, data, distance = os.pullEvent("modem_message")
2532
		if (type(data) == "table") then
2533
			if (type(data.x) == "number") and (type(data.y) == "number") and (type(data.z) == "number") and (type(data.name) == "string") and (type(data.dirChar) == "string") then
2534
				otherWaypoints[data.name] = {data.x,data.y,data.z,colors.red,data.dirChar}
2535
				if data.comp then
2536
					table.insert(otherWaypoints[data.name],data.comp)
2537
				else
2538
					table.insert(otherWaypoints[data.name],-1)
2539
				end
2540
			elseif #data == 2 then
2541
				if (type(data[1]) == "string") and (type(data[2]) == "string") then
2542
					finalMessage = string.sub("<"..data[1].."> "..data[2],1,(scr_x*2)-1)
2543
					printOutput(finalMessage)
2544
				end
2545
			end
2546
		end
2547
	end
2548
end
2549
function listenForMapData()
2550
	netWayPoints = {}
2551
	while true do
2552
		parallel.waitForAny(function() sleep(0.3) end, _rawListenForMapData)
2553
		local seppoint = seperateMethods(otherWaypoints)
2554
		local oldNetWayPoints = newWayPoints
2555
		netWayPoints = {}
2556
		for a = 1, #seppoint do
2557
			table.insert(netWayPoints,{seppoint[a][1],table.unpack(seppoint[a][2])})
2558
		end
2559
		local file = fs.open(mapNetworkWaypointsFile,"w")
2560
		file.write(textutils.serialize(netWayPoints))
2561
		file.close()
2562
		getConfig()
2563
		if (oldNetWayPoints ~= netWayPoints) and displayStuffs then
2564
			hadCleared = true
2565
			redrawMap = true
2566
		end
2567
	end
2568
end
2569
getConfig()
2570
local mon = peripheral.find("monitor")
2571
if mon then
2572
	if not monitorMode then
2573
		mon.setTextScale(monitorTextScale)
2574
	else
2575
		mon.setTextScale(0.5)
2576
	end
2577
end
2578
if spoofMode then --Used if spoofMode == true, if not then these are set in the event that it is later set true.
2579
	if not fakeDir then
2580
		print("Spoof mode is activated.")
2581
		print("Enter current X:")
2582
		repeat
2583
			fakeX = tonumber(read())
2584
		until fakeX
2585
		print("Enter current Y:")
2586
		repeat
2587
			fakeY = tonumber(read())
2588
		until fakeY
2589
		print("Enter current Z:")
2590
		repeat
2591
			fakeZ = tonumber(read())
2592
		until fakeZ
2593
		print("Enter direction ('f' in F3 mode):")
2594
		repeat
2595
			fakeDir = tonumber(read())
2596
		until fakeDir
2597
		refreshOtherConfig()
2598
	end
2599
else
2600
	fakeX = 0
2601
	fakeY = 66
2602
	fakeZ = 0
2603
	fakeDir = 0 --Look at variable 'f' in DEBUG mode in minecraft. (F3)
2604
end
2605
mapturt = { -- I redefine the turtle moving functions to simplify things.
2606
	["forward"] = function() turtle.forward() fakeX=fakeX-(math.sin(90*fakeDir)) fakeZ=fakeZ+(math.cos(90*fakeDir)) refreshOtherConfig() end,
2607
	["back"] = function() turtle.back() fakeX=fakeX+(math.sin(90*fakeDir)) fakeZ=fakeZ-(math.cos(90*fakeDir)) refreshOtherConfig() end,
2608
	["up"] = function() turtle.up() fakeY=fakeY+1 refreshOtherConfig() end,
2609
	["down"] = function() turtle.down() fakeY=fakeY-1 refreshOtherConfig() end,
2610
	["turnLeft"] = function() turtle.turnLeft() fakeDir=rollOver(fakeDir-1,4) refreshOtherConfig() end,
2611
	["turnRight"] = function() turtle.turnRight() fakeDir=rollOver(fakeDir+1,4) refreshOtherConfig() end,
2612
}
2613
--[[The following...huge...tables are the title screens for advanced, grayscale, and monochrome computers.
2614
In order to edit these, you need to somehow convert it back to the default paint format, then use oeed's Sketch--]]
2615
mapTitleScreen_adv = {{8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,},{8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,},{8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,},{8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,},{8,8,8,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,},{8,8,8,32768,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,32768,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,},{8,8,8,32768,16,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,16,32768,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,},{8,8,8,32768,16,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,16,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,8,8,8,8,8,8,8,8,8,8,8,8,8,8,},{8,8,8,32768,16,128,128,32768,1,1,32768,1,1,128,128,32768,1,1,128,32768,1,1,1,128,128,128,16,32768,256,256,256,256,256,256,256,256,32768,8,8,8,8,8,8,8,8,8,8,8,8,8,8,},{8,8,8,32768,16,128,32768,1,128,32768,1,128,32768,1,32768,1,128,32768,1,32768,1,128,32768,1,128,128,16,32768,32768,32768,32768,32768,32768,32768,32768,256,32768,8,8,8,8,8,8,8,8,8,8,8,8,8,8,},{8,8,8,32768,16,128,32768,1,128,32768,1,128,32768,1,32768,1,1,1,1,32768,1,1,1,1,128,128,16,32768,32768,32768,32768,32768,32768,32768,32768,256,32768,8,8,8,8,8,8,8,8,8,8,8,8,8,8,},{8,8,8,32768,16,128,32768,1,128,32768,1,128,32768,1,32768,1,128,32768,1,32768,1,128,128,128,128,128,16,32768,32768,1,1,1,32768,32768,32768,256,32768,8,8,8,8,8,8,8,8,8,8,8,8,8,8,},{8,8,8,32768,16,128,32768,1,128,128,128,128,32768,1,32768,1,128,32768,1,32768,1,128,128,128,128,128,16,32768,32768,1,32768,32768,1,32768,32768,256,32768,8,8,8,8,8,8,8,8,8,8,8,8,8,8,},{8,8,8,32768,16,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,16,32768,32768,1,1,1,1,32768,32768,256,32768,8,8,8,8,8,8,8,8,8,8,8,8,8,8,},{8,8,8,32768,16,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,16,32768,32768,1,32768,32768,32768,32768,32768,256,32768,8,8,8,8,8,8,8,8,8,8,8,8,8,8,},{8192,8192,8192,32768,16,256,256,256,256,128,256,256,256,128,128,128,256,256,128,128,128,256,256,256,256,256,16,32768,32768,1,32768,32768,32768,32768,32768,256,32768,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,},{32,32,32,32768,16,1,1,1,1,128,1,1,1,128,1,1,128,1,128,1,1,128,1,1,1,1,16,32768,32768,32768,32768,32768,32768,32768,32768,256,32768,32,32,32,32,32,32,32,32,32,32,32,32,32,32,},{32,32,32,32768,16,1,1,1,1,128,1,1,1,128,1,1,128,1,128,1,1,128,1,1,1,1,16,32768,32768,32768,32768,32768,32768,32768,32768,256,32768,32,32,32,32,32,32,32,32,32,32,32,32,32,32,},{32,32,32,32768,16,1,1,1,1,128,128,128,1,128,128,128,1,1,128,128,128,1,1,1,1,1,16,32768,1,1,1,1,1,1,32768,256,32768,32,32,32,32,32,32,32,32,32,32,32,32,32,32,},{32,32,32,32768,16,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,16,32768,1,1,1,1,1,1,32768,256,32768,32,32,32,32,32,32,1,1,1,1,1,1,1,1,},}
2616
mapTitleScreen_norm = {{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,},{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,},{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,},{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,},{1,1,1,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,},{1,1,1,32768,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,32768,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,},{1,1,1,32768,1,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,1,32768,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,},{1,1,1,32768,1,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,1,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,1,1,1,1,1,1,1,1,1,1,1,1,1,1,},{1,1,1,32768,1,32768,32768,32768,1,1,32768,1,1,32768,32768,32768,1,1,32768,32768,1,1,1,32768,32768,32768,1,32768,1,1,1,1,1,1,1,1,32768,1,1,1,1,1,1,1,1,1,1,1,1,1,1,},{1,1,1,32768,1,32768,32768,1,32768,32768,1,32768,32768,1,32768,1,32768,32768,1,32768,1,32768,32768,1,32768,32768,1,32768,32768,32768,32768,32768,32768,32768,32768,1,32768,1,1,1,1,1,1,1,1,1,1,1,1,1,1,},{1,1,1,32768,1,32768,32768,1,32768,32768,1,32768,32768,1,32768,1,1,1,1,32768,1,1,1,1,32768,32768,1,32768,32768,32768,32768,32768,32768,32768,32768,1,32768,1,1,1,1,1,1,1,1,1,1,1,1,1,1,},{1,1,1,32768,1,32768,32768,1,32768,32768,1,32768,32768,1,32768,1,32768,32768,1,32768,1,32768,32768,32768,32768,32768,1,32768,32768,1,1,1,32768,32768,32768,1,32768,1,1,1,1,1,1,1,1,1,1,1,1,1,1,},{1,1,1,32768,1,32768,32768,1,32768,32768,32768,32768,32768,1,32768,1,32768,32768,1,32768,1,32768,32768,32768,32768,32768,1,32768,32768,1,32768,32768,1,32768,32768,1,32768,1,1,1,1,1,1,1,1,1,1,1,1,1,1,},{1,1,1,32768,1,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,1,32768,32768,1,1,1,1,32768,32768,1,32768,1,1,1,1,1,1,1,1,1,1,1,1,1,1,},{1,1,1,32768,1,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,1,32768,32768,1,32768,32768,32768,32768,32768,1,32768,1,1,1,1,1,1,1,1,1,1,1,1,1,1,},{32768,32768,32768,32768,1,1,1,1,1,32768,1,1,1,32768,32768,32768,1,1,32768,32768,32768,1,1,1,1,1,1,32768,32768,1,32768,32768,32768,32768,32768,1,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,},{32768,32768,32768,32768,1,1,1,1,1,32768,1,1,1,32768,1,1,32768,1,32768,1,1,32768,1,1,1,1,1,32768,32768,32768,32768,32768,32768,32768,32768,1,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,},{32768,32768,32768,32768,1,1,1,1,1,32768,1,1,1,32768,1,1,32768,1,32768,1,1,32768,1,1,1,1,1,32768,32768,32768,32768,32768,32768,32768,32768,1,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,},{32768,32768,32768,32768,1,1,1,1,1,32768,32768,32768,1,32768,32768,32768,1,1,32768,32768,32768,1,1,1,1,1,1,32768,1,1,1,1,1,1,1,1,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,},{32768,32768,32768,32768,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,32768,1,1,1,1,1,1,1,1,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,},}
2617
mapTitleScreen_gray = {{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,},{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,},{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,},{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,},{1,1,1,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,},{1,1,1,32768,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,32768,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,},{1,1,1,32768,1,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,1,32768,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,},{1,1,1,32768,1,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,1,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,1,1,1,1,1,1,1,1,1,1,1,1,1,1,},{1,1,1,32768,1,128,128,32768,1,1,32768,1,1,128,128,32768,1,1,128,32768,1,1,1,128,128,128,1,32768,256,256,256,256,256,256,256,256,32768,1,1,1,1,1,1,1,1,1,1,1,1,1,1,},{1,1,1,32768,1,128,32768,1,128,32768,1,128,32768,1,32768,1,128,32768,1,32768,1,128,32768,1,128,128,1,32768,32768,32768,32768,32768,32768,32768,32768,256,32768,1,1,1,1,1,1,1,1,1,1,1,1,1,1,},{1,1,1,32768,1,128,32768,1,128,32768,1,128,32768,1,32768,1,1,1,1,32768,1,1,1,1,128,128,1,32768,32768,32768,32768,32768,32768,32768,32768,256,32768,1,1,1,1,1,1,1,1,1,1,1,1,1,1,},{1,1,1,32768,1,128,32768,1,128,32768,1,128,32768,1,32768,1,128,32768,1,32768,1,128,128,128,128,128,1,32768,32768,1,1,1,32768,32768,32768,256,32768,1,1,1,1,1,1,1,1,1,1,1,1,1,1,},{1,1,1,32768,1,128,32768,1,128,128,128,128,32768,1,32768,1,128,32768,1,32768,1,128,128,128,128,128,1,32768,32768,1,32768,32768,1,32768,32768,256,32768,1,1,1,1,1,1,1,1,1,1,1,1,1,1,},{1,1,1,32768,1,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,1,32768,32768,1,1,1,1,32768,32768,256,32768,1,1,1,1,1,1,1,1,1,1,1,1,1,1,},{1,1,1,32768,1,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,1,32768,32768,1,32768,32768,32768,32768,32768,256,32768,1,1,1,1,1,1,1,1,1,1,1,1,1,1,},{128,128,128,32768,1,256,256,256,256,128,256,256,256,128,128,128,256,256,128,128,128,256,256,256,256,256,1,32768,32768,1,32768,32768,32768,32768,32768,256,32768,128,128,128,128,128,128,128,128,128,128,128,128,128,128,},{256,256,256,32768,1,1,1,1,1,128,1,1,1,128,1,1,128,1,128,1,1,128,1,1,1,1,1,32768,32768,32768,32768,32768,32768,32768,32768,256,32768,256,256,256,256,256,256,256,256,256,256,256,256,256,256,},{256,256,256,32768,1,1,1,1,1,128,1,1,1,128,1,1,128,1,128,1,1,128,1,1,1,1,1,32768,32768,32768,32768,32768,32768,32768,32768,256,32768,256,256,256,256,256,256,256,256,256,256,256,256,256,256,},{256,256,256,32768,1,1,1,1,1,128,128,128,1,128,128,128,1,1,128,128,128,1,1,1,1,1,1,32768,1,1,1,1,1,1,1,256,32768,256,256,256,256,256,256,256,256,256,256,256,256,256,256,},{256,256,256,32768,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,32768,1,1,1,1,1,1,1,256,32768,256,256,256,256,256,256,256,256,256,256,1,1,1,1,},}
2618
defineMapBorders() --why do I have a function for this again...? For the screen resizing!
2619
if displayTitle then
2620
	displayTitleScreen() --New title screens for norm/adv/gray computers in 1.3.4!
2621
end
2622
if autoUpdate then
2623
	write("Automagically updating Map...") --Yes I know I misspelled that, that was on purpose.
2624
	updateMapProgram()
2625
	print("up to date!")
2626
end
2627
flashScreen(1)
2628
local parallelFunctions = { --Look, I wanted to simplify it...
2629
	renderMap,
2630
	keyPress,
2631
	captureMouseInput,
2632
	waitForResize,
2633
	drawAnimations,
2634
	listenForMapData,
2635
	broadcastMapData,
2636
}
2637
parallel.waitForAny(table.unpack(parallelFunctions))
2638
end --This end is to close the runMapProgramAlready() function, so don't remove it.
2639
function handleMapErrorMessage(errorMsg)
2640
	local errorMessage = errorMsg
2641
	local interjects = {
2642
		"Oh nose!",
2643
		"Golly gee!",
2644
		"Eh, shit.",
2645
		"Holy Spaghetti and Meatballs, Batman!",
2646
		"Holy Rusted Metal, Batman!",
2647
		"Jiminy!",
2648
		"Leaping leptons!",
2649
		"Cripes!",
2650
		"Khaaaaaaannnnn!!",
2651
		"GURU MEDITATION",
2652
		"It appears that",
2653
		"Exclamation!",
2654
		"Holy Hamburger, Batman!",
2655
		"Holy Priceless Collection of Etruscan Snoods, Batman!",
2656
		"Holy Uncanny Photographic Mental Processes, Batman!",
2657
		"Aw shucks!",
2658
		"Holy Contributing to the Delinquency of Minors, Batman!",
2659
		"Holy Remote Control Robot, Batman!",
2660
		"Holy Euphemism!",
2661
		"Holy Hardest Metal In The World, Batman!",
2662
		"Holy Astringent Plum-like Fruit, Batman!",
2663
		"Holy Greetings Cards, Batman!",
2664
		"Holy One Track Bat Computer Mind, Batman!",
2665
		"Sweet Zombie Jesus!",
2666
		"Holy Batshit, Robin!",
2667
		"Holy Mongolian Clusterfuck!",
2668
		"Holy jumping mother o'God in a side-car with chocolate jimmies and a lobster bib!",
2669
		"string.rep(\"NEIN \",1000)",
2670
		"Oh, how sad.",
2671
		"NYEH HEH HEH!!!!", --This error message fills you with DETERMINATION.
2672
		"One of us messed up.",
2673
		"Holy balls!",
2674
	}
2675
	interjection = interjects[math.random(1, #interjects)]
2676
	local message = {
2677
		interjection,
2678
		"Map v" .. mapVersion .. " has gotten",
2679
		"an error:",
2680
		"",
2681
		tostring(errorMessage),
2682
	}
2683
	if colormode then
2684
		term.setBackgroundColor(colors.red)
2685
	else
2686
		if grayAllowed then
2687
			term.setBackgroundColor(colors.gray)
2688
		else
2689
			term.setBackgroundColor(colors.white)
2690
		end
2691
	end
2692
	term.clear()
2693
	scr_x, scr_y = term.getSize()
2694
	term.setCursorPos(1,1)
2695
	for y = 1, 2 do
2696
		for x = 1, scr_x do
2697
			if x % 2 == 0 then
2698
				if colormode then
2699
					term.setBackgroundColor(colors.black)
2700
					term.setTextColor(colors.lightGray)
2701
				else
2702
					if grayAllowed then
2703
						term.setBackgroundColor(colors.black)
2704
						term.setTextColor(colors.lightGray)
2705
					else
2706
						term.setBackgroundColor(colors.black)
2707
						term.setTextColor(colors.white)
2708
					end
2709
				end
2710
				write("x")
2711
			else
2712
				if colormode then
2713
					term.setBackgroundColor(colors.white)
2714
					term.setTextColor(colors.orange)
2715
				else
2716
					if grayAllowed then
2717
						term.setBackgroundColor(colors.white)
2718
						term.setTextColor(colors.gray)
2719
					else
2720
						term.setBackgroundColor(colors.white)
2721
						term.setTextColor(colors.black)
2722
					end
2723
				end
2724
				write("X")
2725
			end
2726
		end
2727
		term.setCursorPos(1,scr_y)
2728
	end
2729
	midPoint = {
2730
		scr_x / 2,
2731
		scr_y / 2,
2732
	}
2733
	local yoffset = 0
2734
	for a = 1, #message do
2735
		term.setCursorPos(midPoint[1]-math.floor(#message[a]/2)+1,a+3+yoffset)
2736
		if a == 5 then
2737
			if colormode then
2738
				term.setBackgroundColor(colors.gray)
2739
				term.setTextColor(colors.white)
2740
			else
2741
				if grayAllowed then
2742
					term.setBackgroundColor(colors.black)
2743
					term.setTextColor(colors.white)
2744
				else
2745
					term.setBackgroundColor(colors.black)
2746
					term.setTextColor(colors.white)
2747
				end
2748
			end
2749
		else
2750
			if colormode then
2751
				term.setBackgroundColor(colors.red)
2752
				term.setTextColor(colors.white)
2753
			else
2754
				if grayAllowed then
2755
					term.setBackgroundColor(colors.lightGray)
2756
					term.setTextColor(colors.black)
2757
				else
2758
					term.setBackgroundColor(colors.white)
2759
					term.setTextColor(colors.black)
2760
				end
2761
			end
2762
		end
2763
		if #message[a] > scr_x then
2764
			for b = 1, math.ceil(#message[a]/scr_x) do
2765
				local curPosX, curPosY = term.getCursorPos()
2766
				local subString = string.sub(message[a],((b-1)*scr_x)+1,(b*scr_x))
2767
				if #subString < scr_x then
2768
					term.setCursorPos(midPoint[1]-math.ceil(#string.sub(message[a], scr_x)/2),a+2+yoffset)
2769
				else
2770
					term.setCursorPos(1,a+2+yoffset+(b-1))
2771
				end
2772
				print(subString)
2773
				if b ~= math.ceil(#message[a]/scr_x) then
2774
					yoffset = yoffset + 1
2775
				end
2776
			end
2777
		else
2778
			print(message[a])
2779
		end
2780
	end
2781
	if colormode then
2782
		term.setBackgroundColor(colors.yellow)
2783
		term.setTextColor(colors.black)
2784
	else
2785
		if grayAllowed then
2786
			term.setBackgroundColor(colors.lightGray)
2787
			term.setTextColor(colors.black)
2788
		else
2789
			term.setBackgroundColor(colors.white)
2790
			term.setTextColor(colors.black)
2791
		end
2792
	end
2793
	local msg = " E(x)it, or (R)estart? "
2794
	term.setCursorPos(math.ceil(midPoint[1]-(#msg/2)),scr_y-2)
2795
	print(msg)
2796
	local event, key
2797
	repeat
2798
		sleep(0.1) --To prevent premature keypresses.
2799
		event, key = os.pullEvent("char") --We don't need any key output other than letters.
2800
		key = string.lower(key) --In case shift+key returns a capital key.
2801
	until string.find("xr", key)
2802
	local message = nil
2803
	if key == "x" then
2804
		return false
2805
	elseif key == "r" then
2806
		return true
2807
	else
2808
		return false
2809
	end
2810
	error("How did you get here??")
2811
end
2812
if nothing then return end
2813
while true do
2814
	local status, error = pcall(runMapProgramAlready) --Finally, good error handling.
2815
	if status == false then
2816
		local outcome = handleMapErrorMessage(error)
2817
		if outcome == false then
2818
			break
2819
		end
2820
	else
2821
		break
2822
	end
2823
end
2824
term.setTextColor(colors.white)
2825
term.setBackgroundColor(colors.black)
2826
term.clear()
2827
term.setCursorPos(1,1)
2828
print("Thanks for using Map v" .. mapVersion .. "!")
2829
print("(code: " .. pastebinIDList[mapRelease] .. ")")
2830
if math.random(1,64)==64 then print("May you live in interesting times!") end
2831
sleep(0)