83. 2023-10-22周总结

  1. Google Play过审问题
  2. 服务器自动序列化和反序列化DB数据
  3. docker启动问题 mountpoint for devices not found
  4. 模板代码

1. Google Play过审问题

老项目在提审的时候老是提示使用的Unity Ad SDK版本过低,有隐私政策问题。但我们很确信已经把SDK都升级到了4指定版本以上了,最后发现原因是因为其他轨道(开放测试,封闭测试)中存在旧版本,即使已经设置这些轨道为不启用状态也不行。

解决方案就是把最新版本推到不用的这些轨道上,一起提审。

有人在Unity社区提问了,官方也给出这个解决方案:

2. 服务器自动序列化和反序列化DB数据

我们服务器在写逻辑的时候需要实现接口UnpackDb和PackDb来进行反序列化和序列化的过程。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public BsonValue PackDb()
{
BsonDocument doc = new BsonDocument()
{
{ "Gbid", Gbid },
{ "Level", Level },
{ "LeagueId", LeagueId },
{ "State", (int)State },
{ "IsRobot", IsRobot },
{ "SignUpCount", SignUpCount },
{ "UpgradeCount", UpgradeCount },
{ "WinMatchCount", WinMatchCount },
{ "CompleteMatchCount", CompleteMatchCount },
{ "CompleteLeagueCount", CompleteLeagueCount },
{ "UpgradeState", UpgradeState }
};
return doc;
}

public void UnpackDb(BsonValue data)
{
BsonDocument doc = data.AsBsonDocument;
Gbid = doc.Get<string>("Gbid");
Level = doc.Get<int>("Level");
State = (EState)doc.Get<int>("State");
LeagueId = doc.Get<int>("LeagueId");
IsRobot = doc.Get<bool>("IsRobot");
SignUpCount = doc.Get<int>("SignUpCount");
UpgradeCount = doc.Get<int>("UpgradeCount");
WinMatchCount = doc.Get<int>("WinMatchCount");
CompleteMatchCount = doc.Get<int>("CompleteMatchCount");
CompleteLeagueCount = doc.Get<int>("CompleteLeagueCount");
UpgradeState = doc.Get<int>("UpgradeState");
}

整个过程还是比较繁琐的,同时因为Bson的Key用字符串来做会增加整体的Document大小,另外也容易写错。所以考虑把这个过程简化,实现方式就是在要存档的属性上面增加Attribute,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/// <summary>
/// 技能Id
/// </summary>
[StorageableProperty(0)]
public int Id;

/// <summary>
/// 当前等级
/// </summary>
[StorageableProperty(1)]
public int Level;

/// <summary>
/// 技能点数
/// </summary>
[StorageableProperty(2)]
public int SkillPoint;

一个对象用BsonArry来存储,这三个变量会存档在这个BsonArry里面,0,1,2表示存储在BsonArry的位置,同时兼容不连续的情况,防止以后需求变更删除一些字段。

具体的实现方式后续博客在补充吧。

后续还想增加自动将变量同步到客户端操作,不用像现在一样,一个变量变动还得再加协议进行同步,流程还是比较麻烦。

3. docker启动问题 mountpoint for devices not found

在给服务器加新硬盘的时候可能不小心操作了umount了,导致docker在启动的时候报mountpoint for devices not found

最后调用https://github.com/tianon/cgroupfs-mount/blob/master/cgroupfs-mount这个脚本重新挂载之后问题修复

4. 模板代码

服务端在开发的时候最频繁的操作就是增加客户端协议,为了减少服务端出问题的概率,我们规范化这一块的写法,比如所有请求需要分这么几步:

  1. 检查这次请求的是否合法(比如id是否正确,所需的物品是否足够)
  2. 扣除这次请求所需要的资源(比如扣除物品,扣除技能点)
  3. 进行这次的行为(比如加经验,加等级)

这样能尽可能减少某些不当行为或者服务端报错带来刷物品的行为。

这个规范还是比较固化和繁琐的,为了让其他同事写的时候能按照这个规范,利用VS自带的代码块片段管理器实现了一个快速填充这一块代码的功能。

  • 首先参考官方给出的教程:https://learn.microsoft.com/zh-cn/visualstudio/ide/walkthrough-creating-a-code-snippet?view=vs-2022 自己写一个代码块的模板文件,例如我这边的写法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    <?xml version="1.0" encoding="utf-8"?>
    <CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
    <CodeSnippet Format="1.0.0">
    <Header>
    <Title>BabuRequest</Title>
    <Shortcut>BabuRequest</Shortcut>
    </Header>
    <Snippet>
    <Code Language="CSharp">
    <![CDATA[
    #region $RequestName$

    int Check$RequestName$($RequestName$Request request)
    {
    return 0;
    }

    int Cost$RequestName$Resource($RequestName$Request request)
    {
    return 0;
    }

    void Do$RequestName$($RequestName$Request request)
    {

    }

    [ModuleMethod(ProtoId.$RequestName$Request)]
    public $RequestName$Response $RequestName$($RequestName$Request request)
    {
    var response = new $RequestName$Response();
    if ((response.Code = Check$RequestName$(request)) != 0)
    {
    return response;
    }

    if ((response.Code = Cost$RequestName$Resource(request)) != 0)
    {
    return response;
    }

    Do$RequestName$(request);
    return response;
    }

    #endregion
    ]]>
    </Code>
    <Declarations>
    <Literal>
    <ID>RequestName</ID>
    <ToolTip>协议名字(不带Request)</ToolTip>
    <Default>Test</Default>
    </Literal>
    </Declarations>
    <Imports>
    <Import>
    <Namespace>Protocol</Namespace>
    </Import>
    </Imports>
    </Snippet>
    </CodeSnippet>
    </CodeSnippets>

  • 将文件保存为*.snippet(例如BabuRequest.snippet)

  • VS中,打开工具-代码片段管理器-导入,添加到VS中

  • 在代码中输入BabuRequest,然后Tab,然后输入自己的请求名字(例如UpgradeSkill),回车即可把这一块的模板代码给生成

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    #region UpgradeSkill

    int CheckUpgradeSkill(UpgradeSkillRequest request)
    {
    return 0;
    }

    int CostUpgradeSkillResource(UpgradeSkillRequest request)
    {
    return 0;
    }

    void DoUpgradeSkill(UpgradeSkillRequest request)
    {

    }

    [ModuleMethod(ProtoId.UpgradeSkillRequest)]
    public UpgradeSkillResponse UpgradeSkill(UpgradeSkillRequest request)
    {
    var response = new UpgradeSkillResponse();
    if ((response.Code = CheckUpgradeSkill(request)) != 0)
    {
    return response;
    }

    if ((response.Code = CostUpgradeSkillResource(request)) != 0)
    {
    return response;
    }

    DoUpgradeSkill(request);
    return response;
    }

    #endregion

可以看到模板代码分四块,最下面是请求入口,整个之前说的三步流程(检查,扣除,操作),检查和扣除有问题直接返回。

有了这个模板之后,可以简化写代码的同时也规范了这一块的标准,还是挺好的。