Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hotfix: fresh guest getting 0% loading when entering world / emotes failing to load or never reporting failure #6047

Merged
merged 3 commits into from
Jan 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,10 @@ This is the most useful debugging scenario for advanced feature implementation.
### Steps

1. Make sure you have the proper Unity version up and running
3. Make sure you are running browser-interface through `make watch` command on `browser-interface` path.
4. Back in unity editor, open the `DebugConfig` component inspector of `InitialScene`
5. Make sure that the component is setup correctly
6. Hit 'Play' button
2. Make sure you are running browser-interface through `make watch` command on `browser-interface` path.
3. Back in unity editor, open the `DebugConfig` component inspector of `InitialScene`
4. Make sure that the component is setup correctly
5. Hit 'Play' button

## Debug with browsers + local Unity build

Expand All @@ -102,16 +102,16 @@ When the steps are followed, you will be able to run the local Unity build by go
### Steps

1. Make sure you have the proper Unity version up and running
3. Make sure you are running browser-interface through `make watch` command.
4. Produce a Unity wasm targeted build using the Build menu.
5. When the build finishes, copy all the files inside the resulting `/build` folder (`unity.loader.js` is not necessary as we use a modified loader) and paste them inside `browser-interface/node_modules/@dcl/unity-renderer`.
6. Run the browser explorer through `localhost:8080&ENABLE_WEB3`. Now, it should use your local Unity build. Don't mind the white screen at the beginning, that's because the website repo is not being used and it's only loading Browser Interface with the build.
7. If you need a Unity re-build, you can just replace the files and reload the browser without restarting the `make watch` process.
2. Make sure you are running browser-interface correctly by running `npm install`, `make build-unity-local` and `make watch` commands in that directory and leave that server running.
3. Produce a Unity wasm targeted build using the Build menu (the build should be named just "unity" to avoid renamings later).
4. When the build finishes, copy all the files inside the resulting `/build` folder (`unity.loader.js` may not be necessary) and paste them inside `browser-interface/node_modules/@dcl/explorer`.
5. Run the browser explorer through `http://localhost:8080/?ENABLE_WEB3`. Now, it should use your local Unity build. Don't mind the white screen at the beginning, that's because the website repo is not being used and it's only loading Browser Interface with the build.
6. If you need a Unity re-build, you can just replace the files and reload the browser without restarting the `make watch` process.

Alternatively you can go through these 2 steps after step 3 and load the build locally using `localhost:3000`
Alternatively you can go through these steps after step 3 and load the build locally using `localhost:3000`
1. Make sure you have the [explorer website repository](https://github.com/decentraland/explorer-website) cloned.
2. Make sure you have the local website up and running by executing `npm run start:linked` in the cloned repo directory (`npm i` first just in case).
3. When the WebGL build finishes, copy all the files inside the resulting `/build` folder (`unity.loader.js` is not necessary as we use a modified loader) and paste them inside `explorer-website/node_modules/@dcl/unity-renderer`.
3. When the WebGL build finishes, copy all the files inside the resulting `/build` folder (`unity.loader.js` is not necessary as we use a modified loader) and paste them inside `explorer-website/node_modules/@dcl/explorer`.
4. Access using `localhost:3000`

### Troubleshooting
Expand Down Expand Up @@ -147,4 +147,4 @@ If the local WebGL build always fails with the error `System.ComponentModel.Win3
## Copyright info

This repository is protected with a standard Apache 2 license. See the terms and conditions in
the [LICENSE](https://github.com/decentraland/unity-renderer/blob/master/LICENSE) file.
the [LICENSE](https://github.com/decentraland/unity-renderer/blob/master/LICENSE) file.
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using UnityEngine.Pool;

namespace DCLServices.EmotesCatalog
{
public class EmotesRequestWeb : IEmotesRequestSource
public class EmotesBatchRequest : IEmotesRequestSource
{
[Serializable]
public class OwnedEmotesRequestDto
Expand All @@ -35,18 +36,18 @@ public class EmoteRequestDto

private readonly ILambdasService lambdasService;
private readonly ICatalyst catalyst;
private readonly List<string> pendingRequests = new ();
private readonly HashSet<string> pendingRequests = new ();
private readonly CancellationTokenSource cts;
private readonly BaseVariable<FeatureFlag> featureFlags;
private UniTaskCompletionSource<IReadOnlyList<WearableItem>> lastRequestSource;

private string assetBundlesUrl => featureFlags.Get().IsFeatureEnabled("ab-new-cdn") ? "https://ab-cdn.decentraland.org/" : "https://content-assets-as-bundle.decentraland.org/";

public EmotesRequestWeb(ILambdasService lambdasService, IServiceProviders serviceProviders, BaseVariable<FeatureFlag> featureFlags)
public EmotesBatchRequest(ILambdasService lambdasService, IServiceProviders serviceProviders, BaseVariable<FeatureFlag> featureFlags)
{
this.featureFlags = featureFlags;
this.lambdasService = lambdasService;
this.catalyst = serviceProviders.catalyst;
catalyst = serviceProviders.catalyst;
cts = new CancellationTokenSource();
}

Expand All @@ -65,23 +66,23 @@ private async UniTask RequestOwnedEmotesAsync(string userId)
{
var url = $"{catalyst.lambdasUrl}/users/{userId}/emotes";

List<OwnedEmotesRequestDto.EmoteRequestDto> requestedEmotes = new List<OwnedEmotesRequestDto.EmoteRequestDto>();
var requestedEmotes = new List<OwnedEmotesRequestDto.EmoteRequestDto>();

if (!await FullListEmoteFetch(userId, url, requestedEmotes))
return;

var tempList = PoolUtils.RentList<string>();
var emoteUrns = tempList.GetList();
PoolUtils.ListPoolRent<string> tempList = PoolUtils.RentList<string>();
List<string> emoteUrns = tempList.GetList();

Dictionary<string, int> urnToAmountMap = new Dictionary<string, int>();
var urnToAmountMap = new Dictionary<string, int>();

foreach (OwnedEmotesRequestDto.EmoteRequestDto emoteRequestDto in requestedEmotes)
{
emoteUrns.Add(emoteRequestDto.urn);
urnToAmountMap[emoteRequestDto.urn] = emoteRequestDto.amount;
}

var emotes = await FetchEmotes(emoteUrns, urnToAmountMap);
IReadOnlyList<WearableItem> emotes = await FetchEmotes(emoteUrns, urnToAmountMap);

tempList.Dispose();

Expand All @@ -91,18 +92,18 @@ private async UniTask RequestOwnedEmotesAsync(string userId)
// This recursiveness is horrible, we should add proper pagination
private async UniTask<bool> FullListEmoteFetch(string userId, string url, List<OwnedEmotesRequestDto.EmoteRequestDto> requestedEmotes)
{
int requestedCount = 0;
int totalEmotes = 99999;
int pageNum = 1;
var requestedCount = 0;
var totalEmotes = 99999;
var pageNum = 1;

while (requestedCount < totalEmotes)
{
var queryParams = new List<(string name, string value)>
(string name, string value)[] queryParams = new List<(string name, string value)>
{
("pageNum", pageNum.ToString())
("pageNum", pageNum.ToString()),
}.ToArray();

var result = await lambdasService.GetFromSpecificUrl<OwnedEmotesRequestDto>(url, url,
(OwnedEmotesRequestDto response, bool success) result = await lambdasService.GetFromSpecificUrl<OwnedEmotesRequestDto>(url, url,
cancellationToken: cts.Token, urlEncodedParams: queryParams);

if (!result.success) throw new Exception($"Fetching owned wearables failed! {url}\nAddress: {userId}");
Expand Down Expand Up @@ -130,8 +131,8 @@ public void RequestEmote(string emoteId)
private async UniTask RequestWearableBatchAsync(string id)
{
pendingRequests.Add(id);
lastRequestSource ??= new ();
var sourceToAwait = lastRequestSource;
lastRequestSource ??= new UniTaskCompletionSource<IReadOnlyList<WearableItem>>();
UniTaskCompletionSource<IReadOnlyList<WearableItem>> sourceToAwait = lastRequestSource;

// we wait for the latest update possible so we buffer all requests into one
await UniTask.Yield(PlayerLoopTiming.PostLateUpdate, cts.Token);
Expand All @@ -142,29 +143,32 @@ private async UniTask RequestWearableBatchAsync(string id)
{
lastRequestSource = null;

result = await FetchEmotes(pendingRequests);

List<string> tempList = ListPool<string>.Get();
tempList.AddRange(pendingRequests);
pendingRequests.Clear();

result = await FetchEmotes(tempList);
ListPool<string>.Release(tempList);
sourceToAwait.TrySetResult(result);
OnEmotesReceived?.Invoke(result);
}
else
result = await sourceToAwait.Task;

OnEmotesReceived?.Invoke(result);
await sourceToAwait.Task;
}

private async UniTask<IReadOnlyList<WearableItem>> FetchEmotes(List<string> ids, Dictionary<string, int> urnToAmountMap = null)
private async UniTask<IReadOnlyList<WearableItem>> FetchEmotes(IReadOnlyCollection<string> ids, Dictionary<string, int> urnToAmountMap = null)
{
// the copy of the list is intentional
var request = new LambdasEmotesCatalogService.WearableRequest { pointers = new List<string>(ids) };
var url = $"{catalyst.contentUrl}entities/active";

var response = await lambdasService.PostFromSpecificUrl<EmoteEntityDto[], LambdasEmotesCatalogService.WearableRequest>(url, url, request, cancellationToken: cts.Token);
(EmoteEntityDto[] response, bool success) response = await lambdasService.PostFromSpecificUrl<EmoteEntityDto[], LambdasEmotesCatalogService.WearableRequest>(url, url, request, cancellationToken: cts.Token);

if (!response.success) throw new Exception($"Fetching wearables failed! {url}\n{string.Join("\n", request.pointers)}");

var wearables = response.response.Select(dto =>
HashSet<string> receivedIds = HashSetPool<string>.Get();

IEnumerable<WearableItem> wearables = response.response.Select(dto =>
{
var contentUrl = $"{catalyst.contentUrl}contents/";
var wearableItem = dto.ToWearableItem(contentUrl);
Expand All @@ -176,6 +180,14 @@ private async UniTask<IReadOnlyList<WearableItem>> FetchEmotes(List<string> ids,
return wearableItem;
});

foreach (WearableItem wearableItem in wearables)
receivedIds.Add(wearableItem.id);

foreach (string id in ids)
if (!receivedIds.Contains(id))
OnEmoteRejected?.Invoke(id, "Empty response from content server");

HashSetPool<string>.Release(receivedIds);
return wearables.ToList();
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
using Cysharp.Threading.Tasks;
using DCL.Emotes;
using DCLServices.WearablesCatalogService;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.Assertions;
using UnityEngine.Pool;
Expand All @@ -13,12 +15,15 @@ public class AvatarCurator : IAvatarCurator
{
private readonly IWearableItemResolver wearableItemResolver;
private readonly IEmotesCatalogService emotesCatalog;
private EmbeddedEmotesSO embedEmotes;
private string[] embedEmotesId;

public AvatarCurator(IWearableItemResolver wearableItemResolver, IEmotesCatalogService emotesCatalog)
{
Assert.IsNotNull(wearableItemResolver);
this.wearableItemResolver = wearableItemResolver;
this.emotesCatalog = emotesCatalog;

}

/// <summary>
Expand Down Expand Up @@ -49,9 +54,12 @@ List<WearableItem> emotes
//New emotes flow use the emotes catalog
if (emoteIds != null)
{
embedEmotes ??= await emotesCatalog.GetEmbeddedEmotes();
embedEmotesId ??= embedEmotes.GetAllIds();

DateTime startLoadTime = DateTime.Now;

var emoteIdsList = emoteIds.ToList();
var emoteIdsList = emoteIds.Select(ExtendedUrnParser.GetShortenedUrn).ToList();
IReadOnlyList<WearableItem> resolvedEmotes = await emotesCatalog.RequestEmotesAsync(emoteIdsList, ct);
List<WearableItem> nonPublishedEmotes = ListPool<WearableItem>.Get();

Expand All @@ -60,6 +68,8 @@ List<WearableItem> emotes
if (nonPublishedEmoteId.StartsWith("urn")) continue;
bool wasResolved = resolvedEmotes?.Any(item => item?.id == nonPublishedEmoteId) ?? false;
if (wasResolved) continue;
bool isEmbedded = embedEmotesId.Contains(nonPublishedEmoteId);
if (isEmbedded) continue;
WearableItem nonPublishedEmote = await emotesCatalog.RequestEmoteFromBuilderAsync(nonPublishedEmoteId, ct);
if (nonPublishedEmote != null)
nonPublishedEmotes.Add(nonPublishedEmote);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
using Cysharp.Threading.Tasks;
using DCL.Helpers;
using DCLServices.WearablesCatalogService;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Cysharp.Threading.Tasks;
using DCL.Helpers;
using DCLServices.WearablesCatalogService;

namespace AvatarSystem
{
Expand All @@ -23,7 +23,7 @@ public WearableItemResolver(IWearablesCatalogService wearablesCatalogService)
{
try
{
var parsedWearablesIds = wearableIds.Select((wearableId) => ExtendedUrnParser.GetShortenedUrn(wearableId));
IEnumerable<string> parsedWearablesIds = wearableIds.Select(ExtendedUrnParser.GetShortenedUrn);
WearableItem[] allItems = await Resolve(parsedWearablesIds, ct);

List<WearableItem> wearables = new List<WearableItem>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,12 @@ private void OnSignupFlow(bool current, bool previous)
{
onSignUpFlow = current;

if (realmDataStore.playerRealmAboutConfiguration.Get() != null)
{
currentRealm = realmDataStore.playerRealmAboutConfiguration.Get().RealmName;
currentRealmIsWorld = commonDataStore.isWorld.Get();
}

if (current)
FadeOutView();
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ public static ServiceLocator CreateDefault()

result.Register<IEmotesCatalogService>(() =>
{
var emotesRequest = new EmotesRequestWeb(
var emotesRequest = new EmotesBatchRequest(
result.Get<ILambdasService>(),
result.Get<IServiceProviders>(),
featureFlagsDataStore);
Expand Down