- -- Player Indices
- hashes = {} -- Keeps track of players who have joined this round
- function GetRequiredVersion()
- return 10058
- end
- function OnScriptLoad(process)
- end
- function OnScriptUnload()
- table.save(players, "players.data")
- table.save(indices, "indices.data")
- end
- function OnNewGame(map)
- end
- function OnGameEnd(mode)
- end
- function OnServerChat(player, chattype, message)
- return 1
- end
- function OnServerCommand(admin, command)
- local cmd, args = cmdsplit(command)
- -- Players Commands --
- if cmd == "sv_players" then
- -- Modified version of sv_players which prints players' indices as well as their IDs and names
- hprintf("ID Index Name")
- for i = 0,15 do
- local hash = gethash(i)
- if hash then
- hprintf(resolveplayer(i) .. " " .. players[hash].index .. " " .. getname(i))
- end
- end
- return 0
- elseif cmd == "sv_players_recent" then
- -- Prints indices and names of all players who have joined the server during this game (minus those who are still currently in it)
- hprintf("Index Name")
- for k,v in pairs(hashes) do
- local found
- for i = 0,15 do
- if gethash(i) == k then
- found = true
- break
- end
- end
- if not found then
- hprintf(players[k].index .. " " .. v)
- end
- end
- return 0
- elseif cmd == "sv_players_search" then
- -- Prints a list of players' indices and names matching the name search specified
- local search = args[1]
- local matches = {}
- -- Loop through players table
- for k,v in pairs(players) do
- -- Find matches and organize by priority; more common aliases have higher priority
- for name,v in pairs(v.alias) do
- local val = string.find(string.lower(name), string.lower(search))
- if val then
- table.insert(matches, {["priority"] = val + v, ["hash"] = k})
- end
- end
- end
- -- Sort matches table by priority value
- table.sort(matches, function(a,b) return matches[a].priority > matches[b].priority end)
- if #matches > 0 then
- hprintf("Players matching \"" .. search .. "\":")
- hprintf("Index Name")
- -- Print up to 20 results
- local len = math.min(#matches, 20)
- for i = 1,len do
- hprintf(players[matches[i].hash].index .. " " .. players[matches[i].hash].name)
- end
- end
- return 0
- -- Ban Commands
- elseif cmd == "sv_ban" then
- -- Modified version of sv_ban allowing for Ban on Sight (banning a player via their Index while they aren't in the server puts them on the BOS list). Also added a "name" parameter for those players who should be banned on sight who haven't yet joined the server with this script running (this parameter will be ignored in any other case).
- local id = args[1]
- local duration = args[2] or "-1"
- local name = args[3]
- if not id then
- hprintf("Syntax: sv_ban <Player ID, Hash or Index> <opt: Duration> <opt: BOS Name (for players yet to join server)>")
- return 0
- end
- for i = 0,15 do
- if getname(i) == id then
- return 1
- end
- end
- if string.len(id) < 3 then
- return 1
- end
- if indices[string.upper(id)] then
- local hash = indices[string.upper(id)]
- local player = hashtoplayer(hash)
- if player then
- if duration == "-1" then
- svcmd("sv_ban " .. resolveplayer(player))
- else
- svcmd("sv_ban " .. resolveplayer(player) .. " " .. duration)
- end
- else
- players[hash].bos = duration
- hprintf((hashes[hash] or players[hash].name) .. " will be banned on sight.")
- end
- return 0
- end
- if players[id] then
- players[id].bos = duration
- hprintf((hashes[id] or players[id].name) .. " will be banned on sight.")
- else
- name = name or "???"
- players[id] = {}
- players[id].bos = duration
- players[id].name = name
- end
- elseif cmd == "sv_unban" then
- -- Modified version of sv_unban which allows the ability to unban from a player's Ban ID, Hash, or Index and takes the player off of the Ban on Sight list (even if they haven't been banned yet).
- local id = args[1]
- if not id then
- hprintf("Syntax: sv_unban <Ban ID, Hash or Index>")
- return 0
- end
- local hash
- local dir = getprofilepath()
- local banned = io.string(dir .. "\\banned.txt")
- local lines = string.split(banned, "\n")
- for k,v in ipairs(lines) do
- local split = string.split(v, ",")
- local ban_id = split[1]
- local ban_hash = split[3]
- if tonumber(id) == tonumber(ban_id) then
- players[ban_hash].bos = nil
- return 1
- end
- end
- if indices[string.upper(id)] then
- hash = indices[string.upper(id)]
- elseif players[id] then
- hash = id
- end
- if hash then
- players[hash].bos = nil
- hprintf((hashes[id] or players[hash].name) .. " has been taken off of the Ban on Sight list.")
- for k,v in ipairs(lines) do
- local split = string.split(v, ",")
- local ban_id = split[1]
- local ban_hash = split[3]
- if hash == ban_hash then
- svcmd("sv_unban " .. ban_id)
- return 0
- end
- end
- else
- hprintf("Invalid Player.")
- end
- elseif cmd == "sv_bos_list" then
- -- Lists all players on the Ban on Sight list
- hprintf("Players to be banned on sight (-1 duration specifies an indefinite ban):")
- for k,v in pairs(players) do
- if players[k].bos then
- hprintf(players[k].index .. " " .. (hashes[k] or players[k].name) .. " " .. players[k].bos)
- end
- end
- return 0
- -- Alias
- elseif cmd == "sv_alias" then
- -- Modified version of sv_alias which allows the ability to view a player's aliases by their Player ID, Hash or Index. This does not include aliases previously saved by Phasor; the new version of Phasor will hopefully have a way to access the alias database via scripts. Once that happens, I'll be able to add the aliases Phasor has stored into this command as well.
- local id = args[1]
- if not id then
- hprintf("Syntax: sv_alias <Player ID, Hash or Index>")
- return 0
- end
- local hash
- if string.len(id) < 3 then
- local player = rresolveplayer(tonumber(id))
- hash = gethash(player)
- elseif indices[string.upper(id)] then
- hash = indices[string.upper(id)]
- elseif players[id] then
- hash = id
- end
- if hash then
- local aliases = {}
- for k,v in pairs(players[hash].alias) do
- table.insert(aliases, k)
- end
- table.sort(aliases, function(a,b) return players[hash].alias[a] > players[hash].alias[b] end)
- for k,v in ipairs(aliases) do
- aliases[k] = "[" .. players[hash].alias[v] .. "]: " .. aliases[k]
- end
- local str = formatlist(aliases, " ", 4)
- hprintf("Aliases for player " .. players[hash].index .. " sorted by most common alias:")
- hprintf(str)
- return 0
- else
- hprintf("Invalid Player.")
- return 0
- end
- -- Admin Commands
- elseif cmd == "sv_admin_add" then
- -- Modified version of sv_admin_add which allows the ability to add admins with their Player ID, Hash or Index. sv_admin_del does not need Index support because you can pull up the list of admins with sv_admin_list.
- local id = args[1]
- local name = args[2]
- local level = args[3]
- if not id then
- hprintf("Syntax: sv_admin_add <Player ID, Hash or Index> <Authentication Name> <Level>")
- return 0
- end
- local hash
- if string.len(id) < 3 then
- local player = rresolveplayer(tonumber(id))
- hash = gethash(player)
- elseif indices[string.upper(id)] then
- hash = indices[string.upper(id)]
- elseif players[id] then
- return 1
- else
- players[id] = {}
- players[id].name = name or "???"
- hash = id
- end
- if hash then
- if name and level then
- svcmd("sv_admin_add " .. hash .. " " .. name .. " " .. level)
- elseif name and not level then
- svcmd("sv_admin_add " .. hash .. " " .. name)
- elseif not name and not level then
- svcmd("sv_admin_add " .. hash)
- end
- end
- return 0
- elseif cmd == "sv_commands" then
- registertimer(1, "DelayPrint")
- end
- return 1
- end
- function DelayPrint(id, count)
- hprintf("sv_players_recent sv_players_search sv_bos_list")
- return 0
- end
- function OnTeamDecision(team)
- return team
- end
- function OnPlayerJoin(player, team)
- local hash = gethash(player)
- updatePlayer(hash)
- hashes[hash] = getname(player)
- end
- function OnPlayerLeave(player, team)
- end
- function OnPlayerKill(killer, victim, mode)
- end
- function OnKillMultiplier(player, multiplier)
- end
- function OnPlayerSpawn(player, m_objId)
- end
- function OnPlayerSpawnEnd(player, m_objId)
- end
- function OnTeamChange(relevant, player, cur_team, dest_team)
- return 1
- end
- function OnObjectCreation(m_objId, player, tagName)
- end
- function OnObjectInteraction(player, m_objId, tagType, tagName)
- return 1
- end
- function OnWeaponAssignment(player, m_objId, slot, tagName)
- return 0
- end
- function OnWeaponReload(player, m_weapId)
- return 1
- end
- function OnDamageLookup(receiver, causer, tagData, tagName)
- end
- function OnVehicleEntry(relevant, player, m_vehicleId, tagName, seat)
- return 1
- end
- function OnVehicleEject(player, forced)
- return 1
- end
- function OnClientUpdate(player, m_objId)
- end
- math.inf = 1 / 0
- function table.save(t, filename)
- local dir = getprofilepath()
- local file = io.open(dir .. "\\data\\" .. filename, "w")
- local spaces = 0
- local function tab()
- local str = ""
- for i = 1,spaces do
- str = str .. " "
- end
- return str
- end
- local function format(t)
- spaces = spaces + 4
- local str = "{ "
- for k,v in pairs(t) do
- -- Key datatypes
- if type(k) == "string" then
- k = string.format("%q", k)
- end
- -- Value datatypes
- if type(v) == "string" then
- v = string.format("%q", v)
- elseif v == math.inf then
- v = "1 / 0"
- end
- if type(v) == "table" then
- if table.len(v) > 0 then
- str = str .. "\n" .. tab() .. "[" .. k .. "] = " .. format(v) .. ","
- else
- str = str .. "\n" .. tab() .. "[" .. k .. "] = {},"
- end
- else
- str = str .. "\n" .. tab() .. "[" .. k .. "] = " .. tostring(v) .. ","
- end
- end
- spaces = spaces - 4
- return string.sub(str, 1, string.len(str) - 1) .. "\n" .. tab() .. "}"
- end
- file:write("return " .. format(t))
- file:close()
- end
- function table.load(filename)
- local dir = getprofilepath()
- local file = loadfile(dir .. "\\data\\" .. filename)
- if file then
- return file()
- end
- return {}
- end
- function table.len(t)
- local count = 0
- for k,v in pairs(t) do
- count = count + 1
- end
- return count
- end
- function table.max(t)
- local key
- local max = -math.inf
- for k,v in pairs(t) do
- v = tonumber(v)
- if v then
- if v > max then
- key = k
- max = v
- end
- end
- end
- return key, max
- end
- players = table.load("players.data")
- indices = table.load("indices.data")
- function hashtoplayer(hash)
- for i = 0,15 do
- if gethash(i) then return i end
- end
- end
- function updatePlayer(hash, name)
- local player = hashtoplayer(hash)
- local name = name or getname(player)
- players[hash] = players[hash] or {}
- -- Name
- players[hash].alias = players[hash].alias or {}
- players[hash].alias[name] = (players[hash].alias[name] or 0) + 1
- players[hash].name = players[hash].name or table.max(players[hash].alias)
- -- Index
- players[hash].index = players[hash].index or newIndex(hash)
- -- Check if the player should be banned on sight
- if players[hash].bos then
- if players[hash].bos == "-1" then
- svcmd("sv_ban " .. resolveplayer(player))
- else
- svcmd("sv_ban " .. resolveplayer(player) .. " " .. players[hash].bos)
- end
- players[hash].bos = nil
- end
- end
- function newIndex(hash)
- indices.unique = (indices.unique or 0) + 1
- local index
- repeat
- index = convertbase((indices.next or 0), 36)
- while string.len(index) < 3 do
- index = "0" .. index
- end
- indices.next = (indices.next or 0) + 1
- until validIndex(index)
- indices[index] = hash
- return index
- end
- function validIndex(entry)
- local invalid = {"red", "blue", "all", "me"}
- for _,v in ipairs(invalid) do
- if string.lower(entry) == v then
- return false
- end
- end
- return true
- end
- function convertbase(input, base)
- if not base or base == 10 then return tostring(input) end
- local digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- local answer = {}
- repeat
- local digit = (input % base) + 1
- input = math.floor(input / base)
- table.insert(answer, 1, string.sub(digits, digit, digit))
- until input == 0
- return table.concat(answer, "")
- end
- function string.split(str, ...)
- for k,v in ipairs(arg) do
- if v == "" then
- local subs = {}
- for i = 1,string.len(str) do
- table.insert(subs, string.sub(str, i, i))
- end
- return subs
- end
- end
- local subs = {}
- local sub = ""
- for i = 1,string.len(str) do
- local bool
- local char = string.sub(str, i, i)
- for k,v in ipairs(arg) do
- local delim = string.sub(str, i - (string.len(v) - 1), i)
- if v == delim then
- bool = true
- sub = string.sub(sub, 1, string.len(sub) - (string.len(v) - 1))
- if sub ~= "" then
- table.insert(subs, sub)
- end
- sub = ""
- break
- end
- end
- if not bool then
- sub = sub .. char
- end
- if i == string.len(str) then
- table.insert(subs, sub)
- end
- end
- return subs
- end
- function cmdsplit(str)
- local subs = {}
- local sub = ""
- local ignore_quote, inquote, endquote
- for i = 1,string.len(str) do
- local bool
- local char = string.sub(str, i, i)
- if char == " " then
- if (inquote and endquote) or (not inquote and not endquote) then
- bool = true
- end
- elseif char == "\\" then
- ignore_quote = true
- elseif char == "\"" then
- if not ignore_quote then
- if not inquote then
- inquote = true
- else
- endquote = true
- end
- end
- end
- if char ~= "\\" then
- ignore_quote = false
- end
- if bool then
- if inquote and endquote then
- sub = string.sub(sub, 2, string.len(sub) - 1)
- end
- if sub ~= "" then
- table.insert(subs, sub)
- end
- sub = ""
- inquote = false
- endquote = false
- else
- sub = sub .. char
- end
- if i == string.len(str) then
- if string.sub(sub, 1, 1) == "\"" and string.sub(sub, string.len(sub), string.len(sub)) == "\"" then
- sub = string.sub(sub, 2, string.len(sub) - 1)
- end
- table.insert(subs, sub)
- end
- end
- local cmd = subs[1]
- local args = subs
- table.remove(args, 1)
- return cmd, args
- end
- function formatlist(t, delim, length)
- local str = ""
- for k,v in ipairs(t) do
- if k % length == 0 then
- str = str .. v .. "\n"
- else
- str = str .. v .. delim
- end
- end
- return str
- end
- function io.string(filename)
- local str
- local file = io.open(filename, "a+")
- if file then
- str = file:read("*all")
- end
- file:close()
- return str
- end
Recent Pastes