예제 #1
0
    protected override async void LoadPayload(ScreenLoadPromise promise)
    {
        SpinnerOverlay.Show();
        await Context.LevelManager.LoadLevelsOfType(LevelType.User);

        RestClient.GetArray <EventMeta>(new RequestHelper
        {
            Uri         = $"{Context.ApiUrl}/events",
            Headers     = Context.OnlinePlayer.GetRequestHeaders(),
            EnableDebug = true
        }).Then(data =>
        {
            if (data.Length == 0)
            {
                Dialog.PromptGoBack("DIALOG_EVENTS_NOT_AVAILABLE".Get());
                promise.Reject();
                return;
            }
            IntentPayload.Events = data.ToList();
            promise.Resolve(IntentPayload);
        })
        .CatchRequestError(error =>
        {
            Debug.LogError(error);
            Dialog.PromptGoBack("DIALOG_COULD_NOT_CONNECT_TO_SERVER".Get());

            promise.Reject();
        })
        .Finally(() => SpinnerOverlay.Hide());
    }
예제 #2
0
    protected override void LoadPayload(ScreenLoadPromise promise)
    {
        coverImage.color = Color.black;

        if (IntentPayload.Collection != null)
        {
            promise.Resolve(IntentPayload);
            return;
        }

        SpinnerOverlay.Show();
        RestClient.Get <CollectionMeta>(new RequestHelper
        {
            Uri         = $"{Context.ApiUrl}/collections/{IntentPayload.CollectionId}",
            Headers     = Context.OnlinePlayer.GetRequestHeaders(),
            EnableDebug = true
        })
        .Then(meta =>
        {
            IntentPayload.Collection = meta;

            promise.Resolve(IntentPayload);
        })
        .CatchRequestError(error =>
        {
            Debug.LogError(error);
            Dialog.PromptGoBack("DIALOG_COULD_NOT_CONNECT_TO_SERVER".Get());

            promise.Reject();
        })
        .Finally(() => SpinnerOverlay.Hide());
    }
예제 #3
0
    protected override void LoadPayload(ScreenLoadPromise promise)
    {
        IntentPayload.IsPlayer = IntentPayload.Id == Context.OnlinePlayer.LastProfile?.User.Id;
        if (IntentPayload.Profile != null)
        {
            promise.Resolve(IntentPayload);
            return;
        }
        if (IntentPayload.IsPlayer)
        {
            if (Context.OnlinePlayer.LastFullProfile != null)
            {
                IntentPayload.Profile = Context.OnlinePlayer.LastFullProfile;
                promise.Resolve(IntentPayload);
                return;
            }

            if (Context.IsOffline())
            {
                // Fetch offline profile and cast it as full profile
                Context.OnlinePlayer.FetchProfile()
                .Then(profile =>
                {
                    var fullProfile =
                        JsonConvert.DeserializeObject <FullProfile>(JsonConvert.SerializeObject(profile));
                    IntentPayload.Profile = fullProfile;
                    promise.Resolve(IntentPayload);
                })
                .CatchRequestError(error =>
                {
                    Debug.LogError(error);
                    Dialog.PromptGoBack("DIALOG_OFFLINE_FEATURE_NOT_AVAILABLE".Get());
                });
                return;
            }
        }

        SpinnerOverlay.Show();
        RestClient.Get <FullProfile>(new RequestHelper
        {
            Uri         = $"{Context.ApiUrl}/profile/{IntentPayload.Id}/details",
            Headers     = Context.OnlinePlayer.GetRequestHeaders(),
            EnableDebug = true
        }).Then(data =>
        {
            if (IntentPayload.IsPlayer)
            {
                Context.OnlinePlayer.LastFullProfile = data;
            }
            IntentPayload.Profile = data;
            promise.Resolve(IntentPayload);
        }).CatchRequestError(error =>
        {
            Debug.LogError(error);
            Dialog.PromptGoBack("DIALOG_COULD_NOT_CONNECT_TO_SERVER".Get());
        }).Finally(() => SpinnerOverlay.Hide());
    }
예제 #4
0
    public override async void OnScreenBecameActive()
    {
        base.OnScreenBecameActive();
        ProfileWidget.Instance.Enter();
        ScreenCenter = new Vector2(UnityEngine.Screen.width / 2f, UnityEngine.Screen.height / 2f);
        var height  = RectTransform.rect.height;
        var padding = scrollRectContentLayoutGroup.padding;

        padding.top = padding.bottom = (int)((height - 576) / 2f);  // TODO: Un-hardcode tier card height but I'm lazy lol
        scrollRectContentLayoutGroup.padding = padding;

        if (LoadedContent == null)
        {
            SpinnerOverlay.Show();
            await Context.LevelManager.LoadLevelsOfType(LevelType.Tier);

            RestClient.Get(new RequestHelper
            {
                Uri     = $"{Context.ApiUrl}/seasons/alpha",
                Headers = Context.OnlinePlayer.GetRequestHeaders(),
                Timeout = 5,
            }).Then(res =>
            {
                print("TierSelection: " + res.Text);
                var season    = JsonConvert.DeserializeObject <SeasonMeta>(res.Text);
                LoadedContent = new Content {
                    Season = season
                };
                OnContentLoaded(LoadedContent);
                Run.After(0.4f, () =>
                {
                    icons.Enter();
                    SpinnerOverlay.Hide();
                });
            }).CatchRequestError(error =>
            {
                if (!error.IsNetworkError)
                {
                    throw error;
                }

                SpinnerOverlay.Hide();
                Dialog.PromptGoBack("DIALOG_COULD_NOT_CONNECT_TO_SERVER".Get());
            });
        }
        else
        {
            SpinnerOverlay.Show();
            OnContentLoaded(LoadedContent);
            Run.After(0.4f, () =>
            {
                icons.Enter();
                SpinnerOverlay.Hide();
            });
        }
    }
