Module:Advancement: Difference between revisions

From Downtime Wiki
MC>Dianliang233
overflow properly
 
m 1 revision imported
 
(No difference)

Latest revision as of 04:45, 25 April 2025

Usage

Called by {{#if:{{#switch: yes

| y | yes | t | true  | on  | 1 = yes
| n | no  | f | false | off | 0 | = 
| =  
| #default = yes

}}|}}{{{{#if: |subst: }}[[{{#if: {{#pos: AdvancementRow | : }} || Template: }}AdvancementRow|{{ #ifeq: | Template | AdvancementRow | AdvancementRow }}]]{{ #if: | | }}{{ #if: | | }}{{ #if: | | }}{{ #if: | | }}{{ #if: | | }}{{ #if: | | }}{{ #if: | | }}{{ #if: | | }}}}{{#if:{{#switch: yes

| y | yes | t | true  | on  | 1 = yes
| n | no  | f | false | off | 0 | = 
| =  
| #default = yes

}}|}}{{#if: {{#pos: AdvancementRow | File: }}{{#pos: AdvancementRow | Category: }} | }} and {{#if:{{#switch: yes

| y | yes | t | true  | on  | 1 = yes
| n | no  | f | false | off | 0 | = 
| =  
| #default = yes

}}|}}{{{{#if: |subst: }}[[{{#if: {{#pos: Load advancements | : }} || Template: }}Load advancements|{{ #ifeq: | Template | Load advancements | Load advancements }}]]{{ #if: | | }}{{ #if: | | }}{{ #if: | | }}{{ #if: | | }}{{ #if: | | }}{{ #if: | | }}{{ #if: | | }}{{ #if: | | }}}}{{#if:{{#switch: yes

| y | yes | t | true  | on  | 1 = yes
| n | no  | f | false | off | 0 | = 
| =  
| #default = yes

}}|}}{{#if: {{#pos: Load advancements | File: }}{{#pos: Load advancements | Category: }} | }}

{{#if:{{#pos:Advancement|/sandbox}}|| fr:Module:Progrès ko:모듈:Advancement nl:Module:Vooruitgangen pt:Módulo:Advancement }}


local advancement_page = 'Advancement'

local p = {}
local namespace = mw.title.getCurrentTitle().nsText
local page_title = mw.title.getCurrentTitle().text
local full_title = mw.title.getCurrentTitle().fullText
local html
local frame

local function sanitize(str)
	-- remove anything between < and > (simple way to remove span tag)
	-- return lower case alpha numeric characters and spaces
	return str:gsub('<.->',''):gsub('[^%w%s]*', ''):lower()
end

-- Adds one row of advancement data to html object
local function printLine(line, is_input)
	local tr = html:tag('tr'):attr('id', line.title):cssText('text-align:left')
	
	local link = nil
	if not is_input then
		link = advancement_page..'#'..line.title
	end
	
	local image = require('Module:Aicon').aIcon( line.image, line.background, 'raw', (link or '') )
	tr:tag('td'):wikitext(image)
	
	local title_extra = ''
	if line.upcoming_ver then
		title_extra = title_extra .. frame:expandTemplate{title = 'Upcoming', args = {ver = line.upcoming_ver}}
	end
	
	if line.until_ver then
		title_extra = title_extra .. frame:expandTemplate{title = 'Until', args = {ver = line.until_ver}}	
	end
	
	tr:tag('td'):wikitext('[['..(link or full_title)..'|'..line.title..']]', title_extra)
	tr:tag('td'):wikitext(line.game_description)
	if is_input then -- These are only displayed on the input page, not on individual content pages
		tr:tag('td'):wikitext(line.parent)
	end
	tr:tag('td'):wikitext(line.wiki_description)
	if is_input then -- These are only displayed on the input page, not on individual content pages
		tr:tag('td'):wikitext('<code>', line.internal_id, '</code>')
		tr:tag('td'):wikitext(line.reward)
	end
end

-- Puts one line of data into SMW for later querying
local function storeLine(line)
	-- Put data into SMW
	-- The only top level params that are needed is stuff that would be used as selectors
	-- everything else is put into a json blob for flexibility
	if not (namespace == '' or namespace ==  'Minecraft_Wiki') then
		 return -- only store data if we are in main or Minecraft_Wiki namespaces
	end
	
	local smw_sub = {}
	local sanitized_title = sanitize(line.title)
	local subname = 'ADVANCEMENT'..'_'..sanitized_title
	
	-- mw.text.unstrip gets rid of parser artifacts that are put there when a <ref> tag is used.
	line.wiki_description = mw.text.unstrip(line.wiki_description)
	line.game_description = mw.text.unstrip(line.game_description)
	
	local smw_sub = { -- the actual SMW sub-object
		['Advancement Title'] = sanitized_title,
		['Advancement JSON'] = mw.text.jsonEncode(line) -- serializes all data into a json blob
	}
	mw.smw.subobject(smw_sub, subname)
end

-- Public function - Called by {{AdvancementRow}}
function p.inputLine(_frame)
	frame = _frame -- store frame for later use by expandTemplate
	local args = frame:getParent().args
	
	-- Normalize inputs and set defaults
	local line = {
		title = args['title'], -- name
		background = args['bg'] or 'plain', -- background for icon
		upcoming_ver = args['upcoming'], -- version where advancement will be introduced
		until_ver = args['until'], -- version where advancement will be removed
		image = mw.text.trim(args[1]),
		game_description = mw.text.trim(args[2]),
		parent = mw.text.trim(args[3]),
		wiki_description = mw.text.trim(args[4]),
		internal_id = mw.text.trim(args[5] or '—'),
		reward = mw.text.trim(args[6] or '—')
	}
	
	html = mw.html.create()
	
	printLine(line, true)
	storeLine(line)
		
	return html
end

local function printHeader(header_text, short_header)
	-- Can't use table tag because it will close itself, but we need to close it with footer
	html = mw.html.create():wikitext('<div style="overflow: auto;"><table class="wikitable" style="text-align:center">')
	
	if header_text and header_text ~= '' then
		html:tag('th')
			:attr('colspan', 7)
			:attr('data-description', header_text)
			:wikitext(header_text)
	end
	
	local tr = html:tag('tr')
	tr:tag('th'):wikitext('Icon')
	tr:tag('th'):wikitext('Advancement')	
	tr:tag('th'):wikitext('In-game description')
	if not short_header then
		tr:tag('th'):wikitext('Parent')
	end
	tr:tag('th'):wikitext('Actual requirements (if different)')
	if not short_header then
		tr:tag('th'):wikitext('[[Resource location]]')
		tr:tag('th'):wikitext('Rewards')
	end
	
	return html
end

local function printFooter()
	return '</table></div>'
end

-- Public function - called by {{AdvancementTable}}
function p.table(frame)
	local args = frame:getParent().args
	if args[1] == 'foot' then
		return printFooter()
	else
		return printHeader(args[1], false)
	end
end

-- Public function - called by {{Load advancements}}
function p.load(frame_)
	frame = frame_ -- store frame for later use by expandTemplate
	local args = frame:getParent().args
	
	advancement_page = args.page or advancement_page
	
	printHeader('', true)
	
	local queryString = {}
	-- SMW can query up to 15 conditions at once and we always specify the source page, so put queries into groups of 13 names
	local counter = 13 -- Start at 13 so queryString index starts at 1, it just looks cleaner when debugging
	for name in string.gmatch(args[1], "[^;]+") do
		counter = counter + 1
		queryString[math.floor(counter/13)] = (queryString[math.floor(counter/13)] or '')..'||'..sanitize(name)
	end
	
	local expected = counter - 13
	local found = 0
	for _,str in ipairs(queryString) do
		local query = {
			'[[-Has subobject::'..advancement_page..']]',
			'[[Advancement Title::'..str:sub(3)..']]', --Remove the first 2 characters because they will always be ||
			'?Advancement JSON',
			limit = 25
		}
	
		local smwdata = mw.smw.ask(query)
		
		if smwdata then
			for i,v in ipairs(smwdata) do
				if type(v['Advancement JSON']) == "table" then -- if a page has a drop happening multiple times it is returned in a table instead of a string
					for j,k in ipairs(v['Advancement JSON']) do
						found = found + 1
						local line = mw.text.jsonDecode(v['Advancement JSON'][j] or '{}')
						printLine(line, false)
					end
				else
					found = found + 1
					local line = mw.text.jsonDecode(v['Advancement JSON'] or '{}')
					printLine(line, false)
				end
			end
		end
	end
	
	if found ~= expected then
		html:wikitext('[[Category:Missing advancement]]')
	end

	html:wikitext(printFooter())

	return html
end

return p