Module:Sprite

From Official Gamemode 4 Wiki
Jump to navigation Jump to search
-- Based on work by the MC wiki: https://minecraft.gamepedia.com/ and https://minecraft.gamepedia.com/Module:Sprite

local Sprite = {}

local aliasData = {
	vanillaAliases = [[Module:InventorySlot/Aliases]],
	gm4Aliases = [[Module:Gm4Sprite/Aliases]],
	effectAliases = [[Module:EffectSprite/Aliases]],
	trophyAliases = [[Module:TrophySprite/Aliases]]
}	

Sprite.aliasData = aliasData
local vanillaAliases = mw.loadData( aliasData.vanillaAliases )
local gm4Aliases = mw.loadData( aliasData.gm4Aliases )
local effectAliases = mw.loadData( aliasData.effectAliases )
local trophyAliases = mw.loadData( aliasData.trophyAliases )
local aliases

local types = {
	inventory = [[Module:InvSprite]],
	gm4 = [[Module:Gm4Sprite]],
	effect = [[Module:EffectSprite]],
	trophy = [[Module:TrophySprite]],
	gm4RP = [[Module:Gm4RPSprite]]
}

local defaultSettings = {
	scale = 1,
	sheetsize = 256,
	size = 16,
	pos = 1,
	align = 'text-top'
}

function getImage( image )
	if not(image) then return nil end
	local file = mw.title.new(image,"File").file
	if not(file.exists) then return nil end


	local f = mw.getCurrentFrame()
	local t = {
		url = f:expandTemplate{
			title = 'FileUrl',
			args = {image}
		}
	}

	setmetatable(t, {__index = file})

	return t
end

function getSpriteSheet( image )
	if not(image) then return nil end


	local f = mw.getCurrentFrame()
	local t = {
		url = f:expandTemplate{
			title = 'SpriteSheet',
			args = {image}
		}
	}
	if t == "" then return nil end

	return t
end

function Sprite:new (type)
	local source = types[type]
	if not(source) then
		error("Unknown type: " .. tostring(type))
	end

	o = {
			__source = require(source),
		}
	setmetatable(o, {__index = self})
	o:load()
	return o
end

Sprite.Custom = {}
setmetatable(Sprite.Custom, {__index = Sprite})
local CustomSprite = Sprite.Custom

function CustomSprite:new(name, imagename)
	local image = getImage(imagename)
	if not(image) then
		error("Couldn't find image: " .. tostring(imagename))
	end

	local size = image.width


	o = {
			__source = {
				settings = {}
			},
			__settings={
				size = size,
				sheetsize = 1,
				image = image,
				sheetWidth = size,
				tiles = 1,
				name = name,
				title = title,
				lore = lore,
				enchanted = enchanted,
				link = link
			}
		}
	setmetatable(o, {__index = self})
	setmetatable(o.__settings, {__index=defaultSettings})
	return o
end

function Sprite:load()
	local settings = self.__source.settings
	self.__settings = {
		size = settings.size,
		sheetWidth = settings.sheetsize,
		tiles = settings.sheetsize / settings.size,
		scale = settings.scale,
		autoScale = settings.autoscale,
		image = (settings.image and getImage(settings.image))
			-- or (settings.spriteSheet and getSpriteSheet(settings.spriteSheet))
	}

	setmetatable(self.__settings, {__index=defaultSettings})
end

function Sprite:setItem(item, type)
    -- set aliases
    if type == "gm4" or type == "gm4RP" then
        aliases = gm4Aliases
	elseif type == "effect" then
		aliases = effectAliases
	elseif type == "trophy" then
		aliases = trophyAliases
    else
        aliases = vanillaAliases
    end
	-- js-less plaintext title
	self.__settings.name = item

	-- js-modified color title with lore
    if aliases[item] then
		if aliases[item].text then
			self.__settings.lore = aliases[item].text

		end

		if aliases[item].title then
			if #aliases[item].title == 2 then
		        self.__settings.title= aliases[item].title .. aliases[item].name
			else 
				self.__settings.title = aliases[item].title
			end
		elseif aliases[item].name then
			self.__settings.title = aliases[item].name
		end
		
		if aliases[item].enchanted then
			self.__settings.enchanted = aliases[item].enchanted
		end

		if aliases[item].name ~= nil then
			local itemName = aliases[item].name
			self:setPosition(self.__source.ids[itemName].pos)
			if self.__source.ids[itemName].spriteSheet then
                local newSettings = require(types[self.__source.ids[itemName].spriteSheet]).settings
                self.__settings.classname = newSettings.classname
                self.__settings.size = newSettings.size
                self.__settings.tiles = newSettings.sheetsize / newSettings.size
                self.__settings.scale = newSettings.scale
                self.__settings.autoScale = newSettings.autoscale
			end
		end
    else
        self.__settings.title = item;

		if self.__source.ids[item] then
			self:setPosition(self.__source.ids[item].pos)
			if self.__source.ids[item].spriteSheet then
              local newSettings = require(types[self.__source.ids[item].spriteSheet]).settings
              self.__settings.classname = newSettings.classname
              self.__settings.size = newSettings.size
              self.__settings.tiles = newSettings.sheetsize / newSettings.size
              self.__settings.scale = newSettings.scale
              self.__settings.autoScale = newSettings.autoscale
    	    end
		else
			self:setPosition(nil) --will use default
		end
	end

	return self
