ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 멀티플레이어 게임 프로그래밍 - 코드 오류 수정
    프로그래밍/의문 2018. 2. 20. 12:13
    반응형


    178p LinkingContext 코드 개량 부분 오류

    // @comment: 없을 때 0을 반환하기보단, std::optinal(c++14)을 활용해 값이 있고 없음을 구분하도록 하는 게 더 좋을 거 같다.
    uint32_t GetNetworkID(const GameObject* inGameObject, bool inShouldCreateIfNotFound = true)
    {
    auto it = mGameObjectToNetworkIdMap.find(inGameObject);
    if (it != mGameObjectToNetworkIdMap.end())
    {
    return it->second;
    }
    else if (inShouldCreateIfNotFound)
    {
    uint32_t newNetworkId = AllocateId();
    AddGameObject(inGameObject, newNetworkId);
    return newNetworkId;
    }
    return 0;
    }

    std::uint32_t AddGameObject(GameObject* gameObject)
    {
    const std::uint32_t id = AllocateId();
    AddGameObject(gameObject, id);
    return id;
    }

    원인

    인자로 const GameObject*를 받는데, AddGameObject는 GameObject*를 받는다.

    AddGameObject를 호출하려면 inGameObject의 상수성이 깨져야 하므로 오류가 발생한다.


    수정된 코드

    #pragma once

    #include <cstdint>
    #include <unordered_map>
    #include "GameObject.h"

    class LinkingContext
    {
    public:

    LinkingContext() : mNextNetworkId(1)
    {
    }

    // @comment: 없을 때 0을 반환하기보단, std::optinal(c++14)을 활용해 값이 있고 없음을 구분하도록 하는 게 더 좋을 거 같다.
    uint32_t GetNetworkID(GameObject* inGameObject, bool inShouldCreateIfNotFound = true)
    {
    auto it = mGameObjectToNetworkIdMap.find(inGameObject);
    if (it != mGameObjectToNetworkIdMap.end())
    {
    return it->second;
    }
    else if (inShouldCreateIfNotFound)
    {
    uint32_t newNetworkId = AllocateId();
    AddGameObject(inGameObject, newNetworkId);
    return newNetworkId;
    }
    return 0;
    }

    GameObject* GetGameObject(std::uint32_t networkId)
    {
    auto it = mNetworkIdToGameObjectMap.find(networkId);
    return it == mNetworkIdToGameObjectMap.end() ? nullptr : it->second;
    }
    std::uint32_t AddGameObject(GameObject* gameObject)
    {
    const std::uint32_t id = AllocateId();
    AddGameObject(gameObject, id);
    return id;
    }

    void AddGameObject(GameObject* gameObject, std::uint32_t networkId)
    {
    mNetworkIdToGameObjectMap[networkId] = gameObject;
    mGameObjectToNetworkIdMap[gameObject] = networkId;
    }

    void RemoveGameObject(std::uint32_t networkId)
    {
    auto it = mNetworkIdToGameObjectMap.find(networkId);
    if (it == mNetworkIdToGameObjectMap.end())
    {
    return;
    }
    mGameObjectToNetworkIdMap.erase(it->second);
    mNetworkIdToGameObjectMap.erase(it);
    }

    void RemoveGameObject(const GameObject* gameObject)
    {
    auto it = mGameObjectToNetworkIdMap.find(gameObject);
    if (it == mGameObjectToNetworkIdMap.end())
    {
    return;
    }
    mNetworkIdToGameObjectMap.erase(it->second);
    mGameObjectToNetworkIdMap.erase(it);
    }

    private:

    std::uint32_t AllocateId()
    {
    return mNextNetworkId++;
    }

    std::unordered_map<std::uint32_t, GameObject*> mNetworkIdToGameObjectMap;
    std::unordered_map<const GameObject*, std::uint32_t> mGameObjectToNetworkIdMap;
    std::uint32_t mNextNetworkId = 1;
    };


    const를 떼기 싫다면 Write 외부에서 LinkingContext에 등록하는 행위를 Write외부에서 하도록 하거나, GetNetworkID를 const 버전과 non const 버전을 각각 만들어서 const 버전에선 Add를 하지 않고 find만 하도록, 

    non const 버전에선 Add를 하도록 구현을 분리해야 한다.


    추가적으로 LinkingContext에서처럼 인자가 포인터면서, 반드시 들어와야 하는 경우는 인자를 래퍼런스로 받도록 하는 게 더 낫다 생각한다.

    uint32_t GetNetworkID(GameObject& inGameObject, bool inShouldCreateIfNotFound = true)
    {
    auto it = mGameObjectToNetworkIdMap.find(&inGameObject);
    if (it != mGameObjectToNetworkIdMap.end())
    {
    return it->second;
    }
    else if (inShouldCreateIfNotFound)
    {
    uint32_t newNetworkId = AllocateId();
    AddGameObject(inGameObject, newNetworkId);
    return newNetworkId;
    }
    return 0;
    }


    반응형
Designed by Tistory.