Bureaucrats, Check users, emailconfirmed, Interface administrators, staff, Administrators, translation-admin, Widget editors
1,637
edits
(Grids) |
mNo edit summary |
||
(35 intermediate revisions by 3 users not shown) | |||
Line 3: | Line 3: | ||
local UISlot = {} | local UISlot = {} | ||
local | local sprite = require([[Module:Sprite]]) | ||
local Sprites = { | |||
minecraft = sprite:new("inventory"), | |||
gm4 = sprite:new("gm4"), | |||
effect = sprite:new("effect"), | |||
trophy = sprite:new("trophy"), | |||
gm4RP = sprite:new("gm4RP") | |||
} | |||
function UISlot:new(item, large) | function UISlot:new(item, large) | ||
Line 13: | Line 20: | ||
end | end | ||
-- Sets the item of this UISlot. If 'raw html' (=first char == '<') then | |||
-- this will return said html wrapped instead of doing a item lookup | |||
function UISlot:SetItem(item) | function UISlot:SetItem(item) | ||
if string.sub(item or "",1,1) == '<' then | |||
-- If the item is already html just save that | |||
self.__html = item | |||
return self | |||
end | |||
self.__sprite = UISlot.Decode(item) | |||
return self | |||
end | |||
function UISlot.Decode(item) | |||
if not(item) then return nil end | |||
item = mw.text.trim(item) | |||
if item == "" then item = nil end | if item == "" then item = nil end | ||
if item then | |||
return | -- split at ':' | ||
local t={} | |||
for str in string.gmatch(item, "([^:]+)") do | |||
table.insert(t, str) | |||
end | |||
if #t == 1 then | |||
return Sprites.minecraft:Item(item,"minecraft") | |||
elseif #t == 2 then | |||
local spr = Sprites[mw.text.trim(t[1])] | |||
if spr then | |||
return spr:Item(mw.text.trim(t[2]), mw.text.trim(t[1])) | |||
else | |||
error("Unknown namespace: " .. mw.text.trim(t[1])) | |||
end | |||
else | |||
error("Got unexpected amount of ':', namely:" .. (#t - 1)) | |||
end | |||
else | |||
return nil | |||
end | |||
end | end | ||
-- Append the HTML for an item | |||
function UISlot.Item(item, large, html) | function UISlot.Item(item, large, html) | ||
return UISlot:new(item, large):GenerateHTML(html) | return UISlot:new(item, large):GenerateHTML(html) | ||
end | end | ||
function UISlot.Call( | -- Generate the HTML for a grid of items | ||
local w = | function UISlot.Call(items, width, height, size) | ||
local h = | local w = width or 1 | ||
local h = height or 1 | |||
local grid = {} | local grid = {} | ||
local large = size | |||
for i = 1,h do | for i = 1,h do | ||
grid[i] = {} | grid[i] = {} | ||
for j = 1,w do | for j = 1,w do | ||
grid[i][j] = | grid[i][j] = mw.text.trim(items[j+(i-1)*w] or "") | ||
end | end | ||
end | end | ||
return UISlot.Grid(grid) | return UISlot.Grid(grid, large) | ||
end | end | ||
function UISlot.Grid(items) | -- Convert a 2d list of itemnames to an HTML grid | ||
function UISlot.Grid(items, large) | |||
local root = mw.html.create( "table" ):addClass("invgrid") | local root = mw.html.create( "table" ):addClass("invgrid") | ||
for i = 1, #items do | for i = 1, #items do | ||
local row = root:tag("tr"):addClass("invrow") | local row = root:tag("tr"):addClass("invrow") | ||
for j = 1, #items[i] do | for j = 1, #items[i] do | ||
UISlot.Item(items[i][j], | UISlot.Item(items[i][j], large, row) | ||
end | end | ||
end | end | ||
Line 53: | Line 102: | ||
else | else | ||
slot = mw.html.create("div") | slot = mw.html.create("div") | ||
end | |||
slot:addClass( "invslot" ) | |||
if self.__large then | |||
slot:addClass( "invslot-large") | |||
end | end | ||
slot: | if self.__html then | ||
slot:wikitext(self.__html) | |||
end | |||
if self.__sprite then | if self.__sprite then | ||
self.__sprite:GenerateHTML(slot) | self.__sprite:GenerateHTML(slot) | ||
end | end | ||
if | return slot | ||
slot:addClass( | end | ||
-- Well Template:InventorySlot does not use any of the above code, so I'm going | |||
-- to start brand new from here, with the Minecraft code | |||
-- Based on work by the Minecraft wiki, https://minecraft.wiki | |||
local i18n = { | |||
filename = 'Invicon $1', | |||
moduleAliases = [[Module:InventorySlot/Aliases]], | |||
prefixes = { | |||
any = 'Any', | |||
matching = 'Matching', | |||
damaged = 'Damaged', | |||
unwaxed = 'Unwaxed', | |||
}, | |||
} | |||
local aliases = mw.loadData( i18n.moduleAliases ) | |||
--[[Merges a list, or inserts a string | |||
or table into a table | |||
--]] | |||
local function mergeList( parentTable, content ) | |||
local i = #parentTable + 1 | |||
if content[1] then | |||
-- Merge list into table | |||
for _, v in ipairs( content ) do | |||
parentTable[i] = v | |||
i = i + 1 | |||
end | |||
else | |||
-- Add strings or tables to table | |||
parentTable[i] = content | |||
end | |||
end | |||
local function makeItem( args ) | |||
local item = mw.html.create( 'span' ):addClass( 'invslot-item' ) | |||
if args.imgclass then | |||
item:addClass( args.imgclass ) | |||
end | |||
if frame.name == '' then | |||
return item | |||
end | |||
local title = frame.title or mw.text.trim( args.title or '' ) | |||
local name = frame.name or '' | |||
local count = frame.count | |||
local description = frame.text | |||
local img | |||
if name:match( '%.gif$' ) or name:match( '%.png$' ) then | |||
img = file:gsub( '%$1', name ) | |||
-- Remove file extension from name | |||
name = il8n.filename:sub( 0, -5 ) | |||
else | |||
-- Fall back to an individual image if the sprite is lacking | |||
img = i18n.filename:gsub( '%$1', name .. '.png' ) | |||
end | |||
local link = args.link or '' | |||
if link == '' then | |||
link = name:gsub( '^' .. i18n.prefixes.damaged .. ' ', '' ) | |||
for _, suffix in pairs( i18n.suffixes ) do | |||
link = link:gsub( ' ' .. suffix .. '$', '' ) | |||
end | |||
elseif link:lower() == 'none' then | |||
link = nil | |||
end | |||
if link == pageName then | |||
link = nil | |||
end | |||
local formattedTitle | |||
local plainTitle | |||
if title == '' then | |||
plainTitle = name | |||
elseif title:lower() ~= 'none' then | |||
plainTitle = title:gsub( '\\\\', '\' ):gsub( '\\&', '&' ) | |||
local formatPattern = '&[0-9a-fk-or]' | |||
if plainTitle:match( formatPattern ) then | |||
formattedTitle = title | |||
plainTitle = plainTitle:gsub( formatPattern, '' ) | |||
end | |||
if plainTitle == '' then | |||
plainTitle = name | |||
else | |||
plainTitle = plainTitle:gsub( '\', '\\' ):gsub( '&', '&' ) | |||
end | |||
elseif link then | |||
formattedTitle = '' | |||
end | |||
item:attr{ | |||
['data-title'] = formattedTitle, | |||
['data-lore'] = description | |||
} | |||
item:addClass( 'invslot-item-image' ) | |||
:wikitext( '[[File:', img, '|32x32px|link=', link or '', '|alt=', altText, '|', escapedTitle, ']]' ) | |||
if count and count > 1 and count < 1000 then | |||
if link then | |||
item:wikitext( '[[', link, '|' ) | |||
end | |||
local number = item | |||
:tag( 'span' ) | |||
:addClass( 'invslot-stacksize' ) | |||
:attr{ title = plainTitle } | |||
:wikitext( count ) | |||
if link then | |||
item:wikitext( ']]' ) | |||
end | |||
end | |||
return item | |||
end | |||
function UISlot.slot( f ) | |||
local args = f.args or f | |||
-- not really sure what this does | |||
local args = f.args or f | |||
if f == mw.getCurrentFrame() and args[1] == nil then | |||
args = f:getParent().args | |||
end | |||
if not args.parsed then | |||
args[1] = mw.text.trim( args[1] or '' ) | |||
end | |||
-- I see. This frames is where you parse the semicolon separated list | |||
-- and enable cycling, in addition to all of the extra data that you | |||
-- need for items. We'll need to investigate whether or not we'll need | |||
-- this? Like it'll be useful for vanilla items, but not for any of our | |||
-- recipes, since we don't need to cycle any of our custom items in recipes. | |||
-- .... I say that, then realize Zauber armor cycles. But tbf, it's all | |||
-- premade from aliases, and does not need custom in-place data | |||
local frames | |||
if args.parsed then | |||
frames = args[1] | |||
elseif args[1] ~= '' then | |||
-- Not using moddata, but that kinda makes me think we could use the | |||
-- module namespaces from automatically imported items... hmm... | |||
frames = UISlot:parseFrameText ( args[1], false ) | |||
end | |||
local body = mw.html.create( 'span' ):addClass( 'invslot' ):css{ ['vertical-align'] = args.align } | |||
if animated then body:addClass( 'animated' ) end | |||
if args.class then body:addClass( args.class ) end | |||
if args.style then body:cssText( args.style ) end | |||
if not frames then return tostring ( body) end | |||
-- Figure out cycling here | |||
for i, frame in ipairs( frames ) do | |||
local item | |||
-- how? | |||
item = makeItem( frame, i, args) | |||
body:node( item ) | |||
if i == activeFrame and animated then | |||
item:addClass( 'animated-active' ) | |||
end | |||
end | |||
return tostring( body ) | |||
end | |||
function UISlot.parseFrameText ( framesText, aliasReference ) | |||
local frames = {} | |||
local expandedAliases | |||
-- wow so much code for cycling that is being skipped here | |||
-- this line is definitely wrong, but we'll see if this works as a | |||
-- single line hack | |||
local frameText = framesText | |||
local frame = UISlot.makeFrame( frameText ) | |||
local newFrame = frame | |||
-- or gm4 ? | |||
if aliases then | |||
local id = frame.name | |||
if frame.mod and frame.mod == 'gm4' then | |||
-- load gm4 aliases, I guess? | |||
end | |||
-- Figure out how to load and access the gm4 alias | |||
local alias = aliases or aliases[id] | |||
if alias then | |||
newFrame = UISlot.getAlias ( alias, frame ) | |||
-- lots of other code that we need to do when we accept cycle lists | |||
end | |||
mergeList( frames, newFrame ) | |||
end | |||
return frames | |||
end | |||
function UISlot.getAlias( aliasFrames, parentFrame ) | |||
if type( aliasFrames ) == 'string' then | |||
local expandedFrame = mw.clone ( parentFrame ) | |||
expandedFrame.name = aliasFrames | |||
return { expandedFrame } | |||
end | |||
if aliasFrames.name then | |||
aliasFrames = { aliasFrames } | |||
end | |||
for i, aliasFrame in ipairs( aliasFrames ) do | |||
local expandedFrame | |||
if type( aliasFrame ) == 'string' then | |||
expandedFrame = { name = aliasFrame } | |||
else | |||
expandedFrame = cloneTable( aliasFrame ) | |||
end | |||
expandedFrame.title = parentFrame.title or expandedFrame.title | |||
expandedFrame.mod = parentFrame.mod or expandedFrame.mod | |||
expandedFrame.num = parentFrame.num or expandedFrame.num | |||
expandedFrame.text = parentFrame.text or expandedFrame.text | |||
expandedFrames[i] = expandedFrame | |||
end | |||
return expandedFrames | |||
end | |||
function UISlot.makeFrame( frameText ) | |||
local frame = {} | |||
frame.title = frameText:match( '^%[([^%]]+)%]' ) | |||
frame.mod = frameText:match( '([^:%]]+):' ) or mod | |||
local vanilla = { v = 1, vanilla = 1, mc = 1, minecraft = 1 } | |||
if frame.mod and vanilla[mw.ustring.lower( frame.mod )] or frame.mod == '' then | |||
frame.mod = nil | |||
end | |||
local nameStart = ( frameText:find( ':' ) or frameText:find( '%]' ) or 0 ) + 1 | |||
if nameStart - 1 == #frameText then | |||
nameStart = 1 | |||
end | end | ||
return | |||
-- Come back to this later. If we are going to pull names after colons, | |||
-- then we know whether it's vanilla or gm4. Should maybe use the "mod" | |||
-- stuff at some point, but I'd imagine above is where you'd pull and find | |||
frame.name = frameText:sub( nameStart, ( frameText:find( '[,%[]', nameStart ) or 0 ) - 1 ) | |||
frame.text = frameText:match( '%[([^%]]+)%]$' ) | |||
return frame | |||
end | end | ||
return UISlot | return UISlot |
edits