Exemplo n.º 1
0
    IEnumerator InitializeNewPlayer(PhotonPlayer newPlayer)
    {
        NewPlayerInitPayload payload;

        payload.version          = NewPlayerInitPayload.CurrentVersion;
        payload.behaviorDatabase = behaviorSystem.SaveDatabase();
        payload.sojoDatabase     = sojoSystem.SaveDatabase();
        payload.terrainMeta      = terrain.GetMetadata();
        payload.stage            = stage.Save();

        string metaJson = JsonUtility.ToJson(payload);

        byte[] zippedMetaBytes = Util.GZip(Encoding.UTF8.GetBytes(metaJson));
        byte[] zippedVoosBytes = GetVoosInitBytes();
        byte[] terrainV2Bytes  = terrain.SerializeTerrainV2();

        if (((zippedMetaBytes.Length + zippedVoosBytes.Length + terrainV2Bytes.Length) / 1024) > MaximumPlayerInitKbs)
        {
            throw new System.Exception($"Sorry, your game has become too large for multiplayer. We recommend loading it in single player and removing some unnecessary actors, assets, or cards. If you need more help, please post to the Steam discussion forums.");
        }

        Util.Log($"Sending {voosEngine.GetNumActors()} actors and to new player {newPlayer.ID}, zippedMetaBytes: {zippedMetaBytes.Length / 1024} KB, zippedVoosBytes: {zippedVoosBytes.Length / 1024} KB");
        photonView.RPC("InitNewPlayerRPC", newPlayer, zippedMetaBytes, zippedVoosBytes);

        // Send terrain on its own. Avoid the JSON stuff.
        Util.Log($"Sending terrain init msg, {terrainV2Bytes.Length / 1024} kb zipped");
        photonView.RPC("InitNewPlayerTerrainRPC", newPlayer, terrainV2Bytes);

        // IMPORTANT: Also tell ALL players that, after the prior RPCs, the new
        // player should be ready to participate normally. This will trigger
        // everyone to, for example, broadcast fresh snapshots for actors they own
        // to the new player. This was done anyway, by Photon's builtin behavior,
        // but because we manage actor views on our own, the new player wasn't ready
        // to receive those yet. Wasteful, yes, but we need this.
        yield return(new WaitForSecondsRealtime(3f));

        photonView.RPC("NewPlayerWasInitializedRPC", PhotonTargets.AllViaServer);

        // NOTE FOR FUTURE: I think the real solution here is to stop relying on
        // Photon's RDC at all. It's not efficient for us (we can do change
        // detection at the setter level..), and having PhotonView coupled to
        // VoosActor's life time is unnecessarily restrictive. Ideally, all we would
        // do is this: VoosEngine would not be allowed to run on the new client
        // until all other players have sent over their local actors' full state.
        // But while VOOS is paused, we still can receive delta updates via RPC.
        // Then when we get all state from all other players, we can start running
        // like normal. This means we don't waste bandwidth by sending all actor
        // state TWICE to the same client, as we do now.
    }