예제 #5
0
    private async void OnSettingsTab()
    {
        if (!initializedSettingsTab)
        {
            SpinnerOverlay.Show();
            await UniTask.DelayFrame(5);

            InitializeSettingsTab();
            await UniTask.DelayFrame(5);

            SpinnerOverlay.Hide();
        }
    }
예제 #6
0
    private async void OnApplicationPause(bool pauseStatus)
    {
        // Resuming?
        if (!pauseStatus)
        {
            if (Context.ScreenManager.History.All(it => it.ScreenId != MainMenuScreen.Id))
            {
                return;
            }

            // Install levels
            SpinnerOverlay.Show();

            Context.LevelManager.OnLevelInstallProgress.AddListener(SpinnerOverlay.OnLevelInstallProgress);
            var loadedLevelJsonFiles = await Context.LevelManager.InstallUserCommunityLevels();

            Context.LevelManager.OnLevelInstallProgress.RemoveListener(SpinnerOverlay.OnLevelInstallProgress);

            Context.LevelManager.OnLevelLoadProgress.AddListener(SpinnerOverlay.OnLevelLoadProgress);
            var loadedLevels = await Context.LevelManager.LoadFromMetadataFiles(LevelType.User, loadedLevelJsonFiles, true);

            Context.LevelManager.OnLevelLoadProgress.RemoveListener(SpinnerOverlay.OnLevelLoadProgress);

            SpinnerOverlay.Hide();

            if (loadedLevels.Count > 0)
            {
                var lastLoadedLevel = loadedLevels.Last();

                if (Context.ScreenManager.ActiveScreenId != GamePreparationScreen.Id)
                {
                    // Switch to that level
                    while (Context.ScreenManager.PeekHistory().Let(it => it != null && it.ScreenId != MainMenuScreen.Id))
                    {
                        Context.ScreenManager.PopAndPeekHistory();
                    }

                    Context.ScreenManager.History.Push(new Intent(LevelSelectionScreen.Id, null));

                    Context.ScreenManager.ChangeScreen(GamePreparationScreen.Id, ScreenTransition.In,
                                                       payload: new GamePreparationScreen.Payload {
                        Level = lastLoadedLevel
                    });
                }
                else
                {
                    Context.SelectedLevel = lastLoadedLevel; // Trigger the event and screen will relaod
                }
            }
        }
    }
예제 #7
0
    public void UpdateLeaderboard(string mode)
    {
        ClearLeaderboard();

        SpinnerOverlay.Show();
        var uri = Context.ApiUrl + "/leaderboard?limit=50";

        if (mode == "me")
        {
            uri += "&user="******"me")
                {
                    var meEntry = leaderboard.Entries.Find(it => it.Model.Uid == Context.Player.Id);
                    if (meEntry != null)
                    {
                        await UniTask.DelayFrame(0);

                        leaderboardScrollRect.GetComponent <ScrollRectFocusHelper>()
                        .CenterOnItem(meEntry.transform as RectTransform);
                    }
                }
                await UniTask.DelayFrame(2);

                if (LoadedPayload.LeaderboardScrollPosition > -1)
                {
                    leaderboardScrollRect.verticalNormalizedPosition = LoadedPayload.LeaderboardScrollPosition;
                }
            }
            catch (Exception e)
            {
                Debug.LogError(e);
            }
        }
    }
예제 #8
0
    public override void OnPointerClick(PointerEventData eventData)
    {
        base.OnPointerClick(eventData);
        if (isStatic)
        {
            return;
        }
        if (record != null)
        {
            if (Context.ScreenManager.IsChangingScreen)
            {
                return;
            }

            if (Context.IsOffline())
            {
                throw new InvalidOperationException();
            }

            Context.AudioManager.Get("Navigate2").Play();
            Context.Haptic(HapticTypes.MediumImpact, true);

            // Get full meta
            SpinnerOverlay.Show();
            RestClient.Get <OnlineLevel>(new RequestHelper
            {
                Uri     = $"{Context.ApiUrl}/levels/{record.chart.level.Uid}",
                Headers = Context.OnlinePlayer.GetRequestHeaders()
            })
            .Then(it =>
            {
                Context.ScreenManager.ChangeScreen(GamePreparationScreen.Id, ScreenTransition.In, 0.4f,
                                                   transitionFocus: GetComponent <RectTransform>().GetScreenSpaceCenter(),
                                                   payload: new GamePreparationScreen.Payload {
                    Level = it.ToLevel(LevelType.User)
                });
            })
            .CatchRequestError(error =>
            {
                Debug.LogError(error);
                Dialog.PromptAlert("DIALOG_COULD_NOT_CONNECT_TO_SERVER".Get());
            })
            .Finally(() => SpinnerOverlay.Hide());
        }
    }
