--[[ | 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/ --]] ArcCW = ArcCW or {} ArcCW.AttachmentTable = {} ArcCW.AttachmentIDTable = {} ArcCW.AttachmentSlotTable = {} ArcCW.AttachmentBlacklistTable = {} ArcCW.NumAttachments = 1 ArcCW.GenerateAttEntities = true ArcCW.AttachmentCachedLists = {} local shortname = "" local genAttCvar = ArcCW.ConVars["reloadatts_registerentities"] function ArcCW.LoadAttachmentType(att, name) if name == "" then return end name = name or shortname if !att.Ignore or ArcCW.ConVars["reloadatts_showignored"]:GetBool() then ArcCW.AttachmentTable[name] = att ArcCW.AttachmentIDTable[ArcCW.NumAttachments] = name att.Blacklisted = false att.ShortName = name if !ArcCW.AttachmentSlotTable[att.Slot] then ArcCW.AttachmentSlotTable[att.Slot] = {} end table.insert(ArcCW.AttachmentSlotTable[att.Slot], ArcCW.NumAttachments) att.ID = ArcCW.NumAttachments if genAttCvar:GetBool() and !att.DoNotRegister and !att.InvAtt and !att.Free then local attent = {} attent.Base = "arccw_att_base" if CLIENT and att.Icon then attent.IconOverride = string.Replace( att.Icon:GetTexture( "$basetexture" ):GetName() .. ".png", "0001010", "" ) end attent.PrintName = att.PrintName or name attent.Spawnable = att.Spawnable or true attent.AdminOnly = att.AdminOnly or false attent.Category = att.EntityCategory or "ArcCW - Attachments" attent.Model = att.DroppedModel or att.Model or "models/Items/BoxSRounds.mdl" attent.GiveAttachments = { [att.ShortName] = 1 } if att.EntityCategory and !list.HasEntry("ContentCategoryIcons", att.EntityCategory) then list.Set("ContentCategoryIcons", att.EntityCategory, "arccw/icon_16.png") end scripted_ents.Register( attent, "acwatt_" .. name ) end ArcCW.NumAttachments = ArcCW.NumAttachments + 1 hook.Run("ArcCW_OnAttLoad", att) end end local function VerifyBlacklist() for attName, v in pairs(ArcCW.AttachmentBlacklistTable) do if !ArcCW.AttachmentTable[attName] then ArcCW.AttachmentBlacklistTable[attName] = nil end end end local function ArcCW_SendBlacklist(ply) if SERVER then -- Only load if table is empty, bruh if table.IsEmpty(ArcCW.AttachmentBlacklistTable) then ArcCW.AttachmentBlacklistTable = util.JSONToTable(file.Read("arccw_blacklist.txt") or "") or {} local curcount = table.Count(ArcCW.AttachmentBlacklistTable) VerifyBlacklist() print("Loaded " .. curcount .. " active (" .. curcount .. " total) blacklisted ArcCW attachments.") end if ArcCW.AttachmentBlacklistTable and player.GetCount() > 0 then timer.Simple(0, function() net.Start("arccw_blacklist") net.WriteUInt(table.Count(ArcCW.AttachmentBlacklistTable), ArcCW.GetBitNecessity()) for attName, bStatus in pairs(ArcCW.AttachmentBlacklistTable) do net.WriteUInt(ArcCW.AttachmentTable[attName].ID, ArcCW.GetBitNecessity()) end if ply then net.Send(ply) else net.Broadcast() end end) end elseif CLIENT and ArcCW.AttachmentBlacklistTable == nil then -- Actively request the table, this happens on player load into server once net.Start("arccw_blacklist") net.WriteBool(true) net.SendToServer() end end local attachments_path = "arccw/shared/attachments/" local bulk_path = "arccw/shared/attachments_bulk/" local function ArcCW_LoadAtt(att_file) att = {} -- Do not bleed over attributes from previous attachments --shortname = string.sub(att_file, 1, -5) local s = string.Explode("/", att_file) shortname = string.sub(s[#s], 1, -5) include(att_file) AddCSLuaFile(att_file) ArcCW.LoadAttachmentType(att) end local function ArcCW_LoadFolder(folder) folder = folder and (attachments_path .. folder .. "/") or attachments_path for k, v in pairs(file.Find(folder .. "*", "LUA")) do local yaya, yoyo = pcall(function() ArcCW_LoadAtt(folder .. v) end) if !yaya then print( "!!!! Attachment " .. v .. " has errors!", yoyo ) -- Create a stub attachment to prevent customization UI freaking out ArcCW.AttachmentTable[shortname] = { PrintName = shortname or "ERROR", Description = "This attachment failed to load!\nIts file path is: " .. v } end end end local function ArcCW_LoadAtts() ArcCW.AttachmentTable = {} ArcCW.AttachmentIDTable = {} ArcCW.AttachmentSlotTable = {} ArcCW.NumAttachments = 1 ArcCW.AttachmentBits = nil ArcCW.AttachmentCachedLists = {} ArcCW_LoadFolder() local _, folders = file.Find(attachments_path .. "/*", "LUA") if folders then for _, folder in pairs(folders) do ArcCW_LoadFolder(folder) end end local bulkfiles = file.Find(bulk_path .. "/*.lua", "LUA") for _, filename in pairs(bulkfiles) do if filename == "default.lua" then continue end local try = pcall(function() include(bulk_path .. filename) AddCSLuaFile(bulk_path .. filename) end) if !try then print("!!!! Bulk attachment file " .. filename .. " has errors!") end end print("Loaded " .. tostring(ArcCW.NumAttachments) .. " ArcCW attachments.") if !game.SinglePlayer() then ArcCW_SendBlacklist() else -- Simply read the file and do no networking, since both client/server has access to it ArcCW.AttachmentBlacklistTable = util.JSONToTable(file.Read("arccw_blacklist.txt") or "") or {} for i, v in pairs(ArcCW.AttachmentTable) do v.Blacklisted = ArcCW.AttachmentBlacklistTable[i] end print("Loaded blacklist with " .. table.Count(ArcCW.AttachmentBlacklistTable) .. " attachments.") end hook.Run("ArcCW_PostLoadAtts") end function ArcCW.GetBitNecessity() if !ArcCW.AttachmentBits then ArcCW.AttachmentBits = math.min(math.ceil(math.log(ArcCW.NumAttachments + 1, 2)), 32) end return ArcCW.AttachmentBits end if CLIENT then concommand.Add("arccw_reloadatts", function() if !LocalPlayer():IsSuperAdmin() then return end net.Start("arccw_reloadatts") net.SendToServer() end) net.Receive("arccw_reloadatts", function(len, ply) ArcCW_LoadAtts() end) spawnmenu.AddCreationTab( "#spawnmenu.category.entities", function() local ctrl = vgui.Create( "SpawnmenuContentPanel" ) ctrl:EnableSearch( "entities", "PopulateEntities" ) ctrl:CallPopulateHook( "PopulateEntities" ) return ctrl end, "icon16/bricks.png", 20 ) -- Client receives blacklist table from server and updates itself net.Receive("arccw_blacklist", function() ArcCW.AttachmentBlacklistTable = {} local amt = net.ReadUInt(ArcCW.GetBitNecessity()) for i = 1, amt do local id = net.ReadUInt(ArcCW.GetBitNecessity()) ArcCW.AttachmentBlacklistTable[ArcCW.AttachmentIDTable[id]] = true end for i, v in pairs(ArcCW.AttachmentTable) do v.Blacklisted = ArcCW.AttachmentBlacklistTable[i] end print("Received blacklist with " .. table.Count(ArcCW.AttachmentBlacklistTable) .. " attachments.") end) -- Gets around Listen server spawn issues hook.Add( "InitPostEntity", "Ready", function() if !game.SinglePlayer() then net.Start("arccw_blacklist") net.WriteBool(true) net.SendToServer() end end ) elseif SERVER then net.Receive("arccw_reloadatts", function(len, ply) if !ply:IsSuperAdmin() then return end ArcCW_LoadAtts() net.Start("arccw_reloadatts") net.Broadcast() end) local antiSpam = {} net.Receive("arccw_blacklist", function(len, ply) -- If this message is a request to get blacklist, send it and return local isRequest = net.ReadBool() if isRequest then if antiSpam[ply] and antiSpam[ply] > CurTime() then return end -- Debounce client request so they can't attempt to spam netmessages antiSpam[ply] = CurTime() + 10 ArcCW_SendBlacklist(ply) return elseif !isRequest and !ply:IsAdmin() then return end -- Server receives admin's changes to blacklist table local amt = net.ReadUInt(ArcCW.GetBitNecessity()) ArcCW.AttachmentBlacklistTable = {} for i = 1, amt do local id = net.ReadUInt(ArcCW.GetBitNecessity()) local attName = ArcCW.AttachmentIDTable[id] if attName and ArcCW.AttachmentTable[attName] then ArcCW.AttachmentBlacklistTable[attName] = true end end for i, k in pairs(ArcCW.AttachmentTable) do k.Blacklisted = ArcCW.AttachmentBlacklistTable[i] or false end print("Received blacklist with " .. table.Count(ArcCW.AttachmentBlacklistTable) .. " attachments.") file.Write("arccw_blacklist.txt", util.TableToJSON(ArcCW.AttachmentBlacklistTable)) ArcCW_SendBlacklist() end) end hook.Add("PostCleanupMap", "ArcCW_ReloadAttsDebug", function() if ArcCW.ConVars["reloadatts_mapcleanup"]:GetBool() then ArcCW_LoadAtts() end end) ArcCW_LoadAtts()