mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-16 21:33:46 +03:00
Upload
This commit is contained in:
1
gamemodes/helix/plugins/bastion/apikey_proxy.txt.example
Normal file
1
gamemodes/helix/plugins/bastion/apikey_proxy.txt.example
Normal file
@@ -0,0 +1 @@
|
||||
<put https://proxycheck.io proxy key here and remove .example from file name>
|
||||
1
gamemodes/helix/plugins/bastion/apiwebhook_discord.txt
Normal file
1
gamemodes/helix/plugins/bastion/apiwebhook_discord.txt
Normal file
@@ -0,0 +1 @@
|
||||
https://discord.com/api/webhooks/832651486860541973/iYpexHJmA5E6pD6WwUT1GyvLtQ9_8ly-qB0xloIsPu7KmaU0mkQVRE_Kg0qVwGRlwhs_
|
||||
@@ -0,0 +1 @@
|
||||
<put discord webhook URL here and remove .example from filename>
|
||||
152
gamemodes/helix/plugins/bastion/cl_plugin.lua
Normal file
152
gamemodes/helix/plugins/bastion/cl_plugin.lua
Normal file
@@ -0,0 +1,152 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
local CAMI = CAMI
|
||||
local LocalPlayer = LocalPlayer
|
||||
local L = L
|
||||
local SetClipboardText = SetClipboardText
|
||||
local chat = chat
|
||||
local net = net
|
||||
local table = table
|
||||
local string = string
|
||||
local tonumber = tonumber
|
||||
local render = render
|
||||
local Color = Color
|
||||
local gui = gui
|
||||
local hook = hook
|
||||
local surface = surface
|
||||
local netstream = netstream
|
||||
local ipairs = ipairs
|
||||
local MsgN = MsgN
|
||||
local ix = ix
|
||||
|
||||
local PLUGIN = PLUGIN
|
||||
|
||||
PLUGIN.infoIcon = ix.util.GetMaterial("icon16/information.png")
|
||||
|
||||
ix.option.Add("staffChat", ix.type.bool, true, {
|
||||
category = "Administration",
|
||||
hidden = function()
|
||||
return !CAMI.PlayerHasAccess(LocalPlayer(), "Helix - Hear Staff Chat", nil)
|
||||
end
|
||||
})
|
||||
|
||||
function PLUGIN:PopulateScoreboardPlayerMenu(client, menu)
|
||||
if (CAMI.PlayerHasAccess(LocalPlayer(), "Helix - Basic Admin Commands")) then
|
||||
menu:AddOption(L("bastionCopySteamName"), function()
|
||||
SetClipboardText(client:SteamName())
|
||||
LocalPlayer():NotifyLocalized("bastionCopiedSteamName")
|
||||
end)
|
||||
|
||||
menu:AddOption(L("bastionCopyCharName"), function()
|
||||
SetClipboardText(client:Name())
|
||||
LocalPlayer():NotifyLocalized("bastionCopiedCharName")
|
||||
end)
|
||||
end
|
||||
|
||||
if (sam and CAMI.PlayerHasAccess(LocalPlayer(), "Helix - Basic Admin Commands") and !LocalPlayer():InVehicle() and client != LocalPlayer()) then
|
||||
menu:AddOption(L("bastionGoto"), function()
|
||||
if (LocalPlayer():GetMoveType() != MOVETYPE_NOCLIP) then
|
||||
LocalPlayer():ConCommand("noclip")
|
||||
end
|
||||
LocalPlayer():ConCommand("say !goto "..client:Name())
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
function PLUGIN:PrintTarget(target)
|
||||
if (ix.option.Get("pgi")) then
|
||||
SetClipboardText(target:SteamID())
|
||||
end
|
||||
|
||||
chat.AddText(self.infoIcon, target:Name(), " (", target:SteamName(), "; ", target:SteamID(),
|
||||
") | PV : ", target:Health(), " | Armure : ", target:Armor())
|
||||
end
|
||||
|
||||
function PLUGIN:PrintStaffList(amount)
|
||||
for _ = 1, amount do
|
||||
local group = net.ReadString()
|
||||
local members = net.ReadUInt(8)
|
||||
local memberList = {}
|
||||
for _ = 1, members do
|
||||
memberList[#memberList + 1] = net.ReadEntity():SteamName()
|
||||
end
|
||||
|
||||
table.sort(memberList)
|
||||
chat.AddText(self.infoIcon, "[", string.utf8upper(group), "]: ", table.concat(memberList, ", "))
|
||||
end
|
||||
end
|
||||
|
||||
function PLUGIN:ShouldDisplayArea(id)
|
||||
if (LocalPlayer():GetMoveType() == MOVETYPE_NOCLIP and !LocalPlayer():InVehicle()) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
local commands = {
|
||||
["playsound"] = 2,
|
||||
["localevent"] = 2,
|
||||
["showentsinradius"] = 1,
|
||||
["localbroadcast"] = 2,
|
||||
["localbroadcastme"] = 2,
|
||||
["localbroadcastit"] = 2,
|
||||
["playsong"] = 3,
|
||||
["screenshake"] = 4,
|
||||
["removepersistedprops"] = 1,
|
||||
["removeclientprops"] = 1
|
||||
}
|
||||
|
||||
function PLUGIN:PostDrawTranslucentRenderables(bDrawingDepth, bDrawingSkybox)
|
||||
local command = string.utf8lower(ix.chat.currentCommand)
|
||||
|
||||
if (commands[command]) then
|
||||
local range = tonumber(ix.chat.currentArguments[commands[command]])
|
||||
|
||||
if (range) then
|
||||
render.SetColorMaterial()
|
||||
render.DrawSphere(LocalPlayer():GetPos(), 0 - range, 50, 50, Color(255, 150, 0, 100))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
net.Receive("ixOpenURL", function(len)
|
||||
gui.OpenURL(net.ReadString())
|
||||
end)
|
||||
|
||||
net.Receive("ixPlayerInfo", function(len)
|
||||
PLUGIN:PrintTarget(net.ReadEntity())
|
||||
end)
|
||||
|
||||
net.Receive("ixStaffList", function(len)
|
||||
PLUGIN:PrintStaffList(net.ReadUInt(8))
|
||||
end)
|
||||
|
||||
net.Receive("ixPlaySound", function(len)
|
||||
local sound = net.ReadString()
|
||||
local isGlobal = net.ReadBool()
|
||||
|
||||
if (hook.Run("PrePlaySound", sound, isGlobal) != false) then
|
||||
surface.PlaySound(sound)
|
||||
|
||||
hook.Run("PostPlaySound", sound, isGlobal)
|
||||
end
|
||||
end)
|
||||
|
||||
netstream.Hook("PrintInfoList", function(list)
|
||||
for _, v in ipairs(list) do
|
||||
MsgN(v)
|
||||
end
|
||||
end)
|
||||
|
||||
function PLUGIN:OnPlayerChat()
|
||||
if (ix.config.Get("suppressOnPlayerChat", true)) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
137
gamemodes/helix/plugins/bastion/modules/sh_bindchecker.lua
Normal file
137
gamemodes/helix/plugins/bastion/modules/sh_bindchecker.lua
Normal file
@@ -0,0 +1,137 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
if (SERVER) then
|
||||
util.AddNetworkString("ixBindGrab")
|
||||
util.AddNetworkString("ixBindGrabList")
|
||||
end
|
||||
|
||||
CAMI.RegisterPrivilege({
|
||||
Name = "Helix - Check Bind",
|
||||
MinAccess = "superadmin"
|
||||
})
|
||||
|
||||
ix.command.Add("PlyGetBinds", {
|
||||
description = "Get a list of all of someone's binds.",
|
||||
privilege = "Check Bind",
|
||||
arguments = {ix.type.player, bit.bor(ix.type.optional, ix.type.bool)},
|
||||
OnRun = function(self, client, target, all)
|
||||
if (IsValid(target.ixBindGrab) and target.ixBindGrabTime and target.ixBindGrabTime > CurTime()) then
|
||||
return "Someone else is checking this player's binds already. Please wait a few seconds!"
|
||||
end
|
||||
|
||||
target.ixBindGrab = client
|
||||
target.ixBindGrabTime = CurTime() + 5
|
||||
target.ixBindGrabAll = all
|
||||
net.Start("ixBindGrab")
|
||||
net.Send(target)
|
||||
end,
|
||||
bNoIndicator = true
|
||||
})
|
||||
|
||||
if (CLIENT) then
|
||||
net.Receive("ixBindGrab", function()
|
||||
net.Start("ixBindGrab")
|
||||
for i = 1, BUTTON_CODE_LAST do
|
||||
net.WriteString(string.Left(input.LookupKeyBinding(i) or "", 255))
|
||||
end
|
||||
net.SendToServer()
|
||||
end)
|
||||
|
||||
local blacklist = {
|
||||
["slot0"] = true,
|
||||
["slot1"] = true,
|
||||
["slot2"] = true,
|
||||
["slot3"] = true,
|
||||
["slot4"] = true,
|
||||
["slot5"] = true,
|
||||
["slot6"] = true,
|
||||
["slot7"] = true,
|
||||
["slot8"] = true,
|
||||
["slot9"] = true,
|
||||
["+zoom"] = true,
|
||||
|
||||
["+forward"] = true,
|
||||
["+back"] = true,
|
||||
["+moveleft"] = true,
|
||||
["+moveright"] = true,
|
||||
["+jump"] = true,
|
||||
["+speed"] = true,
|
||||
["+walk"] = true,
|
||||
["+duck"] = true,
|
||||
|
||||
["+lookup"] = true,
|
||||
["+left"] = true,
|
||||
["+lookdown"] = true,
|
||||
["+right"] = true,
|
||||
|
||||
["+attack"] = true,
|
||||
["+attack2"] = true,
|
||||
["+reload"] = true,
|
||||
["+use"] = true,
|
||||
["invprev"] = true,
|
||||
["invnext"] = true,
|
||||
|
||||
["+menu"] = true,
|
||||
["+menu_context"] = true,
|
||||
["gmod_undo"] = true,
|
||||
|
||||
["+showscores"] = true,
|
||||
["gm_showhelp"] = true,
|
||||
["gm_showteam"] = true,
|
||||
["gm_showspare1"] = true,
|
||||
["gm_showspare2"] = true,
|
||||
|
||||
["noclip"] = true,
|
||||
["messagemode"] = true,
|
||||
|
||||
["toggleconsole"] = true,
|
||||
["cancelselect"] = true,
|
||||
["pause"] = true,
|
||||
["save quick"] = true,
|
||||
["load quick"] = true,
|
||||
|
||||
["impulse 100"] = true,
|
||||
["+voicerecord"] = true,
|
||||
["jpeg"] = true,
|
||||
}
|
||||
net.Receive("ixBindGrabList", function()
|
||||
local all = net.ReadBool()
|
||||
MsgN(net.ReadString().."'s binds ("..net.ReadString()..")")
|
||||
for i = 1, BUTTON_CODE_LAST do
|
||||
local bind = net.ReadString()
|
||||
if (!all and blacklist[bind]) then continue end
|
||||
|
||||
if (bind and bind != "") then
|
||||
if (#bind == 255) then
|
||||
bind = bind.."..."
|
||||
end
|
||||
MsgN((input.GetKeyName(i) or i)..": ", bind)
|
||||
end
|
||||
end
|
||||
|
||||
LocalPlayer():Notify("Binds were printed in console!")
|
||||
end)
|
||||
else
|
||||
net.Receive("ixBindGrab", function(len, client)
|
||||
if (!IsValid(client.ixBindGrab) or !CAMI.PlayerHasAccess(client.ixBindGrab, "Helix - Check Bind")) then return end
|
||||
net.Start("ixBindGrabList")
|
||||
net.WriteBool(client.ixBindGrabAll)
|
||||
net.WriteString(client:SteamName())
|
||||
net.WriteString(client:SteamID())
|
||||
for i = 1, BUTTON_CODE_LAST do
|
||||
net.WriteString(string.Left(net.ReadString(), 255))
|
||||
end
|
||||
net.Send(client.ixBindGrab)
|
||||
|
||||
client.ixBindGrab = nil
|
||||
end)
|
||||
end
|
||||
507
gamemodes/helix/plugins/bastion/modules/sv_antialt.lua
Normal file
507
gamemodes/helix/plugins/bastion/modules/sv_antialt.lua
Normal file
@@ -0,0 +1,507 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
local pcall = pcall
|
||||
local util = util
|
||||
local ix = ix
|
||||
local string = string
|
||||
local net = net
|
||||
local ipairs = ipairs
|
||||
local IsValid = IsValid
|
||||
local os = os
|
||||
local L = L
|
||||
local math = math
|
||||
local table = table
|
||||
local pairs = pairs
|
||||
local print = print
|
||||
local CHTTP = CHTTP
|
||||
local player = player
|
||||
local CAMI = CAMI
|
||||
|
||||
if (!CHTTP) then
|
||||
pcall(require, "chttp")
|
||||
end
|
||||
|
||||
local PLUGIN = PLUGIN
|
||||
PLUGIN.TYPE_UNKNOWN = 1
|
||||
PLUGIN.TYPE_KNOWN = 2
|
||||
|
||||
local COOKIE_KEY = "qvFT4QSSST8K4tZF"
|
||||
|
||||
local fileChecks = {
|
||||
{"hl2_misc_001.vpk", "hl2"},
|
||||
{"ep2_pak_008.vpk", "ep2"},
|
||||
{"cstrike_pak_003.vpk", "css", "cstrike"},
|
||||
{"bin/client_panorama.dll", "csgo"},
|
||||
{"detail.vbsp", "gmod", "garrysmod"}
|
||||
}
|
||||
|
||||
util.AddNetworkString("RecieveDupe")
|
||||
|
||||
ix.util.Include("sv_antialt_db.lua")
|
||||
|
||||
ix.lang.AddTable("english", {
|
||||
altSignupProxy = "Vous essayez de rejoindre Willard Networks en tant que nouvel utilisateur tout en utilisant un proxy ou un VPN. Pour lutter contre les autres comptes, nous ne l'autorisons pas.\n\nVeuillez désactiver votre proxy/VPN et rejoindre le serveur. Après avoir rejoint le serveur avec succès une fois, vous pouvez réactiver votre proxy/VPN pour de futures visites.\n\nSi vous n'utilisez pas de proxy ou de VPN, veuillez contacter un membre de l'équipe du STAFF sur nos forums ou discord"
|
||||
})
|
||||
|
||||
ix.log.AddType("altNewClient", function(client)
|
||||
return string.format("[AltChecker] %s rejoint pour la première fois.", client:SteamName())
|
||||
end)
|
||||
ix.log.AddType("altKnownNewCookie", function(client)
|
||||
return string.format("[AltChecker] %s rejoint avec une installation inconnue.", client:SteamName())
|
||||
end)
|
||||
ix.log.AddType("altKnownCookieMatched", function(client, matched, total)
|
||||
return string.format("[AltChecker] %s rejoint sans cookie, mais l'installation correspond au cookie existant. %d/%d", client:SteamName(), matched, total)
|
||||
end)
|
||||
|
||||
hook.Add("PlayerInitialSpawn", "bastionAntiAlt", function(client)
|
||||
if (client:IsBot()) then return end
|
||||
|
||||
client.ixAltData = {
|
||||
checks = 4 + #fileChecks,
|
||||
altLogging = 0,
|
||||
error = false,
|
||||
received = false,
|
||||
checkComplete = false,
|
||||
newAltFound = false,
|
||||
|
||||
mode = 0,
|
||||
localCookie = "",
|
||||
cookies = false,
|
||||
ip = false,
|
||||
timestamps = false,
|
||||
|
||||
otherCookies = {},
|
||||
otherIPs = {},
|
||||
otherTimestamps = {},
|
||||
otherTimestampsNZ = {},
|
||||
otherTimeMatches = {},
|
||||
|
||||
discordAlert = {
|
||||
cookies = {},
|
||||
timestamps = {},
|
||||
ips = {},
|
||||
altIDs = {}
|
||||
}
|
||||
}
|
||||
|
||||
-- Lookup user data
|
||||
PLUGIN:AltLoadUserData(client)
|
||||
|
||||
if (PLUGIN.API_KEY) then
|
||||
-- Lookup user IP
|
||||
PLUGIN:AltLookupIP(client)
|
||||
else
|
||||
client.ixAltData.checkes = client.ixAltData.checks - 1
|
||||
end
|
||||
|
||||
-- Check for IP matches
|
||||
PLUGIN:AltLookupIPMatches(client)
|
||||
|
||||
-- Request cookie and install timestamps
|
||||
PLUGIN:RequestClientData(client)
|
||||
end)
|
||||
|
||||
function PLUGIN:RequestClientData(client)
|
||||
net.Start("RecieveDupe")
|
||||
net.WriteUInt(1, 3)
|
||||
net.WriteString(COOKIE_KEY)
|
||||
for _, v in ipairs(fileChecks) do
|
||||
net.WriteString(v[1])
|
||||
net.WriteString(v[3] or v[2])
|
||||
end
|
||||
net.Send(client)
|
||||
end
|
||||
|
||||
net.Receive("RecieveDupe", function(len, client)
|
||||
if (!IsValid(client) or !client.ixAltData or client.ixAltData.received) then return end
|
||||
|
||||
local data = client.ixAltData
|
||||
data.received = true
|
||||
-- set cookie
|
||||
data.localCookie = net.ReadString()
|
||||
-- set file timestamps
|
||||
data.timestamps = {}
|
||||
for i = 1, #fileChecks do
|
||||
data.timestamps[i] = net.ReadUInt(32)
|
||||
end
|
||||
|
||||
-- Check for cookie matches
|
||||
if (data.localCookie != "") then
|
||||
PLUGIN:AltLookupCookieMatches(client, data)
|
||||
else
|
||||
PLUGIN:AltPreFinalChecking(client)
|
||||
end
|
||||
|
||||
-- Check for install timestamp matches
|
||||
data.otherTimestamps = {}
|
||||
data.otherTimestampsNZ = {}
|
||||
for i = 1, #fileChecks do
|
||||
PLUGIN:AltLookupTimestampMatches(client, data, fileChecks[i][2], data.timestamps[i])
|
||||
end
|
||||
end)
|
||||
|
||||
function PLUGIN:AltPreFinalChecking(client)
|
||||
if (!IsValid(client)) then return end
|
||||
|
||||
local data = client.ixAltData
|
||||
-- if we errored, don't do anything
|
||||
-- check will be reexecuted when the client rejoins
|
||||
if (data.error) then return end
|
||||
|
||||
-- check if all queries finished
|
||||
data.checks = data.checks - 1
|
||||
if (data.checks != 0) then return end
|
||||
|
||||
-- cookie matches (STRONG)
|
||||
if (#data.otherCookies > 0) then
|
||||
for _, v in ipairs(data.otherCookies) do
|
||||
self:AltFound(client, v[2], "cookie", "cookie")
|
||||
data.discordAlert.cookies[#data.discordAlert.cookies + 1] = (v[2] or "").." ("..(v[1] or "")..")"
|
||||
data.discordAlert.altIDs[v[2]] = true
|
||||
end
|
||||
end
|
||||
|
||||
-- IP (WEAK)
|
||||
if (#data.otherIPs > 0) then
|
||||
for _, v in ipairs(data.otherIPs) do
|
||||
data.discordAlert.ips[#data.discordAlert.ips + 1] = v[2]
|
||||
data.discordAlert.altIDs[v[2]] = true
|
||||
end
|
||||
end
|
||||
|
||||
-- time matches (STRONG-MEDIUM)
|
||||
self:AggregateTimestampMatches(data)
|
||||
|
||||
-- If no local cookie and player is known, check if a known cookie was time-matched
|
||||
if (data.localCookie == "" and data.mode == self.TYPE_KNOWN) then
|
||||
self:FindMatchingCookie(client, data)
|
||||
end
|
||||
|
||||
if (#data.otherTimeMatches > 0) then
|
||||
-- go looking for the other clients that own our matched timestamps
|
||||
self:AltLookupCookieForTimestamps(client, data, #fileChecks)
|
||||
else
|
||||
-- else we don't need to wait for the lookup above
|
||||
data.checkComplete = true
|
||||
self:AltFinalChecking(client)
|
||||
end
|
||||
end
|
||||
|
||||
function PLUGIN:AltFinalChecking(client)
|
||||
if (!IsValid(client)) then return end
|
||||
|
||||
local data = client.ixAltData
|
||||
if (!data.checkComplete or data.altLogging != 0) then return end
|
||||
|
||||
self:DiscordAlert(client)
|
||||
|
||||
-- update IP list
|
||||
local steamID = client:SteamID64()
|
||||
local ip = self.GetIPAddress(client)
|
||||
local query = mysql:Select("bastion_antialt_userips")
|
||||
query:Where("steamid", steamID)
|
||||
query:Where("ip", ip)
|
||||
query:Callback(function(result)
|
||||
if (!result or #result == 0) then
|
||||
local query2 = mysql:Insert("bastion_antialt_userips")
|
||||
query2:Insert("steamid", steamID)
|
||||
query2:Insert("ip", ip)
|
||||
query2:Insert("last_seen", os.time())
|
||||
query2:Execute()
|
||||
else
|
||||
local query2 = mysql:Update("bastion_antialt_userips")
|
||||
query2:Where("id", result[1].id)
|
||||
query2:Update("last_seen", os.time())
|
||||
query2:Execute()
|
||||
end
|
||||
end)
|
||||
query:Execute()
|
||||
|
||||
-- Kick if new player on proxy/vpn
|
||||
if (data.mode == self.TYPE_UNKNOWN) then
|
||||
if (self.API_KEY and (data.ip.proxy == "yes" or (data.ip.risk or 0) > 60)) then
|
||||
if (ix.config.Get("VPNKick")) then
|
||||
self:ProxyAlert(client)
|
||||
client:Kick(L("altSignupProxy", client))
|
||||
else
|
||||
if (!self:NotifyProxyJoin(client) or ix.config.Get("ProxyAlwaysAlert")) then
|
||||
self:ProxyAlert(client)
|
||||
end
|
||||
end
|
||||
elseif (data.localCookie == "") then
|
||||
ix.log.Add(client, "altNewClient")
|
||||
self:GenerateCookie(client, data)
|
||||
else
|
||||
-- Update the cookie's timestamps
|
||||
self:StoreCookieInfo(data, fileChecks)
|
||||
-- Add this cookie to client as well so it can be time matched/timestamps updated
|
||||
self:StoreClientCookie(client, data)
|
||||
end
|
||||
elseif (data.localCookie == "") then
|
||||
ix.log.Add(client, "altKnownNewCookie")
|
||||
self:GenerateCookie(client, data)
|
||||
else
|
||||
-- Update the cookie's timestamps
|
||||
self:StoreCookieInfo(data, fileChecks)
|
||||
-- Add this cookie to client as well so it can be time matched/timestamps updated
|
||||
self:StoreClientCookie(client, data)
|
||||
end
|
||||
|
||||
if (sam) then
|
||||
timer.Simple(3, function()
|
||||
if (!IsValid(client)) then return end
|
||||
local query1 = mysql:Select("bastion_antialt_alts")
|
||||
query1:Where("steamid", client:SteamID64())
|
||||
query1:Select("alt_id")
|
||||
query1:Callback(function(result)
|
||||
if (!IsValid(client)) then return end
|
||||
if (!result or #result == 0) then return end
|
||||
local query2 = mysql:Select("bastion_antialt_alts")
|
||||
query2:Where("alt_id", result[1].alt_id)
|
||||
query2:WhereNotEqual("steamid", client:SteamID64())
|
||||
query2:Select("steamid")
|
||||
query2:Callback(function(result2)
|
||||
if (!IsValid(client)) then return end
|
||||
if (!result2 or #result2 == 0) then return end
|
||||
|
||||
for k, v in ipairs(result2) do
|
||||
sam.player.is_banned(util.SteamIDFrom64(v.steamid), function(banned)
|
||||
if (!banned or !IsValid(client)) then return end
|
||||
client:Kick("You have a banned alt account.")
|
||||
return
|
||||
end)
|
||||
end
|
||||
end)
|
||||
query2:Execute()
|
||||
end)
|
||||
query1:Execute()
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
COOKIE STUFF
|
||||
]]
|
||||
function PLUGIN:WhitelistPlayer(client)
|
||||
local data = client.ixAltData
|
||||
if (!data) then return end
|
||||
|
||||
if (data.localCookie) then
|
||||
ix.log.Add(client, "altNewClient")
|
||||
self:GenerateCookie(client, data)
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function PLUGIN.RandomString()
|
||||
local result = {} -- The empty table we start with
|
||||
while (#result != 64) do
|
||||
local char = string.char(math.random(32, 126))
|
||||
if (string.find(char, "%w")) then
|
||||
result[#result + 1] = char
|
||||
end
|
||||
end
|
||||
|
||||
return table.concat(result)
|
||||
end
|
||||
|
||||
function PLUGIN:GenerateCookie(client, data)
|
||||
local cookie = self.RandomString()
|
||||
self:UpdateLocalCookie(client, data, cookie)
|
||||
|
||||
local query = mysql:Insert("bastion_antialt_users")
|
||||
query:Insert("steamid", client:SteamID64())
|
||||
query:Insert("steam_name", client:SteamName())
|
||||
query:Insert("cookie", cookie)
|
||||
query:Execute()
|
||||
end
|
||||
|
||||
function PLUGIN:UpdateLocalCookie(client, data, cookie)
|
||||
data.localCookie = cookie
|
||||
|
||||
net.Start("RecieveDupe")
|
||||
net.WriteUInt(2, 3)
|
||||
net.WriteString(COOKIE_KEY)
|
||||
net.WriteString(cookie)
|
||||
net.Send(client)
|
||||
|
||||
self:StoreCookieInfo(data, fileChecks)
|
||||
end
|
||||
|
||||
function PLUGIN:FindMatchingCookie(client, data)
|
||||
for _, v in ipairs(data.otherTimeMatches) do
|
||||
for _, v1 in ipairs(data.cookies) do
|
||||
if (v1.cookie == v[1]) then
|
||||
-- found a timestamp match belonging to the client, restore cookie
|
||||
-- in case of e.g. gmod reinstall
|
||||
ix.log.Add(client, "altKnownCookieMatched", v[2], #fileChecks)
|
||||
self:UpdateLocalCookie(client, data, v[1])
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
LOGGING AND ALERTING
|
||||
]]
|
||||
local ALT_OFFSET = 0
|
||||
function PLUGIN:AltFound(client, steamid, type, info)
|
||||
local ids = {client:SteamID64(), steamid}
|
||||
local data = client.ixAltData
|
||||
|
||||
data.altLogging = data.altLogging + 1
|
||||
|
||||
local query = mysql:Select("bastion_antialt_alts")
|
||||
query:WhereIn("steamid", ids)
|
||||
query:Callback(function(result)
|
||||
if (!result or #result == 0) then
|
||||
local alt_id = os.time() + ALT_OFFSET
|
||||
ALT_OFFSET = ALT_OFFSET + 1
|
||||
|
||||
local text = table.concat(ids,"+")..": "..info.." (alt-id: "..alt_id..")"
|
||||
self:InsertNewAlt(ids[1], alt_id, type, text)
|
||||
self:InsertNewAlt(steamid, alt_id, type, text)
|
||||
|
||||
data.newAltFound = true
|
||||
elseif (#result == 1) then
|
||||
self:InsertNewAlt(
|
||||
result[1].steamid == steamid and ids[1] or steamid,
|
||||
result[1].alt_id,
|
||||
type,
|
||||
table.concat(ids,"+")..": "..info.." (alt-id: "..result[1].alt_id..")"
|
||||
)
|
||||
|
||||
data.newAltFound = true
|
||||
elseif (result[2].alt_id != result[1].alt_id) then
|
||||
self:MergeAlts(
|
||||
result[2].alt_id,
|
||||
result[1].alt_id,
|
||||
table.concat(ids,"+")..": "..info.." (alt-id: "..result[1].alt_id..")"
|
||||
)
|
||||
|
||||
data.newAltFound = true
|
||||
end
|
||||
|
||||
data.altLogging = data.altLogging - 1
|
||||
self:AltFinalChecking(client)
|
||||
end)
|
||||
query:Execute()
|
||||
end
|
||||
|
||||
function PLUGIN:DiscordAlert(client)
|
||||
if (!self.DISCORD_WEBHOOK_ALTS or self.DISCORD_WEBHOOK_ALTS == "") then return end
|
||||
|
||||
local data = client.ixAltData
|
||||
if (!data.newAltFound) then return end
|
||||
|
||||
local tbl = {
|
||||
embeds = {{
|
||||
title = "Alt found for "..client:SteamName(),
|
||||
description = "An alt account match was found for **"..client:SteamName().."** (*"..client:SteamID64().."*)\n\n__COOKIE__: 99.99% certainty via installed cookie\nShown as 'SteamID64 (SteamName)'\n__TIMESTAMP__: check via installation date/time or absense of mounted games (hl2,ep2,css,csgo,gmod)\nMore matches = more certainty, especially if all/most are installed\nShown as 'SteamID64 (SteamName; date/time matches - installed matches)'\n__IP__: users that connected from the same IP address at any point\nShown as 'SteamID64'",
|
||||
color = 13632027,
|
||||
timestamp = os.date("%Y-%m-%d %X%z"),
|
||||
footer = {
|
||||
text = "Bastion Alt Checker for GMod by Gr4Ss"
|
||||
},
|
||||
author = {
|
||||
name = "Bastion Alt Checker"
|
||||
},
|
||||
fields = {
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
if (data.discordAlert.cookies and #data.discordAlert.cookies > 0) then
|
||||
table.insert(tbl.embeds[1].fields, {name = "COOKIE", value = table.concat(data.discordAlert.cookies, "\n")})
|
||||
end
|
||||
if (data.discordAlert.timestamps and #data.discordAlert.timestamps > 0) then
|
||||
table.insert(tbl.embeds[1].fields, {name = "TIMESTAMP", value = table.concat(data.discordAlert.timestamps, "\n")})
|
||||
end
|
||||
if (data.discordAlert.ips and #data.discordAlert.ips > 0) then
|
||||
table.insert(tbl.embeds[1].fields, {
|
||||
name = "IP",
|
||||
value = string.format("Address: [%s](https://proxycheck.io/threats/%s)\n", data.ipAddress, data.ipAddress)..
|
||||
table.concat(data.discordAlert.ips, "\n")
|
||||
})
|
||||
end
|
||||
local ipLinks = {"["..client:SteamID64().."](https://steamidfinder.com/lookup/"..client:SteamID64().."/)"}
|
||||
for k in pairs(data.discordAlert.altIDs) do
|
||||
ipLinks[#ipLinks + 1] = "["..k.."](https://steamidfinder.com/lookup/"..k.."/)"
|
||||
end
|
||||
table.insert(tbl.embeds[1].fields, {
|
||||
name = "SteamID Finder Links",
|
||||
value = table.concat(ipLinks,"\n")
|
||||
})
|
||||
|
||||
for _, field in ipairs(tbl.embeds[1].fields) do
|
||||
if (string.len(field.value) > 1024) then
|
||||
field.value = string.sub(field.value, 1, 1024)
|
||||
end
|
||||
end
|
||||
|
||||
local request = {
|
||||
failed = function(error) print("discord error", error) end,
|
||||
success = function(code, body, headers)
|
||||
if (code != 200) then print("discord error", code, body) end
|
||||
end,
|
||||
method = "post",
|
||||
url = self.DISCORD_WEBHOOK_ALTS,
|
||||
body = util.TableToJSON(tbl),
|
||||
type = "application/json; charset=utf-8"
|
||||
}
|
||||
|
||||
CHTTP(request)
|
||||
end
|
||||
|
||||
function PLUGIN:ProxyAlert(client)
|
||||
if (!self.DISCORD_WEBHOOK_ALTS or self.DISCORD_WEBHOOK_ALTS == "") then return end
|
||||
|
||||
local ip, steamID = client.ixAltData.ipAddress, client:SteamID64()
|
||||
local tbl = {
|
||||
embeds = {{
|
||||
title = "New player using VPN - "..client:SteamName(),
|
||||
description = client:SteamName().." joined WN for the first time, but was using a proxy/VPN. They have been kicked.\n\n"..
|
||||
string.format("More info: [%s](https://proxycheck.io/threats/%s) & [%s](https://steamidfinder.com/lookup/%s/)", ip, ip, steamID, steamID),
|
||||
color = 16312092,
|
||||
timestamp = os.date("%Y-%m-%d %X%z"),
|
||||
footer = {
|
||||
text = "Bastion Alt Checker for GMod by Gr4Ss"
|
||||
},
|
||||
author = {
|
||||
name = "Bastion Alt Checker"
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
local request = {
|
||||
failed = function(error) print("discord error", error) end,
|
||||
method = "post",
|
||||
url = self.DISCORD_WEBHOOK_ALTS,
|
||||
body = util.TableToJSON(tbl),
|
||||
type = "application/json; charset=utf-8"
|
||||
}
|
||||
|
||||
CHTTP(request)
|
||||
end
|
||||
|
||||
function PLUGIN:NotifyProxyJoin(client)
|
||||
local bSend = false
|
||||
for _, v in ipairs(player.GetAll()) do
|
||||
if (CAMI.PlayerHasAccess(v, "Helix - Proxy Notify")) then
|
||||
bSend = true
|
||||
v:NotifyLocalized("bastionProxyNotify", client:SteamName())
|
||||
end
|
||||
end
|
||||
|
||||
return bSend
|
||||
end
|
||||
461
gamemodes/helix/plugins/bastion/modules/sv_antialt_db.lua
Normal file
461
gamemodes/helix/plugins/bastion/modules/sv_antialt_db.lua
Normal file
@@ -0,0 +1,461 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
local IsValid = IsValid
|
||||
local string = string
|
||||
local os = os
|
||||
local print = print
|
||||
local util = util
|
||||
local CHTTP = CHTTP
|
||||
local ipairs = ipairs
|
||||
local table = table
|
||||
local pairs = pairs
|
||||
local netstream = netstream
|
||||
local SortedPairsByMemberValue = SortedPairsByMemberValue
|
||||
|
||||
local PLUGIN = PLUGIN
|
||||
|
||||
local MAX_CACHE_AGE = 7 * 24 * 3600 -- 7 days
|
||||
PLUGIN.ipCache = {}
|
||||
|
||||
hook.Add("DatabaseConnected", "bastionAntiAlt", function()
|
||||
local query = mysql:Create("bastion_antialt_users")
|
||||
query:Create("id", "INT UNSIGNED NOT NULL AUTO_INCREMENT")
|
||||
query:Create("steamid", "VARCHAR(20) NOT NULL")
|
||||
query:Create("steam_name", "VARCHAR(128) NOT NULL")
|
||||
query:Create("cookie", "VARCHAR(64) NOT NULL")
|
||||
query:PrimaryKey("id")
|
||||
query:Execute()
|
||||
|
||||
query = mysql:Create("bastion_antialt_cookies")
|
||||
query:Create("cookie", "VARCHAR(64) NOT NULL")
|
||||
query:Create("ts_hl2", "INT(11) UNSIGNED DEFAULT NULL")
|
||||
query:Create("ts_ep2", "INT(11) UNSIGNED DEFAULT NULL")
|
||||
query:Create("ts_css", "INT(11) UNSIGNED DEFAULT NULL")
|
||||
query:Create("ts_csgo", "INT(11) UNSIGNED DEFAULT NULL")
|
||||
query:Create("ts_gmod", "INT(11) UNSIGNED DEFAULT NULL")
|
||||
query:PrimaryKey("cookie")
|
||||
query:Execute()
|
||||
|
||||
query = mysql:Create("bastion_antialt_userips")
|
||||
query:Create("id", "INT UNSIGNED NOT NULL AUTO_INCREMENT")
|
||||
query:Create("steamid", "VARCHAR(20) NOT NULL")
|
||||
query:Create("ip", "VARCHAR(15) NOT NULL")
|
||||
query:Create("last_seen", "INT(11) UNSIGNED NOT NULL")
|
||||
query:PrimaryKey("id")
|
||||
query:Execute()
|
||||
|
||||
query = mysql:Create("bastion_antialt_ip")
|
||||
query:Create("ip", "VARCHAR(15) NOT NULL")
|
||||
query:Create("updated", "INT(11) UNSIGNED NOT NULL")
|
||||
query:Create("asn", "VARCHAR(12) NOT NULL")
|
||||
query:Create("provider", "VARCHAR(128) NOT NULL")
|
||||
query:Create("isocode", "VARCHAR(2) NOT NULL")
|
||||
query:Create("proxy", "TINYINT(1) UNSIGNED DEFAULT 0")
|
||||
query:Create("type", "VARCHAR(32) NOT NULL")
|
||||
query:Create("risk", "INT UNSIGNED NOT NULL")
|
||||
query:Create("attack_count", "INT UNSIGNED DEFAULT NULL")
|
||||
query:Create("attack_history", "TEXT DEFAULT NULL")
|
||||
query:PrimaryKey("ip")
|
||||
query:Execute()
|
||||
|
||||
query = mysql:Create("bastion_antialt_alts")
|
||||
query:Create("steamid", "VARCHAR(20) NOT NULL")
|
||||
query:Create("alt_id", "INT UNSIGNED NOT NULL")
|
||||
query:Create("type", "VARCHAR(10) NOT NULL")
|
||||
query:Create("info", "TEXT NOT NULL")
|
||||
query:PrimaryKey("steamid")
|
||||
query:Execute()
|
||||
end)
|
||||
|
||||
function PLUGIN:AltLoadUserData(client)
|
||||
local query = mysql:Select("bastion_antialt_users")
|
||||
query:Where("steamid", client:SteamID64())
|
||||
query:Callback(function(result)
|
||||
if (!IsValid(client)) then return end
|
||||
|
||||
if (!result or #result == 0) then
|
||||
client.ixAltData.mode = self.TYPE_UNKNOWN
|
||||
else
|
||||
client.ixAltData.mode = self.TYPE_KNOWN
|
||||
client.ixAltData.cookies = result
|
||||
end
|
||||
|
||||
self:AltPreFinalChecking(client)
|
||||
end)
|
||||
query:Execute()
|
||||
end
|
||||
|
||||
function PLUGIN.GetIPAddress(client)
|
||||
local ip = client:IPAddress()
|
||||
|
||||
return string.gsub(ip, ":%d+$", "", 1)
|
||||
end
|
||||
|
||||
function PLUGIN:AltLookupIP(client)
|
||||
local ip = self.GetIPAddress(client)
|
||||
|
||||
client.ixAltData.ipAddress = ip
|
||||
|
||||
if (self.ipCache[ip]) then
|
||||
-- ip address still in cache
|
||||
client.ixAltData.ip = self.ipCache[ip]
|
||||
self:AltPreFinalChecking(client)
|
||||
else
|
||||
-- lookup address
|
||||
local query = mysql:Select("bastion_antialt_ip")
|
||||
query:Where("ip", ip)
|
||||
query:Callback(function(result)
|
||||
if (!result or #result == 0 or (result[1].updated < (os.time() - MAX_CACHE_AGE))) then
|
||||
self:AltFetchIP(client, ip, !result or #result == 0)
|
||||
else
|
||||
-- load in data from the DB
|
||||
if (result[1].proxy == 1) then
|
||||
result[1].proxy = "yes"
|
||||
else
|
||||
result[1].proxy = "no"
|
||||
end
|
||||
client.ixAltData.ip = result[1]
|
||||
self:AltPreFinalChecking(client)
|
||||
end
|
||||
end)
|
||||
query:Execute()
|
||||
end
|
||||
end
|
||||
|
||||
function PLUGIN:AltFetchIP(client, ip, bCreateNew)
|
||||
-- address not found or record too old, look it up
|
||||
local url = string.format("https://proxycheck.io/v2/%s?key=%s&vpn=1&asn=1&risk=1", ip, self.API_KEY)
|
||||
local request = {
|
||||
failed = function(error)
|
||||
-- error stop matching
|
||||
print("[BASTION] Alt check IP API call failed with error: "..error)
|
||||
print("[BASTION] Client: "..client:SteamName().."; ip: "..ip)
|
||||
client.ixAltData.error = true
|
||||
end,
|
||||
success = function(code, body, headers)
|
||||
if (!IsValid(client)) then return end
|
||||
|
||||
local httpResult = util.JSONToTable(body)
|
||||
if (!httpResult) then
|
||||
-- error stop matching
|
||||
print("[BASTION] Alt check IP API call failed to parse httpResult.")
|
||||
client.ixAltData.error = true
|
||||
return
|
||||
end
|
||||
|
||||
local status = httpResult.status
|
||||
if (status == "denied" or status == "error" or status == "warning") then
|
||||
print("[BASTION] Alt check IP API call failed. Status: "..status.."; Message: "..(httpResult.message or "no message").."\n")
|
||||
if (status != "warning") then
|
||||
-- error stop matching
|
||||
client.ixAltData.error = true
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- we got the data
|
||||
local lookup = httpResult[ip]
|
||||
self:StoreIPLookup(ip, lookup, bCreateNew)
|
||||
|
||||
client.ixAltData.ip = lookup
|
||||
self:AltPreFinalChecking(client)
|
||||
end,
|
||||
url = url,
|
||||
method = "GET"
|
||||
}
|
||||
|
||||
CHTTP(request)
|
||||
end
|
||||
|
||||
function PLUGIN:AltLookupCookieMatches(client, data)
|
||||
local query = mysql:Select("bastion_antialt_users")
|
||||
query:Where("cookie", data.localCookie)
|
||||
query:WhereNotEqual("steamid", client:SteamID64())
|
||||
query:Callback(function(result)
|
||||
-- we found other cookies
|
||||
if (result and #result > 0) then
|
||||
for k, v in ipairs(result) do
|
||||
data.otherCookies[k] = {v.steam_name, v.steamid}
|
||||
end
|
||||
end
|
||||
|
||||
self:AltPreFinalChecking(client)
|
||||
end)
|
||||
query:Execute()
|
||||
end
|
||||
|
||||
function PLUGIN:AltLookupIPMatches(client)
|
||||
local query = mysql:Select("bastion_antialt_userips")
|
||||
query:Where("ip", PLUGIN.GetIPAddress(client))
|
||||
query:WhereNotEqual("steamid", client:SteamID64())
|
||||
query:Callback(function(result)
|
||||
if (!IsValid(client)) then return end
|
||||
|
||||
if (result and #result > 0) then
|
||||
for k, v in ipairs(result) do
|
||||
client.ixAltData.otherIPs[k] = {v.ip, v.steamid}
|
||||
end
|
||||
end
|
||||
|
||||
self:AltPreFinalChecking(client)
|
||||
end)
|
||||
query:Execute()
|
||||
end
|
||||
|
||||
function PLUGIN:AltLookupTimestampMatches(client, data, game, timestamp)
|
||||
local query = mysql:Select("bastion_antialt_cookies")
|
||||
query:Where("ts_"..game, timestamp)
|
||||
if (data.localCookie != "") then
|
||||
-- not interested in timestamps that we know for this client
|
||||
query:WhereNotEqual("cookie", data.localCookie)
|
||||
end
|
||||
query:Callback(function(result)
|
||||
if (result and #result > 0) then
|
||||
for _, v in ipairs(result) do
|
||||
data.otherTimestamps[v.cookie] = data.otherTimestamps[v.cookie] or {}
|
||||
table.insert(data.otherTimestamps[v.cookie], game)
|
||||
-- track timestamp matches
|
||||
-- non-zero timestamps are worth a lot more, so tracked separately too
|
||||
if (timestamp != 0) then
|
||||
data.otherTimestampsNZ[v.cookie] = data.otherTimestampsNZ[v.cookie] or {}
|
||||
data.otherTimestampsNZ[v.cookie][game] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self:AltPreFinalChecking(client)
|
||||
end)
|
||||
query:Execute()
|
||||
end
|
||||
|
||||
function PLUGIN:AggregateTimestampMatches(data)
|
||||
data.otherTimeMatches = {}
|
||||
for cookie, matches in pairs(data.otherTimestamps) do
|
||||
if (#matches == 1) then continue end
|
||||
|
||||
data.otherTimeMatches[#data.otherTimeMatches + 1] = {cookie, #matches}
|
||||
end
|
||||
table.SortByMember(data.otherTimeMatches, 2, false)
|
||||
end
|
||||
|
||||
function PLUGIN:AltLookupCookieForTimestamps(client, data, maxMatches)
|
||||
local cookies = {}
|
||||
for cookie, matches in pairs(data.otherTimestamps) do
|
||||
-- only find cookies if at least 2 matches of which one is non-zero
|
||||
if (#matches >= 2 and data.otherTimestampsNZ[cookie]) then
|
||||
cookies[#cookies + 1] = cookie
|
||||
end
|
||||
end
|
||||
|
||||
if (#cookies == 0) then
|
||||
data.checkComplete = true
|
||||
self:AltFinalChecking(client)
|
||||
return
|
||||
end
|
||||
|
||||
local query = mysql:Select("bastion_antialt_users")
|
||||
query:WhereNotEqual("steamid", client:SteamID64())
|
||||
query:WhereIn("cookie", cookies)
|
||||
query:Callback(function(result)
|
||||
if (!IsValid(client)) then return end
|
||||
|
||||
if (result and #result > 0) then
|
||||
for _, v in ipairs(result) do
|
||||
local installed = table.GetKeys(data.otherTimestampsNZ[v.cookie])
|
||||
local text = string.format("%d/%d matches - installed: %s)",
|
||||
#data.otherTimestamps[v.cookie],
|
||||
maxMatches,
|
||||
table.concat(installed, "+")
|
||||
)
|
||||
self:AltFound(client, v.steamid, "timestamp", text)
|
||||
|
||||
data.discordAlert.timestamps[# data.discordAlert.timestamps + 1] = v.steamid.." ("..v.steam_name.."; "..text..")"
|
||||
data.discordAlert.altIDs[v.steamid] = true
|
||||
end
|
||||
end
|
||||
|
||||
data.checkComplete = true
|
||||
self:AltFinalChecking(client)
|
||||
end)
|
||||
query:Execute()
|
||||
end
|
||||
|
||||
function PLUGIN:StoreCookieInfo(data, fileChecks)
|
||||
local query = mysql:Select("bastion_antialt_cookies")
|
||||
query:Where("cookie", data.localCookie)
|
||||
query:Callback(function(result)
|
||||
if (!result or #result == 0) then
|
||||
local queryInsert = mysql:Insert("bastion_antialt_cookies")
|
||||
queryInsert:Insert("cookie", data.localCookie)
|
||||
for k, v in ipairs(fileChecks) do
|
||||
queryInsert:Insert("ts_"..v[2], data.timestamps[k])
|
||||
end
|
||||
queryInsert:Execute()
|
||||
else
|
||||
local queryUpdate = mysql:Update("bastion_antialt_cookies")
|
||||
queryUpdate:Where("cookie", data.localCookie)
|
||||
for k, v in ipairs(fileChecks) do
|
||||
queryUpdate:Update("ts_"..v[2], data.timestamps[k])
|
||||
end
|
||||
queryUpdate:Execute()
|
||||
end
|
||||
end)
|
||||
query:Execute()
|
||||
end
|
||||
|
||||
function PLUGIN:StoreClientCookie(client, data)
|
||||
local query = mysql:Select("bastion_antialt_users")
|
||||
query:Where("cookie", data.localCookie)
|
||||
query:Where("steamid", client:SteamID64())
|
||||
query:Callback(function(result)
|
||||
if (!IsValid(client)) then return end
|
||||
|
||||
if (!result or #result == 0) then
|
||||
local queryInsert = mysql:Insert("bastion_antialt_users")
|
||||
queryInsert:Insert("steamid", client:SteamID64())
|
||||
queryInsert:Insert("steam_name", client:SteamName())
|
||||
queryInsert:Insert("cookie", data.localCookie)
|
||||
queryInsert:Execute()
|
||||
end
|
||||
end)
|
||||
query:Execute()
|
||||
end
|
||||
|
||||
function PLUGIN:StoreIPLookup(ip, httpResult, bNewEntry)
|
||||
if (!bNewEntry) then
|
||||
local query = mysql:Update("bastion_antialt_ip")
|
||||
query:Where("ip", ip)
|
||||
query:Update("updated", os.time())
|
||||
query:Update("asn", httpResult.asn)
|
||||
query:Update("provider", httpResult.provider)
|
||||
query:Update("isocode", httpResult.isocode)
|
||||
query:Update("proxy", httpResult.proxy == "yes" and 1 or 0)
|
||||
query:Update("type", httpResult.type)
|
||||
query:Update("risk", httpResult.risk or 0)
|
||||
if (httpResult["attack history"]) then
|
||||
query:Update("attack_count", httpResult["attack history"].Total)
|
||||
query:Update("attack_history", util.TableToJSON(httpResult["attack history"]))
|
||||
end
|
||||
query:Execute()
|
||||
else
|
||||
local query = mysql:Insert("bastion_antialt_ip")
|
||||
query:Insert("ip", ip)
|
||||
query:Insert("updated", os.time())
|
||||
query:Insert("asn", httpResult.asn)
|
||||
query:Insert("provider", httpResult.provider)
|
||||
query:Insert("isocode", httpResult.isocode)
|
||||
query:Insert("proxy", httpResult.proxy == "yes" and 1 or 0)
|
||||
query:Insert("type", httpResult.type)
|
||||
query:Insert("risk", httpResult.risk or 0)
|
||||
if (httpResult["attack history"]) then
|
||||
query:Insert("attack_count", httpResult["attack history"].Total)
|
||||
query:Insert("attack_history", util.TableToJSON(httpResult["attack history"]))
|
||||
end
|
||||
query:Execute()
|
||||
end
|
||||
end
|
||||
|
||||
function PLUGIN:InsertNewAlt(steamid, alt_id, type, text)
|
||||
local query = mysql:Insert("bastion_antialt_alts")
|
||||
query:Insert("steamid", steamid)
|
||||
query:Insert("alt_id", alt_id)
|
||||
query:Insert("type", type)
|
||||
query:Insert("info", text)
|
||||
query:Execute()
|
||||
end
|
||||
|
||||
function PLUGIN:MergeAlts(old_id, new_id, text)
|
||||
local query = mysql:Select("bastion_antialt_alts")
|
||||
query:Where("alt_id", old_id)
|
||||
query:Callback(function(result2)
|
||||
for _, v in ipairs(result2) do
|
||||
local queryUpdate = mysql:Update("bastion_antialt_alts")
|
||||
queryUpdate:Where("steamid", v.steamid)
|
||||
queryUpdate:Update("alt_id", new_id)
|
||||
queryUpdate:Update("info", v.info.." - "..text)
|
||||
queryUpdate:Execute()
|
||||
end
|
||||
end)
|
||||
query:Execute()
|
||||
end
|
||||
|
||||
function PLUGIN:LookupSteamID(client, steamid)
|
||||
if (string.find(steamid, "^STEAM_")) then
|
||||
steamid = util.SteamIDTo64()
|
||||
end
|
||||
|
||||
local query = mysql:Select("bastion_antialt_alts")
|
||||
query:Where("steamid", steamid)
|
||||
query:Callback(function(result)
|
||||
if (!IsValid(client)) then return end
|
||||
if (!result or #result == 0) then
|
||||
client:NotifyLocalized("bastionNoRecordFound", steamid)
|
||||
return
|
||||
end
|
||||
|
||||
local querySelect = mysql:Select("bastion_antialt_alts")
|
||||
querySelect:Where("alt_id", result[1].alt_id)
|
||||
querySelect:Callback(function(finalResult)
|
||||
if (!IsValid(client)) then return end
|
||||
|
||||
local toReturn = {"Alts for "..steamid..":", "(SteamID64) - (detection trigger type) - (info)"}
|
||||
for _, v in ipairs(finalResult) do
|
||||
toReturn[#toReturn + 1] = v.steamid.." - "..v.type.." - info: "..v.info
|
||||
end
|
||||
|
||||
netstream.Start(client, "PrintInfoList", toReturn)
|
||||
client:NotifyLocalized("bastionResultsPrinted")
|
||||
end)
|
||||
querySelect:Execute()
|
||||
end)
|
||||
query:Execute()
|
||||
end
|
||||
|
||||
function PLUGIN:LookupIPUsers(client, steamid)
|
||||
if (string.find(steamid, "^STEAM_")) then
|
||||
steamid = util.SteamIDTo64(steamid)
|
||||
end
|
||||
|
||||
local query = mysql:query("bastion_antialt_userips")
|
||||
query:Where("steamid", steamid)
|
||||
query:Callback(function(result)
|
||||
if (!IsValid(client)) then return end
|
||||
if (!result or #result == 0) then
|
||||
client:NotifyLocalized("bastionNoRecordFound", steamid)
|
||||
return
|
||||
end
|
||||
|
||||
local list = {}
|
||||
for k, v in ipairs(result) do
|
||||
list[k] = v.ip
|
||||
end
|
||||
|
||||
local querySelect = mysql:query("bastion_antialt_userips")
|
||||
querySelect:WhereIn("ip", list)
|
||||
querySelect:WhereNotEqual("steamid", steamid)
|
||||
querySelect:Callback(function(finalResult)
|
||||
if (!IsValid(client)) then return end
|
||||
if (!result or #result == 0) then
|
||||
client:NotifyLocalized("bastionNoRecordFound", steamid)
|
||||
return
|
||||
end
|
||||
|
||||
local toReturn = {"Other users on same IP as "..steamid, "(SteamID64) - (ip) - (last seen on this ip)"}
|
||||
for _, v in SortedPairsByMemberValue(finalResult, "steamid") do
|
||||
toReturn[#toReturn + 1] = v.steamid.." - "..v.ip.." - "..os.date("%Y-%m-%d", v.last_seen)
|
||||
end
|
||||
netstream.Start(client, "PrintInfoList", toReturn)
|
||||
client:NotifyLocalized("bastionResultsPrinted")
|
||||
end)
|
||||
querySelect:Execute()
|
||||
end)
|
||||
query:Execute()
|
||||
end
|
||||
96
gamemodes/helix/plugins/bastion/modules/sv_banlist.lua
Normal file
96
gamemodes/helix/plugins/bastion/modules/sv_banlist.lua
Normal file
@@ -0,0 +1,96 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
local hook = hook
|
||||
local ix = ix
|
||||
local util = util
|
||||
|
||||
local PLUGIN = PLUGIN
|
||||
|
||||
PLUGIN.permaBan = {
|
||||
-- Crazyman (~Atle/Gr4Ss), code stealing
|
||||
["STEAM_0:1:120921609"] = true,
|
||||
["2.73.226.221"] = true,
|
||||
["2.72.176.41"] = true,
|
||||
["2.132.96.235"] = true,
|
||||
["2.132.103.122"] = true,
|
||||
["2.132.147.172"] = true,
|
||||
["2.132.150.162"] = true,
|
||||
["95.57.132.81"] = true,
|
||||
-- carlsmei (~Atle/Gr4Ss), code stealing
|
||||
["STEAM_0:0:216726444"] = true,
|
||||
-- Schwarz Kruppzo (~Atle/Gr4Ss), code stealing
|
||||
["STEAM_0:1:44629398"] = true,
|
||||
-- KoC (~Atle/Gr4Ss), toxic, ban evasion
|
||||
["76561198017957016"] = true,
|
||||
["76561199123547331"] = true,
|
||||
["73.121.218.83"] = true,
|
||||
["136.144.43.116"] = true,
|
||||
["136.144.43.63"] = true,
|
||||
-- Kalingi (Staff vote, Hiros/Gr4Ss), toxic, threatening hacks & blackmail
|
||||
["76561198066620287"] = true,
|
||||
["STEAM_0:1:53177279"] = true,
|
||||
["24.197.171.2"] = true,
|
||||
-- Brando (~Atle/Gr4Ss), pedo
|
||||
["STEAM_0:1:54660756"] = true,
|
||||
-- Walter (~Atle/Gr4Ss), none
|
||||
["STEAM_0:1:43085888"] = true,
|
||||
-- PrplSckz/The Enemy (~Rad/Gr4Ss), forum DDoS
|
||||
["STEAM_0:1:68538156"] = true,
|
||||
-- Hackers (~Gr4Ss)
|
||||
["STEAM_0:1:13809165"] = true,
|
||||
["STEAM_0:1:4916602"] = true,
|
||||
["STEAM_0:1:517232907"] = true,
|
||||
["STEAM_0:1:17046093"] = true,
|
||||
-- Exploiters
|
||||
["STEAM_0:0:549109050"] = true,
|
||||
["76561199131288084"] = true,
|
||||
["76561199087140341"] = true,
|
||||
["76561199206105794"] = true,
|
||||
["76561198874018211"] = true,
|
||||
["109.252.109.68"] = true,
|
||||
["76561199121843993"] = true,
|
||||
-- Zeroday / Newport Gaming - Sketchy dude + some hacking & exploiting (~M!NT/RAD)
|
||||
["172.82.32.147"] = true,
|
||||
["76561199441966033"] = true,
|
||||
-- Cazo
|
||||
["82.0.106.136"] = true,
|
||||
["76561199150421701"] = true,
|
||||
-- lqut (Translating ISIS Propaganda) (~M!NT/RAD)
|
||||
["STEAM_0:0:173208852"] = true,
|
||||
["5.30.219.71"] = true,
|
||||
["76561198306683432"] = true,
|
||||
-- madbluntz (doxxing, minging, ddosing, etc etc) (~M!NT)
|
||||
["176.117.229.107"] = true,
|
||||
["176.117.229.107"] = true,
|
||||
["178.214.250.178"] = true,
|
||||
["46.191.232.69"] = true,
|
||||
["178.168.94.11"] = true,
|
||||
["163.182.82.195"] = true,
|
||||
["104.231.185.125"] = true,
|
||||
["STEAM_0:0:763201893"] = true,
|
||||
["STEAM_0:0:629741416"] = true,
|
||||
["STEAM_0:1:764405213"] = true,
|
||||
["STEAM_0:1:817531224"] = true,
|
||||
["STEAM_0:0:785033797"] = true,
|
||||
["STEAM_0:1:421783352"] = true,
|
||||
["STEAM_0:1:78544439"] = true,
|
||||
["STEAM_0:1:178702634"] = true,
|
||||
["STEAM_0:0:627119036"] = true,
|
||||
["STEAM_0:0:585787645"] = true,
|
||||
["STEAM_0:1:43085888"] = true,
|
||||
}
|
||||
|
||||
hook.Add("CheckPassword", "bastionBanList", function(steamid, networkid)
|
||||
if (PLUGIN.permaBan[steamid] or PLUGIN.permaBan[util.SteamIDFrom64(steamid)] or PLUGIN.permaBan[networkid]) then
|
||||
ix.log.AddRaw("[BANS] "..steamid.." ("..networkid..") a essayé de se connecter mais est strictement interdit.")
|
||||
return false
|
||||
end
|
||||
end)
|
||||
211
gamemodes/helix/plugins/bastion/modules/sv_netmonitor.lua
Normal file
211
gamemodes/helix/plugins/bastion/modules/sv_netmonitor.lua
Normal file
@@ -0,0 +1,211 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
local hook_Add = hook.Add
|
||||
local timer_Create = timer.Create
|
||||
local os_time = os.time
|
||||
local pairs = pairs
|
||||
local net_ReadHeader = net.ReadHeader
|
||||
local util_NetworkIDToString = util.NetworkIDToString
|
||||
local ix = ix
|
||||
local IsValid = IsValid
|
||||
local string_len = string.len
|
||||
local string_sub = string.sub
|
||||
|
||||
-- Code inspired by:
|
||||
-- Gmod Net Library Debug
|
||||
-- https://github.com/HexaneNetworks/gmod-netlibrary-debug
|
||||
-- v2.3
|
||||
-- October 2020
|
||||
|
||||
local PLUGIN = PLUGIN
|
||||
|
||||
hook_Add("DatabaseConnected", "bastionNetDB", function()
|
||||
local query = mysql:Create("bastion_netlog")
|
||||
query:Create("id", "BIGINT UNSIGNED NOT NULL AUTO_INCREMENT")
|
||||
query:Create("name", "VARCHAR(50) NOT NULL")
|
||||
query:Create("length", "INT UNSIGNED NOT NULL")
|
||||
query:Create("count", "INT UNSIGNED NOT NULL")
|
||||
query:Create("steamid", "VARCHAR(20) NOT NULL")
|
||||
query:Create("args", "VARCHAR(200) DEFAULT NULL")
|
||||
query:PrimaryKey("id")
|
||||
query:Execute()
|
||||
|
||||
query = mysql:Create("bastion_netspam")
|
||||
query:Create("id", "INT UNSIGNED NOT NULL AUTO_INCREMENT")
|
||||
query:Create("name", "VARCHAR(50) NOT NULL")
|
||||
query:Create("type", "BOOL NOT NULL")
|
||||
query:Create("count", "INT UNSIGNED NOT NULL")
|
||||
query:Create("steamid", "VARCHAR(20) NOT NULL")
|
||||
query:Create("steam_name", "VARCHAR(50) NOT NULL")
|
||||
query:Create("ip", "VARCHAR(25) NOT NULL")
|
||||
query:Create("time", "INT NOT NULL")
|
||||
query:PrimaryKey("id")
|
||||
query:Execute()
|
||||
end)
|
||||
|
||||
local netSpamCount = {}
|
||||
local netFlagged = {}
|
||||
|
||||
local comSpamCount = {}
|
||||
local comFlagged = {}
|
||||
|
||||
local threshold = 20
|
||||
|
||||
timer_Create("ixBastionNetSpam.Clear", 1.1, 0, function()
|
||||
local time = os_time()
|
||||
for steamID, data in pairs(netFlagged) do
|
||||
for name in pairs(data.names) do
|
||||
local query = mysql:Insert("bastion_netspam")
|
||||
query:Insert("name", name)
|
||||
query:Insert("type", 0)
|
||||
query:Insert("count", netSpamCount[steamID][name] or 0)
|
||||
query:Insert("steamid", steamID)
|
||||
query:Insert("steam_name", data.steamName)
|
||||
query:Insert("ip", data.ip)
|
||||
query:Insert("time", time)
|
||||
query:Execute()
|
||||
end
|
||||
end
|
||||
|
||||
netSpamCount = {}
|
||||
netFlagged = {}
|
||||
|
||||
for steamID, data in pairs(comFlagged) do
|
||||
for name in pairs(data.commands) do
|
||||
local query = mysql:Insert("bastion_netspam")
|
||||
query:Insert("name", name)
|
||||
query:Insert("type", 1)
|
||||
query:Insert("count", comSpamCount[steamID][name] or 0)
|
||||
query:Insert("steamid", steamID)
|
||||
query:Insert("steam_name", data.steamName)
|
||||
query:Insert("ip", data.ip)
|
||||
query:Insert("time", time)
|
||||
query:Execute()
|
||||
end
|
||||
end
|
||||
|
||||
comSpamCount = {}
|
||||
comFlagged = {}
|
||||
end)
|
||||
|
||||
|
||||
local netIgnoreList = {
|
||||
["76561198002319953"] = 2
|
||||
}
|
||||
|
||||
local netSpamAmount = {
|
||||
["NetStreamDS"] = 20,
|
||||
["76561198002319953"] = 30
|
||||
}
|
||||
|
||||
function net.Incoming(len, client)
|
||||
local i = net_ReadHeader()
|
||||
local name = util_NetworkIDToString(i)
|
||||
if (!name) then return end
|
||||
|
||||
local func = net.Receivers[name:lower()]
|
||||
if (!func) then return end
|
||||
|
||||
--
|
||||
-- len includes the 16 bit int which told us the message name
|
||||
--
|
||||
len = len - 16
|
||||
|
||||
if (ix.config.Get("netAntiSpam")) then
|
||||
local steamID = IsValid(client) and client:SteamID64() or "UNKNOWN"
|
||||
netSpamCount[steamID] = netSpamCount[steamID] or {}
|
||||
netSpamCount[steamID][name] = (netSpamCount[steamID][name] or 0) + 1
|
||||
if (netSpamCount[steamID][name] > (netSpamAmount[name] or threshold)) then
|
||||
if (!netFlagged[steamID]) then
|
||||
netFlagged[steamID] = {
|
||||
names = {},
|
||||
steamID = steamID,
|
||||
steamName = IsValid(client) and (client.SteamName and client:SteamName() or client:Name()) or "UNKNOWN PLAYER NAME",
|
||||
ip = IsValid(client) and client:IPAddress() or "UNKNOWN IP"
|
||||
}
|
||||
|
||||
if (!ix.config.Get("netLoggingEnabled")) then
|
||||
local query = mysql:Insert("bastion_netlog")
|
||||
query:Insert("name", name)
|
||||
query:Insert("length", len)
|
||||
query:Insert("count", netSpamCount[steamID][name])
|
||||
query:Insert("steamid", steamID)
|
||||
query:Execute()
|
||||
end
|
||||
end
|
||||
|
||||
netFlagged[steamID].names[name] = true
|
||||
end
|
||||
|
||||
|
||||
|
||||
if (ix.config.Get("netLoggingEnabled") and (!netIgnoreList[name] or netIgnoreList[name] < netSpamCount[steamID][name])) then
|
||||
local query = mysql:Insert("bastion_netlog")
|
||||
query:Insert("name", name)
|
||||
query:Insert("length", len)
|
||||
query:Insert("count", netSpamCount[steamID][name])
|
||||
query:Insert("steamid", steamID)
|
||||
query:Execute()
|
||||
end
|
||||
end
|
||||
|
||||
func(len, client)
|
||||
end
|
||||
|
||||
local conSpamAmount = {
|
||||
|
||||
}
|
||||
local conIgnoreList = {
|
||||
|
||||
}
|
||||
|
||||
PLUGIN.oldRun = PLUGIN.oldRun or concommand.Run
|
||||
function concommand.Run(client, command, args, argString)
|
||||
if (IsValid(client) and command and ix.config.Get("netAntiSpam")) then
|
||||
local steamID = IsValid(client) and client:SteamID64() or "UNKNOWN"
|
||||
comSpamCount[steamID] = comSpamCount[steamID] or {}
|
||||
comSpamCount[steamID][command] = (comSpamCount[steamID][command] or 0) + 1
|
||||
if (comSpamCount[steamID][command] > (conSpamAmount[command] or threshold)) then
|
||||
if (!comFlagged[steamID]) then
|
||||
comFlagged[steamID] = {
|
||||
commands = {},
|
||||
steamID = steamID,
|
||||
steamName = IsValid(client) and (client.SteamName and client:SteamName() or client:Name()) or "UNKNOWN PLAYER NAME",
|
||||
ip = IsValid(client) and client:IPAddress() or "UNKNOWN IP"
|
||||
}
|
||||
|
||||
if (!ix.config.Get("netLoggingEnabled")) then
|
||||
local query = mysql:Insert("bastion_netlog")
|
||||
query:Insert("name", command)
|
||||
query:Insert("length", #argString)
|
||||
query:Insert("count", netSpamCount[steamID][command])
|
||||
query:Insert("steamid", steamID)
|
||||
query:Insert("args", string_len(argString or "") > 200 and string_sub(argString, 1, 200) or argString or "")
|
||||
query:Execute()
|
||||
end
|
||||
end
|
||||
|
||||
comFlagged[steamID].commands[command] = true
|
||||
end
|
||||
|
||||
if (ix.config.Get("netLoggingEnabled") and (!conIgnoreList[command] or conIgnoreList[command] < comSpamCount[steamID][command])) then
|
||||
local query = mysql:Insert("bastion_netlog")
|
||||
query:Insert("name", command)
|
||||
query:Insert("length", #argString)
|
||||
query:Insert("count", comSpamCount[steamID][command])
|
||||
query:Insert("steamid", steamID)
|
||||
query:Insert("args", string_len(argString or "") > 200 and string_sub(argString, 1, 200) or argString or "")
|
||||
query:Execute()
|
||||
end
|
||||
end
|
||||
|
||||
return PLUGIN.oldRun(client, command, args, argString)
|
||||
end
|
||||
100
gamemodes/helix/plugins/bastion/modules/sv_netsizelog.lua
Normal file
100
gamemodes/helix/plugins/bastion/modules/sv_netsizelog.lua
Normal file
@@ -0,0 +1,100 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
local PLUGIN = PLUGIN
|
||||
|
||||
--Made by Liquid
|
||||
PLUGIN.MIN_PLAYER_COUNT = 30
|
||||
PLUGIN.STOP_AFTER_CONNECTED_FOR = 600
|
||||
PLUGIN.MIN_SIZE = 100
|
||||
PLUGIN.TRACE_SIZE = 1000
|
||||
|
||||
ORIGINAL_NET = ORIGINAL_NET or table.Copy(net)
|
||||
|
||||
local _net = ORIGINAL_NET
|
||||
local IsValid = IsValid
|
||||
|
||||
local currentMessageName
|
||||
hook.Add("DatabaseConnected", "bastionNetSizeLog", function()
|
||||
local query = mysql:Create("bastion_netsizelog")
|
||||
query:Create("id", "INT UNSIGNED NOT NULL AUTO_INCREMENT")
|
||||
query:Create("steamid", "VARCHAR(20) NOT NULL")
|
||||
query:Create("timestamp", "INT(11) UNSIGNED NOT NULL")
|
||||
query:Create("realtime", "FLOAT NOT NULL")
|
||||
query:Create("message_name", "VARCHAR(128) NOT NULL")
|
||||
query:Create("size", "INT(11) UNSIGNED NOT NULL")
|
||||
query:Create("stack_trace", "TEXT DEFAULT NULL")
|
||||
query:PrimaryKey("id")
|
||||
query:Callback(function()
|
||||
local delete = mysql:Delete("bastion_netsizelog")
|
||||
delete:WhereLT("timestamp", os.time() - 3 * 24 * 3600)
|
||||
delete:Execute()
|
||||
end)
|
||||
query:Execute()
|
||||
end)
|
||||
|
||||
local function netLog(players)
|
||||
local count = player.GetCount()
|
||||
if (count > 1 and count <= PLUGIN.MIN_PLAYER_COUNT) then return end
|
||||
|
||||
if (type(players) == "Player") then
|
||||
players = {players}
|
||||
elseif (type(players) == "CRecipientFilter") then
|
||||
players = players:GetPlayers()
|
||||
end
|
||||
|
||||
local size = _net.BytesWritten()
|
||||
if (size <= PLUGIN.MIN_SIZE) then return end
|
||||
|
||||
for k, v in ipairs(players) do
|
||||
if (!IsValid(v)) then continue end
|
||||
|
||||
if (v.ixStopNetLog or v:TimeConnected() > PLUGIN.STOP_AFTER_CONNECTED_FOR) then
|
||||
v.ixStopNetLog = true
|
||||
continue
|
||||
end
|
||||
|
||||
local query = mysql:Insert("bastion_netsizelog")
|
||||
query:Insert("steamid", v:SteamID64())
|
||||
query:Insert("timestamp", os.time())
|
||||
query:Insert("realtime", RealTime())
|
||||
query:Insert("message_name", currentMessageName)
|
||||
query:Insert("size", size)
|
||||
if (size >= PLUGIN.TRACE_SIZE or currentMessageName == "NetStreamDS") then
|
||||
query:Insert("stack_trace", debug.traceback())
|
||||
end
|
||||
query:Execute()
|
||||
end
|
||||
end
|
||||
|
||||
net.Start = function(name, unreliable)
|
||||
currentMessageName = name
|
||||
|
||||
return _net.Start(name, unreliable)
|
||||
end
|
||||
|
||||
net.Send = function(players)
|
||||
netLog(players)
|
||||
currentMessageName = nil
|
||||
return _net.Send(players)
|
||||
end
|
||||
|
||||
net.SendOmit = function(players)
|
||||
netLog(players)
|
||||
currentMessageName = nil
|
||||
return _net.SendOmit(players)
|
||||
end
|
||||
|
||||
net.Broadcast = function(pos)
|
||||
netLog(player.GetAll())
|
||||
currentMessageName = nil
|
||||
return _net.Broadcast()
|
||||
end
|
||||
190
gamemodes/helix/plugins/bastion/sh_classes.lua
Normal file
190
gamemodes/helix/plugins/bastion/sh_classes.lua
Normal file
@@ -0,0 +1,190 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
local ix = ix
|
||||
local Color = Color
|
||||
local chat = chat
|
||||
local string = string
|
||||
local IsValid = IsValid
|
||||
local LocalPlayer = LocalPlayer
|
||||
local MsgC = MsgC
|
||||
local CAMI = CAMI
|
||||
local surface = surface
|
||||
local team = team
|
||||
|
||||
-- luacheck: globals FACTION_SERVERADMIN
|
||||
|
||||
|
||||
-- Roll information in chat.
|
||||
|
||||
ix.chat.Register("localevent", {
|
||||
CanHear = (ix.config.Get("chatRange", 280) * 2),
|
||||
OnChatAdd = function(self, speaker, text)
|
||||
chat.AddText(Color(255, 150, 0), text)
|
||||
end,
|
||||
})
|
||||
|
||||
local broadcastIcon = ix.util.GetMaterial("willardnetworks/chat/broadcast_icon.png")
|
||||
|
||||
ix.chat.Register("localbroadcast", {
|
||||
CanHear = (ix.config.Get("chatRange", 280) * 2),
|
||||
CanSay = function(self, speaker, text)
|
||||
if (speaker:Team() != FACTION_ADMIN and !speaker:GetCharacter():GetInventory():HasItem("wireless_microphone")) then
|
||||
speaker:NotifyLocalized("notAllowed")
|
||||
|
||||
return false
|
||||
end
|
||||
end,
|
||||
OnChatAdd = function(self, speaker, text)
|
||||
if (ix.option.Get("standardIconsEnabled")) then
|
||||
chat.AddText(broadcastIcon, Color(151, 161, 255), string.format("%s broadcasts locally \"%s\"", (speaker and speaker.Name and speaker:Name() or ""), text))
|
||||
else
|
||||
chat.AddText(Color(151, 161, 255), string.format("%s broadcasts locally \"%s\"", (speaker and speaker.Name and speaker:Name() or ""), text))
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
ix.chat.Register("localbroadcastme", {
|
||||
CanHear = (ix.config.Get("chatRange", 280) * 2),
|
||||
CanSay = function(self, speaker, text)
|
||||
if (speaker:Team() != FACTION_ADMIN and !speaker:GetCharacter():GetInventory():HasItem("wireless_microphone")) then
|
||||
speaker:NotifyLocalized("notAllowed")
|
||||
|
||||
return false
|
||||
end
|
||||
end,
|
||||
OnChatAdd = function(self, speaker, text)
|
||||
if (ix.option.Get("standardIconsEnabled")) then
|
||||
chat.AddText(broadcastIcon, Color(151, 161, 255), string.format("*** %s %s", (speaker and speaker.Name and speaker:Name() or ""), text))
|
||||
else
|
||||
chat.AddText(Color(151, 161, 255), string.format("*** %s %s", (speaker and speaker.Name and speaker:Name() or ""), text))
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
ix.chat.Register("localbroadcastit", {
|
||||
CanHear = (ix.config.Get("chatRange", 280) * 2),
|
||||
CanSay = function(self, speaker, text)
|
||||
if (speaker:Team() != FACTION_ADMIN and !speaker:GetCharacter():GetInventory():HasItem("wireless_microphone")) then
|
||||
speaker:NotifyLocalized("notAllowed")
|
||||
|
||||
return false
|
||||
end
|
||||
end,
|
||||
OnChatAdd = function(self, speaker, text)
|
||||
if (ix.option.Get("standardIconsEnabled")) then
|
||||
chat.AddText(broadcastIcon, Color(151, 161, 255), string.format("***' %s", text))
|
||||
else
|
||||
chat.AddText(Color(151, 161, 255), string.format("***' %s", text))
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
ix.chat.Register("announcement", {
|
||||
OnChatAdd = function(self, speaker, text)
|
||||
chat.AddText(Color(254, 238, 60), "[ADMIN] ", text)
|
||||
end,
|
||||
CanSay = function(self, speaker, text)
|
||||
return true
|
||||
end
|
||||
})
|
||||
|
||||
-- STAFF CHAT
|
||||
do
|
||||
local CLASS = {}
|
||||
local icon = ix.util.GetMaterial("icon16/medal_gold_3.png")
|
||||
|
||||
if (CLIENT) then
|
||||
function CLASS:OnChatAdd(speaker, text, anonymous, data)
|
||||
if (!IsValid(speaker)) then return end
|
||||
|
||||
if (speaker != LocalPlayer() and !ix.option.Get("staffChat")) then
|
||||
local character = LocalPlayer():GetCharacter()
|
||||
if (character and character:GetFaction() != FACTION_SERVERADMIN) then
|
||||
MsgC(Color(255,215,0), "[Staff] ",
|
||||
Color(128, 0, 255, 255), speaker:Name(), " (", speaker:SteamName(), "): ",
|
||||
Color(255, 255, 255), text.."\n")
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
chat.AddText(icon, Color(255,215,0), "[Staff] ",
|
||||
Color(128, 0, 255, 255), speaker:Name(), " (", speaker:SteamName(), "): ",
|
||||
Color(255, 255, 255), text)
|
||||
end
|
||||
else
|
||||
function CLASS:CanHear(speaker, listener)
|
||||
return CAMI.PlayerHasAccess(listener, "Helix - Hear Staff Chat")
|
||||
end
|
||||
end
|
||||
|
||||
ix.chat.Register("staff_chat", CLASS)
|
||||
end
|
||||
|
||||
-- GM CHAT
|
||||
do
|
||||
local CLASS = {}
|
||||
local icon = ix.util.GetMaterial("icon16/rosette.png")
|
||||
|
||||
if (CLIENT) then
|
||||
function CLASS:OnChatAdd(speaker, text, anonymous, data)
|
||||
if (!IsValid(speaker)) then return end
|
||||
|
||||
chat.AddText(icon, Color(142, 28, 255), "[GM] ", Color(255, 215, 0, 255), speaker:Name(), " (", speaker:SteamName(), "): ", Color(255, 255, 255), text)
|
||||
end
|
||||
else
|
||||
function CLASS:CanHear(speaker, listener)
|
||||
return CAMI.PlayerHasAccess(listener, "Helix - Hear GM Chat")
|
||||
end
|
||||
end
|
||||
|
||||
ix.chat.Register("gm_chat", CLASS)
|
||||
end
|
||||
|
||||
-- MENTOR CHAT
|
||||
do
|
||||
local CLASS = {}
|
||||
local icon = ix.util.GetMaterial("icon16/user_suit.png")
|
||||
|
||||
if (CLIENT) then
|
||||
function CLASS:OnChatAdd(speaker, text, anonymous, data)
|
||||
if (!IsValid(speaker)) then return end
|
||||
|
||||
chat.AddText(icon, Color(66, 135, 245), "[Mentor] ", Color(66, 245, 191, 255), speaker:Name(), " (", speaker:SteamName(), "): ", Color(255, 255, 255), text)
|
||||
end
|
||||
else
|
||||
function CLASS:CanHear(speaker, listener)
|
||||
return CAMI.PlayerHasAccess(listener, "Helix - Hear Mentor Chat")
|
||||
end
|
||||
end
|
||||
|
||||
ix.chat.Register("mentor_chat", CLASS)
|
||||
end
|
||||
|
||||
-- ACHIEVEMENT
|
||||
do
|
||||
local CLASS = {}
|
||||
|
||||
if (CLIENT) then
|
||||
function CLASS:OnChatAdd(speaker, text, anonymous, data)
|
||||
if (!IsValid(data[1])) then return end
|
||||
|
||||
if (data[2]) then
|
||||
surface.PlaySound(data[2])
|
||||
end
|
||||
|
||||
local target = data[1]
|
||||
chat.AddText(team.GetColor(target:Team()), target:SteamName(), Color(255, 255, 255), " a gagné le succès : ",
|
||||
Color( 255, 201, 0, 255 ), text)
|
||||
end
|
||||
end
|
||||
|
||||
ix.chat.Register("achievement_get", CLASS)
|
||||
end
|
||||
643
gamemodes/helix/plugins/bastion/sh_commands.lua
Normal file
643
gamemodes/helix/plugins/bastion/sh_commands.lua
Normal file
@@ -0,0 +1,643 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
local bit = bit
|
||||
local IsValid = IsValid
|
||||
local pairs = pairs
|
||||
local table = table
|
||||
local L = L
|
||||
local netstream = netstream
|
||||
local Entity = Entity
|
||||
local print = print
|
||||
local math = math
|
||||
local tostring = tostring
|
||||
local CAMI = CAMI
|
||||
local Vector = Vector
|
||||
local game = game
|
||||
local RunConsoleCommand = RunConsoleCommand
|
||||
local net = net
|
||||
local player = player
|
||||
local ipairs = ipairs
|
||||
local ents = ents
|
||||
local string = string
|
||||
local timer = timer
|
||||
local ix = ix
|
||||
|
||||
local PLUGIN = PLUGIN
|
||||
|
||||
--Links
|
||||
ix.command.Add("Discord", {
|
||||
description = "Obtenir un lien vers le serveur Discord",
|
||||
privilege = "Basic Commands",
|
||||
OnRun = function(self, client)
|
||||
net.Start("ixOpenURL")
|
||||
net.WriteString(ix.config.Get("DiscordLink"))
|
||||
net.Send(client)
|
||||
end,
|
||||
bNoIndicator = true
|
||||
})
|
||||
ix.command.Add("Content", {
|
||||
description = "Obtenir un lien vers le Workshop",
|
||||
privilege = "Basic Commands",
|
||||
OnRun = function(self, client)
|
||||
net.Start("ixOpenURL")
|
||||
net.WriteString(ix.config.Get("ContentLink"))
|
||||
net.Send(client)
|
||||
end
|
||||
})
|
||||
ix.command.Add("Forum", {
|
||||
description = "Obtenir un lien vers les forums",
|
||||
privilege = "Basic Commands",
|
||||
OnRun = function(self, client)
|
||||
net.Start("ixOpenURL")
|
||||
net.WriteString(ix.config.Get("ForumLink"))
|
||||
net.Send(client)
|
||||
end,
|
||||
bNoIndicator = true
|
||||
})
|
||||
|
||||
--Basic Admin
|
||||
ix.command.Add("PGI", {
|
||||
description = "Obtenez les informations de base de quelqu'un et copiez son SteamID.",
|
||||
arguments = {
|
||||
bit.bor(ix.type.player, ix.type.optional)
|
||||
},
|
||||
--alias = "PlyGetInfo",
|
||||
privilege = "Commandes d'administration de base",
|
||||
OnRun = function(self, client, target)
|
||||
if (!target) then
|
||||
target = client:GetEyeTraceNoCursor().Entity
|
||||
end
|
||||
|
||||
if (!IsValid(target) or !target:IsPlayer()) then
|
||||
client:NotifyLocalized("bastionPGIInvalidTarget")
|
||||
return
|
||||
end
|
||||
|
||||
net.Start("ixPlayerInfo")
|
||||
net.WriteEntity(target)
|
||||
net.Send(client)
|
||||
end,
|
||||
bNoIndicator = true
|
||||
})
|
||||
|
||||
ix.command.Add("PrintStaffList", {
|
||||
alias = "PSL",
|
||||
description = "Imprimez une liste des membres du personnel en ligne.",
|
||||
OnRun = function(self, client)
|
||||
local staff = {}
|
||||
local bFound = false
|
||||
for _, v in ipairs(player.GetAll()) do
|
||||
local incognitoSetting = ix.option.Get(v, "iconIncognitoMode", false)
|
||||
local iconIncognitoMode = !client:IsAdmin() and !client:IsSuperAdmin() and incognitoSetting
|
||||
if (v:IsAdmin() or v:IsSuperAdmin()) and !iconIncognitoMode then
|
||||
local userGroup = v:GetUserGroup()
|
||||
staff[userGroup] = staff[userGroup] or {}
|
||||
staff[userGroup][#staff[userGroup] + 1] = v
|
||||
bFound = true
|
||||
end
|
||||
end
|
||||
|
||||
local toSend = {}
|
||||
for k, v in pairs(staff) do
|
||||
toSend[#toSend + 1] = {name = k, players = v}
|
||||
end
|
||||
table.SortByMember(toSend, "name", true)
|
||||
|
||||
if (bFound) then
|
||||
net.Start("ixStaffList")
|
||||
net.WriteUInt(#toSend, 8)
|
||||
for _, v in ipairs(toSend) do
|
||||
net.WriteString(v.name)
|
||||
net.WriteUInt(#v.players, 8)
|
||||
for i = 1, #v.players do
|
||||
net.WriteEntity(v.players[i])
|
||||
end
|
||||
end
|
||||
net.Send(client)
|
||||
else
|
||||
client:Notify("Il n'y a pas de STAFF en ligne actuellement.")
|
||||
end
|
||||
end,
|
||||
bNoIndicator = true
|
||||
})
|
||||
|
||||
ix.command.Add("PrintFactionList", {
|
||||
alias = "PFL",
|
||||
description = "Imprimer une liste des membres d'une faction actuellement en ligne (y compris sur un autre personnage).",
|
||||
arguments = {
|
||||
ix.type.string
|
||||
},
|
||||
privilege = "Basic Admin Commands",
|
||||
OnRun = function(self, client, name)
|
||||
if (name == "") then
|
||||
return "@invalidArg", 2
|
||||
end
|
||||
|
||||
local faction = ix.faction.teams[name]
|
||||
|
||||
if (!faction) then
|
||||
for _, v in ipairs(ix.faction.indices) do
|
||||
if (ix.util.StringMatches(L(v.name, client), name) or ix.util.StringMatches(v.uniqueID, name)) then
|
||||
faction = v
|
||||
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (faction) then
|
||||
local players = {}
|
||||
for _, v in ipairs(player.GetAll()) do
|
||||
if (v:HasWhitelist(faction.index)) then
|
||||
players[#players + 1] = v
|
||||
end
|
||||
end
|
||||
net.Start("ixStaffList")
|
||||
net.WriteUInt(1, 8)
|
||||
net.WriteString(faction.name)
|
||||
net.WriteUInt(#players, 8)
|
||||
for i = 1, #players do
|
||||
net.WriteEntity(players[i])
|
||||
end
|
||||
net.Send(client)
|
||||
else
|
||||
return "@invalidFaction"
|
||||
end
|
||||
end,
|
||||
bNoIndicator = true
|
||||
})
|
||||
|
||||
ix.command.Add("PlaySound", {
|
||||
description = "Jouez un son pour tous les joueurs (lorsqu'aucune portée n'est donnée) ou ceux qui sont proches de vous.",
|
||||
arguments = {
|
||||
ix.type.string,
|
||||
bit.bor(ix.type.number, ix.type.optional)
|
||||
},
|
||||
privilege = "Basic Admin Commands",
|
||||
OnRun = function(self, client, sound, range)
|
||||
local targets = range and {} or player.GetAll()
|
||||
if (range) then
|
||||
range = range * range
|
||||
local clientPos = client:EyePos()
|
||||
for _, target in ipairs(player.GetAll()) do
|
||||
if (target:EyePos():DistToSqr(clientPos) < range) then
|
||||
targets[#targets + 1] = target
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
net.Start("ixPlaySound")
|
||||
net.WriteString(PLUGIN.soundAlias[sound] or sound)
|
||||
net.Send(targets)
|
||||
end,
|
||||
indicator = "chatPerforming"
|
||||
})
|
||||
|
||||
ix.command.Add("ScreenShake", {
|
||||
description = "Shakes the screen of everyone in the specified range. Specify the amplitude, the frequency and the radius for it to work.",
|
||||
arguments = {
|
||||
ix.type.number,
|
||||
ix.type.number,
|
||||
ix.type.number,
|
||||
ix.type.number
|
||||
},
|
||||
argumentNames = {"time(seconds)", "amplitude", "frequency", "radius"},
|
||||
privilege = "Basic Admin Commands",
|
||||
OnRun = function(self, client, seconds, strength, frequency, radius)
|
||||
local vector = client:GetPos()
|
||||
util.ScreenShake(vector, strength or 5, frequency or 5, seconds, radius)
|
||||
end,
|
||||
indicator = "chatPerforming"
|
||||
})
|
||||
|
||||
ix.command.Add("PlaySoundGlobal", {
|
||||
description = "Jouez un son pour tous les joueurs.",
|
||||
arguments = {
|
||||
ix.type.string,
|
||||
},
|
||||
privilege = "Basic Admin Commands",
|
||||
OnRun = function(self, client, sound)
|
||||
net.Start("ixPlaySound")
|
||||
net.WriteString(PLUGIN.soundAlias[sound] or sound)
|
||||
net.WriteBool(true)
|
||||
net.Send(player.GetAll())
|
||||
end,
|
||||
indicator = "chatPerforming"
|
||||
})
|
||||
|
||||
ix.command.Add("ShowEdicts", {
|
||||
description = "Renvoie le nombre d'entités en réseau actuellement sur le serveur.",
|
||||
privilege = "Basic Admin Commands",
|
||||
OnRun = function(self, client)
|
||||
local edictsCount = ents.GetEdictCount()
|
||||
local edictsLeft = 8192 - edictsCount
|
||||
|
||||
return string.format("Il y a actuellement %s édits sur le serveur. Vous pouvez avoir jusqu'à %s de plus.", edictsCount, edictsLeft)
|
||||
end,
|
||||
bNoIndicator = true
|
||||
})
|
||||
|
||||
ix.command.Add("ShowEntsInRadius", {
|
||||
description = "Affiche une liste d'entités dans un rayon donné.",
|
||||
privilege = "Basic Admin Commands",
|
||||
arguments = {ix.type.number},
|
||||
OnRun = function(self, client, radius)
|
||||
local entities = {}
|
||||
local pos = client:GetPos()
|
||||
for _, v in pairs(ents.FindInSphere(pos, radius)) do
|
||||
if (!IsValid(v)) then continue end
|
||||
entities[#entities + 1] = table.concat({v:EntIndex(), v:GetClass(), v:GetModel() or "no model", v:GetPos():Distance(pos), v:MapCreationID()}, ", ")
|
||||
end
|
||||
netstream.Start(client, "ixShowEntsInRadius", table.concat(entities,"\n"))
|
||||
client:NotifyLocalized("entsPrintedInConsole")
|
||||
end,
|
||||
bNoIndicator = true,
|
||||
})
|
||||
|
||||
ix.command.Add("RemoveEntityByID", {
|
||||
description = "Affiche une liste d'entités dans un rayon donné.",
|
||||
superAdminOnly = true,
|
||||
arguments = {ix.type.number},
|
||||
OnRun = function(self, client, number)
|
||||
local entity = Entity(number)
|
||||
if (IsValid(entity)) then
|
||||
client:NotifyLocalized("entityRemoved", number, entity:GetClass())
|
||||
entity:Remove()
|
||||
else
|
||||
client:NotifyLocalized("entityNotFound", number)
|
||||
end
|
||||
end,
|
||||
bNoIndicator = true,
|
||||
})
|
||||
|
||||
if (CLIENT) then
|
||||
netstream.Hook("ixShowEntsInRadius", function(text)
|
||||
print(text)
|
||||
end)
|
||||
end
|
||||
|
||||
ix.command.Add("LocalEvent", {
|
||||
description = "@cmdLocalEvent",
|
||||
privilege = "Event",
|
||||
arguments = {
|
||||
ix.type.string,
|
||||
bit.bor(ix.type.number, ix.type.optional)
|
||||
},
|
||||
OnRun = function(self, client, event, range)
|
||||
local _range = range or (ix.config.Get("chatRange", 280) * 2)
|
||||
|
||||
ix.chat.classes.localevent.range = _range * _range
|
||||
|
||||
local doubleCommand = false
|
||||
|
||||
-- This could probably be done a bit smarter but I'm sure it'll do.
|
||||
if (string.Left(string.lower(event), 11) == "/localevent") then
|
||||
doubleCommand = true
|
||||
|
||||
event = string.Right(event, #event - 12)
|
||||
elseif (string.Left(string.lower(event), 10) == "localevent") then
|
||||
doubleCommand = true
|
||||
|
||||
event = string.Right(event, #event - 11)
|
||||
end
|
||||
|
||||
if (doubleCommand) then
|
||||
client:NotifyLocalized("textDoubleCommand", "/LocalEvent")
|
||||
end
|
||||
|
||||
ix.chat.Send(client, "localevent", event)
|
||||
end,
|
||||
indicator = "chatPerforming"
|
||||
})
|
||||
|
||||
ix.command.Add("RemovePersistedProps", {
|
||||
description = "@cmdRemovePersistedProps",
|
||||
superAdminOnly = true,
|
||||
arguments = {
|
||||
ix.type.number
|
||||
},
|
||||
OnRun = function(self, client, radius)
|
||||
if (radius < 0) then
|
||||
client:Notify("Radius must be a positive number!")
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
for _, entity in ipairs(ents.FindInSphere(client:GetPos(), radius)) do
|
||||
if (!entity:GetNetVar("Persistent")) then continue end
|
||||
|
||||
entity:Remove()
|
||||
end
|
||||
|
||||
client:Notify("Removed all persisted props in a radius of " .. radius .. " units.")
|
||||
end
|
||||
})
|
||||
|
||||
ix.command.Add("Announce", {
|
||||
description = "@cmdAnnounce",
|
||||
arguments = {
|
||||
ix.type.text
|
||||
},
|
||||
OnRun = function(self, client, event)
|
||||
ix.chat.Send(client, "announcement", event)
|
||||
end,
|
||||
OnCheckAccess = function(self, client)
|
||||
return !client or CAMI.PlayerHasAccess(client, "Helix - Basic Admin Commands")
|
||||
end,
|
||||
indicator = "chatTyping"
|
||||
})
|
||||
|
||||
|
||||
-- Help
|
||||
ix.command.Add("Help", {
|
||||
description = "@cmdStaffHelp",
|
||||
arguments = ix.type.text,
|
||||
alias = {"GMHelp", "ModHelp"},
|
||||
OnRun = function(self, client, text)
|
||||
client:Say("@ " .. text)
|
||||
end,
|
||||
OnCheckAccess = function(self, client)
|
||||
return !CAMI.PlayerHasAccess(client, "Helix - Hear Staff Chat")
|
||||
end,
|
||||
indicator = "chatTyping"
|
||||
})
|
||||
|
||||
-- Admin Chat
|
||||
ix.command.Add("Staff", {
|
||||
description = "Discutez avec d'autres membres du STAFF.",
|
||||
arguments = ix.type.text,
|
||||
privilege = "Hear Staff Chat",
|
||||
alias = {"Op", "Mod", "ModChat"},
|
||||
OnRun = function(self, client, text)
|
||||
ix.chat.Send(client, "staff_chat", text)
|
||||
end,
|
||||
indicator = "chatTyping"
|
||||
})
|
||||
|
||||
-- Gamemaster Chat
|
||||
ix.command.Add("GameMaster", {
|
||||
description = "Discutez avec d'autres Gamemasters.",
|
||||
arguments = ix.type.text,
|
||||
privilege = "Hear GM Chat",
|
||||
alias = {"GMChat", "GM"},
|
||||
OnRun = function(self, client, text)
|
||||
ix.chat.Send(client, "gm_chat", text)
|
||||
end,
|
||||
indicator = "chatTyping"
|
||||
})
|
||||
|
||||
-- Mentor Chat
|
||||
ix.command.Add("Mentor", {
|
||||
description = "Discutez avec d'autres mentors.",
|
||||
arguments = ix.type.text,
|
||||
privilege = "Hear Mentor Chat",
|
||||
alias = {"MChat", "M"},
|
||||
OnRun = function(self, client, text)
|
||||
ix.chat.Send(client, "mentor_chat", text)
|
||||
end,
|
||||
indicator = "chatTyping"
|
||||
})
|
||||
|
||||
-- Fun Stuff
|
||||
ix.command.Add("Achievement", {
|
||||
description = "Quelqu'un a gagné une réalisation spéciale !",
|
||||
arguments = {
|
||||
ix.type.player,
|
||||
ix.type.text
|
||||
},
|
||||
privilege = "Fun Stuff",
|
||||
OnRun = function(self, client, target, text)
|
||||
ix.chat.Send(client, "achievement_get", text, false, nil,
|
||||
{target, "ambient/water/drip" .. math.random( 1, 4 ) .. ".wav"})
|
||||
end,
|
||||
indicator = "chatTyping"
|
||||
})
|
||||
ix.command.Add("DarwinAward", {
|
||||
description = "Quelqu'un a mérité un exploit : il a fait le sacrifice ultime pour augmenter le QI moyen de l'humanité.",
|
||||
arguments = {
|
||||
ix.type.player
|
||||
},
|
||||
privilege = "Fun Stuff",
|
||||
OnRun = function(self, client, target)
|
||||
if (!target:Alive()) then
|
||||
local pos = target:GetPos()
|
||||
target:Spawn()
|
||||
|
||||
target:SetPos(pos)
|
||||
end
|
||||
target:SetMoveType(MOVETYPE_WALK)
|
||||
target:SetVelocity(Vector(0, 0, 4000))
|
||||
|
||||
timer.Simple(1, function() PLUGIN:Explode(target) end)
|
||||
ix.chat.Send(client, "achievement_get", "DARWIN AWARD", false, nil,
|
||||
{target, "ambient/alarms/razortrain_horn1.wav"})
|
||||
end,
|
||||
indicator = "chatTyping"
|
||||
})
|
||||
ix.command.Add("PlyRocket", {
|
||||
description = "To infinity, and beyond!.",
|
||||
arguments = {
|
||||
ix.type.player
|
||||
},
|
||||
privilege = "Fun Stuff",
|
||||
OnRun = function(self, client, target)
|
||||
if (!target:Alive()) then
|
||||
local pos = target:GetPos()
|
||||
target:Spawn()
|
||||
|
||||
target:SetPos(pos)
|
||||
end
|
||||
target:SetMoveType(MOVETYPE_WALK)
|
||||
target:SetVelocity(Vector(0, 0, 4000))
|
||||
|
||||
timer.Simple(1, function() PLUGIN:Explode(target) end)
|
||||
end,
|
||||
bNoIndicator = true
|
||||
})
|
||||
|
||||
ix.command.Add("SetTimeScale", {
|
||||
description = "@cmdTimeScale",
|
||||
arguments = {
|
||||
bit.bor(ix.type.number, ix.type.optional)
|
||||
},
|
||||
privilege = "Fun Stuff",
|
||||
OnRun = function(self, client, number)
|
||||
local scale = math.Clamp(number or 1, 0.001, 5)
|
||||
game.SetTimeScale(scale)
|
||||
|
||||
for _, v in ipairs(player.GetAll()) do
|
||||
if (self:OnCheckAccess(v)) then
|
||||
v:NotifyLocalized("bastionTimeScale", client:Name(), scale)
|
||||
end
|
||||
end
|
||||
end,
|
||||
bNoIndicator = true
|
||||
})
|
||||
|
||||
ix.command.Add("SetGravity", {
|
||||
description = "@cmdGravity",
|
||||
arguments = {
|
||||
bit.bor(ix.type.number, ix.type.optional)
|
||||
},
|
||||
privilege = "Fun Stuff",
|
||||
OnRun = function(self, client, number)
|
||||
RunConsoleCommand("sv_gravity", number)
|
||||
|
||||
for _, v in ipairs(player.GetAll()) do
|
||||
if (self:OnCheckAccess(v)) then
|
||||
v:NotifyLocalized("bastionGravity", client:Name(), number)
|
||||
end
|
||||
end
|
||||
end,
|
||||
bNoIndicator = true
|
||||
})
|
||||
|
||||
-- lookup commands
|
||||
ix.command.Add("LookupSteamID", {
|
||||
description = "Lookup a SteamID in the Bastion user database",
|
||||
arguments = {
|
||||
ix.type.text
|
||||
},
|
||||
privilege = "Bastion Lookup",
|
||||
OnRun = function(self, client, target)
|
||||
if (string.find(target, "^STEAM_%d+:%d+:%d+$")) then
|
||||
PLUGIN:LookupSteamID(client, target)
|
||||
return
|
||||
elseif (string.len(target) == 17 and string.find(target, "^%d+$")) then
|
||||
PLUGIN:LookupSteamID(client, target)
|
||||
return
|
||||
end
|
||||
|
||||
target = ix.util.FindPlayer(target, false)
|
||||
client:NotifyLocalized("bastionTargetSelected", target:Name())
|
||||
|
||||
PLUGIN:LookupSteamID(client, target:SteamID64())
|
||||
end,
|
||||
bNoIndicator = true
|
||||
})
|
||||
|
||||
ix.command.Add("LookupIPUsers", {
|
||||
description = "Lookup a SteamID in the Bastion IP database",
|
||||
arguments = {
|
||||
ix.type.text
|
||||
},
|
||||
privilege = "Bastion Lookup",
|
||||
OnRun = function(self, client, target)
|
||||
if (string.find(target, "^STEAM_%d+:%d+:%d+$")) then
|
||||
PLUGIN:LookupIPUsers(client, target)
|
||||
return
|
||||
elseif (string.len(target) == 17 and string.find(target, "^%d+$")) then
|
||||
PLUGIN:LookupIPUsers(client, target)
|
||||
return
|
||||
end
|
||||
|
||||
target = ix.util.FindPlayer(target, false)
|
||||
client:NotifyLocalized("bastionTargetSelected", target:Name())
|
||||
|
||||
PLUGIN:LookupIPUsers(client, target:SteamID64())
|
||||
end,
|
||||
bNoIndicator = true
|
||||
})
|
||||
|
||||
ix.command.Add("ProxyWhitelist", {
|
||||
description = "Whitelist a player as trusted to disable future proxy checks.",
|
||||
arguments = {
|
||||
ix.type.player
|
||||
},
|
||||
privilege = "Bastion Whitelist",
|
||||
OnRun = function(self, client, target)
|
||||
if (PLUGIN:WhitelistPlayer(target)) then
|
||||
client:NotifyLocalized("whitelistDone")
|
||||
else
|
||||
client:NotifyLocalized("whitelistError")
|
||||
end
|
||||
end,
|
||||
indicator = "chatTyping"
|
||||
})
|
||||
|
||||
ix.command.Add("PlyGetCharacters", {
|
||||
description = "Get a list of a player's characters.",
|
||||
arguments = {
|
||||
ix.type.player
|
||||
},
|
||||
adminOnly = true,
|
||||
OnRun = function(self, client, target)
|
||||
client:ChatNotify(target:SteamName() .. "'s characters:")
|
||||
client:ChatNotify("====================")
|
||||
|
||||
for _, character in pairs(target.ixCharList) do
|
||||
client:ChatNotify(ix.char.loaded[character].vars.name)
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
|
||||
ix.command.Add("LTARP", {
|
||||
description = "Automatically ban a player for leaving to avoid RP after a grace period.",
|
||||
arguments = {
|
||||
ix.type.string,
|
||||
ix.type.number,
|
||||
bit.bor(ix.type.text, ix.type.optional),
|
||||
},
|
||||
adminOnly = true,
|
||||
OnRun = function(self, client, steamID, days, reason)
|
||||
local target = player.GetBySteamID64(steamID) or player.GetBySteamID(steamID)
|
||||
if (target) then
|
||||
client:Notify(target:SteamName().." is still on the server as '"..target:Name().."!")
|
||||
return
|
||||
end
|
||||
|
||||
if (days > 100) then
|
||||
client:Notify("Invalid duration entered. Max ban length is 100 days.")
|
||||
return
|
||||
end
|
||||
|
||||
if (string.find(string.upper(steamID), "^STEAM")) then
|
||||
steamID = util.SteamIDTo64(string.upper(steamID))
|
||||
end
|
||||
|
||||
if (!PLUGIN.disconnects[steamID]) then
|
||||
client:Notify("Could not find a disconnect for "..steamID..", manually ban them if needed.")
|
||||
return
|
||||
end
|
||||
|
||||
local info = PLUGIN.disconnects[steamID]
|
||||
if (info.timer) then
|
||||
client:Notify(steamID.." is already tagged for LTARP by "..info.bannedByName..".")
|
||||
return
|
||||
end
|
||||
|
||||
local reconnectTime, maxBanDelay = 30, 40
|
||||
if (info.time + reconnectTime * 60 < os.time()) then
|
||||
if (info.time + maxBanDelay * 60 < os.time()) then
|
||||
client:Notify(steamID.." disconnected more than "..maxBanDelay.." minutes ago already. Manually ban them if needed.")
|
||||
return
|
||||
end
|
||||
|
||||
RunConsoleCommand("sam", "banid", steamID, tostring(days * 60 * 24), reason != "" and reason or "Leaving to avoid RP. Appeal on willard.network ~"..client:SteamName())
|
||||
return
|
||||
end
|
||||
|
||||
local uniqueID = "ixLTARP"..steamID
|
||||
local bannedBy = client and client:SteamName() or "console"
|
||||
timer.Create(uniqueID, info.time - os.time() + reconnectTime * 60, 1, function()
|
||||
if (IsValid(client)) then
|
||||
client:Notify(steamID.." did not reconnect and has been banned.")
|
||||
end
|
||||
RunConsoleCommand("sam", "banid", steamID, tostring(days * 60 * 24), reason != "" and reason or "Leaving to avoid RP. Appeal on willard.network ~"..bannedBy)
|
||||
end)
|
||||
|
||||
info.timer = uniqueID
|
||||
info.bannedBy = client
|
||||
info.bannedByName = client and client:SteamName() or "console"
|
||||
client:Notify("Timer set! "..steamID.." will be banned in "..math.ceil((info.time - os.time() + reconnectTime * 60) / 60).." minutes.")
|
||||
end
|
||||
})
|
||||
324
gamemodes/helix/plugins/bastion/sh_context.lua
Normal file
324
gamemodes/helix/plugins/bastion/sh_context.lua
Normal file
@@ -0,0 +1,324 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
local properties = properties
|
||||
local IsValid = IsValid
|
||||
local RunConsoleCommand = RunConsoleCommand
|
||||
local tostring = tostring
|
||||
|
||||
local Derma_StringRequest = Derma_StringRequest
|
||||
local CAMI = CAMI
|
||||
local hook = hook
|
||||
local SetClipboardText = SetClipboardText
|
||||
local LocalPlayer = LocalPlayer
|
||||
local net = net
|
||||
local ix = ix
|
||||
|
||||
local PLUGIN = PLUGIN
|
||||
|
||||
properties.Add("ixCopyCharName", {
|
||||
MenuLabel = "#Copy Character Name",
|
||||
Order = 0,
|
||||
MenuIcon = "icon16/user.png",
|
||||
|
||||
Filter = function(self, target)
|
||||
return target:IsPlayer()
|
||||
and CAMI.PlayerHasAccess(LocalPlayer(), "Helix - Basic Admin Commands")
|
||||
and hook.Run("CanProperty", LocalPlayer(), "ixCopyCharName", target) != false
|
||||
end,
|
||||
|
||||
Action = function(self, target)
|
||||
SetClipboardText(target:Name())
|
||||
LocalPlayer():NotifyLocalized("bastionCopiedCharName")
|
||||
end,
|
||||
})
|
||||
|
||||
properties.Add("ixCopySteamName", {
|
||||
MenuLabel = "#Copy Steam Name",
|
||||
Order = 1,
|
||||
MenuIcon = "icon16/user.png",
|
||||
|
||||
Filter = function(self, target)
|
||||
return target:IsPlayer()
|
||||
and CAMI.PlayerHasAccess(LocalPlayer(), "Helix - Basic Admin Commands")
|
||||
and hook.Run("CanProperty", LocalPlayer(), "ixCopySteamName", target) != false
|
||||
end,
|
||||
|
||||
Action = function(self, target)
|
||||
SetClipboardText(target:SteamName())
|
||||
LocalPlayer():NotifyLocalized("bastionCopiedSteamName")
|
||||
end,
|
||||
})
|
||||
|
||||
properties.Add("ixCopySteamID", {
|
||||
MenuLabel = "#Copy Steam ID",
|
||||
Order = 2,
|
||||
MenuIcon = "icon16/user.png",
|
||||
|
||||
Filter = function(self, target)
|
||||
return target:IsPlayer()
|
||||
and CAMI.PlayerHasAccess(LocalPlayer(), "Helix - Basic Admin Commands")
|
||||
and hook.Run("CanProperty", LocalPlayer(), "ixCopySteamID", target) != false
|
||||
end,
|
||||
|
||||
Action = function(self, target)
|
||||
SetClipboardText(target:SteamID())
|
||||
LocalPlayer():NotifyLocalized("bastionCopiedSteamID")
|
||||
end,
|
||||
})
|
||||
|
||||
properties.Add("ixViewInventory", {
|
||||
MenuLabel = "#View Inventory",
|
||||
Order = 10,
|
||||
MenuIcon = "icon16/eye.png",
|
||||
PrependSpacer = true,
|
||||
|
||||
Filter = function(self, target, client)
|
||||
client = client or LocalPlayer()
|
||||
return target:IsPlayer()
|
||||
and CAMI.PlayerHasAccess(client, "Helix - View Inventory")
|
||||
and hook.Run("CanProperty", client, "ixViewInventory", target) != false
|
||||
end,
|
||||
|
||||
Action = function(self, target)
|
||||
self:MsgStart()
|
||||
net.WriteEntity(target)
|
||||
self:MsgEnd()
|
||||
end,
|
||||
|
||||
Receive = function(self, length, client)
|
||||
local target = net.ReadEntity()
|
||||
|
||||
if (!IsValid(target)) then return end
|
||||
if (!self:Filter(target, client)) then return end
|
||||
|
||||
PLUGIN:OpenInventory(client, target)
|
||||
end
|
||||
})
|
||||
|
||||
properties.Add("ixSetHealth", {
|
||||
MenuLabel = "#Health",
|
||||
Order = 100,
|
||||
PrependSpacer = true,
|
||||
MenuIcon = "icon16/heart.png",
|
||||
|
||||
Filter = function(self, target, client)
|
||||
client = client or LocalPlayer()
|
||||
return target:IsPlayer()
|
||||
and (sam and (client:HasPermission("hp") or client:HasPermission("slay"))
|
||||
or CAMI.PlayerHasAccess(client, "Helix - Basic Admin Commands"))
|
||||
and hook.Run("CanProperty", client, "ixSetHealth", target) != false
|
||||
end,
|
||||
|
||||
MenuOpen = function(self, option, target)
|
||||
local submenu = option:AddSubMenu()
|
||||
local maxHealth = target:GetMaxHealth()
|
||||
local step = maxHealth > 100 and -50 or -25
|
||||
|
||||
if (sam) then
|
||||
if (LocalPlayer():HasPermission("hp")) then
|
||||
for i = maxHealth, 1, step do
|
||||
submenu:AddOption(i, function() RunConsoleCommand("sam", "hp", target:SteamID(), tostring(i)) end)
|
||||
end
|
||||
submenu:AddOption("1", function() RunConsoleCommand("sam", "hp", target:SteamID(), "1") end)
|
||||
end
|
||||
|
||||
if (LocalPlayer():HasPermission("slay")) then
|
||||
submenu:AddOption("Kill", function() RunConsoleCommand("sam", "slay", target:SteamID()) end)
|
||||
end
|
||||
else
|
||||
for i = maxHealth, 1, step do
|
||||
submenu:AddOption(i, function() self:SetHealth(target, i) end)
|
||||
end
|
||||
|
||||
submenu:AddOption("1", function() self:SetHealth(target, 1) end)
|
||||
submenu:AddOption("Kill", function() self:SetHealth(target, 0) end)
|
||||
end
|
||||
end,
|
||||
|
||||
SetHealth = function(self, target, health)
|
||||
self:MsgStart()
|
||||
net.WriteEntity(target)
|
||||
net.WriteUInt(health, 16)
|
||||
self:MsgEnd()
|
||||
end,
|
||||
|
||||
Receive = function(self, length, client)
|
||||
local target = net.ReadEntity()
|
||||
local health = net.ReadUInt(16)
|
||||
|
||||
if (!IsValid(target)) then return end
|
||||
if (!self:Filter(target, client)) then return end
|
||||
|
||||
if (health > 0) then
|
||||
target:SetHealth(health)
|
||||
ix.log.Add(client, "bastionSetHealth", target)
|
||||
else
|
||||
target:Kill()
|
||||
ix.log.Add(client, "bastionSlay", target)
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
properties.Add("ixSetArmor", {
|
||||
MenuLabel = "#Armor",
|
||||
Order = 110,
|
||||
MenuIcon = "icon16/heart.png",
|
||||
|
||||
Filter = function(self, target, client)
|
||||
client = client or LocalPlayer()
|
||||
return target:IsPlayer()
|
||||
and (sam and client:HasPermission("armor")
|
||||
or CAMI.PlayerHasAccess(client, "Helix - Basic Admin Commands"))
|
||||
and hook.Run("CanProperty", client, "ixSetArmor", target) != false
|
||||
end,
|
||||
|
||||
MenuOpen = function(self, option, target)
|
||||
local submenu = option:AddSubMenu()
|
||||
local maxArmor = 100
|
||||
local step = maxArmor > 100 and -50 or -10
|
||||
|
||||
if (sam) then
|
||||
for i = maxArmor, 1, step do
|
||||
submenu:AddOption(i, function() RunConsoleCommand("sam", "armor", target:SteamID(), tostring(i)) end)
|
||||
end
|
||||
submenu:AddOption("Remove", function() RunConsoleCommand("sam", "armor", target:SteamID(), "0") end)
|
||||
else
|
||||
for i = maxArmor, 1, step do
|
||||
submenu:AddOption(i, function() self:SetArmor(target, i) end)
|
||||
end
|
||||
|
||||
submenu:AddOption("Remove", function() self:SetArmor(target, 0) end)
|
||||
end
|
||||
end,
|
||||
|
||||
SetArmor = function(self, target, armor)
|
||||
self:MsgStart()
|
||||
net.WriteEntity(target)
|
||||
net.WriteUInt(armor, 16)
|
||||
self:MsgEnd()
|
||||
end,
|
||||
|
||||
Receive = function(self, length, client)
|
||||
local target = net.ReadEntity()
|
||||
local armor = net.ReadUInt(16)
|
||||
|
||||
if (!IsValid(target)) then return end
|
||||
if (!self:Filter(target, client)) then return end
|
||||
|
||||
target:SetArmor(armor)
|
||||
ix.log.Add(client, "bastionSetArmor", target)
|
||||
end
|
||||
})
|
||||
|
||||
properties.Add("ixSetCharName", {
|
||||
MenuLabel = "#Set Name",
|
||||
Order = 120,
|
||||
MenuIcon = "icon16/book_edit.png",
|
||||
PrependSpacer = true,
|
||||
|
||||
Filter = function(self, entity, client)
|
||||
return CAMI.PlayerHasAccess(client, "Helix - CharSetName", nil) and entity:IsPlayer() and entity:GetCharacter()
|
||||
end,
|
||||
|
||||
Action = function(self, entity)
|
||||
Derma_StringRequest("Set Name", "Set the character's name", entity:Name(), function(text)
|
||||
if (text == "") then return end
|
||||
|
||||
self:MsgStart()
|
||||
net.WriteEntity(entity)
|
||||
net.WriteString(text)
|
||||
self:MsgEnd()
|
||||
end)
|
||||
|
||||
end,
|
||||
|
||||
Receive = function(self, length, client)
|
||||
if (CAMI.PlayerHasAccess(client, "Helix - CharSetName", nil)) then
|
||||
local entity = net.ReadEntity()
|
||||
local text = net.ReadString()
|
||||
|
||||
if (IsValid(entity) and entity:IsPlayer() and entity:GetCharacter()) then
|
||||
local oldName = entity:GetCharacter():GetName()
|
||||
entity:GetCharacter():SetName(text)
|
||||
|
||||
ix.log.Add(client, "bastionSetName", entity:GetCharacter(), oldName)
|
||||
end
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
properties.Add("ixSetCharDescription", {
|
||||
MenuLabel = "#Set Description",
|
||||
Order = 121,
|
||||
MenuIcon = "icon16/book_edit.png",
|
||||
|
||||
Filter = function(self, entity, client)
|
||||
return CAMI.PlayerHasAccess(client, "Helix - Basic Admin Commands", nil) and entity:IsPlayer() and entity:GetCharacter()
|
||||
end,
|
||||
|
||||
Action = function(self, entity)
|
||||
Derma_StringRequest("Set Description", "Set the character's description", entity:GetCharacter():GetDescription(), function(text)
|
||||
if (text == "") then return end
|
||||
|
||||
self:MsgStart()
|
||||
net.WriteEntity(entity)
|
||||
net.WriteString(text)
|
||||
self:MsgEnd()
|
||||
end)
|
||||
|
||||
end,
|
||||
|
||||
Receive = function(self, length, client)
|
||||
if (CAMI.PlayerHasAccess(client, "Helix - Basic Admin Commands", nil)) then
|
||||
local entity = net.ReadEntity()
|
||||
local text = net.ReadString()
|
||||
|
||||
if (IsValid(entity) and entity:IsPlayer() and entity:GetCharacter()) then
|
||||
entity:GetCharacter():SetDescription(text)
|
||||
|
||||
ix.log.Add(client, "bastionSetDesc", entity:GetCharacter())
|
||||
end
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
properties.Add("ixPropViewOwner", {
|
||||
MenuLabel = "Voir propriétaire",
|
||||
Order = 405,
|
||||
MenuIcon = "icon16/magnifier.png",
|
||||
|
||||
Filter = function(self, entity, client)
|
||||
if (entity:GetClass() == "prop_physics" and CAMI.PlayerHasAccess(client, "Helix - Basic Admin Commands", nil)) then return true end
|
||||
end,
|
||||
|
||||
Action = function(self, entity)
|
||||
self:MsgStart()
|
||||
net.WriteEntity(entity)
|
||||
self:MsgEnd()
|
||||
end,
|
||||
|
||||
Receive = function(self, length, client)
|
||||
local entity = net.ReadEntity()
|
||||
|
||||
if (!IsValid(entity)) then return end
|
||||
if (!self:Filter(entity, client)) then return end
|
||||
|
||||
local ownerCharacter = entity.ownerCharacter
|
||||
local ownerName = entity.ownerName
|
||||
local ownerSteamID = entity.ownerSteamID
|
||||
|
||||
if (ownerCharacter and ownerName and ownerSteamID) then
|
||||
client:ChatNotifyLocalized("bastionPropOwnerInformation", ownerCharacter, ownerName, ownerSteamID)
|
||||
else
|
||||
client:ChatNotifyLocalized("bastionPropOwnerUnknown")
|
||||
end
|
||||
end
|
||||
})
|
||||
54
gamemodes/helix/plugins/bastion/sh_hooks.lua
Normal file
54
gamemodes/helix/plugins/bastion/sh_hooks.lua
Normal file
@@ -0,0 +1,54 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
-- Remake the connect & disconnect chat classes to stop the default ones.
|
||||
function PLUGIN:InitializedChatClasses()
|
||||
ix.chat.classes["connect"] = nil
|
||||
ix.chat.classes["disconnect"] = nil
|
||||
|
||||
ix.chat.Register("new_connect", {
|
||||
CanSay = function(_, speaker, text)
|
||||
return !IsValid(speaker)
|
||||
end,
|
||||
OnChatAdd = function(_, speaker, text)
|
||||
local icon = ix.util.GetMaterial("willardnetworks/chat/connected_icon.png")
|
||||
|
||||
chat.AddText(icon, Color(151, 153, 152), L("playerConnected", text))
|
||||
end,
|
||||
noSpaceAfter = true
|
||||
})
|
||||
|
||||
ix.chat.Register("new_disconnect", {
|
||||
CanSay = function(_, speaker, text)
|
||||
return !IsValid(speaker)
|
||||
end,
|
||||
OnChatAdd = function(_, speaker, text)
|
||||
local icon = ix.util.GetMaterial("willardnetworks/chat/disconnected_icon.png")
|
||||
|
||||
chat.AddText(icon, Color(151, 153, 152), L("playerDisconnected", text))
|
||||
end,
|
||||
noSpaceAfter = true
|
||||
})
|
||||
|
||||
ix.chat.Register("bastionPlayerDeath", {
|
||||
CanSay = function(_, speaker, text)
|
||||
return true
|
||||
end,
|
||||
OnChatAdd = function(_, speaker, text)
|
||||
local icon = ix.util.GetMaterial("icon16/user_red.png")
|
||||
|
||||
chat.AddText(icon, Color(255, 0, 0), text)
|
||||
end,
|
||||
CanHear = function(_, speaker, listener)
|
||||
return listener:IsAdmin() and ix.option.Get(listener, "playerDeathNotification")
|
||||
end
|
||||
})
|
||||
end
|
||||
289
gamemodes/helix/plugins/bastion/sh_plugin.lua
Normal file
289
gamemodes/helix/plugins/bastion/sh_plugin.lua
Normal file
@@ -0,0 +1,289 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
local IsValid = IsValid
|
||||
local ix = ix
|
||||
|
||||
PLUGIN.name = "Bastion"
|
||||
PLUGIN.author = "Gr4Ss"
|
||||
PLUGIN.description = "Some admin extensions for Helix."
|
||||
|
||||
local CAMI = CAMI
|
||||
|
||||
CAMI.RegisterPrivilege({
|
||||
Name = "Helix - Hear Staff Chat",
|
||||
MinAccess = "admin"
|
||||
})
|
||||
|
||||
CAMI.RegisterPrivilege({
|
||||
Name = "Helix - Hear GM Chat",
|
||||
MinAccess = "admin"
|
||||
})
|
||||
|
||||
CAMI.RegisterPrivilege({
|
||||
Name = "Helix - Hear Mentor Chat",
|
||||
MinAccess = "admin"
|
||||
})
|
||||
|
||||
CAMI.RegisterPrivilege({
|
||||
Name = "Helix - Fun Stuff",
|
||||
MinAccess = "superadmin"
|
||||
})
|
||||
|
||||
CAMI.RegisterPrivilege({
|
||||
Name = "Helix - Basic Commands",
|
||||
MinAccess = "user"
|
||||
})
|
||||
|
||||
CAMI.RegisterPrivilege({
|
||||
Name = "Helix - Basic Admin Commands",
|
||||
MinAccess = "admin"
|
||||
})
|
||||
|
||||
CAMI.RegisterPrivilege({
|
||||
Name = "Helix - Full Remover Tool",
|
||||
MinAccess = "admin"
|
||||
})
|
||||
|
||||
CAMI.RegisterPrivilege({
|
||||
Name = "Helix - HL2 Tools",
|
||||
MinAccess = "admin"
|
||||
})
|
||||
|
||||
CAMI.RegisterPrivilege({
|
||||
Name = "Helix - Bastion Whitelist",
|
||||
MinAccess = "admin"
|
||||
})
|
||||
|
||||
CAMI.RegisterPrivilege({
|
||||
Name = "Helix - View Inventory",
|
||||
MinAccess = "superadmin"
|
||||
})
|
||||
|
||||
CAMI.RegisterPrivilege({
|
||||
Name = "Helix - Increase Character Limit",
|
||||
MinAccess = "admin"
|
||||
})
|
||||
|
||||
CAMI.RegisterPrivilege({
|
||||
Name = "Helix - Bastion Lookup",
|
||||
MinAccess = "superadmin"
|
||||
})
|
||||
|
||||
CAMI.RegisterPrivilege({
|
||||
Name = "Helix - Container Password",
|
||||
MinAccess = "superadmin"
|
||||
})
|
||||
CAMI.RegisterPrivilege({
|
||||
Name = "Helix - Proxy Notify",
|
||||
MinAccess = "superadmin"
|
||||
})
|
||||
|
||||
ix.option.Add("pgi", ix.type.bool, true, {category = "Administration"})
|
||||
|
||||
ix.option.Add("playerDeathNotification", ix.type.bool, true, {category = "Administration", bNetworked = true})
|
||||
|
||||
ix.config.Add("netLoggingEnabled", false, "Enable or disable net logging into the database (WARNING: PERFORMANCE IMPACT)", nil, {
|
||||
category = "Bastion"
|
||||
})
|
||||
ix.config.Add("netAntiSpam", true, "Enable or disable net anti-spam (WARNING: PERFORMANCE IMPACT)", nil, {
|
||||
category = "Bastion"
|
||||
})
|
||||
ix.config.Add("suppressOnPlayerChat", true, "Suppress the default OnPlayerChat hook (should not be used by helix)", nil, {
|
||||
category = "Bastion"
|
||||
})
|
||||
ix.config.Add("maxCharactersIncreased", 5, "The maximum number of characters a player can have if they have the increased character limit permission.", nil, {
|
||||
data = {min = 1, max = 50},
|
||||
category = "Personnages"
|
||||
})
|
||||
ix.config.Add("charCreateInterval", 5, "How many minutes there should be between 2 successful character creations of one player (to avoid character spam).", nil, {
|
||||
data = {min = 1, max = 50},
|
||||
category = "Personnages"
|
||||
})
|
||||
ix.config.Add("AllowContainerSpawn", false, "Allow anyone to directly spawn containers by spawning in their prop. Disallowing this will require admins to create containers from a prop using the context menu.", nil, {
|
||||
category = "Conteneurs"
|
||||
})
|
||||
ix.config.Add("VPNKick", false, "Kick new users if they use a VPN.", nil, {
|
||||
category = "Bastion"
|
||||
})
|
||||
ix.config.Add("ProxyAlwaysAlert", true, "Always Discord Alert for new joiners with a VPN.", nil, {
|
||||
category = "Bastion"
|
||||
})
|
||||
ix.config.Add("showConnectMessages", true, "Whether or not to show notifications when players connect to the server. When off, only Staff will be notified.", nil, {
|
||||
category = "Serveur"
|
||||
})
|
||||
ix.config.Add("showDisconnectMessages", true, "Whether or not to show notifications when players disconnect from the server. When off, only Staff will be notified.", nil, {
|
||||
category = "Serveur"
|
||||
})
|
||||
ix.config.Add("DiscordLink", "https://discord.gg/HbDjUQd", "Invite link to the discord.", nil, {
|
||||
category = "Bastion"
|
||||
})
|
||||
ix.config.Add("ContentLink", "https://steamcommunity.com/sharedfiles/filedetails/?id=2934933494", "Link to the workshop collection.", nil, {
|
||||
category = "Bastion"
|
||||
})
|
||||
ix.config.Add("ForumLink", "https://willard.network", "Link to the forums", nil, {
|
||||
category = "Bastion"
|
||||
})
|
||||
ix.config.Add("EdictWarningLimit", 1024, "How many edicts can be left before warning messages start to appear.", nil, {
|
||||
data = {min = 100, max = 1024},
|
||||
category = "Bastion"
|
||||
})
|
||||
|
||||
ix.flag.Add("a", "Accès au duplicateur.")
|
||||
|
||||
ix.lang.AddTable("english", {
|
||||
getPlayerInfo = "Get Player Info",
|
||||
optStaffChat = "Show Staff Chat on all characters",
|
||||
optdStaffChat = "Turns on/off staff chat on all characters. When off, will only show staff chat while in observer or on an admin character.",
|
||||
optPgi = "Copy Steam ID to clipboard on 'PGI'/'View Player'",
|
||||
optdPgi = "Allows you to turn on/off the automatic copy-to-clipboard of a player's SteamID when using the PGI command or 'View Player' context menu option.",
|
||||
cmdStaffHelp = "Call for help from all the staff.\n",
|
||||
cmdAnnounce = "Make an OOC admin announcement to the entire server.",
|
||||
cmdLocalEvent = "Make an IC admin event that can only be heard within a given radius.",
|
||||
bastionPGIInvalidTarget = "You must enter or be looking at a valid target.",
|
||||
bastionTakingItemsTooQuickly = "You are taking items too quickly! Please slow down.",
|
||||
bastionItemDropSpamKick = "%s was kicked for item drop exploiting.",
|
||||
bastionItemDropSpamWarn = "%s was warned for item drop exploiting.",
|
||||
bastionItemDropTooQuick = "You are dropping items too quickly! Please slow down.",
|
||||
bastionItemTakeWarn = "%s was warned for taking items too quickly.",
|
||||
bastionItemTakeKick = "%s was kicked for dropping items too quickly.",
|
||||
charCreateTooFast = "You are creating characters too fast. Please wait at least %d minutes between attempts.",
|
||||
bastionCopiedCharName = "Character name copied",
|
||||
bastionCopiedSteamName = "Steam name copied",
|
||||
bastionCopiedSteamID = "Steam ID copied",
|
||||
bastionGoto = "Go to player",
|
||||
bastionCopyCharName = "Copy character name",
|
||||
bastionCopySteamName = "Copy steam name",
|
||||
bastionNoRecordFound = "Could not find any records for %s.",
|
||||
bastionResultsPrinted = "Results were printed in console.",
|
||||
bastionProxyNotify = "%s connected as new player while using a VPN/Proxy.",
|
||||
bastionPropOwnerInformation = "The owner of this prop is %s (%s - %s).",
|
||||
bastionPropOwnerUnknown = "The owner of this prop has not been registered!",
|
||||
whitelistDone = "Player was whitelisted.",
|
||||
whitelistError = "Something went wrong whitelisting the player. Ask a dev.",
|
||||
cmdTimeScale = "Change the timescale (min 0.001, max 5).",
|
||||
bastionTimeScale = "%s has set the timescale to %d.",
|
||||
cmdGravity = "Change the gravity.",
|
||||
bastionGravity = "%s has set the gravity to %d.",
|
||||
edictWarning = "Only %d edicts are left! Total edict count is currently: %d/8192!",
|
||||
edictCritical = "Only %d edicts are left! Total edict count is currently: %d/8192! Emergency Cleanup Required!",
|
||||
entsPrintedInConsole = "Entity list has been printed in console.",
|
||||
entityRemoved = "Entity %d (%s) was removed!",
|
||||
entityNotFound = "Entity %d was not found/is not valid.",
|
||||
optPlayerDeathNotification = "Player Death Notification",
|
||||
optdPlayerDeathNotification = "Whether to send a chat message when a player dies.",
|
||||
cmdRemovePersistedProps = "Remove all persisted props in a radius around you."
|
||||
})
|
||||
|
||||
ix.lang.AddTable("spanish", {
|
||||
bastionCopySteamName = "Copiar nombre de Steam",
|
||||
bastionPGIInvalidTarget = "Debes especificar o estar mirando a un objetivo válido.",
|
||||
cmdLocalEvent = "Haz un evento IC de administrador que sólo pueda ser escuchado dentro de un radio determinado.",
|
||||
bastionNoRecordFound = "No se ha podido encontrar ningún registro para %s.",
|
||||
cmdAnnounce = "Haz un anuncio OOC de administrador a todo el servidor.",
|
||||
cmdGravity = "Cambia la gravedad.",
|
||||
bastionCopiedSteamID = "Steam ID copiada",
|
||||
bastionProxyNotify = "%s se ha conectado como nuevo jugador mientras usa una VPN/Proxy.",
|
||||
bastionTakingItemsTooQuickly = "¡Estás agarrando objetos demasiado rápido! Por favor, reduce la velocidad.",
|
||||
optdStaffChat = "Activa/desactiva el Chat de Staff en todos los personajes. Cuando está desactivado, sólo se mostrará el Chat de Staff mientras se esté en observer o en un personaje administrativo.",
|
||||
entityNotFound = "La entidad %d no fue encontrada/no es válida.",
|
||||
whitelistDone = "El jugador estaba en la Whitelist.",
|
||||
bastionCopiedCharName = "Nombre del personaje copiado",
|
||||
getPlayerInfo = "Obtener información del jugador",
|
||||
bastionCopyCharName = "Copiar el nombre del personaje",
|
||||
charCreateTooFast = "Estás creando personajes demasiado rápido. Por favor, espera al menos %d minutos entre intentos.",
|
||||
entsPrintedInConsole = "La lista de entidades se ha impreso en la consola.",
|
||||
bastionItemDropTooQuick = "¡Estás soltando objetos demasiado rápido! Por favor, baja la velocidad.",
|
||||
bastionGravity = "%s ha fijado la gravedad en %d.",
|
||||
entityRemoved = "¡La entidad %d (%s) ha sido eliminada!",
|
||||
cmdStaffHelp = "Pide ayuda a todo el Staff.\n",
|
||||
bastionCopiedSteamName = "Nombre de Steam copiado",
|
||||
bastionItemTakeWarn = "%s fue advertido por agarrar objetos demasiado rápido.",
|
||||
bastionResultsPrinted = "Los resultados se imprimieron en la consola.",
|
||||
optStaffChat = "Mostrar el Chat de Staff en todos los personajes",
|
||||
bastionGoto = "Ir al jugador",
|
||||
cmdTimeScale = "Cambie la escala de tiempo (mínimo 0,001, máximo 5).",
|
||||
whitelistError = "Algo fue mal cuando se intentó meter al jugador en la whitelist. Contacta con un desarrollador.",
|
||||
bastionTimeScale = "%s ha fijado la escala de tiempo en %d.",
|
||||
bastionItemDropSpamKick = "%s ha sido expulsado por exploits relacionados con item-dropping.",
|
||||
optdPgi = "Te permite activar/desactivar la copia automática al portapapeles del SteamID de un jugador cuando usa el comando PGI o la opción del menú contextual 'Ver Jugador'.",
|
||||
bastionItemDropSpamWarn = "%s ha sido advertido del uso de exploits relacionados con item-dropping.",
|
||||
bastionItemTakeKick = "%s ha sido expulsado por soltar objetos demasiado rápido.",
|
||||
optPgi = "Copiar Steam ID al portapapeles en el 'PGI'/'Ver Jugador'",
|
||||
edictWarning = "¡Solamente quedan disponibles %d edictos! ¡El conteo total de edictos es de: %d/8192!"
|
||||
})
|
||||
|
||||
PLUGIN.soundAlias = {
|
||||
["restricted_block_deploy"] = "voices/dispatch/restrictedblock_deployment.wav",
|
||||
["restricted_block"] = "voices/dispatch/restrictedblock_warning.wav",
|
||||
["access_restricted"] = "voices/dispatch/access_restricted.wav",
|
||||
["anticivil_evading"] = "voices/dispatch/anticivil_evading.wav",
|
||||
["civil_insurrection"] = "voices/dispatch/civil_insurrection.wav",
|
||||
["victory_music"] = "music/scary_tense/victory_music.mp3",
|
||||
}
|
||||
|
||||
ix.util.Include("cl_plugin.lua")
|
||||
ix.util.Include("sh_classes.lua")
|
||||
ix.util.Include("sh_commands.lua")
|
||||
ix.util.Include("sh_context.lua")
|
||||
ix.util.Include("sh_hooks.lua")
|
||||
ix.util.Include("sv_hooks.lua")
|
||||
ix.util.Include("sv_plugin.lua")
|
||||
|
||||
ix.util.Include("modules/sh_bindchecker.lua")
|
||||
|
||||
function PLUGIN:GetMaxPlayerCharacter(client)
|
||||
if (CAMI.PlayerHasAccess(client, "Helix - Increase Character Limit")) then
|
||||
return ix.config.Get("maxCharactersIncreased", 8)
|
||||
end
|
||||
end
|
||||
|
||||
function PLUGIN:CanProperty(client, property, entity)
|
||||
if (property == "container_setpassword" and !CAMI.PlayerHasAccess(client, "Helix - Container Password")) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function PLUGIN:CanPlayerSpawnContainer()
|
||||
if (!ix.config.Get("AllowContainerSpawn")) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function PLUGIN:CanPlayerAccessDoor(client)
|
||||
if (client:GetMoveType() == MOVETYPE_NOCLIP and !client:InVehicle()) then return true end
|
||||
|
||||
if (ix.faction.Get(client:Team()).lockAllDoors) then return true end
|
||||
end
|
||||
|
||||
PLUGIN.removeWhitelist = {
|
||||
["prop_physics"] = true,
|
||||
["prop_ragdoll"] = true
|
||||
}
|
||||
|
||||
local hl2Tools = {
|
||||
["env_headcrabcanister"] = true,
|
||||
["item_ammo_crate"] = true,
|
||||
["item_item_crate"] = true,
|
||||
["prop_door"] = true,
|
||||
["prop_thumper"] = true
|
||||
}
|
||||
|
||||
function PLUGIN:CanTool(client, trace, tool)
|
||||
if (tool == "remover" and !CAMI.PlayerHasAccess(client, "Helix - Full Remover Tool")) then
|
||||
if (IsValid(trace.Entity) and !self.removeWhitelist[trace.Entity:GetClass()]) then
|
||||
return false
|
||||
end
|
||||
elseif (tool == "advdupe2" and !client:GetCharacter():HasFlags("a")) then
|
||||
return false
|
||||
elseif (hl2Tools[tool] and !CAMI.PlayerHasAccess(client, "Helix - HL2 Tools")) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
193
gamemodes/helix/plugins/bastion/sv_hooks.lua
Normal file
193
gamemodes/helix/plugins/bastion/sv_hooks.lua
Normal file
@@ -0,0 +1,193 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
local timer = timer
|
||||
local pairs = pairs
|
||||
local hook = hook
|
||||
local CurTime = CurTime
|
||||
local player = player
|
||||
local ipairs = ipairs
|
||||
local ix = ix
|
||||
local IsValid = IsValid
|
||||
|
||||
local PLUGIN = PLUGIN
|
||||
|
||||
PLUGIN.disconnects = PLUGIN.disconnects or {}
|
||||
|
||||
PLUGIN.takeCounter = {}
|
||||
timer.Create("ixBastionAntiTakeSpam", 1, 0, function()
|
||||
for client, amount in pairs(PLUGIN.takeCounter) do
|
||||
if (amount < 10) then continue end
|
||||
if (!IsValid(client)) then continue end
|
||||
|
||||
for _, admin in ipairs(player.GetAll()) do
|
||||
if (admin:IsSuperAdmin()) then
|
||||
admin:NotifyLocalized("bastionItemTakeKick", client:Name())
|
||||
end
|
||||
end
|
||||
|
||||
client:Kick("Item take spam")
|
||||
end
|
||||
|
||||
PLUGIN.takeCounter = {}
|
||||
end)
|
||||
|
||||
function PLUGIN:CanPlayerInteractItem(client, action, item, data)
|
||||
if (action == "take") then
|
||||
if (self.takeCounter[client] and self.takeCounter[client] >= 5) then
|
||||
if (self.takeCounter[client] == 5) then
|
||||
for _, v in ipairs(player.GetAll()) do
|
||||
if (v:IsSuperAdmin()) then
|
||||
v:NotifyLocalized("bastionItemTakeWarn", client:Name())
|
||||
end
|
||||
end
|
||||
client:NotifyLocalized("bastionTakingItemsTooQuickly")
|
||||
end
|
||||
|
||||
self.takeCounter[client] = self.takeCounter[client] + 1
|
||||
return false
|
||||
end
|
||||
elseif (action == "drop" and client.ixAntiItemSpam and client.ixAntiItemSpam > CurTime()) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
function PLUGIN:PlayerInteractItem(client, action, item)
|
||||
if (action == "take") then
|
||||
self.takeCounter[client] = (self.takeCounter[client] or 0) + 1
|
||||
end
|
||||
end
|
||||
|
||||
PLUGIN.itemSpawns = {}
|
||||
function PLUGIN:OnItemSpawned(entity)
|
||||
if (IsValid(self.itemSpawns[entity.ixItemID])) then
|
||||
if (self.itemSpawns[entity.ixItemID].ixItemID != entity.ixItemID) then
|
||||
return -- just in case
|
||||
end
|
||||
|
||||
--Now we are trying to spawn an item which already has an entity!
|
||||
--Check if it is the same person, in case of weird behaviour
|
||||
if (entity.ixSteamID == self.itemSpawns[entity.ixItemID]) then
|
||||
local client = player.GetBySteamID(entity.ixSteamID)
|
||||
if ((client.ixAntiItemSpam or 0) > CurTime()) then
|
||||
for _, v in ipairs(player.GetAll()) do
|
||||
if (v:IsSuperAdmin()) then
|
||||
v:NotifyLocalized("bastionItemDropSpamKick", client:Name())
|
||||
end
|
||||
end
|
||||
|
||||
client:Kick("Item drop spam")
|
||||
else
|
||||
client.ixAntiItemSpam = CurTime() + 10
|
||||
|
||||
for _, v in ipairs(player.GetAll()) do
|
||||
if (v:IsSuperAdmin()) then
|
||||
v:NotifyLocalized("bastionItemDropSpamWarn", client:Name())
|
||||
end
|
||||
end
|
||||
|
||||
client:NotifyLocalized("bastionItemDropTooQuick")
|
||||
end
|
||||
end
|
||||
|
||||
self.itemSpawns[entity.ixItemID]:Remove()
|
||||
self.itemSpawns[entity.ixItemID] = entity
|
||||
else
|
||||
self.itemSpawns[entity.ixItemID] = entity
|
||||
end
|
||||
end
|
||||
|
||||
function PLUGIN:CanPlayerCreateCharacter(client)
|
||||
if (client.ixNextCharCreate and (client.ixNextCharCreate + ix.config.Get("charCreateInterval") * 60) > CurTime()) then
|
||||
return false, "charCreateTooFast", ix.config.Get("charCreateInterval")
|
||||
end
|
||||
end
|
||||
|
||||
function PLUGIN:OnCharacterCreated(client)
|
||||
if (!client:IsAdmin()) then
|
||||
client.ixNextCharCreate = CurTime()
|
||||
end
|
||||
end
|
||||
|
||||
function PLUGIN:PlayerSpawnedProp(client, model, entity)
|
||||
entity.ownerCharacter = client:GetName()
|
||||
entity.ownerName = client:SteamName()
|
||||
entity.ownerSteamID = client:SteamID()
|
||||
end
|
||||
|
||||
function PLUGIN:OnPlayerHitGround(client, inWater, onFloater, speed)
|
||||
local currentVelocity = client:GetVelocity()
|
||||
|
||||
client:SetVelocity(-Vector(currentVelocity.x, currentVelocity.y, 0))
|
||||
end
|
||||
|
||||
function PLUGIN:PlayerInitialSpawn(client)
|
||||
local receivers
|
||||
|
||||
if (!ix.config.Get("showConnectMessages", true)) then
|
||||
receivers = {}
|
||||
|
||||
for _, ply in ipairs(player.GetAll()) do
|
||||
if (ply:IsAdmin()) then
|
||||
receivers[#receivers + 1] = ply
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Give some time for the player's data to be loaded, just in case.
|
||||
timer.Simple(1, function()
|
||||
ix.chat.Send(nil, "new_connect", client:SteamName(), false, receivers)
|
||||
end)
|
||||
end
|
||||
|
||||
function PLUGIN:PlayerDisconnected(client)
|
||||
local receivers
|
||||
|
||||
self.disconnects[client:SteamID64()] = {time = os.time(), charID = client:GetCharacter() and client:GetCharacter():GetID()}
|
||||
|
||||
if (!ix.config.Get("showDisconnectMessages", true)) then
|
||||
receivers = {}
|
||||
|
||||
for _, ply in ipairs(player.GetAll()) do
|
||||
if (ply:IsAdmin()) then
|
||||
receivers[#receivers + 1] = ply
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
ix.chat.Send(nil, "new_disconnect", client:SteamName(), false, receivers)
|
||||
end
|
||||
|
||||
function PLUGIN:PlayerLoadedCharacter(client, character, lastChar)
|
||||
if (self.disconnects[client:SteamID64()]) then
|
||||
local info = self.disconnects[client:SteamID64()]
|
||||
if (info.timer) then
|
||||
timer.Remove(info.timer)
|
||||
if (IsValid(info.bannedBy)) then
|
||||
if (info.charID) then
|
||||
if (character:GetID() == info.charID) then
|
||||
info.bannedBy:Notify(client:SteamName().." has reconnected and is back on their character "..character:GetName()..".")
|
||||
end
|
||||
else
|
||||
info.bannedBy:Notify(client:SteamName().." has reconnected on a different character '"..character:GetName().."'.")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function PLUGIN:PlayerDeath(client, inflictor, attacker)
|
||||
if (!client:GetCharacter()) then return end
|
||||
|
||||
ix.chat.Send(client, "bastionPlayerDeath", client:GetName() .. " (" .. client:SteamName() .. ") has died at " .. (client.ixArea and client.ixArea != "" and client.ixArea or "an Uncategorized Location") .. ".")
|
||||
end
|
||||
|
||||
hook.Add("SAM.RanCommand", "BastionSamCommandLogs", function(client, cmd_name, args, cmd)
|
||||
ix.log.Add(client, "bastionSamCommand", cmd_name, args, cmd)
|
||||
end)
|
||||
139
gamemodes/helix/plugins/bastion/sv_plugin.lua
Normal file
139
gamemodes/helix/plugins/bastion/sv_plugin.lua
Normal file
@@ -0,0 +1,139 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
local util = util
|
||||
local file = file
|
||||
local table = table
|
||||
local timer = timer
|
||||
local ipairs = ipairs
|
||||
local player = player
|
||||
local CAMI = CAMI
|
||||
local string = string
|
||||
local ents = ents
|
||||
local IsValid = IsValid
|
||||
local ix = ix
|
||||
|
||||
local PLUGIN = PLUGIN
|
||||
|
||||
util.AddNetworkString("ixOpenURL")
|
||||
util.AddNetworkString("ixPlayerInfo")
|
||||
util.AddNetworkString("ixStaffList")
|
||||
util.AddNetworkString("ixPlaySound")
|
||||
|
||||
function PLUGIN:InitializedPlugins()
|
||||
if (!CHTTP) then return end
|
||||
self.API_KEY = file.Read("gamemodes/helix/plugins/bastion/apikey_proxy.txt", "GAME")
|
||||
if (self.API_KEY) then
|
||||
self.API_KEY = string.gsub(self.API_KEY, "[^%w%-]", "")
|
||||
end
|
||||
self.DISCORD_WEBHOOK_ALTS = file.Read("gamemodes/helix/plugins/bastion/apiwebhook_disocrd.txt", "GAME")
|
||||
end
|
||||
|
||||
function PLUGIN:InitializedConfig()
|
||||
ix.config.Set("EdictWarningLimit", 1024)
|
||||
end
|
||||
|
||||
ix.util.Include("modules/sv_banlist.lua")
|
||||
ix.util.Include("modules/sv_antialt.lua")
|
||||
ix.util.Include("modules/sv_netsizelog.lua")
|
||||
--ix.util.Include("modules/sv_netmonitor.lua") --high performance impact!
|
||||
|
||||
ix.log.AddType("bastionCheckInfo", function(client, target)
|
||||
return string.format("%s has checked %s's info.", client:GetName(), target:GetName())
|
||||
end)
|
||||
ix.log.AddType("bastionSetHealth", function(client, target)
|
||||
return string.format("%s has set %s's health to %d.", client:GetName(), target:GetName(), target:Health())
|
||||
end)
|
||||
ix.log.AddType("bastionSetArmor", function(client, target)
|
||||
return string.format("%s has set %s's armor to %d.", client:GetName(), target:GetName(), target:Armor())
|
||||
end)
|
||||
ix.log.AddType("bastionSetName", function(client, target, oldName)
|
||||
return string.format("%s has set %s's name to %s.", client:GetName(), oldName, target:GetName())
|
||||
end)
|
||||
ix.log.AddType("bastionSetDesc", function(client, target)
|
||||
return string.format("%s has set %s's description to %s.", client:GetName(), target:GetName(), target:GetDescription())
|
||||
end)
|
||||
ix.log.AddType("bastionSlay", function(client, target)
|
||||
return string.format("%s has slayed %s.", client:GetName(), target:GetName())
|
||||
end, FLAG_DANGER)
|
||||
ix.log.AddType("bastionInvSearch", function(client, name)
|
||||
return string.format("%s is admin-searching %s.", client:GetName(), name)
|
||||
end)
|
||||
ix.log.AddType("bastionInvClose", function(client, name)
|
||||
return string.format("%s has closed %s.", client:GetName(), name)
|
||||
end)
|
||||
ix.log.AddType("netstreamHoneypot", function(client, hook, bNoAccess)
|
||||
return string.format("[BANME] %s has just hit the %s HONEYPOT!!! Please ban SteamID: %s (trigger reason: %s)", client:SteamName(), hook, client:SteamID(), bNoAccess and "no access" or "invalid arg")
|
||||
end, FLAG_DANGER)
|
||||
ix.log.AddType("luaHack", function(client, name)
|
||||
return string.format("[BANME] %s just tried to %s through lua-injection!!! Please ban SteamID: %s", client:SteamName(), name, client:SteamID())
|
||||
end)
|
||||
ix.log.AddType("bastionSamCommand", function(client, cmd, args)
|
||||
return string.format("%s ran SAM command '%s' with arguments: '%s'", client:Name(), cmd, table.concat(args, "' '"))
|
||||
end)
|
||||
ix.log.AddType("samReportClaimed", function(client, reporter)
|
||||
return string.format("%s claimed a report by %s (%s).", client:Name(), reporter:Name(), reporter:SteamName())
|
||||
end)
|
||||
|
||||
timer.Create("ixBastionEdictCheck", 60, 0, function()
|
||||
local edictsCount = ents.GetEdictCount()
|
||||
local edictsLeft = 8192 - edictsCount
|
||||
if (edictsLeft < ix.config.Get("EdictWarningLimit")) then
|
||||
if (edictsLeft < 600) then
|
||||
for _, v in ipairs(player.GetAll()) do
|
||||
if (CAMI.PlayerHasAccess(v, "Helix - Basic Admin Commands")) then
|
||||
v:NotifyLocalized("edictCritical", edictsLeft, edictsCount)
|
||||
end
|
||||
end
|
||||
else
|
||||
for _, v in ipairs(player.GetAll()) do
|
||||
if (CAMI.PlayerHasAccess(v, "Helix - Basic Admin Commands")) then
|
||||
v:NotifyLocalized("edictWarning", edictsLeft, edictsCount)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
function PLUGIN:Explode(target)
|
||||
local explosive = ents.Create("env_explosion")
|
||||
explosive:SetPos(target:GetPos())
|
||||
explosive:SetOwner(target)
|
||||
explosive:Spawn()
|
||||
explosive:SetKeyValue("iMagnitude", "1")
|
||||
explosive:Fire("Explode", 0, 0)
|
||||
explosive:EmitSound("ambient/explosions/explode_4.wav", 500, 500)
|
||||
|
||||
target:StopParticles()
|
||||
target:Kill()
|
||||
end
|
||||
|
||||
function PLUGIN:OpenInventory(client, target)
|
||||
if (!IsValid(client) or !IsValid(target)) then return end
|
||||
if (!target:IsPlayer()) then return end
|
||||
|
||||
local character = target:GetCharacter()
|
||||
if (!character) then return end
|
||||
|
||||
local inventory = character:GetInventory()
|
||||
if (inventory) then
|
||||
local name = target:Name().."'s inventory"
|
||||
|
||||
ix.storage.Open(client, inventory, {
|
||||
entity = target,
|
||||
name = name,
|
||||
OnPlayerClose = function()
|
||||
ix.log.Add(client, "bastionInvClose", name)
|
||||
end
|
||||
})
|
||||
|
||||
ix.log.Add(client, "bastionInvSearch", name)
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user