Subversion Repositories Games.Descent

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 1
/*
2
 * This file is part of the DXX-Rebirth project <https://www.dxx-rebirth.com/>.
3
 * It is copyright by its individual contributors, as recorded in the
4
 * project's Git history.  See COPYING.txt at the top level for license
5
 * terms and a link to the Git history.
6
 */
7
#pragma once
8
 
9
#include <type_traits>
10
#include "dxxerror.h"
11
#include "object.h"
12
#include "powerup.h"
13
#include "serial.h"
14
#include "fwd-player.h"
15
 
16
#define _UNPACK_MULTIPLAYER_SERIAL_MESSAGE(A,...)       A, ## __VA_ARGS__
17
#define DEFINE_MULTIPLAYER_SERIAL_MESSAGE(C,T,V,A)      \
18
        DEFINE_SERIAL_UDT_TO_MESSAGE(T,V, (multiplayer_command<C>(), _UNPACK_MULTIPLAYER_SERIAL_MESSAGE A));    \
19
        ASSERT_SERIAL_UDT_MESSAGE_SIZE(T, command_length<C>::value)
20
 
21
#define define_multiplayer_command(NAME,SIZE)   NAME,
22
 
23
#if defined(DXX_BUILD_DESCENT_I) || defined(DXX_BUILD_DESCENT_II)
24
#define for_each_multiplayer_command(VALUE)     \
25
        VALUE(MULTI_POSITION              , 1 + quaternionpos::packed_size::value)      \
26
        VALUE(MULTI_REAPPEAR              , 4)  \
27
        VALUE(MULTI_FIRE                  , 18) \
28
        VALUE(MULTI_FIRE_TRACK            , 21) \
29
        VALUE(MULTI_FIRE_BOMB             , 20) \
30
        VALUE(MULTI_REMOVE_OBJECT         , 4)  \
31
        VALUE(MULTI_MESSAGE               , 37) /* (MAX_MESSAGE_LENGTH = 40) */ \
32
        VALUE(MULTI_QUIT                  , 2)  \
33
        VALUE(MULTI_PLAY_SOUND           , 8)   \
34
        VALUE(MULTI_CONTROLCEN           , 4)   \
35
        VALUE(MULTI_ROBOT_CLAIM          , 5)   \
36
        VALUE(MULTI_CLOAK                , 2)   \
37
        VALUE(MULTI_ENDLEVEL_START       , DXX_MP_SIZE_ENDLEVEL_START)  \
38
        VALUE(MULTI_CREATE_EXPLOSION     , 2)   \
39
        VALUE(MULTI_CONTROLCEN_FIRE      , 16)  \
40
        VALUE(MULTI_CREATE_POWERUP       , 19)  \
41
        VALUE(MULTI_DECLOAK              , 2)   \
42
        VALUE(MULTI_ROBOT_POSITION       , 5 + quaternionpos::packed_size::value)       \
43
        VALUE(MULTI_PLAYER_DERES         , DXX_MP_SIZE_PLAYER_RELATED)  \
44
        VALUE(MULTI_DOOR_OPEN            , DXX_MP_SIZE_DOOR_OPEN)       \
45
        VALUE(MULTI_ROBOT_EXPLODE        , 7)   \
46
        VALUE(MULTI_ROBOT_RELEASE        , 5)   \
47
        VALUE(MULTI_ROBOT_FIRE           , 18)  \
48
        VALUE(MULTI_SCORE                , 6)   \
49
        VALUE(MULTI_CREATE_ROBOT         , 6)   \
50
        VALUE(MULTI_TRIGGER              , 3)   \
51
        VALUE(MULTI_BOSS_TELEPORT        , 5)   \
52
        VALUE(MULTI_BOSS_CLOAK           , 3)   \
53
        VALUE(MULTI_BOSS_START_GATE      , 3)   \
54
        VALUE(MULTI_BOSS_STOP_GATE       , 3)   \
55
        VALUE(MULTI_BOSS_CREATE_ROBOT    , 8)   \
56
        VALUE(MULTI_CREATE_ROBOT_POWERUPS, 27)  \
57
        VALUE(MULTI_HOSTAGE_DOOR         , 7)   \
58
        VALUE(MULTI_SAVE_GAME            , 2+24)        /* (ubyte slot, uint id, char name[20]) */      \
59
        VALUE(MULTI_RESTORE_GAME         , 2+4) /* (ubyte slot, uint id) */     \
60
        VALUE(MULTI_HEARTBEAT            , 5)   \
61
        VALUE(MULTI_KILLGOALS            , 1 + MAX_PLAYERS)     \
62
        VALUE(MULTI_DO_BOUNTY            , 2)   \
63
        VALUE(MULTI_TYPING_STATE         , 3)   \
64
        VALUE(MULTI_GMODE_UPDATE         , 3)   \
65
        VALUE(MULTI_KILL_HOST            , 7)   \
66
        VALUE(MULTI_KILL_CLIENT          , 5)   \
67
        VALUE(MULTI_RANK                 , 3)   \
68
        VALUE(MULTI_DROP_WEAPON          , 10)  \
