public static Result ComposeLaunchURL(string id_opt, WorldAccessLevel accessLevel)
        {
            var access = accessStringOf(accessLevel);

            var bid = ExtractSceneBlueprintId(id_opt);

            if (!bid.IsSucceeded)
            {
                return(bid);
            }
            var blueprintId = bid.blueprintId;

            var nonce  = Guid.NewGuid();
            var instno = new System.Random().Next(1000, 9000);


            // NOTE 'ref' should be other value. But leave it because the API is undocumented.
            //  "vrchat://launch?ref=vrchat.com&id={blueprintId}:{instno}~{access}({userid})~nonce({nonce}){option}";

            var url = "vrchat://launch?ref=vrchat.com&id=" + blueprintId + ":" + instno;

            if (accessLevel != WorldAccessLevel.Public)
            {
                if (!VRC.Core.APIUser.IsLoggedInWithCredentials)
                {
                    return(new Result(bid, false, "Not logged in. (Open 'VRChat SDK/Settings' to check and try again)"));
                }

                var user = VRC.Core.APIUser.CurrentUser;
                if (user == null)
                {
                    return(new Result(bid, false, "user == null"));
                }
                var userid = user.id;
                if (userid == null)
                {
                    return(new Result(bid, false, "user.id == null"));
                }

                // add more
                url += "~" + access + "(" + userid + ")~nonce(" + nonce + ")";

                if (accessLevel == WorldAccessLevel.InvitePlus)
                {
                    // add more
                    url += "~canRequestInvite";
                }
            }

            return(new Result(bid, true, url));
        }
        private static string accessStringOf(WorldAccessLevel wal)
        {
            switch (wal)
            {
            case WorldAccessLevel.Public:      return("");

            case WorldAccessLevel.FriendsPlus: return("hidden");

            case WorldAccessLevel.Friends:     return("friends");

            case WorldAccessLevel.InvitePlus:  return("private");

            case WorldAccessLevel.Invite:      return("private");

            default:
                throw new NotImplementedException("Not implemented for " + wal);
            }
        }
        public static Result TryToOpenLaunchURL(string id_opt, WorldAccessLevel accessLevel)
        {
            var url = ComposeLaunchURL(id_opt, accessLevel);

            return((settings.startLikeAsSDK)? TryToStart(url): TryToOpen(url));
        }