add playernames resource

This commit is contained in:
moscovium
2017-10-14 19:43:49 +02:00
parent 012a40d52d
commit 6d8bf9642b
6 changed files with 844 additions and 0 deletions

View File

@@ -0,0 +1,27 @@
-- add scripts
client_script 'playernames_api.lua'
server_script 'playernames_api.lua'
client_script 'playernames_cl.lua'
server_script 'playernames_sv.lua'
-- make exports
local exportList = {
'setComponentColor',
'setComponentAlpha',
'setComponentVisibility',
'setWantedLevel',
'setHealthBarColor',
'setNameTemplate'
}
exports(exportList)
server_exports(exportList)
-- add files
files {
'template/template.lua'
}
-- support the latest resource manifest
resource_manifest_version '05cfa83c-a124-4cfa-a768-c24a5811d8f9'

View File

@@ -0,0 +1,80 @@
local ids = {}
local function getTriggerFunction(key)
return function(id, ...)
-- if on the client, it's easy
if not IsDuplicityVersion() then
TriggerEvent('playernames:configure', GetPlayerServerId(id), key, ...)
else
-- if on the server, save configuration
if not ids[id] then
ids[id] = {}
end
-- save the setting
ids[id][key] = table.pack(...)
-- broadcast to clients
TriggerClientEvent('playernames:configure', -1, id, key, ...)
end
end
end
if IsDuplicityVersion() then
function reconfigure(source)
for id, data in pairs(ids) do
for key, args in pairs(data) do
TriggerClientEvent('playernames:configure', source, id, key, table.unpack(args))
end
end
end
AddEventHandler('playerDropped', function()
ids[source] = nil
end)
end
setComponentColor = getTriggerFunction('setc')
setComponentAlpha = getTriggerFunction('seta')
setComponentVisibility = getTriggerFunction('tglc')
setWantedLevel = getTriggerFunction('setw')
setHealthBarColor = getTriggerFunction('sehc')
setNameTemplate = getTriggerFunction('tpl')
setName = getTriggerFunction('name')
if not io then
io = { write = nil, open = nil }
end
local template = load(LoadResourceFile(GetCurrentResourceName(), 'template/template.lua'))()
function formatPlayerNameTag(i, templateStr)
--return ('%s <%d>'):format(GetPlayerName(i), GetPlayerServerId(i))
local str = ''
template.print = function(txt)
str = str .. txt
end
local context = {
name = GetPlayerName(i),
i = i,
global = _G
}
if IsDuplicityVersion() then
context.id = i
else
context.id = GetPlayerServerId(i)
end
TriggerEvent('playernames:extendContext', i, function(k, v)
context[k] = v
end)
template.render(templateStr, context, nil, true)
template.print = print
return str
end

View File

