⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 srv_description(utf-8).txt

📁 3号作品是分析WarCraft III游戏的replay文件的命令行工具
💻 TXT
字号:
Simple Replay Viewer 解释文档

一 序言
整个工程分为6个文件,分别为
SRV.h
crc32.h
crc32.c
main.c
console.c
dataprocess.c
其中crc32.h和crc32.c并非由我编写,因此没有具体的解释。
W3G文件的具体解释参考w3g_format.txt和w3g_actions.txt。

二 头文件 - SRV.h
头文件中为了方便使用定义了3种整数类型:DWORD,WORD和BYTE,声明了输入文件in,最后定义了几种结构,分别为
replay_sub_header_0,版本为0的SubHeader,于w3g_format.txt(下同)2.1
replay_sub_header_1,版本为1的SubHeader,于2.2
replay_header,于2.0
replay_block_header,于3.0
以上结构都指定了使用最小的存储空间以方便数据的直接读入(语法详见Using the GNU Compiler Collection (GCC) 5.33)
最后定义了结构slot_s以方便输入和输出slot信息。

三 main.c
main.c中定义了全局变量in,并对命令行参数进行处理。

四 控制台界面 - console.c
控制台界面的主函数是void console(char *),它的主要内容是对main()传来的命令行参数中的文件名进行处理,接下来进入循环处理控制台的命令,并将不同的命令连接到不同的函数上去。它使用数个子函数,分别为char *strtolower(char *),int  parse(char *, char **),int  searchchar(char, char*)和int  time2ms(char *, DWORD *)。其功能分别为将字符串中所有大写字母转为小写,对控制台命令以空格为分隔符进行分段,在字符串中搜索某个特定字符,以及将一般的时间表示法(如3:45表示3分45秒)转换为毫秒数。

五 数据处理 - dataprocess.c
1. 概论
数据处理主要分为读取数据的函数int readdata(),输出基本信息的函数void info(),输出玩家信息的函数void player()以及输出APM信息的void apm(DWORD, DWORD)。另外还有一个释放内存的函数void freemem()。
int readdata()函数分为4个部分,读取头部,读取数据块,调用zlib库解压以及读取slot信息和设置索引。如果前三个部分都没有出现错误,程序就判定这是一个合法的replay文件,所以之后都没有错误处理。返回值并不连续是为了配合zlib解压函数的返回值。
void info()函数分别列出游戏的版本、游戏名、地图名与游戏创建者名以及游戏类型。其中需要对字符串进行解码,我采用了比w3g_format.txt中举例的方法简单一点的方法。
void player()函数并无特别之处。

2. apm的结构 
void apm(DWORD, DWORD)函数的两个参数为统计的起始时间和终止时间。这个函数分为两部分,一是数据的统计,二是数据的输出。鉴于数据实际的存储模式(见5.0及w3g_actions.txt),这个函数的大体结构用伪代码表示如下:

while 数据未读完且时间未到结束时间
begin
  读取数据块第一字节并判断类型
  begin
    如果玩家离开游戏
      停止记录此玩家的时间
    如果是时间槽
      按动作类型判断是否计入APM
      按当前游戏状态(是否暂停)判断是否计入时间
    其他
      跳过
  end // 判断类型
end // while

3. 特别的动作判定
在按动作类型判断是否计入APM时,其中两种动作(0x16与0x19)的判定方法较复杂,参考w3g_actions.txt,解释如下:
这两种动作块分别可储存两种动作类型(Deselect与Select,UpdateSubgroup与SelectSubgroup),根据w3g_actions.txt中对APM的规定,如果前一种动作之后立刻出现了第二种动作,后一个动作不计入APM。设定flag记录状态(分别为DeselectFlag和UpdateSubgroupFlag),当出现前一种动作时,flag标记为2。每个动作判定完之后,flag自减1。当出现后一种动作时,判断flag的值,如果flag为0就记入APM,否则不计入。下面进行实例分析。首先,在同一个时间槽的同一个用户的动作中出现了连续的两种动作,出现第一种动作,令flag=2,之后flag=1;接下来出现第二种动作,由于flag=1,不计入APM,之后flag=0。flag=0时对后续操作没有影响。其次,在同一个时间槽的同一个用户的动作中出现了两种动作,但之间隔了另一种动作,则出现第一种动作时令flag=2,之后flag=1;接下来是不相关的动作,之后flag=0;最后是第二种动作,由于flag=0,所以记入APM。另外,在进入不同玩家的动作记录时将flag重置为0。

4. 记录时间
在记录时间的时候,定义了数组time_ms[13],其中time_ms[0]用来记录游戏时间,time_ms[i]用来记录第i个槽中的用户的时间。另外我使用了2字节(16位)的无符号数exitmark来记录玩家是否退出游戏,第n位代表第n-1个槽的玩家的状态,0表示在游戏中,1表示已退出。由于暂停游戏的存在,我使用了timeaddflag来标记是否记录时间。首先,当出现了暂停游戏或恢复游戏动作的时候,timeaddflag=1,playing分别记为0和1。其次,如果没有出现暂停游戏和恢复游戏的动作,timeaddflag=playing。再根据timeaddflag,实际游戏时间是否在记录起始时间之后,和exitmark的状况,来判定是否记用户时间。

六 编译环境
本程序在gcc-3.4.5-3,mingw-runtime-3.14下编译通过,支持zlib 1.2.3或兼容版本。

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -