通用原则,全部系统都是由Manager和Service组成,Manager负责逻辑操作,通过Service获取服务端信息,Controller操作前端展示 Controller(Mono)→Manager→Service→服务器端。
设计数据结构:配置表结构,协议结构,数据库结构。
服务器:协议结构,数据库结构
客户端:配置表结构
把需要与服务器端交互的字段加入到协议中,给协议中的人物实体增加道具信息,以方便传输人物获得的道具和道具数量。
message NCharacterInfo { --人物信息协议
int32 id = 1;
int32 tid = 2;
string name = 3;
CHARACTER_TYPE type = 4;
CHARACTER_CLASS class = 5;
int32 level = 6;
int32 mapId = 7;
NEntity entity = 8;
repeated NItemInfo Items = 10;
}
message NItemInfo { --道具信息
int32 id = 1;
int32 count= 2;
}
服务器端:ItemManager不能做单例,类里带有一个Character Owner来指定哪个角色,是哪个角色的管理类,来跟随角色。
利用一个字典Dictionary<int, Item>存储所有物品数据,不用每次都要查询数据库。
ItemManager需要在Character实体类中构建,然后填充网络数据(网络数据用于客户端与服务器端的传输。)
OnGameEnter→AddCharacter→Character→ItemManager
-
#ItemManager
class ItemManager { Character Owner; public Dictionary<int, Item> Items = new Dictionary<int, Item>(); //缓存 public ItemManager(Character owner) { //将查询结果存入内存,将itemManger绑定给相应Character this.Owner = owner; foreach (var item in owner.Data.Items) { this.Items.Add(item.ItemId,new Item(item)); } } /** 物品ID,使用数量 */ public bool UseItem(int itemId, int count = 1) { Log.InfoFormat("[{0}] UseItem[{1},{2}]",this.Owner.Data.ID,itemId,count); Item item = null; if (this.Items.TryGetValue(itemId, out item)) { if (item.Count < count) return false; } else { item.Remove(count); return true; } return false; } public bool HasItem(int itemId) { Item item = null; if (Items.TryGetValue(itemId,out item)) { return item.Count>0; } return false; } public Item GetItem(int itemId) { Item item = null; Items.TryGetValue(itemId, out item); return item; } public bool AddItem(int itemId,int count) { //判断是否有 Item item = null; if (Items.TryGetValue(itemId, out item)) { item.Add(count); } else { TCharacterItem characterItem = new TCharacterItem(); characterItem.ItemId = itemId; characterItem.Owner = Owner.Data; characterItem.ItemCount = count; characterItem.TCharacterID = Owner.Data.ID; Owner.Data.Items.Add(characterItem); item = new Item(characterItem); Items.Add(itemId, item); } //DBService.Instance.Save(); return true; } public bool RemoveItem(int itemId,int count) { Item item = null; if (Items.TryGetValue(itemId, out item)) { if (item.Count > count) { item.Remove(count); //DBService.Instance.Save(); return true; } } return false; } public void GetItemInfos(List<NItemInfo> list) { //方便把内存数据转换到网络协议的数据。 foreach(var item in Items) { list.Add(new NItemInfo() {Id = item.Value.ItemID,Count = item.Value.Count}); } } }
测试阶段出现问题:未能更新数据库。
解决:重新生成了数据库解决。
客户端:
创建ItemManager管理道具类,是个单例类,使用Dictionary<int,item>的方式存储物品,初始化方法为开放Init()方法,并且传入参数来初始化。在UserService→OnGameEnter 角色进入游戏时执行并传入服务器发送过来的道具数据至Init()方法。
-
#ItemManager
public class ItemManager : Singleton<ItemManager> { public Dictionary<int, Item> Items = new Dictionary<int, Item>(); internal void Init(List<NItemInfo> items) { this.Items.Clear(); foreach (var item in items) { Item itemInfo = new Item(item); this.Items.Add(item.Id, itemInfo); } } public bool UseItem(int itemId) { return false; } public ItemDefine GetItem(int itemId) { return null; } public bool UseItem(ItemDefine items) { return false; } }