Skip to content

Latest commit

 

History

History
327 lines (279 loc) · 8.61 KB

File metadata and controls

327 lines (279 loc) · 8.61 KB

아이템 #2

많은 작업을 했지만 요약하면

DB에 아이템 정보를 넣어주고

Item Sheet에도 아이템 정보를 넣어주고

로그인을 할 때 메모리에 아이템 정보를 할당하고 클라이언트에도 전달하는 작업까지 완료

이어서는 몬스터가 아이템을 드랍

아이템 Sheet에 아이템 정보 추가

{
  "weapons": [
    {
      "id": "1",
      "name": "견습생의 검",
      "weaponType" : "Sword",
      "damage": "10"
    },
    {
      "id": "2",
      "name": "견습생의 활",
      "weaponType" : "Bow",
      "damage": "5"
    }
  ],
  "armors": [
    {
      "id": "100",
      "name": "뼈 값옷",
      "weaponType" : "Armor",
      "defence": "15"
    },
    {
      "id": "101",
      "name": "뼈 투구",
      "weaponType" : "Helmet",
      "defence": "5"
    }
  ],
  "consumables": [
    {
      "id": "200",
      "name": "HP 물약",
      "consumableType" : "Potion",
      "damage": "10"
    }
  ]
}

인벤토리 및 아이템 클래스 추가

using System;
using System.Collections.Generic;
using System.Text;

namespace Server.Game
{
    // 진짜 아이템 인벤토리만 해당할지는 나중에
    // 착용 아이템, 보관 아이템 등을 똑같이 관리 가능하기 때문

    // lock이 필요하지 않을까?
    // => Inventory class를 어디서 사용할지가 관건 
    // => 실제로는 player 안에서 사용할 예정
    // => 따라서 GameRoom 안에서 접근을 하기 때문에 하나의 쓰레드에서만 접근을 하게 된다. (lock x)
    public class Inventory
    {
        Dictionary<int, Item> _items = new Dictionary<int, Item>();

        public void Add(Item item)
        {
            _items.Add(item.ItemDbId, item);
        }

        public Item Get(int itemDbId)
        {
            Item item = null;
            _items.TryGetValue(itemDbId, out item);

            return item;
        }
        
        public Item Find(Func<Item, bool> condition)
        {
            foreach (Item item in _items.Values)
            {
                if (condition.Invoke(item))
                    return item;
            }
            return null;
        }
    }
}
using System;
using System.Collections.Generic;
using System.Text;
using Google.Protobuf.Protocol;
using Server.Data;
using Server.DB;

namespace Server.Game
{
    public class Item
    {
        public  ItemInfo Info { get; } = new ItemInfo();
        public int ItemDbId 
        {
            get { return Info.ItemDbId; }
            set { Info.ItemDbId = value; }
        } 
        public int TemplateId 
        {
            get { return Info.TemplateId; }
            set { Info.TemplateId = value; }
        } 
        public int Count 
        {
            get { return Info.Count; }
            set { Info.Count = value; }
        } 

        public ItemType ItemType { get; private set; }

        // 이 아이템이 겹쳐지는 여부를 판단
        // 일종의 캐싱의 용도
        // TemplateId를 알면 DataManager에 접근해서 해당하는 Max count를 보는 식으로 
        // 겹쳐지는 여부를 알 수가 있다.
        // 마찬가지로 아이템 타입만 알면 Stackable인지 어느정도 확인할 수가 있다.
        public bool Stackable { get; protected set; }

        public Item(ItemType itemType)
        {
            ItemType = ItemType;
        }

        public static Item MakeItem(ItemDb itemDb)
        {
            Item item = null;

            ItemData itemData = null;
            DataManager.ItemDict.TryGetValue(itemDb.TemplateId, out itemData);
            
            if (itemData == null)
                return null;
            
            switch (itemData.itemType)
            {
                case ItemType.Weapon:
                    item = new Weapon(itemDb.TemplateId);
                    break;
                case ItemType.Armor:
                    item = new Armor(itemDb.TemplateId);
                    break;
                case ItemType.Consumable:
                    item = new Consumable(itemDb.TemplateId);
                    break;
            }

            if (item != null)
            {
                item.ItemDbId = itemDb.ItemDbId;
                item.Count = itemDb.Count;
            }

            return item;
        }
    }

    public class Weapon : Item
    {
        public WeaponType WeaponType { get; private set; }
        public int Damage { get; private set; }

