Module:ScriptItem
Documentation for this module may be created at Module:ScriptItem/doc
local p = {}
-- settings
p.categoryItems = {
-- Category Name = table. (Fully resolved item name(s), case-sensitive.) (Event names must start with a capital letter "O", to match the dumpdoc XML.)
['Audio'] = {'gta.addOneOffSound', 'gta.playFrontEndSound', 'gta.playSuspectLastSeen'},
['Camera'] = {'gta.fading'},
['Chatbox'] = {'message', 'messageClient', 'messageAllExcept', 'setChatWindowEnabled', 'OnChatOutput'},
['Cursor'] = {'gta.getMouseSpeed'},
['CustomText'] = {'gta.setCustomText', 'gta.setCustomText', 'gta.clearCustomText', 'gta.printBig'},
['Drawing'] = {'gta.drawRectangle'},
['Effect'] = {'gta.addParticleEffect', 'addParticleEffect', 'gta.addMovingParticleEffect', 'addMovingParticleEffect', 'gta.createSingleParticle', 'createSingleParticle'},
['Font'] = {'font.render'},
['GarbageCollection'] = {'collectAllGarbage'},
['Game'] = {'gta.game', 'gta.standardControls', 'gta.gameSpeed', 'gta.loadDFF', 'gta.loadTXD', 'gta.loadCOL'},
['GameStat'] = {'gta.setGameStat', 'gta.getGameStat'},
['GUI'] = {'OnGUIClick'},
['Key'] = {'isScancodePressed', 'OnCharacter'},
['KillFrenzy'] = {'gta.startKillFrenzy'},
['Message'] = {'gta.clearMessages', 'gta.smallMessage', 'gta.bigMessage', 'gta.pagerMessage'},
['Miscellaneous'] = {'platform', 'toColour', 'gta.tickCount', 'getRandomSkin', 'gta.getRandomSkin', 'gta.processLineOfSight', 'processLineOfSight', 'gta.setIsland', 'gta.setDefaultInteriors'},
['Network'] = {'isConnected', 'isConnecting', 'connect', 'disconnect', 'triggerNetworkEvent', 'OnDisconnect'},
['Path'] = {'gta.trafficDensity', 'gta.setTrafficEnabled', 'setTrafficEnabled', 'gta.setCiviliansEnabled', 'setCiviliansEnabled'},
['Ped'] = {'gta.tommyFatness'},
['Radio'] = {'gta.setRadioChannel', 'gta.forceRadioChannel'},
['Reflection'] = {'exportFunction', 'setErrorMode'},
['Renderware'] = {'gta.rwRenderStateSet'},
['SaveGame'] = {'gta.saveGame'},
['Screen'] = {'gta.aspectRatio', 'gta.width', 'gta.height'},
['Script'] = {'gta.terminateScript', 'gta.getActiveScripts', 'gta.scriptCommand'},
['Timer'] = {'setImmediate', 'clearImmediate', 'setInterval', 'clearInterval', 'setTimeout', 'clearTimeout'},
['Weather'] = {'snowing', 'forceSnowing'},
['Window'] = {'OnFocus', 'OnLostFocus'},
['World'] = {'gta.ssvBridgeEnabled', 'gta.planesEnabled', 'gta.trainsEnabled', 'setPlanesEnabled', 'setTrainsEnabled', 'world', 'gta.findGroundZForCoord', 'findGroundZForCoord', 'gta.setTrainsEnabled', 'gta.setPlanesEnabled'}
}
p.categoryWords = {
-- Category Names. (String(s) to look for in an item name, case-INsensitive.)
'Blip', 'Building', 'Camera', 'Chatbox', 'Civilian', 'Cheat', 'Client', 'Command', 'Cursor', 'Debug', 'Dodo',
'Element', 'Entity', 'Event', 'File', 'Font', 'Garage', 'HTTP', 'HUD', 'Key', 'Mission', 'Mouse', 'Network', 'Object',
'Pause', 'Ped', 'Pickup', 'Player', 'Process', 'Render', 'Resource', 'Screen', 'Socket', 'Sphere', 'Time', 'Transformable', 'Vehicle', 'Weather', 'World'
}
-- entry point
function p.main(frame)
local args = p.getArgs(frame)
if args.type == 'variable' then
return p.showVariablePage(frame)
elseif args.type == 'function' then
return p.showFunctionPage(frame)
elseif args.type == 'property' then
return p.showPropertyPage(frame)
elseif args.type == 'method' then
return p.showMethodPage(frame)
elseif args.type == 'event' then
return p.showEventPage(frame)
else
return "This page has been documented incorrectly, '''type''' is missing."
end
end
-- item page types
function p.showVariablePage(frame)
local parts = { "Value", "Settable" }
return p.showPage(frame, parts)
end
function p.showFunctionPage(frame)
local parts = { "Parameters", "Return", "Callbacks" }
return p.showPage(frame, parts)
end
function p.showPropertyPage(frame)
local parts = { "Value", "Settable" }
return p.showPage(frame, parts)
end
function p.showMethodPage(frame)
local parts = { "Parameters", "Return", "Callbacks" }
return p.showPage(frame, parts)
end
function p.showEventPage(frame)
local parts = { "Parameters", "Cancellable" }
return p.showPage(frame, parts)
end
-- item page
function p.showPage(frame, parts)
local args = p.getArgs(frame)
local lines = p.getPageTopLines(frame)
table.insert(parts, 1, "Usage")
for i,part in ipairs({"Notes", "Examples", "Compatibility", "Related"}) do
table.insert(parts, part)
end
for i,part in ipairs(parts) do
local data = p[part:lower() == 'return' and 'returns' or part:lower()](frame)
if data and #data > 0 then
if part == 'Settable' then
part = args.readonly == 'true' and 'Read-Only' or 'Read and Set'
end
table.insert(lines, '== '..part..' ==')
table.insert(lines, data)
end
end
return table.concat(lines, "\n")
end
function p.getPageTopLines(frame)
local lines = {}
table.insert(lines, frame:preprocess("{{DISPLAYTITLE:"..p.getDisplayedName(frame).."}}"))
table.insert(lines, "__NOTOC__"..p.getPageTopBoxes(frame).."\n")
table.insert(lines, "<div style='margin-top: 20px;'>Available since "..p.since(frame).."</div>\n")
table.insert(lines, "<div style='margin-top: 6px;'>"..p.syntax(frame).."</div>\n")
table.insert(lines, "<div style='margin-top: 20px;'>"..p.description(frame).."</div>\n")
return lines
end
function p.getPageTopBoxes(frame)
local args = p.getArgs(frame)
local topBoxes = { "type", "endpoint", "games", "online" }
if args.type == 'variable' or args.type == 'property' then
table.insert(topBoxes, "settable")
end
local outBoxes = {}
for i,topBox in ipairs(topBoxes) do
table.insert(outBoxes, p[topBox.."Box"](frame))
end
return table.concat(outBoxes, ' ').."<br>"
end
-- template arguments
function p.getArgs(frame)
if p.argsCache then
return p.argsCache
else
local args = frame:getParent().args
p.copyOldToNewForTemplateArguments(frame, args)
p.copyNonIndexedToIndexedTemplateArguments(frame, args)
p.populateTypeSpecificTemplateArguments(frame, args)
p.populateDefaultTemplateArguments(frame, args)
p.argsCache = args
return args
end
end
function p.copyOldToNewForTemplateArguments(frame, args)
if args.parameters then
args.syntax = args.parameters
end
if args.parametersSS then
args.syntaxSS = args.parametersSS
end
if args.parametersCS then
args.syntaxCS = args.parametersCS
end
if args.callbackParameters then
args.callbackSyntax = args.callbackParameters
end
if args.callbackParametersSS then
args.callbackSyntaxSS = args.callbackParametersSS
end
if args.callbackParametersCS then
args.callbackSyntaxCS = args.callbackParametersCS
end
if args.type == 'event' then
if args.callbackParameters then
args.syntax = args.callbackParameters
end
if args.callbackParametersSS then
args.syntaxSS = args.callbackParametersSS
end
if args.callbackParametersCS then
args.syntaxCS = args.callbackParametersCS
end
end
if args.returnType or args.returnTypes then
local returnType = args.returnType and args.returnType or args.returnTypes
if args.returnInfo then
args.return1 = returnType.." "..args.returnInfo
args.value = returnType.." "..args.returnInfo
else
args.return1 = returnType
args.value = returnType
end
end
if args.usage then
args.description = args.usage
end
if args.notes then
local notes = p.splitLines(args.notes)
for i,note in ipairs(notes) do
args['note'..i] = note
end
end
local exampleKeys = {
'example', 'exampleSS', 'exampleCS', 'exampleJS', 'exampleLua', 'exampleSquirrel',
'exampleJSSS', 'exampleJSCS', 'exampleLuaSS', 'exampleLuaCS', 'exampleSquirrelSS', 'exampleSquirrelCS'
}
for i,exampleKey in ipairs(exampleKeys) do
if args[exampleKey] then
local examples = p.split(args[exampleKey], '<br>')
for i,example in ipairs(examples) do
args[exampleKey..i] = example
end
end
end
if args.bcName and args.bcMaxVersion then
args.previous1 = args.bcName.." "..args.bcMaxVersion
end
end
function p.copyNonIndexedToIndexedTemplateArguments(frame, args)
if args.description then
args.description1 = args.description
end
end
function p.populateTypeSpecificTemplateArguments(frame, args)
if args.type == 'variable' or args.type == 'property' then
if args.value then
local tokens = p.split(args.value, ' ')
local type = tokens[1]
local name
if args.type == 'property' then
name = args.class.."."..args.name
else
name = args.name
end
args.syntax = type.." "..name
end
end
end
function p.populateDefaultTemplateArguments(frame, args)
if not args.since then
args.since = "1.0.0 1.0.0"
end
if args.syntax and args.syntax:lower() == "void" then
args.parameter1 = "void"
end
end
-- item top boxes
function p.typeBox(frame)
local args = p.getArgs(frame)
local typeText = p.getType(args.type)
return p.loadTemplate(frame, 'GreenInformationBox', {typeText,id='type'});
end
function p.endpointBox(frame)
local args = p.getArgs(frame)
local endpointText, isShared = p.getEndpoint(args.endpoint)
if isShared then
return p.loadTemplate(frame, 'GreenInformationBox', {endpointText,id='endpoint'});
else
return p.loadTemplate(frame, 'RedInformationBox', {endpointText,id='endpoint'});
end
end
function p.gamesBox(frame)
local args = p.getArgs(frame)
local gamesText = p.getGames(args.games)
if gamesText == "All Games" then
return p.loadTemplate(frame, 'GreenInformationBox', {gamesText,id='games'});
else
return p.loadTemplate(frame, 'RedInformationBox', {gamesText..' Only',id='games'});
end
end
function p.onlineBox(frame)
local args = p.getArgs(frame)
if args.sp == 'true' then
return p.loadTemplate(frame, 'RedInformationBox', {'Offline Only',id='online'});
else
return p.loadTemplate(frame, 'GreenInformationBox', {'Online and Offline',id='online'});
end
end
function p.settableBox(frame)
local args = p.getArgs(frame)
if args.readonly == 'true' then
return p.loadTemplate(frame, 'RedInformationBox', {'Read-Only',id='settable'});
else
return p.loadTemplate(frame, 'GreenInformationBox', {'Read and Set',id='settable'});
end
end
-- item parts
function p.since(frame)
local args = p.getArgs(frame)
if not args.since then
return p.documentationMissing(frame, "Available since")
else
local endpointVersions = p.getEndpointVersions(args.since, args.endpoint)
if #endpointVersions == 2 then
return "'''Server "..endpointVersions[1].."''', '''Client "..endpointVersions[2].."'''"
else
if args.endpoint == 'server' then
return "'''Server "..endpointVersions[1].."'''"
elseif args.endpoint == 'client' then
return "'''Client "..endpointVersions[1].."'''"
else
return p.documentationMissing(frame, "Available since (Both server and client version is needed for shared items)")
end
end
end
end
function p.syntax(frame)
local args = p.getArgs(frame)
if args.syntax then
return p.loadTemplate(frame, 'CodeSyntax', {p.buildSyntax(frame, args.syntax),id='syntax'})
end
if args.syntaxSS and args.syntaxCS then
local rows = {}
rows[1] = { "'''Server:'''", p.loadTemplate(frame, 'CodeSyntax', {p.buildSyntax(frame, args.syntaxSS),id='syntaxss'}) }
rows[2] = { "'''Client:'''", p.loadTemplate(frame, 'CodeSyntax', {p.buildSyntax(frame, args.syntaxCS),id='syntaxcs'}) }
return p.table(false, rows, { 100 }, false)
end
return p.documentationMissing(frame, "Syntax")
end
function p.description(frame)
local args = p.getArgs(frame)
local entries = p.getIndexedArgs(frame, 'description')
local startTextFirstLine = "The <span style=\"font-family: 'Source Code Pro', monospace;\">"..p.getDisplayedName(frame).."</span> "..args.type.." is "..(args.type == "event" and "invoked when" or "used to").." "
for i,entry in ipairs(entries) do
if i == 1 then
entry = startTextFirstLine..entry
end
entries[i] = p.formatDescription(entry)
end
return table.concat(entries, '<br>')
end
function p.parameters(frame)
local args = p.getArgs(frame)
local entries = p.getIndexedArgs(frame, 'parameter')
local rows = {}
local isEvent = args.type == 'event'
if isEvent and args.syntax and args.syntax:lower() == 'event event' then
elseif #entries == 0 then
return p.documentationMissing(frame, "Parameters")
elseif entries[1] == "void" then
local headers = nil
local rows = { { "void", "This "..args.type.." doesn't take any parameters." } }
local widths = { 30, 80, 510 }
return p.table(headers, rows, widths, 'wikitable-parameters wikitable')
else
for i,arg in ipairs(entries) do
local tokens = p.split(arg, ' ')
local isOptional = tokens[3] == 'optional'
local defaultValue = isOptional and "<span style='font-family: \"Source Code Pro\", monospace;'>"..tokens[4].."</span>" or "n/a"
local description = p.formatDescription(table.concat(tokens, ' ', isOptional and 5 or 3))
if isEvent then
rows[i] = { i..") ", p.formatType(tokens[1], frame), p.formatSource(tokens[2], frame), description }
else
rows[i] = { i..") ", p.formatType(tokens[1], frame), p.formatSource(tokens[2], frame), (isOptional and ("Optional, defaults to "..defaultValue..". ") or "")..description }
end
end
end
if isEvent then
table.insert(rows, 1, { "1) ", p.formatType("Event", frame), "event", "The event object for this event." })
end
local headers, widths
if isEvent then
headers = nil--{ "Type", "Name", "Description" }
widths = { 30, 80, 110, 400 }
else
headers = nil--{ "Type", "Name", "Presence", "Default Value", "Description" }
widths = { 30, 80, 110, 400 }
end
return p.table(headers, rows, widths, 'wikitable-parameters wikitable')
end
function p.returns(frame)
local args = p.getArgs(frame)
local text = ""
local entries
local rows
local headers
local widths
local isVoidReturn = false
rows = {}
entries = p.getIndexedArgs(frame, 'return')
if #entries == 0 then
text = text..p.documentationMissing(frame, "Success returns").."<br><br>"
else
for i,arg in ipairs(entries) do
local tokens = p.split(arg, ' ')
local type = tokens[1]
type = p.standardizeNullType(type)
local description
if type:lower() == "void" then
isVoidReturn = true
description = "This "..args.type.." doesn't return any values on success."
elseif tokens[2] then
description = p.formatDescription(table.concat(tokens, ' ', 2))
else
description = p.documentationMissing(frame, "Description for success return value")
end
rows[i] = { '', p.formatType(tokens[1], frame), description }
end
headers = nil-- { "Type", "Description" }
widths = { 30, 80, 400 }
text = text..p.table(headers, rows, widths, 'wikitable-returns wikitable')
end
--[[
-- commented out as failure returns are not currently implemented in GTAC.
if not isVoidReturn then
rows = {}
entries = p.getIndexedArgs(frame, 'returnFail')
text = text.."'''Failure Return:'''\n\n"
if #entries == 0 then
text = text..p.documentationMissing(frame, "Failure returns")
else
for i,arg in ipairs(entries) do
local tokens = p.split(arg, ' ')
local type = tokens[1]
type = p.standardizeNullType(type)
local value
if type:lower() == 'void' then
value = "n/a"
elseif tokens[2] then
value = p.formatSource(table.concat(tokens, ' ', 2), frame)
else
value = p.formatSource(p.documentationMissing(frame, "Description for failure return value"), frame)
end
rows[i] = { '', p.formatType(tokens[1], frame), value }
end
headers = nil--{ "Type", "Value" }
widths = { 30, 80, 400 }
text = text..p.table(headers, rows, widths, 'wikitable-returns wikitable')
end
end
]]
return text
end
function p.callbacks(frame)
local args = p.getArgs(frame)
local suffixes = {
{ '', '' },
{ 'SS', 'Server-Side Callbacks' },
{ 'CS', 'Client-Side Callbacks' }
}
local html = {}
for i3,suffixData in ipairs(suffixes) do
local suffix = suffixData[1]
local parameters = p.getIndexedArgs(frame, 'parameter')
for i=1, #parameters do
local callbackSyntax = args['callback'..i..'Syntax'..suffix]
local callbackText = args['callback'..i..'Text'..suffix]
local callbackNParameters = p.getIndexedArgs(frame, 'callback'..i..'Parameter'..suffix)
if #callbackNParameters > 0 then
if suffixData[1] ~= '' then
table.insert(html, "'''"..suffixData[2].."'''")
end
local parameterTokens = p.split(parameters[i], ' ')
local rows = {}
if #parameterTokens > 0 then
local syntaxLine = parameterTokens[1]..' '..parameterTokens[2]..'('..callbackSyntax..')'
syntaxLine = p.loadTemplate(frame, 'CodeSyntax', {syntaxLine})
table.insert(html, syntaxLine)
end
if callbackText and #callbackText > 0 then
table.insert(html, callbackText)
end
for i2,callbackNParameter in ipairs(callbackNParameters) do
local callbackTokens = p.split(callbackNParameter, ' ')
local parameterType = callbackTokens[1]
local parameterName = callbackTokens[2]
local description = p.formatDescription(table.concat(callbackTokens, ' ', 3))
rows[i2] = { i2..') ', p.formatType(parameterType, frame), p.formatSource(parameterName, frame), description }
end
local headers, widths
headers = nil--{ "Type", "Name", "Description" }
widths = { 30, 80, 110, 400 }
local table2 = "\n"..p.table(headers, rows, widths, 'wikitable-callback wikitable')
table.insert(html, table2)
if i ~= #parameters then
table.insert(html, "<br>")
end
end
end
end
if args.callbackSyntax then
table.concat(html, p.loadTemplate(frame, 'CodeSyntax', {p.buildSyntax(frame, args.callbackSyntax, true),id='callbacks'}))
end
if args.callbackSyntaxSS and args.callbackSyntaxCS then
local rows = {}
rows[1] = { "'''Server:'''", p.loadTemplate(frame, 'CodeSyntax', {p.buildSyntax(frame, args.callbackSyntaxSS, true),id='callbacks'}) }
rows[2] = { "'''Client:'''", p.loadTemplate(frame, 'CodeSyntax', {p.buildSyntax(frame, args.callbackSyntaxCS, true),id='callbacks'}) }
table.concat(html, p.table(false, rows, { 100 }, false, 'wikitable-callback wikitable'))
end
return #html > 0 and table.concat(html, '') or false
end
function p.cancellable(frame)
local args = p.getArgs(frame)
if p.isCancellable(frame) then
return "This "..args.type.." can be cancelled using [[event.preventDefault|event.preventDefault]]."
else
return "This "..args.type.." can't be cancelled."
end
end
function p.value(frame)
local args = p.getArgs(frame)
if not args.value then
return p.documentationMissing(frame, "Value type and description")
end
local arg = args.value
local tokens = p.split(arg, ' ')
local description = p.formatDescription(table.concat(tokens, ' ', 2))
local headers = nil--{ "Type", "Description" }
local rows = { { '', p.formatType(tokens[1], frame), description } }
local widths = { 30, 80, 400 }
return p.table(headers, rows, widths, 'wikitable-returns wikitable')
end
function p.settable(frame)
local args = p.getArgs(frame)
if args.readonly == 'true' then
return "This "..args.type.." is read-only."
else
return "This "..args.type.." can be read and set."
end
end
function p.usage(frame)
local args = p.getArgs(frame)
return p.getDerivedClassesText(frame, args.class)
end
function p.notes(frame)
local args = p.getArgs(frame)
local entries = p.getIndexedArgs(frame, 'note')
if #entries == 0 then
return "There aren't any notes for this "..args.type.."."
end
for i,entry in ipairs(entries) do
entries[i] = p.dot(entry)
end
return "* "..table.concat(entries, "\n* ")
end
function p.examples(frame)
local args = p.getArgs(frame)
local data = {
{ "example", "" },
{ "exampleSS", "Server-Side" },
{ "exampleCS", "Client-Side" },
{ "exampleJS", "JavaScript" },
{ "exampleLua", "Lua" },
{ "exampleSquirrel", "Squirrel" },
{ "exampleJSSS", "JavaScript - Server-Side" },
{ "exampleJSCS", "JavaScript - Client-Side" },
{ "exampleLuaSS", "Lua - Server-Side" },
{ "exampleLuaCS", "Lua - Client-Side" },
{ "exampleSquirrelSS", "Squirrel - Server-Side" },
{ "exampleSquirrelCS", "Squirrel - Client-Side" }
}
local examples = {}
local exampleIndex = 1
for i,data2 in ipairs(data) do
local entries = p.getIndexedArgs(frame, data2[1])
for i2, entry in ipairs(entries) do
local entry = "'''Example "..exampleIndex.." - "..data2[2]..":'''<br>"..p.loadTemplate(frame, 'CodeSyntax', {entry,id='example_'..exampleIndex})
table.insert(examples, entry)
exampleIndex = exampleIndex + 1
end
end
if #examples == 0 then
return "There aren't any examples for this "..args.type.."."
end
return table.concat(examples, "<br>")
end
function p.compatibility(frame)
local args = p.getArgs(frame)
local entries1 = p.getIndexedArgs(frame, 'previous')
local entries2 = p.getIndexedArgs(frame, 'compat')
if #entries1 == 0 and #entries2 == 0 then
return "There isn't any compatibility information for this "..args.type.."."
else
local entriesOut = {}
for i,arg in ipairs(entries1) do
local versionsText, tokens = p.getVersionsText(arg, args.endpoint, 2)
entriesOut[i] = "This "..args.type.." was previously named <code>"..tokens[1].."</code> in "..versionsText.."."
end
local offset = #entriesOut
for i,arg in ipairs(entries2) do
entriesOut[i + offset] = p.dot(arg)
end
return "* "..table.concat(entriesOut, "\n* ")
end
end
function p.related(frame)
local args = p.getArgs(frame)
local categoryTitle = p.getItemCategory(frame)
if categoryTitle and categoryTitle:len() > 0 then
local shared = args.endpoint:lower() == 'shared'
local server = args.endpoint:lower() == 'shared' or args.endpoint:lower() == 'server'
local client = args.endpoint:lower() == 'shared' or args.endpoint:lower() == 'client'
local pageName = args.type:lower() == 'event' and 'Event' or 'Function'
local parts = {}
local name
if args.type == 'property' then
name = args.class.."."..args.name
else
name = args.name
end
if server then
local title = 'Server/'..pageName..'s/'..categoryTitle
local t = p.loadTemplate(frame, title, args)
--t = p.remove(t, "[["..name.."|"..name.."]]<br>\n")
--[[
t = p.replace(t, " ", " ");
t = p.remove(t, "\t");
t = p.remove(t, "\r");
t = p.remove(t, "\n");
t = p.remove(t, "<a class=\"mw-selflink selflink\">"..name.."</a><br />")
]]
table.insert(parts, "'''Server Related'''<br><br>"..t)
end
if client then
local title = 'Client/'..pageName..'s/'..categoryTitle
local t = p.loadTemplate(frame, title, args)
--t = p.remove(t, "[["..name.."|"..name.."]]<br>\n")
--[[
t = p.replace(t, " ", " ");
t = p.remove(t, "\t");
t = p.remove(t, "\r");
t = p.remove(t, "\n");
t = p.remove(t, "<a class=\"mw-selflink selflink\">"..name.."</a><br />")
]]
table.insert(parts, "'''Client Related'''<br><br>"..t)
end
return table.concat(parts, '<br><br>')
else
return ''
end
end
-- item category
function p.getItemCategory(frame)
local args = p.getArgs(frame)
local resolvedNameLower = p.getDisplayedName(frame):lower()
for categoryTitle,categoryData in pairs(p.categoryItems) do
for i2,resolvedItemName in ipairs(categoryData) do
if resolvedNameLower == resolvedItemName:lower() then
return categoryTitle
end
end
end
for i,categoryTitle in ipairs(p.categoryWords) do
if resolvedNameLower:find(categoryTitle:lower(), 1, true) then
return categoryTitle
end
end
return false
end
-- item part utility
function p.getType(text)
local finds = { "variable", "function", "property", "method", "event", "define" }
local replaces = { "Variable", "Function", "Property", "Method", "Event", "Define" }
local defaults = {}
return p.findText(text, finds, replaces, defaults, "'''undocumented type'''")
end
function p.getGames(text)
local finds = { "iii", "vc", "sa", "iv", "ug" }
local replaces = { "GTA III", "GTA VC", "GTA SA", "GTA IV", "GTA UG" }
local defaults = { "all", "all games" }
return p.findText(text, finds, replaces, defaults, "All Games")
end
function p.getEndpoint(text)
local finds = { "shared", "server", "client" }
local replaces = { "Server and Client", "Server Only", "Client Only" }
local defaults = {}
local result = p.findText(text, finds, replaces, defaults, "'''undocumented endpoint'''")
local isShared = result == replaces[1]
return result, isShared
end
function p.getDisplayedName(frame)
local args = p.getArgs(frame)
if p.isOOP(frame) then
return args.class:lower().."."..args.name
else
return args.name
end
end
function p.getSuccessReturnTypes(frame)
local entries = p.getIndexedArgs(frame, 'return')
if #entries == 0 then
return "unknown"
end
for i,entry in ipairs(entries) do
local tokens = p.split(entry, ' ')
entries[i] = tokens[1]
end
return table.concat(entries, ", ")
end
function p.isOOP(frame)
local args = p.getArgs(frame)
return args.type == "property" or args.type == "method"
end
function p.warning(frame, text)
return p.loadTemplate(frame, 'BlueInformationBox', {text})..'\n'
end
function p.documentationMissing(frame, text)
return p.warning(frame, "Documentation Missing: "..text)
end
function p.buildSyntax(frame, parameters, isCallback)
if isCallback == nil then
isCallback = false;
end
local args = p.getArgs(frame)
if not isCallback and (args.type == 'variable' or args.type == 'property') then
return p.getSuccessReturnTypes(frame).." "..p.getDisplayedName(frame)
elseif isCallback or args.type == 'event' then
return "function("..parameters..")"
else
return p.getSuccessReturnTypes(frame).." "..p.getDisplayedName(frame).."("..parameters..")"
end
end
function p.getDerivedClassesText(frame, baseType)
local args = p.getArgs(frame)
local derivedTypes = {
ped = {'Civilian', 'Player'},
physical = {'Object', 'Ped', 'Vehicle', 'Civilian', 'Player'},
entity = {'Building', 'Physical', 'Object', 'Ped', 'Vehicle', 'Civilian', 'Player'},
transformable = {'Blip', 'Entity', 'Marker', 'Building', 'Physical', 'Object', 'Ped', 'Vehicle', 'Civilian', 'Player'},
element = {'Transformable', 'Blip', 'Entity', 'Marker', 'Building', 'Physical', 'Object', 'Ped', 'Vehicle', 'Civilian', 'Player'}
}
local serverTypes = {
'World', 'Train'
}
local sharedTypes = {
'Client', 'Effect', 'Event', 'Font', 'Timer', 'ReflectedFunction', 'Resource', 'Stream', 'Vec2', 'Vec3', 'Matrix4x4',
'Element', 'Transformable', 'Blip', 'Pickup', 'Entity', 'Physical','Vehicle'
}
local out = {}
local line1 = "The <span style=\"font-family: 'Source Code Pro', monospace;\">"..p.getDisplayedName(frame).."</span> "..args.type.." is used "
if args.type == 'variable' or args.type == 'function' then
line1 = line1.."globally."
elseif args.type == 'property' or args.type == 'method' then
line1 = line1.."via OOP."
elseif args.type == 'event' then
line1 = line1.."via the observer pattern. [https://wiki.gtaconnected.com/HowTo/Events Read more.]"
end
table.insert(out, line1)
table.insert(out, "<div style='margin-top: 20px;'></div>")
local getTypeSide = function(type)
for i2,type2 in ipairs(serverTypes) do
if type:lower() == type2:lower() then
return 'server'
end
end
for i2,type2 in ipairs(sharedTypes) do
if type:lower() == type2:lower() then
return 'shared'
end
end
return 'client'
end
if args.type ~= 'event' then
local baseTypeLower = baseType:lower()
local allTypes = p.copyTable(derivedTypes[baseTypeLower] and derivedTypes[baseTypeLower] or { baseType })
local types = {}
for i,type in ipairs(allTypes) do
types[i] = type
end
p.sortTable(types)
for i,type in ipairs(types) do
types[i] = p.loadTemplate(frame, 'Side', {[getTypeSide(type)]='1'}).." "..type
end
table.insert(out, table.concat(types, ""))
local parts = p.split(p.getDisplayedName(frame), ".")
local rows = {}
if args.type == 'variable' or args.type == 'function' then
for i=1,(#parts)-1,1 do
rows[i] = { "<span style=\"font-family: 'Source Code Pro', monospace;\">"..p.properCase(parts[i]).."</span>", "namespace" }
end
rows[#parts] = { "<span style=\"font-family: 'Source Code Pro', monospace;\">"..parts[#parts].."</span>", p.properCase(args.type) }
elseif args.type == 'property' or args.type == 'method' then
rows[1] = { "<span style=\"font-family: 'Source Code Pro', monospace;\">"..p.properCase(parts[1]).."</span>", "Object (JS Object, Lua Userdata, Squirrel Userdata)" }
rows[2] = { "<span style=\"font-family: 'Source Code Pro', monospace;\">"..parts[2].."</span>", p.properCase(args.type) }
end
if #rows > 0 then
table.insert(out, p.table(false, rows, { 80, 400 }, false))
end
end
return table.concat(out, "<br>\n")
end
function p.isCancellable(frame)
local args = p.getArgs(frame)
return (args.cancellable and args.cancellable == 'true') or (args.cancelable and args.cancelable == 'true')
end
function p.formatType(type, frame)
return p.formatSource(type, frame)
end
function p.formatSource(type, frame)
return frame:preprocess('<source>'..type..'</source>')
end
function p.formatCode(code)
return "<code>"..code.."</code>"
end
function p.formatDescription(description)
description = p.capital(description)
description = p.dot(description)
return description
end
function p.standardizeNullType(type)
type = type:lower()
if type == 'void' or type == 'null' or type == 'undefined' or type == 'n/a' then
return 'void'
else
return type
end
end
-- general utility
function p.split(str, sep, limit)
if not sep or sep == "" then
return false
end
if not str then
return false
end
limit = limit or math.huge
if limit == 0 or limit == 1 then
return {str}, 1
end
local r = {}
local n, init = 0, 1
while true do
local s,e = str:find(sep, init, true)
if not s then
break
end
r[#r+1] = str:sub(init, s - 1)
init = e + 1
n = n + 1
if n == limit - 1 then
break
end
end
if init <= str:len() then
r[#r+1] = str:sub(init)
else
r[#r+1] = ""
end
n = n + 1
if limit < 0 then
for i=n, n + limit + 1, -1 do r[i] = nil end
n = n + limit
end
return r, n
end
function p.splitLines(text)
text = p.remove(text, "\n")
text = p.remove(text, "\r")
return p.split(text, "<br>")
end
function p.remove(text, remove)
return p.replace(text, remove, "")
end
function p.replace(text, find, replace)
return text:gsub(find, replace)
end
function p.getIndexedArgs(frame, name)
local args = p.getArgs(frame)
local i = 1
local out = {}
while args[name..i] do
out[i] = args[name..i]
i = i + 1
end
return out
end
function p.loadTemplate(frame, title, args)
return frame:expandTemplate{ title = title, args = args }
end
function p.getEndpointVersions(arg, endpoint, start)
if not start then start = 1 end
local tokens = p.split(arg, ' ')
local endpointVersions = {}
if endpoint == 'shared' then
if tokens[start+1] then
endpointVersions[1] = tokens[start]
endpointVersions[2] = tokens[start+1]
else
endpointVersions[1] = tokens[start]
end
elseif endpoint == 'server' then
endpointVersions[1] = tokens[start]
elseif endpoint == 'client' then
endpointVersions[1] = tokens[start]
end
return endpointVersions, tokens
end
function p.getVersionsText(arg, endpoint, start)
if not start then start = 1 end
local tokens = p.split(arg, ' ')
local text
if endpoint == 'shared' then
if tokens[start+1] then
text = "server version "..tokens[start].." and client version "..tokens[start+1]
else
text = "version "..tokens[start]
end
elseif endpoint == 'server' then
text = "server version "..tokens[start]
elseif endpoint == 'client' then
text = "client version "..tokens[start]
end
return text, tokens
end
function p.properCase(text)
return text:sub(1,1):upper()..text:sub(2):lower()
end
function p.findText(text, finds, replaces, defaults, default)
if not text then return default end
local textLower = text:lower()
for i,default2 in ipairs(defaults) do
if textLower == default2 then
return default
end
end
local items = {}
for i,find in ipairs(finds) do
if textLower:find(find, 1, true) then
table.insert(items, replaces[i])
end
end
return p.getListText(items)
end
function p.getListText(items)
local count = #items
if count == 1 then
return items[1]
elseif count == 2 then
return items[1].." and "..items[2]
else
return table.concat(items, ", ", 1, count - 1).." and "..items[count]
end
end
function p.dot(text)
local i = #text
while i > 0 and text:sub(i, i) == "." do
i = i - 1
end
return text:sub(1,i).."."
end
function p.capital(text)
return text:sub(1,1):upper()..text:sub(2)
end
function p.copyTable(t)
local out = {}
for k,v in pairs(t) do
out[k] = v
end
return out
end
function p.sortTable(t)
table.sort(t, function(a,b)
return a:lower() < b:lower()
end)
end
function p.table(headers, rows, widths, tableCssClass)
if tableCssClass == nil then tableCssClass = 'wikitable' end
rows = p.copyTable(rows)
if not widths then widths = {} end
if headers then
headers = p.copyTable(headers)
for i,header in ipairs(headers) do
local width = widths[i]
if width and width > 0 then
headers[i] = "id='th_"..i.."' style='text-align:left;"..(i==#headers and 'min-width' or 'width')..":"..width.."px;'| "..header
end
end
else
for i,cell in ipairs(rows[1]) do
local width = widths[i]
if width and width > 0 then
rows[1][i] = "id='td_"..i.."' style='text-align:left;"..(i==#rows[1] and 'min-width' or 'width')..":"..width.."px;'| "..cell
end
end
end
for i,row in ipairs(rows) do
rows[i] = '|'..table.concat(row, '\n|')
end
return '{|'..(tableCssClass and ' class="'..tableCssClass..'"' or '')..(headers and " id='headers' " and '\n!'..table.concat(headers, '\n!')..'\n|-' or '')..'\n'..table.concat(rows, '\n|-\n')..'\n|}'
end
-- return the module
return p