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 |