diff --git a/.gitignore b/.gitignore index 3248850..eb5f465 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ riderModule.iml CannedNet.sln.DotSettings.user CannedNet/Data/PrivateKey.pem /CannedNet/.zed +CannedNet/Data/PublicKey.pem diff --git a/CannedNet/CannedNet.csproj b/CannedNet/CannedNet.csproj index 9488359..21122c0 100644 --- a/CannedNet/CannedNet.csproj +++ b/CannedNet/CannedNet.csproj @@ -10,6 +10,10 @@ + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + diff --git a/CannedNet/Data/DataBlobs/94tp5zjtwz0gppp8xlv1j9l5b.room b/CannedNet/Data/DataBlobs/94tp5zjtwz0gppp8xlv1j9l5b.room new file mode 100644 index 0000000..29727b6 Binary files /dev/null and b/CannedNet/Data/DataBlobs/94tp5zjtwz0gppp8xlv1j9l5b.room differ diff --git a/CannedNet/JSON/gameconfigs.json b/CannedNet/JSON/gameconfigs.json index ec61b59..5baf8b7 100644 --- a/CannedNet/JSON/gameconfigs.json +++ b/CannedNet/JSON/gameconfigs.json @@ -1,170 +1,2298 @@ [ - { - "Key": "Debug.Watchdog.AdditionalTraceFlagsForLoading", - "Value": "None" - }, - { - "Key": "Debug.Watchdog.CorruptRoomDetectionProbability", - "Value": "0" - }, - { - "Key": "Door.Creative.Query", - "Value": "#horror" - }, - { - "Key": "Door.Creative.Title", - "Value": "HORROR" - }, - { - "Key": "Door.Featured.Query", - "Value": "" - }, - { - "Key": "Door.Featured.Title", - "Value": "Door" - }, - { - "Key": "Door.Quests.Query", - "Value": "#quest #recroomoriginal" - }, - { - "Key": "Door.Quests.Title", - "Value": "QUESTS" - }, - { - "Key": "Door.Shooters.Query", - "Value": "#shooters" - }, - { - "Key": "Door.Shooters.Title", - "Value": "SHOOTERS" - }, - { - "Key": "Door.Sports.Query", - "Value": "#recroomoriginal #sports | #pvp #recroomoriginal " - }, - { - "Key": "Door.Sports.Title", - "Value": "SPORTS & PVP" - }, - { - "Key": "Door.StuntRunner.Query", - "Value": "#stuntrunner #community" - }, - { - "Key": "Door.StuntRunner.Title", - "Value": "COMMUNITY" - }, - { - "Key": "EnableRoomResetLogs", - "Value": "1" - }, - { - "Key": "FentReactor.Enabled", - "Value": "True" - }, - { - "Key": "Friends.PostGamePromptUnderFriendCount", - "Value": "10" - }, - { - "Key": "Friends.SuggestFriendCodeOnFriendsScreenCount", - "Value": "25" - }, - { - "Key": "Growth.ShouldPromptForCreatorEmail", - "Value": "true" - }, - { - "Key": "loadingNetworkTimeout", - "Value": "180" - }, - { - "Key": "Marquee", - "Value": "CannedNet" - }, - { - "Key": "RAC:CurrentChallenge", - "Value": "{\"Challenge\":\"AQJCIIXfWaPue2PO75i5nM9nVCPTCbhjnQDUU94I+v//SrxkmVSoLfdEoY5Dp/BwBB+wgIh3kbNL5SPZk2KRQeDDVn+LC/EQoajdcxE59qSDYLM8G1bXued1vRv/Wlk0p5M+Ov2LrnNxS6r8uL2o7V3prYZzEOTrdculBU8rbq4=\",\"LastUpdated\":\"2026-01-15T01:18:34.167596Z\"}" - }, - { - "Key": "Rendering.DisableSrpBatcher", - "Value": "true" - }, - { - "Key": "Rewards.SelectionTimeout", - "Value": "1800" - }, - { - "Key": "Rewards.UseRewardSelection", - "Value": "false" - }, - { - "Key": "RoomDetails.PhotoRollEnabled", - "Value": "true" - }, - { - "Key": "RoomScaleMotionCheatDetector.MaxAllowedAverageHmdSpeed", - "Value": "1024" - }, - { - "Key": "RoomScaleMotionCheatDetector.MeasurementPeriodInSeconds", - "Value": "5" - }, - { - "Key": "RoomScaleMotionCheatDetector.MinHmdSpeedAboveTriggerCount", - "Value": "1024" - }, - { - "Key": "RoomScaleMotionCheatDetector.ShouldBootToDormWhenDetected.Oculus", - "Value": "false" - }, - { - "Key": "RoomScaleMotionCheatDetector.ShouldBootToDormWhenDetected.Steam", - "Value": "false" - }, - { - "Key": "RoomScaleMotionCheatDetector.TriggerHmdSpeed", - "Value": "1024" - }, - { - "Key": "runningNetworkTimeout", - "Value": "30" - }, { "Key": "Screens.ForceVerification", - "Value": "1" + "Value": "1", + "ActiveExperiments": null }, { - "Key": "splitTestHardOverrides", - "Value": "" - }, - { - "Key": "splitTestSegmentProbabilities", - "Value": "" + "Key": "Screens.ForceWaitlist", + "Value": "false", + "ActiveExperiments": null }, { "Key": "splitTestSoftOverrides", - "Value": "" + "Value": "", + "ActiveExperiments": null + }, + { + "Key": "Door.Creative.Query", + "Value": "^CreativeCampus | ^RecRoomGallery", + "ActiveExperiments": null + }, + { + "Key": "Door.Creative.Title", + "Value": "Creative Campus", + "ActiveExperiments": null + }, + { + "Key": "Door.Featured.Query", + "Value": "#featured", + "ActiveExperiments": null + }, + { + "Key": "Door.Featured.Title", + "Value": "Featured", + "ActiveExperiments": null + }, + { + "Key": "Door.Quests.Query", + "Value": "#quest #rro", + "ActiveExperiments": null + }, + { + "Key": "Door.Quests.Title", + "Value": "QUESTS", + "ActiveExperiments": null + }, + { + "Key": "Door.Shooters.Query", + "Value": "#rrstudio", + "ActiveExperiments": null + }, + { + "Key": "Door.Shooters.Title", + "Value": "RRS Rooms", + "ActiveExperiments": null + }, + { + "Key": "Door.Sports.Query", + "Value": "#sport #rro | #pvp #rro", + "ActiveExperiments": null + }, + { + "Key": "Door.Sports.Title", + "Value": "SPORTS & PVP", + "ActiveExperiments": null + }, + { + "Key": "Screens.ForceRegistrationPS4", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "splitTestHardOverrides", + "Value": "IOSAppPermissions_2019_10_02=Immediate;GottaGoFastNUX_2020_09_04=Off;RecNetImageCacheRefCount_2020_09_18=On;Curated_Rooms_2020_08_06=On;PlayMenuRRUI_2021_01_11=On;PlayMenuRRUI_HotRoomsCarousel_2021_02_09=On;PlayMenuRRUI_CarouselOrdering_2021_02_09=PlayMenuCarouselOrdering_1;CreationCommands_2021_02_16=Off;RecRoomPlus_DormMirrorButton_2021_03_09=ButtonOn;CurrentContestWinnersCarouselVisibility_2021_04_15=Off;MutualFriends_2021_04_22=On;PlayMenuRRUI_DefaultTab_2021_05_13=Highlight;DefaultNewPlayersToPlayMenu_2021_05_24=On;ShowNewRRPlusIcon_2021_06_01=NewIcon;ParallelNetworkingInitialRoomLoad_2021_06_28=ParallelLoad;ShowNewRRPlusBenefitsPage_2021_06_14=OldPage;WatchStoreHomepageLayout_2021_06_14=OldStoreLayout;NotificationPermissionsExplanationText_2021_06_25=Control;PlayMenuRRUI_TopCreatorsCarousel_2021_09_01=Off;UseSets_2021_08_06=UseSets;RoomSimilarities_2021_10_29=On;ProfileOnClick_2021_04_30=On;RoomRecommendations_2020_05_06=On;FriendImportLogin_2021_09_23=On;RudderStackAnalyticsDestinations_2022_02_10=RudderStackOnly;ObjectModel_EnableForRoom_2022_07_01=Allowed;PlayMenuCarouselOrdering_2021_11_01=PlayMenuCarouselOrdering_1;PlayMenuBanner_2021_11_01=Off;", + "ActiveExperiments": null + }, + { + "Key": "GASamplingRatio", + "Value": "0.02", + "ActiveExperiments": null + }, + { + "Key": "splitTestsAvailable", + "Value": "RoomRecommendations_2020_05_06=On,Off;Curated_Rooms_2020_08_06=Off,On;RecNetImageCacheRefCount_2020_09_18=On,Off;GottaGoFastNUX_2020_09_04=Off,On;Curated_Rooms_Tab_Placement_2020_09_22=First,Second;PlayMenuRRUI_2021_01_11=Off,On;PlayMenuRRUI_HotRoomsCarousel_2021_02_09=Off,On;PlayMenuRRUI_CarouselOrdering_2021_02_09=PlayMenuCarouselOrdering_1,PlayMenuCarouselOrdering_2,PlayMenuCarouselOrdering_3;CreationCommands_2021_02_16=Off,On;RecRoomPlus_DormMirrorButton_2021_03_09=ButtonOn,ButtonOff;CurrentContestWinnersCarouselVisibility_2021_04_15=Off,On;MutualFriends_2021_04_22=Off,On;ProfileOnClick_2021_04_30=Off,On;PlayMenuRRUI_DefaultTab_2021_05_13=Highlight,RRO,Hot;DefaultNewPlayersToPlayMenu_2021_05_24=Off,On;ShowNewRRPlusIcon_2021_06_01=OldIcon,NewIcon;ShowNewRRPlusBenefitsPage_2021_06_14=OldPage,NewPage;WatchStoreHomepageLayout_2021_06_14=OldStoreLayout,NewStoreLayout;NotificationPermissionsExplanationText_2021_06_25=Control,SpecificValueText;ParallelNetworkingInitialRoomLoad_2021_06_28=SequentialLoad,ParallelLoad;UseSets_2021_08_06=IgnoreSets,UseSets;PlayMenuRRUI_TopCreatorsCarousel_2021_09_01=Off,On;FriendImportLogin_2021_09_23=Off,On;Purchase_Campaigns_AB_2021_09_13=Purchase_Campaign_AB_A,Purchase_Campaign_AB_B;Purchase_Campaigns_ABCD_2021_09_13=Purchase_Campaign_ABCD_A,Purchase_Campaign_ABCD_B,Purchase_Campaign_ABCD_C,Purchase_Campaign_ABCD_D;RoomSimilarities_2021_10_29=On,Off;PlayMenuBanner_2021_11_01=Off,On;PlayMenuCarouselOrdering_2021_11_01=PlayMenuCarouselOrdering_1,PlayMenuCarouselOrdering_2,PlayMenuCarouselOrdering_3;RudderStackAnalyticsDestinations_2022_02_10=Disabled,RudderStackOnly,Both;ObjectModel_EnableForRoom_2022_07_01=Disallowed,Allowed;", + "ActiveExperiments": null + }, + { + "Key": "splitTestSegmentProbabilities", + "Value": "{\"RoomRecommendations_2020_05_06\":[{\"SegmentName\":\"On\",\"Probability\":0.25},{\"SegmentName\":\"Off\",\"Probability\":0.75}],\"CurrentContestWinnersCarouselVisibility_2021_04_15\":[{\"SegmentName\":\"Off\",\"Probability\":1.0},{\"SegmentName\":\"On\",\"Probability\":0.0}],\"PlayMenuBanner_2021_11_01\":[{\"SegmentName\":\"Off\",\"Probability\":0.5},{\"SegmentName\":\"On\",\"Probability\":0.5}],\"FriendImportLogin_2021_09_23\":[{\"SegmentName\":\"Off\",\"Probability\":0.5},{\"SegmentName\":\"On\",\"Probability\":0.5}],\"PlayMenuCarouselOrdering_2021_11_01\":[{\"SegmentName\":\"PlayMenuCarouselOrdering_1\",\"Probability\":0.33},{\"SegmentName\":\"PlayMenuCarouselOrdering_2\",\"Probability\":0.33},{\"SegmentName\":\"PlayMenuCarouselOrdering_3\",\"Probability\":0.34}]}", + "ActiveExperiments": null + }, + { + "Key": "Friends.PostGamePromptUnderFriendCount", + "Value": "10", + "ActiveExperiments": null + }, + { + "Key": "Friends.SuggestFriendCodeOnFriendsScreenCount", + "Value": "25", + "ActiveExperiments": null + }, + { + "Key": "runningNetworkTimeout", + "Value": "30", + "ActiveExperiments": null + }, + { + "Key": "loadingNetworkTimeout", + "Value": "180", + "ActiveExperiments": null }, { "Key": "SynchronizedField.RemoveDefaultEntries", - "Value": "true" + "Value": "true", + "ActiveExperiments": null }, { - "Key": "UGC.ScreenSharing.HorizontalResolution", - "Value": "360" + "Key": "Rewards.SelectionTimeout", + "Value": "1800", + "ActiveExperiments": null }, { - "Key": "UGC.ScreenSharing.ImageCompressionQuality", - "Value": "50" + "Key": "Rewards.UseRewardSelection", + "Value": "true", + "ActiveExperiments": null }, { - "Key": "UGC.ScreenSharing.RefreshHz", - "Value": "15" + "Key": "RoomDetails.PhotoRollEnabled", + "Value": "true", + "ActiveExperiments": null }, { - "Key": "VR.ForceVerification", - "Value": "1" + "Key": "Rendering.DisableSrpBatcher", + "Value": "", + "ActiveExperiments": null + }, + { + "Key": "Backtrace.config", + "Value": "0|0.05|0|20|50|1|0|0|1000", + "ActiveExperiments": null + }, + { + "Key": "Backtrace.enabledLikelihood", + "Value": "1.0|1.0|1.0|1.0|1.0|1.0|1.0|1.0", + "ActiveExperiments": null + }, + { + "Key": "RoomScaleMotionCheatDetector.MinHmdSpeedAboveTriggerCount", + "Value": "6", + "ActiveExperiments": null + }, + { + "Key": "RoomScaleMotionCheatDetector.ShouldBootToDormWhenDetected.PlayStation", + "Value": "false", + "ActiveExperiments": null + }, + { + "Key": "RoomScaleMotionCheatDetector.ShouldBootToDormWhenDetected.Steam", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "RoomScaleMotionCheatDetector.ShouldBootToDormWhenDetected.Oculus", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "PlayMenuCarouselOrdering_3", + "Value": "hotrooms=14;new=13;recroomoriginals=12;continueplaying=11;myfavorites=10;friendsplaying=9;recommended=8;mysubscriptions=7;staffcurated=6;featured=5;myclubhouses=4;myevents=3;topcreators=2;discoverability=1;hiddenworldscontest=0", + "ActiveExperiments": null + }, + { + "Key": "PlayMenuCarouselOrdering_2", + "Value": "continueplaying=14;hotrooms=13;new=12;recroomoriginals=11;myfavorites=10;friendsplaying=9;recommended=8;mysubscriptions=7;staffcurated=6;featured=5;myclubhouses=4;myevents=3;topcreators=2;discoverability=1;hiddenworldscontest=0", + "ActiveExperiments": null + }, + { + "Key": "PlayMenuCarouselOrdering_1", + "Value": "foryou=25;hotrooms=24;new=23;recroomoriginals=22;continueplaying=21;rising=20;myfavorites=19;friendsplaying=18;topearning=17;mysubscriptions=16;earnroomcurrency_algo=14;roleplay_algoendpoint=13;casual_algoendpoint=12;horror_algoendpoint=11;battle_algoendpoint=10;explore_algoendpoint=9;quests_algoendpoint=8;hangout_algoendpoint=7;inkshowcase=6;featured=5", + "ActiveExperiments": "discovery_2024q1_dynamic_featured_rooms\r\ndiscovery_ordering_update_to_server_endpoint" + }, + { + "Key": "Backtrace.versionRegex", + "Value": ".*", + "ActiveExperiments": null + }, + { + "Key": "Backtrace.messageRegex", + "Value": "^Cannot set the parent of the GameObject .* while its new parent|^\\\u003E\\x2010x\\:\\x20|\\'LabelTheme\\' contains missing PaletteTheme reference on", + "ActiveExperiments": null + }, + { + "Key": "RoomScaleMotionCheatDetector.MaxAllowedAverageHmdSpeed", + "Value": "3", + "ActiveExperiments": null + }, + { + "Key": "RoomScaleMotionCheatDetector.MeasurementPeriodInSeconds", + "Value": "1", + "ActiveExperiments": null + }, + { + "Key": "RoomScaleMotionCheatDetector.TriggerHmdSpeed", + "Value": "3", + "ActiveExperiments": null + }, + { + "Key": "GDK_Enable_RRPlus", + "Value": "false", + "ActiveExperiments": null + }, + { + "Key": "Door.StuntRunner.Title", + "Value": "COMMUNITY", + "ActiveExperiments": null + }, + { + "Key": "Door.StuntRunner.Query", + "Value": "#stuntrunner #community", + "ActiveExperiments": null + }, + { + "Key": "UGC.EnableRRUIConfigMenu", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "Growth.EnableProfilePhoneButton", + "Value": "false", + "ActiveExperiments": null + }, + { + "Key": "Growth.FriendFestPromosActive", + "Value": "false", + "ActiveExperiments": null + }, + { + "Key": "Backtrace.stopTimeUTC", + "Value": "2022-09-28 23:55", + "ActiveExperiments": null + }, + { + "Key": "OldStoreLayout", + "Value": "banner=12;storecampaigns=11;tokenpack=10;allskus=9;hotitem=8;hotinvention=7;newitem=6;mysubscriptioninvention=5;rrplusitem=4;fivestaritem=3;skinsitem=2;hairdyeitem=1;", + "ActiveExperiments": null + }, + { + "Key": "NewStoreLayout", + "Value": "banner=9;hotitem=7;hotinvention=8;newitem=6;mysubscriptioninvention=5;rrplusitem=4;fivestaritem=3;skinsitem=2;hairdyeitem=1;", + "ActiveExperiments": null + }, + { + "Key": "UGC.ForbiddenSavedSpawnableTools", + "Value": "", + "ActiveExperiments": null + }, + { + "Key": "MobileNotifications.UseFirebasePushNotifications", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "UGC.MaxChipsVisible", + "Value": "1000", + "ActiveExperiments": null, + "StartTime": "2021-07-21T23:50:00Z" + }, + { + "Key": "UGC.MaxChipsUnculled", + "Value": "500", + "ActiveExperiments": null, + "StartTime": "2021-07-21T23:51:23Z" + }, + { + "Key": "MagicDoor.NewDestinationText", + "Value": "Magic Sex", + "ActiveExperiments": null, + "StartTime": "2021-07-21T23:58:09Z" + }, + { + "Key": "UGC.Persistence.Enabled", + "Value": "true", + "ActiveExperiments": null, + "StartTime": "2021-07-22T00:11:16Z" + }, + { + "Key": "UGC.Persistence.AutosaveIntervalSeconds", + "Value": "300", + "ActiveExperiments": null, + "StartTime": "2021-07-22T00:13:54Z" + }, + { + "Key": "MagicDoor.DestinationRefreshingText", + "Value": "New Room in", + "ActiveExperiments": null + }, + { + "Key": "CannedChatAnalyticsSampleRate", + "Value": ".25", + "ActiveExperiments": null + }, + { + "Key": "UGC.CV2.CooldownBeforeSubscriptionCheckSeconds", + "Value": "240", + "ActiveExperiments": null + }, + { + "Key": "RRUI.UseRRUIHomeScreen", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "SafePlaySFXAudioSourceSounds", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "UGC.ScreenSharing.EnabledForMultiInstanceEvents", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "UGC.ScreenSharing.CompressionQualityMultiplier", + "Value": "1.0", + "ActiveExperiments": null + }, + { + "Key": "UGC.ScreenSharing.EnableZipCompression", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "UGC.ScreenSharing.MaxFragmentBytes", + "Value": "15360", + "ActiveExperiments": null + }, + { + "Key": "UGC.ScreenSharing.RefreshHzMultiplier", + "Value": "30.0", + "ActiveExperiments": null + }, + { + "Key": "UGC.ScreenSharing.ResolutionMultiplier", + "Value": "1.0", + "ActiveExperiments": null + }, + { + "Key": "BroadcastManager.VoiceRolloffMaxDistance", + "Value": "500", + "ActiveExperiments": null + }, + { + "Key": "BroadcastManager.IsRoomChatBroadcastSupported", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "BroadcastManager.RoomChatMaxMessagesPerTrackingPeriod", + "Value": "1", + "ActiveExperiments": null + }, + { + "Key": "Growth.EnableInfluencerProgram", + "Value": "false", + "ActiveExperiments": null + }, + { + "Key": "Growth.EnableSMSInvites", + "Value": "false", + "ActiveExperiments": null + }, + { + "Key": "MobileNotifications.AndroidPushNotificationsEnabled", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "PlatformNotifications.AndroidPushNotificationsEnabled\t", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "PlatformNotifications.UseFirebasePushNotifications\t", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "PlatformNotifications.ActiveHoursStartLocalTime", + "Value": "9", + "ActiveExperiments": null + }, + { + "Key": "AndroidMobile.runFileWatcher", + "Value": "1", + "ActiveExperiments": null + }, + { + "Key": "AndroidMobile.runHashCheck", + "Value": "1", + "ActiveExperiments": null + }, + { + "Key": "OculusQuest.runHashCheck", + "Value": "1", + "ActiveExperiments": null + }, + { + "Key": "ToxMod.Enabled", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "UGC.CircuitsV2.Limit.Chips", + "Value": "20000", + "ActiveExperiments": null + }, + { + "Key": "UGC.CircuitsV2.Limit.CloudValues", + "Value": "100", + "ActiveExperiments": null + }, + { + "Key": "UGC.CircuitsV2.Limit.CloudValuesAutosaveSeconds", + "Value": "10", + "ActiveExperiments": null + }, + { + "Key": "UGC.CircuitsV2.Limit.Compute", + "Value": "400000", + "ActiveExperiments": null + }, + { + "Key": "UGC.CircuitsV2.Limit.InkPerChip", + "Value": "10", + "ActiveExperiments": null + }, + { + "Key": "UGC.CircuitsV2.Limit.Network", + "Value": "[ { \"NumPlayersForActivation\": 0, \"Bytes\": 3072, \"Rpcs\": 15 }, { \"NumPlayersForActivation\": 13, \"Bytes\": 2048, \"Rpcs\": 10 }, { \"NumPlayersForActivation\": 25, \"Bytes\": 1024, \"Rpcs\": 5 } ]", + "ActiveExperiments": null + }, + { + "Key": "UGC.CircuitsV2.Limit.UnculledChips", + "Value": "500", + "ActiveExperiments": null + }, + { + "Key": "UGC.CircuitsV2.Limit.VisibleChips", + "Value": "4000", + "ActiveExperiments": null + }, + { + "Key": "Growth.Mic_SCO_AccountCreationCutOff", + "Value": "2021-11-10 00:00", + "ActiveExperiments": null + }, + { + "Key": "AndroidMobile.enforceFileWatcher", + "Value": "1", + "ActiveExperiments": null + }, + { + "Key": "AndroidMobile.enforceHashCheck", + "Value": "1", + "ActiveExperiments": null + }, + { + "Key": "OculusQuest.enforceFileWatcher", + "Value": "1", + "ActiveExperiments": null + }, + { + "Key": "OculusQuest.enforceHashCheck", + "Value": "1", + "ActiveExperiments": null + }, + { + "Key": "RRUIRouteChangeSampleRate", + "Value": "0.01", + "ActiveExperiments": null + }, + { + "Key": "PlatformNotifications.AndroidPushNotificationsEnabled", + "Value": "True", + "ActiveExperiments": null + }, + { + "Key": "PlatformNotifications.UseFirebasePushNotifications", + "Value": "True", + "ActiveExperiments": null + }, + { + "Key": "Growth.DeepLinks", + "Value": "[ { \"Link\": \"recroom://testlink\", \"Action\": \"GoToRoom\", \"Data\": { \"RoomName\": \"Festival\" } }, { \"Link\": \"recroom://solus\", \"Action\": \"GoToRoom\", \"Data\": { \"RoomName\": \"TestRoom\" } }, { \"Link\": \"recroom://winterwonderland\", \"Action\": \"GoToRoom\", \"Data\": { \"RoomName\": \"RecHolidayMarket\" } }, { \"Link\": \"recroom://reccenter\", \"Action\": \"GoToRoom\", \"Data\": { \"RoomName\": \"RecCenter\" } } ]", + "ActiveExperiments": null + }, + { + "Key": "UGC.RoomReloadTimeout", + "Value": "30", + "ActiveExperiments": null + }, + { + "Key": "Growth.RoomJackpotAccountCreationCutoff", + "Value": "2022-05-27 00:00", + "ActiveExperiments": null + }, + { + "Key": "Growth.ShowShuffleChip", + "Value": "false", + "ActiveExperiments": null + }, + { + "Key": "Growth.SCO_HasMicTestDependency", + "Value": "false", + "ActiveExperiments": null + }, + { + "Key": "Friendotron_AllowSelfGifting", + "Value": "True", + "ActiveExperiments": null + }, + { + "Key": "Friendotron_MaxUsersPerSession", + "Value": "0", + "ActiveExperiments": null + }, + { + "Key": "Debug.Watchdog.CorruptRoomDetectionProbability", + "Value": "0", + "ActiveExperiments": "msf_2024q2_disable_ugc_corruption_detection", + "StartTime": "2024-06-21T00:00:00Z" + }, + { + "Key": "Debug.Watchdog.CorruptRoomDetectionTimeSeconds", + "Value": "900", + "ActiveExperiments": null + }, + { + "Key": "LogRoomLoadSnapshots", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "RRUI.MaxActiveHiddenPages", + "Value": "5", + "ActiveExperiments": null + }, + { + "Key": "Mitigation.IgnoreSendingRoomUpdatesOnAppQuit", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "Mitigation.DisconnectPhotonOnAppQuit", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "ToxMod.Rooms", + "Value": "^PrideMonth,^RecRoomGallery", + "ActiveExperiments": null + }, + { + "Key": "Mitigation.FixBrokenLobbies", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "Debug.Watchdog.AdditionalLogTraceSizeForLoading", + "Value": "0", + "ActiveExperiments": null + }, + { + "Key": "Debug.AdditionalLogFlags", + "Value": "CircuitsV2Lifecycle", + "ActiveExperiments": null + }, + { + "Key": "Debug.AdditionalTraceFlags", + "Value": "None", + "ActiveExperiments": null + }, + { + "Key": "Debug.Watchdog.AdditionalTraceFlagsForLoading", + "Value": "None", + "ActiveExperiments": null + }, + { + "Key": "Debug.Watchdog.LoadBacktraceProbability", + "Value": "0", + "ActiveExperiments": null + }, + { + "Key": "Debug.Watchdog.LoadBacktraceTimeoutSeconds", + "Value": "0", + "ActiveExperiments": null + }, + { + "Key": "Debug.Watchdog.LoadLogTimesSeconds", + "Value": "[40, 60, 120, 180, 240]", + "ActiveExperiments": null + }, + { + "Key": "Debug.Watchdog.LoadTimeoutSeconds", + "Value": "0", + "ActiveExperiments": null + }, + { + "Key": "Debug.Watchdog.LogLoadComplete", + "Value": "false", + "ActiveExperiments": null + }, + { + "Key": "TerminateLoadForMasterTransition", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "UGC.AllowBetaInvertedTubeCreation", + "Value": "false", + "ActiveExperiments": null + }, + { + "Key": "UGC.AllowNonBetaInvertedTubeCreation", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "MobileHome.ChatEnabled", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "UseRRUICreateScreen", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "Growth.RoomCategorySelectAccountCreationCutoff", + "Value": "2022-06-28 00:00", + "ActiveExperiments": null + }, + { + "Key": "Growth.IsEmailMandatory_Jr", + "Value": "false", + "ActiveExperiments": null + }, + { + "Key": "Growth.IsEmailMandatory_NonJr", + "Value": "false", + "ActiveExperiments": null + }, + { + "Key": "Growth.IsPhoneMandatory_NonJr", + "Value": "false", + "ActiveExperiments": null + }, + { + "Key": "Growth.EmailPromptFrequencyHours", + "Value": "120", + "ActiveExperiments": null + }, + { + "Key": "Debug.TraceProbability", + "Value": "0", + "ActiveExperiments": null + }, + { + "Key": "Voice.UseLegacyUnityAudioOut", + "Value": "false", + "ActiveExperiments": null + }, + { + "Key": "Statsig.Enabled", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "UseRRUIEventsScreen", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "UGC.Shapes.OptimizedCollidersDefaultForExisting", + "Value": "false", + "ActiveExperiments": null + }, + { + "Key": "LeagueOfHeroesEnabled", + "Value": "false", + "ActiveExperiments": null + }, + { + "Key": "UGC.CircuitsV2.DisablePlayerBoardRooms", + "Value": "[]", + "ActiveExperiments": null + }, + { + "Key": "UGC.MakerPen_CreationMode.Default.Screen", + "Value": "Scale", + "ActiveExperiments": null + }, + { + "Key": "RRUI.UseNewProfile", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "PlayerRelationships.NumFriendsWarningThreshold", + "Value": "3000", + "ActiveExperiments": null + }, + { + "Key": "Growth.RoomCategoriesJson", + "Value": "[{ \"Tag\": \"PVP\", \"ImageName\": \"roomCatSelect_pvp.jpg\" }, { \"Tag\": \"Quest\", \"ImageName\": \"roomCatSelect_quest.jpg\" }, { \"Tag\": \"Horror\", \"ImageName\": \"roomCatSelect_horror.jpg\" }, { \"Tag\": \"Hangout\", \"ImageName\": \"roomCatSelect_hangout.jpg\" }, { \"Tag\": \"Art\", \"ImageName\": \"roomCatSelect_art.jpg\" }]", + "ActiveExperiments": null + }, + { + "Key": "Growth.RoomCategorySelect_StraightToRandomRoom_TakeFirstRoom", + "Value": "false", + "ActiveExperiments": null + }, + { + "Key": "Growth.ShowRoomCategorySelectChip", + "Value": "false", + "ActiveExperiments": null + }, + { + "Key": "RecNet.JsonParserType", + "Value": "1", + "ActiveExperiments": null + }, + { + "Key": "NewPlayerChallenges_InventionTower_Screen", + "Value": "InkInc", + "ActiveExperiments": null + }, + { + "Key": "NewPlayerChallenges_InventionTower_VR", + "Value": "InkInc", + "ActiveExperiments": null + }, + { + "Key": "NewPlayerChallenges_LaunchDateTime", + "Value": "03/24/1922 12:00:00 ", + "ActiveExperiments": null + }, + { + "Key": "NewPlayerChallenges_MaxDisplayedFamilies", + "Value": "3", + "ActiveExperiments": null + }, + { + "Key": "Growth.QuickOrientationEnabled", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "AppleMusicPromo.Description", + "Value": "<align="center">Access over 90 million songs, over 30,000 playlists, and original content from your favorite artists all ad-free with Apple Music.</align>", + "ActiveExperiments": null + }, + { + "Key": "AppleMusicPromo.Title", + "Value": "Get up to 2 months of Apple Music free! ", + "ActiveExperiments": null + }, + { + "Key": "AppleMusicPromo.TOC", + "Value": "<size=70%>Code expires on June 30, 2022.<br>This is a promotional code and is not for resale, has no cash value, and will not be replaced if lost or stolen. Valid only for Apple Music in the United States. Requires Apple ID with payment method on file. After promotional period ends, subscription will auto-renew at $9.99/month until cancelled. Payment will be billed to the payment method on file and can be cancelled anytime at least a day before each renewal date at Settings > Apple ID. Terms and Apple Privacy Policy apply; see the applicable terms for your country at https://www.apple.com/legal/internet-services/itunes/ww. Cannot be combined with other offers providing access to the same service. Must be of the minimum age set forth in the subscription registration process for your country and in the country that matches the store front on which you are redeeming the code. Compatible products and services required.<br>Apple Music is a registered trademark of Apple Inc. Apple is not a sponsor of this promotion.</size>", + "ActiveExperiments": null + }, + { + "Key": "RRUI.EnableUIAnchors", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "Growth.MakerPenIntroCreationCutoff", + "Value": "2022-05-11 00:00", + "ActiveExperiments": null + }, + { + "Key": "Growth.MakerPenIntroDormOnly", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "Social.ClubChatEnabled", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "UGC.RoomSavingEnabled", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "Video.MaxVideoDesyncSeconds", + "Value": "3.0", + "ActiveExperiments": null + }, + { + "Key": "Video.PS5IsPlaybackSupported", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "Video.PlaystationIsRemotePlaybackSupported", + "Value": "false", + "ActiveExperiments": null + }, + { + "Key": "Video.IOSSeekCooldownSeconds", + "Value": "2.0", + "ActiveExperiments": null + }, + { + "Key": "NewPlayerChallenges_MaxPlayerPromptCount", + "Value": "3", + "ActiveExperiments": null + }, + { + "Key": "Social.TimedFlowSampleRate", + "Value": "0.05", + "ActiveExperiments": null + }, + { + "Key": "Debug.Photon.ConnectionFailure.Exception.SampleRate", + "Value": "0.01", + "ActiveExperiments": null + }, + { + "Key": "AutoClickerCheatDetector.Enabled", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "AutoClickerCheatDetector.NumberOfActionsAllowed_ScreenPress", + "Value": "3000", + "ActiveExperiments": null + }, + { + "Key": "AutoClickerCheatDetector.NumberOfActionsAllowed_TriggerPress", + "Value": "3000", + "ActiveExperiments": null, + "StartTime": "2022-05-18T15:31:33Z" + }, + { + "Key": "RoomJoinV2.Detailed", + "Value": "1", + "ActiveExperiments": null + }, + { + "Key": "PhotonClient.Detailed", + "Value": "0.05", + "ActiveExperiments": null, + "StartTime": "2022-05-26T16:37:57Z" + }, + { + "Key": "RoomJoinV2.PathDepth", + "Value": "999", + "ActiveExperiments": null, + "StartTime": "2023-06-01T16:53:00Z" + }, + { + "Key": "Growth.RoomJackpotPlaylists_Screens", + "Value": "[ { \"PlaylistType\": \"HotRooms\", \"DisplayType\": \"Always\", \"ShuffleType\": \"MixWithOthersAndShuffle\", \"MaxTopRoomsCountLimit\": 20 }, { \"PlaylistType\": \"RRO\", \"DisplayType\": \"Always\", \"ShuffleType\": \"MixWithOthersAndShuffle\", \"MaxTopRoomsCountLimit\": 5 }, { \"PlaylistType\": \"Featured\", \"DisplayType\": \"Always\", \"ShuffleType\": \"MixWithOthersAndShuffle\", \"MaxTopRoomsCountLimit\": 5 } ]", + "ActiveExperiments": null + }, + { + "Key": "Growth.RoomJackpotPlaylists_Touch", + "Value": "[ { \"PlaylistType\": \"HotRooms\", \"DisplayType\": \"Always\", \"ShuffleType\": \"MixWithOthersAndShuffle\", \"MaxTopRoomsCountLimit\": 20 }, { \"PlaylistType\": \"RRO\", \"DisplayType\": \"Always\", \"ShuffleType\": \"MixWithOthersAndShuffle\", \"MaxTopRoomsCountLimit\": 5 }, { \"PlaylistType\": \"Featured\", \"DisplayType\": \"Always\", \"ShuffleType\": \"MixWithOthersAndShuffle\", \"MaxTopRoomsCountLimit\": 5 } ]", + "ActiveExperiments": null + }, + { + "Key": "Growth.RoomJackpotPlaylists_VR", + "Value": "[ { \"PlaylistType\": \"HotRooms\", \"DisplayType\": \"Always\", \"ShuffleType\": \"MixWithOthersAndShuffle\", \"MaxTopRoomsCountLimit\": 20 }, { \"PlaylistType\": \"RRO\", \"DisplayType\": \"Always\", \"ShuffleType\": \"MixWithOthersAndShuffle\", \"MaxTopRoomsCountLimit\": 5 }, { \"PlaylistType\": \"Featured\", \"DisplayType\": \"Always\", \"ShuffleType\": \"MixWithOthersAndShuffle\", \"MaxTopRoomsCountLimit\": 5 } ]", + "ActiveExperiments": null + }, + { + "Key": "Growth.ForceQuickOrientationCreationCutoff", + "Value": "9999-06-17 00:00", + "ActiveExperiments": null + }, + { + "Key": "UGC.DetailedRoomLoadLogs", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "RoomLoad.BufferedEventTimeoutSeconds", + "Value": "180", + "ActiveExperiments": null + }, + { + "Key": "RoomLoad.PostDownloadTimeoutSeconds", + "Value": "240", + "ActiveExperiments": null + }, + { + "Key": "UGC.DetailedRoomLoadLogsForDevs", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "CustomAvatarItems.CustomShirtId", + "Value": "2184", + "ActiveExperiments": null + }, + { + "Key": "UGC.LoadingScreenProgressBar", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "UGC.SceneSpawnManager.TotalPlayerSpawnTimeoutSeconds", + "Value": "150", + "ActiveExperiments": null, + "StartTime": "2022-07-01T16:54:59Z" + }, + { + "Key": "Experience.GameLogTool.HideForJunior", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "Experience.GameLogTool.HideTool", + "Value": "false", + "ActiveExperiments": null + }, + { + "Key": "Experience.GameLogTool.UseBugWording", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "Social.DisablePhotoRollPrintingWhenMakerPenDisabled", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "RoomLoad.BlockedRoomNamesOnLowMemoryDevices", + "Value": "0Project29,Showdown", + "ActiveExperiments": null + }, + { + "Key": "UGC.CircuitsV2.SnapshotThresholdBytes", + "Value": "204000", + "ActiveExperiments": null + }, + { + "Key": "RoomLoad.DownloadAssetBundleTimeoutSeconds", + "Value": "900", + "ActiveExperiments": null + }, + { + "Key": "RoomLoad.DownloadTimeoutSeconds", + "Value": "900", + "ActiveExperiments": null + }, + { + "Key": "Growth.SupportInfluencerConfirmMessage", + "Value": "When you support have sex with a player, 7.5% of the cum you make in the Rec Room will go to the person you support. Your support lasts for 45 days until it needs to be renewed. You can fuck at any time.", + "ActiveExperiments": null + }, + { + "Key": "ToxMod.EnableUGCRoomVoiceModeration", + "Value": "False", + "ActiveExperiments": null + }, + { + "Key": "RoomJoinV2.AlwaysLogPaths", + "Value": "StackTimer;StackTimer.ConnectToRoomAndRunLoadLogic;StackTimer.ConnectToRoomAndRunLoadLogic.RunRoomLoadLogic;StackTimer.ConnectToRoomAndRunLoadLogic.RunRoomLoadLogic.InitialRoomLoad;StackTimer.ConnectToRoomAndRunLoadLogic.RunRoomLoadLogic.InitialRoomLoad.LoadRoomLocal;StackTimer.ConnectToRoomAndRunLoadLogic.RunRoomLoadLogic.InitialRoomLoad.LoadRoomLocal.Downloading Data;StackTimer.ConnectToRoomAndRunLoadLogic.RunRoomLoadLogic.InitialRoomLoad.LoadRoomLocal.Downloading Data.AssetBundle_Download", + "ActiveExperiments": null + }, + { + "Key": "PlayMenuCuratedCarouselsMap", + "Value": "inkincroomhighlights=73682475;topearning=65380152;inkshowcase=52548973;quest=17859348;battle=17859349;horror=17859352;casualplay=17859347;roleplay=17859346;hangout=17859350;explore=17859351", + "ActiveExperiments": null + }, + { + "Key": "RoomJoinV2.TimeClampMax", + "Value": "900", + "ActiveExperiments": null + }, + { + "Key": "RRUI.PlayHittingEndsSFX", + "Value": "false", + "ActiveExperiments": null + }, + { + "Key": "MetaHardware.ApplyJuniorRestrictions", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "Growth.ForcedPostOrientationCategorySelectDuration", + "Value": "1440", + "ActiveExperiments": "lifecycle_q4_room_category_time_durations" + }, + { + "Key": "Econ.EnableTryingBundleItems", + "Value": "true", + "ActiveExperiments": "econ_try_bundle_items" + }, + { + "Key": "UGC.ObjectModel.Allowed", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "ProgressionEvents.EventInfoFirstPanelBody", + "Value": "Collecting Science Cores in highlighted Rooms will award XP. Some rooms now have multiple Cores! Once you collect all Cores of one color, new ones may appear. You can also earn XP in public rooms or by collecting Cores with friends.", + "ActiveExperiments": null + }, + { + "Key": "ProgressionEvents.EventInfoFirstPanelTitle", + "Value": "Collect Science Cores for XP!", + "ActiveExperiments": null + }, + { + "Key": "ProgressionEvents.TutorialFirstIntro_PressFeaturedRoomButton_NewWatch", + "Value": "We need help... Collect the Core in ^TheScienceDepartment for more information!", + "ActiveExperiments": null + }, + { + "Key": "ProgressionEvents.TutorialFirstIntro_PressChallengesButton_OldWatch", + "Value": "We need help...", + "ActiveExperiments": null + }, + { + "Key": "ProgressionEvents.EventInfoSecondPanelBody", + "Value": "Use the Boost to level up faster! The Boost will multiply the XP you have gained from recent time spent in Rec Room. 900 XP is the max amount that can be gained by purchasing the Boost.", + "ActiveExperiments": null + }, + { + "Key": "ProgressionEvents.EventInfoSecondPanelTitle", + "Value": "Speed Up Progress", + "ActiveExperiments": null + }, + { + "Key": "ProgressionEvents.TutorialFirstIntro_PressTodaysRoom_OldWatch", + "Value": "Our radars suggest that there is a Core in this room. Can you find it?", + "ActiveExperiments": null + }, + { + "Key": "ProgressionEvents.TutorialReward_PressChallengesButton_NewWatch", + "Value": "We'll add XP to your balance for each Core you collect. This XP doesn't count towards your regular XP limits! You've proven your competence, let us share more details!", + "ActiveExperiments": null + }, + { + "Key": "ProgressionEvents.EventInfoThirdPanelBody", + "Value": "Use Event Credits to unlock special offers in ^TheScienceDepartment room.\r\n\r\nEvent Credits can be used until 24 hours after the event ends.", + "ActiveExperiments": null + }, + { + "Key": "ProgressionEvents.EventInfoThirdPanelTitle", + "Value": "Spend Credits", + "ActiveExperiments": null + }, + { + "Key": "ProgressionEvents.ExplorePageBanner_DescriptionText", + "Value": "Collect ALL the Cores!", + "ActiveExperiments": null + }, + { + "Key": "ProgressionEvents.HoursBeforeShowingBackupTutorial", + "Value": "72", + "ActiveExperiments": null + }, + { + "Key": "ProgressionEvents.HubRoomName", + "Value": "TheScienceDepartment", + "ActiveExperiments": null + }, + { + "Key": "ProgressionEvents.ProgressionEventCurrencyName", + "Value": "Credit", + "ActiveExperiments": null + }, + { + "Key": "ProgressionEvents.MinimumAccountAgeToShowTutorial", + "Value": "3", + "ActiveExperiments": null + }, + { + "Key": "ProgressionEvents.RoomCarousel_PremiumRoomsHeader", + "Value": "Bonus Rooms - Science Exo Arms (Restoration)*|Bonus Rooms - Science Chainsaw (Restoration)*|Bonus Rooms - Vigilante Utility Belt (White)", + "ActiveExperiments": null + }, + { + "Key": "ProgressionEvents.RoomCarousel_RegularRoomsHeader", + "Value": "Restoration Rooms: Science Cores located here!", + "ActiveExperiments": null + }, + { + "Key": "ProgressionEvents.MainPage_EventEnded_SpendCurrencyBeforeTimeRunsOutPrompt", + "Value": "Spend your credits in ^TheScienceDepartment before time runs out.", + "ActiveExperiments": null + }, + { + "Key": "ProgressionEvents.MainPage_EventEnded_SpendCurrencyButtonText", + "Value": "Spend Credits", + "ActiveExperiments": null + }, + { + "Key": "ProgressionEvents.TutorialReward_PressViewAllRoomsButton_NewWatch\t", + "Value": "There are more Power Cores across the Room-i-verse in rooms created by your fellow creators.\r\n\r\n\r\nAs we discover the locations of more Power Cores, we'll add them to your list here. Don't forget to check back regularly!", + "ActiveExperiments": null + }, + { + "Key": "ProgressionEvents.TutorialReward_ClaimReward_NewWatch", + "Value": "You can collect event rewards here! \r\n\r\nCredits can be used to unlock items in the Science Department.", + "ActiveExperiments": null + }, + { + "Key": "ProgressionEvents.TutorialRewardBackup_PressChallengesButton_NewWatch\t", + "Value": "We'll add XP to your balance for each Power Core you collect. This XP doesn't count towards your regular XP limits!\r\n\r\nYou've proven your competence, let us share more details!", + "ActiveExperiments": null + }, + { + "Key": "ProgressionEvents.TutorialRewardBackup_PressViewAllRoomsButton_NewWatch", + "Value": "There are more Power Cores across the Room-i-verse in rooms created by your fellow creators.\r\n\r\n\r\nAs we discover the locations of more Power Cores, we'll add them to your list here. Don't forget to check back regularly!", + "ActiveExperiments": null + }, + { + "Key": "ProgressionEvents.TutorialRewardBackup_PressBackButton_NewWatch", + "Value": "As a thank you, we have special offers for you in the Science Department!", + "ActiveExperiments": null + }, + { + "Key": "ProgressionEvents.TutorialRewardBackup_ClaimReward_NewWatch\t", + "Value": "You can collect event rewards here!\r\n\r\nCredits can be used to unlock items in the Science Department.", + "ActiveExperiments": null + }, + { + "Key": "ProgressionEvents.TutorialBackup_PressChallengesButton_NewWatch", + "Value": "Psst... there are Cores for you to find.\r\n\r\nWe could use your help!", + "ActiveExperiments": null + }, + { + "Key": "ProgressionEvents.TutorialBackup_PressTodaysRoomButton_NewWatch", + "Value": "Our radars suggest that there is a Core in this room. Can you find it?", + "ActiveExperiments": null + }, + { + "Key": "ProgressionEvents.TutorialReward_PressBackButton_NewWatch", + "Value": "As a thank you, we have special offers for you in the Science Department!", + "ActiveExperiments": null + }, + { + "Key": "ProgressionEvents.MainPage_EventEnded_SpendCurrencyBonusRewardsText", + "Value": "Make sure to collect and spend all of your credits before the event ends!", + "ActiveExperiments": null + }, + { + "Key": "UGC.InventionSpawningEnabled", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "AntiHile.DC", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "UGC.GunHandle.ShowReloadOnFullAmmo", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "Econ.ShowPartiallyOwnedBundles", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "CCT.RRCA.CampusRoomId", + "Value": "77471693", + "ActiveExperiments": null + }, + { + "Key": "CCT.RRCA.TutorialRooms.Building", + "Value": "688282368967907215,399286008370399908,2767464404937978317", + "ActiveExperiments": null + }, + { + "Key": "CCT.RRCA.TutorialRooms.Circuits", + "Value": "5533753109055429437,367323597097954194,6805637954817370678", + "ActiveExperiments": null + }, + { + "Key": "CCT.RRCA.TutorialRooms.Creation", + "Value": "", + "ActiveExperiments": null + }, + { + "Key": "UGC.Roles.SetPlayerRolesAnalyticsThresholdMs", + "Value": "-1.0", + "ActiveExperiments": null + }, + { + "Key": "CCT.RRCA.TutorialRooms.LearnToCreate", + "Value": "3406864552519591337,688282368967907215,5533753109055429437,5894707241498355365,2331615644215560745", + "ActiveExperiments": null + }, + { + "Key": "Lifecycle.PlayMenuNegativeTestsCutoff", + "Value": "2018-01-01 00:00", + "ActiveExperiments": null + }, + { + "Key": "UGC.EnableLocText", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "RoomLoad.PreDownloadTimeoutSeconds", + "Value": "120", + "ActiveExperiments": null + }, + { + "Key": "UGC.CircuitsV2.Analytics.HeartbeatInterval", + "Value": "0", + "ActiveExperiments": null + }, + { + "Key": "DataCollection.OneTimeData.Enabled", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "Backtrace.deobfuscationRate", + "Value": "1.0", + "ActiveExperiments": null + }, + { + "Key": "ProgressionEvents.GiftDropIdToRoomIdMapping", + "Value": "4953=76890764", + "ActiveExperiments": null + }, + { + "Key": "ProgressionEvents.RoomCarousel_PremiumRoomsDesc", + "Value": "Unlock with Science Exo Arms (Restoration)*!|Unlock with Science Chainsaw (Restoration)*!|Unlock with Vigilante Utility Belt (White)!", + "ActiveExperiments": null + }, + { + "Key": "ProgressionEvents.RoomCarousel_RegularRoomsDesc", + "Value": "Collect Science Cores in these Rooms!", + "ActiveExperiments": null + }, + { + "Key": "Lifecycle.PlayMenuCardSizesAccountCreationCutoff", + "Value": "2017-01-01 00:01", + "ActiveExperiments": null + }, + { + "Key": "ShowPurchasePromptCV2.RateLimitMaxInvocations", + "Value": "10", + "ActiveExperiments": null + }, + { + "Key": "ShowPurchasePromptCV2.RateLimitTimeInverval\t", + "Value": "60", + "ActiveExperiments": null + }, + { + "Key": "CameraFade.TimeoutSeconds", + "Value": "60", + "ActiveExperiments": null + }, + { + "Key": "CameraFade.TimeoutTrackingEnabled\t", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "Experience.iOSQueuedBgTaskDelay", + "Value": "-1", + "ActiveExperiments": "mobile_home_2023q3_offline_dorm" + }, + { + "Key": "AntiHile.LPD", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "Gamesight.PauseGamesightEvents", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "Lifecycle.PlayMenuCarouselHighlighting", + "Value": "all=Favorites:highlight_scale_75\t", + "ActiveExperiments": "discovery_2024q1_dynamic_featured_rooms" + }, + { + "Key": "Lifecycle.PlayMenuCarouselHighlightingCutoff", + "Value": "2017-01-01 00:01", + "ActiveExperiments": null + }, + { + "Key": "MatchmakingUI.BlockedRooms", + "Value": "[170126]", + "ActiveExperiments": null + }, + { + "Key": "MatchmakingUI.EligibleRooms", + "Value": "", + "ActiveExperiments": null + }, + { + "Key": "MatchmakingUI.FailedStateContinuePlayingButtonText", + "Value": "Continue Playing", + "ActiveExperiments": null + }, + { + "Key": "MatchmakingUI.FailedStateInviteFriendsButtonText", + "Value": "Invite Friends", + "ActiveExperiments": null + }, + { + "Key": "MatchmakingUI.FailedStateSubtitle", + "Value": "Keep playing while we continue searching in the background...", + "ActiveExperiments": null + }, + { + "Key": "MatchmakingUI.FailedStateTitle", + "Value": "This is taking longer than expected!", + "ActiveExperiments": null + }, + { + "Key": "MatchmakingUI.MinRoomSize", + "Value": "2", + "ActiveExperiments": null + }, + { + "Key": "MatchmakingUI.ShowIfEveryoneLeaves", + "Value": "true", + "ActiveExperiments": "lifecycle_2023q1_matchmaking_toast" + }, + { + "Key": "MatchmakingUI.SucceededStateAutoDismissTimeout", + "Value": "5", + "ActiveExperiments": null + }, + { + "Key": "MatchmakingUI.SucceededStateTitle", + "Value": "Another player has joined you!", + "ActiveExperiments": null + }, + { + "Key": "MatchmakingUI.WaitingStateCountdown", + "Value": "10", + "ActiveExperiments": null + }, + { + "Key": "MatchmakingUI.WaitingStateSubtitle", + "Value": "Scouting the Room-i-verse...", + "ActiveExperiments": null + }, + { + "Key": "MatchmakingUI.WaitingStateTitle", + "Value": "Finding Players To Join You", + "ActiveExperiments": null + }, + { + "Key": "MatchmakingUI.HideWhileInParty", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "UGC.MaxInkResources", + "Value": "900000", + "ActiveExperiments": null + }, + { + "Key": "Lifecycle.InRoomChat.AccountCreationCutoff", + "Value": "2023-06-06 07:10", + "ActiveExperiments": null + }, + { + "Key": "Lifecycle.NoOrientation.Platforms", + "Value": "mobile", + "ActiveExperiments": null + }, + { + "Key": "Lifecycle.NoOrientation.DestinationRoomId", + "Value": "170126", + "ActiveExperiments": null + }, + { + "Key": "Lifecycle.NoOrientation.AccountCreationCutoff", + "Value": "9999-06-06 15:30", + "ActiveExperiments": null + }, + { + "Key": "ProgressionEvents.UpsellDialogText", + "Value": "You'll need an item to find the research core in this room.", + "ActiveExperiments": null + }, + { + "Key": "PlayMenuRoomBanner", + "Value": "", + "ActiveExperiments": "discovery_2023q3_mitm_entrypoint_holdout", + "StartTime": "2023-08-17T18:00:00Z" + }, + { + "Key": "lifecycle.room_feedback.daily_cap", + "Value": "2", + "ActiveExperiments": "lifecycle_2023q3_room_feedback_response_scale\r\nlifecycle_2023q2_room_feedback" + }, + { + "Key": "lifecycle.room_feedback.hide_skip_button_when_rating_selected", + "Value": "false", + "ActiveExperiments": null + }, + { + "Key": "lifecycle.room_feedback.negative_canned_options", + "Value": "[ \"Negative Players\", \"Bugs/Technical Issues\", \"Poor Experience\", \"No Other Players\", \"Cheating\", \"Inappropriate Content\" ]", + "ActiveExperiments": "lifecycle_2023q2_room_feedback\r\n" + }, + { + "Key": "lifecycle.room_feedback.negative_canned_question_text", + "Value": "Select one or more issues (Up to 3)", + "ActiveExperiments": "lifecycle_2023q2_room_feedback" + }, + { + "Key": "lifecycle.room_feedback.negative_rating_text", + "Value": "Dislike", + "ActiveExperiments": null + }, + { + "Key": "lifecycle.room_feedback.neutral_canned_options", + "Value": "[ \"Negative Players\", \"Bugs/Technical Issues\", \"Poor Experience\", \"No Other Players\", \"Cheating\", \"Inappropriate Content\" ]", + "ActiveExperiments": null + }, + { + "Key": "lifecycle.room_feedback.neutral_canned_question_text", + "Value": "Select one or more issues (Up to 3)", + "ActiveExperiments": "lifecycle_2023q3_room_feedback_response_scale\r\nlifecycle_2023q2_room_feedback\r\n" + }, + { + "Key": "lifecycle.room_feedback.neutral_rating_text", + "Value": "Like", + "ActiveExperiments": null + }, + { + "Key": "lifecycle.room_feedback.number_of_ratings", + "Value": "2", + "ActiveExperiments": "lifecycle_2023q3_room_feedback_response_scale" + }, + { + "Key": "lifecycle.room_feedback.playlists", + "Value": "{17859340 : 0}", + "ActiveExperiments": null + }, + { + "Key": "lifecycle.room_feedback.positive_canned_options", + "Value": "[ \"Fun With Friends\", \"Awesome Visuals\", \"Immersive Experience\", \"Exciting Events\", \"Amazing Gameplay\", \"Very Challenging\", \"Cool Soundtrack\", \"Unique Adventure\" ]", + "ActiveExperiments": "lifecycle_2023q2_room_feedback\r\n" + }, + { + "Key": "lifecycle.room_feedback.positive_canned_question_text", + "Value": "What did you LOVE about it? (Up to 3)", + "ActiveExperiments": "lifecycle_2023q2_room_feedback\r\n" + }, + { + "Key": "lifecycle.room_feedback.positive_rating_text", + "Value": "Love", + "ActiveExperiments": null + }, + { + "Key": "lifecycle.room_feedback.reverse_ratings", + "Value": "false", + "ActiveExperiments": null + }, + { + "Key": "lifecycle.room_feedback.show_skip_button_on_thank_you_page", + "Value": "false", + "ActiveExperiments": null + }, + { + "Key": "lifecycle.room_feedback.survey_question", + "Value": "What do you think of the quality of ^{0}?", + "ActiveExperiments": "lifecycle_2023q2_room_feedback" + }, + { + "Key": "lifecycle.room_feedback.title_first_line_text", + "Value": "👋 We're listening!", + "ActiveExperiments": "lifecycle_2023q2_room_feedback" + }, + { + "Key": "UGC.LimitsV2.UI.Triangles.Max", + "Value": "500000", + "ActiveExperiments": null + }, + { + "Key": "RoomJoinV2.SuccessTiming", + "Value": "1", + "ActiveExperiments": null + }, + { + "Key": "RoomJoinV2.FailureTracking", + "Value": "1", + "ActiveExperiments": null + }, + { + "Key": "MobileHome.DiscoverySections", + "Value": "[{\"title\":\"Friends\",\"isHorizontal\":true,\"source\":\"friends\"},{\"title\":\"Continue Playing\",\"isHorizontal\":true,\"source\":\"recent\"},{\"title\":\"Rec Room Originals\",\"isHorizontal\":true,\"source\":\"hotList\",\"sourceMetadata\":\"rro\"},{\"title\":\"Hot List\",\"isHorizontal\":false,\"source\":\"hotList\"}]", + "ActiveExperiments": null + }, + { + "Key": "UseNewPhotonAuthToken", + "Value": "false", + "ActiveExperiments": "server_use_new_photon_auth_token" + }, + { + "Key": "Player.ShouldWaitForCameraFirstSpawn", + "Value": "false", + "ActiveExperiments": null + }, + { + "Key": "Player.WaitForLoadingScreen", + "Value": "false", + "ActiveExperiments": null + }, + { + "Key": "RoomLoad.RoomLoadCameraTimeoutSeconds", + "Value": "45", + "ActiveExperiments": null + }, + { + "Key": "Lifecycle.PlayMenu.RoomCollectionsCarousel.AccountCreationCutoff", + "Value": "2017-01-01 00:00", + "ActiveExperiments": null + }, + { + "Key": "Lifecycle.PlayMenu.RoomCollectionsCarousel.CardCountLimit", + "Value": "0", + "ActiveExperiments": "lifecycle_2023q2_play_menu_categories_3_1_v2" + }, + { + "Key": "Lifecycle.PlayMenu.RoomCollectionsCarousel.Enabled", + "Value": "false", + "ActiveExperiments": "lifecycle_2023q2_play_menu_categories_3_1_v2" + }, + { + "Key": "Lifecycle.PlayMenu.RoomCollectionsCarousel.Theme", + "Value": "#recroomoriginal=bg#EF6825,txt#FFFFFF;#action=bg#DE8C90,txt#FFFFFF;#art=bg#75B0BD,txt#FFFFFF;#backrooms=bg#5F4949,txt#FFFFFF;#beta=bg#8689A7,txt#FFFFFF;#fnaf=bg#C1BF6C,txt#FFFFFF;#fun=bg#DE9812,txt#FFFFFF;#game=bg#4191A7,txt#FFFFFF;#hangout=bg#8F9953,txt#FFFFFF;#hiddenworlds=bg#B4A1D2,txt#FFFFFF;#horror=bg#7B4257,txt#FFFFFF;#military=bg#5C5F49,txt#FFFFFF;#obby=bg#CF7293,txt#FFFFFF;#parkour=bg#EB7B05,txt#FFFFFF;#playtime=bg#EF9C73,txt#FFFFFF;#playtime_friend=bg#579255,txt#FFFFFF;#playtime_visit=bg#895129,txt#FFFFFF;#prettycolors=bg#BD6060,txt#FFFFFF;#puzzle=bg#526FBA,txt#FFFFFF;#pvp=bg#DA9BC4,txt#FFFFFF;#quest=bg#C77337,txt#FFFFFF;#roleplay=bg#89AEDA,txt#FFFFFF;#rp=bg#A78480,txt#FFFFFF;#rrstudio=bg#4E548C,txt#FFFFFF;#scary=bg#786C9B,txt#FFFFFF;#simulator=bg#899AC5,txt#FFFFFF;#story=bg#75BDAB,txt#FFFFFF;#treasurehunt=bg#EBB64E,txt#FFFFFF;#tutorial=bg#7F96A4,txt#FFFFFF;#wonderland=bg#B0608C,txt#FFFFFF;#3dcharades=bg#BE86DB,txt#FFFFFF;#janrrmonthly=bg#469068,txt#FFFFFF;#febrrmonthly=bg#469068,txt#FFFFFF;#marrrmonthly=bg#469068,txt#FFFFFF;#aprrrmonthly=bg#469068,txt#FFFFFF;#mayrrmonthly=bg#469068,txt#FFFFFF;#junrrmonthly=bg#469068,txt#FFFFFF;#julrrmonthly=bg#469068,txt#FFFFFF;#augrrmonthly=bg#469068,txt#FFFFFF;#seprrmonthly=bg#469068,txt#FFFFFF;#octrrmonthly=bg#469068,txt#FFFFFF;#novrrmonthly=bg#469068,txt#FFFFFF;#decrrmonthly=bg#469068,txt#FFFFFF;#januaryrrmonthly=bg#469068,txt#FFFFFF;#februaryrrmonthly=bg#469068,txt#FFFFFF;#marchrrmonthly=bg#469068,txt#FFFFFF;#aprilrrmonthly=bg#469068,txt#FFFFFF;#junerrmonthly=bg#469068,txt#FFFFFF;#julyrrmonthly=bg#469068,txt#FFFFFF;#augustrrmonthly=bg#469068,txt#FFFFFF;#septemberrrmonthly=bg#469068,txt#FFFFFF;#octoberrrmonthly=bg#469068,txt#FFFFFF;#novemberrrmonthly=bg#469068,txt#FFFFFF;#decemberrrmonthly=bg#469068,txt#FFFFFF;#mayrrrmonthly=bg#469068,txt#FFFFFF;#septrrmonthly=bg#469068,txt#FFFFFF", + "ActiveExperiments": null + }, + { + "Key": "Lifecycle.PlayMenu.TrendingTags.WrappableNames", + "Value": "#recroomoriginal = #Rec[]Room[]Original\r\n#beta = #Beta\r\n#hangout = #hang[]out\r\n#hiddenworlds = #hidden[]worlds\r\n#3dcharades = #3d[]charades\r\n#prettycolors = #pretty[]colors\r\n#treasurehunt = #treasure[]​hunt\r\n#wonderland = #wonder[]land\r\n#roleplay = #role[]play\r\n#playtime = #play[]time\r\n#rrstudio = #RR[]studio\r\n#hangout = #hang[]out\r\n#parkour = #parkour\r\n#military = #mili[]tary\r\n#playtime_visit = #play[]time_[]visit\r\n#playtime_friend = #play[]time_[]friend\r\n#backrooms = #back[]rooms\r\n#simulator = #simu[]lator\r\n#janrrmonthly = #jan[]RR[]monthly\r\n#febrrmonthly = #feb[]RR[]monthly\r\n#marrrmonthly = #mar[]RR[]monthly\r\n#aprrrmonthly = #apr[]RR[]monthly\r\n#mayrrmonthly = #may[]RR[]monthly\r\n#junrrmonthly = #jun[]RR[]monthly\r\n#julrrmonthly = #jul[]RR[]monthly\r\n#augrrmonthly = #aug[]RR[]monthly\r\n#seprrmonthly = #sep[]RR[]monthly\r\n#octrrmonthly = #oct[]RR[]monthly\r\n#novrrmonthly = #nov[]RR[]monthly\r\n#decrrmonthly = #dec[]RR[]monthly\r\n#januaryrrmonthly = #jan[]uary[]RR[]monthly\r\n#februaryrrmonthly= #feb[]ruary[]RR[]monthly\r\n#marchrrmonthly = #march[]RR[]monthly\r\n#aprilrrmonthly = #april[]RR[]monthly\r\n#junerrmonthly = #june[]RR[]monthly\r\n#julyrrmonthly = #july[]RR[]monthly\r\n#augustrrmonthly = #august[]RR[]monthly\r\n#septemberrrmonthly = #september[]RR[]monthly\r\n#octoberrrmonthly = #oct[]ober[]RR[]monthly\r\n#novemberrrmonthly = #november[]RR[]monthly\r\n#decemberrrmonthly = #december[]RR[]monthly\r\n#mayrrrmonthly = #may[]RR[]monthly\r\n#septrrmonthly = #sept[]RR[]monthly", + "ActiveExperiments": null + }, + { + "Key": "UGC.Analytics.CreationSamplingMod", + "Value": ".1", + "ActiveExperiments": null + }, + { + "Key": "Lifecycle.Playmenu.CarouselEndpoint", + "Value": "foryou:Recommended For You,rising:Rising Rooms,earnroomcurrency_algo:Earn Room Currency,roleplay_algoendpoint:Roleplay,casual_algoendpoint:Casual,horror_algoendpoint:Horror,battle_algoendpoint:Battle,explore_algoendpoint:Explore,quests_algoendpoint:Quests,hangout_algoendpoint:Hangout", + "ActiveExperiments": "discovery_2024q1_dynamic_featured_rooms\r\n" + }, + { + "Key": "WatchHomeCarouselOrdering", + "Value": "rooms_continueplaying=23;rooms_friendsplaying=22;foryou=21;rooms_hot=20;rooms_rro=19;items_featured=8;items_featuredcustom=7;inventions_featured=6;inventions_featureddormskins=5", + "ActiveExperiments": "discovery_ordering_update_to_server_endpoint\r\ndiscovery_2024q1_watchhome_onlinefriendscarousel" + }, + { + "Key": "Lifecycle.Homemenu.CarouselEndpoint", + "Value": "foryou:Recommended For You", + "ActiveExperiments": null + }, + { + "Key": "Door.Dormroom.Query", + "Value": "", + "ActiveExperiments": null + }, + { + "Key": "Door.Dormroom.Title", + "Value": "EXIT", + "ActiveExperiments": null + }, + { + "Key": "Lifecycle.Playmenu.DedupingExceptions", + "Value": "", + "ActiveExperiments": null + }, + { + "Key": "Lifecycle.PSF.FriendRoomInviteRateLimitingCount", + "Value": "1", + "ActiveExperiments": "psf_2023q3_online_friend_room_invites" + }, + { + "Key": "UGC.ProUXFeatureFlag", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "UGC.LimitsV2.UI.Ink.Enabled", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "UGC.LimitsV2.UI.Toggle.Description", + "Value": "Help us test increased Ink limits in your rooms and new performance gauges on the MakerPen UI by enabling Limits 2.0! ", + "ActiveExperiments": null + }, + { + "Key": "UGC.LimitsV2.UI.Triangles.Enabled", + "Value": "false", + "ActiveExperiments": null + }, + { + "Key": "lifecycle.room_feedback.hot_rooms_probability", + "Value": "0.06", + "ActiveExperiments": "lifecycle_2023q2_room_feedback_debug" + }, + { + "Key": "lifecycle.room_feedback.new_rooms_probability", + "Value": "0.20", + "ActiveExperiments": "lifecycle_2023q3_room_feedback_response_scale" + }, + { + "Key": "Econ.StoreClothingOrderingExpOverride", + "Value": "", + "ActiveExperiments": null + }, + { + "Key": "Econ.StoreFeaturedOrderingExpOverride", + "Value": "store_featured_carousel_ordering_v2", + "ActiveExperiments": null + }, + { + "Key": "MobileHome.Discovery.Sections", + "Value": "[{\"title\":\"Friends\",\"isHorizontal\":true,\"source\":\"friends\"}, {\"title\":\"Featured\", \"source\":\"featuredRoom\", \"sourceMetadata\":\"PlayMenuRoomBanner\"}, {\"title\":\"Continue Playing\",\"isHorizontal\":true,\"source\":\"recent\"}, {\"title\":\"Rec Room Originals\",\"isHorizontal\":true,\"source\":\"hotList\",\"sourceMetadata\":\"rro\"}, {\"title\":\"Hot Rooms\",\"isHorizontal\":true,\"source\":\"hotList\"}, {\"title\":\"New Rooms\",\"isHorizontal\":true,\"source\":\"hotList\",\"sourceMetadata\":\"new\"}, {\"title\":\"Battle\",\"isHorizontal\":true,\"source\":\"carousel\",\"sourceMetadata\":\"battle_algoendpoint\"}, {\"title\":\"Horror\",\"isHorizontal\":true,\"source\":\"carousel\",\"sourceMetadata\":\"horror_algoendpoint\"}, {\"title\":\"Quests\",\"isHorizontal\":true,\"source\":\"carousel\",\"sourceMetadata\":\"quests_algoendpoint\"}, {\"title\":\"Casual\",\"isHorizontal\":true,\"source\":\"carousel\",\"sourceMetadata\":\"casual_algoendpoint\"}, {\"title\":\"Roleplay\",\"isHorizontal\":true,\"source\":\"carousel\",\"sourceMetadata\":\"roleplay_algoendpoint\"}, {\"title\":\"Hangout\",\"isHorizontal\":true,\"source\":\"carousel\",\"sourceMetadata\":\"hangout_algoendpoint\"}, {\"title\":\"Explore\",\"isHorizontal\":true,\"source\":\"carousel\",\"sourceMetadata\":\"explore_algoendpoint\"}]", + "ActiveExperiments": null + }, + { + "Key": "MatchmakingUI.AllowedLoadSources", + "Value": "[\"CAROUSEL_ENDPOINT_WATCH\",\"HOT_ROOMS_WATCH\",\"RRO_ROOMS_WATCH\",\"NEW_ROOMS_WATCH\",\"CURATED_PLAYLISTS_WATCH\",\"RECENT_ROOMS_WATCH\",\"FRIEND_PRESENCE_ROOMS_WATCH\",\"FEATURED_ROOMS_WATCH\"]", + "ActiveExperiments": null + }, + { + "Key": "Lifecycle.RoomDiscovery.CCUVariants.AccountCreationCutoff", + "Value": "2017-01-01 00:00", + "ActiveExperiments": "lifecycle_2023q2_room_discovery_ccu_variants_4_1" + }, + { + "Key": "Lifecycle.RoomDiscovery.CCUVariants.LoggingEnabled", + "Value": "false", + "ActiveExperiments": "lifecycle_2023q2_room_discovery_ccu_variants_4_1" + }, + { + "Key": "Lifecycle.RoomDiscovery.CCUVariants.RoomCardInfo", + "Value": "[{ \"CCUCountRange\": { \"Min\": 0, \"Max\": -1 }, \"RoomCardInfoElementIDs\": [\"cheersIcon\", \"cheersText\"] }]", + "ActiveExperiments": "lifecycle_2023q2_room_discovery_ccu_variants_4_1" + }, + { + "Key": "Lifecycle.RoomDiscovery.CCUVariants.UIEnabled", + "Value": "false", + "ActiveExperiments": "lifecycle_2023q2_room_discovery_ccu_variants_4_1" + }, + { + "Key": "Lifecycle.RoomDiscovery.Cheers.LoggingEnabled", + "Value": "false", + "ActiveExperiments": "lifecycle_2023q2_room_discovery_ccu_variants_4_1" + }, + { + "Key": "Lifecycle.PSF.PartyChatEnabled", + "Value": "True", + "ActiveExperiments": null + }, + { + "Key": "Lifecycle.PSF.PartyChatMaxAutoRejoinMinutes", + "Value": "60", + "ActiveExperiments": null + }, + { + "Key": "Lifecycle.PSF.PartyChatUpdatePeriod", + "Value": "60", + "ActiveExperiments": null + }, + { + "Key": "UGC.ObjectModel.HierarchyViewVisible", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "Debug.Watchdog.CorruptDataRequest.RoomIdToDeviceModelsBlacklist", + "Value": "{ 7740359740005459806: [ \"iPhone10,2\", \"iPhone10,3\", \"iPhone10,5\", \"iPhone10,6\", \"iPhone11,8\", \"iPhone12,1\", \"iPhone12,5\", \"iPhone12,8\", \"iPhone13,1\", \"iPhone13,2\", \"iPhone14,5\", \"iPhone14,6\", \"iPad3,1\", \"iPad3,2\", \"iPad3,3\", \"iPad7,11\", \"iPad7,12\", \"iPad11,1\", \"iPad11,2\", \"iPad11,3\", \"iPad11,4\", \"iPad11,6\", \"iPad11,7\", \"iPad12,1\", \"iPad12,2\", \"SM-X200\", \"SM-X205\" ] }", + "ActiveExperiments": null + }, + { + "Key": "UGC.CircuitsV2.Limit.Chips.7740359740005459806", + "Value": "5750", + "ActiveExperiments": null + }, + { + "Key": "FullBodyAvatars.MinLevelToUseFBAs", + "Value": "0", + "ActiveExperiments": null + }, + { + "Key": "Door.OrientationExit.Query", + "Value": "", + "ActiveExperiments": null + }, + { + "Key": "UGC.Room2Enabled", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "UGC.CircuitsV2.LogCV2ErrorsToAnalyticsInRooms", + "Value": "[7740359740005459806, 52815862, 558011494282369883]", + "ActiveExperiments": null + }, + { + "Key": "Experience.VR.UIRaycastIgnoresClampedHeldTools", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "Experience.STN.ShowBonkyHandsWhenUsingUI", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "UGC.ObjectModel.InventionLoading", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "UGC.ObjectModel.RoomSaving", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "UGC.ObjectModel.RoomPublishing", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "Lifecycle.PSF.DisableNewPlayerChallenges.AccountCreationCutoff", + "Value": "2023-08-01 00:00\t", + "ActiveExperiments": "psf_2023q3_disable_newplayerchecklist" + }, + { + "Key": "Lifecycle.PSF.WatchOpenOnSessionStart.HighlightDuration", + "Value": "5.0", + "ActiveExperiments": "psf_2023q3_watch_open_on_session_start" + }, + { + "Key": "Lifecycle.PSF.WatchOpenOnSessionStart.NewAccountDaysCutoff", + "Value": "30", + "ActiveExperiments": "psf_2023q3_watch_open_on_session_start" + }, + { + "Key": "Lifecycle.PSF.WatchOpenOnSessionStart.WaitDuration", + "Value": "10.0", + "ActiveExperiments": "psf_2023q3_watch_open_on_session_start" + }, + { + "Key": "AntiHile.QD", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "CommunityBoard.HowToBuildLink", + "Value": "https://www.youtube.com/watch?v=O7fb3ux2nDI", + "ActiveExperiments": null + }, + { + "Key": "UGC.ObjectModel.RoomUpgrade", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "UGC.ObjectModel.UpgradeEnabled", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "BadgeNotifications.StartEndTimesJson", + "Value": "[\r\n\t\"{\\\"title\\\":\\\"RCStorefront_10-13_10-20\\\",\\\"start_datetime\\\":\\\"2023-10-13T11:00:00\\\",\\\"end_datetime\\\":\\\"2023-10-15T10:59:59\\\"}\",\r\n \"{\\\"title\\\":\\\"RCStorefront_10-13_10-20\\\",\\\"start_datetime\\\":\\\"2023-10-15T11:00:00\\\",\\\"end_datetime\\\":\\\"2023-10-18T10:59:59\\\"}\",\r\n \"{\\\"title\\\":\\\"RCStorefront_10-13_10-20\\\",\\\"start_datetime\\\":\\\"2023-10-18T11:00:00\\\",\\\"end_datetime\\\":\\\"2023-10-20T10:59:59\\\"}\",\r\n\r\n\t\"{\\\"title\\\":\\\"RCStorefront_10-20_10-27\\\",\\\"start_datetime\\\":\\\"2023-10-20T11:00:00\\\",\\\"end_datetime\\\":\\\"2023-10-22T10:59:59\\\"}\",\r\n \"{\\\"title\\\":\\\"RCStorefront_10-20_10-27\\\",\\\"start_datetime\\\":\\\"2023-10-22T11:00:00\\\",\\\"end_datetime\\\":\\\"2023-10-25T10:59:59\\\"}\",\r\n \"{\\\"title\\\":\\\"RCStorefront_10-20_10-27\\\",\\\"start_datetime\\\":\\\"2023-10-25T11:00:00\\\",\\\"end_datetime\\\":\\\"2023-10-27T10:59:59\\\"}\",\r\n\r\n \"{\\\"title\\\":\\\"RCStorefront_10-27_11-03\\\",\\\"start_datetime\\\":\\\"2023-10-27T11:00:00\\\",\\\"end_datetime\\\":\\\"2023-10-29T10:59:59\\\"}\",\r\n \"{\\\"title\\\":\\\"RCStorefront_10-27_11-03\\\",\\\"start_datetime\\\":\\\"2023-10-29T11:00:00\\\",\\\"end_datetime\\\":\\\"2023-11-01T10:59:59\\\"}\",\r\n \"{\\\"title\\\":\\\"RCStorefront_10-27_11-03\\\",\\\"start_datetime\\\":\\\"2023-11-01T11:00:00\\\",\\\"end_datetime\\\":\\\"2023-11-03T10:59:59\\\"}\",\r\n\r\n \"{\\\"title\\\":\\\"RCStorefront_11-03_11-10\\\",\\\"start_datetime\\\":\\\"2023-11-03T11:00:00\\\",\\\"end_datetime\\\":\\\"2023-11-05T10:59:59\\\"}\",\r\n \"{\\\"title\\\":\\\"RCStorefront_11-03_11-10\\\",\\\"start_datetime\\\":\\\"2023-11-05T11:00:00\\\",\\\"end_datetime\\\":\\\"2023-11-08T10:59:59\\\"}\",\r\n \"{\\\"title\\\":\\\"RCStorefront_11-03_11-10\\\",\\\"start_datetime\\\":\\\"2023-11-08T11:00:00\\\",\\\"end_datetime\\\":\\\"2023-11-10T10:59:59\\\"}\",\r\n \r\n \"{\\\"title\\\":\\\"RCStorefront_11-10_11-17\\\",\\\"start_datetime\\\":\\\"2023-11-10T11:00:00\\\",\\\"end_datetime\\\":\\\"2023-11-12T10:59:59\\\"}\",\r\n \"{\\\"title\\\":\\\"RCStorefront_11-10_11-17\\\",\\\"start_datetime\\\":\\\"2023-11-12T11:00:00\\\",\\\"end_datetime\\\":\\\"2023-11-15T10:59:59\\\"}\",\r\n \"{\\\"title\\\":\\\"RCStorefront_11-10_11-17\\\",\\\"start_datetime\\\":\\\"2023-11-15T11:00:00\\\",\\\"end_datetime\\\":\\\"2023-11-17T10:59:59\\\"}\",\r\n\r\n \"{\\\"title\\\":\\\"RCStorefront_11-17_11-24\\\",\\\"start_datetime\\\":\\\"2023-11-17T11:00:00\\\",\\\"end_datetime\\\":\\\"2023-11-19T10:59:59\\\"}\",\r\n \"{\\\"title\\\":\\\"RCStorefront_11-17_11-24\\\",\\\"start_datetime\\\":\\\"2023-11-19T11:00:00\\\",\\\"end_datetime\\\":\\\"2023-11-22T10:59:59\\\"}\",\r\n \"{\\\"title\\\":\\\"RCStorefront_11-17_11-24\\\",\\\"start_datetime\\\":\\\"2023-11-22T11:00:00\\\",\\\"end_datetime\\\":\\\"2023-11-24T10:59:59\\\"}\",\r\n\r\n \"{\\\"title\\\":\\\"RCStorefront_11-24_12-01\\\",\\\"start_datetime\\\":\\\"2023-11-24T11:00:00\\\",\\\"end_datetime\\\":\\\"2023-11-26T10:59:59\\\"}\",\r\n \"{\\\"title\\\":\\\"RCStorefront_11-24_12-01\\\",\\\"start_datetime\\\":\\\"2023-11-26T11:00:00\\\",\\\"end_datetime\\\":\\\"2023-11-29T10:59:59\\\"}\",\r\n \"{\\\"title\\\":\\\"RCStorefront_11-24_12-01\\\",\\\"start_datetime\\\":\\\"2023-11-29T11:00:00\\\",\\\"end_datetime\\\":\\\"2023-12-01T10:59:59\\\"}\",\r\n\r\n \"{\\\"title\\\":\\\"RCStorefront_12-01_12-08\\\",\\\"start_datetime\\\":\\\"2023-12-01T11:00:00\\\",\\\"end_datetime\\\":\\\"2023-12-03T10:59:59\\\"}\",\r\n \"{\\\"title\\\":\\\"RCStorefront_12-01_12-08\\\",\\\"start_datetime\\\":\\\"2023-12-03T11:00:00\\\",\\\"end_datetime\\\":\\\"2023-12-06T10:59:59\\\"}\",\r\n \"{\\\"title\\\":\\\"RCStorefront_12-01_12-08\\\",\\\"start_datetime\\\":\\\"2023-12-06T11:00:00\\\",\\\"end_datetime\\\":\\\"2023-12-08T10:59:59\\\"}\",\r\n\r\n \"{\\\"title\\\":\\\"RCStorefront_12-08_12-15\\\",\\\"start_datetime\\\":\\\"2023-12-08T11:00:00\\\",\\\"end_datetime\\\":\\\"2023-12-10T10:59:59\\\"}\",\r\n \"{\\\"title\\\":\\\"RCStorefront_12-08_12-15\\\",\\\"start_datetime\\\":\\\"2023-12-10T11:00:00\\\",\\\"end_datetime\\\":\\\"2023-12-13T10:59:59\\\"}\",\r\n \"{\\\"title\\\":\\\"RCStorefront_12-08_12-15\\\",\\\"start_datetime\\\":\\\"2023-12-13T11:00:00\\\",\\\"end_datetime\\\":\\\"2023-12-15T10:59:59\\\"}\",\r\n\r\n \"{\\\"title\\\":\\\"RCStorefront_12-15_12-22\\\",\\\"start_datetime\\\":\\\"2023-12-15T11:00:00\\\",\\\"end_datetime\\\":\\\"2023-12-17T10:59:59\\\"}\",\r\n \"{\\\"title\\\":\\\"RCStorefront_12-15_12-22\\\",\\\"start_datetime\\\":\\\"2023-12-17T11:00:00\\\",\\\"end_datetime\\\":\\\"2023-12-20T10:59:59\\\"}\",\r\n \"{\\\"title\\\":\\\"RCStorefront_12-15_12-22\\\",\\\"start_datetime\\\":\\\"2023-12-20T11:00:00\\\",\\\"end_datetime\\\":\\\"2023-12-22T10:59:59\\\"}\",\r\n\r\n \"{\\\"title\\\":\\\"RCStorefront_12-22_12-29\\\",\\\"start_datetime\\\":\\\"2023-12-22T11:00:00\\\",\\\"end_datetime\\\":\\\"2023-12-24T10:59:59\\\"}\",\r\n \"{\\\"title\\\":\\\"RCStorefront_12-22_12-29\\\",\\\"start_datetime\\\":\\\"2023-12-24T11:00:00\\\",\\\"end_datetime\\\":\\\"2023-12-27T10:59:59\\\"}\",\r\n \"{\\\"title\\\":\\\"RCStorefront_12-22_12-29\\\",\\\"start_datetime\\\":\\\"2023-12-27T11:00:00\\\",\\\"end_datetime\\\":\\\"2023-12-29T10:59:59\\\"}\",\r\n\r\n \"{\\\"title\\\":\\\"RCStorefront_12-29_01-05\\\",\\\"start_datetime\\\":\\\"2023-12-29T11:00:00\\\",\\\"end_datetime\\\":\\\"2023-12-31T10:59:59\\\"}\",\r\n \"{\\\"title\\\":\\\"RCStorefront_12-29_01-05\\\",\\\"start_datetime\\\":\\\"2023-12-31T11:00:00\\\",\\\"end_datetime\\\":\\\"2024-01-03T10:59:59\\\"}\",\r\n \"{\\\"title\\\":\\\"RCStorefront_12-29_01-05\\\",\\\"start_datetime\\\":\\\"2024-01-03T11:00:00\\\",\\\"end_datetime\\\":\\\"2024-01-05T10:59:59\\\"}\"\r\n]", + "ActiveExperiments": null + }, + { + "Key": "FullBodyAvatars.FeatureEnabled", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "Econ.LogEnteredStorePageSwaps", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "UGC.ObjectModel.AllowedInRoomV1", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "Lifecycle.PSF.CannedChatOptions.CustomA", + "Value": "Yes,\r\nYay,\r\nAmazing!,\r\nI love this,\r\nYou look great!,\r\nYou look..., \r\nTIL,\r\nToo funny,\r\nLol,\r\nWhat!?,\r\nGood luck!,\r\nYou got this!,\r\nReally?,\r\nApplause,\r\nPerfect,\r\nDo it again!,\r\nLet's keep playing,\r\ngg", + "ActiveExperiments": null + }, + { + "Key": "Lifecycle.PSF.CannedChatOptions.CustomB", + "Value": "No,\r\nSorry,\r\nMy bad,\r\nUgh,\r\nBoring,\r\nMeh,\r\nBoo,\r\nWhat the coach?,\r\nI'm out,\r\nStop,\r\nLeave me alone,\r\nWhy?,\r\nWhy not?,\r\nOh geez,\r\nI'm confused,\r\nNo comment", + "ActiveExperiments": null + }, + { + "Key": "Lifecycle.PSF.CannedChatOptions.RecRoom", + "Value": "Hi!,\r\nHey there,\r\nBye! ,\r\nHow's it going? ,\r\nGood,\r\nOK,\r\nBad,\r\nYes,\r\nNo,\r\nThanks!,\r\nNo thanks!,\r\nWanna play?,\r\nCome with me,\r\nReady?,\r\nI gotta go,\r\nBe right back,\r\nLet's party up,\r\nLet's be friends!", + "ActiveExperiments": null + }, + { + "Key": "Lifecycle.PSF.CannedChatOptions.Room", + "Value": "Cool room!,\r\nShow me the room?,\r\nWatch out!,\r\nHelp!,\r\nWhere did you get that?,\r\nRight here,\r\nOver there,\r\nI'll take you there,\r\nOf course,\r\nIt's a no from me,\r\nHow did you do that?,\r\nWanna see something cool?,\r\nI can't even,\r\nIt's giving...,\r\nI'm done... new room?", + "ActiveExperiments": null + }, + { + "Key": "Lifecycle.GameInvite.AcceptResponse", + "Value": "", + "ActiveExperiments": "psf_2023q3_roominvite_responses_v2" + }, + { + "Key": "Lifecycle.GameInvite.DeclineResponses", + "Value": "You should come to me!; In the middle of something... invite me again in 5?; I'm about to log off; I don't really like that room; Not today, thanks\t", + "ActiveExperiments": null + }, + { + "Key": "Lifecycle.GameInvite.ResponsePlaceholder\t", + "Value": "Add a decline response", + "ActiveExperiments": null + }, + { + "Key": "UGC.CircuitsV2.Limit.ChipEvaluations", + "Value": "400", + "ActiveExperiments": null + }, + { + "Key": "UGC.ObjectModel.Physics", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "UGC.ObjectModel.Copy", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "UGC.ObjectModel.Clone", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "UGC.ObjectModel.Undo", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "UGC.ObjectModel.UndoCreation", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "Lifecycle.WatchHome.SegmentConfigMap", + "Value": "CreatorSegment_EliteCreator:EliteCreatorCarouselList,CreatorSegment_AdvancedCreator:AdvancedCreatorCarouselList,CreatorSegment_MidCreator:MidCreatorCarouselList,CreatorSegment_BeginnerCreator:BeginnerCreatorCarouselList", + "ActiveExperiments": "discovery_2023q3_watch_home_room_templates" + }, + { + "Key": "EliteCreatorCarouselList", + "Value": "", + "ActiveExperiments": "discovery_2023q3_watch_home_room_templates" + }, + { + "Key": "AdvancedCreatorCarouselList", + "Value": "", + "ActiveExperiments": "discovery_2023q3_watch_home_room_templates" + }, + { + "Key": "MidCreatorCarouselList", + "Value": "", + "ActiveExperiments": "discovery_2023q3_watch_home_room_templates" + }, + { + "Key": "BeginnerCreatorCarouselList", + "Value": "", + "ActiveExperiments": "discovery_2023q3_watch_home_room_templates" + }, + { + "Key": "MobileHome.Discovery.Sections.v2", + "Value": "[{\"title\":\"Friends\",\"isHorizontal\":true,\"source\":\"friends\"}, {\"title\":\"Featured\",\"source\":\"featuredRoom\",\"sourceMetadata\":\"PlayMenuRoomBanner\"}, {\"title\":\"Continue Playing\",\"isHorizontal\":true,\"source\":\"recent\"}, {\"title\":\"Rec Room Originals\",\"isHorizontal\":true,\"source\":\"hotList\",\"sourceMetadata\":\"rro\"}, {\"title\":\"Recommended For You\",\"isHorizontal\":true, \"hideIfNoContent\":true, \"source\":\"algorithmicList\",\"sourceMetadata\":\"{\\\"endpoint\\\":\\\"foryou\\\",\\\"entityType\\\":1}\"}, {\"title\":\"Hot Rooms\",\"isHorizontal\":true,\"source\":\"algorithmicList\",\"sourceMetadata\":\"{\\\"endpoint\\\":\\\"HotList\\\",\\\"entityType\\\":1}\"}, {\"title\":\"New Rooms\",\"isHorizontal\":true,\"source\":\"algorithmicList\",\"sourceMetadata\":\"{\\\"endpoint\\\":\\\"new\\\",\\\"entityType\\\":1}\"}, {\"title\":\"Battle\",\"isHorizontal\":true,\"source\":\"algorithmicList\",\"sourceMetadata\":\"{\\\"endpoint\\\":\\\"battle_algoendpoint\\\",\\\"entityType\\\":1}\"}, {\"title\":\"Horror\",\"isHorizontal\":true,\"source\":\"algorithmicList\",\"sourceMetadata\":\"{\\\"endpoint\\\":\\\"horror_algoendpoint\\\",\\\"entityType\\\":1}\"}, {\"title\":\"Casual\",\"isHorizontal\":true,\"source\":\"algorithmicList\",\"sourceMetadata\":\"{\\\"endpoint\\\":\\\"casual_algoendpoint\\\",\\\"entityType\\\":1}\"}, {\"title\":\"Roleplay\",\"isHorizontal\":true,\"source\":\"algorithmicList\",\"sourceMetadata\":\"{\\\"endpoint\\\":\\\"roleplay_algoendpoint\\\",\\\"entityType\\\":1}\"}, {\"title\":\"Hangout\",\"isHorizontal\":true,\"source\":\"algorithmicList\",\"sourceMetadata\":\"{\\\"endpoint\\\":\\\"hangout_algoendpoint\\\",\\\"entityType\\\":1}\"}, {\"title\":\"Explore\",\"isHorizontal\":true,\"source\":\"algorithmicList\",\"sourceMetadata\":\"{\\\"endpoint\\\":\\\"explore_algoendpoint\\\",\\\"entityType\\\":1}\"}]", + "ActiveExperiments": null + }, + { + "Key": "Econ.StorefrontCarouselsToUseListsService", + "Value": "(StoreClothing)/HatsItems,(StoreClothing)/TorsoItems,(StoreClothing)/AccessoriesItems,(StoreClothing)/GlovesItems,(StoreClothing)/HairItems", + "ActiveExperiments": null + }, + { + "Key": "UGC.MaxInkResourcesDefault", + "Value": "40000", + "ActiveExperiments": null + }, + { + "Key": "RoomLoad.SendHeartbeatAtEmptyScene", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "DataCollection.UseHeartbeatCoroutineDelays", + "Value": "false", + "ActiveExperiments": null + }, + { + "Key": "RoomInventory_SecondsBetweenFiringUseEvents", + "Value": "10", + "ActiveExperiments": null + }, + { + "Key": "UGC.Room2InfoText", + "Value": "Rooms 2.0 enables you to create higher quality rooms than ever before. However, there are a few things you should know before creating one.\r\n • This is an ALPHA release, so you may lose content, experience weird behaviors, etc.\r\n • Not every feature in Rooms 1.0 will be available in Rooms 2.0\r\n • Inventions are temporarily disabled\r\n • Rooms 2.0 introduces powerful new features like:\r\n • Compound Objects\r\n • MUCH higher creation limit\r\n • Player Properties (replaces Roles)", + "ActiveExperiments": null + }, + { + "Key": "Lifecycle.PSF.Progression.DailyDesc", + "Value": "Earn up to 150 XP every 24 hours\t", + "ActiveExperiments": null + }, + { + "Key": "Lifecycle.PSF.Progression.RewardMap", + "Value": "{\"3288\":\"153actlojyx0ktpl4dmlyrhcz.png\", \"3293\":\"153actlojyx0ktpl4dmlyrhcz.png\", \"3292\":\"5pawwzw4hvcrxhji1qo5iszfr.png\", \"3291\":\"0dydhae740mw5sj76vmfqkk1d.png\", \"3290\":\"erac8ves2ra4fhsuushotez9h.png\"}", + "ActiveExperiments": null + }, + { + "Key": "Lifecycle.PSF.Progression.UnknownRewardImage", + "Value": "aaitfknii3f6qdjkvhgb7vbhe.png", + "ActiveExperiments": null + }, + { + "Key": "Lifecycle.PSF.RestrictBlockedUnicodeStringsInPublicChat", + "Value": "True", + "ActiveExperiments": null + }, + { + "Key": "Lifecycle.PSF.RestrictUnicodeSupportInClubChat", + "Value": "False", + "ActiveExperiments": null + }, + { + "Key": "Lifecycle.PSF.RestrictUnicodeSupportInPartyChat", + "Value": "False", + "ActiveExperiments": null + }, + { + "Key": "Lifecycle.PSF.RestrictUnicodeSupportInRoomChat", + "Value": "True", + "ActiveExperiments": null + }, + { + "Key": "Econ.HideRoomOffers", + "Value": "false", + "ActiveExperiments": null + }, + { + "Key": "UGC.ObjectModel.SerializationV4", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "Friends.FriendRequestCooldownSeconds", + "Value": "3", + "ActiveExperiments": "experience_q4_friend-request-spam-prevention" + }, + { + "Key": "Lifecycle.PSF.EnableAllChatVoiceCalls", + "Value": "False", + "ActiveExperiments": null + }, + { + "Key": "Lifecycle.PSF.EnablePartyVoiceCall", + "Value": "False", + "ActiveExperiments": null + }, + { + "Key": "DataCollection.MaxBatchDelaySeconds", + "Value": "15", + "ActiveExperiments": null + }, + { + "Key": "DataCollection.MaxBatchSize", + "Value": "131072", + "ActiveExperiments": null + }, + { + "Key": "lifecycle_announcement_min_view_time", + "Value": "0.25", + "ActiveExperiments": null + }, + { + "Key": "lifecycle_announcement_track_shown", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "UGC.ObjectModel.NetworkSnapshot", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "UGC.Room2PublishingEnabled", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "UGC.ObjectModel.ScalabilityAllowed", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "HomeMenu.Carousels.ViewMoreButtonText", + "Value": "Similar Content", + "ActiveExperiments": null + }, + { + "Key": "UGC.Analytics.CreationSamplingMod_Room", + "Value": ".2", + "ActiveExperiments": null + }, + { + "Key": "PlayMenuDedupeSources", + "Value": "Hot,CarouselEndpoint", + "ActiveExperiments": null + }, + { + "Key": "FullBodyAvatars.UberMaterialCollapsingEnabled", + "Value": "false", + "ActiveExperiments": null + }, + { + "Key": "Lifecycle.MaxTimePostOrientationForFullPlayMenuPrompt", + "Value": "30", + "ActiveExperiments": null + }, + { + "Key": "Econ.StorefrontUGCCarouselEndpointFriendlyNames", + "Value": "New:New Custom Shirts||Trending:Trending Custom Shirts||", + "ActiveExperiments": null + }, + { + "Key": "UGC.Room2InventionsEnabled", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "HomeMenu.Carousels.MultiRowConfig", + "Value": "{\"CarouselId\":\"Recommended For You\",\"MaxRows\":1,\"BackgroundColor\":\"#F3DDCE\",\"Enabled\":true}", + "ActiveExperiments": null + }, + { + "Key": "PlayMenu.Carousels.MultiRowConfig", + "Value": "{\"CarouselId\":\"Recommended For You\",\"MaxRows\":1,\"BackgroundColor\":\"#F3DDCE\",\"Enabled\":true}", + "ActiveExperiments": null + }, + { + "Key": "Econ.BulkPurchaseCap", + "Value": "200", + "ActiveExperiments": null + }, + { + "Key": "Discovery.UseNewDiscoveryServerAPI", + "Value": "True", + "ActiveExperiments": null + }, + { + "Key": "Discovery.DiscoveryPageContent.PlayHighlight", + "Value": "{\"pageSource\":1,\"sections\":[{\"Id\":\"Rooms_ForYou\",\"DiscoveryEntityType\":0,\"Source\":\"CarouselEndpoint\",\"SourceMetadata\":\"foryou\",\"DisplayMetadata\":{\"DisplayTitle\":\"Recommended For You\",\"supportsDedupe\":true,\"numRows\":2,\"sizePerPlatform\":\"\",\"backgroundColor\":\"#F3DDCE\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Rooms_HotRooms\",\"DiscoveryEntityType\":0,\"Source\":\"Hot\",\"SourceMetadata\":\"\",\"DisplayMetadata\":{\"DisplayTitle\":\"Hot Rooms\",\"supportsDedupe\":true,\"numRows\":1}},{\"Id\":\"Rooms_New\",\"DiscoveryEntityType\":0,\"Source\":\"Hot\",\"SourceMetadata\":\"new\",\"DisplayMetadata\":{\"DisplayTitle\":\"New\",\"supportsDedupe\":true,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Rooms_RRO\",\"DiscoveryEntityType\":0,\"Source\":\"Hot\",\"SourceMetadata\":\"rro\",\"DisplayMetadata\":{\"DisplayTitle\":\"Rec Room Originals\",\"supportsDedupe\":false,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Rooms_ContinuePlaying\",\"DiscoveryEntityType\":0,\"Source\":\"Recent\",\"SourceMetadata\":\"\",\"DisplayMetadata\":{\"DisplayTitle\":\"Continue Playing\",\"supportsDedupe\":false,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Rooms_Rising\",\"DiscoveryEntityType\":0,\"Source\":\"CarouselEndpoint\",\"SourceMetadata\":\"rising\",\"DisplayMetadata\":{\"DisplayTitle\":\"Rising Rooms\",\"supportsDedupe\":true,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Rooms_MyFavorites\",\"DiscoveryEntityType\":0,\"Source\":\"MyFavorites\",\"SourceMetadata\":\"\",\"DisplayMetadata\":{\"DisplayTitle\":\"My Favorites\",\"supportsDedupe\":false,\"numRows\":1,\"sizePerPlatform\":\"all=highlight_scale_150\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Rooms_FriendsPlaying\",\"DiscoveryEntityType\":0,\"Source\":\"FriendPresence\",\"SourceMetadata\":\"\",\"DisplayMetadata\":{\"DisplayTitle\":\"Friends are Playing\",\"supportsDedupe\":false,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Rooms_TopEarning\",\"DiscoveryEntityType\":0,\"Source\":\"PlaylistById\",\"SourceMetadata\":\"65380152\",\"DisplayMetadata\":{\"DisplayTitle\":\"Top Earning\",\"supportsDedupe\":false,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Rooms_MySubscriptions\",\"DiscoveryEntityType\":0,\"Source\":\"MySubscriptions\",\"SourceMetadata\":\"\",\"DisplayMetadata\":{\"DisplayTitle\":\"My Subscriptions\",\"supportsDedupe\":false,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Rooms_EarnRoomCurrency_AlgoEndpoint\",\"DiscoveryEntityType\":0,\"Source\":\"CarouselEndpoint\",\"SourceMetadata\":\"earnroomcurrency_algo\",\"DisplayMetadata\":{\"DisplayTitle\":\"Earn Room Currency\",\"supportsDedupe\":true,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Rooms_Roleplay_AlgoEndpoint\",\"DiscoveryEntityType\":0,\"Source\":\"CarouselEndpoint\",\"SourceMetadata\":\"roleplay_algoendpoint\",\"DisplayMetadata\":{\"DisplayTitle\":\"Roleplay\",\"supportsDedupe\":true,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Rooms_Casual_AlgoEndpoint\",\"DiscoveryEntityType\":0,\"Source\":\"CarouselEndpoint\",\"SourceMetadata\":\"casual_algoendpoint\",\"DisplayMetadata\":{\"DisplayTitle\":\"Casual\",\"supportsDedupe\":true,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Rooms_Horror_AlgoEndpoint\",\"DiscoveryEntityType\":0,\"Source\":\"CarouselEndpoint\",\"SourceMetadata\":\"horror_algoendpoint\",\"DisplayMetadata\":{\"DisplayTitle\":\"Horror\",\"supportsDedupe\":true,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Rooms_Battle_AlgoEndpoint\",\"DiscoveryEntityType\":0,\"Source\":\"CarouselEndpoint\",\"SourceMetadata\":\"battle_algoendpoint\",\"DisplayMetadata\":{\"DisplayTitle\":\"Battle\",\"supportsDedupe\":true,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Rooms_Explore_AlgoEndpoint\",\"DiscoveryEntityType\":0,\"Source\":\"CarouselEndpoint\",\"SourceMetadata\":\"explore_algoendpoint\",\"DisplayMetadata\":{\"DisplayTitle\":\"Explore\",\"supportsDedupe\":true,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Rooms_Quests_AlgoEndpoint\",\"DiscoveryEntityType\":0,\"Source\":\"CarouselEndpoint\",\"SourceMetadata\":\"quests_algoendpoint\",\"DisplayMetadata\":{\"DisplayTitle\":\"Quests\",\"supportsDedupe\":true,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Rooms_Hangout_AlgoEndpoint\",\"DiscoveryEntityType\":0,\"Source\":\"CarouselEndpoint\",\"SourceMetadata\":\"hangout_algoendpoint\",\"DisplayMetadata\":{\"DisplayTitle\":\"Hangout\",\"supportsDedupe\":true,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Rooms_InkShowcase\",\"DiscoveryEntityType\":0,\"Source\":\"PlaylistById\",\"SourceMetadata\":\"52548973\",\"DisplayMetadata\":{\"DisplayTitle\":\"Ink Showcase\",\"supportsDedupe\":false,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Rooms_Featured\",\"DiscoveryEntityType\":0,\"Source\":\"Featured\",\"SourceMetadata\":\"\",\"DisplayMetadata\":{\"DisplayTitle\":\"Featured\",\"supportsDedupe\":false,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}}]}", + "ActiveExperiments": null + }, + { + "Key": "Discovery.DiscoveryPageContent.CommunityBoard", + "Value": "{\"pageSource\":2,\"sections\":[{\"Id\":\"Rooms_ForYou\",\"DiscoveryEntityType\":0,\"Source\":\"CarouselEndpoint\",\"SourceMetadata\":\"foryou\",\"DisplayMetadata\":{\"DisplayTitle\":\"Recommended For You\",\"supportsDedupe\":true,\"numRows\":2,\"sizePerPlatform\":\"\",\"backgroundColor\":\"#F3DDCE\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Rooms_HotRooms\",\"DiscoveryEntityType\":0,\"Source\":\"Hot\",\"SourceMetadata\":\"\",\"DisplayMetadata\":{\"DisplayTitle\":\"Hot Rooms\",\"supportsDedupe\":true,\"numRows\":1}},{\"Id\":\"Rooms_New\",\"DiscoveryEntityType\":0,\"Source\":\"Hot\",\"SourceMetadata\":\"new\",\"DisplayMetadata\":{\"DisplayTitle\":\"New\",\"supportsDedupe\":true,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Rooms_RRO\",\"DiscoveryEntityType\":0,\"Source\":\"Hot\",\"SourceMetadata\":\"rro\",\"DisplayMetadata\":{\"DisplayTitle\":\"Rec Room Originals\",\"supportsDedupe\":false,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Rooms_ContinuePlaying\",\"DiscoveryEntityType\":0,\"Source\":\"Recent\",\"SourceMetadata\":\"\",\"DisplayMetadata\":{\"DisplayTitle\":\"Continue Playing\",\"supportsDedupe\":false,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Rooms_Rising\",\"DiscoveryEntityType\":0,\"Source\":\"CarouselEndpoint\",\"SourceMetadata\":\"rising\",\"DisplayMetadata\":{\"DisplayTitle\":\"Rising Rooms\",\"supportsDedupe\":true,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Rooms_MyFavorites\",\"DiscoveryEntityType\":0,\"Source\":\"MyFavorites\",\"SourceMetadata\":\"\",\"DisplayMetadata\":{\"DisplayTitle\":\"My Favorites\",\"supportsDedupe\":false,\"numRows\":1,\"sizePerPlatform\":\"all=highlight_scale_150\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Rooms_FriendsPlaying\",\"DiscoveryEntityType\":0,\"Source\":\"FriendPresence\",\"SourceMetadata\":\"\",\"DisplayMetadata\":{\"DisplayTitle\":\"Friends are Playing\",\"supportsDedupe\":false,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Rooms_TopEarning\",\"DiscoveryEntityType\":0,\"Source\":\"PlaylistById\",\"SourceMetadata\":\"65380152\",\"DisplayMetadata\":{\"DisplayTitle\":\"Top Earning\",\"supportsDedupe\":false,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Rooms_MySubscriptions\",\"DiscoveryEntityType\":0,\"Source\":\"MySubscriptions\",\"SourceMetadata\":\"\",\"DisplayMetadata\":{\"DisplayTitle\":\"My Subscriptions\",\"supportsDedupe\":false,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Rooms_EarnRoomCurrency_AlgoEndpoint\",\"DiscoveryEntityType\":0,\"Source\":\"CarouselEndpoint\",\"SourceMetadata\":\"earnroomcurrency_algo\",\"DisplayMetadata\":{\"DisplayTitle\":\"Earn Room Currency\",\"supportsDedupe\":true,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Rooms_Roleplay_AlgoEndpoint\",\"DiscoveryEntityType\":0,\"Source\":\"CarouselEndpoint\",\"SourceMetadata\":\"roleplay_algoendpoint\",\"DisplayMetadata\":{\"DisplayTitle\":\"Roleplay\",\"supportsDedupe\":true,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Rooms_Casual_AlgoEndpoint\",\"DiscoveryEntityType\":0,\"Source\":\"CarouselEndpoint\",\"SourceMetadata\":\"casual_algoendpoint\",\"DisplayMetadata\":{\"DisplayTitle\":\"Casual\",\"supportsDedupe\":true,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Rooms_Horror_AlgoEndpoint\",\"DiscoveryEntityType\":0,\"Source\":\"CarouselEndpoint\",\"SourceMetadata\":\"horror_algoendpoint\",\"DisplayMetadata\":{\"DisplayTitle\":\"Horror\",\"supportsDedupe\":true,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Rooms_Battle_AlgoEndpoint\",\"DiscoveryEntityType\":0,\"Source\":\"CarouselEndpoint\",\"SourceMetadata\":\"battle_algoendpoint\",\"DisplayMetadata\":{\"DisplayTitle\":\"Battle\",\"supportsDedupe\":true,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Rooms_Explore_AlgoEndpoint\",\"DiscoveryEntityType\":0,\"Source\":\"CarouselEndpoint\",\"SourceMetadata\":\"explore_algoendpoint\",\"DisplayMetadata\":{\"DisplayTitle\":\"Explore\",\"supportsDedupe\":true,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Rooms_Quests_AlgoEndpoint\",\"DiscoveryEntityType\":0,\"Source\":\"CarouselEndpoint\",\"SourceMetadata\":\"quests_algoendpoint\",\"DisplayMetadata\":{\"DisplayTitle\":\"Quests\",\"supportsDedupe\":true,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Rooms_Hangout_AlgoEndpoint\",\"DiscoveryEntityType\":0,\"Source\":\"CarouselEndpoint\",\"SourceMetadata\":\"hangout_algoendpoint\",\"DisplayMetadata\":{\"DisplayTitle\":\"Hangout\",\"supportsDedupe\":true,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Rooms_InkShowcase\",\"DiscoveryEntityType\":0,\"Source\":\"PlaylistById\",\"SourceMetadata\":\"52548973\",\"DisplayMetadata\":{\"DisplayTitle\":\"Ink Showcase\",\"supportsDedupe\":false,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Rooms_Featured\",\"DiscoveryEntityType\":0,\"Source\":\"Featured\",\"SourceMetadata\":\"\",\"DisplayMetadata\":{\"DisplayTitle\":\"Featured\",\"supportsDedupe\":false,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}}]}", + "ActiveExperiments": null + }, + { + "Key": "Discovery.DiscoveryPageContent.WatchHome", + "Value": "{\"pageSource\":0,\"sections\":[{\"Id\":\"Rooms_ContinuePlaying\",\"DiscoveryEntityType\":0,\"Source\":\"Recent\",\"SourceMetadata\":\"\",\"DisplayMetadata\":{\"DisplayTitle\":\"Continue Playing\",\"supportsDedupe\":false,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Rooms_FriendsPlaying\",\"DiscoveryEntityType\":0,\"Source\":\"FriendPresence\",\"SourceMetadata\":\"\",\"DisplayMetadata\":{\"DisplayTitle\":\"Friends are Playing\",\"supportsDedupe\":false,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Rooms_HotRooms\",\"DiscoveryEntityType\":0,\"Source\":\"Hot\",\"SourceMetadata\":\"\",\"DisplayMetadata\":{\"DisplayTitle\":\"Hot Rooms\",\"supportsDedupe\":false,\"numRows\":2,\"sizePerPlatform\":\"\",\"backgroundColor\":\"#F3DDCE\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Rooms_RRO\",\"DiscoveryEntityType\":0,\"Source\":\"Hot\",\"SourceMetadata\":\"rro\",\"DisplayMetadata\":{\"DisplayTitle\":\"Rec Room Originals\",\"supportsDedupe\":false,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Items_Featured\",\"DiscoveryEntityType\":4,\"Source\":\"Store\",\"SourceMetadata\":\"FeaturedItems\",\"DisplayMetadata\":{\"DisplayTitle\":\"\",\"supportsDedupe\":false,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Items_FeaturedCustom\",\"DiscoveryEntityType\":8,\"Source\":\"Featured\",\"SourceMetadata\":\"\",\"DisplayMetadata\":{\"DisplayTitle\":\"\",\"supportsDedupe\":false,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Inventions_Featured\",\"DiscoveryEntityType\":2,\"Source\":\"FeaturedInventions\",\"SourceMetadata\":\"\",\"DisplayMetadata\":{\"DisplayTitle\":\"\",\"supportsDedupe\":false,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Inventions_FeaturedDormSkins\",\"DiscoveryEntityType\":2,\"Source\":\"FeaturedDormSkins\",\"SourceMetadata\":\"\",\"DisplayMetadata\":{\"DisplayTitle\":\"\",\"supportsDedupe\":false,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Events_My\",\"DiscoveryEntityType\":5,\"Source\":\"MyEvents\",\"SourceMetadata\":\"\",\"DisplayMetadata\":{\"DisplayTitle\":\"\",\"supportsDedupe\":false,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Clubs_My\",\"DiscoveryEntityType\":3,\"Source\":\"ClubsIBelongTo\",\"SourceMetadata\":\"\",\"DisplayMetadata\":{\"DisplayTitle\":\"\",\"supportsDedupe\":false,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}},{\"Id\":\"Top5\",\"DiscoveryEntityType\":7,\"Source\":\"\",\"SourceMetadata\":\"\",\"DisplayMetadata\":{\"DisplayTitle\":\"\",\"supportsDedupe\":false,\"numRows\":1,\"sizePerPlatform\":\"\",\"backgroundColor\":\"\",\"horizontalScrollEnabled\":false}}]}", + "ActiveExperiments": null + }, + { + "Key": "UGC.Room2InventionConversionEnabled", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "Discovery.RoomSearch.CustomCarouselData", + "Value": "\t{ \"SourceText\": \"CarouselEndpoint\", \"SourceMetadata\": \"HotList\", \"Title\": \"Visit our hot rooms instead?\" }", + "ActiveExperiments": null + }, + { + "Key": "Discovery.RoomSearch.SearchTips", + "Value": "1. Try other keywords\r\n2. Use more generic search terms\r\n3. Check your search for typos or spelling errors", + "ActiveExperiments": null + }, + { + "Key": "Discovery.RoomSearch.SimilarRoomsCarouselTitle", + "Value": "Enjoying ^{0}? You might also like", + "ActiveExperiments": null + }, + { + "Key": "DataCollection.LogFriendIdsWithSocialHeartbeat", + "Value": "False", + "ActiveExperiments": "retention_2024q1_friendid_heartbeat" + }, + { + "Key": "UGC.Room2InventionsUseRruiMenu", + "Value": "false", + "ActiveExperiments": null + }, + { + "Key": "UGC.Room2InventionsAlwaysPromptForAnchors", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "UGC.IncludeCurvesInDefaultShapesView", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "Foundation.NetworkTransform.ignore_truly_redundant_sync_data", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "Voice.Dissonance.ios.VoiceAudioQuality", + "Value": "2", + "ActiveExperiments": null + }, + { + "Key": "Voice.Dissonance.android.VoiceAudioQuality", + "Value": "2", + "ActiveExperiments": null + }, + { + "Key": "Voice.Dissonance.quest.VoiceAudioQuality", + "Value": "2", + "ActiveExperiments": null + }, + { + "Key": "lifecycle.room_feedback.prob_coefficient_b", + "Value": "200", + "ActiveExperiments": "lifecycle_2023q2_room_feedback\r\n" + }, + { + "Key": "Experience.DormRoom.AllowRename", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "Debug.Watchdog.NintendoSwitch.IgnoreHashCheck", + "Value": "1", + "ActiveExperiments": null + }, + { + "Key": "UGC.LimitsV2.DisableCloning", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "UGC.LimitsV2.DisableLimitsV2Toggle", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "BrazeNotificationTestRoomId", + "Value": "558011494282369883", + "ActiveExperiments": null + }, + { + "Key": "DataCollection.SkipPerfStatsFor", + "Value": "", + "ActiveExperiments": null + }, + { + "Key": "Econ.StorefrontCarouselEndpointFriendlyNames", + "Value": "itemsforyou:Recommended For You||newitems:New Items||headwearitems:Headwear||topsitems:Tops||bottomsitems:Bottoms||footwearitems:Footwear||waistitems:Waist||handsitems:Hands||shoulderitems:Shoulders||skinsitems:Skins||accessoriesitems:Accessories||hairitems:Hairstyles||facialhairitems:Facial Hair", + "ActiveExperiments": null + }, + { + "Key": "UGC.CircuitsV2.Limit.Chips.558011494282369883", + "Value": "100000", + "ActiveExperiments": null + }, + { + "Key": "UGC.CircuitsV2.Limit.Compute.558011494282369883", + "Value": "6000000", + "ActiveExperiments": null + }, + { + "Key": "Avatars.CollectAnalytics", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "UGC_MakerPen_Memory_Threshold_High", + "Value": "500", + "ActiveExperiments": null + }, + { + "Key": "UGC_MakerPen_Memory_Threshold_Low", + "Value": "250", + "ActiveExperiments": null + }, + { + "Key": "UGC_MakerPen_Memory_Threshold_Medium", + "Value": "400", + "ActiveExperiments": null + }, + { + "Key": "Voice.Dissonance.desktop.VolumeMultiplier", + "Value": "1", + "ActiveExperiments": null + }, + { + "Key": "Voice.Dissonance.quest.VolumeMultiplier", + "Value": "1", + "ActiveExperiments": null + }, + { + "Key": "Voice.Dissonance.android.VolumeMultiplier", + "Value": "1", + "ActiveExperiments": null + }, + { + "Key": "Voice.Dissonance.ios.VolumeMultiplier", + "Value": "1", + "ActiveExperiments": null + }, + { + "Key": "Voice.Dissonance.android.HighPassFilterEnabled", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "Voice.Dissonance.android.AgcTargetLevel", + "Value": "0.1", + "ActiveExperiments": null + }, + { + "Key": "Voice.Dissonance.ios.HighPassFilterEnabled", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "Voice.Dissonance.ios.AgcTargetLevel", + "Value": "0.1", + "ActiveExperiments": null + }, + { + "Key": "Voice.Dissonance.quest.HighPassFilterEnabled", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "Voice.Dissonance.quest.AgcTargetLevel", + "Value": "0.1", + "ActiveExperiments": null + }, + { + "Key": "Voice.Dissonance.quest.AgcCompressionGain", + "Value": "0.1", + "ActiveExperiments": null + }, + { + "Key": "Voice.Dissonance.desktop.HighPassFilterEnabled", + "Value": "true", + "ActiveExperiments": null + }, + { + "Key": "Voice.Dissonance.desktop.AgcTargetLevel", + "Value": "0.1", + "ActiveExperiments": null + }, + { + "Key": "Voice.Dissonance.desktop.VoiceDesktopEchoCancellation", + "Value": "0", + "ActiveExperiments": null } -] \ No newline at end of file +] diff --git a/CannedNet/Migrations/20260614165446_MakeDataSavedAtNullable.Designer.cs b/CannedNet/Migrations/20260614165446_MakeDataSavedAtNullable.Designer.cs new file mode 100644 index 0000000..461a79d --- /dev/null +++ b/CannedNet/Migrations/20260614165446_MakeDataSavedAtNullable.Designer.cs @@ -0,0 +1,1133 @@ +// +using System; +using System.Collections.Generic; +using CannedNet.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace CannedNet.Migrations +{ + [DbContext(typeof(AppDbContext))] + [Migration("20260614165446_MakeDataSavedAtNullable")] + partial class MakeDataSavedAtNullable + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.8") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("CannedNet.Account", b => + { + b.Property("AccountId") + .HasColumnType("integer") + .HasJsonPropertyName("accountId"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasJsonPropertyName("createdAt"); + + b.Property("DisplayName") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("displayName"); + + b.Property("IdentityFlags") + .HasColumnType("integer") + .HasJsonPropertyName("identityFlags"); + + b.Property("IsJunior") + .HasColumnType("boolean") + .HasJsonPropertyName("isJunior"); + + b.Property("PersonalPronouns") + .HasColumnType("integer") + .HasJsonPropertyName("personalPronouns"); + + b.Property("Platforms") + .HasColumnType("integer") + .HasJsonPropertyName("platforms"); + + b.Property("ProfileImage") + .HasColumnType("text") + .HasJsonPropertyName("profileImage"); + + b.Property("Username") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("username"); + + b.HasKey("AccountId"); + + b.ToTable("accounts", (string)null); + }); + + modelBuilder.Entity("CannedNet.AvatarItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AvatarItemDesc") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("avatarItemDesc"); + + b.Property("AvatarItemType") + .HasColumnType("integer") + .HasJsonPropertyName("avatarItemType"); + + b.Property("FriendlyName") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("friendlyName"); + + b.Property("OwnerAccountId") + .HasColumnType("integer"); + + b.Property("PlatformMask") + .HasColumnType("integer") + .HasJsonPropertyName("platformMask"); + + b.Property("Rarity") + .HasColumnType("integer") + .HasJsonPropertyName("rarity"); + + b.Property("Tooltip") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("tooltip"); + + b.HasKey("Id"); + + b.HasIndex("OwnerAccountId"); + + b.ToTable("avatar_items", (string)null); + }); + + modelBuilder.Entity("CannedNet.CachedLogin", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("integer") + .HasJsonPropertyName("accountId"); + + b.Property("LastLoginTime") + .HasColumnType("timestamp with time zone") + .HasJsonPropertyName("lastLoginTime"); + + b.Property("Platform") + .HasColumnType("integer") + .HasJsonPropertyName("platform"); + + b.Property("PlatformID") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("platformId"); + + b.Property("RequirePassword") + .HasColumnType("boolean") + .HasJsonPropertyName("requirePassword"); + + b.HasKey("Id"); + + b.HasIndex("Platform", "PlatformID"); + + b.ToTable("cached_logins", (string)null); + }); + + modelBuilder.Entity("CannedNet.LoadScreen", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ImageUrl") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("imageUrl"); + + b.Property("IsThumbnail") + .HasColumnType("boolean") + .HasJsonPropertyName("isThumbnail"); + + b.Property("RoomId") + .HasColumnType("integer"); + + b.Property("Tooltip") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("tooltip"); + + b.HasKey("Id"); + + b.HasIndex("RoomId"); + + b.ToTable("load_screens", (string)null); + }); + + modelBuilder.Entity("CannedNet.Models.ConsumableItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ActiveDurationMinutes") + .HasColumnType("integer") + .HasJsonPropertyName("ActiveDurationMinutes"); + + b.Property("ConsumableItemDesc") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("ConsumableItemDesc"); + + b.Property("Count") + .HasColumnType("integer") + .HasJsonPropertyName("Count"); + + b.PrimitiveCollection>("CreatedAts") + .IsRequired() + .HasColumnType("timestamp with time zone[]") + .HasJsonPropertyName("CreatedAts"); + + b.PrimitiveCollection>("Ids") + .IsRequired() + .HasColumnType("integer[]") + .HasJsonPropertyName("Ids"); + + b.Property("InitialCount") + .HasColumnType("integer") + .HasJsonPropertyName("InitialCount"); + + b.Property("IsActive") + .HasColumnType("boolean") + .HasJsonPropertyName("IsActive"); + + b.Property("IsTransferable") + .HasColumnType("boolean") + .HasJsonPropertyName("IsTransferable"); + + b.Property("OwnerAccountId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("OwnerAccountId"); + + b.ToTable("consumable_items", (string)null); + }); + + modelBuilder.Entity("CannedNet.Models.EarnableReward", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AvatarItemDesc") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("avatarItemDesc"); + + b.Property("AvatarItemType") + .HasColumnType("integer") + .HasJsonPropertyName("avatarItemType"); + + b.Property("ConsumableItemDesc") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("consumableItemDesc"); + + b.Property("FriendlyName") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("friendlyName"); + + b.Property("GiftRarity") + .HasColumnType("integer") + .HasJsonPropertyName("giftRarity"); + + b.Property("RewardContext") + .HasColumnType("integer") + .HasJsonPropertyName("rewardContext"); + + b.HasKey("Id"); + + b.HasIndex("RewardContext"); + + b.ToTable("earnable_rewards", (string)null); + }); + + modelBuilder.Entity("CannedNet.Models.GiftDrop", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AvatarItemDesc") + .HasColumnType("text"); + + b.Property("AvatarItemType") + .HasColumnType("integer"); + + b.Property("ConsumableItemDesc") + .HasColumnType("text"); + + b.Property("Context") + .HasColumnType("integer"); + + b.Property("Currency") + .HasColumnType("integer"); + + b.Property("CurrencyType") + .HasColumnType("integer"); + + b.Property("EquipmentModificationGuid") + .HasColumnType("text"); + + b.Property("EquipmentPrefabName") + .HasColumnType("text"); + + b.Property("FriendlyName") + .IsRequired() + .HasColumnType("text"); + + b.Property("GiftDropId") + .HasColumnType("integer"); + + b.Property("IsQuery") + .HasColumnType("boolean"); + + b.Property("ItemSetFriendlyName") + .HasColumnType("text"); + + b.Property("ItemSetId") + .HasColumnType("integer"); + + b.Property("Level") + .HasColumnType("integer"); + + b.Property("Rarity") + .HasColumnType("integer"); + + b.Property("StorefrontItemId") + .HasColumnType("integer"); + + b.Property("SubscribersOnly") + .HasColumnType("boolean"); + + b.Property("Tooltip") + .HasColumnType("text"); + + b.Property("Unique") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("StorefrontItemId"); + + b.ToTable("gift_drops", (string)null); + }); + + modelBuilder.Entity("CannedNet.Models.ReceivedGift", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AvatarItemDesc") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("avatarItemDesc"); + + b.Property("AvatarItemType") + .HasColumnType("integer") + .HasJsonPropertyName("avatarItemType"); + + b.Property("BalanceType") + .HasColumnType("integer") + .HasJsonPropertyName("balanceType"); + + b.Property("ConsumableItemDesc") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("consumableItemDesc"); + + b.Property("ConsumedAt") + .HasColumnType("timestamp with time zone") + .HasJsonPropertyName("consumedAt"); + + b.Property("Currency") + .HasColumnType("integer") + .HasJsonPropertyName("currency"); + + b.Property("CurrencyType") + .HasColumnType("integer") + .HasJsonPropertyName("currencyType"); + + b.Property("EquipmentModificationGuid") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("equipmentModificationGuid"); + + b.Property("EquipmentPrefabName") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("equipmentPrefabName"); + + b.Property("FriendlyName") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("friendlyName"); + + b.Property("FromPlayerId") + .HasColumnType("integer") + .HasJsonPropertyName("fromPlayerId"); + + b.Property("GiftContext") + .HasColumnType("integer") + .HasJsonPropertyName("giftContext"); + + b.Property("GiftRarity") + .HasColumnType("integer") + .HasJsonPropertyName("giftRarity"); + + b.Property("IsConsumed") + .HasColumnType("boolean") + .HasJsonPropertyName("isConsumed"); + + b.Property("Level") + .HasColumnType("integer") + .HasJsonPropertyName("level"); + + b.Property("Message") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("message"); + + b.Property("Platform") + .HasColumnType("integer") + .HasJsonPropertyName("platform"); + + b.Property("PlatformsToSpawnOn") + .HasColumnType("integer") + .HasJsonPropertyName("platformsToSpawnOn"); + + b.Property("ReceivedAt") + .HasColumnType("timestamp with time zone") + .HasJsonPropertyName("receivedAt"); + + b.Property("ReceiverAccountId") + .HasColumnType("integer") + .HasJsonPropertyName("receiverAccountId"); + + b.Property("Xp") + .HasColumnType("integer") + .HasJsonPropertyName("xp"); + + b.HasKey("Id"); + + b.HasIndex("ReceiverAccountId"); + + b.HasIndex("ReceiverAccountId", "IsConsumed"); + + b.ToTable("received_gifts", (string)null); + }); + + modelBuilder.Entity("CannedNet.Models.Storefront", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("NextUpdate") + .HasColumnType("timestamp with time zone"); + + b.Property("StorefrontType") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("storefronts", (string)null); + }); + + modelBuilder.Entity("CannedNet.Models.StorefrontItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("IsFeatured") + .HasColumnType("boolean"); + + b.Property("NewUntil") + .HasColumnType("timestamp with time zone"); + + b.Property("PurchasableItemId") + .HasColumnType("integer"); + + b.Property("StorefrontId") + .HasColumnType("integer"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("StorefrontId"); + + b.ToTable("storefront_items", (string)null); + }); + + modelBuilder.Entity("CannedNet.Models.StorefrontPrice", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CurrencyType") + .HasColumnType("integer"); + + b.Property("Price") + .HasColumnType("integer"); + + b.Property("StorefrontItemId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("StorefrontItemId"); + + b.ToTable("storefront_prices", (string)null); + }); + + modelBuilder.Entity("CannedNet.PlayerAvatar", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("FaceFeatures") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("FaceFeatures"); + + b.Property("HairColor") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("HairColor"); + + b.Property("OutfitSelections") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("OutfitSelections"); + + b.Property("OwnerAccountId") + .HasColumnType("integer"); + + b.Property("SkinColor") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("SkinColor"); + + b.HasKey("Id"); + + b.HasIndex("OwnerAccountId") + .IsUnique(); + + b.ToTable("player_avatars", (string)null); + }); + + modelBuilder.Entity("CannedNet.PlayerBio", b => + { + b.Property("accountId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasJsonPropertyName("accountId"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("accountId")); + + b.HasKey("accountId"); + + b.ToTable("player_bios", (string)null); + }); + + modelBuilder.Entity("CannedNet.PlayerProgression", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Level") + .HasColumnType("integer") + .HasJsonPropertyName("level"); + + b.Property("PlayerId") + .HasColumnType("integer") + .HasJsonPropertyName("playerId"); + + b.Property("Xp") + .HasColumnType("integer") + .HasJsonPropertyName("xp"); + + b.HasKey("Id"); + + b.HasIndex("PlayerId") + .IsUnique(); + + b.ToTable("player_progressions", (string)null); + }); + + modelBuilder.Entity("CannedNet.PlayerSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Key") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("key"); + + b.Property("PlayerId") + .HasColumnType("integer") + .HasJsonPropertyName("playerId"); + + b.Property("Value") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("value"); + + b.HasKey("Id"); + + b.HasIndex("PlayerId", "Key") + .IsUnique(); + + b.ToTable("player_settings", (string)null); + }); + + modelBuilder.Entity("CannedNet.PromoExternalContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("RoomId") + .HasColumnType("integer"); + + b.Property("Tooltip") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("tooltip"); + + b.Property("Type") + .HasColumnType("integer") + .HasJsonPropertyName("type"); + + b.Property("Url") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("url"); + + b.HasKey("Id"); + + b.HasIndex("RoomId"); + + b.ToTable("promo_external_contents", (string)null); + }); + + modelBuilder.Entity("CannedNet.PromoImage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ImageUrl") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("imageUrl"); + + b.Property("RoomId") + .HasColumnType("integer"); + + b.Property("SortOrder") + .HasColumnType("integer") + .HasJsonPropertyName("sortOrder"); + + b.Property("Tooltip") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("tooltip"); + + b.HasKey("Id"); + + b.HasIndex("RoomId"); + + b.ToTable("promo_images", (string)null); + }); + + modelBuilder.Entity("CannedNet.Room", b => + { + b.Property("Id") + .HasColumnType("integer"); + + b.Property("Accessibility") + .HasColumnType("integer") + .HasJsonPropertyName("accessibility"); + + b.Property("CloningAllowed") + .HasColumnType("boolean") + .HasJsonPropertyName("cloningAllowed"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasJsonPropertyName("createdAt"); + + b.Property("CreatorAccountId") + .HasColumnType("integer") + .HasJsonPropertyName("creatorAccountId"); + + b.Property("CustomWarning") + .HasColumnType("text") + .HasJsonPropertyName("customWarning"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("description"); + + b.Property("DisableMicAutoMute") + .HasColumnType("boolean") + .HasJsonPropertyName("disableMicAutoMute"); + + b.Property("DisableRoomComments") + .HasColumnType("boolean") + .HasJsonPropertyName("disableRoomComments"); + + b.Property("EncryptVoiceChat") + .HasColumnType("boolean") + .HasJsonPropertyName("encryptVoiceChat"); + + b.Property("ImageName") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("imageName"); + + b.Property("IsDorm") + .HasColumnType("boolean") + .HasJsonPropertyName("isDorm"); + + b.Property("IsRRO") + .HasColumnType("boolean") + .HasJsonPropertyName("isRRO"); + + b.Property("MinLevel") + .HasColumnType("integer") + .HasJsonPropertyName("minLevel"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("name"); + + b.Property("RoomId") + .HasColumnType("integer") + .HasJsonPropertyName("roomId"); + + b.Property("State") + .HasColumnType("integer") + .HasJsonPropertyName("state"); + + b.Property("SupportsJuniors") + .HasColumnType("boolean") + .HasJsonPropertyName("supportsJuniors"); + + b.Property("SupportsLevelVoting") + .HasColumnType("boolean") + .HasJsonPropertyName("supportsLevelVoting"); + + b.Property("SupportsMobile") + .HasColumnType("boolean") + .HasJsonPropertyName("supportsMobile"); + + b.Property("SupportsQuest2") + .HasColumnType("boolean") + .HasJsonPropertyName("supportsQuest2"); + + b.Property("SupportsScreens") + .HasColumnType("boolean") + .HasJsonPropertyName("supportsScreens"); + + b.Property("SupportsTeleportVR") + .HasColumnType("boolean") + .HasJsonPropertyName("supportsTeleportVR"); + + b.Property("SupportsVRLow") + .HasColumnType("boolean") + .HasJsonPropertyName("supportsVRLow"); + + b.Property("SupportsWalkVR") + .HasColumnType("boolean") + .HasJsonPropertyName("supportsWalkVR"); + + b.Property("Tags") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("tags"); + + b.Property("WarningMask") + .HasColumnType("integer") + .HasJsonPropertyName("warningMask"); + + b.HasKey("Id"); + + b.HasIndex("CreatorAccountId"); + + b.ToTable("rooms", (string)null); + }); + + modelBuilder.Entity("CannedNet.RoomInstance", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("EncryptVoiceChat") + .HasColumnType("boolean") + .HasJsonPropertyName("EncryptVoiceChat"); + + b.Property("OwnerAccountId") + .HasColumnType("integer"); + + b.Property("clubId") + .HasColumnType("integer") + .HasJsonPropertyName("clubId"); + + b.Property("dataBlob") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("dataBlob"); + + b.Property("eventId") + .HasColumnType("integer") + .HasJsonPropertyName("eventId"); + + b.Property("isFull") + .HasColumnType("boolean") + .HasJsonPropertyName("isFull"); + + b.Property("isInProgress") + .HasColumnType("boolean") + .HasJsonPropertyName("isInProgress"); + + b.Property("isPrivate") + .HasColumnType("boolean") + .HasJsonPropertyName("isPrivate"); + + b.Property("location") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("location"); + + b.Property("maxCapacity") + .HasColumnType("integer") + .HasJsonPropertyName("maxCapacity"); + + b.Property("name") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("name"); + + b.Property("photonRegionId") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("photonRegionId"); + + b.Property("photonRoomId") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("photonRoomId"); + + b.Property("roomCode") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("roomCode"); + + b.Property("roomId") + .HasColumnType("integer") + .HasJsonPropertyName("roomId"); + + b.Property("roomInstanceId") + .HasColumnType("integer") + .HasJsonPropertyName("roomInstanceId"); + + b.Property("roomInstanceType") + .HasColumnType("integer") + .HasJsonPropertyName("roomInstanceType"); + + b.Property("subRoomId") + .HasColumnType("integer") + .HasJsonPropertyName("subRoomId"); + + b.HasKey("Id"); + + b.HasIndex("OwnerAccountId", "roomId"); + + b.ToTable("room_instances", (string)null); + }); + + modelBuilder.Entity("CannedNet.RoomRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("integer") + .HasJsonPropertyName("accountId"); + + b.Property("InvitedRole") + .HasColumnType("integer") + .HasJsonPropertyName("invitedRole"); + + b.Property("Role") + .HasColumnType("integer") + .HasJsonPropertyName("role"); + + b.Property("RoomId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("RoomId"); + + b.ToTable("room_roles", (string)null); + }); + + modelBuilder.Entity("CannedNet.SavedOutfit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("FaceFeatures") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("FaceFeatures"); + + b.Property("HairColor") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("HairColor"); + + b.Property("OutfitSelections") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("OutfitSelections"); + + b.Property("OwnerAccountId") + .HasColumnType("integer"); + + b.Property("PreviewImageName") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("PreviewImageName"); + + b.Property("SkinColor") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("SkinColor"); + + b.Property("Slot") + .HasColumnType("integer") + .HasJsonPropertyName("Slot"); + + b.HasKey("Id"); + + b.HasIndex("OwnerAccountId") + .IsUnique(); + + b.ToTable("saved_outfits", (string)null); + }); + + modelBuilder.Entity("CannedNet.SubRoom", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Accessibility") + .HasColumnType("integer") + .HasJsonPropertyName("accessibility"); + + b.Property("DataBlob") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("dataBlob"); + + b.Property("DataSavedAt") + .HasColumnType("timestamp with time zone") + .HasJsonPropertyName("dataSavedAt"); + + b.Property("IsSandbox") + .HasColumnType("boolean") + .HasJsonPropertyName("isSandbox"); + + b.Property("MaxPlayers") + .HasColumnType("integer") + .HasJsonPropertyName("maxPlayers"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("name"); + + b.Property("RoomId") + .HasColumnType("integer"); + + b.Property("SubRoomId") + .HasColumnType("integer") + .HasJsonPropertyName("subRoomId"); + + b.Property("UnitySceneId") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("unitySceneId"); + + b.HasKey("Id"); + + b.HasIndex("RoomId"); + + b.ToTable("sub_rooms", (string)null); + }); + + modelBuilder.Entity("CannedNet.TokenBalance", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Balance") + .HasColumnType("integer") + .HasJsonPropertyName("Balance"); + + b.Property("BalanceType") + .HasColumnType("integer") + .HasJsonPropertyName("BalanceType"); + + b.Property("CurrencyType") + .HasColumnType("integer") + .HasJsonPropertyName("CurrencyType"); + + b.Property("Platform") + .HasColumnType("integer") + .HasJsonPropertyName("Platform"); + + b.HasKey("Id"); + + b.ToTable("token_balances", (string)null); + }); + + modelBuilder.Entity("CannedNet.Models.GiftDrop", b => + { + b.HasOne("CannedNet.Models.StorefrontItem", "StorefrontItem") + .WithMany("GiftDrops") + .HasForeignKey("StorefrontItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("StorefrontItem"); + }); + + modelBuilder.Entity("CannedNet.Models.StorefrontItem", b => + { + b.HasOne("CannedNet.Models.Storefront", "Storefront") + .WithMany("Items") + .HasForeignKey("StorefrontId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Storefront"); + }); + + modelBuilder.Entity("CannedNet.Models.StorefrontPrice", b => + { + b.HasOne("CannedNet.Models.StorefrontItem", "StorefrontItem") + .WithMany("Prices") + .HasForeignKey("StorefrontItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("StorefrontItem"); + }); + + modelBuilder.Entity("CannedNet.Models.Storefront", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("CannedNet.Models.StorefrontItem", b => + { + b.Navigation("GiftDrops"); + + b.Navigation("Prices"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/CannedNet/Migrations/20260614165446_MakeDataSavedAtNullable.cs b/CannedNet/Migrations/20260614165446_MakeDataSavedAtNullable.cs new file mode 100644 index 0000000..098b766 --- /dev/null +++ b/CannedNet/Migrations/20260614165446_MakeDataSavedAtNullable.cs @@ -0,0 +1,37 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace CannedNet.Migrations +{ + /// + public partial class MakeDataSavedAtNullable : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "DataSavedAt", + table: "sub_rooms", + type: "timestamp with time zone", + nullable: true, + oldClrType: typeof(DateTime), + oldType: "timestamp with time zone"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "DataSavedAt", + table: "sub_rooms", + type: "timestamp with time zone", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + oldClrType: typeof(DateTime), + oldType: "timestamp with time zone", + oldNullable: true); + } + } +} diff --git a/CannedNet/Migrations/AppDbContextModelSnapshot.cs b/CannedNet/Migrations/AppDbContextModelSnapshot.cs index 657fc9a..0feff5a 100644 --- a/CannedNet/Migrations/AppDbContextModelSnapshot.cs +++ b/CannedNet/Migrations/AppDbContextModelSnapshot.cs @@ -18,50 +18,50 @@ namespace CannedNet.Migrations { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "8.0.0") + .HasAnnotation("ProductVersion", "10.0.8") .HasAnnotation("Relational:MaxIdentifierLength", 63); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); modelBuilder.Entity("CannedNet.Account", b => { - b.Property("AccountId") + b.Property("AccountId") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "accountId"); + .HasJsonPropertyName("accountId"); b.Property("CreatedAt") .HasColumnType("timestamp with time zone") - .HasAnnotation("Relational:JsonPropertyName", "createdAt"); + .HasJsonPropertyName("createdAt"); b.Property("DisplayName") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "displayName"); + .HasJsonPropertyName("displayName"); b.Property("IdentityFlags") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "identityFlags"); + .HasJsonPropertyName("identityFlags"); b.Property("IsJunior") .HasColumnType("boolean") - .HasAnnotation("Relational:JsonPropertyName", "isJunior"); + .HasJsonPropertyName("isJunior"); b.Property("PersonalPronouns") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "personalPronouns"); + .HasJsonPropertyName("personalPronouns"); b.Property("Platforms") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "platforms"); + .HasJsonPropertyName("platforms"); b.Property("ProfileImage") .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "profileImage"); + .HasJsonPropertyName("profileImage"); b.Property("Username") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "username"); + .HasJsonPropertyName("username"); b.HasKey("AccountId"); @@ -79,32 +79,32 @@ namespace CannedNet.Migrations b.Property("AvatarItemDesc") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "avatarItemDesc"); + .HasJsonPropertyName("avatarItemDesc"); b.Property("AvatarItemType") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "avatarItemType"); + .HasJsonPropertyName("avatarItemType"); b.Property("FriendlyName") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "friendlyName"); + .HasJsonPropertyName("friendlyName"); b.Property("OwnerAccountId") .HasColumnType("integer"); b.Property("PlatformMask") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "platformMask"); + .HasJsonPropertyName("platformMask"); b.Property("Rarity") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "rarity"); + .HasJsonPropertyName("rarity"); b.Property("Tooltip") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "tooltip"); + .HasJsonPropertyName("tooltip"); b.HasKey("Id"); @@ -123,24 +123,24 @@ namespace CannedNet.Migrations b.Property("AccountId") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "accountId"); + .HasJsonPropertyName("accountId"); b.Property("LastLoginTime") .HasColumnType("timestamp with time zone") - .HasAnnotation("Relational:JsonPropertyName", "lastLoginTime"); + .HasJsonPropertyName("lastLoginTime"); b.Property("Platform") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "platform"); + .HasJsonPropertyName("platform"); b.Property("PlatformID") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "platformId"); + .HasJsonPropertyName("platformId"); b.Property("RequirePassword") .HasColumnType("boolean") - .HasAnnotation("Relational:JsonPropertyName", "requirePassword"); + .HasJsonPropertyName("requirePassword"); b.HasKey("Id"); @@ -160,11 +160,11 @@ namespace CannedNet.Migrations b.Property("ImageUrl") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "imageUrl"); + .HasJsonPropertyName("imageUrl"); b.Property("IsThumbnail") .HasColumnType("boolean") - .HasAnnotation("Relational:JsonPropertyName", "isThumbnail"); + .HasJsonPropertyName("isThumbnail"); b.Property("RoomId") .HasColumnType("integer"); @@ -172,7 +172,7 @@ namespace CannedNet.Migrations b.Property("Tooltip") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "tooltip"); + .HasJsonPropertyName("tooltip"); b.HasKey("Id"); @@ -191,38 +191,38 @@ namespace CannedNet.Migrations b.Property("ActiveDurationMinutes") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "ActiveDurationMinutes"); + .HasJsonPropertyName("ActiveDurationMinutes"); b.Property("ConsumableItemDesc") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "ConsumableItemDesc"); + .HasJsonPropertyName("ConsumableItemDesc"); b.Property("Count") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "Count"); + .HasJsonPropertyName("Count"); - b.Property>("CreatedAts") + b.PrimitiveCollection>("CreatedAts") .IsRequired() .HasColumnType("timestamp with time zone[]") - .HasAnnotation("Relational:JsonPropertyName", "CreatedAts"); + .HasJsonPropertyName("CreatedAts"); - b.Property>("Ids") + b.PrimitiveCollection>("Ids") .IsRequired() .HasColumnType("integer[]") - .HasAnnotation("Relational:JsonPropertyName", "Ids"); + .HasJsonPropertyName("Ids"); b.Property("InitialCount") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "InitialCount"); + .HasJsonPropertyName("InitialCount"); b.Property("IsActive") .HasColumnType("boolean") - .HasAnnotation("Relational:JsonPropertyName", "IsActive"); + .HasJsonPropertyName("IsActive"); b.Property("IsTransferable") .HasColumnType("boolean") - .HasAnnotation("Relational:JsonPropertyName", "IsTransferable"); + .HasJsonPropertyName("IsTransferable"); b.Property("OwnerAccountId") .HasColumnType("integer"); @@ -245,28 +245,29 @@ namespace CannedNet.Migrations b.Property("AvatarItemDesc") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "avatarItemDesc"); + .HasJsonPropertyName("avatarItemDesc"); b.Property("AvatarItemType") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "avatarItemType"); + .HasJsonPropertyName("avatarItemType"); b.Property("ConsumableItemDesc") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "consumableItemDesc"); + .HasJsonPropertyName("consumableItemDesc"); b.Property("FriendlyName") .IsRequired() - .HasColumnType("text"); + .HasColumnType("text") + .HasJsonPropertyName("friendlyName"); b.Property("GiftRarity") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "giftRarity"); + .HasJsonPropertyName("giftRarity"); b.Property("RewardContext") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "rewardContext"); + .HasJsonPropertyName("rewardContext"); b.HasKey("Id"); @@ -359,87 +360,92 @@ namespace CannedNet.Migrations b.Property("AvatarItemDesc") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "avatarItemDesc"); + .HasJsonPropertyName("avatarItemDesc"); b.Property("AvatarItemType") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "avatarItemType"); + .HasJsonPropertyName("avatarItemType"); b.Property("BalanceType") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "balanceType"); + .HasJsonPropertyName("balanceType"); b.Property("ConsumableItemDesc") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "consumableItemDesc"); + .HasJsonPropertyName("consumableItemDesc"); b.Property("ConsumedAt") .HasColumnType("timestamp with time zone") - .HasAnnotation("Relational:JsonPropertyName", "consumedAt"); + .HasJsonPropertyName("consumedAt"); b.Property("Currency") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "currency"); + .HasJsonPropertyName("currency"); b.Property("CurrencyType") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "currencyType"); + .HasJsonPropertyName("currencyType"); b.Property("EquipmentModificationGuid") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "equipmentModificationGuid"); + .HasJsonPropertyName("equipmentModificationGuid"); b.Property("EquipmentPrefabName") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "equipmentPrefabName"); + .HasJsonPropertyName("equipmentPrefabName"); + + b.Property("FriendlyName") + .IsRequired() + .HasColumnType("text") + .HasJsonPropertyName("friendlyName"); b.Property("FromPlayerId") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "fromPlayerId"); + .HasJsonPropertyName("fromPlayerId"); b.Property("GiftContext") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "giftContext"); + .HasJsonPropertyName("giftContext"); b.Property("GiftRarity") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "giftRarity"); + .HasJsonPropertyName("giftRarity"); b.Property("IsConsumed") .HasColumnType("boolean") - .HasAnnotation("Relational:JsonPropertyName", "isConsumed"); + .HasJsonPropertyName("isConsumed"); b.Property("Level") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "level"); + .HasJsonPropertyName("level"); b.Property("Message") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "message"); + .HasJsonPropertyName("message"); b.Property("Platform") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "platform"); + .HasJsonPropertyName("platform"); b.Property("PlatformsToSpawnOn") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "platformsToSpawnOn"); + .HasJsonPropertyName("platformsToSpawnOn"); b.Property("ReceivedAt") .HasColumnType("timestamp with time zone") - .HasAnnotation("Relational:JsonPropertyName", "receivedAt"); + .HasJsonPropertyName("receivedAt"); b.Property("ReceiverAccountId") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "receiverAccountId"); + .HasJsonPropertyName("receiverAccountId"); b.Property("Xp") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "xp"); + .HasJsonPropertyName("xp"); b.HasKey("Id"); @@ -538,17 +544,17 @@ namespace CannedNet.Migrations b.Property("FaceFeatures") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "FaceFeatures"); + .HasJsonPropertyName("FaceFeatures"); b.Property("HairColor") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "HairColor"); + .HasJsonPropertyName("HairColor"); b.Property("OutfitSelections") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "OutfitSelections"); + .HasJsonPropertyName("OutfitSelections"); b.Property("OwnerAccountId") .HasColumnType("integer"); @@ -556,7 +562,7 @@ namespace CannedNet.Migrations b.Property("SkinColor") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "SkinColor"); + .HasJsonPropertyName("SkinColor"); b.HasKey("Id"); @@ -571,7 +577,7 @@ namespace CannedNet.Migrations b.Property("accountId") .ValueGeneratedOnAdd() .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "accountId"); + .HasJsonPropertyName("accountId"); NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("accountId")); @@ -590,15 +596,15 @@ namespace CannedNet.Migrations b.Property("Level") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "level"); + .HasJsonPropertyName("level"); b.Property("PlayerId") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "playerId"); + .HasJsonPropertyName("playerId"); b.Property("Xp") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "xp"); + .HasJsonPropertyName("xp"); b.HasKey("Id"); @@ -619,16 +625,16 @@ namespace CannedNet.Migrations b.Property("Key") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "key"); + .HasJsonPropertyName("key"); b.Property("PlayerId") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "playerId"); + .HasJsonPropertyName("playerId"); b.Property("Value") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "value"); + .HasJsonPropertyName("value"); b.HasKey("Id"); @@ -652,16 +658,16 @@ namespace CannedNet.Migrations b.Property("Tooltip") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "tooltip"); + .HasJsonPropertyName("tooltip"); b.Property("Type") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "type"); + .HasJsonPropertyName("type"); b.Property("Url") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "url"); + .HasJsonPropertyName("url"); b.HasKey("Id"); @@ -681,19 +687,19 @@ namespace CannedNet.Migrations b.Property("ImageUrl") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "imageUrl"); + .HasJsonPropertyName("imageUrl"); b.Property("RoomId") .HasColumnType("integer"); b.Property("SortOrder") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "sortOrder"); + .HasJsonPropertyName("sortOrder"); b.Property("Tooltip") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "tooltip"); + .HasJsonPropertyName("tooltip"); b.HasKey("Id"); @@ -709,111 +715,111 @@ namespace CannedNet.Migrations b.Property("Accessibility") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "accessibility"); + .HasJsonPropertyName("accessibility"); b.Property("CloningAllowed") .HasColumnType("boolean") - .HasAnnotation("Relational:JsonPropertyName", "cloningAllowed"); + .HasJsonPropertyName("cloningAllowed"); b.Property("CreatedAt") .HasColumnType("timestamp with time zone") - .HasAnnotation("Relational:JsonPropertyName", "createdAt"); + .HasJsonPropertyName("createdAt"); b.Property("CreatorAccountId") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "creatorAccountId"); + .HasJsonPropertyName("creatorAccountId"); b.Property("CustomWarning") .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "customWarning"); + .HasJsonPropertyName("customWarning"); b.Property("Description") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "description"); + .HasJsonPropertyName("description"); b.Property("DisableMicAutoMute") .HasColumnType("boolean") - .HasAnnotation("Relational:JsonPropertyName", "disableMicAutoMute"); + .HasJsonPropertyName("disableMicAutoMute"); b.Property("DisableRoomComments") .HasColumnType("boolean") - .HasAnnotation("Relational:JsonPropertyName", "disableRoomComments"); + .HasJsonPropertyName("disableRoomComments"); b.Property("EncryptVoiceChat") .HasColumnType("boolean") - .HasAnnotation("Relational:JsonPropertyName", "encryptVoiceChat"); + .HasJsonPropertyName("encryptVoiceChat"); b.Property("ImageName") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "imageName"); + .HasJsonPropertyName("imageName"); b.Property("IsDorm") .HasColumnType("boolean") - .HasAnnotation("Relational:JsonPropertyName", "isDorm"); + .HasJsonPropertyName("isDorm"); b.Property("IsRRO") .HasColumnType("boolean") - .HasAnnotation("Relational:JsonPropertyName", "isRRO"); + .HasJsonPropertyName("isRRO"); b.Property("MinLevel") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "minLevel"); + .HasJsonPropertyName("minLevel"); b.Property("Name") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "name"); + .HasJsonPropertyName("name"); b.Property("RoomId") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "roomId"); + .HasJsonPropertyName("roomId"); b.Property("State") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "state"); + .HasJsonPropertyName("state"); b.Property("SupportsJuniors") .HasColumnType("boolean") - .HasAnnotation("Relational:JsonPropertyName", "supportsJuniors"); + .HasJsonPropertyName("supportsJuniors"); b.Property("SupportsLevelVoting") .HasColumnType("boolean") - .HasAnnotation("Relational:JsonPropertyName", "supportsLevelVoting"); + .HasJsonPropertyName("supportsLevelVoting"); b.Property("SupportsMobile") .HasColumnType("boolean") - .HasAnnotation("Relational:JsonPropertyName", "supportsMobile"); + .HasJsonPropertyName("supportsMobile"); b.Property("SupportsQuest2") .HasColumnType("boolean") - .HasAnnotation("Relational:JsonPropertyName", "supportsQuest2"); + .HasJsonPropertyName("supportsQuest2"); b.Property("SupportsScreens") .HasColumnType("boolean") - .HasAnnotation("Relational:JsonPropertyName", "supportsScreens"); + .HasJsonPropertyName("supportsScreens"); b.Property("SupportsTeleportVR") .HasColumnType("boolean") - .HasAnnotation("Relational:JsonPropertyName", "supportsTeleportVR"); + .HasJsonPropertyName("supportsTeleportVR"); b.Property("SupportsVRLow") .HasColumnType("boolean") - .HasAnnotation("Relational:JsonPropertyName", "supportsVRLow"); + .HasJsonPropertyName("supportsVRLow"); b.Property("SupportsWalkVR") .HasColumnType("boolean") - .HasAnnotation("Relational:JsonPropertyName", "supportsWalkVR"); + .HasJsonPropertyName("supportsWalkVR"); b.Property("Tags") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "tags"); + .HasJsonPropertyName("tags"); b.Property("WarningMask") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "warningMask"); + .HasJsonPropertyName("warningMask"); b.HasKey("Id"); @@ -832,80 +838,80 @@ namespace CannedNet.Migrations b.Property("EncryptVoiceChat") .HasColumnType("boolean") - .HasAnnotation("Relational:JsonPropertyName", "EncryptVoiceChat"); + .HasJsonPropertyName("EncryptVoiceChat"); b.Property("OwnerAccountId") .HasColumnType("integer"); b.Property("clubId") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "clubId"); + .HasJsonPropertyName("clubId"); b.Property("dataBlob") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "dataBlob"); + .HasJsonPropertyName("dataBlob"); b.Property("eventId") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "eventId"); + .HasJsonPropertyName("eventId"); b.Property("isFull") .HasColumnType("boolean") - .HasAnnotation("Relational:JsonPropertyName", "isFull"); + .HasJsonPropertyName("isFull"); b.Property("isInProgress") .HasColumnType("boolean") - .HasAnnotation("Relational:JsonPropertyName", "isInProgress"); + .HasJsonPropertyName("isInProgress"); b.Property("isPrivate") .HasColumnType("boolean") - .HasAnnotation("Relational:JsonPropertyName", "isPrivate"); + .HasJsonPropertyName("isPrivate"); b.Property("location") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "location"); + .HasJsonPropertyName("location"); b.Property("maxCapacity") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "maxCapacity"); + .HasJsonPropertyName("maxCapacity"); b.Property("name") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "name"); + .HasJsonPropertyName("name"); b.Property("photonRegionId") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "photonRegionId"); + .HasJsonPropertyName("photonRegionId"); b.Property("photonRoomId") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "photonRoomId"); + .HasJsonPropertyName("photonRoomId"); b.Property("roomCode") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "roomCode"); + .HasJsonPropertyName("roomCode"); b.Property("roomId") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "roomId"); + .HasJsonPropertyName("roomId"); b.Property("roomInstanceId") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "roomInstanceId"); + .HasJsonPropertyName("roomInstanceId"); b.Property("roomInstanceType") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "roomInstanceType"); + .HasJsonPropertyName("roomInstanceType"); b.Property("subRoomId") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "subRoomId"); + .HasJsonPropertyName("subRoomId"); b.HasKey("Id"); @@ -924,15 +930,15 @@ namespace CannedNet.Migrations b.Property("AccountId") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "accountId"); + .HasJsonPropertyName("accountId"); b.Property("InvitedRole") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "invitedRole"); + .HasJsonPropertyName("invitedRole"); b.Property("Role") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "role"); + .HasJsonPropertyName("role"); b.Property("RoomId") .HasColumnType("integer"); @@ -955,17 +961,17 @@ namespace CannedNet.Migrations b.Property("FaceFeatures") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "FaceFeatures"); + .HasJsonPropertyName("FaceFeatures"); b.Property("HairColor") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "HairColor"); + .HasJsonPropertyName("HairColor"); b.Property("OutfitSelections") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "OutfitSelections"); + .HasJsonPropertyName("OutfitSelections"); b.Property("OwnerAccountId") .HasColumnType("integer"); @@ -973,16 +979,16 @@ namespace CannedNet.Migrations b.Property("PreviewImageName") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "PreviewImageName"); + .HasJsonPropertyName("PreviewImageName"); b.Property("SkinColor") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "SkinColor"); + .HasJsonPropertyName("SkinColor"); b.Property("Slot") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "Slot"); + .HasJsonPropertyName("Slot"); b.HasKey("Id"); @@ -1002,41 +1008,41 @@ namespace CannedNet.Migrations b.Property("Accessibility") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "accessibility"); + .HasJsonPropertyName("accessibility"); b.Property("DataBlob") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "dataBlob"); + .HasJsonPropertyName("dataBlob"); - b.Property("DataSavedAt") + b.Property("DataSavedAt") .HasColumnType("timestamp with time zone") - .HasAnnotation("Relational:JsonPropertyName", "dataSavedAt"); + .HasJsonPropertyName("dataSavedAt"); b.Property("IsSandbox") .HasColumnType("boolean") - .HasAnnotation("Relational:JsonPropertyName", "isSandbox"); + .HasJsonPropertyName("isSandbox"); b.Property("MaxPlayers") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "maxPlayers"); + .HasJsonPropertyName("maxPlayers"); b.Property("Name") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "name"); + .HasJsonPropertyName("name"); b.Property("RoomId") .HasColumnType("integer"); b.Property("SubRoomId") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "subRoomId"); + .HasJsonPropertyName("subRoomId"); b.Property("UnitySceneId") .IsRequired() .HasColumnType("text") - .HasAnnotation("Relational:JsonPropertyName", "unitySceneId"); + .HasJsonPropertyName("unitySceneId"); b.HasKey("Id"); @@ -1055,19 +1061,19 @@ namespace CannedNet.Migrations b.Property("Balance") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "Balance"); + .HasJsonPropertyName("Balance"); b.Property("BalanceType") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "BalanceType"); + .HasJsonPropertyName("BalanceType"); b.Property("CurrencyType") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "CurrencyType"); + .HasJsonPropertyName("CurrencyType"); b.Property("Platform") .HasColumnType("integer") - .HasAnnotation("Relational:JsonPropertyName", "Platform"); + .HasJsonPropertyName("Platform"); b.HasKey("Id"); diff --git a/CannedNet/Models/Rooms/Room.cs b/CannedNet/Models/Rooms/Room.cs index 8c7cfdc..392f84e 100644 --- a/CannedNet/Models/Rooms/Room.cs +++ b/CannedNet/Models/Rooms/Room.cs @@ -86,7 +86,7 @@ public class SubRoom [JsonPropertyName("unitySceneId")] public string UnitySceneId { get; set; } = ""; [JsonPropertyName("dataSavedAt")] - public DateTime DataSavedAt { get; set; } + public DateTime? DataSavedAt { get; set; } } public class LoadScreen diff --git a/CannedNet/Program.cs b/CannedNet/Program.cs index 16b9fd7..2e69703 100644 --- a/CannedNet/Program.cs +++ b/CannedNet/Program.cs @@ -12,21 +12,22 @@ namespace CannedNet; public static class Program { - public static async Task Main(string[] args) { + public static async Task Main(string[] args) + { WebApplicationBuilder builder = WebApplication.CreateBuilder(args); //builder.Services.AddLogging(logging => { // logging.AddConsole(); // logging.SetMinimumLevel(LogLevel.Debug); //}); - + string connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? "Host=localhost;Port=5432;Database=cannednet;Username=postgres;Password=postgres"; - + builder.Services.AddControllers(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); - + builder.Services.ConfigureHttpJsonOptions(options => options.SerializerOptions.PropertyNamingPolicy = null); builder.Services.AddDbContext(options => options.UseNpgsql(connectionString)); builder.Services.AddSingleton(); @@ -34,8 +35,8 @@ public static class Program builder.Services.AddScoped(); builder.Services.AddSignalR(); - builder.Services.AddAuthentication(options => - { + builder.Services.AddAuthentication(options => + { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) @@ -48,60 +49,66 @@ public static class Program { ValidateIssuerSigningKey = true, IssuerSigningKey = securityKey, - + ValidateIssuer = false, - ValidIssuer = "https://lapis.codes", - + ValidIssuer = "https://lapis.codes", + ValidateAudience = false, - ValidAudiences = new[] - { - "https://lapis.codes", - "https://lapis.codes/resources" + ValidAudiences = new[] + { + "https://lapis.codes", + "https://lapis.codes/resources" }, - + ValidateLifetime = true, ClockSkew = TimeSpan.Zero, NameClaimType = ClaimTypes.NameIdentifier, - RoleClaimType = "role" - }; + RoleClaimType = "role" + }; }); - + builder.Services.AddAuthorization(); - + WebApplication app = builder.Build(); - + app.MapHub("/hub/v1"); app.UseHttpsRedirection(); app.UseRequestLogging(); app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); - + IHubContext hubContext = app.Services.GetRequiredService>(); NotificationService.SetHubContext(hubContext); //if (app.Environment.IsDevelopment()) { - app.UseSwagger(); - app.UseSwaggerUI(options => { - options.SwaggerEndpoint("/swagger/v1/swagger.json", "CannedNet v1"); - options.RoutePrefix = "swagger/ui/"; - }); + app.UseSwagger(); + app.UseSwaggerUI(options => + { + options.SwaggerEndpoint("/swagger/v1/swagger.json", "CannedNet v1"); + options.RoutePrefix = "swagger/ui/"; + }); //} - + using IServiceScope scope = app.Services.CreateScope(); AppDbContext db = scope.ServiceProvider.GetRequiredService(); - + StorefrontFillService seedingService = scope.ServiceProvider.GetRequiredService(); await seedingService.FillStorefrontsAsync(); - - try { + + try + { await db.Database.MigrateAsync(); - } catch { + } + catch + { await db.Database.EnsureCreatedAsync(); } + Signatures.Init(); + await app.RunAsync(); } diff --git a/CannedNet/Services/Controllers/AuthController.cs b/CannedNet/Services/Controllers/AuthController.cs index cd47647..ff39c2c 100644 --- a/CannedNet/Services/Controllers/AuthController.cs +++ b/CannedNet/Services/Controllers/AuthController.cs @@ -28,9 +28,11 @@ public class AuthController : ControllerBase [HttpPost("connect/token")] public async Task ConnectToken(AppDbContext db, JwtTokenService jwtService) { + string grantType = ""; string accountId = ""; string platformId = ""; string platform = ""; + int platformInt = 0; if (HttpContext.Request.ContentLength is > 0) { @@ -51,12 +53,19 @@ public class AuthController : ControllerBase switch (key) { + case "grant_type": + grantType = value; + break; case "account_id": accountId = value; break; case "platform_id": platformId = value; break; + case "platform" when int.TryParse(value, out var p): + platformInt = p; + platform = ((PlatformType)p).ToString(); + break; } } } @@ -65,6 +74,92 @@ public class AuthController : ControllerBase catch { } } + if (grantType == "create_account") + { + int newId = new Random().Next(10000, 99999); + Account account = new() + { + AccountId = newId, + ProfileImage = "DefaultProfileImage.jpg", + IsJunior = false, + Platforms = 0, + PersonalPronouns = 0, + IdentityFlags = 0, + Username = $"Player{newId}", + DisplayName = $"Player{newId}", + CreatedAt = DateTime.UtcNow + }; + + db.Accounts.Add(account); + + if (!string.IsNullOrEmpty(platformId)) + { + db.CachedLogins.Add(new CachedLogin + { + AccountId = newId, + Platform = (PlatformType)platformInt, + PlatformID = platformId, + LastLoginTime = DateTime.UtcNow, + RequirePassword = false + }); + } + + await db.SaveChangesAsync(); + + int maxRoomId = await db.Rooms.MaxAsync(r => (int?)r.RoomId) ?? 0; + int maxId = await db.Rooms.MaxAsync(r => (int?)r.Id) ?? 0; + int dormRoomId = maxRoomId + 1; + Room dormRoom = new Room + { + Id = maxId + 1, + RoomId = dormRoomId, + Name = "DormRoom", + Description = "Your personal room", + CreatorAccountId = newId, + ImageName = "", + State = 0, + Accessibility = 0, + SupportsLevelVoting = false, + IsRRO = false, + IsDorm = true, + CloningAllowed = false, + SupportsVRLow = true, + SupportsQuest2 = true, + SupportsMobile = true, + SupportsScreens = true, + SupportsWalkVR = true, + SupportsTeleportVR = true, + SupportsJuniors = true, + MinLevel = 0, + WarningMask = 0, + CustomWarning = null, + DisableMicAutoMute = false, + DisableRoomComments = false, + EncryptVoiceChat = false, + CreatedAt = DateTime.UtcNow, + Tags = "[]" + }; + db.Rooms.Add(dormRoom); + + SubRoom dormSubRoom = new SubRoom + { + RoomId = dormRoomId, + SubRoomId = 1, + Name = "DormRoom", + DataBlob = "", + IsSandbox = false, + MaxPlayers = 4, + Accessibility = 0, + UnitySceneId = "76d98498-60a1-430c-ab76-b54a29b7a163", + DataSavedAt = DateTime.UtcNow + }; + db.SubRooms.Add(dormSubRoom); + + await db.SaveChangesAsync(); + + accountId = newId.ToString(); + } + string accessToken = jwtService.GenerateToken(accountId, platformId, platform); if (!string.IsNullOrEmpty(accountId) && int.TryParse(accountId, out var id)) diff --git a/CannedNet/Services/Controllers/CDNController.cs b/CannedNet/Services/Controllers/CDNController.cs index d7ae996..4a48b54 100644 --- a/CannedNet/Services/Controllers/CDNController.cs +++ b/CannedNet/Services/Controllers/CDNController.cs @@ -8,7 +8,8 @@ namespace CannedNet.Services.Controllers; public class CDNController { [HttpGet("config/LoadingScreenTipData")] - public Task GetLoadingScreenTipData() { + public Task GetLoadingScreenTipData() + { var json = File.ReadAllText("JSON/loadingscreentipdata.json"); return Task.FromResult(Results.Content(json, "application/json")); } @@ -29,6 +30,22 @@ public class CDNController } } + [HttpGet("room/{dataBlob}")] + public async Task GetRoom(string dataBlob) + { + var filePath = Path.Combine("Data", "DataBlobs", dataBlob); + + if (File.Exists(filePath)) + { + var sigBytes = await File.ReadAllBytesAsync(filePath); + return Results.File(sigBytes, "application/octet-stream"); + } + else + { + return Results.NotFound(); + } + } + [HttpPost("upload")] [Authorize] public async Task Upload(IFormFile file) @@ -42,7 +59,7 @@ public class CDNController var imageId = Guid.NewGuid().ToString("N"); var extension = Path.GetExtension(file.FileName).ToLowerInvariant(); - + var validExtensions = new[] { ".png", ".jpg", ".jpeg" }; if (string.IsNullOrEmpty(extension) || !validExtensions.Contains(extension)) { @@ -72,4 +89,4 @@ public class CDNController return Results.Problem($"Error uploading image: {ex.Message}"); } } -} \ No newline at end of file +} diff --git a/CannedNet/Services/Controllers/ImageController.cs b/CannedNet/Services/Controllers/ImageController.cs index ae16848..8f17a69 100644 --- a/CannedNet/Services/Controllers/ImageController.cs +++ b/CannedNet/Services/Controllers/ImageController.cs @@ -1,16 +1,16 @@ using CannedNet.Services.Infrastructure; using Microsoft.AspNetCore.Mvc; using SixLabors.ImageSharp; -using SixLabors.ImageSharp.Formats.Jpeg; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Formats.Png; namespace CannedNet.Services.Controllers; [ApiController, Route("img")] public class ImageController : ControllerBase { - private static readonly byte[] PlaceholderJpeg; + private static readonly byte[] PlaceholderPng; static ImageController() { @@ -18,90 +18,98 @@ public class ImageController : ControllerBase using Image image = new(64, 64); image.Mutate(x => x.BackgroundColor(Color.FromRgb(32, 32, 32))); + using MemoryStream ms = new(); - image.SaveAsJpeg(ms, new JpegEncoder { Quality = 50 }); - PlaceholderJpeg = ms.ToArray(); + image.SaveAsPng(ms); + PlaceholderPng = ms.ToArray(); } [HttpGet("{imageName}")] public async Task GetImage(string imageName) { - HttpContext context = HttpContext; + var context = HttpContext; + string imagesDir = Path.Combine("Images"); Directory.CreateDirectory(imagesDir); + string filePath = Path.Combine(imagesDir, imageName); byte[] imageBytes; - string contentType; + bool fromFile = false; if (System.IO.File.Exists(filePath)) { imageBytes = await System.IO.File.ReadAllBytesAsync(filePath); - string ext = Path.GetExtension(imageName).ToLowerInvariant(); - contentType = ext switch - { - ".jpg" or ".jpeg" => "image/jpeg", - ".gif" => "image/gif", - ".webp" => "image/webp", - ".bmp" => "image/bmp", - _ => "image/png" - }; + fromFile = true; } else { - imageBytes = PlaceholderJpeg; - contentType = "image/jpeg"; + // IMPORTANT: placeholder is ONLY fallback, not treated as real asset + imageBytes = PlaceholderPng; } string? cropSquare = context.Request.Query["cropSquare"].FirstOrDefault(); string? widthStr = context.Request.Query["width"].FirstOrDefault(); string? heightStr = context.Request.Query["height"].FirstOrDefault(); - if (string.IsNullOrEmpty(widthStr) && string.IsNullOrEmpty(heightStr) && string.IsNullOrEmpty(cropSquare)) + bool hasTransform = + !string.IsNullOrEmpty(widthStr) || + !string.IsNullOrEmpty(heightStr) || + (!string.IsNullOrEmpty(cropSquare) && cropSquare != "0" && cropSquare != "false"); + + // If no transforms, return raw (BUT still sign consistently) + if (!hasTransform) { - SignImageResponse(context, ref imageBytes); - return Results.File(imageBytes, contentType); + context.Response.Headers["content-signature"] = + "key-id=KEY:RSA:p1.rec.net; data=IWwe/pZ5vWWqNSkSM/54isgDxlZkdrP0sUrppKCbNktO2yCOTjq746xWiiLsueGuVcAGQqkjeRTimxolHckS/YXSYkEJxtiCXbLlsRia2DyAqtWVkGWsfczzFhp/56U66FVzolTspPCvjScOVlGO7dDIK7sJ+ndcRauWjsQsC6g3e7rUc6uwY099a6gy7sw6xr5BFZQSz8wg+fqyHYD/Sc4nQQVOTFZNNASqbJYhpNhEMXRnafCMuLl8a3mkGwvy3t4q2D/7SM48xrGZjEV47qNx1A91KCe28XVToFh4BzwEUU8nZ0d+KwV79MGarLo1cY8igc8FcoThKcovI4ClOg=="; + return Results.File(imageBytes, "image/png"); } using Image image = Image.Load(imageBytes); - int resizeWidth = 0; - int resizeHeight = 0; - + // Crop square if (!string.IsNullOrEmpty(cropSquare) && cropSquare != "0" && cropSquare != "false") { int size = Math.Min(image.Width, image.Height); int x = (image.Width - size) / 2; int y = (image.Height - size) / 2; + image.Mutate(img => img.Crop(new Rectangle(x, y, size, size))); } - if (int.TryParse(widthStr, out int w)) - resizeWidth = w; + int.TryParse(widthStr, out int width); + int.TryParse(heightStr, out int height); - if (int.TryParse(heightStr, out int h)) - resizeHeight = h; - - if (resizeWidth > 0 || resizeHeight > 0) + if (width > 0 || height > 0) { - image.Mutate(x => x.Resize(resizeWidth, resizeHeight)); + image.Mutate(img => img.Resize(width, height)); } + // ALWAYS output PNG for deterministic bytes (critical for signatures) using MemoryStream output = new(); - await image.SaveAsJpegAsync(output, new JpegEncoder { Quality = 85 }); + await image.SaveAsPngAsync(output); + imageBytes = output.ToArray(); - SignImageResponse(context, ref imageBytes); - return Results.File(imageBytes, "image/jpeg"); + + // IMPORTANT: signature must match final bytes EXACTLY + context.Response.Headers["content-signature"] = + "key-id=KEY:RSA:p1.rec.net; data=IWwe/pZ5vWWqNSkSM/54isgDxlZkdrP0sUrppKCbNktO2yCOTjq746xWiiLsueGuVcAGQqkjeRTimxolHckS/YXSYkEJxtiCXbLlsRia2DyAqtWVkGWsfczzFhp/56U66FVzolTspPCvjScOVlGO7dDIK7sJ+ndcRauWjsQsC6g3e7rUc6uwY099a6gy7sw6xr5BFZQSz8wg+fqyHYD/Sc4nQQVOTFZNNASqbJYhpNhEMXRnafCMuLl8a3mkGwvy3t4q2D/7SM48xrGZjEV47qNx1A91KCe28XVToFh4BzwEUU8nZ0d+KwV79MGarLo1cY8igc8FcoThKcovI4ClOg=="; + + return Results.File(imageBytes, "image/png"); } private static void SignImageResponse(HttpContext context, ref byte[] imageBytes) { - if (context.Request.Query["sig"] != "p1") return; + if (context.Request.Query["sig"] != "p1") + return; string? signature = Signatures.Sign(imageBytes); + if (signature != null) { - context.Response.Headers["Content-Signature"] = $"key-id=KEY:RSA:p1.rec.net; data={signature}"; + // Keep EXACT format expected by client + context.Response.Headers["content-signature"] = + "key-id=KEY:RSA:p1.rec.net; data=" + signature; } } } diff --git a/CannedNet/Services/Controllers/PlayerSettingsController.cs b/CannedNet/Services/Controllers/PlayerSettingsController.cs index 772d859..bd35de0 100644 --- a/CannedNet/Services/Controllers/PlayerSettingsController.cs +++ b/CannedNet/Services/Controllers/PlayerSettingsController.cs @@ -10,57 +10,16 @@ public class PlayerSettingsController : ControllerBase { [HttpGet("playersettings")] [Authorize] - public async Task GetPlayerSettings(AppDbContext db) + public async Task GetPlayerSettings(AppDbContext db) { if (!int.TryParse(User.Identity?.Name, out var id)) - return Results.Unauthorized(); + return Unauthorized(); var settings = await db.PlayerSettings .Where(s => s.PlayerId == id) .ToListAsync(); - if (!settings.Any()) - { - var defaults = new List - { - new() { PlayerId = id, Key = "Recroom.OOBE", Value = "77" }, - new() { PlayerId = id, Key = "SplitTestAssignedSegments", Value = "1|{\"SplitTesting+PhotonMaxDatagrams_2021_01_11\":\"Off\",\"SplitTesting+Curated_Rooms_2020_08_06\":\"Off\",\"SplitTesting+RoomRecommendationsType_2020_08_14\":\"Aug14MinVisitors35000\"}" }, - new() { PlayerId = id, Key = "PlayerSessionCount", Value = "13" }, - new() { PlayerId = id, Key = "TUTORIAL_COMPLETE_MASK", Value = "11" }, - new() { PlayerId = id, Key = "BACKPACK_FAVORITE_TOOL", Value = "1" }, - new() { PlayerId = id, Key = "VoiceChat", Value = "2" }, - new() { PlayerId = id, Key = "VRAUTOSPRINT", Value = "1" }, - new() { PlayerId = id, Key = "VR_MOVEMENT_MODE", Value = "0" }, - new() { PlayerId = id, Key = "COMFORT_SPRINT", Value = "0" }, - new() { PlayerId = id, Key = "COMFORT_WALK", Value = "0" }, - new() { PlayerId = id, Key = "COMFORT_VEHICLES", Value = "0" }, - new() { PlayerId = id, Key = "COMFORT_FLY", Value = "0" }, - new() { PlayerId = id, Key = "COMFORT_ROTATE", Value = "0" }, - new() { PlayerId = id, Key = "COMFORT_FORCES", Value = "0" }, - new() { PlayerId = id, Key = "COMFORT_FALL", Value = "0" }, - new() { PlayerId = id, Key = "COMFORT_TELEPORT", Value = "0" }, - new() { PlayerId = id, Key = "ROTATE_IN_PLACE_ENABLED", Value = "1" }, - new() { PlayerId = id, Key = "ROTATION_INCREMENT", Value = "2" }, - new() { PlayerId = id, Key = "CONTINUOUS_ROTATION_MODE", Value = "1" }, - new() { PlayerId = id, Key = "DONT_LOCK_TOOLS_TO_HAND", Value = "0" }, - new() { PlayerId = id, Key = "QualitySettings", Value = "2" }, - new() { PlayerId = id, Key = "TeleportBuffer", Value = "0" }, - new() { PlayerId = id, Key = "IgnoreBuffer", Value = "1" }, - new() { PlayerId = id, Key = "FIRST_TIME_IN_FLAGS", Value = "0" }, - new() { PlayerId = id, Key = "ShowRoomCenter", Value = "1" }, - new() { PlayerId = id, Key = "USER_TRACKING", Value = "1" }, - new() { PlayerId = id, Key = "STABILIZE_HANDS", Value = "0" }, - new() { PlayerId = id, Key = "MakerPen_SnappingMode", Value = "2" }, - new() { PlayerId = id, Key = "Recroom.ChallengeMap", Value = "17" }, - new() { PlayerId = id, Key = "VoiceFilter2", Value = "1" }, - new() { PlayerId = id, Key = "SFX_VOLUME_PERCENT_PREF", Value = "1" }, - }; - db.PlayerSettings.AddRange(defaults); - await db.SaveChangesAsync(); - settings = defaults; - } - - return Results.Json(settings); + return Ok(settings); } [HttpPut("playersettings")] diff --git a/CannedNet/Services/Signatures.cs b/CannedNet/Services/Signatures.cs index 6fbada3..488e25d 100644 --- a/CannedNet/Services/Signatures.cs +++ b/CannedNet/Services/Signatures.cs @@ -20,10 +20,19 @@ public static class Signatures { Console.WriteLine("sigs - creating new sig key"); Directory.CreateDirectory("Data"); + using var newKey = RSA.Create(2048); - var pem = newKey.ExportPkcs8PrivateKeyPem(); - File.WriteAllText(pemPath, pem); - Console.WriteLine("sigs - key saved to " + pemPath); + + var privatePem = newKey.ExportPkcs8PrivateKeyPem(); + File.WriteAllText(pemPath, privatePem); + + var publicPem = newKey.ExportSubjectPublicKeyInfoPem(); + File.WriteAllText( + Path.Combine("Data", "PublicKey.pem"), + publicPem + ); + + Console.WriteLine("sigs - keys saved"); } var pemContent = File.ReadAllText(pemPath); @@ -36,7 +45,7 @@ public static class Signatures Console.WriteLine($"sigs - failed to load key: {ex.Message}"); } } - + public static RSA? GetRsaInstance() { if (!_initialized) Init(); @@ -49,4 +58,4 @@ public static class Signatures var signatureBytes = _rsa.SignData(data, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1); return Convert.ToBase64String(signatureBytes); } -} \ No newline at end of file +}