69
        VALUE(MULTI_PLAYER_INV           , DXX_MP_SIZE_PLAYER_INVENTORY)        \
70
        D2X_MP_COMMANDS(VALUE)  \
71
 
72
#if defined(DXX_BUILD_DESCENT_I)
73
#define DXX_MP_SIZE_ENDLEVEL_START      3
74
#define DXX_MP_SIZE_PLAYER_RELATED      58
75
#define DXX_MP_SIZE_PLAYER_INVENTORY    15
76
#define DXX_MP_SIZE_BEGIN_SYNC  37
77
#define DXX_MP_SIZE_DOOR_OPEN   4
78
#define D2X_MP_COMMANDS(VALUE)
79
#elif defined(DXX_BUILD_DESCENT_II)
80
#define DXX_MP_SIZE_ENDLEVEL_START      2
81
#define DXX_MP_SIZE_PLAYER_RELATED      (97+10)
82
#define DXX_MP_SIZE_PLAYER_INVENTORY    21
83
#define DXX_MP_SIZE_BEGIN_SYNC  41
84
#define DXX_MP_SIZE_DOOR_OPEN   5
85
#define D2X_MP_COMMANDS(VALUE)  \
86
        VALUE(MULTI_MARKER               , 55)  \
87
        VALUE(MULTI_GUIDED               , 26)  \
88
        VALUE(MULTI_STOLEN_ITEMS         , 1 + std::tuple_size<decltype(d_thief_unique_state::Stolen_items)>::value)    \
89
        VALUE(MULTI_WALL_STATUS          , 6)   /* send to new players */       \
90
        VALUE(MULTI_SEISMIC              , 5)   \
91
        VALUE(MULTI_LIGHT                , 16)  \
92
        VALUE(MULTI_START_TRIGGER        , 2)   \
93
        VALUE(MULTI_FLAGS                , 6)   \
94
        VALUE(MULTI_DROP_BLOB            , 2)   \
95
        VALUE(MULTI_SOUND_FUNCTION       , 4)   \
96
        VALUE(MULTI_CAPTURE_BONUS        , 2)   \
97
        VALUE(MULTI_GOT_FLAG             , 2)   \
98
        VALUE(MULTI_DROP_FLAG            , 8)   \
99
        VALUE(MULTI_FINISH_GAME          , 2)   \
100
        VALUE(MULTI_ORB_BONUS            , 3)   \
101
        VALUE(MULTI_GOT_ORB              , 2)   \
102
        VALUE(MULTI_EFFECT_BLOWUP        , 17)  \
103
        VALUE(MULTI_VULWPN_AMMO_ADJ      , 6)   \
104
        VALUE(MULTI_UPDATE_BUDDY_STATE, 7)      \
105
 
106
#endif
107
 
108
#include "dxxsconf.h"
109
 
110
enum multiplayer_command_t : uint8_t
111
{
112
        for_each_multiplayer_command(define_multiplayer_command)
113
};
114
 
115
template <multiplayer_command_t>
116
struct command_length;
117
#define define_command_length(NAME,SIZE)        \
118
        template <>     \
119
        struct command_length<NAME> : public std::integral_constant<unsigned, SIZE> {};
120
for_each_multiplayer_command(define_command_length);
121
 
122
template <multiplayer_command_t C>
123
struct multi_command : public std::array<uint8_t, command_length<C>::value>
124
{
125
};
126
 
127
void _multi_send_data(const uint8_t *buf, unsigned len, int priority);
128
 
129
template <multiplayer_command_t C>
130
static inline void multi_send_data(uint8_t *const buf, const unsigned len, const int priority)
131
{
132
        buf[0] = C;
133
        constexpr unsigned expected = command_length<C>::value;
134
#ifdef DXX_CONSTANT_TRUE
135
        if (DXX_CONSTANT_TRUE(len != expected))
136
                DXX_ALWAYS_ERROR_FUNCTION(dxx_trap_multi_send_data, "wrong packet size");
137
#endif
138
        if (len != expected)
139
        {
140
                Error("multi_send_data: Packet type %i length: %i, expected: %i\n", C, len, expected);
141
        }
142
        _multi_send_data(buf, len, priority);
143
}
144
 
145
template <multiplayer_command_t C>
146
static inline void multi_send_data(multi_command<C> &buf, const int priority)
147
{
148
        buf[0] = C;
149
        _multi_send_data(buf.data(), buf.size(), priority);
150
}
151
 
152
template <typename T>
153
static inline void multi_serialize_read(const uint8_t *const buf, T &t)
154
{
155
        serial::reader::bytebuffer_t b(buf);
156
        serial::process_buffer(b, t);
157
}
158
 
159
template <typename T>
160
static inline void multi_serialize_write(int priority, const T &t)
161
{
162
        constexpr size_t maximum_size = serial::message_type<T>::maximum_size;
163
        uint8_t buf[maximum_size];
164
        serial::writer::bytebuffer_t b(buf);
165
        serial::process_buffer(b, t);
166
        _multi_send_data(buf, maximum_size, priority);
167
}
168
 
169
template <multiplayer_command_t C>
170
using multiplayer_command = serial::pad<1, static_cast<uint8_t>(C)>;
171
 
172
#endif