[url]http://uh.9ria.com/space-12147-do-blog-id-5251.html[/url]
假请求对于玩家交互,非常不友好。
拿偷菜的例子就够能说明问题了。下面说的则是在假请求的基础上,一些对于玩家交互的修正处理。
你对玩家的东西做了操作,改变了它们的状态,直接改玩家的数据是可以的吗?
举个极端的例子。比如你可以偷玩家的钱,原来人家100快,你给偷到只剩50了。如果那个玩家不在线还好,他上来看到自己只有50,看看日志知道你是干的,那事情就算没事了。但如果当时玩家还在线,他自己是不知道有这回事的,看到自己还有100快,而因为买东西也是假操作,他仍然可以买100块的东西,然后保存的时候服务器因为钱不够就让他回档。
这样很不好。
偷钱这种简单的也许可以接受,但遇到一些复杂的情况,玩家可能完全不明白怎么回事。而且回档这种事情应该是在出错的时候才有,玩家交互的结果并不是错误……
这个的解决方案则是,玩家的操作都不直接修改数据,而是相当于“发一封信”,然后玩家收到这封信之后才产生效果。这样玩家收到信之前买了100块的东西,系统还是给予认可的,然后保存的时候收到了信,打开减了50,钱就变成-50。
这样结果虽然有少许不同,但他是可以理解的。
并不一定是“发一封信”,这个的要点在于好友对自己的操作需要玩家自己确认后才生效,确认前效果都当做不存在,而目的就是为了避免回档。
这个同样可用户BUFF之上,因为BUFF影响众多,甚至连用真请求都不能解决。但只要这样推迟效果产生的时间,逻辑上就仍然可以保持正确性。
下面这个则是关于物品ID,确切的说,是礼品的处理办法。
如果你的游戏里物品都是堆叠的,或者说保存物品用的是类型的ID,则不存在这个问题。礼品过来只是在物品数量上+1而已。但是如果是游戏中的物品,包含存在时间,坐标等属性的话,那么为了区别同类型不同的物品,就需要一个专门的ID。
一般这个都是递增ID,平常的做法都是由服务器生成这个ID,自然没有问题。但如果是假请求的话,新增的物品暂时不会去服务器下行数据,所以这个ID只能客户端生成。
如果没有好友,礼品一类影响的话也是没有问题的,因为反正都是递增,新增的物品ID全都由客户端生成,服务端保存一下就好。但如果有好友送礼的情况……
我在线,客户端生成了一个物品,而正好这时候好友送了一个物品给我,如果两边都是简单的递增的话,ID就会重复。然后必然就是报错回档。
解决方案也很多,经典的做法就是做一个礼品盒(不一定是实体),玩家需要自己把礼品盒的东西拖出来,然后生成新ID,这不会产生问题。
还有变相的礼品盒方案,就是让服务端生成的ID从-1开始向负的方法递增,这样也不会重复。
我现在说的是一个比较彻底的方案,能应付所有情况,就是所谓的双ID。
物品都有两个ID,一个id,一个sid。前者是客户端使用的,后者则是服务端使用的。需要特别提出的是,区分不用物品用的是sid,服务端保存的也是sid,id它是不存的。而且客户端id是随便生成的(只要不重复),每次登陆游戏都可能错位(因为没保存)。
可以简单把客户端id理解成临时id。临时id存在的目的是在假请求没有发送,客户端还没有从服务端获得真正的id(sid)前的暂定物。因为一个物品存在就必须有id,客户端也需要它,但真正的sid应当是服务器生成的,为了在得到生成物之前客户端也要操作,这个临时id的目的就在这也仅仅在这。
临时ID的意义仅在假请求未发送前的短暂时间内,一旦发送,服务端就会生成所有物品的sid并返回,然后根据这些临时ID作为指引,分配到各个物品对象上。至此临死ID就失去了存在意义。但即使是这样,客户端运算还是得用临时ID,因为客户端不在乎数据保存的顺序,只在乎分清谁是谁。新创建的物品只有id没有sid,靠sid是分不清的,而id一定存在而且不同。所以它还是客户端需要主要关心的id。
总而言之,双id的要点就是,服务端看sid,客户端看id,保存时两边进行同步,同时关心两者只在保存时。
假请求对于玩家交互,非常不友好。
拿偷菜的例子就够能说明问题了。下面说的则是在假请求的基础上,一些对于玩家交互的修正处理。
你对玩家的东西做了操作,改变了它们的状态,直接改玩家的数据是可以的吗?
举个极端的例子。比如你可以偷玩家的钱,原来人家100快,你给偷到只剩50了。如果那个玩家不在线还好,他上来看到自己只有50,看看日志知道你是干的,那事情就算没事了。但如果当时玩家还在线,他自己是不知道有这回事的,看到自己还有100快,而因为买东西也是假操作,他仍然可以买100块的东西,然后保存的时候服务器因为钱不够就让他回档。
这样很不好。
偷钱这种简单的也许可以接受,但遇到一些复杂的情况,玩家可能完全不明白怎么回事。而且回档这种事情应该是在出错的时候才有,玩家交互的结果并不是错误……
这个的解决方案则是,玩家的操作都不直接修改数据,而是相当于“发一封信”,然后玩家收到这封信之后才产生效果。这样玩家收到信之前买了100块的东西,系统还是给予认可的,然后保存的时候收到了信,打开减了50,钱就变成-50。
这样结果虽然有少许不同,但他是可以理解的。
并不一定是“发一封信”,这个的要点在于好友对自己的操作需要玩家自己确认后才生效,确认前效果都当做不存在,而目的就是为了避免回档。
这个同样可用户BUFF之上,因为BUFF影响众多,甚至连用真请求都不能解决。但只要这样推迟效果产生的时间,逻辑上就仍然可以保持正确性。
下面这个则是关于物品ID,确切的说,是礼品的处理办法。
如果你的游戏里物品都是堆叠的,或者说保存物品用的是类型的ID,则不存在这个问题。礼品过来只是在物品数量上+1而已。但是如果是游戏中的物品,包含存在时间,坐标等属性的话,那么为了区别同类型不同的物品,就需要一个专门的ID。
一般这个都是递增ID,平常的做法都是由服务器生成这个ID,自然没有问题。但如果是假请求的话,新增的物品暂时不会去服务器下行数据,所以这个ID只能客户端生成。
如果没有好友,礼品一类影响的话也是没有问题的,因为反正都是递增,新增的物品ID全都由客户端生成,服务端保存一下就好。但如果有好友送礼的情况……
我在线,客户端生成了一个物品,而正好这时候好友送了一个物品给我,如果两边都是简单的递增的话,ID就会重复。然后必然就是报错回档。
解决方案也很多,经典的做法就是做一个礼品盒(不一定是实体),玩家需要自己把礼品盒的东西拖出来,然后生成新ID,这不会产生问题。
还有变相的礼品盒方案,就是让服务端生成的ID从-1开始向负的方法递增,这样也不会重复。
我现在说的是一个比较彻底的方案,能应付所有情况,就是所谓的双ID。
物品都有两个ID,一个id,一个sid。前者是客户端使用的,后者则是服务端使用的。需要特别提出的是,区分不用物品用的是sid,服务端保存的也是sid,id它是不存的。而且客户端id是随便生成的(只要不重复),每次登陆游戏都可能错位(因为没保存)。
可以简单把客户端id理解成临时id。临时id存在的目的是在假请求没有发送,客户端还没有从服务端获得真正的id(sid)前的暂定物。因为一个物品存在就必须有id,客户端也需要它,但真正的sid应当是服务器生成的,为了在得到生成物之前客户端也要操作,这个临时id的目的就在这也仅仅在这。
临时ID的意义仅在假请求未发送前的短暂时间内,一旦发送,服务端就会生成所有物品的sid并返回,然后根据这些临时ID作为指引,分配到各个物品对象上。至此临死ID就失去了存在意义。但即使是这样,客户端运算还是得用临时ID,因为客户端不在乎数据保存的顺序,只在乎分清谁是谁。新创建的物品只有id没有sid,靠sid是分不清的,而id一定存在而且不同。所以它还是客户端需要主要关心的id。
总而言之,双id的要点就是,服务端看sid,客户端看id,保存时两边进行同步,同时关心两者只在保存时。