예제 #9
0
    public static async UniTask Show(Story story)
    {
        var instance = Instance;

        if (instance.IsActive)
        {
            await UniTask.WaitUntil(() => !instance.IsActive);
        }
        await instance.Enter();

        var spriteSets    = new Dictionary <string, DialogueSpriteSet>();
        var animationSets = new Dictionary <string, DialogueAnimationSet>();

        if (story.globalTags != null)
        {
            story.globalTags.FindAll(it => it.Trim().StartsWith("SpriteSet:"))
            .Select(it => it.Substring(it.IndexOf(':') + 1).Trim())
            .Select(DialogueSpriteSet.Parse)
            .ForEach(it => spriteSets[it.Id] = it);
            story.globalTags.FindAll(it => it.Trim().StartsWith("AnimationSet:"))
            .Select(it => it.Substring(it.IndexOf(':') + 1).Trim())
            .Select(DialogueAnimationSet.Parse)
            .ForEach(it => animationSets[it.Id] = it);
        }

        await spriteSets.Values.Select(it => it.Initialize());

        await animationSets.Values.Select(it => it.Initialize());

        Sprite currentImageSprite     = null;
        string currentImageSpritePath = null;
        Sprite currentSprite          = null;
        string currentAnimation       = null;
        var    currentSpeaker         = "";
        var    currentPosition        = DialogueBoxPosition.Bottom;

        var                     shouldSetImageSprite = false;
        Dialogue                lastDialogue         = null;
        DialogueBox             lastDialogueBox      = null;
        DialogueHighlightTarget lastHighlightTarget  = null;

        while (story.canContinue && !TerminateCurrentStory)
        {
            var message  = ReplacePlaceholders(story.Continue());
            var duration = 0f;
            var tags     = story.currentTags;

            var doAction = TagValue(tags, "Action");
            if (doAction != null)
            {
                switch (doAction)
                {
                case "GamePreparation/ShowGameplayTab":
                    var tabs = Context.ScreenManager.GetScreen <GamePreparationScreen>().actionTabs;
                    tabs.OnAction(tabs.Actions.Find(it => it.index == 2));
                    break;
                }
            }

            var setDuration = TagValue(tags, "Duration");
            if (setDuration != null)
            {
                duration = float.Parse(setDuration);
            }

            var setOverlayOpacity = TagValue(tags, "OverlayOpacity");
            if (setOverlayOpacity != null)
            {
                setOverlayOpacity.Split('/', out var targetOpacity, out var fadeDuration, out var fadeDelay);
                SetOverlayOpacity().Forget();
                async UniTaskVoid SetOverlayOpacity()
                {
                    await UniTask.Delay(TimeSpan.FromSeconds(float.Parse(fadeDelay)));

                    instance.backdropImage.DOFade(float.Parse(targetOpacity), float.Parse(fadeDuration));
                }
            }

            var setHighlight = TagValue(tags, "Highlight");
            if (setHighlight != null)
            {
                lastHighlightTarget = await DialogueHighlightTarget.Find(setHighlight);

                if (lastHighlightTarget != null)
                {
                    lastHighlightTarget.Highlighted = true;
                }
            }

            var waitForHighlightOnClick = FlagValue(tags, "WaitForHighlightOnClick");
            if (waitForHighlightOnClick && lastHighlightTarget == null)
            {
                waitForHighlightOnClick = false;
            }

            var    setImage = TagValue(tags, "Image");
            string imageWidth = null, imageHeight = null, imageRadius = null;
            if (setImage != null)
            {
                if (setImage == "null")
                {
                    currentImageSprite = null;
                }
                else
                {
                    setImage.Split('/', out imageWidth, out imageHeight, out imageRadius, out var imageUrl);

                    imageUrl = ReplacePlaceholders(imageUrl);

                    SpinnerOverlay.Show();
                    currentImageSprite = await Context.AssetMemory.LoadAsset <Sprite>(imageUrl, AssetTag.DialogueImage);

                    currentImageSpritePath = imageUrl;
                    SpinnerOverlay.Hide();

                    shouldSetImageSprite = true;
                }
            }

            var setSprite = TagValue(tags, "Sprite");
            if (setSprite != null)
            {
                if (setSprite == "null")
                {
                    currentSprite = null;
                    DisposeImageSprite();
                }
                else
                {
                    setSprite.Split('/', out var id, out var state);

                    if (!spriteSets.ContainsKey(id))
                    {
                        throw new ArgumentOutOfRangeException();
                    }
                    currentSprite    = spriteSets[id].States[state].Sprite;
                    currentAnimation = null;
                }
            }

            var setAnimation = TagValue(tags, "Animation");
            if (setAnimation != null)
            {
                if (setAnimation == "null")
                {
                    currentAnimation = null;
                }
                else
                {
                    currentAnimation = setAnimation;
                    currentSprite    = null;
                }
            }

            var setSpeaker = TagValue(tags, "Speaker");
            if (setSpeaker != null)
            {
                currentSpeaker = setSpeaker == "null" ? null : setSpeaker;
            }

            var setPosition = TagValue(tags, "Position");
            if (setPosition != null)
            {
                currentPosition = (DialogueBoxPosition)Enum.Parse(typeof(DialogueBoxPosition), setPosition);
            }

            var dialogue = new Dialogue
            {
                Message     = message,
                SpeakerName = currentSpeaker,
                Sprite      = currentSprite,
                Position    = currentPosition,
                HasChoices  = story.currentChoices.Count > 0,
                IsBlocked   = waitForHighlightOnClick || duration > 0
            };

            // Lookup animation
            if (currentAnimation != null)
            {
                currentAnimation.Split('/', out var id, out var animationName);

                if (!animationSets.ContainsKey(id))
                {
                    throw new ArgumentOutOfRangeException();
                }
                dialogue.AnimatorController = animationSets[id].Controller;
                dialogue.AnimationName      = animationName;
            }

            DialogueBox dialogueBox;
            if (dialogue.Position == DialogueBoxPosition.Top)
            {
                dialogueBox = instance.topDialogueBox;
            }
            else if (dialogue.Sprite != null || dialogue.AnimatorController != null)
            {
                dialogueBox = instance.bottomFullDialogueBox;
            }
            else
            {
                dialogueBox = instance.bottomDialogueBox;
            }

            if (lastDialogue != null && (lastDialogueBox != dialogueBox || lastDialogue.SpeakerName != dialogue.SpeakerName))
            {
                await lastDialogueBox.SetDisplayed(false);

                dialogueBox.messageBox.SetLocalScale(1f);
            }

            // Display image
            if (currentImageSprite != null)
            {
                if (shouldSetImageSprite)
                {
                    instance.image.SetData(currentImageSprite, int.Parse(imageWidth), int.Parse(imageHeight), int.Parse(imageRadius));
                    await UniTask.Delay(TimeSpan.FromSeconds(1.5f));

                    shouldSetImageSprite = false;
                }
            }
            else
            {
                instance.image.Clear();
            }

            if (message.IsNullOrEmptyTrimmed())
            {
                await dialogueBox.SetDisplayed(false);
            }
            else
            {
                await dialogueBox.SetDisplayed(true);

                lastDialogue    = dialogue;
                lastDialogueBox = dialogueBox;

                instance.detectionArea.onPointerDown.SetListener(_ => { dialogueBox.messageBox.DOScale(0.97f, 0.2f); });
                instance.detectionArea.onPointerUp.SetListener(_ => { dialogueBox.messageBox.DOScale(1f, 0.2f); });
                instance.detectionArea.onPointerClick.SetListener(_ => { dialogueBox.WillFastForwardDialogue = true; });
                await dialogueBox.ShowDialogue(dialogue);
            }

            if (waitForHighlightOnClick)
            {
                instance.detectionArea.onPointerDown.RemoveAllListeners();
                instance.detectionArea.onPointerUp.RemoveAllListeners();
                await lastHighlightTarget.WaitForOnClick();
            }
            else if (story.currentChoices.Count > 0)
            {
                var proceed = false;
                var buttons = new List <SoftButton>();
                for (var index = 0; index < story.currentChoices.Count; index++)
                {
                    var choice       = story.currentChoices[index];
                    var choiceButton = Instantiate(instance.choiceButtonPrefab, instance.choicesRoot);
                    var closureIndex = index;
                    choiceButton.onPointerClick.SetListener(_ =>
                    {
                        if (proceed)
                        {
                            return;
                        }
                        story.ChooseChoiceIndex(closureIndex);
                        proceed = true;
                    });
                    choiceButton.Label = choice.text.Get();
                    buttons.Add(choiceButton);
                }

                LayoutFixer.Fix(instance.choicesRoot);
                await UniTask.DelayFrame(5);

                foreach (var button in buttons)
                {
                    button.transitionElement.UseCurrentStateAsDefault();
                    button.transitionElement.Enter();
                    await UniTask.Delay(TimeSpan.FromSeconds(0.2f));
                }

                await UniTask.WaitUntil(() => proceed);

                buttons.ForEach(it => Destroy(it.gameObject));
            }
            else
            {
                var proceed = false;
                instance.detectionArea.onPointerDown.SetListener(_ => { dialogueBox.messageBox.DOScale(0.95f, 0.2f); });
                instance.detectionArea.onPointerUp.SetListener(_ =>
                {
                    dialogueBox.messageBox.DOScale(1f, 0.2f);
                    proceed = true;
                });
                if (duration > 0)
                {
                    await UniTask.WhenAny(UniTask.WaitUntil(() => proceed),
                                          UniTask.Delay(TimeSpan.FromSeconds(duration)));
                }
                else
                {
                    await UniTask.WaitUntil(() => proceed);
                }
                instance.detectionArea.onPointerDown.RemoveAllListeners();
                instance.detectionArea.onPointerUp.RemoveAllListeners();
            }

            if (lastHighlightTarget != null)
            {
                lastHighlightTarget.Highlighted = false;
                lastHighlightTarget             = null;
            }
        }
        TerminateCurrentStory = false;
        if (lastDialogueBox != null)
        {
            lastDialogueBox.SetDisplayed(false);
        }

        instance.image.Clear();
        await instance.Leave();

        DisposeImageSprite();
        spriteSets.Values.ForEach(it => it.Dispose());
        animationSets.Values.ForEach(it => it.Dispose());

        string TagValue(List <string> tags, string tag)
        {
            return(tags.Find(it => it.Trim().StartsWith(tag + ":"))?.Let(it => it.Substring(it.IndexOf(':') + 1).Trim()));
        }

        bool FlagValue(List <string> tags, string tag)
        {
            return(tags.Any(it => it.Trim() == tag));
        }

        void DisposeImageSprite()
        {
            if (currentImageSprite != null)
            {
                Context.AssetMemory.DisposeAsset(currentImageSpritePath, AssetTag.DialogueImage);
                currentImageSprite     = null;
                currentImageSpritePath = null;
            }
        }

        string ReplacePlaceholders(string str)
        {
            str = str.Replace("[N/A]", "");
            str = str.Trim();
            if (str.StartsWith("[STORY_"))
            {
                str = str.Substring(1, str.Length - 2).Get();
            }
            foreach (var(placeholder, function) in PlaceholderFunctions)
            {
                if (str.Contains(placeholder))
                {
                    str = str.Replace(placeholder, function());
                }
            }
            return(str);
        }
    }