@@ -0,0 +1,196 @@
local mpGamerTags = {}
local mpGamerTagSettings = {}
local gtComponent = {
GAMER_NAME = 0,
CREW_TAG = 1,
healthArmour = 2,
BIG_TEXT = 3,
AUDIO_ICON = 4,
MP_USING_MENU = 5,
MP_PASSIVE_MODE = 6,
WANTED_STARS = 7,
MP_DRIVER = 8,
MP_CO_DRIVER = 9,
MP_TAGGED = 10,
GAMER_NAME_NEARBY = 11,
ARROW = 12,
MP_PACKAGES = 13,
INV_IF_PED_FOLLOWING = 14,
RANK_TEXT = 15,
MP_TYPING = 16
}
local function makeSettings()
return {
alphas = {},
colors = {},
healthColor = false,
toggles = {},
wantedLevel = false
}
end
local templateStr
function updatePlayerNames()
-- re-run this function the next frame
SetTimeout(0, updatePlayerNames)
-- return if no template string is set
if not templateStr then
return
end
-- get local coordinates to compare to
local localCoords = GetEntityCoords(PlayerPedId())
-- for each valid player index
for i = 0, 255 do
-- if the player exists
if NetworkIsPlayerActive(i) and i ~= PlayerId() then
-- get their ped
local ped = GetPlayerPed(i)
local pedCoords = GetEntityCoords(ped)
-- make a new settings list if needed
if not mpGamerTagSettings[i] then
mpGamerTagSettings[i] = makeSettings()
end
-- check the ped, because changing player models may recreate the ped
-- also check gamer tag activity in case the game deleted the gamer tag
if not mpGamerTags[i] or mpGamerTags[i].ped ~= ped or not IsMpGamerTagActive(mpGamerTags[i].tag) then
local nameTag = formatPlayerNameTag(i, templateStr)
-- remove any existing tag
if mpGamerTags[i] then
RemoveMpGamerTag(mpGamerTags[i].tag)
end
-- store the new tag
mpGamerTags[i] = {
tag = CreateMpGamerTag(GetPlayerPed(i), nameTag, false, false, '', 0),
ped = ped
}
end
-- store the tag in a local
local tag = mpGamerTags[i].tag
-- should the player be renamed? this is set by events
if mpGamerTagSettings[i].rename then
SetMpGamerTagName(tag, formatPlayerNameTag(i, templateStr))
mpGamerTagSettings[i].rename = nil
end
-- check distance
local distance = #(pedCoords - localCoords)
-- show/hide based on nearbyness/line-of-sight
-- nearby checks are primarily to prevent a lot of LOS checks
if distance < 250 and HasEntityClearLosToEntity(PlayerPedId(), ped, 17) then
SetMpGamerTagVisibility(tag, gtComponent.GAMER_NAME, true)
SetMpGamerTagVisibility(tag, gtComponent.healthArmour, IsPlayerTargettingEntity(PlayerId(), ped))
SetMpGamerTagVisibility(tag, gtComponent.AUDIO_ICON, NetworkIsPlayerTalking(i))
SetMpGamerTagAlpha(tag, gtComponent.AUDIO_ICON, 255)
SetMpGamerTagAlpha(tag, gtComponent.healthArmour, 255)
-- override settings
local settings = mpGamerTagSettings[i]
for k, v in pairs(settings.toggles) do
SetMpGamerTagVisibility(tag, gtComponent[k], v)
end
for k, v in pairs(settings.alphas) do
SetMpGamerTagAlpha(tag, gtComponent[k], v)
end
for k, v in pairs(settings.colors) do
SetMpGamerTagColour(tag, gtComponent[k], v)
end
if settings.wantedLevel then
SetMpGamerTagWantedLevel(tag, settings.wantedLevel)
end
if settings.healthColor then
SetMpGamerTagHealthBarColour(tag, settings.healthColor)
end
else
SetMpGamerTagVisibility(tag, gtComponent.GAMER_NAME, false)
SetMpGamerTagVisibility(tag, gtComponent.healthArmour, false)
SetMpGamerTagVisibility(tag, gtComponent.AUDIO_ICON, false)
end
elseif mpGamerTags[i] then
RemoveMpGamerTag(mpGamerTags[i].tag)
mpGamerTags[i] = nil
end
end
end
local function getSettings(id)
local i = GetPlayerFromServerId(tonumber(id))
if not mpGamerTagSettings[i] then
mpGamerTagSettings[i] = makeSettings()
end
return mpGamerTagSettings[i]
end
RegisterNetEvent('playernames:configure')
AddEventHandler('playernames:configure', function(id, key, ...)
local args = table.pack(...)
if key == 'tglc' then
getSettings(id).toggles[args[1]] = args[2]
elseif key == 'seta' then
getSettings(id).alphas[args[1]] = args[2]
elseif key == 'setc' then
getSettings(id).colors[args[1]] = args[2]
elseif key == 'setw' then
getSettings(id).wantedLevel = args[1]
elseif key == 'sehc' then
getSettings(id).healthColor = args[1]
elseif key == 'rnme' then
getSettings(id).rename = true
elseif key == 'name' then
print(id, 'id')
print(getSettings(id))
getSettings(id).serverName = args[1]
getSettings(id).rename = true
elseif key == 'tpl' then
for _, v in pairs(mpGamerTagSettings) do
v.rename = true
end
templateStr = args[1]
end
end)
AddEventHandler('playernames:extendContext', function(i, cb)
print(getSettings(GetPlayerServerId(i)))
cb('serverName', getSettings(GetPlayerServerId(i)).serverName)
end)
AddEventHandler('onResourceStop', function(name)
if name == GetCurrentResourceName() then
for _, v in pairs(mpGamerTags) do
RemoveMpGamerTag(v.tag)
end
end
end)
SetTimeout(0, function()
TriggerServerEvent('playernames:init')
end)
-- run this function every frame
SetTimeout(0, updatePlayerNames)

