Module:Map

From RuneScape Classic Wiki
Jump to: navigation, search

Documentation for this module may be created at Module:Map/doc

local hc = require('Module:Paramtest').has_content

local p = {}

local zoomSizes = {
	{ 3, 8 },
	{ 2, 4 },
	{ 1, 2 },
	{ 0, 1 },
	{ -1, 1/2 },
	{ -2, 1/4 },
	{ -3, 1/8 }
}

function toJSON(j)
	local json_good, json = pcall(mw.text.jsonEncode, j)--, mw.text.JSON_PRETTY)
	if json_good then
		return json
	end
	return error('Error converting to JSON')
end

function createMapElement(elem, args, json)
	local mapelem = mw.html.create(elem)
	mapelem:attr(args):newline():wikitext(toJSON(json)):newline()
	return mapelem
end

function p.npcmap(frame)
	return p.generateNPCMap(frame:getParent().args)
end

function p.generateNPCMap(args)
	local x, y = -args.x, -args.y
	local opts = {
		x = x,
		y = y,
		width = args.width or 300,
		height = args.height or 300,
		mapID = args.mapID or 0,
		plane = args.plane or 0,
		zoom = args.zoom or 2,
		align = args.align or 'center'
	}
	if hc(args.caption) then
		opts.text = args.caption
	else
		opts.frameless = ''
	end
	local squareX = args.squareX or 20
	local squareY = args.squareY or 20
	squareX = args.r or math.floor(squareX / 2)
	squareY = args.r or math.floor(squareY / 2)
	local json = {
		type = 'FeatureCollection',
		features = {
			{
				type = 'Feature',
				properties = {['_']='_', mapID=opts.mapID, plane=opts.plane},
				geometry = {
					type = 'Polygon',
					coordinates = {
						{
							{ x-squareX, y-squareY },
							{ x-squareX, y+squareY },
							{ x+squareX, y+squareY },
							{ x+squareX, y-squareY }
						}
					}
				}
			}
		}
	}
	
	local map = createMapElement('mapframe', opts, json)
	
	if args.nopreprocess then
		return map
	end
	return mw.getCurrentFrame():preprocess(tostring(map))
end

function p.locationmap(frame)
	return p.generateLocationMap(frame:getParent().args)
end

function p.generateLocationMap(args)
	local x, y = -args.x, -args.y
	local opts = {
		x = x,
		y = y,
		width = args.width or 300,
		height = args.height or 300,
		mapID = args.mapID or 0,
		plane = args.plane or 0,
		zoom = args.zoom or 2,
		align = args.align or 'center'
	}
	if hc(args.caption) then
		opts.text = args.caption
	else
		opts.frameless = ''
	end
	
	local map = createMapElement('mapframe', opts, {})
	
	if args.nopreprocess then
		return map
	end
	return mw.getCurrentFrame():preprocess(tostring(map))
end

function p.itemspawnmap(frame)
	return p.generateSpawnMap(frame:getParent().args, 'item')
end

function p.npcspawnmap(frame)
	return p.generateSpawnMap(frame:getParent().args, 'npc')
end

function p.generateSpawnMap(args, mapType)
	local sep = args.sep or ','
	local name = args.item or args.name or mw.title.getCurrentTitle().text
	local opts = {
		text = '',
		width = args.width or 300,
		height = args.height or 300,
		zoom = args.zoom or 2,
		mapID = args.mapID or 0,
		plane = tonumber(args.plane) or 0,
		group = args.group or 'spawns'
	}
	local bounds = {
		x_min = 10000000,
		x_max = -10000000,
		y_min = 10000000,
		y_max = -10000000
	}
	local spawnDetails = {}
	local i = 1
	while (args[i]) do
		local v = mw.text.trim(args[i])
		local spawnElt = {}
		for u in mw.text.gsplit(v, sep) do
			local _u = mw.text.split(u, ':')
			if _u[2] then
				spawnElt[mw.text.trim(_u[1])] = mw.text.trim(_u[2])
			else
				if spawnElt.x then
					spawnElt.y = tonumber(_u[1])
				else
					spawnElt.x = tonumber(_u[1])
				end
			end
		end
		if spawnElt.x > bounds.x_max then
			bounds.x_max = spawnElt.x
		end
		if spawnElt.x < bounds.x_min then
			bounds.x_min = spawnElt.x
		end
		if spawnElt.y > bounds.y_max then
			bounds.y_max = spawnElt.y
		end
		if spawnElt.y < bounds.y_min then
			bounds.y_min = spawnElt.y
		end
		
		local properties = {
			providerID = 0,
			icon = 'greenPin',
			mapID=opts.mapID,
			plane=opts.plane
		}

		if mapType == 'item' then
			local desc = {
				"'''Item''': "..name,
				"'''Quantity''': ".. (spawnElt.qty or 1)
			}
			if spawnElt.respawn then
				table.insert(desc, "'''Respawn time''': "..spawnElt.respawn)
			end
			if spawnElt.notes then
				table.insert(desc, "'''Notes''': "..spawnElt.notes)
			end
			properties.description = table.concat(desc, '<br>')
		end

		table.insert(spawnDetails, {
			type = 'Feature',
			geometry = {
				type = 'Point',
				coordinates = {
					-spawnElt.x, -spawnElt.y, opts.plane
				}
			},
			properties = properties
		})
		i = i + 1
	end
		
	bounds.x_range = bounds.x_max - bounds.x_min
	bounds.y_range = bounds.y_max - bounds.y_min
	
	opts.x = -math.floor(bounds.x_min + bounds.x_range/2)
	opts.y = -math.floor(bounds.y_min + bounds.y_range/2)
	local zoom = -3
	for i,v in ipairs(zoomSizes) do
		local sqs = 800/v[2]
		if sqs > bounds.x_range and sqs > bounds.y_range then
			zoom = v[1]
			break
		end
	end
	opts.zoom = zoom
	
	if tonumber(args.x) then
		opts.x = -args.x
	end
	if tonumber(args.y) then
		opts.y = -args.y
	end
	if tonumber(args.zoom) then
		opts.zoom = args.zoom
	end
	
	local json = {
		type = 'FeatureCollection',
		features = spawnDetails
	}

	local tagType = 'maplink'
	if args.mapframe then
		tagType = 'mapframe'
	end

	local map = createMapElement(tagType, opts, json)
	
	if args.nopreprocess then
		return map
	end
	return '<span class="rsw-maplink-spawns">'..mw.getCurrentFrame():preprocess(tostring(map))..'</span> ' .. (args.text or '')
end

return p