예제 #10
0
    protected override void LoadPayload(ScreenLoadPromise promise)
    {
        SpinnerOverlay.Show();
        Context.CharacterManager.GetAvailableCharactersMeta()
        .Then(async characters =>
        {
            try
            {
                if (Application.isEditor)
                {
                    Debug.Log("Available characters:");
                    characters.PrintJson();
                }

                if (characters.Count == 0)
                {
                    // TODO: This should not happen! We have Sayaka
                    SpinnerOverlay.Hide();
                    Dialog.PromptGoBack("DIALOG_OFFLINE_FEATURE_NOT_AVAILABLE".Get());
                    promise.Reject();
                    return;
                }

                if (!await Context.BundleManager.DownloadAndSaveCatalog())
                {
                    SpinnerOverlay.Hide();
                    Dialog.PromptGoBack("DIALOG_COULD_NOT_CONNECT_TO_SERVER".Get());
                    promise.Reject();
                    return;
                }

                SpinnerOverlay.Hide();

                var downloadsRequired = 0;
                foreach (var meta in characters)
                {
                    if (!Context.BundleManager.IsUpToDate(CharacterAsset.GetMainBundleId(meta.AssetId)))
                    {
                        downloadsRequired++;
                    }
                }

                print($"Number of downloads required: {downloadsRequired}");

                var downloaded = 0;
                foreach (var meta in characters)
                {
                    var(success, locallyResolved) =
                        await Context.CharacterManager.DownloadCharacterAssetDialog(
                            CharacterAsset.GetMainBundleId(meta.AssetId));
                    if (success && !locallyResolved)
                    {
                        downloaded++;
                        print("Downloaded " + meta.AssetId);
                    }

                    if (!success)
                    {
                        Toast.Next(Toast.Status.Failure, "CHARACTER_FAILED_TO_DOWNLOAD".Get());
                    }
                    else
                    {
                        IntentPayload.OwnedCharacters.Add(meta);
                    }
                }

                print($"Number of downloads: {downloaded}");

                if (downloaded > downloadsRequired)
                {
                    // Update was performed, which requires player to restart the game
                    // Why? Too lazy to figure out dynamic reloads...
                    Dialog.PromptUnclosable("DIALOG_RESTART_REQUIRED".Get());
                    promise.Reject();
                    return;
                }

                if (IntentPayload.OwnedCharacters.Count == 0)
                {
                    Dialog.PromptGoBack("DIALOG_OFFLINE_FEATURE_NOT_AVAILABLE".Get());
                    promise.Reject();
                    return;
                }

                promise.Resolve(IntentPayload);
            }
            catch (Exception e)
            {
                Debug.LogError(e);
                SpinnerOverlay.Hide();
                Dialog.PromptGoBack("DIALOG_COULD_NOT_CONNECT_TO_SERVER".Get());
                promise.Reject();
            }
        })
        .CatchRequestError(error =>
        {
            SpinnerOverlay.Hide();
            promise.Reject();
            if (!error.IsNetworkError)
            {
                throw error;
            }

            Dialog.PromptGoBack("DIALOG_COULD_NOT_CONNECT_TO_SERVER".Get());
        });
    }
