{"TotalCount":23,"Files":[{"Ident":"nolankicks.sceneloadingutility","Path":"Attributes.cs","FileName":"Attributes.cs","PackageType":"library","CodeKind":"Game","AssetVersionId":65380,"Code":"\r\nusing System;\r\n\r\nnamespace Sandbox.Events;\r\n\r\n/// \u003Csummary\u003E\r\n/// Only valid on \u003Csee cref=\u0022IGameEventHandler{T}.OnGameEvent\u0022/\u003E implementations. Forces this\r\n/// event handler to be invoked before any handlers not marked as early, except if more specific\r\n/// constraints are given (i.e., \u003Csee cref=\u0022BeforeAttribute{T}\u0022/\u003E, \u003Csee cref=\u0022AfterAttribute{T}\u0022/\u003E).\r\n/// \u003C/summary\u003E\r\n[AttributeUsage( AttributeTargets.Method )]\r\npublic sealed class EarlyAttribute : Attribute\r\n{\r\n\r\n}\r\n\r\n/// \u003Csummary\u003E\r\n/// Only valid on \u003Csee cref=\u0022IGameEventHandler{T}.OnGameEvent\u0022/\u003E implementations. Forces this\r\n/// event handler to be invoked after any handlers not marked as late, except if more specific\r\n/// constraints are given (i.e., \u003Csee cref=\u0022BeforeAttribute{T}\u0022/\u003E, \u003Csee cref=\u0022AfterAttribute{T}\u0022/\u003E).\r\n/// \u003C/summary\u003E\r\n[AttributeUsage( AttributeTargets.Method )]\r\npublic sealed class LateAttribute : Attribute\r\n{\r\n\r\n}\r\n\r\ninternal interface IBeforeAttribute\r\n{\r\n\tType Type { get; }\r\n}\r\n\r\ninternal interface IAfterAttribute\r\n{\r\n\tType Type { get; }\r\n}\r\n\r\n/// \u003Csummary\u003E\r\n/// Only valid on \u003Csee cref=\u0022IGameEventHandler{T}.OnGameEvent\u0022/\u003E implementations. Forces this\r\n/// event handler to be invoked before any handlers in the specified type.\r\n/// \u003C/summary\u003E\r\n[AttributeUsage( AttributeTargets.Method, AllowMultiple = true )]\r\npublic sealed class BeforeAttribute\u003CT\u003E : Attribute, IBeforeAttribute\r\n{\r\n\tType IBeforeAttribute.Type =\u003E typeof(T);\r\n}\r\n\r\n/// \u003Csummary\u003E\r\n/// Only valid on \u003Csee cref=\u0022IGameEventHandler{T}.OnGameEvent\u0022/\u003E implementations. Forces this\r\n/// event handler to be invoked after any handlers in the specified type.\r\n/// \u003C/summary\u003E\r\n[AttributeUsage( AttributeTargets.Method, AllowMultiple = true )]\r\npublic sealed class AfterAttribute\u003CT\u003E : Attribute, IAfterAttribute\r\n{\r\n\tType IAfterAttribute.Type =\u003E typeof( T );\r\n}\r\n"},{"Ident":"nolankicks.sceneloadingutility","Path":"SortingHelper.cs","FileName":"SortingHelper.cs","PackageType":"library","CodeKind":"Game","AssetVersionId":65380,"Code":"using System.Collections.Generic;\r\nusing System.Linq;\r\n\r\nnamespace Sandbox.Events;\r\n\r\n/// \u003Csummary\u003E\r\n/// Generate an ordering based on a set of first-most and last-most items, and\r\n/// individual constraints between pairs of items. All first-most items will be\r\n/// ordered before all last-most items, and any other items will be put in the\r\n/// middle unless forced to be elsewhere by a constraint.\r\n/// \u003C/summary\u003E\r\ninternal class SortingHelper\r\n{\r\n\tpublic record struct SortConstraint( int EarlierIndex, int LaterIndex )\r\n\t{\r\n\t\tpublic SortConstraint Complement =\u003E new ( LaterIndex, EarlierIndex );\r\n\t}\r\n\r\n\tprivate readonly int _itemCount;\r\n\r\n\tprivate readonly HashSet\u003CSortConstraint\u003E _initialConstraints = new HashSet\u003CSortConstraint\u003E();\r\n\r\n\tprivate readonly HashSet\u003Cint\u003E _first = new HashSet\u003Cint\u003E();\r\n\tprivate readonly HashSet\u003Cint\u003E _last = new HashSet\u003Cint\u003E();\r\n\r\n\tpublic SortingHelper( int itemCount )\r\n\t{\r\n\t\t_itemCount = itemCount;\r\n\t}\r\n\r\n\tpublic void AddConstraint( int earlierIndex, int laterIndex )\r\n\t{\r\n\t\t_initialConstraints.Add( new SortConstraint( earlierIndex, laterIndex ) );\r\n\t}\r\n\r\n\tpublic void AddFirst( int earlierIndex )\r\n\t{\r\n\t\t_first.Add( earlierIndex );\r\n\t}\r\n\r\n\tpublic void AddLast( int laterIndex )\r\n\t{\r\n\t\t_last.Add( laterIndex );\r\n\t}\r\n\r\n\tpublic bool Sort( List\u003Cint\u003E result, out SortConstraint invalidConstraint )\r\n\t{\r\n\t\tvar middle = new HashSet\u003Cint\u003E();\r\n\r\n\t\tfor ( var index = 0; index \u003C _itemCount; \u002B\u002Bindex )\r\n\t\t{\r\n\t\t\tif ( !_first.Contains( index ) \u0026\u0026 !_last.Contains( index ) )\r\n\t\t\t\tmiddle.Add( index );\r\n\t\t}\r\n\r\n\t\tvar allConstraints = new HashSet\u003CSortConstraint\u003E();\r\n\t\tvar newConstraints = new Queue\u003CSortConstraint\u003E();\r\n\t\tvar beforeDict = new Dictionary\u003Cint, HashSet\u003Cint\u003E\u003E();\r\n\t\tvar afterDict = new Dictionary\u003Cint, HashSet\u003Cint\u003E\u003E();\r\n\r\n\t\tbool AddWorkingConstraint( int earlierIndex, int laterIndex, out SortConstraint constraint )\r\n\t\t{\r\n\t\t\tconstraint = new SortConstraint( earlierIndex, laterIndex );\r\n\r\n\t\t\tif ( allConstraints.Contains( constraint.Complement ) )\r\n\t\t\t\treturn false;\r\n\r\n\t\t\tif ( !allConstraints.Add( constraint ) )\r\n\t\t\t\treturn true;\r\n\r\n\t\t\tnewConstraints.Enqueue( constraint );\r\n\r\n\t\t\tif ( !beforeDict.TryGetValue( earlierIndex, out var before ) )\r\n\t\t\t\tbeforeDict.Add( earlierIndex, before = new HashSet\u003Cint\u003E() );\r\n\r\n\t\t\tif ( !afterDict.TryGetValue( laterIndex, out var after ) )\r\n\t\t\t\tafterDict.Add( laterIndex, after = new HashSet\u003Cint\u003E() );\r\n\r\n\t\t\tbefore.Add( laterIndex );\r\n\t\t\tafter.Add( earlierIndex );\r\n\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\t\t// Add initial constraints\r\n\r\n\t\tforeach ( var initialConstraint in _initialConstraints )\r\n\t\t{\r\n\t\t\tif ( !AddWorkingConstraint( initialConstraint.EarlierIndex, initialConstraint.LaterIndex, out invalidConstraint ) )\r\n\t\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\t// Everything in _first should be before everything in _last\r\n\r\n\t\tforeach ( var earlierIndex in _first )\r\n\t\t{\r\n\t\t\tforeach ( var laterIndex in _last )\r\n\t\t\t{\r\n\t\t\t\tif ( !AddWorkingConstraint( earlierIndex, laterIndex, out invalidConstraint ) )\r\n\t\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Keep propagating constraints until nothing changes\r\n\r\n\t\twhile ( newConstraints.TryDequeue( out var nextConstraint ) )\r\n\t\t{\r\n\t\t\t// if a \u003C b, and b \u003C c, then a \u003C c etc\r\n\r\n\t\t\tif ( beforeDict.TryGetValue( nextConstraint.LaterIndex, out var before ) )\r\n\t\t\t{\r\n\t\t\t\tforeach ( var laterIndex in before )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( !AddWorkingConstraint( nextConstraint.EarlierIndex, laterIndex, out invalidConstraint ) )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif ( afterDict.TryGetValue( nextConstraint.EarlierIndex, out var after ) )\r\n\t\t\t{\r\n\t\t\t\tforeach ( var earlierIndex in after )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( !AddWorkingConstraint( earlierIndex, nextConstraint.LaterIndex, out invalidConstraint ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Now if we have any items that aren\u0027t using GroupOrder.First, and haven\u0027t\r\n\t\t// determined that they are ordered before another item with GroupOrder.First,\r\n\t\t// we can safely order them after all GroupOrder.First items. And vice versa.\r\n\r\n\t\tforeach ( var middleIndex in middle )\r\n\t\t{\r\n\t\t\tvar isBeforeAnyFirst = beforeDict.TryGetValue( middleIndex, out var before )\r\n\t\t\t\t\u0026\u0026 before.Any( x =\u003E _first.Contains( x ) );\r\n\r\n\t\t\tvar isAfterAnyLast = afterDict.TryGetValue( middleIndex, out var after )\r\n\t\t\t\t\u0026\u0026 after.Any( x =\u003E _last.Contains( x ) );\r\n\r\n\t\t\tif ( !isBeforeAnyFirst )\r\n\t\t\t{\r\n\t\t\t\tforeach ( var earlierIndex in _first )\r\n\t\t\t\t\tAddWorkingConstraint( earlierIndex, middleIndex, out invalidConstraint );\r\n\t\t\t}\r\n\r\n\t\t\tif ( !isAfterAnyLast )\r\n\t\t\t{\r\n\t\t\t\tforeach ( var laterIndex in _last )\r\n\t\t\t\t\tAddWorkingConstraint( middleIndex, laterIndex, out invalidConstraint );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Now lets add items to the final ordering if all items that should be sorted\r\n\t\t// before them are already added to that ordering. We\u0027ll implement this by choosing\r\n\t\t// items that have an empty list / don\u0027t appear in afterDict, and update that\r\n\t\t// dictionary as we go.\r\n\r\n\t\tvar earliestRemaining = new Queue\u003Cint\u003E();\r\n\r\n\t\t// First, seed the queue with everything that\u0027s already not ordered after anything\r\n\r\n\t\tfor ( var index = 0; index \u003C _itemCount; \u002B\u002Bindex )\r\n\t\t{\r\n\t\t\tif ( !afterDict.ContainsKey( index ) )\r\n\t\t\t{\r\n\t\t\t\tearliestRemaining.Enqueue( index );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tresult.Clear();\r\n\r\n\t\twhile ( earliestRemaining.TryDequeue( out var nextIndex ) )\r\n\t\t{\r\n\t\t\tresult.Add( nextIndex );\r\n\r\n\t\t\tforeach ( var laterIndex in beforeDict.TryGetValue( nextIndex, out var laterIndices )\r\n\t\t\t\t? laterIndices : Enumerable.Empty\u003Cint\u003E() )\r\n\t\t\t{\r\n\t\t\t\tvar beforeLater = afterDict[laterIndex];\r\n\t\t\t\tbeforeLater.Remove( nextIndex );\r\n\r\n\t\t\t\tif ( beforeLater.Count == 0 )\r\n\t\t\t\t\tearliestRemaining.Enqueue( laterIndex );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tinvalidConstraint = default;\r\n\t\treturn result.Count == _itemCount;\r\n\t}\r\n}\r\n"},{"Ident":"nolankicks.sceneloadingutility","Path":"UnitTests/LibraryTest.cs","FileName":"LibraryTest.cs","PackageType":"library","CodeKind":"UnitTest","AssetVersionId":65380,"Code":"using Sandbox;\r\n\r\n[TestClass]\r\npublic partial class LibraryTests\r\n{\r\n\t[TestMethod]\r\n\tpublic void SceneTest()\r\n\t{\r\n\t\tvar scene = new Scene();\r\n\t\tusing ( scene.Push() )\r\n\t\t{\r\n\t\t\tvar go = new GameObject();\r\n\r\n\t\t\tAssert.AreEqual( 1, scene.Directory.GameObjectCount );\r\n\t\t}\r\n\t}\r\n\r\n}\r\n"},{"Ident":"nolankicks.sceneloadingutility","Path":"PlayerPusher.cs","FileName":"PlayerPusher.cs","PackageType":"library","CodeKind":"Game","AssetVersionId":65380,"Code":"\r\npublic sealed class PlayerPusher : Component\r\n{\r\n\t[Property] public float Radius { get; set; } = 100;\r\n\r\n\tprotected override void DrawGizmos()\r\n\t{\r\n\t\tbase.DrawGizmos();\r\n\r\n\t\tGizmo.Draw.LineSphere( Vector3.Zero, Radius );\r\n\t}\r\n\r\n\tpublic static Vector3 GetPushVector( in Vector3 position, Scene scene, GameObject ignore )\r\n\t{\r\n\t\tVector3 vec = default;\r\n\r\n\t\tforeach ( var pusher in scene.GetAllComponents\u003CPlayerPusher\u003E() )\r\n\t\t{\r\n\t\t\tif ( pusher.GameObject.IsAncestor( ignore ) )\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\tpusher.Collect( position, ref vec );\r\n\t\t}\r\n\r\n\t\treturn vec;\r\n\t}\r\n\r\n\tprivate void Collect( Vector3 position, ref Vector3 output )\r\n\t{\r\n\t\tvar delta = (position - Transform.Position);\r\n\t\tif ( delta.Length \u003E Radius ) return;\r\n\r\n\t\tdelta.z = 0; // ignore z\r\n\r\n\t\tvar distanceDelta = (delta.Length / Radius);\r\n\r\n\t\toutput \u002B= delta.Normal * (1.0f - distanceDelta);\r\n\t}\r\n}\r\n"},{"Ident":"nolankicks.sceneloadingutility","Path":"PlayerFootsteps.cs","FileName":"PlayerFootsteps.cs","PackageType":"library","CodeKind":"Game","AssetVersionId":65380,"Code":"\r\npublic sealed class PlayerFootsteps : Component\r\n{\r\n\t[Property] SkinnedModelRenderer Source { get; set; }\r\n\r\n\tprotected override void OnEnabled()\r\n\t{\r\n\t\tif ( Source is null )\r\n\t\t\treturn;\r\n\r\n\t\tSource.OnFootstepEvent \u002B= OnEvent;\r\n\t}\r\n\r\n\tprotected override void OnDisabled()\r\n\t{\r\n\t\tif ( Source is null )\r\n\t\t\treturn;\r\n\r\n\t\tSource.OnFootstepEvent -= OnEvent;\r\n\t}\r\n\r\n\tTimeSince timeSinceStep;\r\n\r\n\tprivate void OnEvent( SceneModel.FootstepEvent e )\r\n\t{\r\n\t\tif ( timeSinceStep \u003C 0.2f )\r\n\t\t\treturn;\r\n\r\n\t\tvar tr = Scene.Trace\r\n\t\t\t.Ray( e.Transform.Position \u002B Vector3.Up * 20, e.Transform.Position \u002B Vector3.Up * -20 )\r\n\t\t\t.Run();\r\n\r\n\t\tif ( !tr.Hit )\r\n\t\t\treturn;\r\n\r\n\t\tif ( tr.Surface is null )\r\n\t\t\treturn;\r\n\r\n\t\ttimeSinceStep = 0;\r\n\r\n\t\tvar sound = e.FootId == 0 ? tr.Surface.Sounds.FootLeft : tr.Surface.Sounds.FootRight;\r\n\t\tif ( sound is null ) return;\r\n\r\n\t\tvar handle = Sound.Play( sound, tr.HitPosition \u002B tr.Normal * 5 );\r\n\t\thandle.Volume *= e.Volume;\r\n\t\thandle.Update();\r\n\t}\r\n}\r\n"},{"Ident":"nolankicks.sceneloadingutility","Path":"BouncyBone.cs","FileName":"BouncyBone.cs","PackageType":"library","CodeKind":"Game","AssetVersionId":65380,"Code":"public sealed class BouncyBone : TransformProxyComponent\r\n{\r\n\tJiggleBoneState state = new JiggleBoneState();\r\n\r\n\t[Property]\r\n\tpublic Vector3 Influence { get; set; } = new Vector3( 1, 1, 1 );\r\n\r\n\t[Property, Range( 0, 50.0f )]\r\n\tpublic float Stiffness { get; set; } = 1;\r\n\r\n\t[Property, Range( 0, 50.0f )]\r\n\tpublic float Damping { get; set; } = 1;\r\n\r\n\tTransform LocalJigglePosition;\r\n\tTransformSpring springer;\r\n\r\n\tprotected override void OnEnabled()\r\n\t{\r\n\t\tspringer = new TransformSpring();\r\n\t\tspringer.Transform = Transform.World;\r\n\t\tLocalJigglePosition = springer.Transform;\r\n\r\n\t\tbase.OnEnabled();\r\n\r\n\r\n\t}\r\n\r\n\tprotected override void OnUpdate()\r\n\t{\r\n\t\tvar oldPos = LocalJigglePosition;\r\n\r\n\t\tusing ( Transform.DisableProxy() )\r\n\t\t{\r\n\t\t\tvar worldTx = Transform.World;\r\n\r\n\t\t\tspringer.Stiffness = Stiffness;\r\n\t\t\tspringer.Damping = Damping;\r\n\t\t\tspringer.UpdateSpring( Transform.World, Time.Delta );\r\n\r\n\t\t\tvar tx = GameObject.Parent.Transform.World.ToLocal( springer.Transform );\r\n\t\t\tLocalJigglePosition = tx;\r\n\t\t}\r\n\r\n\t\tif ( oldPos != LocalJigglePosition )\r\n\t\t{\r\n\t\t\tMarkTransformChanged();\r\n\t\t}\r\n\t}\r\n\r\n\tpublic override Transform GetLocalTransform()\r\n\t{\r\n\t\treturn LocalJigglePosition;\r\n\t}\r\n}\r\n\r\n\r\npublic struct TransformSpring\r\n{\r\n\tpublic Transform Transform;\r\n\r\n\tprivate Vector3 velocityPosition;\r\n\tprivate Vector3 velocityScale;\r\n\tprivate Rotation velocityRotation = Rotation.Identity;\r\n\r\n\tpublic float Stiffness = 1.5f;  // Spring stiffness, higher is stiffer\r\n\tpublic float Damping = 1.0f;      // Damping, higher is less oscillation\r\n\r\n\tpublic TransformSpring()\r\n\t{\r\n\t\tTransform = global::Transform.Zero;\r\n\t}\r\n\r\n\tpublic void UpdateSpring( Transform target, float deltaTime )\r\n\t{\r\n\t\tTransform.Position = SpringLerp( Transform.Position, target.Position, ref velocityPosition, deltaTime );\r\n\t\tTransform.Scale = SpringLerp( Transform.Scale, target.Scale, ref velocityScale, deltaTime );\r\n\t\tTransform.Rotation = target.Rotation;\r\n\t}\r\n\r\n\tprivate Vector3 SpringLerp( Vector3 current, Vector3 target, ref Vector3 velocity, float deltaTime )\r\n\t{\r\n\t\tfloat omega = 2f * MathF.PI * Stiffness;\r\n\t\tfloat damper = MathF.Exp( -Damping * deltaTime * omega );\r\n\r\n\t\tVector3 displacement = current - target;\r\n\t\tVector3 springForce = -omega * omega * displacement;\r\n\t\tVector3 dampingForce = -2f * omega * Damping * velocity;\r\n\r\n\t\tVector3 acceleration = springForce \u002B dampingForce;\r\n\t\tvelocity = (velocity \u002B acceleration * deltaTime) * damper;\r\n\t\treturn target \u002B displacement \u002B velocity * deltaTime;\r\n\t}\r\n\r\n\r\n}\r\n"},{"Ident":"nolankicks.sceneloadingutility","Path":"GameEvent.cs","FileName":"GameEvent.cs","PackageType":"library","CodeKind":"Game","AssetVersionId":65380,"Code":"using System;\r\nusing System.Collections.Generic;\r\nusing System.Collections.Immutable;\r\nusing System.Linq;\r\n\r\nnamespace Sandbox.Events;\r\n\r\n/// \u003Csummary\u003E\r\n/// Interface for event payloads that can be listened for by \u003Csee cref=\u0022IGameEventHandler{T}\u0022/\u003Es.\r\n/// \u003C/summary\u003E\r\npublic interface IGameEvent { }\r\n\r\n/// \u003Csummary\u003E\r\n/// Interface for components that handle game events with a payload of type \u003Csee cref=\u0022T\u0022/\u003E.\r\n/// \u003C/summary\u003E\r\n/// \u003Ctypeparam name=\u0022T\u0022\u003EEvent payload type.\u003C/typeparam\u003E\r\npublic interface IGameEventHandler\u003Cin T\u003E\r\n\twhere T : IGameEvent\r\n{\r\n\t/// \u003Csummary\u003E\r\n\t/// Called when an event with payload of type \u003Csee cref=\u0022T\u0022/\u003E is dispatched on a \u003Csee cref=\u0022GameObject\u0022/\u003E\r\n\t/// that contains this component, including on a descendant.\r\n\t/// \u003C/summary\u003E\r\n\t/// \u003Cparam name=\u0022eventArgs\u0022\u003EEvent payload.\u003C/param\u003E\r\n\tvoid OnGameEvent( T eventArgs );\r\n}\r\n\r\n/// \u003Csummary\u003E\r\n/// Helper for dispatching game events in a scene.\r\n/// \u003C/summary\u003E\r\npublic static class GameEvent\r\n{\r\n\tprivate static Dictionary\u003CType, IReadOnlyDictionary\u003CType, int\u003E\u003E HandlerOrderingCache { get; } = new();\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Notifies all \u003Csee cref=\u0022IGameEventHandler{T}\u0022/\u003E components that are within \u003Cparamref name=\u0022root\u0022/\u003E,\r\n\t/// with a payload of type \u003Ctypeparamref name=\u0022T\u0022/\u003E.\r\n\t/// \u003C/summary\u003E\r\n\tpublic static void Dispatch\u003CT\u003E( this GameObject root, T eventArgs )\r\n\t\twhere T : IGameEvent\r\n\t{\r\n\t\tvar handlers = (root is Scene scene\r\n\t\t\t? scene.GetAllComponents\u003CIGameEventHandler\u003CT\u003E\u003E() // I think this is more efficient?\r\n\t\t\t: root.Components.GetAll\u003CIGameEventHandler\u003CT\u003E\u003E())\r\n\t\t\t.ToArray();\r\n\r\n\t\tif ( !HandlerOrderingCache.TryGetValue( typeof(T), out var ordering ) || handlers.Any( x =\u003E !ordering.ContainsKey( x.GetType() ) ) )\r\n\t\t{\r\n\t\t\tordering = HandlerOrderingCache[typeof(T)] = GetHandlerOrdering\u003CT\u003E();\r\n\t\t}\r\n\r\n\t\tList\u003CException\u003E? exceptions = null;\r\n\r\n\t\tforeach ( var handler in handlers.OrderBy( x =\u003E ordering[x.GetType()] ) )\r\n\t\t{\r\n\t\t\ttry\r\n\t\t\t{\r\n\t\t\t\thandler.OnGameEvent( eventArgs );\r\n\t\t\t}\r\n\t\t\tcatch ( Exception e )\r\n\t\t\t{\r\n\t\t\t\texceptions ??= new();\r\n\t\t\t\texceptions.Add( e );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tswitch ( exceptions?.Count )\r\n\t\t{\r\n\t\t\tcase 1:\r\n\t\t\t\tLog.Error( exceptions[0] );\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase \u003E 1:\r\n\t\t\t\tLog.Error( new AggregateException( exceptions ) );\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tprivate static bool IsImplementingMethodName( string methodName )\r\n\t{\r\n\t\tif ( methodName == nameof(IGameEventHandler\u003CIGameEvent\u003E.OnGameEvent) )\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\t\treturn methodName.StartsWith( \u0022Sandbox.Events.IGameEventHandler\u003C\u0022 ) \u0026\u0026 methodName.EndsWith( \u0022\u003E.OnGameEvent\u0022 );\r\n\t}\r\n\r\n\tprivate static MethodDescription? GetImplementation\u003CT\u003E( TypeDescription type )\r\n\t{\r\n\t\tforeach ( var method in type.Methods )\r\n\t\t{\r\n\t\t\tif ( method.IsStatic ) continue;\r\n\t\t\tif ( method.Parameters.Length != 1 ) continue;\r\n\t\t\tif ( method.Parameters[0].ParameterType != typeof( T ) ) continue;\r\n\r\n\t\t\tif ( !IsImplementingMethodName( method.Name ) ) continue;\r\n\r\n\t\t\treturn method;\r\n\t\t}\r\n\r\n\t\treturn null;\r\n\t}\r\n\r\n\tprivate static IReadOnlyDictionary\u003CType, int\u003E GetHandlerOrdering\u003CT\u003E()\r\n\t\twhere T : IGameEvent\r\n\t{\r\n\t\tvar types = TypeLibrary.GetTypes\u003CIGameEventHandler\u003CT\u003E\u003E().ToArray();\r\n\t\tvar helper = new SortingHelper( types.Length );\r\n\r\n\t\tfor ( var i = 0; i \u003C types.Length; \u002B\u002Bi )\r\n\t\t{\r\n\t\t\tvar type = types[i];\r\n\t\t\tvar method = GetImplementation\u003CT\u003E( type );\r\n\r\n\t\t\tif ( method is null )\r\n\t\t\t{\r\n\t\t\t\tLog.Warning( $\u0022Can\u0027t find {nameof( IGameEventHandler\u003CT\u003E )}\u003C{typeof( T ).Name}\u003E implementation in {type.Name}!\u0022 );\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tforeach ( var attrib in method.Attributes )\r\n\t\t\t{\r\n\t\t\t\tswitch ( attrib )\r\n\t\t\t\t{\r\n\t\t\t\t\tcase EarlyAttribute:\r\n\t\t\t\t\t\thelper.AddFirst( i );\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase LateAttribute:\r\n\t\t\t\t\t\thelper.AddLast( i );\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase IBeforeAttribute before:\r\n\t\t\t\t\t\tfor ( var j = 0; j \u003C types.Length; \u002B\u002Bj )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif ( i == j ) continue;\r\n\r\n\t\t\t\t\t\t\tvar other = types[j];\r\n\r\n\t\t\t\t\t\t\tif ( before.Type.IsAssignableFrom( other.TargetType ) )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\thelper.AddConstraint( i, j );\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase IAfterAttribute after:\r\n\t\t\t\t\t\tfor ( var j = 0; j \u003C types.Length; \u002B\u002Bj )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif ( i == j ) continue;\r\n\r\n\t\t\t\t\t\t\tvar other = types[j];\r\n\r\n\t\t\t\t\t\t\tif ( after.Type.IsAssignableFrom( other.TargetType ) )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\thelper.AddConstraint( j, i );\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tvar ordering = new List\u003Cint\u003E();\r\n\r\n\t\tif ( !helper.Sort( ordering, out var invalid ) )\r\n\t\t{\r\n\t\t\tLog.Error( $\u0022Invalid event ordering constraint between {types[invalid.EarlierIndex].Name} and {types[invalid.LaterIndex].Name}!\u0022 );\r\n\t\t\treturn ImmutableDictionary\u003CType, int\u003E.Empty;\r\n\t\t}\r\n\r\n\t\treturn Enumerable.Range( 0, ordering.Count )\r\n\t\t\t.ToImmutableDictionary( i =\u003E types[ordering[i]].TargetType, i =\u003E i );\r\n\t}\r\n}\r\n\r\npublic delegate void GameEventAction\u003Cin T\u003E( T eventArgs )\r\n\twhere T : IGameEvent;\r\n\r\n/// \u003Csummary\u003E\r\n/// Base class for components that expose game events to Action Graph.\r\n/// \u003C/summary\u003E\r\npublic abstract class GameEventComponent\u003CT\u003E : Component, IGameEventHandler\u003CT\u003E\r\n\twhere T : IGameEvent\r\n{\r\n\t/// \u003Csummary\u003E\r\n\t/// Action invoked when the \u003Ctypeparamref name=\u0022T\u0022/\u003E event is dispatched.\r\n\t/// \u003C/summary\u003E\r\n\t[Property]\r\n\tpublic GameEventAction\u003CT\u003E? OnEvent { get; set; }\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// If this component is within a state machine, optional state to transition\r\n\t/// to when this event is dispatched.\r\n\t/// \u003C/summary\u003E\r\n\t[Property]\r\n\tpublic StateComponent? NextState { get; set; }\r\n\r\n\tvoid IGameEventHandler\u003CT\u003E.OnGameEvent( T eventArgs )\r\n\t{\r\n\t\tOnEvent?.Invoke( eventArgs );\r\n\r\n\t\tif ( NextState is not null )\r\n\t\t{\r\n\t\t\tComponents.GetInAncestorsOrSelf\u003CStateMachineComponent\u003E()?.Transition( NextState );\r\n\t\t}\r\n\t}\r\n}\r\n"},{"Ident":"nolankicks.sceneloadingutility","Path":"StateMachine.cs","FileName":"StateMachine.cs","PackageType":"library","CodeKind":"Game","AssetVersionId":65380,"Code":"using System;\r\nusing System.Collections.Generic;\r\nusing System.Linq;\r\nusing Sandbox.Diagnostics;\r\n\r\nnamespace Sandbox.Events;\r\n\r\n/// \u003Csummary\u003E\r\n/// \u003Cpara\u003E\r\n/// A state machine containing a set of \u003Csee cref=\u0022StateComponent\u0022/\u003Es. The \u003Csee cref=\u0022GameObject\u0022/\u003E containing\r\n/// the currently active state will be enabled (including its ancestors), and all other objects containing states\r\n/// are disabled.\r\n/// \u003C/para\u003E\r\n/// \u003Cpara\u003E\r\n/// The currently active state is controlled by the owner, and synchronised over the network. When a transition occurs,\r\n/// a \u003Csee cref=\u0022LeaveStateEvent\u0022/\u003E is dispatched on the old state\u0027s containing object, followed by a\r\n/// \u003Csee cref=\u0022EnterStateEvent\u0022/\u003E event on the object containing the new state. These events are only dispatched\r\n/// on the owner.\r\n/// \u003C/para\u003E\r\n/// \u003C/summary\u003E\r\n[Title( \u0022State Machine\u0022 ), Category( \u0022State Machines\u0022 )]\r\npublic sealed class StateMachineComponent : Component\r\n{\r\n\tprivate StateComponent? _currentState;\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// How many instant state transitions in a row until we throw an error?\r\n\t/// \u003C/summary\u003E\r\n\tpublic const int MaxInstantTransitions = 16;\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Which state is currently active?\r\n\t/// \u003C/summary\u003E\r\n\t[Property, Sync]\r\n\tpublic StateComponent? CurrentState\r\n\t{\r\n\t\tget =\u003E _currentState;\r\n\t\tset\r\n\t\t{\r\n\t\t\tif ( _currentState == value ) return;\r\n\t\t\t_currentState = value;\r\n\r\n\t\t\tif ( Network.IsProxy )\r\n\t\t\t{\r\n\t\t\t\tEnableActiveStates( false );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Which state will we transition to next, at \u003Csee cref=\u0022NextStateTime\u0022/\u003E?\r\n\t/// \u003C/summary\u003E\r\n\t[Sync]\r\n\tpublic StateComponent? NextState { get; set; }\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// What time will we transition to \u003Csee cref=\u0022NextState\u0022/\u003E?\r\n\t/// \u003C/summary\u003E\r\n\t[Sync]\r\n\tpublic float NextStateTime { get; set; }\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// All states found on descendant objects.\r\n\t/// \u003C/summary\u003E\r\n\tpublic IEnumerable\u003CStateComponent\u003E States =\u003E Components.GetAll\u003CStateComponent\u003E( FindMode.EverythingInSelfAndDescendants );\r\n\r\n\tprotected override void OnStart()\r\n\t{\r\n\t\tforeach ( var state in States )\r\n\t\t{\r\n\t\t\tstate.Enabled = false;\r\n\t\t\tstate.GameObject.Enabled = state.GameObject == GameObject;\r\n\t\t}\r\n\r\n\t\tif ( !Network.IsProxy \u0026\u0026 CurrentState is { } current )\r\n\t\t{\r\n\t\t\tTransition( current );\r\n\t\t}\r\n\t}\r\n\r\n\tprivate void EnableActiveStates( bool dispatch )\r\n\t{\r\n\t\tvar current = CurrentState;\r\n\t\tvar active = current?.GetAncestors() ?? Array.Empty\u003CStateComponent\u003E();\r\n\t\tvar activeSet = active.ToHashSet();\r\n\r\n\t\tvar toDeactivate = new Queue\u003CStateComponent\u003E( States.Where( x =\u003E x.Enabled \u0026\u0026 !activeSet.Contains( x ) ).Reverse() );\r\n\t\tvar toActivate = new Queue\u003CStateComponent\u003E( active.Where( x =\u003E !x.Enabled ) );\r\n\r\n\t\tif ( current != null )\r\n\t\t{\r\n\t\t\ttoActivate.Enqueue( current );\r\n\t\t}\r\n\r\n\t\twhile ( toDeactivate.TryDequeue( out var next ) )\r\n\t\t{\r\n\t\t\tnext.Leave( dispatch );\r\n\r\n\t\t\tif ( toDeactivate.All( x =\u003E x.GameObject != next.GameObject ) \u0026\u0026 toActivate.All( x =\u003E x.GameObject != next.GameObject ) )\r\n\t\t\t{\r\n\t\t\t\tnext.GameObject.Enabled = false;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\twhile ( toActivate.TryDequeue( out var next ) )\r\n\t\t{\r\n\t\t\tnext.GameObject.Enabled = true;\r\n\r\n\t\t\tnext.Enter( dispatch );\r\n\t\t}\r\n\t}\r\n\r\n\tprotected override void OnFixedUpdate()\r\n\t{\r\n\t\tif ( Network.IsProxy )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif ( CurrentState is not { } current )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tcurrent.Update();\r\n\r\n\t\tvar transitions = 0;\r\n\r\n\t\twhile ( transitions\u002B\u002B \u003C MaxInstantTransitions )\r\n\t\t{\r\n\t\t\tif ( NextState is not { } next || !(Time.Now \u003E= NextStateTime) )\r\n\t\t\t{\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tif ( next.DefaultNextState is not null )\r\n\t\t\t{\r\n\t\t\t\tTransition( next.DefaultNextState, next.DefaultDuration );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tClearTransition();\r\n\t\t\t}\r\n\r\n\t\t\tCurrentState = next;\r\n\r\n\t\t\tEnableActiveStates( true );\r\n\t\t}\r\n\t}\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Queue up a transition to the given state. This will occur at the end of\r\n\t/// a fixed update on the state machine.\r\n\t/// \u003C/summary\u003E\r\n\tpublic void Transition( StateComponent next, float delaySeconds = 0f )\r\n\t{\r\n\t\tAssert.NotNull( next );\r\n\t\tAssert.False( Network.IsProxy );\r\n\r\n\t\tNextState = next;\r\n\t\tNextStateTime = Time.Now \u002B delaySeconds;\r\n\t}\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Removes any pending transitions, so this state machine will remain in the\r\n\t/// current state until another transition is queued with \u003Csee cref=\u0022Transition\u0022/\u003E.\r\n\t/// \u003C/summary\u003E\r\n\tpublic void ClearTransition()\r\n\t{\r\n\t\tAssert.False( Network.IsProxy );\r\n\r\n\t\tNextState = null;\r\n\t\tNextStateTime = float.PositiveInfinity;\r\n\t}\r\n}\r\n"},{"Ident":"nolankicks.sceneloadingutility","Path":"__gen_RazorNamespace.cs","FileName":"__gen_RazorNamespace.cs","PackageType":"library","CodeKind":"Game","AssetVersionId":65380,"Code":"global using Microsoft.AspNetCore.Components; \nglobal using Microsoft.AspNetCore.Components.Rendering;\n"},{"Ident":"nolankicks.sceneloadingutility","Path":"UnitTests/UnitTest.cs","FileName":"UnitTest.cs","PackageType":"library","CodeKind":"UnitTest","AssetVersionId":65380,"Code":"global using Microsoft.VisualStudio.TestTools.UnitTesting;\r\n\r\n[TestClass]\r\npublic class TestInit\r\n{\r\n\t[AssemblyInitialize]\r\n\tpublic static void ClassInitialize( TestContext context )\r\n\t{\r\n\t\tSandbox.Application.InitUnitTest();\r\n\t}\r\n}\r\n"},{"Ident":"nolankicks.sceneloadingutility","Path":"Code/SceneLoadingExample.cs","FileName":"SceneLoadingExample.cs","PackageType":"library","CodeKind":"Game","AssetVersionId":65380,"Code":"using System.Linq;\r\nusing Microsoft.VisualBasic;\r\nusing Sandbox;\r\nusing SceneLoading;\r\npublic sealed class ChangeSceneTrigger : Component, Component.ITriggerListener\r\n{\r\n\t[Property] public SceneFile sceneFile { get; set; }\r\n\t[Property] public GameObject PrefabTest { get; set; }\r\n\r\n\tvoid ITriggerListener.OnTriggerEnter( Sandbox.Collider other )\r\n\t{\r\n\t\tif ( other.GameObject.Tags.Has( \u0022player\u0022 ) )\r\n\t\t{\r\n\t\t\tLoadScene();\r\n\t\t}\r\n\t}\r\n\r\n\tvoid ITriggerListener.OnTriggerExit( Sandbox.Collider other )\r\n\t{\r\n\r\n\t}\r\n\r\n\tpublic void LoadScene()\r\n\t{\r\n\t\tvar customScene = new CustomScene( sceneFile );\r\n\t\tif ( customScene.GetAllObjectsByType( typeof( SkinnedModelRenderer ) ).Count() == 0 )\r\n\t\t{\r\n\t\t\tcustomScene.CreateObject( new GameObject() );\r\n\t\t}\r\n\r\n\t\tcustomScene.LoadScene();\r\n\t}\r\n}\r\n"},{"Ident":"nolankicks.sceneloadingutility","Path":"MyLibraryComponent.cs","FileName":"MyLibraryComponent.cs","PackageType":"library","CodeKind":"Game","AssetVersionId":65380,"Code":"using Sandbox;\r\n\r\n/// \u003Csummary\u003E\r\n/// This is a component - in your library!\r\n/// \u003C/summary\u003E\r\n[Title( \u0022Screen Shot Library - My Component\u0022 )]\r\npublic class MyLibraryComponent : Component\r\n{\r\n\r\n}\r\n"},{"Ident":"nolankicks.sceneloadingutility","Path":"SceneLoadingExample.cs","FileName":"SceneLoadingExample.cs","PackageType":"library","CodeKind":"Game","AssetVersionId":65380,"Code":"using System.Linq;\r\nusing Microsoft.VisualBasic;\r\nusing Sandbox;\r\nusing SceneLoading;\r\npublic sealed class ChangeSceneTrigger : Component, Component.ITriggerListener\r\n{\r\n\t[Property] public SceneFile sceneFile { get; set; }\r\n\t[Property] public GameObject PrefabTest { get; set; }\r\n\r\n\tvoid ITriggerListener.OnTriggerEnter( Sandbox.Collider other )\r\n\t{\r\n\t\tif ( other.GameObject.Tags.Has( \u0022player\u0022 ) )\r\n\t\t{\r\n\t\t\tLoadScene();\r\n\t\t}\r\n\t}\r\n\r\n\tvoid ITriggerListener.OnTriggerExit( Sandbox.Collider other )\r\n\t{\r\n\r\n\t}\r\n\r\n\tpublic void LoadScene()\r\n\t{\r\n\t\tvar customScene = new CustomScene( sceneFile );\r\n\t\tif ( customScene.GetAllObjectsByType( typeof( SkinnedModelRenderer ) ).Count() == 0 )\r\n\t\t{\r\n\t\t\tcustomScene.CreateObject( new GameObject() );\r\n\t\t}\r\n\r\n\t\tcustomScene.LoadScene();\r\n\t}\r\n}\r\n"},{"Ident":"nolankicks.sceneloadingutility","Path":"State.cs","FileName":"State.cs","PackageType":"library","CodeKind":"Game","AssetVersionId":65380,"Code":"using System;\r\nusing System.Collections.Generic;\r\n\r\nnamespace Sandbox.Events;\r\n\r\n/// \u003Csummary\u003E\r\n/// Marks a \u003Csee cref=\u0022GameObject\u0022/\u003E as a state in a state machine. There must be a\r\n/// \u003Csee cref=\u0022StateMachineComponent\u0022/\u003E on an ancestor object for this to function.\r\n/// The object containing this state (and all ancestors) will be enabled when the state\r\n/// machine transitions to this state, and will disable again when this state is exited.\r\n/// States may be nested within each other.\r\n/// \u003C/summary\u003E\r\n[Title( \u0022State\u0022 ), Category( \u0022State Machines\u0022 )]\r\npublic sealed class StateComponent : Component\r\n{\r\n\tprivate StateMachineComponent? _stateMachine;\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Which state machine does this state belong to?\r\n\t/// \u003C/summary\u003E\r\n\tpublic StateMachineComponent StateMachine =\u003E\r\n\t\t_stateMachine ??= Components.GetInAncestorsOrSelf\u003CStateMachineComponent\u003E();\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Which state is this nested in, if any?\r\n\t/// \u003C/summary\u003E\r\n\tpublic StateComponent? Parent =\u003E Components.GetInAncestors\u003CStateComponent\u003E( true );\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Transition to this state by default.\r\n\t/// \u003C/summary\u003E\r\n\t[Property]\r\n\tpublic StateComponent? DefaultNextState { get; set; }\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// If \u003Csee cref=\u0022DefaultNextState\u0022/\u003E is given, transition after this delay in seconds.\r\n\t/// \u003C/summary\u003E\r\n\t[Property, HideIf( nameof( DefaultNextState ), null )]\r\n\tpublic float DefaultDuration { get; set; }\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Event dispatched on the owner when this state is entered.\r\n\t/// \u003C/summary\u003E\r\n\t[Property]\r\n\tpublic event Action? OnEnterState;\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Event dispatched on the owner while this state is active.\r\n\t/// \u003C/summary\u003E\r\n\t[Property]\r\n\tpublic event Action? OnUpdateState;\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Event dispatched on the owner when this state is exited.\r\n\t/// \u003C/summary\u003E\r\n\t[Property]\r\n\tpublic event Action? OnLeaveState;\r\n\r\n\tinternal void Enter( bool dispatch )\r\n\t{\r\n\t\tEnabled = true;\r\n\r\n\t\tif ( dispatch )\r\n\t\t{\r\n\t\t\tOnEnterState?.Invoke();\r\n\t\t\tGameObject.Dispatch( new EnterStateEvent( this ) );\r\n\t\t}\r\n\t}\r\n\r\n\tinternal void Update()\r\n\t{\r\n\t\tOnUpdateState?.Invoke();\r\n\t\tScene.Dispatch( new UpdateStateEvent( this ) );\r\n\t}\r\n\r\n\tinternal void Leave( bool dispatch )\r\n\t{\r\n\t\tif ( dispatch )\r\n\t\t{\r\n\t\t\tOnLeaveState?.Invoke();\r\n\t\t\tGameObject.Dispatch( new LeaveStateEvent( this ) );\r\n\t\t}\r\n\r\n\t\tEnabled = false;\r\n\t}\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Queue up a transition to the given state. This will occur at the end of\r\n\t/// a fixed update on the state machine.\r\n\t/// \u003C/summary\u003E\r\n\tpublic void Transition( StateComponent next, float delaySeconds = 0f )\r\n\t{\r\n\t\tStateMachine.Transition( next, delaySeconds );\r\n\t}\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Queue up a transition to the default next state.\r\n\t/// \u003C/summary\u003E\r\n\tpublic void Transition()\r\n\t{\r\n\t\tStateMachine.Transition( DefaultNextState! );\r\n\t}\r\n\r\n\tinternal IReadOnlyList\u003CStateComponent\u003E GetAncestors()\r\n\t{\r\n\t\tvar list = new List\u003CStateComponent\u003E();\r\n\r\n\t\tvar parent = Parent;\r\n\r\n\t\twhile ( parent != null )\r\n\t\t{\r\n\t\t\tlist.Add( parent );\r\n\t\t\tparent = parent.Parent;\r\n\t\t}\r\n\r\n\t\tlist.Reverse();\r\n\r\n\t\treturn list;\r\n\t}\r\n}\r\n\r\n/// \u003Csummary\u003E\r\n/// Event dispatched on the owner when a \u003Csee cref=\u0022StateMachineComponent\u0022/\u003E changes state.\r\n/// Only invoked on components on the same object as the new state.\r\n/// \u003C/summary\u003E\r\npublic record EnterStateEvent( StateComponent State ) : IGameEvent;\r\n\r\n/// \u003Cinheritdoc cref=\u0022EnterStateEvent\u0022/\u003E\r\n[Title( \u0022Enter State Event\u0022 ), Group( \u0022State Machines\u0022 ), Icon( \u0022electric_bolt\u0022 )]\r\npublic sealed class EnterStateEventComponent : GameEventComponent\u003CEnterStateEvent\u003E { }\r\n\r\n/// \u003Csummary\u003E\r\n/// Event dispatched on the owner when a \u003Csee cref=\u0022StateMachineComponent\u0022/\u003E changes state.\r\n/// Only invoked on components on the same object as the old state.\r\n/// \u003C/summary\u003E\r\npublic record LeaveStateEvent( StateComponent State ) : IGameEvent;\r\n\r\n/// \u003Cinheritdoc cref=\u0022LeaveStateEvent\u0022/\u003E\r\n[Title( \u0022Leave State Event\u0022 ), Group( \u0022State Machines\u0022 ), Icon( \u0022electric_bolt\u0022 )]\r\npublic sealed class LeaveStateEventComponent : GameEventComponent\u003CLeaveStateEvent\u003E { }\r\n\r\n/// \u003Csummary\u003E\r\n/// Event dispatched on the owner every fixed update while a \u003Csee cref=\u0022StateComponent\u0022/\u003E is active.\r\n/// Only invoked on components on the same object as the state.\r\n/// \u003C/summary\u003E\r\npublic record UpdateStateEvent( StateComponent State ) : IGameEvent;\r\n\r\n/// \u003Cinheritdoc cref=\u0022UpdateStateEvent\u0022/\u003E\r\n[Title( \u0022Update State Event\u0022 ), Group( \u0022State Machines\u0022 ), Icon( \u0022electric_bolt\u0022 )]\r\npublic sealed class UpdateStateEventComponent : GameEventComponent\u003CUpdateStateEvent\u003E { }\r\n"},{"Ident":"nolankicks.sceneloadingutility","Path":"SceneLoadingUtility.cs","FileName":"SceneLoadingUtility.cs","PackageType":"library","CodeKind":"Game","AssetVersionId":65380,"Code":"using System;\r\nusing System.Collections.Generic;\r\nusing System.Data;\r\nusing System.Dynamic;\r\nusing System.Formats.Tar;\r\nusing System.Linq;\r\nusing System.Reflection.PortableExecutable;\r\nusing System.Text.Json;\r\nusing System.Text.Json.Nodes;\r\nusing System.Text.Json.Serialization;\r\nusing Microsoft.CSharp.RuntimeBinder;\r\nusing Sandbox;\r\nusing Sandbox.ActionGraphs;\r\nnamespace SceneLoading\r\n{\r\n\tpublic class SceneLoadingUtility\r\n\t{\r\n\t\tpublic static void LoadScene( SceneFile sceneFile, SceneLoadingResource sceneLoadingResource )\r\n\t\t{\r\n\t\t\tvar objects = sceneFile.GameObjects;\r\n\t\t\tGame.ActiveScene.Load( new SceneFile() );\r\n\r\n\t\t\tforeach ( var obj in objects )\r\n\t\t\t{\r\n\t\t\t\tvar gameObject = Game.ActiveScene.CreateObject();\r\n\t\t\t\tgameObject.Deserialize( obj );\r\n\t\t\t}\r\n\r\n\t\t\tforeach ( var clone in sceneLoadingResource.SceneLoadingClasses )\r\n\t\t\t{\r\n\t\t\t\tbool gameObjectSpawned = false;\r\n\r\n\t\t\t\tforeach ( var componentType in clone.ComponentTypes )\r\n\t\t\t\t{\r\n\r\n\t\t\t\t\tif ( clone.Flags == LoadingFlags.CheckForComponents \u0026\u0026 Game.ActiveScene.Components.GetAll( componentType, FindMode.EverythingInSelfAndDescendants ).Count() \u003E 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tLog.Info( \u0022Component found, skipping\u0022 );\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if ( clone.Flags == LoadingFlags.DestroyFirst \u0026\u0026 Game.ActiveScene.Components.GetAll( componentType, FindMode.EverythingInSelfAndDescendants ).Count() \u003E 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tLog.Info( \u0022Component found, replacing\u0022 );\r\n\t\t\t\t\t\tGame.ActiveScene.Components.GetAll( componentType, FindMode.EverythingInSelfAndDescendants ).FirstOrDefault()?.GameObject.Destroy();\r\n\t\t\t\t\t\tif ( gameObjectSpawned ) return;\r\n\t\t\t\t\t\tvar gb = clone.Prefab.Clone();\r\n\t\t\t\t\t\tgb.BreakFromPrefab();\r\n\t\t\t\t\t\tif ( clone.NetworkSpawn ) gb.NetworkSpawn( null );\r\n\t\t\t\t\t\tgameObjectSpawned = true;\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if ( clone.Flags == LoadingFlags.DestroyAll \u0026\u0026 Game.ActiveScene.Components.GetAll( componentType, FindMode.EverythingInSelfAndDescendants ).Count() \u003E 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tLog.Info( \u0022Component found, replacing all\u0022 );\r\n\t\t\t\t\t\tforeach ( var component in Game.ActiveScene.Components.GetAll( componentType, FindMode.EverythingInSelfAndDescendants ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tcomponent.GameObject.Destroy();\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif ( gameObjectSpawned ) return;\r\n\t\t\t\t\t\tvar gb = clone.Prefab.Clone();\r\n\t\t\t\t\t\tgb.BreakFromPrefab();\r\n\t\t\t\t\t\tif ( clone.NetworkSpawn ) gb.NetworkSpawn( null );\r\n\t\t\t\t\t\tgameObjectSpawned = true;\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( !gameObjectSpawned )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tvar obj = clone.Prefab.Clone();\r\n\t\t\t\t\t\tobj.BreakFromPrefab();\r\n\t\t\t\t\t\tif ( clone.NetworkSpawn ) obj.NetworkSpawn( null );\r\n\t\t\t\t\t\tgameObjectSpawned = true;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tpublic enum LoadingFlags\r\n\t{\r\n\t\tNone,\r\n\t\t[Description( \u0022Checks if a component is in the scene, if it is, the prefab will not be spawned\u0022 )]\r\n\t\tCheckForComponents,\r\n\t\t[Description( \u0022Checks if a component is in the scene, if it is, the first one will be destroyed, and the prefab will be spawned\u0022 )]\r\n\t\tDestroyFirst,\r\n\t\t[Description( \u0022Checks if a component is in the scene, if it is, all of them will be destroyed and the prefab will be spawned\u0022 )]\r\n\t\tDestroyAll,\r\n\r\n\t}\r\n\r\n\r\n\t[GameResource( \u0022SceneLoadingResource\u0022, \u0022loading\u0022, \u0022A resource that allows spawning of prefabs on scene start\u0022, Icon = \u0022public\u0022 )]\r\n\tpublic class SceneLoadingResource : GameResource\r\n\t{\r\n\t\tpublic List\u003CSceneLoadingClass\u003E SceneLoadingClasses { get; set; } = new();\r\n\t}\r\n\tpublic class SceneLoadingClass\r\n\t{\r\n\t\tpublic GameObject Prefab { get; set; }\r\n\t\tpublic LoadingFlags Flags { get; set; } = LoadingFlags.None;\r\n\t\tpublic List\u003CType\u003E ComponentTypes { get; set; }\r\n\t\tpublic bool NetworkSpawn { get; set; } = false;\r\n\r\n\r\n\t\tpublic SceneLoadingClass()\r\n\t\t{\r\n\t\t\tPrefab = null;\r\n\t\t\tFlags = LoadingFlags.None;\r\n\t\t\tComponentTypes = null;\r\n\t\t}\r\n\r\n\t\tpublic SceneLoadingClass( GameObject prefab, LoadingFlags flags, List\u003CType\u003E componentType )\r\n\t\t{\r\n\t\t\tPrefab = prefab;\r\n\t\t\tFlags = flags;\r\n\t\t\tComponentTypes = componentType;\r\n\t\t}\r\n\t}\r\n\t[Description( \u0022A custom scene that allows for manipulation of the scene file before loading\u0022 )]\r\n\tpublic class CustomScene\r\n\t{\r\n\t\t[Description( \u0022The scenefile you are manipulating, override to change it\u0022 )] public virtual SceneFile sceneFileDupe { get; set; }\r\n\t\tpublic string RawScene { get; private set; }\r\n\t\tpublic Scene newScene { get; private set; } = new();\r\n\t\t[Description( \u0022Called when a scene object is created, return the object you want to spawn, or null to use the default object\u0022 )]\r\n\t\tpublic Action\u003CJsonObject\u003E OnSceneObjectCreated { get; set; }\r\n\t\tpublic Action\u003CJsonObject[]\u003E BeforeSceneLoaded { get; set; }\r\n\t\tpublic CustomScene( SceneFile sceneFile )\r\n\t\t{\r\n\t\t\tsceneFileDupe = new SceneFile();\r\n\t\t\tsceneFileDupe.GameObjects = sceneFile.GameObjects\r\n\t\t\t\t.Select( obj =\u003E JsonSerializer.Deserialize\u003CJsonObject\u003E( JsonSerializer.Serialize( obj ) ) )\r\n\t\t\t\t.ToArray();\r\n\t\t}\r\n\r\n\t\tinternal void LoadSceneInternal()\r\n\t\t{\r\n\t\t\tvar finalScene = new SceneFile();\r\n\t\t\tvar finalList = new List\u003CJsonObject\u003E();\r\n\t\t\tforeach ( var obj in sceneFileDupe.GameObjects )\r\n\t\t\t{\r\n\t\t\t\tOnSceneObjectCreated?.Invoke( obj );\r\n\t\t\t\tfinalList.Add( obj );\r\n\t\t\t}\r\n\r\n\t\t\tfinalScene.GameObjects = finalList.ToArray();\r\n\t\t\tBeforeSceneLoaded?.Invoke( finalScene.GameObjects );\r\n\t\t\tGame.ActiveScene.Load( finalScene );\r\n\t\t}\r\n\t\t[Description( \u0022Load the custom scene\u0022 )]\r\n\t\tpublic void LoadScene()\r\n\t\t{\r\n\t\t\tLoadSceneInternal();\r\n\t\t}\r\n\r\n\t\t[Description( \u0022Create a GameObject within the custom scene\u0022 )]\r\n\t\tpublic void CreateObject( GameObject gameObject )\r\n\t\t{\r\n\t\t\tvar clone = gameObject.Clone();\r\n\t\t\tvar objects = sceneFileDupe.GameObjects.ToList();\r\n\t\t\tobjects.Add( clone.Serialize() );\r\n\t\t\tLog.Info( clone.Serialize().ToString() );\r\n\t\t\tsceneFileDupe.GameObjects = objects.ToArray();\r\n\t\t}\r\n\r\n\t\t[Description( \u0022Remove a GameObject from the custom scene\u0022 )]\r\n\t\tpublic void RemoveObject( JsonNode obj )\r\n\t\t{\r\n\t\t\tList\u003CJsonObject\u003E gameObjects = sceneFileDupe.GameObjects.ToList();\r\n\t\t\tvar selectedObject = gameObjects.Find( x =\u003E x == obj );\r\n\t\t\tgameObjects.Remove( selectedObject );\r\n\t\t\tsceneFileDupe.GameObjects = gameObjects.ToArray();\r\n\r\n\t\t}\r\n\r\n\r\n\r\n\t\tpublic void RemoveComponentByType( JsonObject obj, Type type )\r\n\t\t{\r\n\t\t\tvar preObj = JsonSerializer.Deserialize\u003CJsonObject\u003E( JsonSerializer.Serialize( obj ) );\r\n\t\t\tif ( obj.TryGetPropertyValue( \u0022Components\u0022, out var jsonnode ) \u0026\u0026 jsonnode is not null )\r\n\t\t\t{\r\n\t\t\t\tvar jsonString = jsonnode.ToString();\r\n\t\t\t\tif ( !string.IsNullOrWhiteSpace( jsonString ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tvar components = JsonSerializer.Deserialize\u003CList\u003CJsonNode\u003E\u003E( jsonString );\r\n\t\t\t\t\tvar component = components.Find( x =\u003E x[\u0022__type\u0022]?.ToString() == type.ToString() );\r\n\t\t\t\t\tif ( component is not null )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcomponents.Remove( component );\r\n\t\t\t\t\t\tobj[\u0022Components\u0022] = JsonSerializer.Deserialize\u003CJsonNode\u003E( JsonSerializer.Serialize( components ) );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar gbList = sceneFileDupe.GameObjects.ToList();\r\n\t\t\t\tif ( gbList.Find( x =\u003E x == obj ) is null )\r\n\t\t\t\t{\r\n\t\t\t\t\tvar parentNode = FindParent( preObj );\r\n\t\t\t\t\tvar parent = gbList.Find( x =\u003E x == parentNode );\r\n\t\t\t\t\tif ( parent != null \u0026\u0026 parent.TryGetPropertyValue( \u0022Children\u0022, out var childrenJsonNode ) \u0026\u0026 childrenJsonNode != null )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( childrenJsonNode is JsonArray childrenArray )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tUpdateChildComponentsRecursively( childrenArray, obj );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tLog.Warning( \u0022The \u0027Children\u0027 node is not of type \u0027JsonArray\u0027.\u0022 );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tgbList[gbList.FindIndex( x =\u003E x == obj )] = obj;\r\n\t\t\t\t}\r\n\t\t\t\tsceneFileDupe.GameObjects = gbList.ToArray();\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tprivate void UpdateChildComponentsRecursively( JsonArray childrenArray, JsonObject obj )\r\n\t\t{\r\n\t\t\tforeach ( var child in childrenArray )\r\n\t\t\t{\r\n\t\t\t\tif ( child is JsonObject childObject )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( childObject[\u0022__guid\u0022].ToString() == obj[\u0022__guid\u0022].ToString() )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tchildObject[\u0022Components\u0022] = JsonSerializer.Deserialize\u003CJsonNode\u003E( JsonSerializer.Serialize( obj[\u0022Components\u0022] ) );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if ( childObject.TryGetPropertyValue( \u0022Children\u0022, out var nestedChildrenJsonNode ) \u0026\u0026 nestedChildrenJsonNode is JsonArray nestedChildrenArray )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tUpdateChildComponentsRecursively( nestedChildrenArray, obj );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tpublic void AddComponent( JsonObject obj, JsonObject newComponent )\r\n\t\t{\r\n\t\t\tvar preObj = JsonSerializer.Deserialize\u003CJsonObject\u003E( JsonSerializer.Serialize( obj ) );\r\n\t\t\tif ( obj.TryGetPropertyValue( \u0022Components\u0022, out var jsonnode ) \u0026\u0026 jsonnode is not null )\r\n\t\t\t{\r\n\t\t\t\tvar jsonString = jsonnode.ToString();\r\n\t\t\t\tif ( !string.IsNullOrWhiteSpace( jsonString ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tvar components = JsonSerializer.Deserialize\u003CList\u003CJsonNode\u003E\u003E( jsonString );\r\n\t\t\t\t\tcomponents.Add( newComponent );\r\n\t\t\t\t\tobj[\u0022Components\u0022] = JsonSerializer.Deserialize\u003CJsonNode\u003E( JsonSerializer.Serialize( components ) );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tvar components = new List\u003CJsonNode\u003E { newComponent };\r\n\t\t\t\t\tobj[\u0022Components\u0022] = JsonSerializer.Deserialize\u003CJsonNode\u003E( JsonSerializer.Serialize( components ) );\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar gbList = sceneFileDupe.GameObjects.ToList();\r\n\t\t\t\tif ( gbList.Find( x =\u003E x == obj ) is null )\r\n\t\t\t\t{\r\n\t\t\t\t\tvar parentNode = FindParent( preObj );\r\n\t\t\t\t\tvar parent = gbList.Find( x =\u003E x == parentNode );\r\n\t\t\t\t\tif ( parent != null \u0026\u0026 parent.TryGetPropertyValue( \u0022Children\u0022, out var childrenJsonNode ) \u0026\u0026 childrenJsonNode != null )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( childrenJsonNode is JsonArray childrenArray )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tUpdateChildComponentsRecursively( childrenArray, obj );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tLog.Warning( \u0022The \u0027Children\u0027 node is not of type \u0027JsonArray\u0027.\u0022 );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tgbList[gbList.FindIndex( x =\u003E x == obj )] = obj;\r\n\t\t\t\t}\r\n\t\t\t\tsceneFileDupe.GameObjects = gbList.ToArray();\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tpublic void AddComponentByType( JsonObject obj, Type componentType )\r\n\t\t{\r\n\t\t\tvar preObj = JsonSerializer.Deserialize\u003CJsonObject\u003E( JsonSerializer.Serialize( obj ) );\r\n\t\t\tif ( obj.TryGetPropertyValue( \u0022Components\u0022, out var jsonnode ) \u0026\u0026 jsonnode is not null )\r\n\t\t\t{\r\n\t\t\t\tvar jsonString = jsonnode.ToString();\r\n\t\t\t\tvar components = !string.IsNullOrWhiteSpace( jsonString )\r\n\t\t\t\t\t? JsonSerializer.Deserialize\u003CList\u003CJsonNode\u003E\u003E( jsonString )\r\n\t\t\t\t\t: new List\u003CJsonNode\u003E();\r\n\r\n\t\t\t\tvar newComponent = new JsonObject\r\n\t\t\t\t{\r\n\t\t\t\t\t[\u0022__type\u0022] = componentType.ToString()\r\n\t\t\t\t};\r\n\r\n\t\t\t\tcomponents.Add( newComponent );\r\n\t\t\t\tobj[\u0022Components\u0022] = JsonSerializer.Deserialize\u003CJsonNode\u003E( JsonSerializer.Serialize( components ) );\r\n\r\n\t\t\t\tvar gbList = sceneFileDupe.GameObjects.ToList();\r\n\t\t\t\tif ( gbList.Find( x =\u003E x == obj ) is null )\r\n\t\t\t\t{\r\n\t\t\t\t\tvar parentNode = FindParent( preObj );\r\n\t\t\t\t\tvar parent = gbList.Find( x =\u003E x == parentNode );\r\n\t\t\t\t\tif ( parent != null \u0026\u0026 parent.TryGetPropertyValue( \u0022Children\u0022, out var childrenJsonNode ) \u0026\u0026 childrenJsonNode != null )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( childrenJsonNode is JsonArray childrenArray )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tUpdateChildComponentsRecursively( childrenArray, obj );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tLog.Warning( \u0022The \u0027Children\u0027 node is not of type \u0027JsonArray\u0027.\u0022 );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tgbList[gbList.FindIndex( x =\u003E x == obj )] = obj;\r\n\t\t\t\t}\r\n\t\t\t\tsceneFileDupe.GameObjects = gbList.ToArray();\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tpublic JsonObject FindParent( JsonNode children )\r\n\t\t{\r\n\t\t\tforeach ( var obj in sceneFileDupe.GameObjects )\r\n\t\t\t{\r\n\t\t\t\tvar parent = FindParentRecursive( obj, children );\r\n\t\t\t\tif ( parent != null )\r\n\t\t\t\t{\r\n\t\t\t\t\treturn parent;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn null;\r\n\t\t}\r\n\r\n\t\tprivate JsonObject FindParentRecursive( JsonObject parent, JsonNode children )\r\n\t\t{\r\n\t\t\tif ( parent.TryGetPropertyValue( \u0022Children\u0022, out var childrenJsonNode ) )\r\n\t\t\t{\r\n\t\t\t\tvar childrenList = JsonSerializer.Deserialize\u003CList\u003CJsonObject\u003E\u003E( childrenJsonNode.ToString() );\r\n\t\t\t\tif ( childrenList != null )\r\n\t\t\t\t{\r\n\t\t\t\t\tforeach ( var child in childrenList )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( child != null \u0026\u0026 child[\u0022__guid\u0022].ToString() == children[\u0022__guid\u0022].ToString() )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\treturn parent;\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tvar foundParent = FindParentRecursive( child, children );\r\n\t\t\t\t\t\tif ( foundParent != null )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\treturn parent;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn null;\r\n\t\t}\r\n\r\n\t\tpublic IEnumerable\u003CJsonObject\u003E GetAllObjectsByType( Type type )\r\n\t\t{\r\n\t\t\treturn GetAllObjectsByTypeRecursive( sceneFileDupe.GameObjects, type );\r\n\t\t}\r\n\r\n\t\tpublic IEnumerable\u003CJsonObject\u003E GetAllObjectsByGuid( string guid )\r\n\t\t{\r\n\t\t\treturn GetAllObjectsByGuidRecursive( sceneFileDupe.GameObjects, guid );\r\n\t\t}\r\n\r\n\t\tprivate IEnumerable\u003CJsonObject\u003E GetAllObjectsByTypeRecursive( IEnumerable\u003CJsonObject\u003E gameObjects, Type type )\r\n\t\t{\r\n\t\t\tforeach ( var obj in gameObjects )\r\n\t\t\t{\r\n\t\t\t\tif ( obj.TryGetPropertyValue( \u0022Components\u0022, out var jsonnode ) \u0026\u0026 jsonnode is not null )\r\n\t\t\t\t{\r\n\t\t\t\t\tvar jsonString = jsonnode.ToString();\r\n\t\t\t\t\tif ( !string.IsNullOrWhiteSpace( jsonString ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tvar components = JsonSerializer.Deserialize\u003CList\u003CJsonNode\u003E\u003E( jsonString );\r\n\t\t\t\t\t\tif ( components.Any( component =\u003E component[\u0022__type\u0022]?.ToString() == type.ToString() ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tyield return obj;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( obj.TryGetPropertyValue( \u0022Children\u0022, out var childrenJsonNode ) \u0026\u0026 childrenJsonNode is not null )\r\n\t\t\t\t{\r\n\t\t\t\t\tvar childrenString = childrenJsonNode.ToString();\r\n\t\t\t\t\tif ( !string.IsNullOrWhiteSpace( childrenString ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tvar children = JsonSerializer.Deserialize\u003CList\u003CJsonObject\u003E\u003E( childrenString );\r\n\t\t\t\t\t\tforeach ( var child in GetAllObjectsByTypeRecursive( children, type ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tyield return child;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tprivate IEnumerable\u003CJsonObject\u003E GetAllObjectsByGuidRecursive( IEnumerable\u003CJsonObject\u003E gameObjects, string guid )\r\n\t\t{\r\n\t\t\tforeach ( var obj in gameObjects )\r\n\t\t\t{\r\n\t\t\t\tif ( obj.TryGetPropertyValue( \u0022__guid\u0022, out var jsonNode ) \u0026\u0026 jsonNode is not null )\r\n\t\t\t\t{\r\n\t\t\t\t\tvar objectGuid = jsonNode.ToString();\r\n\t\t\t\t\tif ( !string.IsNullOrWhiteSpace( objectGuid ) \u0026\u0026 objectGuid == guid )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tyield return obj;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( obj.TryGetPropertyValue( \u0022Children\u0022, out var childrenJsonNode ) \u0026\u0026 childrenJsonNode is not null )\r\n\t\t\t\t{\r\n\t\t\t\t\tvar childrenString = childrenJsonNode.ToString();\r\n\t\t\t\t\tif ( !string.IsNullOrWhiteSpace( childrenString ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tvar children = JsonSerializer.Deserialize\u003CList\u003CJsonObject\u003E\u003E( childrenString );\r\n\t\t\t\t\t\tforeach ( var child in GetAllObjectsByGuidRecursive( children, guid ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tyield return child;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tpublic IEnumerable\u003CJsonNode\u003E GetAllObjectsByName( string name )\r\n\t\t{\r\n\t\t\tvar objects = sceneFileDupe.GameObjects;\r\n\t\t\tforeach ( var obj in objects )\r\n\t\t\t{\r\n\t\t\t\tobj.TryGetPropertyValue( \u0022Name\u0022, out var objName );\r\n\t\t\t\tif ( objName is not null \u0026\u0026 objName.ToString() == name )\r\n\t\t\t\t{\r\n\t\t\t\t\tyield return obj;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n}\r\n"},{"Ident":"nolankicks.sceneloadingutility","Path":"Editor/SceneLoadingResourceCustomEditor.cs","FileName":"SceneLoadingResourceCustomEditor.cs","PackageType":"library","CodeKind":"Editor","AssetVersionId":65380,"Code":"using Editor;\r\nusing Sandbox;\r\nusing SceneLoading;\r\n\r\n//[CustomEditor(typeof(SceneLoadingClass))]\r\npublic sealed class SceneLoadingResourceCustomEditor : ControlWidget\r\n{\r\n\tpublic SceneLoadingResourceCustomEditor( SerializedProperty property ) : base( property )\r\n\t{\r\n\t\tLayout = Layout.Column();\r\n\r\n\t\tif ( property.IsNull )\r\n\t\t{\r\n\t\t\tproperty.SetValue( new SceneLoadingClass() );\r\n\t\t}\r\n\r\n\t\tvar so = property.GetValue\u003CSceneLoadingClass\u003E()?.GetSerialized();\r\n\t\tif ( so is null ) return;\r\n\t\tvar controlSheet = new ControlSheet();\r\n\t\tcontrolSheet.AddObject( so );\r\n\t\tLayout.Add( controlSheet );\r\n\t}\r\n}\r\n"},{"Ident":"nolankicks.sceneloadingutility","Path":"PlayerController.cs","FileName":"PlayerController.cs","PackageType":"library","CodeKind":"Game","AssetVersionId":65380,"Code":"using Sandbox.Citizen;\r\n\r\n[Group( \u0022Walker\u0022 )]\r\n[Title( \u0022Walker - Player Controller\u0022 )]\r\npublic sealed class PlayerController : Component\r\n{\r\n\t[Property] public CharacterController CharacterController { get; set; }\r\n\t[Property] public float CrouchMoveSpeed { get; set; } = 64.0f;\r\n\t[Property] public float WalkMoveSpeed { get; set; } = 190.0f;\r\n\t[Property] public float RunMoveSpeed { get; set; } = 190.0f;\r\n\t[Property] public float SprintMoveSpeed { get; set; } = 320.0f;\r\n\r\n\t[Property] public CitizenAnimationHelper AnimationHelper { get; set; }\r\n\r\n\t[Sync] public bool Crouching { get; set; }\r\n\t[Sync] public Angles EyeAngles { get; set; }\r\n\t[Sync] public Vector3 WishVelocity { get; set; }\r\n\r\n\tpublic bool WishCrouch;\r\n\tpublic float EyeHeight = 64;\r\n\r\n\tprotected override void OnUpdate()\r\n\t{\r\n\t\tif ( !IsProxy )\r\n\t\t{\r\n\t\t\tMouseInput();\r\n\t\t\tTransform.Rotation = new Angles( 0, EyeAngles.yaw, 0 );\r\n\t\t}\r\n\r\n\t\tUpdateAnimation();\r\n\t}\r\n\r\n\tprotected override void OnFixedUpdate()\r\n\t{\r\n\t\tif ( IsProxy )\r\n\t\t\treturn;\r\n\r\n\t\tCrouchingInput();\r\n\t\tMovementInput();\r\n\t}\r\n\r\n\tprivate void MouseInput()\r\n\t{\r\n\t\tvar e = EyeAngles;\r\n\t\te \u002B= Input.AnalogLook;\r\n\t\te.pitch = e.pitch.Clamp( -90, 90 );\r\n\t\te.roll = 0.0f;\r\n\t\tEyeAngles = e;\r\n\t}\r\n\r\n\tfloat CurrentMoveSpeed\r\n\t{\r\n\t\tget\r\n\t\t{\r\n\t\t\tif ( Crouching ) return CrouchMoveSpeed;\r\n\t\t\tif ( Input.Down( \u0022run\u0022 ) ) return SprintMoveSpeed;\r\n\t\t\tif ( Input.Down( \u0022walk\u0022 ) ) return WalkMoveSpeed;\r\n\r\n\t\t\treturn RunMoveSpeed;\r\n\t\t}\r\n\t}\r\n\r\n\tRealTimeSince lastGrounded;\r\n\tRealTimeSince lastUngrounded;\r\n\tRealTimeSince lastJump;\r\n\r\n\tfloat GetFriction()\r\n\t{\r\n\t\tif ( CharacterController.IsOnGround ) return 6.0f;\r\n\r\n\t\t// air friction\r\n\t\treturn 0.2f;\r\n\t}\r\n\r\n\tprivate void MovementInput()\r\n\t{\r\n\t\tif ( CharacterController is null )\r\n\t\t\treturn;\r\n\r\n\t\tvar cc = CharacterController;\r\n\r\n\t\tVector3 halfGravity = Scene.PhysicsWorld.Gravity * Time.Delta * 0.5f;\r\n\r\n\t\tWishVelocity = Input.AnalogMove;\r\n\r\n\t\tif ( lastGrounded \u003C 0.2f \u0026\u0026 lastJump \u003E 0.3f \u0026\u0026 Input.Pressed( \u0022jump\u0022 ) )\r\n\t\t{\r\n\t\t\tlastJump = 0;\r\n\t\t\tcc.Punch( Vector3.Up * 300 );\r\n\t\t}\r\n\r\n\t\tif ( !WishVelocity.IsNearlyZero() )\r\n\t\t{\r\n\t\t\tWishVelocity = new Angles( 0, EyeAngles.yaw, 0 ).ToRotation() * WishVelocity;\r\n\t\t\tWishVelocity = WishVelocity.WithZ( 0 );\r\n\t\t\tWishVelocity = WishVelocity.ClampLength( 1 );\r\n\t\t\tWishVelocity *= CurrentMoveSpeed;\r\n\r\n\t\t\tif ( !cc.IsOnGround )\r\n\t\t\t{\r\n\t\t\t\tWishVelocity = WishVelocity.ClampLength( 50 );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\r\n\t\tcc.ApplyFriction( GetFriction() );\r\n\r\n\t\tif ( cc.IsOnGround )\r\n\t\t{\r\n\t\t\tcc.Accelerate( WishVelocity );\r\n\t\t\tcc.Velocity = CharacterController.Velocity.WithZ( 0 );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tcc.Velocity \u002B= halfGravity;\r\n\t\t\tcc.Accelerate( WishVelocity );\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\t\t// Don\u0027t walk through other players, let them push you out of the way\r\n\t\t//\r\n\t\tvar pushVelocity = PlayerPusher.GetPushVector( Transform.Position \u002B Vector3.Up * 40.0f, Scene, GameObject );\r\n\t\tif ( !pushVelocity.IsNearlyZero() )\r\n\t\t{\r\n\t\t\tvar travelDot = cc.Velocity.Dot( pushVelocity.Normal );\r\n\t\t\tif ( travelDot \u003C 0 )\r\n\t\t\t{\r\n\t\t\t\tcc.Velocity -= pushVelocity.Normal * travelDot * 0.6f;\r\n\t\t\t}\r\n\r\n\t\t\tcc.Velocity \u002B= pushVelocity * 128.0f;\r\n\t\t}\r\n\r\n\t\tcc.Move();\r\n\r\n\t\tif ( !cc.IsOnGround )\r\n\t\t{\r\n\t\t\tcc.Velocity \u002B= halfGravity;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tcc.Velocity = cc.Velocity.WithZ( 0 );\r\n\t\t}\r\n\r\n\t\tif ( cc.IsOnGround )\r\n\t\t{\r\n\t\t\tlastGrounded = 0;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tlastUngrounded = 0;\r\n\t\t}\r\n\t}\r\n\tfloat DuckHeight = (64 - 36);\r\n\r\n\tbool CanUncrouch()\r\n\t{\r\n\t\tif ( !Crouching ) return true;\r\n\t\tif ( lastUngrounded \u003C 0.2f ) return false;\r\n\r\n\t\tvar tr = CharacterController.TraceDirection( Vector3.Up * DuckHeight );\r\n\t\treturn !tr.Hit; // hit nothing - we can!\r\n\t}\r\n\r\n\tpublic void CrouchingInput()\r\n\t{\r\n\t\tWishCrouch = Input.Down( \u0022duck\u0022 );\r\n\r\n\t\tif ( WishCrouch == Crouching )\r\n\t\t\treturn;\r\n\r\n\t\t// crouch\r\n\t\tif ( WishCrouch )\r\n\t\t{\r\n\t\t\tCharacterController.Height = 36;\r\n\t\t\tCrouching = WishCrouch;\r\n\r\n\t\t\t// if we\u0027re not on the ground, slide up our bbox so when we crouch\r\n\t\t\t// the bottom shrinks, instead of the top, which will mean we can reach\r\n\t\t\t// places by crouch jumping that we couldn\u0027t.\r\n\t\t\tif ( !CharacterController.IsOnGround )\r\n\t\t\t{\r\n\t\t\t\tCharacterController.MoveTo( Transform.Position \u002B= Vector3.Up * DuckHeight, false );\r\n\t\t\t\tTransform.ClearLerp();\r\n\t\t\t\tEyeHeight -= DuckHeight;\r\n\t\t\t}\r\n\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// uncrouch\r\n\t\tif ( !WishCrouch )\r\n\t\t{\r\n\t\t\tif ( !CanUncrouch() ) return;\r\n\r\n\t\t\tCharacterController.Height = 64;\r\n\t\t\tCrouching = WishCrouch;\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\r\n\t}\r\n\r\n\tprivate void UpdateCamera()\r\n\t{\r\n\t\tvar camera = Scene.GetAllComponents\u003CCameraComponent\u003E().Where( x =\u003E x.IsMainCamera ).FirstOrDefault();\r\n\t\tif ( camera is null ) return;\r\n\r\n\t\tvar targetEyeHeight = Crouching ? 28 : 64;\r\n\t\tEyeHeight = EyeHeight.LerpTo( targetEyeHeight, RealTime.Delta * 10.0f );\r\n\r\n\t\tvar targetCameraPos = Transform.Position \u002B new Vector3( 0, 0, EyeHeight );\r\n\r\n\t\t// smooth view z, so when going up and down stairs or ducking, it\u0027s smooth af\r\n\t\tif ( lastUngrounded \u003E 0.2f )\r\n\t\t{\r\n\t\t\ttargetCameraPos.z = camera.Transform.Position.z.LerpTo( targetCameraPos.z, RealTime.Delta * 25.0f );\r\n\t\t}\r\n\r\n\t\tcamera.Transform.Position = targetCameraPos;\r\n\t\tcamera.Transform.Rotation = EyeAngles;\r\n\t\tcamera.FieldOfView = Preferences.FieldOfView;\r\n\t}\r\n\r\n\tprotected override void OnPreRender()\r\n\t{\r\n\t\tUpdateBodyVisibility();\r\n\r\n\t\tif ( IsProxy )\r\n\t\t\treturn;\r\n\r\n\t\tUpdateCamera();\r\n\t}\r\n\r\n\tprivate void UpdateAnimation()\r\n\t{\r\n\t\tif ( AnimationHelper is null || CharacterController is null ) return;\r\n\r\n\r\n\t\tvar wv = WishVelocity.Length;\r\n\r\n\t\tAnimationHelper.WithWishVelocity( WishVelocity );\r\n\t\tAnimationHelper.WithVelocity( CharacterController.Velocity );\r\n\t\tAnimationHelper.IsGrounded = CharacterController.IsOnGround;\r\n\t\tAnimationHelper.DuckLevel = Crouching ? 1.0f : 0.0f;\r\n\r\n\t\tAnimationHelper.MoveStyle = wv \u003C 160f ? CitizenAnimationHelper.MoveStyles.Walk : CitizenAnimationHelper.MoveStyles.Run;\r\n\r\n\t\tvar lookDir = EyeAngles.ToRotation().Forward * 1024;\r\n\t\tAnimationHelper.WithLook( lookDir, 1, 0.5f, 0.25f );\r\n\t}\r\n\r\n\tprivate void UpdateBodyVisibility()\r\n\t{\r\n\t\tif ( AnimationHelper is null )\r\n\t\t\treturn;\r\n\r\n\t\tvar renderMode = ModelRenderer.ShadowRenderType.On;\r\n\t\tif ( !IsProxy ) renderMode = ModelRenderer.ShadowRenderType.ShadowsOnly;\r\n\r\n\t\tAnimationHelper.Target.RenderType = renderMode;\r\n\r\n\t\tforeach ( var clothing in AnimationHelper.Target.Components.GetAll\u003CModelRenderer\u003E( FindMode.InChildren ) )\r\n\t\t{\r\n\t\t\tif ( !clothing.Tags.Has( \u0022clothing\u0022 ) )\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\tclothing.RenderType = renderMode;\r\n\t\t}\r\n\t}\r\n\r\n}\r\n"},{"Ident":"nolankicks.sceneloadingutility","Path":"JiggleBone.cs","FileName":"JiggleBone.cs","PackageType":"library","CodeKind":"Game","AssetVersionId":65380,"Code":"public sealed class JiggleBone : TransformProxyComponent\r\n{\r\n\tJiggleBoneState state = new JiggleBoneState();\r\n\r\n\t[Property]\r\n\tpublic Vector3 StartPoint = new Vector3( 0, 0, 0 );\r\n\r\n\t[Property]\r\n\tpublic Vector3 EndPoint = new Vector3( 32, 0, 0 );\r\n\r\n\t[Property, Range( 0, 2 )]\r\n\tpublic float Speed { get; set; } = 1.0f;\r\n\r\n\t[Property, Range( 0, 2 )]\r\n\tpublic float Stiffness { get; set; } = 1.0f;\r\n\r\n\t[Property, Range( 0, 2 )]\r\n\tpublic float Damping { get; set; } = 1.0f;\r\n\r\n\t[Property, Range( 0, 100 )]\r\n\tpublic float Radius { get; set; } = 40.0f;\r\n\r\n\t[Property, Range( 0, 100 )]\r\n\tpublic float Mass { get; set; } = 1.0f;\r\n\r\n\tTransform LocalJigglePosition;\r\n\r\n\tprotected override void OnEnabled()\r\n\t{\r\n\t\tLocalJigglePosition = Transform.Local;\r\n\r\n\t\tbase.OnEnabled();\r\n\r\n\t\tstate = new JiggleBoneState();\r\n\t}\r\n\r\n\tprotected override void OnUpdate()\r\n\t{\r\n\t\tvar oldPos = LocalJigglePosition;\r\n\r\n\r\n\r\n\t\tusing ( Transform.DisableProxy() )\r\n\t\t{\r\n\t\t\tvar worldTx = Transform.World;\r\n\r\n\t\t\tvar startPoint = worldTx.PointToWorld( StartPoint );\r\n\t\t\tvar endPoint = worldTx.PointToWorld( EndPoint );\r\n\r\n\t\t\t//Gizmo.Draw.LineSphere( startPoint, 1 );\r\n\t\t\t//Gizmo.Draw.LineSphere( endPoint, 1 );\r\n\r\n\t\t\tstate.Extent = (endPoint - startPoint);\r\n\t\t\tstate.Stiffness = Stiffness;\r\n\t\t\tstate.Damping = Damping;\r\n\t\t\tstate.Radius = Radius;\r\n\t\t\tstate.Mass = Mass;\r\n\r\n\t\t\tstate.Update( startPoint, Time.Delta * Speed * 16.0f );\r\n\r\n\t\t\tvar tx = worldTx.RotateAround( startPoint, state.Rotation );\r\n\t\t\tLocalJigglePosition = GameObject.Parent.Transform.World.ToLocal( tx );\r\n\t\t}\r\n\r\n\t\tif ( oldPos != LocalJigglePosition )\r\n\t\t{\r\n\t\t\tMarkTransformChanged();\r\n\t\t}\r\n\t}\r\n\r\n\tprotected override void DrawGizmos()\r\n\t{\r\n\t\tbase.DrawGizmos();\r\n\r\n\t\tif ( !Gizmo.IsSelected )\r\n\t\t\treturn;\r\n\r\n\t\tusing ( Transform.DisableProxy() )\r\n\t\t{\r\n\t\t\tGizmo.Transform = Transform.World;\r\n\t\t\tGizmo.Draw.IgnoreDepth = false;\r\n\t\t\tGizmo.Draw.Color = Gizmo.Colors.Yaw.WithAlpha( 0.5f );\r\n\t\t\tGizmo.Draw.Line( StartPoint, EndPoint );\r\n\t\t\tGizmo.Draw.LineBBox( BBox.FromPositionAndSize( StartPoint, 5 ) );\r\n\t\t\tGizmo.Draw.LineBBox( BBox.FromPositionAndSize( EndPoint, 5 ) );\r\n\t\t\tGizmo.Draw.LineSphere( EndPoint, Radius * 2.0f, 4 );\r\n\t\t}\r\n\t}\r\n\r\n\tpublic override Transform GetLocalTransform()\r\n\t{\r\n\t\treturn LocalJigglePosition;\r\n\t}\r\n}\r\n\r\nclass JiggleBoneState\r\n{\r\n\tpublic Vector3 Extent = new Vector3( 32, 0, 0 );\r\n\r\n\tpublic Vector3 Position { get; set; }\r\n\tpublic Rotation Rotation { get; set; }\r\n\tpublic float Stiffness { get; set; } = 1.0f;\r\n\tpublic float Damping { get; set; } = 1.0f;\r\n\tpublic float Radius { get; set; } = 10.0f;\r\n\tpublic float Gravity { get; set; } = 1.0f;\r\n\tpublic float Mass { get; set; } = 1.0f;\r\n\r\n\r\n\tVector3 basePosition;\r\n\tVector3 velocity;\r\n\r\n\tpublic JiggleBoneState()\r\n\t{\r\n\r\n\t}\r\n\r\n\tinternal void Update( Vector3 position, float timeDelta )\r\n\t{\r\n\t\tbasePosition = position \u002B Extent;\r\n\r\n\t\t// initialization\r\n\t\tif ( Position == default )\r\n\t\t{\r\n\t\t\tPosition = basePosition;\r\n\t\t}\r\n\r\n\t\t// Calculate spring force based on displacement from the cube\r\n\t\tVector3 displacement = Position - basePosition;\r\n\t\tVector3 springForce = -Stiffness * displacement;\r\n\r\n\t\t// Calculate acceleration (Newton\u0027s second law)\r\n\t\tVector3 acceleration = springForce / Mass;\r\n\r\n\t\t// Update velocity (integrate acceleration)\r\n\t\tvelocity \u002B= acceleration * timeDelta;\r\n\r\n\t\t// Apply exponential damping\r\n\t\tvelocity *= (float)Math.Exp( -Damping * timeDelta );\r\n\r\n\t\t// Update position (integrate velocity)\r\n\t\tPosition \u002B= velocity * timeDelta;\r\n\r\n\t\t{\r\n\t\t\tvar diff = Position - basePosition;\r\n\t\t\tvar diffLen = diff.Length;\r\n\t\t\tif ( diffLen \u003E Radius )\r\n\t\t\t{\r\n\t\t\t\tPosition = basePosition \u002B diff.Normal * Radius;\r\n\t\t\t\t//velocity = velocity.AddClamped( -diff * 2.0f, diff.Length );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Store the rotation offset result\r\n\t\tRotation = Rotation.FromToRotation( basePosition - position, Position - position );\r\n\r\n\t\t//Gizmo.Draw.IgnoreDepth = true;\r\n\t\t//Gizmo.Draw.Line( position, Position );\r\n\t\t//Gizmo.Draw.Line( basePosition, Position );\r\n\t}\r\n}\r\n"},{"Ident":"nolankicks.sceneloadingutility","Path":"BlankPostProcess.cs","FileName":"BlankPostProcess.cs","PackageType":"library","CodeKind":"Game","AssetVersionId":65380,"Code":"using System;\r\nusing Sandbox;\r\n\r\n\r\n//Only uses to get the scene camera\r\npublic sealed class BlankPostProcess : PostProcess\r\n{\r\n\tIDisposable renderHook;\r\n\tpublic SceneCamera sceneCam { get; set; }\r\n\r\n\tprotected override void OnEnabled()\r\n\t{\r\n\t\trenderHook = Camera.AddHookBeforeOverlay( \u0022My Post Processing\u0022, 1000, RenderEffect );\r\n\t}\r\n\r\n\tprotected override void OnDisabled()\r\n\t{\r\n\t\trenderHook?.Dispose();\r\n\t\trenderHook = null;\r\n\t}\r\n\r\n\tRenderAttributes attributes = new RenderAttributes();\r\n\r\n\tpublic void RenderEffect( SceneCamera camera )\r\n\t{\r\n\t\tif ( !camera.EnablePostProcessing )\r\n\t\t\treturn;\r\n\t\tsceneCam = camera;\r\n\t}\r\n}\r\n"},{"Ident":"nolankicks.sceneloadingutility","Path":".obj/__compiler_extra.cs","FileName":"__compiler_extra.cs","PackageType":"library","CodeKind":"Game","AssetVersionId":65380,"Code":"global using static Sandbox.Internal.GlobalGameNamespace;\r\n[assembly: global::System.Reflection.AssemblyMetadata( \u0022AddonTitle\u0022, \u0022Scene Loading Utility\u0022 )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \u0022AddonIdent\u0022, \u0022sceneloadingutility\u0022 )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \u0022OrgIdent\u0022, \u0022nolankicks\u0022 )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \u0022Ident\u0022, \u0022nolankicks.sceneloadingutility\u0022 )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \u0022CompileTime\u0022, \u00228/10/2024 7:55:20 PM\u0022 )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \u0022EngineVersion\u0022, \u002217\u0022 )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \u0022EngineMinorVersion\u0022, \u00221\u0022 )]\r\n\r\n[assembly: System.Runtime.Versioning.TargetFramework( \u0022.NETCoreApp,Version=v7.0\u0022, FrameworkDisplayName = \u0022.NET 7.0\u0022 )]\r\n[assembly: global::System.Reflection.AssemblyVersion(\u00220.0.120.0\u0022)]\r\n[assembly: global::System.Reflection.AssemblyFileVersion(\u00220.0.120.0\u0022)]"}]}