end

function Sprite:Item(item, type)
	local sprite = {}
	setmetatable(sprite, {__index = self})
	local settings = {}
	setmetatable(settings, {__index = self.__settings})
	sprite.__settings = settings
	return sprite:setItem(item, type)
end

function Sprite:setPosition(pos)
	self.__settings.pos = pos or self.__settings.pos
	return self
end

function Sprite:SetScale(scale)
	self.__settings.scale = scale
	return self
end

function Sprite:SetSize(size)
	self.__settings.scale = size / self.__settings.size
	return self
end

function Sprite:SetTitle(name)
	self.__settings.title = name
	return self
end

function Sprite:SetLore(text)
	self.__settings.lore = text
	return self
end

function Sprite:HideTooltip()
	self.__settings.hideTooltip = true
	return self
end

function Sprite:calculateStyles()
	styles = {}
	function append(key, value) if value ~= nil then styles[#styles+1]=key .. ": " .. value end end
	local settings = self.__settings

	-- has to be done first, otherwise the possition is overriden in chrome
	if settings.image then
		append("background", settings.image.url)
		append("mask-image", settings.image.url)
		append("-webkit-mask-image", settings.image.url)
	end

	append ("background-size", settings.sheetWidth * settings.scale .. 'px auto')
	append ("mask-size", settings.sheetWidth * settings.scale .. 'px auto')
	append ("-webkit-mask-size", settings.sheetWidth * settings.scale .. 'px auto')

	local t = settings.size * settings.scale .. 'px'

	append ("height", t)
	append ("width", t)
	append ("vertical-align", settings.align)

	local pos = self.__settings.pos - 1
	local left = pos % settings.tiles * settings.size * settings.scale
	local top = math.floor( pos / settings.tiles ) * settings.size * settings.scale
	append("background-position", '-' .. left .. 'px -' .. top .. 'px')
	append("mask-position", '-' .. left .. 'px -' .. top .. 'px')
	append("-webkit-mask-position", '-' .. left .. 'px -' .. top .. 'px')

	return table.concat( styles, "; " )
end

function Sprite:GenerateHTML (html)
	local sprite
	if html then
		if type(html) == "string" then
			sprite = mw.html.create(html)
		else
			sprite = html:tag("div")
		end
	else
		sprite = mw.html.create("div")
	end

	sprite:addClass("sprite")

	if self.__settings.hideTooltip ~= true then
		sprite:addClass("masterTooltip")
	end

	local source = self.__source
	sprite:addClass(self.__settings.classname or source.settings.classname)

	if self.__settings.hideTooltip ~= true then
		sprite:attr( "title", self.__settings.name )
	end

	sprite:attr( "data-title", self.__settings.title )
	
	if self.__settings.lore then
		sprite:attr( "data-lore", self.__settings.lore )
	end

	if self.__settings.enchanted == "true" then
		sprite:addClass("enchanted")
	end

	local styles =  self:calculateStyles()
	sprite:cssText( styles )

	if self.__settings.link then
		sprite = html:tag("span")
		local link = self.__settings.link
		if link:sub ( 1,1 ) == '[' then
			local parentDiv = mw.html.create("a"):attr("href",link:sub ( 2,#link-1 ))
		elseif link:sub ( 1,1 ) == '#' then
			local section_id = self.__source.ids[itemName].section
			for index, tab in pairs(self.__source.sections) do
				if tab.id == section_id then
					local parentDiv = mw.html.create("a"):attr("href","/" .. tab.name .. "/" .. link:sub ( 2,#link ))
				end
			end
		elseif string.match(link, "%#") then
			local parentDiv = mw.html.create("a"):attr("href","/" .. link)
		else
			local parentDiv = mw.html.create("a"):attr("href","/#" .. link)
		end
		parentDiv:node(sprite)
		return parentDiv
	end

	return sprite
end

return Sprite