コード例 #1
0
    /// <summary>
    /// Update entire view and alert session of changes.
    /// </summary>
    public bool Update(Vector2 MouseFloorPos)
    {
        // This is the only time that we lock the world on the primary thread (Except for rare debugging cases in CGameSession).
        // All state information is copied from the world from the perspective of a player (_viewPlayerIndex).
        // As little work as possible should be done during the state copy. We want to unlock the world ASAP.

        CGame.PrimaryThreadProfiler.Push(CProfiler.EID.I_RENDER_TICK);
        lock (_world)
        {
            // TODO: Check for a console var to remain on crash.
            if (_world.mCrashed)
            {
                CGame.PrimaryThreadProfiler.Pop();
                return(false);
            }

            System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
            sw.Start();

            CGame.PrimaryThreadProfiler.Push(CProfiler.EID.I_RENDER_TICK);

            // Copy door segments for visibility
            _world.mMap.TrimStaticVisSegments();
            for (int i = 0; i < _world.mItems.Count; ++i)
            {
                CItem item = _world.mItems[i];
                if (item.mType == CEntity.EType.ITEM_DOOR && !item.mBluerprint && !(item as CItemDoor).mOpen)
                {
                    _world.mMap.mStaticVisSegments.Add(new CVisibilityBlockingSegment(item.ItemToWorldSpacePosition(new Vector2(0, 1)), item.ItemToWorldSpacePosition(new Vector2(1, 1))));
                }
            }

            // Copy all the state!!!!!
            mTransientEvents       = _world.SwapAndClearTransientEvents();
            mPaydayTimerNormalised = 1.0f - _world.GetPaydayTimeNormalize();
            mGameTick = _world.mGameTick;

            // Company Data
            // ...

            // Player Data
            for (int i = 0; i < mPlayerViews.Length; ++i)
            {
                CPlayer     player = _world.mPlayers[i];
                CPlayerView view   = mPlayerViews[i];

                view.mIndex                = player.mID;
                view.mColor                = player.mColor;
                view.mMoney                = player.mMoney;
                view.mDebt                 = player.mDebt;
                view.mSpawnPos             = player.GetSpawnPos();
                view.mCanInteractWithWorld = player.mCanInteractWithWorld;
                view.mCanInteractWithUI    = player.mCanInteractWithUI;
                view.mCanControlCamera     = player.mCanControlCamera;
                view.mMusicTrack           = player.mMusicTrack;
                view.mShowUI               = player.mShowUI;
                view.mCamPosition          = player.mCamPosition;
                view.mCamSpeed             = player.mCamSpeed;
                view.mAvailableItems       = player.mAvailableItems.ToArray();
            }

            // TODO: Should just iterate all entities and ask them if they are valid for state copy.

            // Unit Data
            // TODO: Surely the sim knows what units are visible to the player already?
            for (int i = 0; i < _world.mUnits.Count; ++i)
            {
                if (_world.mUnits[i].IsVisibleToPlayer(_viewPlayerIndex))
                {
                    if (_world.mUnits[i].mStateView == null)
                    {
                        CUnitView view = new CUnitView();
                        view.mState = CStateView.EState.NEW;
                        mStateViews.Add(view);
                        view.CopyInitialState(_world.mUnits[i]);
                        view.Init(_viewPlayerIndex, this);
                        _world.mUnits[i].mStateView = view;
                    }
                    else
                    {
                        _world.mUnits[i].mStateView.mState = CStateView.EState.UPDATING;
                    }

                    _world.mUnits[i].mStateView.CopyState(_world.mUnits[i]);
                }
                else
                {
                    _world.mUnits[i].mStateView = null;
                }
            }

            // Pickups
            for (int i = 0; i < _world.mPickups.Count; ++i)
            {
                if (_world.mPickups[i].IsVisibleToPlayer(_viewPlayerIndex))
                {
                    if (_world.mPickups[i].mStateView == null)
                    {
                        CPickupView view = new CPickupView();
                        view.mState = CStateView.EState.NEW;
                        mStateViews.Add(view);
                        view.CopyInitialState(_world.mPickups[i]);
                        view.Init(_viewPlayerIndex, this);
                        _world.mPickups[i].mStateView = view;
                    }
                    else
                    {
                        _world.mPickups[i].mStateView.mState = CStateView.EState.UPDATING;
                    }

                    _world.mPickups[i].mStateView.CopyState(_world.mPickups[i]);
                }
                else
                {
                    _world.mPickups[i].mStateView = null;
                }
            }

            // Missiles
            for (int i = 0; i < _world.mMissiles.Count; ++i)
            {
                if (_world.mMissiles[i].IsVisibleToPlayer(_viewPlayerIndex))
                {
                    if (_world.mMissiles[i].mStateView == null)
                    {
                        CMissileView view = new CMissileView();
                        view.mState = CStateView.EState.NEW;
                        mStateViews.Add(view);
                        view.CopyInitialState(_world.mMissiles[i]);
                        view.Init(_viewPlayerIndex, this);
                        _world.mMissiles[i].mStateView = view;
                    }
                    else
                    {
                        _world.mMissiles[i].mStateView.mState = CStateView.EState.UPDATING;
                    }

                    _world.mMissiles[i].mStateView.CopyState(_world.mMissiles[i]);
                }
                else
                {
                    _world.mMissiles[i].mStateView = null;
                }
            }

            // Item View Data
            for (int i = 0; i < _world.mItemProxies[_viewPlayerIndex].Count; ++i)
            {
                CItemProxy proxy = _world.mItemProxies[_viewPlayerIndex][i];

                if (proxy.mVisuals == null)
                {
                    // new
                    CItemView view = new CItemView();
                    view.mState = CStateView.EState.NEW;
                    mStateViews.Add(view);
                    view.CopyInitialState(proxy);
                    view.Init(_viewPlayerIndex, this);
                    proxy.mVisuals = view;
                }
                else
                {
                    proxy.mVisuals.mState = CStateView.EState.UPDATING;
                }

                proxy.mVisuals.CopyState(proxy);
            }

            // Contract Data
            for (int i = 0; i < _world.mContracts.Count; ++i)
            {
                CContract contract = _world.mContracts[i];

                // TODO: All contracts always part of user view state?
                //if (contract.mOwner == -1 || contract.mOwner == _viewPlayerIndex)
                if (true)
                {
                    if (contract.mStateView == null)
                    {
                        // new
                        CContractView view = new CContractView();
                        view.mState = CStateView.EState.NEW;
                        mStateViews.Add(view);
                        view.CopyInitialState(contract);
                        view.Init(_viewPlayerIndex, this);
                        contract.mStateView = view;
                    }
                    else
                    {
                        contract.mStateView.mState = CStateView.EState.UPDATING;
                    }

                    contract.mStateView.CopyState(contract);
                }
                else
                {
                    contract.mStateView = null;
                }
            }

            // Resume View Data
            for (int i = 0; i < _world.mResumes.Count; ++i)
            {
                CResume resume = _world.mResumes[i];

                if (resume.mOwner != -1)
                {
                    if (resume.mStateView == null)
                    {
                        // new
                        CResumeView view = new CResumeView();
                        view.mState = CStateView.EState.NEW;
                        mStateViews.Add(view);
                        view.CopyInitialState(resume);
                        view.Init(_viewPlayerIndex, this);
                        resume.mStateView = view;
                    }
                    else
                    {
                        resume.mStateView.mState = CStateView.EState.UPDATING;
                    }

                    resume.mStateView.CopyState(resume);
                }
                else
                {
                    resume.mStateView = null;
                }
            }

            // Decal View Data
            for (int i = 0; i < _world.mDecals.Count; ++i)
            {
                CDecal decal = _world.mDecals[i];

                // TODO: Allow decals to be visible to certain players only.

                if (decal.mStateView == null)
                {
                    // new
                    CDecalView view = new CDecalView();
                    view.mState = CStateView.EState.NEW;
                    mStateViews.Add(view);
                    view.CopyInitialState(decal);
                    view.Init(_viewPlayerIndex, this);
                    decal.mStateView = view;
                }
                else
                {
                    decal.mStateView.mState = CStateView.EState.UPDATING;
                }

                decal.mStateView.CopyState(decal);
            }

            sw.Stop();
            //Debug.Log("Copy " + sw.Elapsed.TotalMilliseconds + "ms");

            CGame.PrimaryThreadProfiler.Pop();
        }
        CGame.PrimaryThreadProfiler.Pop();

        // NOTE: Now that the state has been copied from the simulation and we have released the thread lock, we can
        // process the new state and make appropriate changes to the Unity scene.

        CGame.UIManager.PlayMusic(mPlayerViews[_viewPlayerIndex].mMusicTrack);
        CGame.UIManager.mShowUI       = mPlayerViews[_viewPlayerIndex].mShowUI;
        _userSession.mUserInteraction = mPlayerViews[_viewPlayerIndex].mCanInteractWithWorld;
        CGame.CameraManager.SetInteractable(mPlayerViews[_viewPlayerIndex].mCanControlCamera);
        CGame.CameraManager.SetLerpSpeed(mPlayerViews[_viewPlayerIndex].mCamSpeed);

        // TODO: Different bool to control tracked camera?
        if (!mPlayerViews[_viewPlayerIndex].mCanControlCamera)
        {
            // TODO: Immediate of on different cam step.
            CGame.CameraManager.SetTargetPosition(mPlayerViews[_viewPlayerIndex].mCamPosition, false, mPlayerViews[_viewPlayerIndex].mCamPosition.w);
        }

        for (int i = 0; i < mTransientEvents.Count; ++i)
        {
            CTransientEvent tev = mTransientEvents[i];

            // Ignore events that occured over 1 second ago.
            if (mGameTick > tev.mGameTick + 20)
            {
                continue;
            }

            if ((tev.mViewerFlags & (1 << _viewPlayerIndex)) == 0)
            {
                continue;
            }

            if (tev.mType == CTransientEvent.EType.SOUND)
            {
                //AudioSource.PlayClipAtPoint(CGame.PrimaryResources.AudioClips[tev.mData], tev.mPosition, 1.0f);
                AudioClip  clip   = CGame.PrimaryResources.AudioClips[tev.mData];
                GameObject source = new GameObject("AudioPosOneShot");
                source.transform.SetParent(_userSession.mPrimaryScene.transform);
                source.transform.position = tev.mPosition;
                AudioSource audio = source.AddComponent <AudioSource>();
                audio.clip = clip;
                audio.outputAudioMixerGroup = CGame.UIResources.SoundsMixer;
                audio.spatialBlend          = 1.0f;
                audio.Play();
                GameObject.Destroy(source, clip.length);
            }
            else if (tev.mType == CTransientEvent.EType.UI_SOUND)
            {
                CGame.UIManager.PlaySound(CGame.PrimaryResources.AudioClips[tev.mData]);
            }
            else if (tev.mType == CTransientEvent.EType.EFFECT)
            {
                GameObject.Instantiate(CGame.PrimaryResources.Particles, tev.mPosition, Quaternion.identity);
                //CGame.CameraManager.Shake();
            }
            else if (tev.mType == CTransientEvent.EType.PAYDAY)
            {
                CGame.UIManager.PlaySound(CGame.PrimaryResources.AudioClips[17]);
            }
            else if (tev.mType == CTransientEvent.EType.NOTIFY)
            {
                Debug.Log("Got notify: " + tev.mMessage);
                _userSession.CreateNotifyStackIcon(2, null, CGame.AssetManager.GetAsset <CItemAsset>(tev.mMessage));
            }
        }

        for (int i = 0; i < mStateViews.Count; ++i)
        {
            if (!mStateViews[i].Update(_userSession))
            {
                mStateViews.RemoveAt(i);
                --i;
            }
            else
            {
                mStateViews[i].mState = CStateView.EState.WAITING;
                mStateViews[i].DrawDebugPrims();
            }
        }

        /*
         * for (int i = 0; i < _stateViews.Count; ++i)
         * {
         *      _stateViews[i].DrawDebugPrims();
         * }
         */

        if (CGame.VarShowFlowField.mValue)
        {
            DrawFlowField();
        }

        if (CGame.VarShowNavMesh.mValue)
        {
            mNavMesh.DebugDraw();
        }

        if (CGame.VarShowNavRect.mValue > 0)
        {
            _world.mMap.mNavMeshes[CGame.VarShowNavRect.mValue - 1].DebugDraw();
        }

        return(true);
    }