예제 #11
0
    public async void LoadCharacter(CharacterMeta meta)
    {
        ParallaxHolder.WillDelaySet = true;

        var isNewCharacter = Context.CharacterManager.ActiveCharacterBundleId != meta.AssetId;

        if (isNewCharacter)
        {
            SpinnerOverlay.Show();

            infoCard.Leave(false);
            characterTransitionElement.Leave(false);
        }

        var character = await Context.CharacterManager.SetActiveCharacter(meta.AssetId);

        if (character == null)
        {
            throw new Exception("Character not downloaded or corrupted");
        }

        if (isNewCharacter)
        {
            await UniTask.Delay(TimeSpan.FromSeconds(0.4f));
        }

        nameText.text = meta.Name;
        nameGradient.SetGradient(character.nameGradient.GetGradient());
        descriptionText.text = meta.Description;
        levelCard.SetModel(meta.Level.ToLevel(LevelType.User));
        illustratorText.text = meta.Illustrator.Name;
        illustratorProfileButton.onPointerClick.SetListener(_ => Application.OpenURL(meta.Illustrator.Url));
        if (meta.CharacterDesigner != null && !meta.CharacterDesigner.Name.IsNullOrEmptyTrimmed())
        {
            characterDesignerHolder.gameObject.SetActive(true);
            characterDesignerText.text = meta.CharacterDesigner.Name;
            characterDesignerProfileButton.onPointerClick.SetListener(_ =>
                                                                      Application.OpenURL(meta.CharacterDesigner.Url));
        }
        else
        {
            characterDesignerHolder.gameObject.SetActive(false);
        }
        infoCard.transform.RebuildLayout();

        if (character.musicAudio == null)
        {
            muteButtonImage.sprite = volumeSprite;
            muteButtonImage.SetAlpha(0.3f);
            muteButton.scaleOnClick = false;
            muteButton.onPointerClick.RemoveAllListeners();
        }
        else
        {
            muteButtonImage.sprite = Context.Player.Settings.PlayCharacterTheme ? volumeSprite : volumeMuteSprite;
            muteButtonImage.SetAlpha(1f);
            muteButton.scaleOnClick = true;
            muteButton.onPointerClick.SetListener(_ =>
            {
                Context.Player.Settings.PlayCharacterTheme = !Context.Player.Settings.PlayCharacterTheme;
                Context.Player.SaveSettings();
                LoopAudioPlayer.Instance.SetMainAudio(Context.Player.Settings.PlayCharacterTheme ? character.musicAudio : LoopAudioPlayer.Instance.defaultLoopAudio);
                muteButtonImage.sprite = Context.Player.Settings.PlayCharacterTheme ? volumeSprite : volumeMuteSprite;
            });
        }

        await characterDisplay.Load(CharacterAsset.GetTachieBundleId(meta.AssetId));

        NavigationBackdrop.Instance.UpdateBlur();

        infoCard.Enter();
        characterTransitionElement.Leave(false, true);
        characterTransitionElement.Enter();
        characterTransitionElement.Apply(it =>
        {
            it.enterMultiplier = 0.4f;
            it.enterDelay      = 0.4f;
            it.enterDuration   = 0.8f;
        });

        if (Context.IsOffline())
        {
            SpinnerOverlay.Hide();
        }
        else
        {
            RestClient.Post(new RequestHelper
            {
                Uri         = $"{Context.ApiUrl}/profile/{Context.Player.Id}/character",
                Headers     = Context.OnlinePlayer.GetRequestHeaders(),
                EnableDebug = true,
                Body        = new CharacterPostData
                {
                    characterId = meta.Id
                }
            })
            .CatchRequestError(error =>
            {
                Debug.LogError(error);
                Toast.Next(Toast.Status.Failure, "TOAST_FAILED_TO_UPDATE_PROFILE_CHARACTER".Get());
            })
            .Finally(() =>
            {
                SpinnerOverlay.Hide();
            });
        }

        ParallaxHolder.WillDelaySet = false;
    }