View File

@@ -0,0 +1,36 @@
local curTemplate
local curTags = {}
local function detectUpdates()
SetTimeout(500, detectUpdates)
local template = GetConvar('playerNames_template', '[{{id}}] {{name}}')
if curTemplate ~= template then
setNameTemplate(-1, template)
curTemplate = template
end
template = GetConvar('playerNames_svTemplate', '[{{id}}] {{name}}')
for _, v in ipairs(GetPlayers()) do
local newTag = formatPlayerNameTag(v, template)
if newTag ~= curTags[v] then
setName(v, newTag)
curTags[v] = newTag
end
end
end
RegisterNetEvent('playernames:init')
AddEventHandler('playernames:init', function()
reconfigure(source)
end)
SetTimeout(500, detectUpdates)
detectUpdates()

View File

@@ -0,0 +1,27 @@
Copyright (c) 2014 - 2017 Aapo Talvensaari
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
* Neither the name of the {organization} nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,478 @@
local setmetatable = setmetatable
local loadstring = loadstring
local loadchunk
local tostring = tostring
local setfenv = setfenv
local require = require
local capture
local concat = table.concat
local assert = assert
local prefix
local write = io.write
local pcall = pcall
local phase
local open = io.open
local load = load
local type = type
local dump = string.dump
local find = string.find
local gsub = string.gsub
local byte = string.byte
local null
local sub = string.sub
local ngx = ngx
local jit = jit
local var
local _VERSION = _VERSION
local _ENV = _ENV
local _G = _G
local HTML_ENTITIES = {
["&"] = "&amp;",
["<"] = "&lt;",
[">"] = "&gt;",
['"'] = "&quot;",
["'"] = "&#39;",
["/"] = "&#47;"
}
local CODE_ENTITIES = {
["{"] = "&#123;",
["}"] = "&#125;",
["&"] = "&amp;",
["<"] = "&lt;",
[">"] = "&gt;",
['"'] = "&quot;",
["'"] = "&#39;",
["/"] = "&#47;"
}
local VAR_PHASES
local ok, newtab = pcall(require, "table.new")
if not ok then newtab = function() return {} end end
local caching = true
local template = newtab(0, 12)
template._VERSION = "1.9"
template.cache = {}
local function enabled(val)
if val == nil then return true end
return val == true or (val == "1" or val == "true" or val == "on")
end
local function trim(s)
return gsub(gsub(s, "^%s+", ""), "%s+$", "")
end
local function rpos(view, s)
while s > 0 do
local c = sub(view, s, s)
if c == " " or c == "\t" or c == "\0" or c == "\x0B" then
s = s - 1
else
break
end
end
return s
end
local function escaped(view, s)
if s > 1 and sub(view, s - 1, s - 1) == "\\" then
if s > 2 and sub(view, s - 2, s - 2) == "\\" then
return false, 1
else
return true, 1
end
end
return false, 0
end
local function readfile(path)
local file = open(path, "rb")
if not file then return nil end
local content = file:read "*a"
file:close()
return content
end
local function loadlua(path)
return readfile(path) or path
end
local function loadngx(path)
local vars = VAR_PHASES[phase()]
local file, location = path, vars and var.template_location
if sub(file, 1) == "/" then file = sub(file, 2) end
if location and location ~= "" then
if sub(location, -1) == "/" then location = sub(location, 1, -2) end
local res = capture(concat{ location, '/', file})
if res.status == 200 then return res.body end
end
local root = vars and (var.template_root or var.document_root) or prefix
if sub(root, -1) == "/" then root = sub(root, 1, -2) end
return readfile(concat{ root, "/", file }) or path
end
do
if ngx then
VAR_PHASES = {
set = true,
rewrite = true,
access = true,
content = true,
header_filter = true,
body_filter = true,
log = true
}
template.print = ngx.print or write
template.load = loadngx
prefix, var, capture, null, phase = ngx.config.prefix(), ngx.var, ngx.location.capture, ngx.null, ngx.get_phase
if VAR_PHASES[phase()] then
caching = enabled(var.template_cache)
end
else
template.print = write
template.load = loadlua
end
if _VERSION == "Lua 5.1" then
local context = { __index = function(t, k)
return t.context[k] or t.template[k] or _G[k]
end }
if jit then
loadchunk = function(view)
return assert(load(view, nil, nil, setmetatable({ template = template }, context)))
end
else
loadchunk = function(view)
local func = assert(loadstring(view))
setfenv(func, setmetatable({ template = template }, context))
return func
end
end
else
local context = { __index = function(t, k)
return t.context[k] or t.template[k] or _ENV[k]
end }
loadchunk = function(view)
return assert(load(view, nil, nil, setmetatable({ template = template }, context)))
end
end
end
function template.caching(enable)
if enable ~= nil then caching = enable == true end
return caching
end
function template.output(s)
if s == nil or s == null then return "" end
if type(s) == "function" then return template.output(s()) end
return tostring(s)
end
function template.escape(s, c)
if type(s) == "string" then
if c then return gsub(s, "[}{\">/<'&]", CODE_ENTITIES) end
return gsub(s, "[\">/<'&]", HTML_ENTITIES)
end
return template.output(s)
end
function template.new(view, layout)
assert(view, "view was not provided for template.new(view, layout).")
local render, compile = template.render, template.compile
if layout then
if type(layout) == "table" then
return setmetatable({ render = function(self, context)
local context = context or self
context.blocks = context.blocks or {}
context.view = compile(view)(context)
layout.blocks = context.blocks or {}
layout.view = context.view or ""
return layout:render()
end }, { __tostring = function(self)
local context = self
context.blocks = context.blocks or {}
context.view = compile(view)(context)
layout.blocks = context.blocks or {}
layout.view = context.view
return tostring(layout)
end })
else
return setmetatable({ render = function(self, context)
local context = context or self
context.blocks = context.blocks or {}
context.view = compile(view)(context)
return render(layout, context)
end }, { __tostring = function(self)
local context = self
context.blocks = context.blocks or {}
context.view = compile(view)(context)
return compile(layout)(context)
end })
end
end
return setmetatable({ render = function(self, context)
return render(view, context or self)
end }, { __tostring = function(self)
return compile(view)(self)
end })
end
function template.precompile(view, path, strip)
local chunk = dump(template.compile(view), strip ~= false)
if path then
local file = open(path, "wb")
file:write(chunk)
file:close()
end
return chunk
end
function template.compile(view, key, plain)
assert(view, "view was not provided for template.compile(view, key, plain).")
if key == "no-cache" then
return loadchunk(template.parse(view, plain)), false
end
key = key or view
local cache = template.cache
if cache[key] then return cache[key], true end
local func = loadchunk(template.parse(view, plain))
if caching then cache[key] = func end
return func, false
end
function template.parse(view, plain)
assert(view, "view was not provided for template.parse(view, plain).")
if not plain then
view = template.load(view)
if byte(view, 1, 1) == 27 then return view end
end
local j = 2
local c = {[[
context=... or {}
local function include(v, c) return template.compile(v)(c or context) end
local ___,blocks,layout={},blocks or {}
]] }
local i, s = 1, find(view, "{", 1, true)
while s do
local t, p = sub(view, s + 1, s + 1), s + 2
if t == "{" then
local e = find(view, "}}", p, true)
if e then
local z, w = escaped(view, s)
if i < s - w then
c[j] = "___[#___+1]=[=[\n"
c[j+1] = sub(view, i, s - 1 - w)
c[j+2] = "]=]\n"
j=j+3
end
if z then
i = s
else
c[j] = "___[#___+1]=template.escape("
c[j+1] = trim(sub(view, p, e - 1))
c[j+2] = ")\n"
j=j+3
s, i = e + 1, e + 2
end
end
elseif t == "*" then
local e = find(view, "*}", p, true)
if e then
local z, w = escaped(view, s)
if i < s - w then
c[j] = "___[#___+1]=[=[\n"
c[j+1] = sub(view, i, s - 1 - w)
c[j+2] = "]=]\n"
j=j+3
end
if z then
i = s
else
c[j] = "___[#___+1]=template.output("
c[j+1] = trim(sub(view, p, e - 1))
c[j+2] = ")\n"
j=j+3
s, i = e + 1, e + 2
end
end
elseif t == "%" then
local e = find(view, "%}", p, true)
if e then
local z, w = escaped(view, s)
if z then
if i < s - w then
c[j] = "___[#___+1]=[=[\n"
c[j+1] = sub(view, i, s - 1 - w)
c[j+2] = "]=]\n"
j=j+3
end
i = s
else
local n = e + 2
if sub(view, n, n) == "\n" then
n = n + 1
end
local r = rpos(view, s - 1)
if i <= r then
c[j] = "___[#___+1]=[=[\n"
c[j+1] = sub(view, i, r)
c[j+2] = "]=]\n"
j=j+3
end
c[j] = trim(sub(view, p, e - 1))
c[j+1] = "\n"
j=j+2
s, i = n - 1, n
end
end
elseif t == "(" then
local e = find(view, ")}", p, true)
if e then
local z, w = escaped(view, s)
if i < s - w then
c[j] = "___[#___+1]=[=[\n"
c[j+1] = sub(view, i, s - 1 - w)
c[j+2] = "]=]\n"
j=j+3
end
if z then
i = s
else
local f = sub(view, p, e - 1)
local x = find(f, ",", 2, true)
if x then
c[j] = "___[#___+1]=include([=["
c[j+1] = trim(sub(f, 1, x - 1))
c[j+2] = "]=],"
c[j+3] = trim(sub(f, x + 1))
c[j+4] = ")\n"
j=j+5
else
c[j] = "___[#___+1]=include([=["
c[j+1] = trim(f)
c[j+2] = "]=])\n"
j=j+3
end
s, i = e + 1, e + 2
end
end
elseif t == "[" then
local e = find(view, "]}", p, true)
if e then
local z, w = escaped(view, s)
if i < s - w then
c[j] = "___[#___+1]=[=[\n"
c[j+1] = sub(view, i, s - 1 - w)
c[j+2] = "]=]\n"
j=j+3
end
if z then
i = s
else
c[j] = "___[#___+1]=include("
c[j+1] = trim(sub(view, p, e - 1))
c[j+2] = ")\n"
j=j+3
s, i = e + 1, e + 2
end
end
elseif t == "-" then
local e = find(view, "-}", p, true)
if e then
local x, y = find(view, sub(view, s, e + 1), e + 2, true)
if x then
local z, w = escaped(view, s)
if z then
if i < s - w then
c[j] = "___[#___+1]=[=[\n"
c[j+1] = sub(view, i, s - 1 - w)
c[j+2] = "]=]\n"
j=j+3
end
i = s
else
y = y + 1
x = x - 1
if sub(view, y, y) == "\n" then
y = y + 1
end
local b = trim(sub(view, p, e - 1))
if b == "verbatim" or b == "raw" then
if i < s - w then
c[j] = "___[#___+1]=[=[\n"
c[j+1] = sub(view, i, s - 1 - w)
c[j+2] = "]=]\n"
j=j+3
end
c[j] = "___[#___+1]=[=["
c[j+1] = sub(view, e + 2, x)
c[j+2] = "]=]\n"
j=j+3
else
if sub(view, x, x) == "\n" then
x = x - 1
end
local r = rpos(view, s - 1)
if i <= r then
c[j] = "___[#___+1]=[=[\n"
c[j+1] = sub(view, i, r)
c[j+2] = "]=]\n"
j=j+3
end
c[j] = 'blocks["'
c[j+1] = b
c[j+2] = '"]=include[=['
c[j+3] = sub(view, e + 2, x)
c[j+4] = "]=]\n"
j=j+5
end
s, i = y - 1, y
end
end
end
elseif t == "#" then
local e = find(view, "#}", p, true)
if e then
local z, w = escaped(view, s)
if i < s - w then
c[j] = "___[#___+1]=[=[\n"
c[j+1] = sub(view, i, s - 1 - w)
c[j+2] = "]=]\n"
j=j+3
end
if z then
i = s
else
e = e + 2
if sub(view, e, e) == "\n" then
e = e + 1
end
s, i = e - 1, e
end
end
end
s = find(view, "{", s + 1, true)
end
s = sub(view, i)
if s and s ~= "" then
c[j] = "___[#___+1]=[=[\n"
c[j+1] = s
c[j+2] = "]=]\n"
j=j+3
end
c[j] = "return layout and include(layout,setmetatable({view=table.concat(___),blocks=blocks},{__index=context})) or table.concat(___)"
return concat(c)
end
function template.render(view, context, key, plain)
assert(view, "view was not provided for template.render(view, context, key, plain).")
return template.print(template.compile(view, key, plain)(context))
end
return template