        // TemplateId에 따라 WeaponType과 Damage를 채워줘야 한다.
        public Weapon(int templateId) : base(ItemType.Weapon)
        {
            
        }

        void Init(int templateId)
        {
            ItemData itemData = null;
            DataManager.ItemDict.TryGetValue(templateId, out itemData);
            if (itemData.itemType != ItemType.Weapon)
                return;
            
            WeaponData data = (WeaponData)itemData;
            {
                TemplateId = data.id;
                // 무기는 겹치는 개념이 아니기 때문
                Count = 1;
                WeaponType = data.weaponType;
                Damage = data.damage;
                Stackable = false;
            }
        }
    }

    public class Armor : Item
    {
        public ArmorType ArmorType { get; private set; }
        public int Defence { get; private set; }

        // TemplateId에 따라 WeaponType과 Damage를 채워줘야 한다.
        public Armor(int templateId) : base(ItemType.Armor)
        {
            Init(templateId);
        }

        void Init(int templateId)
        {
            ItemData itemData = null;
            DataManager.ItemDict.TryGetValue(templateId, out itemData);
            if (itemData.itemType != ItemType.Armor)
                return;
            
            ArmorData data = (ArmorData)itemData;
            {
                TemplateId = data.id;
                // 무기는 겹치는 개념이 아니기 때문
                Count = 1;
                ArmorType = data.armorType;
                Defence = data.defence;
                Stackable = false;
            }
        }
    }

    public class Consumable : Item
    {
        public ConsumableType ConsumableType { get; private set; }
        public int MaxCount { get; private set; }

        // TemplateId에 따라 WeaponType과 Damage를 채워줘야 한다.
        public Consumable(int templateId) : base(ItemType.Consumable)
        {
            Init(templateId);
        }

        void Init(int templateId)
        {
            ItemData itemData = null;
            DataManager.ItemDict.TryGetValue(templateId, out itemData);
            if (itemData.itemType != ItemType.Consumable)
                return;
            
            ConsumableData data = (ConsumableData)itemData;
            {
                TemplateId = data.id;
                // 무기는 겹치는 개념이 아니기 때문
                Count = 1;
                MaxCount = data.maxCount;
                ConsumableType = data.consumableType;
                Stackable = (data.maxCount > 1);
            }
        }
    }
}

처음 접속 할 때 아이템 정보를 메모리에 들고 있고 클라에게도 전송

// 클라쪽에서 player를 선택 한 다음 Game에 들어올 때 작업
public void HandleEnterGame(C_EnterGame enterGamePacket)
{
    if (ServerState != PlayerServerState.ServerStateLobby)
        return;
    
    LobbyPlayerInfo playerInfo = LobbyPlayers.Find(p => p.Name == enterGamePacket.Name);
    if (playerInfo == null)
        return;
            
			MyPlayer = ObjectManager.Instance.Add<Player>();
			{
          MyPlayer.PlayerDbId = playerInfo.PlayerDbId;
					MyPlayer.Info.Name = playerInfo.Name;
					MyPlayer.Info.PosInfo.State = CreatureState.Idle;
					MyPlayer.Info.PosInfo.MoveDir = MoveDir.Down;
					MyPlayer.Info.PosInfo.PosX = 0;
					MyPlayer.Info.PosInfo.PosY = 0;
					MyPlayer.Stat.MergeFrom(playerInfo.StatInfo);
					MyPlayer.Session = this;

          S_ItemList itemListPacket = new S_ItemList();

          // 이 부분은 게임에 들어가기 이전 상태이다 보니 
          // 여기서 바로 DB에 접근을 해도 크게 문제가 없는 상황
          // PreGame은 DB 접근 안전지대와 같다.

          // Item 목록을 갖고 온다.
          using (AppDbContext db = new AppDbContext())
          {
              List<ItemDb> items = db.Items
                  .Where(i => i.OwnerDbId == playerInfo.PlayerDbId)
                  .ToList();
              
              foreach (ItemDb itemDb in items)
              {
                  Item item = Item.MakeItem(itemDb);
                  if (item != null)
                  {
                      MyPlayer.Inven.Add(item);
                      ItemInfo info = new ItemInfo();
                      info.MergeFrom(item.Info);
                      itemListPacket.Items.Add(info);
                  }
              }
          }
          // TODO 클라한테도 아이템 목록을 전달
          Send(itemListPacket);
			}

    ServerState = PlayerServerState.ServerStateGame;

		GameRoom room = RoomManager.Instance.Find(1);
		room.Push(room.EnterGame, MyPlayer);
}