예제 #12
0
    protected override async void LoadPayload(ScreenLoadPromise promise)
    {
        if (Context.Player.ShouldOneShot("Agree Copyright Policy"))
        {
            Context.Player.ClearOneShot("Agree Copyright Policy");
            if (!await TermsOverlay.Show("COPYRIGHT_POLICY".Get()))
            {
                promise.Reject();
                Context.ScreenManager.ChangeScreen(Context.ScreenManager.PopAndPeekHistory(), ScreenTransition.Out,
                                                   addTargetScreenToHistory: false);
                return;
            }
            Context.Player.ShouldOneShot("Agree Copyright Policy");
        }

        SpinnerOverlay.Show();

        var promises = new List <IPromise>();

        foreach (var section in IntentPayload.Layout.Sections)
        {
            switch (section)
            {
            case Layout.LevelSection levelSection:
                promises.Add(RestClient.GetArray <OnlineLevel>(new RequestHelper
                {
                    Uri         = levelSection.Query.BuildUri(levelSection.PreviewSize),
                    Headers     = Context.OnlinePlayer.GetRequestHeaders(),
                    EnableDebug = true
                }).Then(data =>
                {
                    levelSection.Levels = data.ToList();
                }));
                break;

            case Layout.CollectionSection collectionSection:
            {
                var collectionPromises = new List <RSG.IPromise <CollectionMeta> >();
                foreach (var collectionId in collectionSection.CollectionIds)
                {
                    collectionPromises.Add(RestClient.Get <CollectionMeta>(new RequestHelper {
                            Uri         = $"{Context.ApiUrl}/collections/{collectionId}",
                            Headers     = Context.OnlinePlayer.GetRequestHeaders(),
                            EnableDebug = true
                        }));
                }
                promises.Add(Promise <CollectionMeta> .All(collectionPromises).Then(data =>
                    {
                        collectionSection.Collections = data.ToList()
                                                        .Zip(collectionSection.CollectionIds, (meta, id) => meta.Also(it => it.id                = id))
                                                        .Zip(collectionSection.CollectionTitleKeys, (meta, title) => meta.Also(it => it.title    = title.Get()))
                                                        .Zip(collectionSection.CollectionSloganKeys, (meta, slogan) => meta.Also(it => it.slogan = slogan.Get()))
                                                        .ToList();
                    }));
                break;
            }
            }
        }

        Promise.All(promises)
        .Then(() =>
        {
            promise.Resolve(IntentPayload);
        })
        .Catch(error =>
        {
            Dialog.PromptGoBack("DIALOG_COULD_NOT_CONNECT_TO_SERVER".Get());
            Debug.LogError(error);
            promise.Reject();
        })
        .Finally(() => SpinnerOverlay.Hide());
    }
예제 #13
0
    public void LoadEvent(EventMeta meta)
    {
        async UniTask LoadCover(CancellationToken token)
        {
            Assert.IsNotNull(meta.cover);

            var tasks = new List <UniTask>();

            if (coverImage.sprite != null)
            {
                coverImage.DOKill();
                coverImage.DOColor(Color.black, 0.4f);
                tasks.Add(UniTask.Delay(TimeSpan.FromSeconds(0.4f), cancellationToken: token));
            }

            Sprite sprite = null;

            tasks.Add(Context.AssetMemory.LoadAsset <Sprite>(meta.cover.OriginalUrl, AssetTag.EventCover, cancellationToken: token).ContinueWith(result => sprite = result));

            try
            {
                await tasks;
            }
            catch (OperationCanceledException)
            {
                return;
            }

            coverImage.sprite = sprite;
            coverImage.FitSpriteAspectRatio();
            coverImage.DOColor(Color.white, 2f).SetDelay(0.8f);
        }

        async UniTask LoadLogo(CancellationToken token)
        {
            Assert.IsNotNull(meta.logo);

            var tasks = new List <UniTask>();

            if (logoImage.sprite != null)
            {
                logoImage.DOKill();
                logoImage.DOFade(0, 0.4f);
                tasks.Add(UniTask.Delay(TimeSpan.FromSeconds(0.4f), cancellationToken: token));
            }

            Sprite sprite = null;

            tasks.Add(Context.AssetMemory.LoadAsset <Sprite>(meta.logo.OriginalUrl, AssetTag.EventLogo, cancellationToken: token).ContinueWith(result => sprite = result));

            try
            {
                await tasks;
            }
            catch (OperationCanceledException)
            {
                return;
            }

            logoImage.sprite = sprite;
            logoImage.DOFade(1, 0.8f).SetDelay(0.4f);
        }

        AddTask(LoadCover);
        AddTask(LoadLogo);

        Context.Player.Settings.SeenEvents.Add(meta.uid);
        Context.Player.SaveSettings();

        infoBanner.Leave(onComplete: () =>
        {
            if (!Context.Player.Settings.ReadEventDetails.Contains(meta.uid))
            {
                viewDetailsNotification.Show();
            }
            viewDetailsButton.onPointerClick.SetListener(_ =>
            {
                Context.Player.Settings.ReadEventDetails.Add(meta.uid);
                Context.Player.SaveSettings();
                viewDetailsNotification.Hide();
                if (meta.url.IsNullOrEmptyTrimmed())
                {
                    Application.OpenURL($"{Context.WebsiteUrl}/posts/{meta.uid}");
                }
                else
                {
                    WebViewOverlay.Show(meta.url,
                                        onFullyShown: () =>
                    {
                        LoopAudioPlayer.Instance.FadeOutLoopPlayer();
                    },
                                        onFullyHidden: async() =>
                    {
                        AudioSettings.Reset(AudioSettings.GetConfiguration());
                        Context.AudioManager.Dispose();
                        Context.AudioManager.Initialize();
                        await UniTask.DelayFrame(5);
                        LoopAudioPlayer.Instance.Apply(it =>
                        {
                            it.FadeInLoopPlayer();
                            it.PlayAudio(it.PlayingAudio, forceReplay: true);
                        });
                    });
                }
            });
            const string dateFormat = "yyyy/MM/dd HH:mm";
            durationText.text       = (meta.startDate.HasValue ? meta.startDate.Value.LocalDateTime.ToString(dateFormat) : "")
                                      + "~"
                                      + (meta.endDate.HasValue ? meta.endDate.Value.LocalDateTime.ToString(dateFormat) : "");
            enterButton.onPointerClick.SetListener(_ =>
            {
                if (meta.locked)
                {
                    Context.Haptic(HapticTypes.Failure, true);
                    // TODO
                    return;
                }
                Context.Haptic(HapticTypes.SoftImpact, true);
                if (meta.levelId != null)
                {
                    SpinnerOverlay.Show();

                    RestClient.Get <OnlineLevel>(new RequestHelper
                    {
                        Uri = $"{Context.ApiUrl}/levels/{meta.levelId}"
                    }).Then(level =>
                    {
                        Context.ScreenManager.ChangeScreen(
                            GamePreparationScreen.Id, ScreenTransition.In, 0.4f,
                            transitionFocus: GetComponent <RectTransform>().GetScreenSpaceCenter(),
                            payload: new GamePreparationScreen.Payload {
                            Level = level.ToLevel(LevelType.User)
                        }
                            );
                    }).CatchRequestError(error =>
                    {
                        Debug.LogError(error);
                        Dialog.PromptAlert("DIALOG_COULD_NOT_CONNECT_TO_SERVER".Get());
                    }).Finally(() => SpinnerOverlay.Hide());
                }
                else if (meta.collectionId != null)
                {
                    Context.ScreenManager.ChangeScreen(
                        CollectionDetailsScreen.Id, ScreenTransition.In, 0.4f,
                        transitionFocus: GetComponent <RectTransform>().GetScreenSpaceCenter(),
                        payload: new CollectionDetailsScreen.Payload
                    {
                        CollectionId = meta.collectionId, Type = LevelType.User
                    }
                        );
                }
            });
            infoBanner.transform.RebuildLayout();
            infoBanner.Enter();
        });
    }
