6

我正在开发一个从 Quake 2 松散地继承下来的游戏引擎,添加了一些诸如脚本效果之类的东西(允许服务器向客户端详细指定特殊效果,而不是只有客户端能够使用的有限数量的硬编码效果的。)这是网络效率与灵活性的权衡。

我遇到了一个有趣的障碍。看,最大数据包大小是 2800 字节,每个客户端每帧只能发出一个。

这是做“火花”效果的脚本(可能对子弹撞击火花、电击等有好处) http://pastebin.com/m7acdf519(如果您不理解,请不要出汗;这是我制作的自定义语法,与我提出的问题无关。)

我已尽一切可能缩小该脚本的大小。我什至将变量名简化为单个字母。但结果正好是 405 个字节。这意味着每帧最多可以容纳 6 个。我还想到了一些服务器端更改,可能会再减少 12 个,而协议更改可能会再节省 6 个。虽然节省会因您使用的脚本而异。

然而,在这 387 个字节中,我估计只有 41 个字节在效果的多次使用中是唯一的。换句话说,这是压缩的主要候选对象。

恰好 R1Q2(具有扩展网络协议的向后兼容 Quake 2 引擎)具有 Zlib 压缩代码。我可以解除此代码,或者至少密切关注它作为参考。

但是 Zlib 一定是这里的最佳选择吗?我能想到至少一种替代方案,LZMA,而且很容易有更多。

要求:

  1. 必须非常快(如果每秒运行超过 100 次,性能损失必须非常小。)
  2. 必须将尽可能多的数据塞进 2800 字节
  3. 元数据占用空间小
  4. GPL 兼容

Zlib 看起来不错,但还有什么更好的吗?请记住,这些代码还没有被合并,所以有足够的实验空间。

谢谢,-马克斯

编辑:感谢那些建议将脚本编译成字节码的人。我应该说清楚——是的,我正在这样做。如果你喜欢你可以在我的网站上浏览相关的源代码,虽然它仍然没有“修饰”。
这是服务器端代码:
Lua 组件:http
://meliaserlow.dyndns.tv:8000/alienarena/lua_source/lua/scriptedfx.lua C 组件: http://meliaserlow.dyndns.tv:8000/alienarena/ lua_source /game/g_scriptedfx.c
对于我发布的特定示例脚本,这将 1172 字节的源代码缩小到 405 字节——仍然不够小。(请记住,我想将尽可能多的这些内容放入 2800 字节中!)

EDIT2:不能保证任何给定的数据包都会到达。每个数据包都应该包含“世界状态”,而不依赖于先前数据包中传达的信息。通常,这些脚本将用于传达“眼睛糖果”。如果没有空间,它就会从数据包中丢弃,这没什么大不了的。但是,如果掉了太多,事情开始在视觉上看起来很奇怪,这是不可取的。

4

6 回答 6

4

LZO可能是一个很好的候选人。

于 2010-02-17T10:05:11.507 回答
2

最后更新:这两个库似乎差不多。Zlib 提供了大约 20% 的更好压缩,而 LZO 的解码速度大约快了两倍,但对两者的性能影响非常小,几乎可以忽略不计。这就是我的最终答案。感谢所有其他答案和评论!

更新:在实施 LZO 压缩并且只看到明显更好的性能之后,很明显我自己的代码要为性能下降负责(每个数据包可能大量增加脚本效果的数量,因此我的效果“解释器”得到了更多的锻炼.) 对于争先恐后的推卸责任,我要谦虚地道歉,希望没有难过的感觉。我会做一些分析,然后也许我能得到一些对其他人更有用的数字。

原帖:

好的,我终于有时间为此编写一些代码。我从 Zlib 开始,这是我的第一个发现。

Zlib 的压缩非常棒。即使使用 Z_BEST_SPEED(而不是 Z_DEFAULT_COMPRESSION)压缩时,它也能可靠地将 8.5 kib 的数据包减少到 750 字节或更少。压缩时间也相当不错。

然而,我不知道任何东西的减压速度甚至可能如此糟糕。我没有实际数字,但每个数据包至少需要 1/8 秒!(Core2Duo T550 @ 1.83 Ghz。)完全不可接受。

据我所知,与 Zlib 相比,LZMA 是性能更差与压缩更好的权衡。由于 Zlib 的压缩已经过大了,而且它的性能已经非常糟糕,所以 LZMA 暂时无法看到。

如果 LZO 的减压时间和它声称的一样好,那么这就是我将使用的。我认为最终服务器仍然能够在极端情况下发送 Zlib 数据包,但客户端可以配置为忽略它们,这将是默认设置。

于 2010-02-22T05:19:53.163 回答
1

zlib可能是一个很好的候选者——许可证非常好,运行速度很快,而且它的作者说它的开销很小,而且开销是使用少量数据有问题的东西。

于 2010-02-17T10:11:23.057 回答
1

你应该看看OpenTNL并调整他们在那里使用的一些技术,比如网络字符串的概念

于 2010-02-17T17:49:57.140 回答
0

我倾向于使用当前浪费的每个字符的最高有效位,通过向左移动 9 个字节的组,您将适合 8 个字节。

您可以走得更远,将字符映射到一个小空间 - 您可以通过例如不允许大写字母并从每个字符中减去 0x20 将它们降低到 6 位(即只有 64 个有效字符)(这样空间就变成了价值0)

您可以通过映射每个字符的频率走得更远,并进行 Huffman 类型压缩以减少每个字符的平均位数。

我怀疑没有任何算法可以更好地保存数据,在一般情况下,因为在您已经做出更改之后,消息中基本上没有冗余。

于 2010-02-17T10:19:47.517 回答
0

如何发送脚本的二进制表示?

所以我正在考虑抽象语法树的行,每个过程都有一个标识符。

这意味着由于一次性解析而在客户端上获得了性能增益,并且由于删除了方法名称而减小了大小。

于 2010-02-17T10:26:07.903 回答