public void Init(int PlayerID, CItem Item, CWorld World, bool Blueprint)
    {
        if (PlayerID == -1)
        {
            Debug.LogError("CItemProxy should never have a playerID of -1!");
        }

        mID                   = GetNextID();
        mItemID               = Item.mID;
        mState                = EState.S_VISIBLE;
        mPlayerID             = PlayerID;
        mWorld                = World;
        _item                 = Item;
        mBlueprint            = Blueprint;
        mAsset                = Item.mAsset;
        mDurability           = Item.mDurability;
        mMaxDurability        = Item.mMaxDurability;
        mQueueList            = new List <CQueueToken>();
        mPosition             = Item.mPosition;
        mRotation             = Item.mItemRot;
        mBounds               = Item.mBounds;
        mOwnerID              = Item.mOwner;
        mAssignedPaperStacks  = new List <CContractStack>();
        mPaperStackUpdateTick = 0;
        mAssignedUnitID       = -1;

        mSurfaceColor = mWorld.mMap.mBackgroundColor;
        mBounds       = CItem.CalculateBounds(mPosition, mRotation, mAsset.mWidth, mAsset.mLength);

        if (!mBlueprint)
        {
            ModifyLocalCollisionMap(true);

            if (Item.mType == CEntity.EType.ITEM_DOOR)
            {
                mLocked = true;

                if (mWorld.IsAllied(Item.mOwner, PlayerID))
                {
                    mLocked = ((CItemDoor)Item).mLocked;
                }

                DoorModifyLocalCollisionMap(mLocked);
            }
            else if (Item.mType == CEntity.EType.ITEM_SAFE)
            {
                mValue = ((CItemSafe)Item).mValue;
            }
            else if (Item.mType == CEntity.EType.ITEM_DESK)
            {
                mMaxPaperStackSlots = ((CItemDesk)Item).mMaxPaperStackSlots;
            }
        }

        SetVisible();
        UpdateState(Item);
    }
    public void UpdateState(CItem Item)
    {
        if (!mBlueprint)
        {
            mDurability    = Item.mDurability;
            mMaxDurability = Item.mMaxDurability;

            if (Item.mType == CEntity.EType.ITEM_DOOR)
            {
                CItemDoor door = (CItemDoor)Item;
                mDoorPosition = door.mAngle;

                if (mPlayerID == mOwnerID)
                {
                    door.mLocked = mLocked;
                }
                else if (mWorld.IsAllied(mPlayerID, mOwnerID))
                {
                    if (mLocked != door.mLocked)
                    {
                        SetDoorLock(door.mLocked);
                    }
                }
            }
            else if (Item.mType == CEntity.EType.ITEM_START)
            {
                mDoorPosition = ((CItemStart)Item).mDoorPosition;
            }
            else if (Item.mType == CEntity.EType.ITEM_DESK)
            {
                mUserID = ((CItemDesk)Item).mUserID;
                mCompletedPaperStacks = ((CItemDesk)Item).mCompletedStacks.Count;
                mMaxCompletedPapers   = ((CItemDesk)Item).mMaxCompletedPapers;
            }
            else if (Item.mType == CEntity.EType.ITEM_SAFE)
            {
                mValue = ((CItemSafe)Item).mValue;
            }

            // TODO: Update State is only called when the item is visible. We need to update queue tokens every tick.
            UpdateQueueTokens();
        }
    }