我在我目前正在使用的游戏引擎中遇到以下方法:

bool addmsg(int type, const char *fmt, ...) {
    if (!connected) return false;
    static uchar buf[MAXTRANS];
    ucharbuf p(buf, sizeof (buf));
    putint(p, type);
    int numi = 1, numf = 0, nums = 0, mcn = -1;
    bool reliable = false;
    if (fmt)
    {
        va_list args;
        va_start(args, fmt);
        while (*fmt) switch (*fmt++)
            {
            case 'r': reliable = true; break;
            case 'c':
                {
                    gameent *d = va_arg(args, gameent *);
                    mcn = !d || d == player1 ? -1 : d->clientnum;
                    break;
                }
            case 'v':
                {
                    int n = va_arg(args, int);
                    int *v = va_arg(args, int *);
                    loopi(n) putint(p, v[i]);
                    numi += n;
                    break;
                }

            case 'i':
                {
                    int n = isdigit(*fmt) ? *fmt++ - '0' : 1;
                    loopi(n) putint(p, va_arg(args, int));
                    numi += n;
                    break;
                }
            case 'f':
                {
                    int n = isdigit(*fmt) ? *fmt++ - '0' : 1;
                    loopi(n) putfloat(p, (float)va_arg(args, double));
                    numf += n;
                    break;
                }
            case 's': sendstring(va_arg(args, const char *), p); nums++; break;
            }
        va_end(args);
    }
    int num = nums || numf ? 0 : numi, msgsize = server::msgsizelookup(type);
    if (msgsize && num != msgsize) { fatal("inconsistent msg size for %d (%d != %d)", type, num, msgsize); }
    if (reliable) messagereliable = true;
    if (mcn != messagecn)
    {
        static uchar mbuf[16];
        ucharbuf m(mbuf, sizeof (mbuf));
        putint(m, N_FROMAI);
        putint(m, mcn);
        messages.put(mbuf, m.length());
        messagecn = mcn;
    }
    messages.put(buf, p.length());

    return true;
}

真可怕人们实际上认为通过这样的网络发送消息是一个好主意:
addmsg(MY_ACTION, "rii3ii5", 1, 42, 42, 42, e.type, e.attr1, e.attr2, e.attr3, e.attr4, e.attr5)

哦,是的! super 可读。现在,我试图保持积极态度,并慢慢地重构它。我正在考虑使用模板来动态解释消息中的类型并正确编码。有人对如何开始这种废话有建议吗?谢谢!

最佳答案

您可以只使用函数重载。确实不需要模板。

#include <string>

constexpr size_t MAXTRANS = 128;

enum reliable_t { reliable };

class message
{
public:
    void send() { }

    message& operator<<(reliable_t)
    {
        m_reliable = true;
        return *this;
    }

    message& operator<<(int x)
    {
        // add int to message
        return *this;
    }

    message& operator<<(float x)
    {
        // add float to message
        return *this;
    }

    message& operator<<(const std::string& x)
    {
        // add string to message
        return *this;
    }

private:
    unsigned char m_buf[MAXTRANS];
    bool m_reliable = false;
};

int main()
{
    message msg;
    msg << reliable << 42 << 42 << "ultimate question";
    msg.send();
    return 0;
}

这是coliru示例的链接。

关于c++ - 打包用于UDP网络的消息,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37727205/

10-17 00:30