예제 #14
0
    private async void OnDeepLinkReceived(string url)
    {
        Debug.Log($"Deep link received: {url}");
        if (!url.StartsWith("cytoid://"))
        {
            return;
        }

        var token = deepLinkToken = DateTimeOffset.Now;

        await UniTask.WaitUntil(() => Context.ScreenManager != null &&
                                Context.ScreenManager.History.Any(it => it.ScreenId == MainMenuScreen.Id));

        if (token != deepLinkToken)
        {
            return;
        }

        if (DeepLinkDisabledScreenIds.Contains(Context.ScreenManager.ActiveScreenId))
        {
            Debug.Log($"Ignoring, current screen: {Context.ScreenManager.ActiveScreenId}");
            return;
        }

        url = url.Substring("cytoid://".Length);

        if (url.StartsWith("levels/"))
        {
            var id = url.Substring("levels/".Length);

            SpinnerOverlay.Show();

            RestClient.Get <OnlineLevel>(new RequestHelper
            {
                Uri = $"{Context.ApiUrl}/levels/{id}"
            }).Then(async level =>
            {
                try
                {
                    if (token != deepLinkToken)
                    {
                        return;
                    }

                    foreach (var tag in (AssetTag[])Enum.GetValues(typeof(AssetTag)))
                    {
                        if (tag == AssetTag.PlayerAvatar)
                        {
                            continue;
                        }
                        Context.AssetMemory.DisposeTaggedCacheAssets(tag);
                    }

                    while (Context.ScreenManager.PeekHistory().Let(it => it != null && it.ScreenId != MainMenuScreen.Id))
                    {
                        Context.ScreenManager.PopAndPeekHistory();
                    }

                    await UniTask.WaitUntil(() => !Context.ScreenManager.IsChangingScreen);

                    // Resolve level
                    if (Context.LevelManager.LoadedLocalLevels.ContainsKey(level.Uid))
                    {
                        var localLevel = Context.LevelManager.LoadedLocalLevels[level.Uid];
                        Debug.Log($"Online level {level.Uid} resolved locally");

                        Context.ScreenManager.History.Push(new Intent(LevelSelectionScreen.Id, null));
                        Context.ScreenManager.ChangeScreen(GamePreparationScreen.Id, ScreenTransition.In,
                                                           payload: new GamePreparationScreen.Payload {
                            Level = localLevel
                        });
                    }
                    else
                    {
                        Context.ScreenManager.History.Push(new Intent(CommunityHomeScreen.Id, null));
                        Context.ScreenManager.ChangeScreen(GamePreparationScreen.Id, ScreenTransition.In,
                                                           payload: new GamePreparationScreen.Payload {
                            Level = level.ToLevel(LevelType.User)
                        });
                    }
                }
                catch (Exception e)
                {
                    Debug.LogError(e);
                    Dialog.PromptAlert("DIALOG_COULD_NOT_CONNECT_TO_SERVER".Get());
                }
            }).CatchRequestError(error =>
            {
                if (token != deepLinkToken)
                {
                    return;
                }
                if (error.IsHttpError)
                {
                    if (error.StatusCode != 404)
                    {
                        throw error;
                    }
                }
                Context.Haptic(HapticTypes.Failure, true);
                Dialog.Instantiate().Also(it =>
                {
                    it.Message           = "DIALOG_COULD_NOT_OPEN_LEVEL_X".Get(id);
                    it.UsePositiveButton = true;
                    it.UseNegativeButton = false;
                }).Open();
            }).Finally(() =>
            {
                if (token != deepLinkToken)
                {
                    return;
                }
                SpinnerOverlay.Hide();
            });
        }
        else
        {
            Debug.LogError("Unsupported deep link");
        }
    }
