mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-17 21:53: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>
|
||||
217
gamemodes/helix/plugins/bastion/cl_plugin.lua
Normal file
217
gamemodes/helix/plugins/bastion/cl_plugin.lua
Normal file
@@ -0,0 +1,217 @@
|
||||
--[[
|
||||
| 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")
|
||||
|
||||
surface.CreateFont( "GMFont", {
|
||||
font = "Roboto-Bold",
|
||||
size = 48,
|
||||
weight = 700,
|
||||
antialias = true,
|
||||
shadow = true,
|
||||
} )
|
||||
surface.CreateFont( "GMSubtitleFont", {
|
||||
font = "Roboto-Regular",
|
||||
size = 18,
|
||||
weight = 500,
|
||||
antialias = true,
|
||||
shadow = true,
|
||||
} )
|
||||
|
||||
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(),
|
||||
") | HP: ", target:Health(), " | Armor: ", 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,
|
||||
["gmpresence"] = 1,
|
||||
["localevent"] = 2,
|
||||
["showentsinradius"] = 1,
|
||||
["localbroadcast"] = 2,
|
||||
["localbroadcastme"] = 2,
|
||||
["localbroadcastit"] = 2,
|
||||
["playsong"] = 3,
|
||||
["screenshake"] = 4,
|
||||
["moviebars"] = 1,
|
||||
["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)
|
||||
|
||||
net.Receive("ixGMPresence", function(len)
|
||||
local sound = "music/stingers/stinger1.ogg"
|
||||
|
||||
if (hook.Run("PrePlaySound", sound) != false) then
|
||||
surface.PlaySound(sound)
|
||||
|
||||
hook.Run("PostPlaySound", sound)
|
||||
end
|
||||
|
||||
local fadeDuration = 5
|
||||
local fadeDelay = 15
|
||||
|
||||
local text = "İlahi bir varlığın sizi izlediği hissine kapılıyorsunuz."
|
||||
local subtitle = "[GM Aktif]"
|
||||
|
||||
local startTime = CurTime()
|
||||
local endTime = startTime + fadeDuration
|
||||
local fadeOutTime = endTime + fadeDelay
|
||||
|
||||
hook.Add("HUDPaint", "FadeText", function()
|
||||
local currentTime = CurTime()
|
||||
|
||||
if currentTime < endTime then
|
||||
local alpha = math.Clamp((currentTime - startTime) / fadeDuration, 0, 1) * 255
|
||||
|
||||
surface.SetTextColor(Color(255, 178, 80, alpha))
|
||||
|
||||
local x = ScrW() / 2
|
||||
local y = ScrH() / 4
|
||||
|
||||
draw.SimpleText(text, "GMFont", x, y, Color(255, 178, 80, alpha), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
|
||||
draw.SimpleText(subtitle, "GMSubtitleFont", x, y * 1.15, Color(100, 100, 100, alpha), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
|
||||
elseif currentTime < fadeOutTime then
|
||||
local alpha = math.Clamp(1 - (currentTime - endTime) / fadeDuration, 0, 1) * 255
|
||||
|
||||
surface.SetTextColor(Color(255, 178, 80, alpha))
|
||||
|
||||
local x = ScrW() / 2
|
||||
local y = ScrH() / 4
|
||||
|
||||
draw.SimpleText(text, "GMFont", x, y, Color(255, 178, 80, alpha), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
|
||||
draw.SimpleText(subtitle, "GMSubtitleFont", x, y * 1.15, Color(100, 100, 100, alpha), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
|
||||
else
|
||||
hook.Remove("HUDPaint", "FadeText")
|
||||
end
|
||||
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("Bindlar konsola yazdırıldı!")
|
||||
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 = "You are trying to join Willard Networks Turkiye as a new user while using a proxy or VPN. To combat alt accounts, we do not allow this.\n\nPlease turn off your proxy/VPN and rejoin the server. After you successfully joined the server once, you can turn on your proxy/VPN again for future visits.\n\nIf you are not using a proxy or VPN, please contact the community management on our forums or discord"
|
||||
})
|
||||
|
||||
ix.log.AddType("altNewClient", function(client)
|
||||
return string.format("[AltChecker] %s joined for the first time, generating new cookie.", client:SteamName())
|
||||
end)
|
||||
ix.log.AddType("altKnownNewCookie", function(client)
|
||||
return string.format("[AltChecker] %s joined with unknown installation, generating new cookie.", client:SteamName())
|
||||
end)
|
||||
ix.log.AddType("altKnownCookieMatched", function(client, matched, total)
|
||||
return string.format("[AltChecker] %s joined without a cookie, but matched installation with existing cookie. Certainty %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..") tried to connect but is hard-banned.")
|
||||
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
|
||||
201
gamemodes/helix/plugins/bastion/sh_classes.lua
Normal file
201
gamemodes/helix/plugins/bastion/sh_classes.lua
Normal file
@@ -0,0 +1,201 @@
|
||||
--[[
|
||||
| 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("gmroll", {
|
||||
format = "** You have gm-rolled %s out of %s.",
|
||||
color = Color(155, 111, 176),
|
||||
CanHear = function(self, speaker, listener)
|
||||
return speaker == listener
|
||||
end,
|
||||
deadCanChat = true,
|
||||
OnChatAdd = function(self, speaker, text, bAnonymous, data)
|
||||
chat.AddText(self.color, string.format(self.format, text, data.max or 20))
|
||||
end
|
||||
})
|
||||
|
||||
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), " earned the achievement ",
|
||||
Color( 255, 201, 0, 255 ), text)
|
||||
end
|
||||
end
|
||||
|
||||
ix.chat.Register("achievement_get", CLASS)
|
||||
end
|
||||
687
gamemodes/helix/plugins/bastion/sh_commands.lua
Normal file
687
gamemodes/helix/plugins/bastion/sh_commands.lua
Normal file
@@ -0,0 +1,687 @@
|
||||
--[[
|
||||
| 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 = "Get a link to the Discord Server",
|
||||
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 = "Get a link to theWorkshop Content Pack",
|
||||
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 = "Get a link to the 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 = "Get someone's basic information and copy their SteamID.",
|
||||
arguments = {
|
||||
bit.bor(ix.type.player, ix.type.optional)
|
||||
},
|
||||
--alias = "PlyGetInfo",
|
||||
privilege = "Basic Admin Commands",
|
||||
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 = "Print a list of staff members online.",
|
||||
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("Şu anda aktif yetkili yok.")
|
||||
end
|
||||
end,
|
||||
bNoIndicator = true
|
||||
})
|
||||
|
||||
ix.command.Add("PrintFactionList", {
|
||||
alias = "PFL",
|
||||
description = "Print a list of members of a faction currently online (including on another character).",
|
||||
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 = "Play a sound for all players (when no range is given) or those near you.",
|
||||
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("GMPresence", {
|
||||
description = "Allows players to understand that a GM is watching them.",
|
||||
arguments = {
|
||||
bit.bor(ix.type.number)
|
||||
},
|
||||
privilege = "Basic Admin Commands",
|
||||
OnRun = function(self, client, range)
|
||||
if not range then return "Bir alan belirtmelisiniz." end
|
||||
local targets = range and {}
|
||||
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("ixGMPresence")
|
||||
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, true)
|
||||
end,
|
||||
indicator = "chatPerforming"
|
||||
})
|
||||
|
||||
ix.command.Add("PlaySoundGlobal", {
|
||||
description = "Play a sound for all players.",
|
||||
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 = "Returns the amount of networked entities currently on the server.",
|
||||
privilege = "Basic Admin Commands",
|
||||
OnRun = function(self, client)
|
||||
local edictsCount = ents.GetEdictCount()
|
||||
local edictsLeft = 8192 - edictsCount
|
||||
|
||||
return string.format("There are currently %s edicts on the server. You can have up to %s more.", edictsCount, edictsLeft)
|
||||
end,
|
||||
bNoIndicator = true
|
||||
})
|
||||
|
||||
ix.command.Add("ShowEntsInRadius", {
|
||||
description = "Shows a list of entities within a given radius.",
|
||||
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 = "Shows a list of entities within a given radius.",
|
||||
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"
|
||||
})
|
||||
|
||||
ix.command.Add("GmRoll", {
|
||||
description = "Do a roll that only you can see.",
|
||||
arguments = {
|
||||
bit.bor(ix.type.number, ix.type.optional)
|
||||
},
|
||||
privilege = "Basic Admin Commands",
|
||||
OnRun = function(self, client, maximum)
|
||||
maximum = math.Clamp(maximum or 20, 0, 1000000)
|
||||
|
||||
local value = math.random(0, maximum)
|
||||
|
||||
ix.chat.Send(client, "gmroll", tostring(value), nil, nil, {
|
||||
max = maximum
|
||||
})
|
||||
|
||||
ix.log.Add(client, "roll", value, maximum)
|
||||
end,
|
||||
bNoIndicator = true
|
||||
})
|
||||
|
||||
-- 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 = "Chat with other staff members.",
|
||||
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 = "Chat with other 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 = "Chat with other 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 = "Someone has earned a special achievement!",
|
||||
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 = "Someone has earned an achievement: he has made the ultimate sacrifice to increase humanity's average IQ.",
|
||||
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() .. "kişisinin karakterleri:")
|
||||
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("Geçersiz süre belirtildi. Maksimum ban süresi 100 gün.")
|
||||
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("Zamanlayıcı ayarlandı! "..steamID.." şu süre içerisinde banlanacak: "..math.ceil((info.time - os.time() + reconnectTime * 60) / 60).." dakika.")
|
||||
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 = "View Owner",
|
||||
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 = "characters"
|
||||
})
|
||||
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 = "characters"
|
||||
})
|
||||
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 = "containers"
|
||||
})
|
||||
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 = "server"
|
||||
})
|
||||
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 = "server"
|
||||
})
|
||||
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=2145501003", "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", "Access to the advanced duplicator.")
|
||||
|
||||
ix.lang.AddTable("english", {
|
||||
getPlayerInfo = "Oyuncu Bilgisi Al",
|
||||
optStaffChat = "Tüm karakterlerde Yetkili Sohbetini göster",
|
||||
optdStaffChat = "Tüm karakterlerde yetkili sohbetini açar/kapatır. Kapalıyken, yalnızca gözlemci modunda ya da bir admin karakterindeyken yetkili sohbeti gösterir.",
|
||||
optPgi = "'PGI'/'Oyuncuyu Görüntüle' komutunda Steam ID'yi panoya kopyala",
|
||||
optdPgi = "PGI komutunu veya 'Oyuncuyu Görüntüle' bağlam menü seçeneğini kullanırken bir oyuncunun SteamID'sini otomatik olarak panoya kopyalamayı açar/kapatır.",
|
||||
cmdStaffHelp = "Tüm yetkililerden yardım isteyin.\n",
|
||||
cmdAnnounce = "Tüm sunucuya OOC bir admin duyurusu yapın.",
|
||||
cmdLocalEvent = "Verilen bir yarıçap içinde sadece duyulabilen bir IC admin etkinliği yapın.",
|
||||
bastionPGIInvalidTarget = "Geçerli bir hedefe bakmalı veya girmelisiniz.",
|
||||
bastionTakingItemsTooQuickly = "Eşyaları çok hızlı alıyorsunuz! Lütfen yavaşlayın.",
|
||||
bastionItemDropSpamKick = "%s eşya bırakma istismarı için atıldı.",
|
||||
bastionItemDropSpamWarn = "%s eşya bırakma istismarı için uyarıldı.",
|
||||
bastionItemDropTooQuick = "Eşyaları çok hızlı bırakıyorsunuz! Lütfen yavaşlayın.",
|
||||
bastionItemTakeWarn = "%s eşyaları çok hızlı aldığı için uyarıldı.",
|
||||
bastionItemTakeKick = "%s eşyaları çok hızlı bıraktığı için atıldı.",
|
||||
charCreateTooFast = "Karakterleri çok hızlı oluşturuyorsunuz. Lütfen denemeler arasında en az %d dakika bekleyin.",
|
||||
bastionCopiedCharName = "Karakter adı kopyalandı",
|
||||
bastionCopiedSteamName = "Steam adı kopyalandı",
|
||||
bastionCopiedSteamID = "Steam ID kopyalandı",
|
||||
bastionGoto = "Oyuncuya git",
|
||||
bastionCopyCharName = "Karakter adını kopyala",
|
||||
bastionCopySteamName = "Steam adını kopyala",
|
||||
bastionNoRecordFound = "%s için herhangi bir kayıt bulunamadı.",
|
||||
bastionResultsPrinted = "Sonuçlar konsolda yazdırıldı.",
|
||||
bastionProxyNotify = "%s bir VPN/Proxy kullanarak yeni oyuncu olarak bağlandı.",
|
||||
bastionPropOwnerInformation = "Bu prop'un sahibi %s (%s - %s).",
|
||||
bastionPropOwnerUnknown = "Bu prop'un sahibi kayıtlara geçmemiş!",
|
||||
whitelistDone = "Oyuncu beyaz listeye eklendi.",
|
||||
whitelistError = "Oyuncuyu beyaz listeye eklerken bir şeyler ters gitti. Bir geliştiriciye sorun.",
|
||||
cmdTimeScale = "Zaman ölçeğini değiştir (min 0.001, max 5).",
|
||||
bastionTimeScale = "%s zaman ölçeğini %d olarak ayarladı.",
|
||||
cmdGravity = "Yer çekimini değiştir.",
|
||||
bastionGravity = "%s yer çekimini %d olarak ayarladı.",
|
||||
edictWarning = "Yalnızca %d edict kaldı! Toplam edict sayısı şu anda: %d/8192!",
|
||||
edictCritical = "Yalnızca %d edict kaldı! Toplam edict sayısı şu anda: %d/8192! Acil Temizlik Gereklidir!",
|
||||
entsPrintedInConsole = "Entity listesi konsolda yazdırıldı.",
|
||||
entityRemoved = "Entity %d (%s) kaldırıldı!",
|
||||
entityNotFound = "Entity %d bulunamadı/geçerli değil.",
|
||||
optPlayerDeathNotification = "Oyuncu Ölüm Bildirimi",
|
||||
optdPlayerDeathNotification = "Bir oyuncu öldüğünde bir sohbet mesajı gönderilip gönderilmeyeceği.",
|
||||
cmdRemovePersistedProps = "Çevrenizdeki belirli bir alanda kalıcı olan tüm nesneleri kaldırın."
|
||||
})
|
||||
|
||||
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)
|
||||
140
gamemodes/helix/plugins/bastion/sv_plugin.lua
Normal file
140
gamemodes/helix/plugins/bastion/sv_plugin.lua
Normal file
@@ -0,0 +1,140 @@
|
||||
--[[
|
||||
| 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")
|
||||
util.AddNetworkString("ixGMPresence")
|
||||
|
||||
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