游戏好友系统
最近实现了游戏好友系统。第一次按照自己的方法实现,觉得代码有些冗余,估计是思路问题。特在此记录,一是为了以后维护,二是向和我一样没有啥经验的程序员提供一个思路,更希望大家不吝赐教提供更好的设计思路。
需求:
- 添加好友
a)根据当前玩家等级获取10个正负20级其他玩家列表
b) 获取的其他玩家最近一次登录时间不得大于1天
c)当其他玩家列表内玩家数量<10,则放松筛选条件
d)获取其他玩家列表,推送至玩家添加好友UI
e)玩家点击申请向申请玩家发送添加好友请求
f) 玩家可以对列表内其他玩家1键全部申请添加
g)被申请玩家同意后该好友添加成功,若对方拒绝不返回信息
h)每个玩家应有1个ID
i)A玩家知道B玩家ID,A玩家可通过ID直接向B玩家发送添加好友请求
- 申请列表
a)当其他玩家申请与当前玩家成为好友时,该玩家信息出现至申请列表
b)同意与该玩家成为好友,则该玩家移至当前玩家好友列表且申请列表内清除该玩家信息
c)拒绝与该玩家成为好友,则申请列表内清除该玩家信息
d)玩家可以对申请列表内玩家1键全部同意添加
e)玩家可以对申请列表内玩家1键全部拒绝添加
- 好友列表
a)与当前玩家已成为好友的其他玩家刷新在此列表
b) 好友之间可以送心
c)玩家A向玩家B送心则玩家B可在好友列表内领取玩家A送的心
d)当前玩家可以向其拥有的所有好友1键送心
e)当前玩家可以1键收取其好友送的心
f)每日可领取的心数量有上限
我的设计思路:
我是按照"请求-回答"的形式设计,将用户的操作分为请求和对请求的回答。
请求:添加好友 回答:接受 , 拒绝
请求:好友送心 回答 :领取 , 不领取(过时心自动消失)
每种请求被设计成一个消息,例如:A 在 某时 向 B 发送了一条 申请好友 的请求,这时,当服务器收到这个协议后,封装一封消息,并插入到数据库,数据库字段如下:
表项: id , fromid , toid , msgtype , isread , srecvtime. ( msgtype:我将每个操作分类,如1就是申请好友 , isread:表示申请的对象是否对此作出了回应,无论是同意或是拒绝都会对此作出回应,即将isread 置为1,
srecvtime:服务器收到的时间 )
例如: id 为 1 的用户向 2发送了申请好友请求 , 则会记录 1 , 1 , 2 , 1 (申请) , 0(还未被确认) , 1446454554(收到消息的时间)
但要说明的是,若此时B在线则这条消息将由B插入数据库,表示B收到了一条来自A的申请好友的消息,并在自己的 被申请列表 中将A的ID加入 ,若B不在线,则该记录由A插入,表示A向B申请好友,并在自己的 已申请好友列表中将B的ID加入。 当B看到这条消息时,B会对此进行回复 , 接受或者拒绝 , 这两个操作都是对A发出的申请的回复 , 此时若 A 还在线 , 则B会在服务器内部向A发送消息,“我同意或拒绝你的请 求” , 则A会将之前自己的申请记录中的isread 标记为1,表示这条申请已经作废。同时,若是收到同意的消息 , 则A会在数据库中插入记录表明A和B已经是好友; 若此时A不在线了 , 则对A的申请记录作出回应的操 作由B完成,即B将isread置为1,表示B拒绝A的好友请求。 此时u_friendmsg(用于记录消息的表)中有一条记录: 1 , 1 , 2 , 1 (申请) , 1(被确认) , 1446454554(收到消息的时间) ,此时由于isread = 1 表示这条消息已经被确认。若B同意A的请求则u_friend中会有记录,表明两者一是好友关系。那么B是如何判断要对哪条记录作出回应的呢,这里可以根据id字段,和srecvtime字段。
这种方式下,当我需要好友列表的时候,直接搜索u_friend 中 friendid( id , uid , friendid , ... ) 字段便可,当需要申请列表时,搜索u_friendmsg中"toid"为当前用户id并且"isread"字段为0(未处理)的记录即可。
由于目前在使用 "skynet"(当前阶段,仅限使用,惭愧) , 简单说一下申请好友,拒绝或同意的过程:
1.A 在线 , 在搜索好友或在推荐列表中申请某个玩家B后,这是A在服务端的数据变化为 A维护的一个已申请好友列表(申请其他人)中添加上B的ID,并创建一条消息,内容如上所述。
2.此时B有在线和不在线两种可能。若B在线,则将这条消息发送到B处理,这是B将这条消息插入数据库,并B自己的“被申请”列表中加上A的ID。若B不在线则有A向数据库插入这条消息。当B在上线后搜索u_friendmsg中toid为自己的并且isread = 0的记录,便可得到自己的申请列表(被申请)
3.B对这条申请有两个选择,拒绝或接受。若A请求时B在线且拒绝了A的请求,此时B向A发送一条消息,告诉A我拒绝你的申请,则A若此时仍在线的话,便会将之前的申请列表中移除B的ID,并且对自己之前的请求操作进行确认,即把 isread 改为1。若A不在线,则由B来完成确认操作,并将A的 ID,从自己的被申请列表中移除;若B接受了好友请求 , B首先在自己的好友列表中加入A的ID,此时若A在线的话,便将消息发给A告诉A我接受你的申请,此时A若在线,便对之前的消息进行确认,并在自己的好友列表中加入B的ID,并向u_friend中插入记录两条记录( 1 , 1 , 2 ...) , ( 2 , 2 , 1 )表示已经是好友 ,若A此时不在线,插入好友和确认的操作由B进行。剩下送心和接受心的操作过程大体类似
skynet中判断是否在线的方法很多,我们是在用户登录的时候,在datacenter中注册此用户,在离线的时候删除,这样通过调用 dc.set{ userid = 1 ,...} , dc.get( 1 )操作来判断用户此时是否在线并获取其数据。
由于操作不一定实时,因此很可能出现A申请好友,B在几天后才看到,所以服务器发送给客户端的数据中有个专门的时间字段(srecvtime)来标示记录,也就是,这个字段由服务器下发,当B接受申请的时候,向服务器发送数据时要把这个时间标识再传回来,我不清楚这样做是否合适。请高手指教。
思路是这样,代码感觉还需优化,过几天再贴,希望能对像我这样的新手带来帮助。待续。。。。