예제 #15
0
    private async void OnOfflineModeToggled(bool offline)
    {
        SpinnerOverlay.Show();
        async void Fix(GameObject itGameObject, bool active)
        {
            // Yes, welcome to Unity.
            // Don't change, unless you are absolutely certain what I am (and you are) doing.
            itGameObject.SetActive(active);
            LayoutFixer.Fix(itGameObject.transform);
            await UniTask.DelayFrame(5);

            itGameObject.SetActive(!itGameObject.activeSelf);
            await UniTask.DelayFrame(0);

            itGameObject.SetActive(!itGameObject.activeSelf);
            await UniTask.DelayFrame(0);

            LayoutFixer.Fix(itGameObject.transform);
            if (active)
            {
                itGameObject.GetComponent <TransitionElement>()?.Apply(x => x.UseCurrentStateAsDefault());
            }
        }

        foreach (var gameObject in SceneManager.GetActiveScene().GetRootGameObjects())
        {
            gameObject.GetComponentsInChildren <OfflineElement>(true).ForEach(it =>
            {
                if (offline)
                {
                    it.targets.ForEach(x => x.SetActive(false));
                    it.gameObject.SetActive(true);
                }
                else
                {
                    it.gameObject.SetActive(false);
                    it.targets.ForEach(x => x.SetActive(true));
                }
                it.rebuildTransform.RebuildLayout();
                var o = it.rebuildTransform.gameObject;
                Fix(o, o.activeSelf);
            });
        }

        await UniTask.DelayFrame(10);

        foreach (var gameObject in SceneManager.GetActiveScene().GetRootGameObjects())
        {
            gameObject.GetComponentsInChildren <HiddenIfOfflineElement>(true).ForEach(it =>
            {
                Fix(it.gameObject, !offline);
                var rebuild = it.rebuildTransform;
                if (rebuild != null)
                {
                    rebuild.RebuildLayout();
                    var o = rebuild.gameObject;
                    Fix(o, o.activeSelf);
                }
            });
        }

        await UniTask.DelayFrame(10);

        foreach (var screen in Context.ScreenManager.createdScreens)
        {
            LayoutFixer.Fix(screen.transform);
        }

        await UniTask.DelayFrame(5);

        SpinnerOverlay.Hide();
    }
예제 #16
0
    public async void LoadContent()
    {
        SpinnerOverlay.Show();
        var willUnpackAll = false;

        if (Context.Player.Settings.TrainingModeVersion < BuiltInData.TrainingModeVersion)
        {
            Context.Player.Settings.TrainingModeVersion = BuiltInData.TrainingModeVersion;
            Context.Player.SaveSettings();
            willUnpackAll = true;
        }

        // Logic:
        // If online: load from API
        // If offline: load from static list
        // Then for any not found in path & data built in, extract from StreamingAssets folder

        var levels = new List <Level>();
        var builtInLevelsToUnpack = new List <string>();

        if (Context.IsOnline())
        {
            RestClient.Get <TrainingData>(Context.ApiUrl + "/training")
            .Then(data =>
            {
                // Save to DB
                Context.Database.Let(it =>
                {
                    var col = it.GetCollection <TrainingData>("training");
                    col.DeleteMany(x => true);
                    col.Insert(data);
                });

                foreach (var onlineLevel in data.Levels)
                {
                    if (!willUnpackAll && (onlineLevel.HasLocal(LevelType.User) || !BuiltInData.TrainingModeLevelIds.Contains(onlineLevel.Uid)))
                    {
                        levels.Add(onlineLevel.ToLevel(LevelType.User));
                    }
                    else
                    {
                        builtInLevelsToUnpack.Add(onlineLevel.Uid);
                    }
                }
                Continuation();
            })
            .CatchRequestError(error =>
            {
                Debug.LogError(error);
                Dialog.PromptGoBack("DIALOG_COULD_NOT_CONNECT_TO_SERVER".Get());
                SpinnerOverlay.Hide();
            });
        }
        else
        {
            // Load from DB, or use default
            var levelUids =
                Context.Database.GetCollection <TrainingData>("training").FindOne(x => true)?.Levels
                .Select(it => it.Uid) ?? BuiltInData.TrainingModeLevelIds;

            foreach (var uid in levelUids)
            {
                if (!willUnpackAll && Context.LevelManager.LoadedLocalLevels.ContainsKey(uid) &&
                    Context.LevelManager.LoadedLocalLevels[uid].Type == LevelType.User)
                {
                    levels.Add(Context.LevelManager.LoadedLocalLevels[uid]);
                }
                else
                {
                    builtInLevelsToUnpack.Add(uid);
                }
            }
            Continuation();
        }

        async void Continuation()
        {
            print($"Resolved levels: {string.Join(", ", levels.Select(it => it.Id))}");
            print($"Built-in levels to unpack: {string.Join(", ", builtInLevelsToUnpack)}");

            var packagePaths = await Context.LevelManager.CopyBuiltInLevelsToDownloads(builtInLevelsToUnpack);

            if (packagePaths.Count > 0)
            {
                Toast.Next(Toast.Status.Loading, "TOAST_INITIALIZING_TRAINING_MODE".Get());

                Context.LevelManager.OnLevelInstallProgress.AddListener(SpinnerOverlay.OnLevelInstallProgress);
                var jsonPaths = await Context.LevelManager.InstallLevels(packagePaths, LevelType.User);

                Context.LevelManager.OnLevelInstallProgress.RemoveListener(SpinnerOverlay.OnLevelInstallProgress);

                Context.LevelManager.OnLevelLoadProgress.AddListener(SpinnerOverlay.OnLevelLoadProgress);
                var loadedLevels = await Context.LevelManager.LoadFromMetadataFiles(LevelType.User, jsonPaths);

                Context.LevelManager.OnLevelLoadProgress.RemoveListener(SpinnerOverlay.OnLevelLoadProgress);

                levels.AddRange(loadedLevels);
            }

            SpinnerOverlay.Hide();

            LoadedContent = new Content {
                Levels = levels.OrderBy(it => it.Meta.GetEasiestDifficultyLevel()).ToList()
            };
            OnContentLoaded(LoadedContent);
        }
    }