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 |