diff --git a/NAK_CVR_Mods.sln b/NAK_CVR_Mods.sln index 55d8b13..01ced9a 100644 --- a/NAK_CVR_Mods.sln +++ b/NAK_CVR_Mods.sln @@ -1,253 +1,253 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.2.32630.192 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CVRGizmos", "CVRGizmos\CVRGizmos.csproj", "{CF9BC79E-4FB6-429A-8C19-DF31F040BD4A}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FuckToes", "FuckToes\FuckToes.csproj", "{79B2A7C4-348D-4A8E-94D1-BA22FDD5FEED}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GestureLock", "GestureLock\GestureLock.csproj", "{45A65AEB-4BFC-4E47-B181-BBB43BD81283}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PathCamDisabler", "PathCamDisabler\PathCamDisabler.csproj", "{98169FD2-5CEB-46D1-A320-D7E06F82C9E0}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PortableCameraAdditions", "PortableCameraAdditions\PortableCameraAdditions.csproj", "{C4DAFE9D-C79B-4417-9B7D-B7327999DA4C}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PropUndoButton", "PropUndoButton\PropUndoButton.csproj", "{FBFDB717-F81E-4C06-ACF9-A0F3FFDCDE00}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThirdPerson", "ThirdPerson\ThirdPerson.csproj", "{675CEC0E-3E8A-4970-98EA-9B79277A7252}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FOVAdjustment", "FOVAdjustment\FOVAdjustment.csproj", "{EE552804-30B1-49CF-BBDE-3B312895AFF7}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MuteSFX", "MuteSFX\MuteSFX.csproj", "{77D222FC-4AEC-4672-A87A-B860B4C39E17}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChatBoxExtensions", "ChatBoxExtensions\ChatBoxExtensions.csproj", "{0E1DD746-33A1-4179-AE70-8FB83AC40ABC}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PhysicsGunMod", "PhysicsGunMod\PhysicsGunMod.csproj", "{F94DDB73-9041-4F5C-AD43-6960701E8417}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nevermind", "Nevermind\Nevermind.csproj", "{AC4857DD-F6D9-436D-A3EE-D148A518E642}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShadowCloneFallback", "ShadowCloneFallback\ShadowCloneFallback.csproj", "{69AF3C10-1BB1-4746-B697-B5A81D78C8D9}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StopClosingMyMenuOnWorldLoad", "StopClosingMyMenuOnWorldLoad\StopClosingMyMenuOnWorldLoad.csproj", "{9FA83514-13F8-412C-9790-C2B750E0E7E7}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RelativeSync", "RelativeSync\RelativeSync.csproj", "{B48C8F19-9451-4EE2-999F-82C0033CDE2C}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ScriptingSpoofer", "ScriptingSpoofer\ScriptingSpoofer.csproj", "{6B4396C7-B451-4FFD-87B6-3ED8377AC308}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LuaTTS", "LuaTTS\LuaTTS.csproj", "{24A069F4-4D69-4ABD-AA16-77765469245B}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LazyPrune", "LazyPrune\LazyPrune.csproj", "{8FA6D481-5801-4E4C-822E-DE561155D22B}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReconnectionSystemFix", "ReconnectionSystemFix\ReconnectionSystemFix.csproj", "{05C427DD-1261-4AAD-B316-A551FC126F2C}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AASDefaultProfileFix", "AASDefaultProfileFix\AASDefaultProfileFix.csproj", "{C6794B18-E785-4F91-A517-3A2A8006E008}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OriginShift", "OriginShift\OriginShift.csproj", "{F381F604-9C16-4870-AD49-4BD7CA3F36DC}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ScrollFlight", "ScrollFlight\ScrollFlight.csproj", "{1B5D7DCB-01A4-4988-8B25-211948AEED76}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Portals", "Portals\Portals.csproj", "{BE9629C2-8461-481C-B267-1B8A1805DCD7}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PropLoadingHexagon", "PropLoadingHexagon\PropLoadingHexagon.csproj", "{642A2BC7-C027-4F8F-969C-EF0F867936FD}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IKSimulatedRootAngleFix", "IKSimulatedRootAngleFix\IKSimulatedRootAngleFix.csproj", "{D11214B0-94FE-4008-8D1B-3DC8614466B3}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DropPropTweak", "DropPropTweak\DropPropTweak.csproj", "{2CC1F7C6-A953-4008-8C10-C7592EB401E8}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VisualCloneFix", "VisualCloneFix\VisualCloneFix.csproj", "{39915C4C-B555-4CB9-890F-26DE1388BC2E}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InteractionTest", "InteractionTest\InteractionTest.csproj", "{7C675E64-0A2D-4B34-B6D1-5D6AA369A520}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeepVelocityOnExitFlight", "KeepVelocityOnExitFlight\KeepVelocityOnExitFlight.csproj", "{0BB3D187-BBBA-4C58-B246-102342BE5E8C}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ASTExtension", "ASTExtension\ASTExtension.csproj", "{6580AA87-6A95-438E-A5D3-70E583CCD77B}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AvatarQueueSystemTweaks", "AvatarQueueSystemTweaks\AvatarQueueSystemTweaks.csproj", "{D178E422-283B-4FB3-89A6-AA4FB9F87E2F}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CustomSpawnPoint", "CustomSpawnPoint\CustomSpawnPoint.csproj", "{51CA34CA-7684-4819-AC9E-89DFAD63E9AB}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CVRLuaToolsExtension", "CVRLuaToolsExtension\CVRLuaToolsExtension.csproj", "{FE6BA6EC-2C11-49E1-A2FB-13F2A1C9E7F9}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stickers", "Stickers\Stickers.csproj", "{E5F54B3E-A676-4DD5-A6DB-73AFA54BEC5E}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SmartReticle", "SmartReticle\SmartReticle.csproj", "{3C992D0C-9729-438E-800C-496B7EFFFB25}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WhereAmIPointing", "WhereAmIPointing\WhereAmIPointing.csproj", "{E285BCC9-D953-4066-8FA2-97EA28EB348E}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AvatarScaleMod", "AvatarScaleMod\AvatarScaleMod.csproj", "{A38E687F-8B6B-499E-ABC9-BD95C53DD391}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SmootherRay", "SmootherRay\SmootherRay.csproj", "{99F9D60D-9A2D-4DBE-AA52-13D8A0838696}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LuaNetworkVariables", "LuaNetworkVariables\LuaNetworkVariables.csproj", "{A3D97D1A-3099-49C5-85AD-D8C79CC5FDE3}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {CF9BC79E-4FB6-429A-8C19-DF31F040BD4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CF9BC79E-4FB6-429A-8C19-DF31F040BD4A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CF9BC79E-4FB6-429A-8C19-DF31F040BD4A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CF9BC79E-4FB6-429A-8C19-DF31F040BD4A}.Release|Any CPU.Build.0 = Release|Any CPU - {79B2A7C4-348D-4A8E-94D1-BA22FDD5FEED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {79B2A7C4-348D-4A8E-94D1-BA22FDD5FEED}.Debug|Any CPU.Build.0 = Debug|Any CPU - {79B2A7C4-348D-4A8E-94D1-BA22FDD5FEED}.Release|Any CPU.ActiveCfg = Release|Any CPU - {79B2A7C4-348D-4A8E-94D1-BA22FDD5FEED}.Release|Any CPU.Build.0 = Release|Any CPU - {45A65AEB-4BFC-4E47-B181-BBB43BD81283}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {45A65AEB-4BFC-4E47-B181-BBB43BD81283}.Debug|Any CPU.Build.0 = Debug|Any CPU - {45A65AEB-4BFC-4E47-B181-BBB43BD81283}.Release|Any CPU.ActiveCfg = Release|Any CPU - {45A65AEB-4BFC-4E47-B181-BBB43BD81283}.Release|Any CPU.Build.0 = Release|Any CPU - {98169FD2-5CEB-46D1-A320-D7E06F82C9E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {98169FD2-5CEB-46D1-A320-D7E06F82C9E0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {98169FD2-5CEB-46D1-A320-D7E06F82C9E0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {98169FD2-5CEB-46D1-A320-D7E06F82C9E0}.Release|Any CPU.Build.0 = Release|Any CPU - {C4DAFE9D-C79B-4417-9B7D-B7327999DA4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C4DAFE9D-C79B-4417-9B7D-B7327999DA4C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C4DAFE9D-C79B-4417-9B7D-B7327999DA4C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C4DAFE9D-C79B-4417-9B7D-B7327999DA4C}.Release|Any CPU.Build.0 = Release|Any CPU - {FBFDB717-F81E-4C06-ACF9-A0F3FFDCDE00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FBFDB717-F81E-4C06-ACF9-A0F3FFDCDE00}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FBFDB717-F81E-4C06-ACF9-A0F3FFDCDE00}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FBFDB717-F81E-4C06-ACF9-A0F3FFDCDE00}.Release|Any CPU.Build.0 = Release|Any CPU - {675CEC0E-3E8A-4970-98EA-9B79277A7252}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {675CEC0E-3E8A-4970-98EA-9B79277A7252}.Debug|Any CPU.Build.0 = Debug|Any CPU - {675CEC0E-3E8A-4970-98EA-9B79277A7252}.Release|Any CPU.ActiveCfg = Release|Any CPU - {675CEC0E-3E8A-4970-98EA-9B79277A7252}.Release|Any CPU.Build.0 = Release|Any CPU - {EE552804-30B1-49CF-BBDE-3B312895AFF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EE552804-30B1-49CF-BBDE-3B312895AFF7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EE552804-30B1-49CF-BBDE-3B312895AFF7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EE552804-30B1-49CF-BBDE-3B312895AFF7}.Release|Any CPU.Build.0 = Release|Any CPU - {77D222FC-4AEC-4672-A87A-B860B4C39E17}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {77D222FC-4AEC-4672-A87A-B860B4C39E17}.Debug|Any CPU.Build.0 = Debug|Any CPU - {77D222FC-4AEC-4672-A87A-B860B4C39E17}.Release|Any CPU.ActiveCfg = Release|Any CPU - {77D222FC-4AEC-4672-A87A-B860B4C39E17}.Release|Any CPU.Build.0 = Release|Any CPU - {0E1DD746-33A1-4179-AE70-8FB83AC40ABC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0E1DD746-33A1-4179-AE70-8FB83AC40ABC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0E1DD746-33A1-4179-AE70-8FB83AC40ABC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0E1DD746-33A1-4179-AE70-8FB83AC40ABC}.Release|Any CPU.Build.0 = Release|Any CPU - {F94DDB73-9041-4F5C-AD43-6960701E8417}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F94DDB73-9041-4F5C-AD43-6960701E8417}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F94DDB73-9041-4F5C-AD43-6960701E8417}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F94DDB73-9041-4F5C-AD43-6960701E8417}.Release|Any CPU.Build.0 = Release|Any CPU - {AC4857DD-F6D9-436D-A3EE-D148A518E642}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AC4857DD-F6D9-436D-A3EE-D148A518E642}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AC4857DD-F6D9-436D-A3EE-D148A518E642}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AC4857DD-F6D9-436D-A3EE-D148A518E642}.Release|Any CPU.Build.0 = Release|Any CPU - {69AF3C10-1BB1-4746-B697-B5A81D78C8D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {69AF3C10-1BB1-4746-B697-B5A81D78C8D9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {69AF3C10-1BB1-4746-B697-B5A81D78C8D9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {69AF3C10-1BB1-4746-B697-B5A81D78C8D9}.Release|Any CPU.Build.0 = Release|Any CPU - {9FA83514-13F8-412C-9790-C2B750E0E7E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9FA83514-13F8-412C-9790-C2B750E0E7E7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9FA83514-13F8-412C-9790-C2B750E0E7E7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9FA83514-13F8-412C-9790-C2B750E0E7E7}.Release|Any CPU.Build.0 = Release|Any CPU - {B48C8F19-9451-4EE2-999F-82C0033CDE2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B48C8F19-9451-4EE2-999F-82C0033CDE2C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B48C8F19-9451-4EE2-999F-82C0033CDE2C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B48C8F19-9451-4EE2-999F-82C0033CDE2C}.Release|Any CPU.Build.0 = Release|Any CPU - {6B4396C7-B451-4FFD-87B6-3ED8377AC308}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6B4396C7-B451-4FFD-87B6-3ED8377AC308}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6B4396C7-B451-4FFD-87B6-3ED8377AC308}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6B4396C7-B451-4FFD-87B6-3ED8377AC308}.Release|Any CPU.Build.0 = Release|Any CPU - {24A069F4-4D69-4ABD-AA16-77765469245B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {24A069F4-4D69-4ABD-AA16-77765469245B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {24A069F4-4D69-4ABD-AA16-77765469245B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {24A069F4-4D69-4ABD-AA16-77765469245B}.Release|Any CPU.Build.0 = Release|Any CPU - {8FA6D481-5801-4E4C-822E-DE561155D22B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8FA6D481-5801-4E4C-822E-DE561155D22B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8FA6D481-5801-4E4C-822E-DE561155D22B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8FA6D481-5801-4E4C-822E-DE561155D22B}.Release|Any CPU.Build.0 = Release|Any CPU - {05C427DD-1261-4AAD-B316-A551FC126F2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {05C427DD-1261-4AAD-B316-A551FC126F2C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {05C427DD-1261-4AAD-B316-A551FC126F2C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {05C427DD-1261-4AAD-B316-A551FC126F2C}.Release|Any CPU.Build.0 = Release|Any CPU - {C6794B18-E785-4F91-A517-3A2A8006E008}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C6794B18-E785-4F91-A517-3A2A8006E008}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C6794B18-E785-4F91-A517-3A2A8006E008}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C6794B18-E785-4F91-A517-3A2A8006E008}.Release|Any CPU.Build.0 = Release|Any CPU - {F381F604-9C16-4870-AD49-4BD7CA3F36DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F381F604-9C16-4870-AD49-4BD7CA3F36DC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F381F604-9C16-4870-AD49-4BD7CA3F36DC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F381F604-9C16-4870-AD49-4BD7CA3F36DC}.Release|Any CPU.Build.0 = Release|Any CPU - {1B5D7DCB-01A4-4988-8B25-211948AEED76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1B5D7DCB-01A4-4988-8B25-211948AEED76}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1B5D7DCB-01A4-4988-8B25-211948AEED76}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1B5D7DCB-01A4-4988-8B25-211948AEED76}.Release|Any CPU.Build.0 = Release|Any CPU - {BE9629C2-8461-481C-B267-1B8A1805DCD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BE9629C2-8461-481C-B267-1B8A1805DCD7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BE9629C2-8461-481C-B267-1B8A1805DCD7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BE9629C2-8461-481C-B267-1B8A1805DCD7}.Release|Any CPU.Build.0 = Release|Any CPU - {642A2BC7-C027-4F8F-969C-EF0F867936FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {642A2BC7-C027-4F8F-969C-EF0F867936FD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {642A2BC7-C027-4F8F-969C-EF0F867936FD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {642A2BC7-C027-4F8F-969C-EF0F867936FD}.Release|Any CPU.Build.0 = Release|Any CPU - {D11214B0-94FE-4008-8D1B-3DC8614466B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D11214B0-94FE-4008-8D1B-3DC8614466B3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D11214B0-94FE-4008-8D1B-3DC8614466B3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D11214B0-94FE-4008-8D1B-3DC8614466B3}.Release|Any CPU.Build.0 = Release|Any CPU - {2CC1F7C6-A953-4008-8C10-C7592EB401E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2CC1F7C6-A953-4008-8C10-C7592EB401E8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2CC1F7C6-A953-4008-8C10-C7592EB401E8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2CC1F7C6-A953-4008-8C10-C7592EB401E8}.Release|Any CPU.Build.0 = Release|Any CPU - {39915C4C-B555-4CB9-890F-26DE1388BC2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {39915C4C-B555-4CB9-890F-26DE1388BC2E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {39915C4C-B555-4CB9-890F-26DE1388BC2E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {39915C4C-B555-4CB9-890F-26DE1388BC2E}.Release|Any CPU.Build.0 = Release|Any CPU - {7C675E64-0A2D-4B34-B6D1-5D6AA369A520}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7C675E64-0A2D-4B34-B6D1-5D6AA369A520}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7C675E64-0A2D-4B34-B6D1-5D6AA369A520}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7C675E64-0A2D-4B34-B6D1-5D6AA369A520}.Release|Any CPU.Build.0 = Release|Any CPU - {0BB3D187-BBBA-4C58-B246-102342BE5E8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0BB3D187-BBBA-4C58-B246-102342BE5E8C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0BB3D187-BBBA-4C58-B246-102342BE5E8C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0BB3D187-BBBA-4C58-B246-102342BE5E8C}.Release|Any CPU.Build.0 = Release|Any CPU - {6580AA87-6A95-438E-A5D3-70E583CCD77B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6580AA87-6A95-438E-A5D3-70E583CCD77B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6580AA87-6A95-438E-A5D3-70E583CCD77B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6580AA87-6A95-438E-A5D3-70E583CCD77B}.Release|Any CPU.Build.0 = Release|Any CPU - {D178E422-283B-4FB3-89A6-AA4FB9F87E2F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D178E422-283B-4FB3-89A6-AA4FB9F87E2F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D178E422-283B-4FB3-89A6-AA4FB9F87E2F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D178E422-283B-4FB3-89A6-AA4FB9F87E2F}.Release|Any CPU.Build.0 = Release|Any CPU - {51CA34CA-7684-4819-AC9E-89DFAD63E9AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {51CA34CA-7684-4819-AC9E-89DFAD63E9AB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {51CA34CA-7684-4819-AC9E-89DFAD63E9AB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {51CA34CA-7684-4819-AC9E-89DFAD63E9AB}.Release|Any CPU.Build.0 = Release|Any CPU - {FE6BA6EC-2C11-49E1-A2FB-13F2A1C9E7F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FE6BA6EC-2C11-49E1-A2FB-13F2A1C9E7F9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FE6BA6EC-2C11-49E1-A2FB-13F2A1C9E7F9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FE6BA6EC-2C11-49E1-A2FB-13F2A1C9E7F9}.Release|Any CPU.Build.0 = Release|Any CPU - {E5F54B3E-A676-4DD5-A6DB-73AFA54BEC5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E5F54B3E-A676-4DD5-A6DB-73AFA54BEC5E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E5F54B3E-A676-4DD5-A6DB-73AFA54BEC5E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E5F54B3E-A676-4DD5-A6DB-73AFA54BEC5E}.Release|Any CPU.Build.0 = Release|Any CPU - {3C992D0C-9729-438E-800C-496B7EFFFB25}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3C992D0C-9729-438E-800C-496B7EFFFB25}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3C992D0C-9729-438E-800C-496B7EFFFB25}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3C992D0C-9729-438E-800C-496B7EFFFB25}.Release|Any CPU.Build.0 = Release|Any CPU - {E285BCC9-D953-4066-8FA2-97EA28EB348E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E285BCC9-D953-4066-8FA2-97EA28EB348E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E285BCC9-D953-4066-8FA2-97EA28EB348E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E285BCC9-D953-4066-8FA2-97EA28EB348E}.Release|Any CPU.Build.0 = Release|Any CPU - {A38E687F-8B6B-499E-ABC9-BD95C53DD391}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A38E687F-8B6B-499E-ABC9-BD95C53DD391}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A38E687F-8B6B-499E-ABC9-BD95C53DD391}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A38E687F-8B6B-499E-ABC9-BD95C53DD391}.Release|Any CPU.Build.0 = Release|Any CPU - {99F9D60D-9A2D-4DBE-AA52-13D8A0838696}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {99F9D60D-9A2D-4DBE-AA52-13D8A0838696}.Debug|Any CPU.Build.0 = Debug|Any CPU - {99F9D60D-9A2D-4DBE-AA52-13D8A0838696}.Release|Any CPU.ActiveCfg = Release|Any CPU - {99F9D60D-9A2D-4DBE-AA52-13D8A0838696}.Release|Any CPU.Build.0 = Release|Any CPU - {A3D97D1A-3099-49C5-85AD-D8C79CC5FDE3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A3D97D1A-3099-49C5-85AD-D8C79CC5FDE3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A3D97D1A-3099-49C5-85AD-D8C79CC5FDE3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A3D97D1A-3099-49C5-85AD-D8C79CC5FDE3}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {CD7DECEC-F4A0-4EEF-978B-72748414D52A} - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.2.32630.192 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CVRGizmos", "CVRGizmos\CVRGizmos.csproj", "{CF9BC79E-4FB6-429A-8C19-DF31F040BD4A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FuckToes", "FuckToes\FuckToes.csproj", "{79B2A7C4-348D-4A8E-94D1-BA22FDD5FEED}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GestureLock", "GestureLock\GestureLock.csproj", "{45A65AEB-4BFC-4E47-B181-BBB43BD81283}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PathCamDisabler", "PathCamDisabler\PathCamDisabler.csproj", "{98169FD2-5CEB-46D1-A320-D7E06F82C9E0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PortableCameraAdditions", "PortableCameraAdditions\PortableCameraAdditions.csproj", "{C4DAFE9D-C79B-4417-9B7D-B7327999DA4C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PropUndoButton", "PropUndoButton\PropUndoButton.csproj", "{FBFDB717-F81E-4C06-ACF9-A0F3FFDCDE00}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThirdPerson", "ThirdPerson\ThirdPerson.csproj", "{675CEC0E-3E8A-4970-98EA-9B79277A7252}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FOVAdjustment", "FOVAdjustment\FOVAdjustment.csproj", "{EE552804-30B1-49CF-BBDE-3B312895AFF7}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MuteSFX", "MuteSFX\MuteSFX.csproj", "{77D222FC-4AEC-4672-A87A-B860B4C39E17}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChatBoxExtensions", "ChatBoxExtensions\ChatBoxExtensions.csproj", "{0E1DD746-33A1-4179-AE70-8FB83AC40ABC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PhysicsGunMod", "PhysicsGunMod\PhysicsGunMod.csproj", "{F94DDB73-9041-4F5C-AD43-6960701E8417}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nevermind", "Nevermind\Nevermind.csproj", "{AC4857DD-F6D9-436D-A3EE-D148A518E642}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShadowCloneFallback", "ShadowCloneFallback\ShadowCloneFallback.csproj", "{69AF3C10-1BB1-4746-B697-B5A81D78C8D9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StopClosingMyMenuOnWorldLoad", "StopClosingMyMenuOnWorldLoad\StopClosingMyMenuOnWorldLoad.csproj", "{9FA83514-13F8-412C-9790-C2B750E0E7E7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RelativeSync", "RelativeSync\RelativeSync.csproj", "{B48C8F19-9451-4EE2-999F-82C0033CDE2C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ScriptingSpoofer", "ScriptingSpoofer\ScriptingSpoofer.csproj", "{6B4396C7-B451-4FFD-87B6-3ED8377AC308}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LuaTTS", "LuaTTS\LuaTTS.csproj", "{24A069F4-4D69-4ABD-AA16-77765469245B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LazyPrune", "LazyPrune\LazyPrune.csproj", "{8FA6D481-5801-4E4C-822E-DE561155D22B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReconnectionSystemFix", "ReconnectionSystemFix\ReconnectionSystemFix.csproj", "{05C427DD-1261-4AAD-B316-A551FC126F2C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AASDefaultProfileFix", "AASDefaultProfileFix\AASDefaultProfileFix.csproj", "{C6794B18-E785-4F91-A517-3A2A8006E008}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OriginShift", "OriginShift\OriginShift.csproj", "{F381F604-9C16-4870-AD49-4BD7CA3F36DC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ScrollFlight", "ScrollFlight\ScrollFlight.csproj", "{1B5D7DCB-01A4-4988-8B25-211948AEED76}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Portals", "Portals\Portals.csproj", "{BE9629C2-8461-481C-B267-1B8A1805DCD7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PropLoadingHexagon", "PropLoadingHexagon\PropLoadingHexagon.csproj", "{642A2BC7-C027-4F8F-969C-EF0F867936FD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IKSimulatedRootAngleFix", "IKSimulatedRootAngleFix\IKSimulatedRootAngleFix.csproj", "{D11214B0-94FE-4008-8D1B-3DC8614466B3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DropPropTweak", "DropPropTweak\DropPropTweak.csproj", "{2CC1F7C6-A953-4008-8C10-C7592EB401E8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VisualCloneFix", "VisualCloneFix\VisualCloneFix.csproj", "{39915C4C-B555-4CB9-890F-26DE1388BC2E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InteractionTest", "InteractionTest\InteractionTest.csproj", "{7C675E64-0A2D-4B34-B6D1-5D6AA369A520}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeepVelocityOnExitFlight", "KeepVelocityOnExitFlight\KeepVelocityOnExitFlight.csproj", "{0BB3D187-BBBA-4C58-B246-102342BE5E8C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ASTExtension", "ASTExtension\ASTExtension.csproj", "{6580AA87-6A95-438E-A5D3-70E583CCD77B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AvatarQueueSystemTweaks", "AvatarQueueSystemTweaks\AvatarQueueSystemTweaks.csproj", "{D178E422-283B-4FB3-89A6-AA4FB9F87E2F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CustomSpawnPoint", "CustomSpawnPoint\CustomSpawnPoint.csproj", "{51CA34CA-7684-4819-AC9E-89DFAD63E9AB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CVRLuaToolsExtension", "CVRLuaToolsExtension\CVRLuaToolsExtension.csproj", "{FE6BA6EC-2C11-49E1-A2FB-13F2A1C9E7F9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stickers", "Stickers\Stickers.csproj", "{E5F54B3E-A676-4DD5-A6DB-73AFA54BEC5E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SmartReticle", "SmartReticle\SmartReticle.csproj", "{3C992D0C-9729-438E-800C-496B7EFFFB25}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WhereAmIPointing", "WhereAmIPointing\WhereAmIPointing.csproj", "{E285BCC9-D953-4066-8FA2-97EA28EB348E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AvatarScaleMod", "AvatarScaleMod\AvatarScaleMod.csproj", "{A38E687F-8B6B-499E-ABC9-BD95C53DD391}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SmootherRay", "SmootherRay\SmootherRay.csproj", "{99F9D60D-9A2D-4DBE-AA52-13D8A0838696}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LuaNetworkVariables", "LuaNetworkVariables\LuaNetworkVariables.csproj", "{A3D97D1A-3099-49C5-85AD-D8C79CC5FDE3}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CF9BC79E-4FB6-429A-8C19-DF31F040BD4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CF9BC79E-4FB6-429A-8C19-DF31F040BD4A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CF9BC79E-4FB6-429A-8C19-DF31F040BD4A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CF9BC79E-4FB6-429A-8C19-DF31F040BD4A}.Release|Any CPU.Build.0 = Release|Any CPU + {79B2A7C4-348D-4A8E-94D1-BA22FDD5FEED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {79B2A7C4-348D-4A8E-94D1-BA22FDD5FEED}.Debug|Any CPU.Build.0 = Debug|Any CPU + {79B2A7C4-348D-4A8E-94D1-BA22FDD5FEED}.Release|Any CPU.ActiveCfg = Release|Any CPU + {79B2A7C4-348D-4A8E-94D1-BA22FDD5FEED}.Release|Any CPU.Build.0 = Release|Any CPU + {45A65AEB-4BFC-4E47-B181-BBB43BD81283}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {45A65AEB-4BFC-4E47-B181-BBB43BD81283}.Debug|Any CPU.Build.0 = Debug|Any CPU + {45A65AEB-4BFC-4E47-B181-BBB43BD81283}.Release|Any CPU.ActiveCfg = Release|Any CPU + {45A65AEB-4BFC-4E47-B181-BBB43BD81283}.Release|Any CPU.Build.0 = Release|Any CPU + {98169FD2-5CEB-46D1-A320-D7E06F82C9E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {98169FD2-5CEB-46D1-A320-D7E06F82C9E0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {98169FD2-5CEB-46D1-A320-D7E06F82C9E0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {98169FD2-5CEB-46D1-A320-D7E06F82C9E0}.Release|Any CPU.Build.0 = Release|Any CPU + {C4DAFE9D-C79B-4417-9B7D-B7327999DA4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C4DAFE9D-C79B-4417-9B7D-B7327999DA4C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C4DAFE9D-C79B-4417-9B7D-B7327999DA4C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C4DAFE9D-C79B-4417-9B7D-B7327999DA4C}.Release|Any CPU.Build.0 = Release|Any CPU + {FBFDB717-F81E-4C06-ACF9-A0F3FFDCDE00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FBFDB717-F81E-4C06-ACF9-A0F3FFDCDE00}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FBFDB717-F81E-4C06-ACF9-A0F3FFDCDE00}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FBFDB717-F81E-4C06-ACF9-A0F3FFDCDE00}.Release|Any CPU.Build.0 = Release|Any CPU + {675CEC0E-3E8A-4970-98EA-9B79277A7252}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {675CEC0E-3E8A-4970-98EA-9B79277A7252}.Debug|Any CPU.Build.0 = Debug|Any CPU + {675CEC0E-3E8A-4970-98EA-9B79277A7252}.Release|Any CPU.ActiveCfg = Release|Any CPU + {675CEC0E-3E8A-4970-98EA-9B79277A7252}.Release|Any CPU.Build.0 = Release|Any CPU + {EE552804-30B1-49CF-BBDE-3B312895AFF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EE552804-30B1-49CF-BBDE-3B312895AFF7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EE552804-30B1-49CF-BBDE-3B312895AFF7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EE552804-30B1-49CF-BBDE-3B312895AFF7}.Release|Any CPU.Build.0 = Release|Any CPU + {77D222FC-4AEC-4672-A87A-B860B4C39E17}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {77D222FC-4AEC-4672-A87A-B860B4C39E17}.Debug|Any CPU.Build.0 = Debug|Any CPU + {77D222FC-4AEC-4672-A87A-B860B4C39E17}.Release|Any CPU.ActiveCfg = Release|Any CPU + {77D222FC-4AEC-4672-A87A-B860B4C39E17}.Release|Any CPU.Build.0 = Release|Any CPU + {0E1DD746-33A1-4179-AE70-8FB83AC40ABC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0E1DD746-33A1-4179-AE70-8FB83AC40ABC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0E1DD746-33A1-4179-AE70-8FB83AC40ABC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0E1DD746-33A1-4179-AE70-8FB83AC40ABC}.Release|Any CPU.Build.0 = Release|Any CPU + {F94DDB73-9041-4F5C-AD43-6960701E8417}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F94DDB73-9041-4F5C-AD43-6960701E8417}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F94DDB73-9041-4F5C-AD43-6960701E8417}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F94DDB73-9041-4F5C-AD43-6960701E8417}.Release|Any CPU.Build.0 = Release|Any CPU + {AC4857DD-F6D9-436D-A3EE-D148A518E642}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AC4857DD-F6D9-436D-A3EE-D148A518E642}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AC4857DD-F6D9-436D-A3EE-D148A518E642}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AC4857DD-F6D9-436D-A3EE-D148A518E642}.Release|Any CPU.Build.0 = Release|Any CPU + {69AF3C10-1BB1-4746-B697-B5A81D78C8D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {69AF3C10-1BB1-4746-B697-B5A81D78C8D9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {69AF3C10-1BB1-4746-B697-B5A81D78C8D9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {69AF3C10-1BB1-4746-B697-B5A81D78C8D9}.Release|Any CPU.Build.0 = Release|Any CPU + {9FA83514-13F8-412C-9790-C2B750E0E7E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9FA83514-13F8-412C-9790-C2B750E0E7E7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9FA83514-13F8-412C-9790-C2B750E0E7E7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9FA83514-13F8-412C-9790-C2B750E0E7E7}.Release|Any CPU.Build.0 = Release|Any CPU + {B48C8F19-9451-4EE2-999F-82C0033CDE2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B48C8F19-9451-4EE2-999F-82C0033CDE2C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B48C8F19-9451-4EE2-999F-82C0033CDE2C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B48C8F19-9451-4EE2-999F-82C0033CDE2C}.Release|Any CPU.Build.0 = Release|Any CPU + {6B4396C7-B451-4FFD-87B6-3ED8377AC308}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6B4396C7-B451-4FFD-87B6-3ED8377AC308}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6B4396C7-B451-4FFD-87B6-3ED8377AC308}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6B4396C7-B451-4FFD-87B6-3ED8377AC308}.Release|Any CPU.Build.0 = Release|Any CPU + {24A069F4-4D69-4ABD-AA16-77765469245B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {24A069F4-4D69-4ABD-AA16-77765469245B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {24A069F4-4D69-4ABD-AA16-77765469245B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {24A069F4-4D69-4ABD-AA16-77765469245B}.Release|Any CPU.Build.0 = Release|Any CPU + {8FA6D481-5801-4E4C-822E-DE561155D22B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8FA6D481-5801-4E4C-822E-DE561155D22B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8FA6D481-5801-4E4C-822E-DE561155D22B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8FA6D481-5801-4E4C-822E-DE561155D22B}.Release|Any CPU.Build.0 = Release|Any CPU + {05C427DD-1261-4AAD-B316-A551FC126F2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {05C427DD-1261-4AAD-B316-A551FC126F2C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {05C427DD-1261-4AAD-B316-A551FC126F2C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {05C427DD-1261-4AAD-B316-A551FC126F2C}.Release|Any CPU.Build.0 = Release|Any CPU + {C6794B18-E785-4F91-A517-3A2A8006E008}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C6794B18-E785-4F91-A517-3A2A8006E008}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C6794B18-E785-4F91-A517-3A2A8006E008}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C6794B18-E785-4F91-A517-3A2A8006E008}.Release|Any CPU.Build.0 = Release|Any CPU + {F381F604-9C16-4870-AD49-4BD7CA3F36DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F381F604-9C16-4870-AD49-4BD7CA3F36DC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F381F604-9C16-4870-AD49-4BD7CA3F36DC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F381F604-9C16-4870-AD49-4BD7CA3F36DC}.Release|Any CPU.Build.0 = Release|Any CPU + {1B5D7DCB-01A4-4988-8B25-211948AEED76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1B5D7DCB-01A4-4988-8B25-211948AEED76}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1B5D7DCB-01A4-4988-8B25-211948AEED76}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1B5D7DCB-01A4-4988-8B25-211948AEED76}.Release|Any CPU.Build.0 = Release|Any CPU + {BE9629C2-8461-481C-B267-1B8A1805DCD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BE9629C2-8461-481C-B267-1B8A1805DCD7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BE9629C2-8461-481C-B267-1B8A1805DCD7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BE9629C2-8461-481C-B267-1B8A1805DCD7}.Release|Any CPU.Build.0 = Release|Any CPU + {642A2BC7-C027-4F8F-969C-EF0F867936FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {642A2BC7-C027-4F8F-969C-EF0F867936FD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {642A2BC7-C027-4F8F-969C-EF0F867936FD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {642A2BC7-C027-4F8F-969C-EF0F867936FD}.Release|Any CPU.Build.0 = Release|Any CPU + {D11214B0-94FE-4008-8D1B-3DC8614466B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D11214B0-94FE-4008-8D1B-3DC8614466B3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D11214B0-94FE-4008-8D1B-3DC8614466B3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D11214B0-94FE-4008-8D1B-3DC8614466B3}.Release|Any CPU.Build.0 = Release|Any CPU + {2CC1F7C6-A953-4008-8C10-C7592EB401E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2CC1F7C6-A953-4008-8C10-C7592EB401E8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2CC1F7C6-A953-4008-8C10-C7592EB401E8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2CC1F7C6-A953-4008-8C10-C7592EB401E8}.Release|Any CPU.Build.0 = Release|Any CPU + {39915C4C-B555-4CB9-890F-26DE1388BC2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {39915C4C-B555-4CB9-890F-26DE1388BC2E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {39915C4C-B555-4CB9-890F-26DE1388BC2E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {39915C4C-B555-4CB9-890F-26DE1388BC2E}.Release|Any CPU.Build.0 = Release|Any CPU + {7C675E64-0A2D-4B34-B6D1-5D6AA369A520}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7C675E64-0A2D-4B34-B6D1-5D6AA369A520}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7C675E64-0A2D-4B34-B6D1-5D6AA369A520}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7C675E64-0A2D-4B34-B6D1-5D6AA369A520}.Release|Any CPU.Build.0 = Release|Any CPU + {0BB3D187-BBBA-4C58-B246-102342BE5E8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0BB3D187-BBBA-4C58-B246-102342BE5E8C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0BB3D187-BBBA-4C58-B246-102342BE5E8C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0BB3D187-BBBA-4C58-B246-102342BE5E8C}.Release|Any CPU.Build.0 = Release|Any CPU + {6580AA87-6A95-438E-A5D3-70E583CCD77B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6580AA87-6A95-438E-A5D3-70E583CCD77B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6580AA87-6A95-438E-A5D3-70E583CCD77B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6580AA87-6A95-438E-A5D3-70E583CCD77B}.Release|Any CPU.Build.0 = Release|Any CPU + {D178E422-283B-4FB3-89A6-AA4FB9F87E2F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D178E422-283B-4FB3-89A6-AA4FB9F87E2F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D178E422-283B-4FB3-89A6-AA4FB9F87E2F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D178E422-283B-4FB3-89A6-AA4FB9F87E2F}.Release|Any CPU.Build.0 = Release|Any CPU + {51CA34CA-7684-4819-AC9E-89DFAD63E9AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {51CA34CA-7684-4819-AC9E-89DFAD63E9AB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {51CA34CA-7684-4819-AC9E-89DFAD63E9AB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {51CA34CA-7684-4819-AC9E-89DFAD63E9AB}.Release|Any CPU.Build.0 = Release|Any CPU + {FE6BA6EC-2C11-49E1-A2FB-13F2A1C9E7F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FE6BA6EC-2C11-49E1-A2FB-13F2A1C9E7F9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FE6BA6EC-2C11-49E1-A2FB-13F2A1C9E7F9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FE6BA6EC-2C11-49E1-A2FB-13F2A1C9E7F9}.Release|Any CPU.Build.0 = Release|Any CPU + {E5F54B3E-A676-4DD5-A6DB-73AFA54BEC5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E5F54B3E-A676-4DD5-A6DB-73AFA54BEC5E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E5F54B3E-A676-4DD5-A6DB-73AFA54BEC5E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E5F54B3E-A676-4DD5-A6DB-73AFA54BEC5E}.Release|Any CPU.Build.0 = Release|Any CPU + {3C992D0C-9729-438E-800C-496B7EFFFB25}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3C992D0C-9729-438E-800C-496B7EFFFB25}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3C992D0C-9729-438E-800C-496B7EFFFB25}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3C992D0C-9729-438E-800C-496B7EFFFB25}.Release|Any CPU.Build.0 = Release|Any CPU + {E285BCC9-D953-4066-8FA2-97EA28EB348E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E285BCC9-D953-4066-8FA2-97EA28EB348E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E285BCC9-D953-4066-8FA2-97EA28EB348E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E285BCC9-D953-4066-8FA2-97EA28EB348E}.Release|Any CPU.Build.0 = Release|Any CPU + {A38E687F-8B6B-499E-ABC9-BD95C53DD391}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A38E687F-8B6B-499E-ABC9-BD95C53DD391}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A38E687F-8B6B-499E-ABC9-BD95C53DD391}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A38E687F-8B6B-499E-ABC9-BD95C53DD391}.Release|Any CPU.Build.0 = Release|Any CPU + {99F9D60D-9A2D-4DBE-AA52-13D8A0838696}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {99F9D60D-9A2D-4DBE-AA52-13D8A0838696}.Debug|Any CPU.Build.0 = Debug|Any CPU + {99F9D60D-9A2D-4DBE-AA52-13D8A0838696}.Release|Any CPU.ActiveCfg = Release|Any CPU + {99F9D60D-9A2D-4DBE-AA52-13D8A0838696}.Release|Any CPU.Build.0 = Release|Any CPU + {A3D97D1A-3099-49C5-85AD-D8C79CC5FDE3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A3D97D1A-3099-49C5-85AD-D8C79CC5FDE3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A3D97D1A-3099-49C5-85AD-D8C79CC5FDE3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A3D97D1A-3099-49C5-85AD-D8C79CC5FDE3}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {CD7DECEC-F4A0-4EEF-978B-72748414D52A} + EndGlobalSection +EndGlobal diff --git a/Stickers/Integrations/BTKUI/UIAddon.Category.StickersMod.cs b/Stickers/Integrations/BTKUI/UIAddon.Category.StickersMod.cs index 6660a52..0dfb059 100644 --- a/Stickers/Integrations/BTKUI/UIAddon.Category.StickersMod.cs +++ b/Stickers/Integrations/BTKUI/UIAddon.Category.StickersMod.cs @@ -1,89 +1,123 @@ -using BTKUILib; -using BTKUILib.UIObjects; -using BTKUILib.UIObjects.Components; -using BTKUILib.UIObjects.Objects; - -namespace NAK.Stickers.Integrations; - -public static partial class BTKUIAddon -{ - private static Category _ourCategory; - - private static readonly MultiSelection _sfxSelection = - MultiSelection.CreateMultiSelectionFromMelonPref(ModSettings.Entry_SelectedSFX); - - private static readonly MultiSelection _desktopKeybindSelection = - MultiSelection.CreateMultiSelectionFromMelonPref(ModSettings.Entry_PlaceBinding); - - private static readonly MultiSelection _tabDoubleClickSelection = - MultiSelection.CreateMultiSelectionFromMelonPref(ModSettings.Entry_TabDoubleClick); - - #region Category Setup - - private static void Setup_StickersModCategory() - { - _ourCategory = _rootPage.AddMelonCategory(ModSettings.Hidden_Foldout_SettingsCategory); - - Button placeStickersButton = _ourCategory.AddButton("Place Stickers", "Stickers-magic-wand", "Place stickers via raycast.", ButtonStyle.TextWithIcon); - placeStickersButton.OnPress += OnPlaceStickersButtonClick; - - Button clearSelfStickersButton = _ourCategory.AddButton("Clear Self", "Stickers-eraser", "Clear own stickers.", ButtonStyle.TextWithIcon); - clearSelfStickersButton.OnPress += OnClearSelfStickersButtonClick; - - Button clearAllStickersButton = _ourCategory.AddButton("Clear All", "Stickers-rubbish-bin", "Clear all stickers.", ButtonStyle.TextWithIcon); - clearAllStickersButton.OnPress += OnClearAllStickersButtonClick; - - Button openStickersFolderButton = _ourCategory.AddButton("Open Stickers Folder", "Stickers-folder", "Open UserData/Stickers folder in explorer. If above 256kb your image will automatically be downscaled for networking reasons.", ButtonStyle.TextWithIcon); - openStickersFolderButton.OnPress += OnOpenStickersFolderButtonClick; - - Button openStickerSFXButton = _ourCategory.AddButton("Sticker SFX", "Stickers-headset", "Choose the SFX used when a sticker is placed.", ButtonStyle.TextWithIcon); - openStickerSFXButton.OnPress += () => QuickMenuAPI.OpenMultiSelect(_sfxSelection); - - ToggleButton toggleDesktopKeybindButton = _ourCategory.AddToggle("Use Desktop Keybind", "Should the Desktop keybind be active.", ModSettings.Entry_UsePlaceBinding.Value); - Button openDesktopKeybindButton = _ourCategory.AddButton("Desktop Keybind", "Stickers-alphabet", "Choose the key binding to place stickers.", ButtonStyle.TextWithIcon); - openDesktopKeybindButton.OnPress += () => QuickMenuAPI.OpenMultiSelect(_desktopKeybindSelection); - toggleDesktopKeybindButton.OnValueUpdated += (b) => - { - ModSettings.Entry_UsePlaceBinding.Value = b; - openDesktopKeybindButton.Disabled = !b; - }; - - Button openTabDoubleClickButton = _ourCategory.AddButton("Tab Double Click", "Stickers-mouse", "Choose the action to perform when double clicking the Stickers tab.", ButtonStyle.TextWithIcon); - openTabDoubleClickButton.OnPress += () => QuickMenuAPI.OpenMultiSelect(_tabDoubleClickSelection); - } - - #endregion Category Setup - - #region Button Actions - - private static void OnPlaceStickersButtonClick() - { - if (!_isOurTabOpened) return; - string mode = StickerSystem.Instance.IsInStickerMode ? "Exiting" : "Entering"; - QuickMenuAPI.ShowAlertToast($"{mode} sticker placement mode...", 2); - StickerSystem.Instance.IsInStickerMode = !StickerSystem.Instance.IsInStickerMode; - } - - private static void OnClearSelfStickersButtonClick() - { - if (!_isOurTabOpened) return; - QuickMenuAPI.ShowAlertToast("Clearing own stickers in world...", 2); - StickerSystem.Instance.ClearStickersSelf(); - } - - private static void OnClearAllStickersButtonClick() - { - if (!_isOurTabOpened) return; - QuickMenuAPI.ShowAlertToast("Clearing all stickers in world...", 2); - StickerSystem.Instance.ClearAllStickers(); - } - - private static void OnOpenStickersFolderButtonClick() - { - if (!_isOurTabOpened) return; - QuickMenuAPI.ShowAlertToast("Opening Stickers folder in Explorer...", 2); - StickerSystem.OpenStickersFolder(); - } - - #endregion Button Actions +using BTKUILib; +using BTKUILib.UIObjects; +using BTKUILib.UIObjects.Components; +using BTKUILib.UIObjects.Objects; + +namespace NAK.Stickers.Integrations; + +public static partial class BTKUIAddon +{ + private static Category _ourCategory; + + private static readonly MultiSelection _sfxSelection = + MultiSelection.CreateMultiSelectionFromMelonPref(ModSettings.Entry_SelectedSFX); + + private static readonly MultiSelection _desktopKeybindSelection = + MultiSelection.CreateMultiSelectionFromMelonPref(ModSettings.Entry_PlaceBinding); + + private static readonly MultiSelection _tabDoubleClickSelection = + MultiSelection.CreateMultiSelectionFromMelonPref(ModSettings.Entry_TabDoubleClick); + + public static Button placeStickersButton; + + #region Category Setup + + private static void Setup_StickersModCategory() + { + _ourCategory = _rootPage.AddMelonCategory(ModSettings.Hidden_Foldout_SettingsCategory); + + placeStickersButton = _ourCategory.AddButton("Place Stickers", "Stickers-magic-wand", "Place stickers via raycast.", ButtonStyle.TextWithIcon); + placeStickersButton.OnPress += OnPlaceStickersButtonClick; + + Button clearSelfStickersButton = _ourCategory.AddButton("Clear Self", "Stickers-eraser", "Clear own stickers.", ButtonStyle.TextWithIcon); + clearSelfStickersButton.OnPress += OnClearSelfStickersButtonClick; + + Button clearAllStickersButton = _ourCategory.AddButton("Clear All", "Stickers-rubbish-bin", "Clear all stickers.", ButtonStyle.TextWithIcon); + clearAllStickersButton.OnPress += OnClearAllStickersButtonClick; + + Button openStickersFolderButton = _ourCategory.AddButton("Open Stickers Folder", "Stickers-folder", "Open UserData/Stickers folder in explorer. If above 256kb your image will automatically be downscaled for networking reasons.", ButtonStyle.TextWithIcon); + openStickersFolderButton.OnPress += OnOpenStickersFolderButtonClick; + + Button openStickerSFXButton = _ourCategory.AddButton("Sticker SFX", "Stickers-headset", "Choose the SFX used when a sticker is placed.", ButtonStyle.TextWithIcon); + openStickerSFXButton.OnPress += () => QuickMenuAPI.OpenMultiSelect(_sfxSelection); + + ToggleButton toggleDesktopKeybindButton = _ourCategory.AddToggle("Use Desktop Keybind", "Should the Desktop keybind be active.", ModSettings.Entry_UsePlaceBinding.Value); + Button openDesktopKeybindButton = _ourCategory.AddButton("Desktop Keybind", "Stickers-alphabet", "Choose the key binding to place stickers.", ButtonStyle.TextWithIcon); + openDesktopKeybindButton.OnPress += () => QuickMenuAPI.OpenMultiSelect(_desktopKeybindSelection); + toggleDesktopKeybindButton.OnValueUpdated += (b) => + { + ModSettings.Entry_UsePlaceBinding.Value = b; + openDesktopKeybindButton.Disabled = !b; + }; + + Button openTabDoubleClickButton = _ourCategory.AddButton("Tab Double Click", "Stickers-mouse", "Choose the action to perform when double clicking the Stickers tab.", ButtonStyle.TextWithIcon); + openTabDoubleClickButton.OnPress += () => QuickMenuAPI.OpenMultiSelect(_tabDoubleClickSelection); + } + + #endregion Category Setup + + #region Button Actions + + private static void OnPlaceStickersButtonClick() + { + if (!_isOurTabOpened) return; + + if (StickerSystem.RestrictedInstance == false) + { + string mode = StickerSystem.Instance.IsInStickerMode ? "Exiting" : "Entering"; + QuickMenuAPI.ShowAlertToast($"{mode} sticker placement mode...", 2); + StickerSystem.Instance.IsInStickerMode = !StickerSystem.Instance.IsInStickerMode; + } + else + { + QuickMenuAPI.ShowAlertToast("Stickers are not allowed in this world!", 2); + } + } + + private static void OnClearSelfStickersButtonClick() + { + if (!_isOurTabOpened) return; + QuickMenuAPI.ShowAlertToast("Clearing own stickers in world...", 2); + StickerSystem.Instance.ClearStickersSelf(); + } + + private static void OnClearAllStickersButtonClick() + { + if (!_isOurTabOpened) return; + QuickMenuAPI.ShowAlertToast("Clearing all stickers in world...", 2); + StickerSystem.Instance.ClearAllStickers(); + } + + private static void OnOpenStickersFolderButtonClick() + { + if (!_isOurTabOpened) return; + QuickMenuAPI.ShowAlertToast("Opening Stickers folder in Explorer...", 2); + StickerSystem.OpenStickersFolder(); + } + + public static void UpdateStickerMenu() //TODO: add Icon changing, Bono needs to expose the value first. + { + if (StickerSystem.RestrictedInstance == true) + { + _rootPage.MenuSubtitle = "Stickers... are sadly disabled in this world."; + + placeStickersButton.Disabled = true; + placeStickersButton.ButtonText = "Stickers Disabled"; + placeStickersButton.ButtonTooltip = "This world is not allowing Stickers."; + placeStickersButton.ButtonIcon = "Stickers-magic-wand-broken"; + + } + else + { + _rootPage.MenuSubtitle = "Stickers! Double-click the tab to quickly toggle Sticker Mode."; + + placeStickersButton.Disabled = false; + placeStickersButton.ButtonText = "Place Stickers"; + placeStickersButton.ButtonTooltip = "Place stickers via raycast."; + placeStickersButton.ButtonIcon = "Stickers-magic-wand"; + } + + } + + #endregion Button Actions } \ No newline at end of file diff --git a/Stickers/Integrations/BTKUI/UIAddon.Main.cs b/Stickers/Integrations/BTKUI/UIAddon.Main.cs index 30827a1..e741432 100644 --- a/Stickers/Integrations/BTKUI/UIAddon.Main.cs +++ b/Stickers/Integrations/BTKUI/UIAddon.Main.cs @@ -1,107 +1,114 @@ -using BTKUILib; -using BTKUILib.UIObjects; -using NAK.Stickers.Networking; -using NAK.Stickers.Utilities; - -namespace NAK.Stickers.Integrations; - -public static partial class BTKUIAddon -{ - private static Page _rootPage; - private static string _rootPageElementID; - - private static bool _isOurTabOpened; - - public static void Initialize() - { - Setup_Icons(); - Setup_StickerModTab(); - Setup_PlayerOptionsPage(); - } - - #region Setup - - private static void Setup_Icons() - { - // All icons used - https://www.flaticon.com/authors/gohsantosadrive - QuickMenuAPI.PrepareIcon(ModSettings.ModName, "Stickers-alphabet", UIUtils.GetIconStream("Gohsantosadrive_Icons.Stickers-alphabet.png")); - QuickMenuAPI.PrepareIcon(ModSettings.ModName, "Stickers-eraser", UIUtils.GetIconStream("Gohsantosadrive_Icons.Stickers-eraser.png")); - QuickMenuAPI.PrepareIcon(ModSettings.ModName, "Stickers-folder", UIUtils.GetIconStream("Gohsantosadrive_Icons.Stickers-folder.png")); - QuickMenuAPI.PrepareIcon(ModSettings.ModName, "Stickers-headset", UIUtils.GetIconStream("Gohsantosadrive_Icons.Stickers-headset.png")); - QuickMenuAPI.PrepareIcon(ModSettings.ModName, "Stickers-magnifying-glass", UIUtils.GetIconStream("Gohsantosadrive_Icons.Stickers-magnifying-glass.png")); - QuickMenuAPI.PrepareIcon(ModSettings.ModName, "Stickers-magic-wand", UIUtils.GetIconStream("Gohsantosadrive_Icons.Stickers-magic-wand.png")); - QuickMenuAPI.PrepareIcon(ModSettings.ModName, "Stickers-mouse", UIUtils.GetIconStream("Gohsantosadrive_Icons.Stickers-mouse.png")); - //QuickMenuAPI.PrepareIcon(ModSettings.ModName, "Stickers-pencil", UIUtils.GetIconStream("Gohsantosadrive_Icons.Stickers-pencil.png")); - QuickMenuAPI.PrepareIcon(ModSettings.ModName, "Stickers-puzzle", UIUtils.GetIconStream("Gohsantosadrive_Icons.Stickers-puzzle.png")); - QuickMenuAPI.PrepareIcon(ModSettings.ModName, "Stickers-rubbish-bin", UIUtils.GetIconStream("Gohsantosadrive_Icons.Stickers-rubbish-bin.png")); - } - - private static void Setup_StickerModTab() - { - _rootPage = new Page(ModSettings.ModName, ModSettings.SM_SettingsCategory, true, "Stickers-puzzle") - { - MenuTitle = ModSettings.SM_SettingsCategory, - MenuSubtitle = "Stickers! Double-click the tab to quickly toggle Sticker Mode.", - }; - - _rootPageElementID = _rootPage.ElementID; - - QuickMenuAPI.OnTabChange += OnTabChange; - ModNetwork.OnTextureOutboundStateChanged += (isSending) => - { - if (_isOurTabOpened && isSending) QuickMenuAPI.ShowAlertToast("Sending Sticker over Mod Network...", 2); - //_rootPage.Disabled = isSending; // TODO: fix being able to select stickers while sending - }; - - StickerSystem.OnStickerLoaded += (slotIndex, imageRelativePath) => - { - if (_isOurTabOpened) QuickMenuAPI.ShowAlertToast($"Sticker loaded: {imageRelativePath}", 2); - _stickerSelectionButtons[slotIndex].ButtonIcon = StickerCache.GetBtkUiIconName(imageRelativePath); - }; - - StickerSystem.OnStickerLoadFailed += (slotIndex, error) => - { - if (_isOurTabOpened) QuickMenuAPI.ShowAlertToast(error, 3); - }; - - Setup_StickersModCategory(); - Setup_StickerSelectionCategory(); - Setup_OtherOptionsCategory(); - } - - #endregion Setup - - #region Double-Click Place Sticker - - private static DateTime lastTime = DateTime.Now; - - private static void OnTabChange(string newTab, string previousTab) - { - _isOurTabOpened = newTab == _rootPageElementID; - if (!_isOurTabOpened) return; - - TimeSpan timeDifference = DateTime.Now - lastTime; - if (timeDifference.TotalSeconds <= 0.5) - { - switch (ModSettings.Entry_TabDoubleClick.Value) - { - default: - case TabDoubleClick.ToggleStickerMode: - OnPlaceStickersButtonClick(); - break; - case TabDoubleClick.ClearAllStickers: - OnClearAllStickersButtonClick(); - break; - case TabDoubleClick.ClearSelfStickers: - OnClearSelfStickersButtonClick(); - break; - case TabDoubleClick.None: - break; - } - return; - } - lastTime = DateTime.Now; - } - - #endregion Double-Click Place Sticker +using BTKUILib; +using BTKUILib.UIObjects; +using NAK.Stickers.Networking; +using NAK.Stickers.Utilities; +using System.Reflection; +using System.Runtime.InteropServices; + +namespace NAK.Stickers.Integrations; + +public static partial class BTKUIAddon +{ + private static Page _rootPage; + private static string _rootPageElementID; + + private static bool _isOurTabOpened; + + public static void Initialize() + { + Setup_Icons(); + Setup_StickerModTab(); + Setup_PlayerOptionsPage(); + } + + #region Setup + + private static void Setup_Icons() + { + // All icons used - https://www.flaticon.com/authors/gohsantosadrive + QuickMenuAPI.PrepareIcon(ModSettings.ModName, "Stickers-alphabet", Assembly.GetExecutingAssembly().GetManifestResourceStream("Stickers.Resources.Gohsantosadrive_Icons.Stickers-alphabet.png")); + QuickMenuAPI.PrepareIcon(ModSettings.ModName, "Stickers-eraser", Assembly.GetExecutingAssembly().GetManifestResourceStream("Stickers.Resources.Gohsantosadrive_Icons.Stickers-eraser.png")); + QuickMenuAPI.PrepareIcon(ModSettings.ModName, "Stickers-folder", Assembly.GetExecutingAssembly().GetManifestResourceStream("Stickers.Resources.Gohsantosadrive_Icons.Stickers-folder.png")); + QuickMenuAPI.PrepareIcon(ModSettings.ModName, "Stickers-headset", Assembly.GetExecutingAssembly().GetManifestResourceStream("Stickers.Resources.Gohsantosadrive_Icons.Stickers-headset.png")); + QuickMenuAPI.PrepareIcon(ModSettings.ModName, "Stickers-magnifying-glass", Assembly.GetExecutingAssembly().GetManifestResourceStream("Stickers.Resources.Gohsantosadrive_Icons.Stickers-magnifying-glass.png")); + QuickMenuAPI.PrepareIcon(ModSettings.ModName, "Stickers-magic-wand", Assembly.GetExecutingAssembly().GetManifestResourceStream("Stickers.Resources.Gohsantosadrive_Icons.Stickers-magic-wand.png")); + QuickMenuAPI.PrepareIcon(ModSettings.ModName, "Stickers-magic-wand-broken", Assembly.GetExecutingAssembly().GetManifestResourceStream("Stickers.Resources.Gohsantosadrive_Icons.Stickers-magic-wand-broken.png")); + QuickMenuAPI.PrepareIcon(ModSettings.ModName, "Stickers-mouse", Assembly.GetExecutingAssembly().GetManifestResourceStream("Stickers.Resources.Gohsantosadrive_Icons.Stickers-mouse.png")); + //QuickMenuAPI.PrepareIcon(ModSettings.ModName, "Stickers-pencil", UIUtils.GetIconStream("Gohsantosadrive_Icons.Stickers-pencil.png")); + QuickMenuAPI.PrepareIcon(ModSettings.ModName, "Stickers-puzzle", Assembly.GetExecutingAssembly().GetManifestResourceStream("Stickers.Resources.Gohsantosadrive_Icons.Stickers-puzzle.png")); + QuickMenuAPI.PrepareIcon(ModSettings.ModName, "Stickers-puzzle-disabled", Assembly.GetExecutingAssembly().GetManifestResourceStream("Stickers.Resources.Gohsantosadrive_Icons.Stickers-puzzle-disabled.png")); //Disabled Sticker Puzzle + QuickMenuAPI.PrepareIcon(ModSettings.ModName, "Stickers-rubbish-bin", Assembly.GetExecutingAssembly().GetManifestResourceStream("Stickers.Resources.Gohsantosadrive_Icons.Stickers-rubbish-bin.png")); + } + + private static void Setup_StickerModTab() + { + _rootPage = new Page(ModSettings.ModName, ModSettings.SM_SettingsCategory, true, "Stickers-Puzzle") //Sticker Icon will be left blank as it is updated on world join, AFTER Icon value is exposed.. + { + MenuTitle = ModSettings.SM_SettingsCategory, + MenuSubtitle = "", //Left this blank as it is defined when the world loads + }; + + _rootPageElementID = _rootPage.ElementID; + + QuickMenuAPI.OnTabChange += OnTabChange; + ModNetwork.OnTextureOutboundStateChanged += (isSending) => + { + if (_isOurTabOpened && isSending) QuickMenuAPI.ShowAlertToast("Sending Sticker over Mod Network...", 2); + //_rootPage.Disabled = isSending; // TODO: fix being able to select stickers while sending + }; + + StickerSystem.OnStickerLoaded += (slotIndex, imageRelativePath) => + { + if (_isOurTabOpened) QuickMenuAPI.ShowAlertToast($"Sticker loaded: {imageRelativePath}", 2); + _stickerSelectionButtons[slotIndex].ButtonIcon = StickerCache.GetBtkUiIconName(imageRelativePath); + }; + + StickerSystem.OnStickerLoadFailed += (slotIndex, error) => + { + if (_isOurTabOpened) QuickMenuAPI.ShowAlertToast(error, 3); + }; + + Setup_StickersModCategory(); + Setup_StickerSelectionCategory(); + Setup_OtherOptionsCategory(); + } + + #endregion Setup + + #region Double-Click Place Sticker + + private static DateTime lastTime = DateTime.Now; + + private static void OnTabChange(string newTab, string previousTab) + { + _isOurTabOpened = newTab == _rootPageElementID; + if (!_isOurTabOpened) return; + + TimeSpan timeDifference = DateTime.Now - lastTime; + if (timeDifference.TotalSeconds <= 0.5) + { + switch (ModSettings.Entry_TabDoubleClick.Value) + { + default: + case TabDoubleClick.ToggleStickerMode: + if (StickerSystem.RestrictedInstance == false) + { + OnPlaceStickersButtonClick(); + } + break; + case TabDoubleClick.ClearAllStickers: + OnClearAllStickersButtonClick(); + break; + case TabDoubleClick.ClearSelfStickers: + OnClearSelfStickersButtonClick(); + break; + case TabDoubleClick.None: + break; + } + return; + } + lastTime = DateTime.Now; + } + + #endregion Double-Click Place Sticker } \ No newline at end of file diff --git a/Stickers/Properties/AssemblyInfo.cs b/Stickers/Properties/AssemblyInfo.cs index 425649a..5107aed 100644 --- a/Stickers/Properties/AssemblyInfo.cs +++ b/Stickers/Properties/AssemblyInfo.cs @@ -1,32 +1,32 @@ -using NAK.Stickers.Properties; -using MelonLoader; -using System.Reflection; - -[assembly: AssemblyVersion(AssemblyInfoParams.Version)] -[assembly: AssemblyFileVersion(AssemblyInfoParams.Version)] -[assembly: AssemblyInformationalVersion(AssemblyInfoParams.Version)] -[assembly: AssemblyTitle(nameof(NAK.Stickers))] -[assembly: AssemblyCompany(AssemblyInfoParams.Author)] -[assembly: AssemblyProduct(nameof(NAK.Stickers))] - -[assembly: MelonInfo( - typeof(NAK.Stickers.StickerMod), - nameof(NAK.Stickers), - AssemblyInfoParams.Version, - AssemblyInfoParams.Author, - downloadLink: "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/Stickers" -)] - -[assembly: MelonGame("Alpha Blend Interactive", "ChilloutVR")] -[assembly: MelonPlatform(MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] -[assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.MONO)] -[assembly: MelonColor(255, 246, 25, 99)] // red-pink -[assembly: MelonAuthorColor(255, 158, 21, 32)] // red -[assembly: HarmonyDontPatchAll] - -namespace NAK.Stickers.Properties; -internal static class AssemblyInfoParams -{ - public const string Version = "1.0.7"; - public const string Author = "NotAKidoS"; +using NAK.Stickers.Properties; +using MelonLoader; +using System.Reflection; + +[assembly: AssemblyVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyFileVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyInformationalVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyTitle(nameof(NAK.Stickers))] +[assembly: AssemblyCompany(AssemblyInfoParams.Author)] +[assembly: AssemblyProduct(nameof(NAK.Stickers))] + +[assembly: MelonInfo( + typeof(NAK.Stickers.StickerMod), + nameof(NAK.Stickers), + AssemblyInfoParams.Version, + AssemblyInfoParams.Author, + downloadLink: "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/Stickers" +)] + +[assembly: MelonGame("Alpha Blend Interactive", "ChilloutVR")] +[assembly: MelonPlatform(MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] +[assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.MONO)] +[assembly: MelonColor(255, 246, 25, 99)] // red-pink +[assembly: MelonAuthorColor(255, 158, 21, 32)] // red +[assembly: HarmonyDontPatchAll] + +namespace NAK.Stickers.Properties; +internal static class AssemblyInfoParams +{ + public const string Version = "1.0.8"; + public const string Author = "NotAKidoS, SketchFoxsky"; } \ No newline at end of file diff --git a/Stickers/README.md b/Stickers/README.md index eff471a..ae0f4ae 100644 --- a/Stickers/README.md +++ b/Stickers/README.md @@ -22,6 +22,12 @@ Any image placed in the `UserData/Stickers/` folder will be available to choose - Requires the experimental Shader Safety Settings to be disabled as it will cause crashes when decals attempt to generate on GPU. - The mod will automatically disable this setting when it is enabled on startup. +### Restrictions +- Full Restriction. + - To disable Stickers for the whole world, name an empty GameObject "**[DisableStickers]**". +- Partial Restriction. + - To keep stickers enabled but not allowing it on certain objects, add the "**[NoSticker]**" tag to the GameObject name. + ## Attributions - All icons used are by [Gohsantosadrive]() on Flaticon. - Decal generation system by [Mr F]() on the Unity Asset Store. diff --git a/Stickers/Resources/Gohsantosadrive_Icons/Stickers-magic-wand-broken.png b/Stickers/Resources/Gohsantosadrive_Icons/Stickers-magic-wand-broken.png new file mode 100644 index 0000000..a8e222c Binary files /dev/null and b/Stickers/Resources/Gohsantosadrive_Icons/Stickers-magic-wand-broken.png differ diff --git a/Stickers/Resources/Gohsantosadrive_Icons/Stickers-puzzle-Disabled.png b/Stickers/Resources/Gohsantosadrive_Icons/Stickers-puzzle-Disabled.png new file mode 100644 index 0000000..600038b Binary files /dev/null and b/Stickers/Resources/Gohsantosadrive_Icons/Stickers-puzzle-Disabled.png differ diff --git a/Stickers/Stickers/Networking/ModNetwork.Inbound.cs b/Stickers/Stickers/Networking/ModNetwork.Inbound.cs index 7a6af74..ad04daf 100644 --- a/Stickers/Stickers/Networking/ModNetwork.Inbound.cs +++ b/Stickers/Stickers/Networking/ModNetwork.Inbound.cs @@ -1,248 +1,250 @@ -using ABI_RC.Core.Networking.IO.Social; -using ABI_RC.Core.Savior; -using ABI_RC.Systems.ModNetwork; -using NAK.Stickers.Utilities; -using UnityEngine; - -namespace NAK.Stickers.Networking; - -public static partial class ModNetwork -{ - #region Inbound Buffers - - private static readonly Dictionary _textureChunkBuffers = new(); - private static readonly Dictionary _receivedChunkCounts = new(); - private static readonly Dictionary _expectedChunkCounts = new(); - private static readonly Dictionary _textureMetadata = new(); - - #endregion Inbound Buffers - - #region Reset Method - - public static void Reset() - { - _textureChunkBuffers.Clear(); - _receivedChunkCounts.Clear(); - _expectedChunkCounts.Clear(); - _textureMetadata.Clear(); - - LoggerInbound("ModNetwork inbound buffers and metadata have been reset."); - } - - #endregion Reset Method - - #region Inbound Methods - - private static bool ShouldReceiveFromSender(string sender) - { - if (_disallowedForSession.Contains(sender)) - return false; // ignore messages from disallowed users - - if (MetaPort.Instance.blockedUserIds.Contains(sender)) - return false; // ignore messages from blocked users - - if (ModSettings.Entry_FriendsOnly.Value && !Friends.FriendsWith(sender)) - return false; // ignore messages from non-friends if friends only is enabled - - return true; - } - - private static void HandleMessageReceived(ModNetworkMessage msg) - { - try - { - string sender = msg.Sender; - msg.Read(out byte msgTypeRaw); - - if (!Enum.IsDefined(typeof(MessageType), msgTypeRaw)) - return; - - if (!ShouldReceiveFromSender(sender)) - return; - - LoggerInbound($"Received message from {msg.Sender}, Type: {(MessageType)msgTypeRaw}"); - - switch ((MessageType)msgTypeRaw) - { - case MessageType.PlaceSticker: - HandlePlaceSticker(msg); - break; - case MessageType.ClearSticker: - HandleClearSticker(msg); - break; - case MessageType.ClearAllStickers: - HandleClearAllStickers(msg); - break; - case MessageType.StartTexture: - HandleStartTexture(msg); - break; - case MessageType.SendTexture: - HandleSendTexture(msg); - break; - case MessageType.EndTexture: - HandleEndTexture(msg); - break; - case MessageType.RequestTexture: - HandleRequestTexture(msg); - break; - default: - LoggerInbound($"Invalid message type received: {msgTypeRaw}"); - break; - } - } - catch (Exception e) - { - LoggerInbound($"Error handling message from {msg.Sender}: {e.Message}", true); - } - } - - private static void HandlePlaceSticker(ModNetworkMessage msg) - { - msg.Read(out int stickerSlot); - msg.Read(out Guid textureHash); - msg.Read(out Vector3 position); - msg.Read(out Vector3 forward); - msg.Read(out Vector3 up); - - if (!StickerSystem.Instance.HasTextureHash(msg.Sender, textureHash)) - SendRequestTexture(stickerSlot, textureHash); - - StickerSystem.Instance.OnStickerPlaceReceived(msg.Sender, stickerSlot, position, forward, up); - } - - private static void HandleClearSticker(ModNetworkMessage msg) - { - msg.Read(out int stickerSlot); - StickerSystem.Instance.OnStickerClearReceived(msg.Sender, stickerSlot); - } - - private static void HandleClearAllStickers(ModNetworkMessage msg) - { - StickerSystem.Instance.OnStickerClearAllReceived(msg.Sender); - } - - private static void HandleStartTexture(ModNetworkMessage msg) - { - string sender = msg.Sender; - msg.Read(out int stickerSlot); - msg.Read(out Guid textureHash); - msg.Read(out int chunkCount); - msg.Read(out int width); - msg.Read(out int height); - - if (_textureChunkBuffers.ContainsKey(sender)) - { - LoggerInbound($"Received StartTexture message from {sender} while still receiving texture data!"); - return; - } - - if (StickerSystem.Instance.HasTextureHash(sender, textureHash)) - { - LoggerInbound($"Received StartTexture message from {sender} with existing texture hash {textureHash}, skipping texture data."); - return; - } - - if (chunkCount > MaxChunkCount) - { - LoggerInbound($"Received StartTexture message from {sender} with too many chunks: {chunkCount}", true); - return; - } - - _textureMetadata[sender] = (stickerSlot, textureHash, width, height); - _textureChunkBuffers[sender] = new byte[Mathf.Clamp(chunkCount * ChunkSize, 0, MaxTextureSize)]; - _expectedChunkCounts[sender] = Mathf.Clamp(chunkCount, 0, MaxChunkCount); - _receivedChunkCounts[sender] = 0; - - LoggerInbound($"Received StartTexture message from {sender}: Slot: {stickerSlot}, Hash: {textureHash}, Chunks: {chunkCount}, Resolution: {width}x{height}"); - } - - private static void HandleSendTexture(ModNetworkMessage msg) - { - string sender = msg.Sender; - msg.Read(out int chunkIdx); - msg.Read(out byte[] chunkData); - - if (!_textureChunkBuffers.TryGetValue(sender, out var buffer)) - return; - - int startIndex = chunkIdx * ChunkSize; - Array.Copy(chunkData, 0, buffer, startIndex, chunkData.Length); - - _receivedChunkCounts[sender]++; - if (_receivedChunkCounts[sender] < _expectedChunkCounts[sender]) - return; - - (int stickerSlot, Guid Hash, int Width, int Height) metadata = _textureMetadata[sender]; - - // All chunks received, reassemble texture - _textureChunkBuffers.Remove(sender); - _receivedChunkCounts.Remove(sender); - _expectedChunkCounts.Remove(sender); - _textureMetadata.Remove(sender); - - // Validate image - if (!ImageUtility.IsValidImage(buffer)) - { - LoggerInbound($"[Inbound] Received texture data is not a valid image from {sender}!", true); - return; - } - - // Validate data TODO: fix hash??????? - (Guid imageHash, int width, int height) = ImageUtility.ExtractImageInfo(buffer); - if (metadata.Width != width - || metadata.Height != height) - { - LoggerInbound($"Received texture data does not match metadata! Expected: {metadata.Hash} ({metadata.Width}x{metadata.Height}), received: {imageHash} ({width}x{height})", true); - return; - } - - Texture2D texture = new(1,1); - texture.LoadImage(buffer); - texture.Compress(true); - - StickerSystem.Instance.OnPlayerStickerTextureReceived(sender, metadata.Hash, texture, metadata.stickerSlot); - - LoggerInbound($"All chunks received and texture reassembled from {sender}. " + - $"Texture size: {metadata.Width}x{metadata.Height}"); - } - - private static void HandleEndTexture(ModNetworkMessage msg) - { - string sender = msg.Sender; - if (!_textureChunkBuffers.ContainsKey(sender)) - return; - - LoggerInbound($"Received EndTexture message without all chunks received from {sender}! Only {_receivedChunkCounts[sender]} out of {_expectedChunkCounts[sender]} received."); - - _textureChunkBuffers.Remove(sender); - _receivedChunkCounts.Remove(sender); - _expectedChunkCounts.Remove(sender); - _textureMetadata.Remove(sender); - } - - private static void HandleRequestTexture(ModNetworkMessage msg) - { - string sender = msg.Sender; - msg.Read(out int stickerSlot); - msg.Read(out Guid textureHash); - - if (!_isSubscribedToModNetwork || IsSendingTexture) - return; - - if (stickerSlot < 0 || stickerSlot >= _textureStorage.Length) - { - LoggerInbound($"Received RequestTexture message from {sender} with invalid slot {stickerSlot}!"); - return; - } - - if (_textureStorage[stickerSlot].textureHash != textureHash) - { - LoggerInbound($"Received RequestTexture message from {sender} with invalid texture hash {textureHash} for slot {stickerSlot}!"); - return; - } - - SendTexture(stickerSlot); - } - - #endregion Inbound Methods +using ABI_RC.Core.Networking.IO.Social; +using ABI_RC.Core.Savior; +using ABI_RC.Systems.ModNetwork; +using NAK.Stickers.Utilities; +using UnityEngine; + +namespace NAK.Stickers.Networking; + +public static partial class ModNetwork +{ + #region Inbound Buffers + + private static readonly Dictionary _textureChunkBuffers = new(); + private static readonly Dictionary _receivedChunkCounts = new(); + private static readonly Dictionary _expectedChunkCounts = new(); + private static readonly Dictionary _textureMetadata = new(); + + #endregion Inbound Buffers + + #region Reset Method + + public static void Reset() + { + _textureChunkBuffers.Clear(); + _receivedChunkCounts.Clear(); + _expectedChunkCounts.Clear(); + _textureMetadata.Clear(); + + LoggerInbound("ModNetwork inbound buffers and metadata have been reset."); + } + + #endregion Reset Method + + #region Inbound Methods + + private static bool ShouldReceiveFromSender(string sender) + { + if (_disallowedForSession.Contains(sender)) + return false; // ignore messages from disallowed users + + if (MetaPort.Instance.blockedUserIds.Contains(sender)) + return false; // ignore messages from blocked users + + if (ModSettings.Entry_FriendsOnly.Value && !Friends.FriendsWith(sender)) + return false; // ignore messages from non-friends if friends only is enabled + if (StickerSystem.RestrictedInstance == true) // ignore messages from users when the world is restricted. This also includes older or modified version of Stickers mod. + return false; + + return true; + } + + private static void HandleMessageReceived(ModNetworkMessage msg) + { + try + { + string sender = msg.Sender; + msg.Read(out byte msgTypeRaw); + + if (!Enum.IsDefined(typeof(MessageType), msgTypeRaw)) + return; + + if (!ShouldReceiveFromSender(sender)) + return; + + LoggerInbound($"Received message from {msg.Sender}, Type: {(MessageType)msgTypeRaw}"); + + switch ((MessageType)msgTypeRaw) + { + case MessageType.PlaceSticker: + HandlePlaceSticker(msg); + break; + case MessageType.ClearSticker: + HandleClearSticker(msg); + break; + case MessageType.ClearAllStickers: + HandleClearAllStickers(msg); + break; + case MessageType.StartTexture: + HandleStartTexture(msg); + break; + case MessageType.SendTexture: + HandleSendTexture(msg); + break; + case MessageType.EndTexture: + HandleEndTexture(msg); + break; + case MessageType.RequestTexture: + HandleRequestTexture(msg); + break; + default: + LoggerInbound($"Invalid message type received: {msgTypeRaw}"); + break; + } + } + catch (Exception e) + { + LoggerInbound($"Error handling message from {msg.Sender}: {e.Message}", true); + } + } + + private static void HandlePlaceSticker(ModNetworkMessage msg) + { + msg.Read(out int stickerSlot); + msg.Read(out Guid textureHash); + msg.Read(out Vector3 position); + msg.Read(out Vector3 forward); + msg.Read(out Vector3 up); + + if (!StickerSystem.Instance.HasTextureHash(msg.Sender, textureHash)) + SendRequestTexture(stickerSlot, textureHash); + + StickerSystem.Instance.OnStickerPlaceReceived(msg.Sender, stickerSlot, position, forward, up); + } + + private static void HandleClearSticker(ModNetworkMessage msg) + { + msg.Read(out int stickerSlot); + StickerSystem.Instance.OnStickerClearReceived(msg.Sender, stickerSlot); + } + + private static void HandleClearAllStickers(ModNetworkMessage msg) + { + StickerSystem.Instance.OnStickerClearAllReceived(msg.Sender); + } + + private static void HandleStartTexture(ModNetworkMessage msg) + { + string sender = msg.Sender; + msg.Read(out int stickerSlot); + msg.Read(out Guid textureHash); + msg.Read(out int chunkCount); + msg.Read(out int width); + msg.Read(out int height); + + if (_textureChunkBuffers.ContainsKey(sender)) + { + LoggerInbound($"Received StartTexture message from {sender} while still receiving texture data!"); + return; + } + + if (StickerSystem.Instance.HasTextureHash(sender, textureHash)) + { + LoggerInbound($"Received StartTexture message from {sender} with existing texture hash {textureHash}, skipping texture data."); + return; + } + + if (chunkCount > MaxChunkCount) + { + LoggerInbound($"Received StartTexture message from {sender} with too many chunks: {chunkCount}", true); + return; + } + + _textureMetadata[sender] = (stickerSlot, textureHash, width, height); + _textureChunkBuffers[sender] = new byte[Mathf.Clamp(chunkCount * ChunkSize, 0, MaxTextureSize)]; + _expectedChunkCounts[sender] = Mathf.Clamp(chunkCount, 0, MaxChunkCount); + _receivedChunkCounts[sender] = 0; + + LoggerInbound($"Received StartTexture message from {sender}: Slot: {stickerSlot}, Hash: {textureHash}, Chunks: {chunkCount}, Resolution: {width}x{height}"); + } + + private static void HandleSendTexture(ModNetworkMessage msg) + { + string sender = msg.Sender; + msg.Read(out int chunkIdx); + msg.Read(out byte[] chunkData); + + if (!_textureChunkBuffers.TryGetValue(sender, out var buffer)) + return; + + int startIndex = chunkIdx * ChunkSize; + Array.Copy(chunkData, 0, buffer, startIndex, chunkData.Length); + + _receivedChunkCounts[sender]++; + if (_receivedChunkCounts[sender] < _expectedChunkCounts[sender]) + return; + + (int stickerSlot, Guid Hash, int Width, int Height) metadata = _textureMetadata[sender]; + + // All chunks received, reassemble texture + _textureChunkBuffers.Remove(sender); + _receivedChunkCounts.Remove(sender); + _expectedChunkCounts.Remove(sender); + _textureMetadata.Remove(sender); + + // Validate image + if (!ImageUtility.IsValidImage(buffer)) + { + LoggerInbound($"[Inbound] Received texture data is not a valid image from {sender}!", true); + return; + } + + // Validate data TODO: fix hash??????? + (Guid imageHash, int width, int height) = ImageUtility.ExtractImageInfo(buffer); + if (metadata.Width != width + || metadata.Height != height) + { + LoggerInbound($"Received texture data does not match metadata! Expected: {metadata.Hash} ({metadata.Width}x{metadata.Height}), received: {imageHash} ({width}x{height})", true); + return; + } + + Texture2D texture = new(1,1); + texture.LoadImage(buffer); + texture.Compress(true); + + StickerSystem.Instance.OnPlayerStickerTextureReceived(sender, metadata.Hash, texture, metadata.stickerSlot); + + LoggerInbound($"All chunks received and texture reassembled from {sender}. " + + $"Texture size: {metadata.Width}x{metadata.Height}"); + } + + private static void HandleEndTexture(ModNetworkMessage msg) + { + string sender = msg.Sender; + if (!_textureChunkBuffers.ContainsKey(sender)) + return; + + LoggerInbound($"Received EndTexture message without all chunks received from {sender}! Only {_receivedChunkCounts[sender]} out of {_expectedChunkCounts[sender]} received."); + + _textureChunkBuffers.Remove(sender); + _receivedChunkCounts.Remove(sender); + _expectedChunkCounts.Remove(sender); + _textureMetadata.Remove(sender); + } + + private static void HandleRequestTexture(ModNetworkMessage msg) + { + string sender = msg.Sender; + msg.Read(out int stickerSlot); + msg.Read(out Guid textureHash); + + if (!_isSubscribedToModNetwork || IsSendingTexture) + return; + + if (stickerSlot < 0 || stickerSlot >= _textureStorage.Length) + { + LoggerInbound($"Received RequestTexture message from {sender} with invalid slot {stickerSlot}!"); + return; + } + + if (_textureStorage[stickerSlot].textureHash != textureHash) + { + LoggerInbound($"Received RequestTexture message from {sender} with invalid texture hash {textureHash} for slot {stickerSlot}!"); + return; + } + + SendTexture(stickerSlot); + } + + #endregion Inbound Methods } \ No newline at end of file diff --git a/Stickers/Stickers/StickerSystem.Main.cs b/Stickers/Stickers/StickerSystem.Main.cs index ab95877..0a5a4ef 100644 --- a/Stickers/Stickers/StickerSystem.Main.cs +++ b/Stickers/Stickers/StickerSystem.Main.cs @@ -1,124 +1,151 @@ -using ABI_RC.Core.IO; -using ABI_RC.Core.Networking.IO.Instancing; -using ABI_RC.Core.UI; -using ABI_RC.Systems.GameEventSystem; -using NAK.Stickers.Networking; -using NAK.Stickers.Utilities; - -namespace NAK.Stickers; - -public partial class StickerSystem -{ - #region Singleton - - public static StickerSystem Instance { get; private set; } - - public static void Initialize() - { - if (Instance != null) - return; - - Instance = new StickerSystem(); - - // configure decalery - DecalManager.SetPreferredMode(DecalUtils.Mode.GPU, false, 0); - - // ensure cache folder exists - EnsureStickersFolderExists(); - - // listen for game events - CVRGameEventSystem.Initialization.OnPlayerSetupStart.AddListener(Instance.OnPlayerSetupStart); - } - - #endregion Singleton - - #region Callback Registration - - private void OnPlayerSetupStart() - { - CVRGameEventSystem.World.OnUnload.AddListener(_ => OnWorldUnload()); - CVRGameEventSystem.Instance.OnConnected.AddListener((_) => { if (!Instances.IsReconnecting) OnInitialConnection(); }); - - CVRGameEventSystem.Player.OnJoinEntity.AddListener(Instance.OnPlayerJoined); - CVRGameEventSystem.Player.OnLeaveEntity.AddListener(Instance.OnPlayerLeft); - SchedulerSystem.AddJob(Instance.OnUpdate, 10f, -1); - LoadAllImagesAtStartup(); - } - - #endregion Callback Registration - - #region Game Events - - private void OnInitialConnection() - { - ClearStickersSelf(); // clear stickers on remotes just in case we rejoined - ModNetwork.Reset(); // reset network buffers and metadata - } - - private void OnWorldUnload() - { - CleanupAllButSelf(); // release all stickers except for self - } - - #endregion Game Events - - #region Data - - // private bool _isEnabled = true; - // - // public bool IsEnabled - // { - // get => _isEnabled; - // set - // { - // if (_isEnabled == value) - // return; - // - // _isEnabled = value; - // if (!_isEnabled) ClearAllStickers(); - // ModNetwork.IsEnabled = _isEnabled; - // } - // } - - private string SelectedStickerName => ModSettings.Hidden_SelectedStickerNames.Value[_selectedStickerSlot]; - - private const float StickerKillTime = 30f; - private const float StickerCooldown = 0.2f; - private readonly Dictionary _playerStickers = new(); - internal const string PlayerLocalId = "_PLAYERLOCAL"; - - private int _selectedStickerSlot; - public int SelectedStickerSlot - { - get => _selectedStickerSlot; - set - { - _selectedStickerSlot = value < 0 ? ModSettings.MaxStickerSlots - 1 : value % ModSettings.MaxStickerSlots; - IsInStickerMode = IsInStickerMode; // refresh sticker mode - } - } - - private bool _isInStickerMode; - public bool IsInStickerMode - { - get => _isInStickerMode; - set - { - _isInStickerMode = value; - if (_isInStickerMode) - { - CohtmlHud.Instance.SelectPropToSpawn( - StickerCache.GetCohtmlResourcesPath(SelectedStickerName), - Path.GetFileNameWithoutExtension(SelectedStickerName), - "Sticker selected for stickering:"); - } - else - { - CohtmlHud.Instance.ClearPropToSpawn(); - ClearStickerPreview(); - } - } - } - - #endregion Data +using ABI_RC.Core.IO; +using ABI_RC.Core.Networking.IO.Instancing; +using ABI_RC.Core.UI; +using ABI_RC.Systems.GameEventSystem; +using JetBrains.Annotations; +using NAK.Stickers.Networking; +using NAK.Stickers.Utilities; +using System.EnterpriseServices; +using UnityEngine; +using MelonLoader; +using UnityEngine.ProBuilder.MeshOperations; +using NAK.Stickers.Integrations; + +namespace NAK.Stickers; + +public partial class StickerSystem +{ + #region Singleton + + public static bool RestrictedInstance = false; + + public static StickerSystem Instance { get; private set; } + + public static void Initialize() + { + if (Instance != null) + return; + + Instance = new StickerSystem(); + + // configure decalery + DecalManager.SetPreferredMode(DecalUtils.Mode.GPU, false, 0); + + // ensure cache folder exists + EnsureStickersFolderExists(); + + // listen for game events + CVRGameEventSystem.Initialization.OnPlayerSetupStart.AddListener(Instance.OnPlayerSetupStart); + +} + + #endregion Singleton + + #region Callback Registration + + private void OnPlayerSetupStart() + { + CVRGameEventSystem.World.OnUnload.AddListener(_ => OnWorldUnload()); + CVRGameEventSystem.World.OnLoad.AddListener(_ => OnWorldLoad()); + CVRGameEventSystem.Instance.OnConnected.AddListener((_) => { if (!Instances.IsReconnecting) OnInitialConnection(); }); + + CVRGameEventSystem.Player.OnJoinEntity.AddListener(Instance.OnPlayerJoined); + CVRGameEventSystem.Player.OnLeaveEntity.AddListener(Instance.OnPlayerLeft); + SchedulerSystem.AddJob(Instance.OnUpdate, 10f, -1); + LoadAllImagesAtStartup(); + } + + #endregion Callback Registration + + #region Game Events + + private void OnInitialConnection() + { + OnWorldLoad(); //Checks the world again in case the bundle updated. + ClearStickersSelf(); // clear stickers on remotes just in case we rejoined + ModNetwork.Reset(); // reset network buffers and metadata + } + + private void OnWorldLoad() + { + GameObject StickerWorldRestriction = GameObject.Find("[DisableStickers]"); + if (StickerWorldRestriction != null) + { + RestrictedInstance = true; + MelonLogger.Msg("This is a Restricted Instance"); + } + else + { + MelonLogger.Msg("This is NOT a Restricted Instance"); + } + BTKUIAddon.UpdateStickerMenu(); + } + + private void OnWorldUnload() + { + RestrictedInstance = false; + CleanupAllButSelf(); // release all stickers except for self + } + + #endregion Game Events + + #region Data + + // private bool _isEnabled = true; + // + // public bool IsEnabled + // { + // get => _isEnabled; + // set + // { + // if (_isEnabled == value) + // return; + // + // _isEnabled = value; + // if (!_isEnabled) ClearAllStickers(); + // ModNetwork.IsEnabled = _isEnabled; + // } + // } + + private string SelectedStickerName => ModSettings.Hidden_SelectedStickerNames.Value[_selectedStickerSlot]; + + private const float StickerKillTime = 30f; + private const float StickerCooldown = 0.2f; + private readonly Dictionary _playerStickers = new(); + internal const string PlayerLocalId = "_PLAYERLOCAL"; + + private int _selectedStickerSlot; + public int SelectedStickerSlot + { + get => _selectedStickerSlot; + set + { + _selectedStickerSlot = value < 0 ? ModSettings.MaxStickerSlots - 1 : value % ModSettings.MaxStickerSlots; + IsInStickerMode = IsInStickerMode; // refresh sticker mode + } + } + + private bool _isInStickerMode; + public bool IsInStickerMode + { + get => _isInStickerMode; + set + { + _isInStickerMode = value; + if (_isInStickerMode) + { + CohtmlHud.Instance.SelectPropToSpawn( + StickerCache.GetCohtmlResourcesPath(SelectedStickerName), + Path.GetFileNameWithoutExtension(SelectedStickerName), + "Sticker selected for stickering:"); + } + else + { + CohtmlHud.Instance.ClearPropToSpawn(); + ClearStickerPreview(); + } + } + } + + #endregion Data } \ No newline at end of file diff --git a/Stickers/Stickers/StickerSystem.StickerLifecycle.cs b/Stickers/Stickers/StickerSystem.StickerLifecycle.cs index 2977dff..821aedc 100644 --- a/Stickers/Stickers/StickerSystem.StickerLifecycle.cs +++ b/Stickers/Stickers/StickerSystem.StickerLifecycle.cs @@ -1,190 +1,194 @@ -using ABI_RC.Core; -using ABI_RC.Core.Player; -using ABI_RC.Systems.InputManagement; -using NAK.Stickers.Networking; -using UnityEngine; - -namespace NAK.Stickers; - -public partial class StickerSystem -{ - #region Sticker Lifecycle - - private StickerData GetOrCreateStickerData(string playerId) - { - if (_playerStickers.TryGetValue(playerId, out StickerData stickerData)) - return stickerData; - - stickerData = new StickerData(playerId, ModSettings.MaxStickerSlots); - _playerStickers[playerId] = stickerData; - return stickerData; - } - - public void PlaceStickerFromControllerRay(Transform transform, CVRHand hand = CVRHand.Left, bool isPreview = false) - { - Vector3 controllerForward = transform.forward; - Vector3 controllerUp = transform.up; - Vector3 playerUp = PlayerSetup.Instance.transform.up; - - // extracting angle of controller ray on forward axis - Vector3 projectedControllerUp = Vector3.ProjectOnPlane(controllerUp, controllerForward).normalized; - Vector3 projectedPlayerUp = Vector3.ProjectOnPlane(playerUp, controllerForward).normalized; - float angle = Vector3.Angle(projectedControllerUp, projectedPlayerUp); - - float angleThreshold = ModSettings.Entry_PlayerUpAlignmentThreshold.Value; - Vector3 targetUp = (angleThreshold != 0f && angle <= angleThreshold) - // leave 0.01% of the controller up vector to prevent issues with alignment on floor & ceiling in Desktop - ? Vector3.Slerp(controllerUp, playerUp, 0.99f) - : controllerUp; - - if (isPreview) - { - PlaceStickerPreview(transform.position, controllerForward, targetUp); - return; - } - - if (!PlaceStickerSelf(transform.position, transform.forward, targetUp)) - return; - - CVRInputManager.Instance.Vibrate(0f, 0.1f, 10f, 0.1f, hand); - } - - private bool PlaceStickerSelf(Vector3 position, Vector3 forward, Vector3 up, bool alignWithNormal = true) - { - if (!AttemptPlaceSticker(PlayerLocalId, position, forward, up, alignWithNormal, SelectedStickerSlot)) - return false; // failed - - // placed, now network - ModNetwork.SendPlaceSticker(SelectedStickerSlot, position, forward, up); - return true; - } - - private bool AttemptPlaceSticker(string playerId, Vector3 position, Vector3 forward, Vector3 up, bool alignWithNormal = true, int stickerSlot = 0, bool isPreview = false) - { - StickerData stickerData = GetOrCreateStickerData(playerId); - if (Time.time - stickerData.LastPlacedTime < StickerCooldown) - return false; - - // Every layer other than IgnoreRaycast, PlayerLocal, PlayerClone, PlayerNetwork, and UI Internal - const int LayerMask = ~((1 << 2) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 15)); - if (!Physics.Raycast(position, forward, out RaycastHit hit, - 10f, LayerMask, QueryTriggerInteraction.Ignore)) - return false; - - // if gameobject name starts with [NoSticker] then don't place sticker - if (hit.transform.gameObject.name.StartsWith("[NoSticker]")) - return false; - - if (isPreview) - { - stickerData.PlacePreview(hit, alignWithNormal ? -hit.normal : forward, up, stickerSlot); - return true; - } - - stickerData.Place(hit, alignWithNormal ? -hit.normal : forward, up, stickerSlot); - stickerData.PlayAudio(); - return true; - } - - public void ClearStickersSelf() - { - ClearStickersForPlayer(PlayerLocalId); - ModNetwork.SendClearAllStickers(); - } - - public void ClearStickerSelf(int stickerSlot) - { - ClearStickersForPlayer(PlayerLocalId, stickerSlot); - ModNetwork.SendClearSticker(stickerSlot); - } - - private void ClearStickersForPlayer(string playerId) - { - if (!_playerStickers.TryGetValue(playerId, out StickerData stickerData)) - return; - - stickerData.Clear(); - } - - private void ClearStickersForPlayer(string playerId, int stickerSlot) - { - if (!_playerStickers.TryGetValue(playerId, out StickerData stickerData)) - return; - - stickerData.Clear(stickerSlot); - } - - private void SetTextureSelf(byte[] imageBytes, int stickerSlot = 0) - { - Texture2D texture = new(1, 1); // placeholder - texture.LoadImage(imageBytes); - texture.Compress(true); // noachi said to do - - ClearStickerSelf(stickerSlot); // clear placed stickers in-scene so we can't replace an entire wall at once - OnPlayerStickerTextureReceived(PlayerLocalId, Guid.Empty, texture, stickerSlot); - ModNetwork.SetTexture(stickerSlot, imageBytes); - } - - public void ClearAllStickers() - { - foreach (StickerData stickerData in _playerStickers.Values) - stickerData.Clear(); - - ModNetwork.SendClearAllStickers(); - } - - public void OnPlayerStickerTextureReceived(string playerId, Guid textureHash, Texture2D texture, int stickerSlot = 0) - { - StickerData stickerData = GetOrCreateStickerData(playerId); - stickerData.SetTexture(textureHash, texture, stickerSlot); - } - - public bool HasTextureHash(string playerId, Guid textureHash) - { - StickerData stickerData = GetOrCreateStickerData(playerId); - return stickerData.CheckHasTextureHash(textureHash); - } - - public void CleanupAll() - { - foreach ((_, StickerData data) in _playerStickers) - data.Cleanup(); - - _playerStickers.Clear(); - } - - public void CleanupAllButSelf() - { - StickerData localStickerData = GetOrCreateStickerData(PlayerLocalId); - - foreach ((_, StickerData data) in _playerStickers) - { - if (data == localStickerData) data.Clear(); - else data.Cleanup(); - } - - _playerStickers.Clear(); - _playerStickers[PlayerLocalId] = localStickerData; - } - - public void PlaceStickerPreview(Vector3 position, Vector3 forward, Vector3 up) - { - AttemptPlaceSticker(PlayerLocalId, position, forward, up, true, SelectedStickerSlot, true); - } - - public void UpdateStickerPreview() - { - if (!IsInStickerMode) return; - - StickerData localStickerData = GetOrCreateStickerData(PlayerLocalId); - localStickerData.UpdatePreview(SelectedStickerSlot); - } - - public void ClearStickerPreview() - { - StickerData localStickerData = GetOrCreateStickerData(PlayerLocalId); - localStickerData.ClearPreview(); - } - - #endregion Sticker Lifecycle -} +using ABI_RC.Core; +using ABI_RC.Core.Player; +using ABI_RC.Systems.InputManagement; +using NAK.Stickers.Networking; +using UnityEngine; + +namespace NAK.Stickers; + +public partial class StickerSystem +{ + #region Sticker Lifecycle + + private StickerData GetOrCreateStickerData(string playerId) + { + if (_playerStickers.TryGetValue(playerId, out StickerData stickerData)) + return stickerData; + + stickerData = new StickerData(playerId, ModSettings.MaxStickerSlots); + _playerStickers[playerId] = stickerData; + return stickerData; + } + + public void PlaceStickerFromControllerRay(Transform transform, CVRHand hand = CVRHand.Left, bool isPreview = false) + { + Vector3 controllerForward = transform.forward; + Vector3 controllerUp = transform.up; + Vector3 playerUp = PlayerSetup.Instance.transform.up; + + // extracting angle of controller ray on forward axis + Vector3 projectedControllerUp = Vector3.ProjectOnPlane(controllerUp, controllerForward).normalized; + Vector3 projectedPlayerUp = Vector3.ProjectOnPlane(playerUp, controllerForward).normalized; + float angle = Vector3.Angle(projectedControllerUp, projectedPlayerUp); + + float angleThreshold = ModSettings.Entry_PlayerUpAlignmentThreshold.Value; + Vector3 targetUp = (angleThreshold != 0f && angle <= angleThreshold) + // leave 0.01% of the controller up vector to prevent issues with alignment on floor & ceiling in Desktop + ? Vector3.Slerp(controllerUp, playerUp, 0.99f) + : controllerUp; + + if (isPreview) + { + PlaceStickerPreview(transform.position, controllerForward, targetUp); + return; + } + + if (!PlaceStickerSelf(transform.position, transform.forward, targetUp)) + return; + + CVRInputManager.Instance.Vibrate(0f, 0.1f, 10f, 0.1f, hand); + } + + private bool PlaceStickerSelf(Vector3 position, Vector3 forward, Vector3 up, bool alignWithNormal = true) + { + if (!AttemptPlaceSticker(PlayerLocalId, position, forward, up, alignWithNormal, SelectedStickerSlot, RestrictedInstance)) + return false; // failed + + // placed, now network + ModNetwork.SendPlaceSticker(SelectedStickerSlot, position, forward, up); + return true; + } + + private bool AttemptPlaceSticker(string playerId, Vector3 position, Vector3 forward, Vector3 up, bool alignWithNormal = true, int stickerSlot = 0, bool RestrictedInstance = false, bool isPreview = false) + { + StickerData stickerData = GetOrCreateStickerData(playerId); + if (Time.time - stickerData.LastPlacedTime < StickerCooldown) + return false; + + // Every layer other than IgnoreRaycast, PlayerLocal, PlayerClone, PlayerNetwork, and UI Internal + const int LayerMask = ~((1 << 2) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 15)); + if (!Physics.Raycast(position, forward, out RaycastHit hit, + 10f, LayerMask, QueryTriggerInteraction.Ignore)) + return false; + + // if gameobject name starts with [NoSticker] then don't place sticker + if (hit.transform.gameObject.name.StartsWith("[NoSticker]")) + return false; + + // if the world contained a gameobject with the [DisableStickers] name and restricted the instance disable stickers! + if (RestrictedInstance == true) + return false; + + if (isPreview) + { + stickerData.PlacePreview(hit, alignWithNormal ? -hit.normal : forward, up, stickerSlot); + return true; + } + + stickerData.Place(hit, alignWithNormal ? -hit.normal : forward, up, stickerSlot); + stickerData.PlayAudio(); + return true; + } + + public void ClearStickersSelf() + { + ClearStickersForPlayer(PlayerLocalId); + ModNetwork.SendClearAllStickers(); + } + + public void ClearStickerSelf(int stickerSlot) + { + ClearStickersForPlayer(PlayerLocalId, stickerSlot); + ModNetwork.SendClearSticker(stickerSlot); + } + + private void ClearStickersForPlayer(string playerId) + { + if (!_playerStickers.TryGetValue(playerId, out StickerData stickerData)) + return; + + stickerData.Clear(); + } + + private void ClearStickersForPlayer(string playerId, int stickerSlot) + { + if (!_playerStickers.TryGetValue(playerId, out StickerData stickerData)) + return; + + stickerData.Clear(stickerSlot); + } + + private void SetTextureSelf(byte[] imageBytes, int stickerSlot = 0) + { + Texture2D texture = new(1, 1); // placeholder + texture.LoadImage(imageBytes); + texture.Compress(true); // noachi said to do + + ClearStickerSelf(stickerSlot); // clear placed stickers in-scene so we can't replace an entire wall at once + OnPlayerStickerTextureReceived(PlayerLocalId, Guid.Empty, texture, stickerSlot); + ModNetwork.SetTexture(stickerSlot, imageBytes); + } + + public void ClearAllStickers() + { + foreach (StickerData stickerData in _playerStickers.Values) + stickerData.Clear(); + + ModNetwork.SendClearAllStickers(); + } + + public void OnPlayerStickerTextureReceived(string playerId, Guid textureHash, Texture2D texture, int stickerSlot = 0) + { + StickerData stickerData = GetOrCreateStickerData(playerId); + stickerData.SetTexture(textureHash, texture, stickerSlot); + } + + public bool HasTextureHash(string playerId, Guid textureHash) + { + StickerData stickerData = GetOrCreateStickerData(playerId); + return stickerData.CheckHasTextureHash(textureHash); + } + + public void CleanupAll() + { + foreach ((_, StickerData data) in _playerStickers) + data.Cleanup(); + + _playerStickers.Clear(); + } + + public void CleanupAllButSelf() + { + StickerData localStickerData = GetOrCreateStickerData(PlayerLocalId); + + foreach ((_, StickerData data) in _playerStickers) + { + if (data == localStickerData) data.Clear(); + else data.Cleanup(); + } + + _playerStickers.Clear(); + _playerStickers[PlayerLocalId] = localStickerData; + } + + public void PlaceStickerPreview(Vector3 position, Vector3 forward, Vector3 up) + { + AttemptPlaceSticker(PlayerLocalId, position, forward, up, true, SelectedStickerSlot, true); + } + + public void UpdateStickerPreview() + { + if (!IsInStickerMode) return; + + StickerData localStickerData = GetOrCreateStickerData(PlayerLocalId); + localStickerData.UpdatePreview(SelectedStickerSlot); + } + + public void ClearStickerPreview() + { + StickerData localStickerData = GetOrCreateStickerData(PlayerLocalId); + localStickerData.ClearPreview(); + } + + #endregion Sticker Lifecycle +}