Skip to content

Commit f6af5c8

Browse files
fix: prevent loading stale profiles on realm change (#8834)
1 parent 050db6d commit f6af5c8

6 files changed

Lines changed: 52 additions & 9 deletions

File tree

Explorer/Assets/DCL/Infrastructure/Global/Dynamic/DynamicWorldContainer.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@
5858
using DCL.Multiplayer.Profiles.BroadcastProfiles;
5959
using DCL.Multiplayer.Profiles.Entities;
6060
using DCL.Multiplayer.Profiles.Poses;
61+
using DCL.Multiplayer.Profiles.RemoteAnnouncements;
62+
using DCL.Multiplayer.Profiles.RemoteProfiles;
6163
using DCL.Multiplayer.Profiles.Tables;
6264
using DCL.Multiplayer.SDK.Systems.GlobalWorld;
6365
using DCL.Navmap;
@@ -443,6 +445,11 @@ static IMultiPool MultiPoolFactory() =>
443445

444446
var messagePipesHub = new MessagePipesHub(roomHub, MultiPoolFactory(), memoryPool, islandThroughputBunch, sceneThroughputBunch, chatThroughputBunch);
445447

448+
var remoteMetadata = new DebounceRemoteMetadata(new RemoteMetadata(roomHub, staticContainer.RealmData, bootstrapContainer.DecentralandUrlsSource));
449+
450+
var remoteAnnouncements = new RemoteAnnouncements(messagePipesHub);
451+
var remoteProfiles = new RemoteProfiles(profilesRepository, remoteMetadata);
452+
446453
var roomsStatus = new RoomsStatus(
447454
roomHub,
448455

@@ -471,7 +478,7 @@ static IMultiPool MultiPoolFactory() =>
471478

472479
var worldAccessGate = new PrivateWorldAccessHandler(worldPermissionsService, mvcManager, staticContainer.RealmData);
473480
var realmNavigatorContainer = RealmNavigationContainer.Create
474-
(staticContainer, bootstrapContainer, lodContainer, realmContainer, remoteEntities, globalWorld, roomHub, terrainContainer.Landscape, exposedGlobalDataContainer, loadingScreen, placesAPIService, worldAccessGate);
481+
(staticContainer, bootstrapContainer, lodContainer, realmContainer, remoteEntities, remoteAnnouncements, remoteProfiles, globalWorld, roomHub, terrainContainer.Landscape, exposedGlobalDataContainer, loadingScreen, placesAPIService, worldAccessGate);
475482

476483
IHealthCheck livekitHealthCheck = bootstrapContainer.DebugSettings.EnableEmulateNoLivekitConnection
477484
? new IHealthCheck.AlwaysFails()
@@ -649,8 +656,6 @@ await MapRendererContainer
649656
// Configure proxies for scene-side masked emote system
650657
staticContainer.EmotesMessageBusProxy.SetObject(multiplayerEmotesMessageBus);
651658

652-
var remoteMetadata = new DebounceRemoteMetadata(new RemoteMetadata(roomHub, staticContainer.RealmData, bootstrapContainer.DecentralandUrlsSource));
653-
654659
var characterPreviewEventBus = new CharacterPreviewEventBus();
655660
var upscaleController = new UpscalingController(mvcManager);
656661

@@ -780,6 +785,8 @@ await MapRendererContainer
780785
entityParticipantTable,
781786
messagePipesHub,
782787
remoteMetadata,
788+
remoteAnnouncements,
789+
remoteProfiles,
783790
staticContainer.CharacterContainer.CharacterObject,
784791
staticContainer.RealmData,
785792
remoteEntities,

Explorer/Assets/DCL/Multiplayer/Profiles/Announcements/RemoteAnnouncements.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,10 @@ private void OnMessageReceived(ReceivedMessage<AnnounceProfileVersion> obj)
2525

2626
public Bunch<RemoteAnnouncement> Bunch() =>
2727
new (list);
28+
29+
public void Reset()
30+
{
31+
list.Clear();
32+
}
2833
}
2934
}

