{"TotalCount":3,"Files":[{"Ident":"badandbest.sprays","Path":"Code/Spray.Placement.cs","FileName":"Spray.Placement.cs","PackageType":"library","CodeKind":"Game","AssetVersionId":61422,"IsPrivate":false,"Code":"using Sandbox;\r\nusing Sandbox.Utility;\r\nusing System.Collections.Generic;\r\nnamespace badandbest.Sprays;\r\n\r\npublic static partial class Spray\r\n{\r\n\tpublic static GameObject LocalSpray;\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Places an image on a surface.\r\n\t/// \u003C/summary\u003E\r\n\tpublic static void Place()\r\n\t{\r\n\t\tconst float RANGE = 128;// Range in GMOD.\r\n\r\n\t\tvar ray = Game.ActiveScene.Camera.Transform.World.ForwardRay;\r\n\t\tvar trace = Game.SceneTrace.Ray( ray, RANGE );\r\n\r\n\t\tPlace( trace );\r\n\t}\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Places an image on a surface.\r\n\t/// \u003C/summary\u003E\r\n\t/// \u003Cparam name=\u0022trace\u0022\u003EThe trace to use.\u003C/param\u003E\r\n\tpublic static void Place( SceneTrace trace )\r\n\t{\r\n\t\t// We only want to hit static bodies. ( maps, etc )\r\n\t\tif ( trace.Run() is not { Body.BodyType: PhysicsBodyType.Static } tr )\r\n\t\t\treturn;\r\n\r\n\t\tvar config = new CloneConfig\r\n\t\t{\r\n\t\t\tName = $\u0022Spray - {Steam.PersonaName}\u0022,\r\n\t\t\tTransform = new Transform( tr.HitPosition, Rotation.LookAt( tr.Normal ) ),\r\n\t\t\tPrefabVariables = new Dictionary\u003Cstring, object\u003E\r\n\t\t\t{\r\n\t\t\t\t{ \u0022Image\u0022, Cookie.Get( \u0022spray.url\u0022, \u0022materials/decals/default.png\u0022 ) },\r\n\t\t\t\t{ \u0022Placer\u0022, Steam.PersonaName },\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\tLocalSpray?.Destroy();\r\n\t\tLocalSpray = GameObject.Clone( \u0022prefabs/spray.prefab\u0022, config );\r\n\r\n\t\tLocalSpray.NetworkSpawn(); // NetworkSpawn breaks the prefab\r\n\t\tLocalSpray.SetPrefabSource( \u0022prefabs/spray.prefab\u0022 );\r\n\t}\r\n}\r\n\r\n[Title( \u0022Spray Renderer\u0022 ), Icon( \u0022imagesearch_roller\u0022 )]\r\ninternal class SprayRenderer : Renderer\r\n{\r\n\t[Property] internal DecalRenderer _decal { get; set; }\r\n\t[Property] internal TextRenderer _text { get; set; }\r\n\r\n\t[Property, ImageAssetPath]\r\n\tpublic string Image { get; set; }\r\n\r\n\t[Button( \u0022Remove Spray\u0022, Icon = \u0022clear\u0022 )]\r\n\tpublic void Remove() =\u003E GameObject.Destroy();\r\n\t\r\n\tpublic virtual void UpdateObject()\r\n\t{\r\n\t\t_decal.Enabled = !Spray.DisableRendering;\r\n\t\t_text.Enabled = Spray.EnableDebug;\r\n\t}\r\n\r\n\tprotected override async void OnAwake()\r\n\t{\r\n\t\tUpdateObject();\r\n\r\n\t\tvar texture = await Texture.LoadAsync( FileSystem.Mounted, Image );\r\n\r\n\t\t_decal.Material = Material.Load( \u0022materials/spray.vmat\u0022 ).CreateCopy();\r\n\t\t_decal.Material.Set( \u0022g_tColor\u0022, texture );\r\n\t}\r\n}\r\n"},{"Ident":"badandbest.sprays","Path":"Code/Spray.ConVars.cs","FileName":"Spray.ConVars.cs","PackageType":"library","CodeKind":"Game","AssetVersionId":61422,"IsPrivate":false,"Code":"using Sandbox;\r\nnamespace badandbest.Sprays;\r\n\r\npublic static partial class Spray\r\n{\r\n\t[ConVar( \u0022spraydebug\u0022, Help = \u0022Renders who placed a spray.\u0022 ), Change( nameof( OnDirty ) )]\r\n\tinternal static bool EnableDebug { get; set; }\r\n\r\n\t[ConVar( \u0022spraydisable\u0022, Help = \u0022Disables player sprays. Good for streamers.\u0022, Saved = true ), Change( nameof( OnDirty ) )]\r\n\tinternal static bool DisableRendering { get; set; }\r\n\r\n\tprivate static void OnDirty( object oldValue, object newValue )\r\n\t{\r\n\t\tforeach ( var spray in Game.ActiveScene.GetAllComponents\u003CSprayRenderer\u003E() )\r\n\t\t{\r\n\t\t\tspray.UpdateObject();\r\n\t\t}\r\n\t}\r\n}\r\n"},{"Ident":"badandbest.sprays","Path":"Code/Spray.Downloading.cs","FileName":"Spray.Downloading.cs","PackageType":"library","CodeKind":"Game","AssetVersionId":61422,"IsPrivate":false,"Code":"using Sandbox;\r\nusing System;\r\nusing System.IO;\r\nusing System.Linq;\r\nusing System.Net.Http;\r\n\r\nnamespace badandbest.Sprays;\r\n\r\n/// \u003Csummary\u003E\r\n/// A library to allow the placement of sprays in the world\r\n/// \u003C/summary\u003E\r\npublic static partial class Spray\r\n{\r\n\tprivate static bool IsImage( this HttpContent content ) =\u003E content.Headers.GetValues( \u0022Content-Type\u0022 ).Any( type =\u003E type.Contains( \u0022image\u0022 ) );\r\n\r\n\t[ConCmd( \u0022spray\u0022, Help = \u0022URL of image. Must be in quotes.\u0022 )]\r\n\tinternal static async void SetImage( string imageUrl )\r\n\t{\r\n\t\ttry\r\n\t\t{\r\n\t\t\tvar uri = new Uri( imageUrl );\r\n\t\t\tvar response = await Http.RequestAsync( uri.AbsoluteUri );\r\n\t\t\t\r\n\t\t\tif ( !response.Content.IsImage() )\r\n\t\t\t{\r\n\t\t\t\tthrow new FileNotFoundException(\u0022Not an image type: Sites like Tenor require you to Right click \u003E Copy image address\u0022);\r\n\t\t\t}\r\n\t\t}\r\n\t\tcatch ( Exception e )\r\n\t\t{\r\n\t\t\tLog.Warning( e );\r\n\t\t\timageUrl = \u0022materials/fallback.vtex\u0022;\r\n\t\t}\r\n\t\tfinally\r\n\t\t{\r\n\t\t\tCookie.Set( \u0022spray.url\u0022, imageUrl );\r\n\t\t}\r\n\t}\r\n}\r\n"}]}