Explorer/Assets/DCL/Multiplayer/Profiles/RemoteProfiles/RemoteProfiles.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,15 @@ public bool NewBunchAvailable() =>
6767
public Bunch<RemoteProfile> Bunch() =>
6868
new (remoteProfiles);
6969

70+
public void Reset()
71+
{
72+
foreach (var kv in pendingProfiles)
73+
kv.Value.Cts.SafeCancelAndDispose();
74+
75+
pendingProfiles.Clear();
76+
remoteProfiles.Clear();
77+
}
78+
7079
private async UniTaskVoid TryDownloadAsync(RemoteAnnouncement remoteAnnouncement)
7180
{
7281
URLDomain? lambdasEndpoint = remoteMetadata.GetLambdaDomainOrNull(remoteAnnouncement.WalletId);
@@ -107,8 +116,11 @@ private async UniTaskVoid TryDownloadAsync(RemoteAnnouncement remoteAnnouncement
107116
if (profile is null)
108117
return;
109118

110-
// Take the room source from the dictionary as the value could be updated
111-
remoteProfiles.Add(new RemoteProfile(profile, remoteAnnouncement.WalletId, pendingProfiles[remoteAnnouncement.WalletId].FromRoom));
119+
// Reset() may have cancelled and cleared pendingProfiles while we were awaiting.
120+
if (cts.IsCancellationRequested || !pendingProfiles.TryGetValue(remoteAnnouncement.WalletId, out PendingRequest currentRequest))
121+
return;
122+
123+
remoteProfiles.Add(new RemoteProfile(profile, remoteAnnouncement.WalletId, currentRequest.FromRoom));
112124

113125
ReportHub.Log(ReportCategory.PROFILE,
114126
$"{remoteAnnouncement} was downloaded for {(DateTime.Now - startedAt).TotalSeconds} s.");

Explorer/Assets/DCL/PluginSystem/Global/MultiplayerPlugin.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ public class MultiplayerPlugin : IDCLGlobalPlugin<MultiplayerPlugin.Settings>
5757
private readonly IRealmData realmData;
5858
private readonly IRemoteEntities remoteEntities;
5959
private readonly IRemoteMetadata remoteMetadata;
60+
private readonly RemoteAnnouncements remoteAnnouncements;
61+
private readonly RemoteProfiles remoteProfiles;
6062
private readonly IRoomHub roomHub;
6163
private readonly RoomsStatus roomsStatus;
6264
private readonly IScenesCache scenesCache;
@@ -81,6 +83,8 @@ public MultiplayerPlugin(
8183
IEntityParticipantTable entityParticipantTable,
8284
IMessagePipesHub messagePipesHub,
8385
IRemoteMetadata remoteMetadata,
86+
RemoteAnnouncements remoteAnnouncements,
87+
RemoteProfiles remoteProfiles,
8488
ICharacterObject characterObject,
8589
IRealmData realmData,
8690
IRemoteEntities remoteEntities,
@@ -104,6 +108,8 @@ public MultiplayerPlugin(
104108
this.entityParticipantTable = entityParticipantTable;
105109
this.messagePipesHub = messagePipesHub;
106110
this.remoteMetadata = remoteMetadata;
111+
this.remoteAnnouncements = remoteAnnouncements;
112+
this.remoteProfiles = remoteProfiles;
107113
this.characterObject = characterObject;
108114
this.remoteEntities = remoteEntities;
109115
this.realmData = realmData;
@@ -141,11 +147,11 @@ public void InjectToWorld(ref ArchSystemsWorldBuilder<Arch.Core.World> builder,
141147
DebugThroughputRoomsSystem.InjectToWorld(ref builder, roomHub, debugContainerBuilder, islandThroughputBufferBunch, sceneThroughputBufferBunch);
142148

143149
MultiplayerProfilesSystem.InjectToWorld(ref builder,
144-
new RemoteAnnouncements(messagePipesHub),
150+
remoteAnnouncements,
145151
new LogRemoveIntentions(
146152
new ThreadSafeRemoveIntentions(roomHub)
147153
),
148-
new RemoteProfiles(profileRepository, remoteMetadata),
154+
remoteProfiles,
149155
profileBroadcast,
150156
remoteEntities,
151157
remoteMetadata,

Explorer/Assets/DCL/RealmNavigation/Container/RealmNavigationContainer.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
using DCL.LOD.Systems;
55
using DCL.Multiplayer.Connections.RoomHubs;
66
using DCL.Multiplayer.Profiles.Entities;
7+
using DCL.Multiplayer.Profiles.RemoteAnnouncements;
8+
using DCL.Multiplayer.Profiles.RemoteProfiles;
79
using DCL.PerformanceAndDiagnostics.Analytics;
810
using DCL.PlacesAPIService;
911
using DCL.PrivateWorlds;
@@ -38,6 +40,8 @@ public static RealmNavigationContainer Create(
3840
LODContainer lodContainer,
3941
RealmContainer realmContainer,
4042
RemoteEntities remoteEntities,
43+
RemoteAnnouncements remoteAnnouncements,
44+
RemoteProfiles remoteProfiles,
4145
World globalWorld,
4246
IRoomHub roomHub,
4347
ILandscape landscape,
@@ -53,7 +57,7 @@ public static RealmNavigationContainer Create(
5357
var realmChangeOperations = new AnalyticsSequentialLoadingOperation<TeleportParams>(staticContainer.LoadingStatus, new ITeleportOperation[]
5458
{
5559
new RestartLoadingStatus(),
56-
new RemoveRemoteEntitiesTeleportOperation(remoteEntities, globalWorld),
60+
new RemoveRemoteEntitiesTeleportOperation(remoteEntities, remoteAnnouncements, remoteProfiles, globalWorld),
5761
new StopRoomAsyncTeleportOperation(roomHub, LIVEKIT_TIMEOUT),
5862
new RemoveCameraSamplingDataTeleportOperation(globalWorld, exposedGlobalDataContainer.ExposedCameraData.CameraEntityProxy),
5963
new ClearWorldsCacheTeleportOperation(placesAPIService),

Explorer/Assets/DCL/RealmNavigation/TeleportOperations/RemoveRemoteEntitiesTeleportOperation.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,32 @@
11
using Arch.Core;
22
using Cysharp.Threading.Tasks;
33
using DCL.Multiplayer.Profiles.Entities;
4+
using DCL.Multiplayer.Profiles.RemoteAnnouncements;
5+
using DCL.Multiplayer.Profiles.RemoteProfiles;
46
using System.Threading;
57

68
namespace DCL.RealmNavigation.TeleportOperations
79
{
810
public class RemoveRemoteEntitiesTeleportOperation : TeleportOperationBase
911
{
1012
private readonly IRemoteEntities remoteEntities;
13+
private readonly RemoteAnnouncements remoteAnnouncements;
14+
private readonly RemoteProfiles remoteProfiles;
1115
private readonly World globalWorld;
1216

13-
public RemoveRemoteEntitiesTeleportOperation(IRemoteEntities remoteEntities, World globalWorld)
17+
public RemoveRemoteEntitiesTeleportOperation(IRemoteEntities remoteEntities, RemoteAnnouncements remoteAnnouncements, RemoteProfiles remoteProfiles, World globalWorld)
1418
{
1519
this.remoteEntities = remoteEntities;
20+
this.remoteAnnouncements = remoteAnnouncements;
21+
this.remoteProfiles = remoteProfiles;
1622
this.globalWorld = globalWorld;
1723
}
1824

1925
protected override UniTask InternalExecuteAsync(TeleportParams teleportParams, CancellationToken ct)
2026
{
27+
// Drop in-flight profile downloads and queued announcements from the previous realm so they don't appear as ghosts
28+
remoteAnnouncements.Reset();
29+
remoteProfiles.Reset();
2130
remoteEntities.ForceRemoveAll(globalWorld);
2231
return UniTask.CompletedTask;
2332
}

0 commit comments

Comments
 (0)