Subversion Repositories Games.Descent

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Portions of this file are copyright Rebirth contributors and licensed as
  3.  * described in COPYING.txt.
  4.  * Portions of this file are copyright Parallax Software and licensed
  5.  * according to the Parallax license below.
  6.  * See COPYING.txt for license details.
  7.  
  8. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  9. SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
  10. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  11. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  12. IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  13. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  14. FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  15. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
  16. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
  17. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
  18. */
  19.  
  20. /*
  21.  *
  22.  * Defines and exported variables for multi.c
  23.  *
  24.  */
  25.  
  26. #pragma once
  27.  
  28. #include <type_traits>
  29. #include "dxxsconf.h"
  30. #include "fwd-partial_range.h"
  31. #include "fwd-player.h"
  32. #include "player-callsign.h"
  33. #include "player-flags.h"
  34. #include "weapon.h"
  35. #include "mission.h"
  36. #include "newmenu.h"
  37. #include "powerup.h"
  38. #include "fwd-object.h"
  39. #include "fwd-wall.h"
  40. #include "window.h"
  41. #include "game.h"
  42. #include "gameplayopt.h"
  43.  
  44. #ifdef _WIN32
  45. #include <winsock2.h>
  46. #include <ws2tcpip.h>
  47. #include <io.h>
  48. #else
  49. #include <sys/socket.h>
  50. #include <netinet/in.h>
  51. #include <netdb.h>
  52. #include <arpa/inet.h>
  53. #include <unistd.h>
  54. #include <stdint.h>
  55. #include <sys/time.h>
  56. #endif
  57.  
  58. #ifdef __cplusplus
  59. #include <stdexcept>
  60. #include "digi.h"
  61. #include "pack.h"
  62. #include "ntstring.h"
  63. #include "compiler-static_assert.h"
  64. #include <array>
  65.  
  66. namespace dcx {
  67.  
  68. struct _sockaddr
  69. {
  70.         union {
  71.                 sockaddr sa;
  72.                 sockaddr_in sin;
  73. #if DXX_USE_IPv6
  74.                 sockaddr_in6 sin6;
  75. #define DXX_IPv6(v4,v6) v6
  76. #else
  77. #define DXX_IPv6(v4,v6) v4
  78. #endif
  79.         };
  80.         enum {
  81.                 presentation_buffer_size = DXX_IPv6(INET_ADDRSTRLEN, INET6_ADDRSTRLEN),
  82.         };
  83.         static int address_family()
  84.         {
  85.                 return DXX_IPv6(AF_INET, AF_INET6);
  86.         }
  87.         static int protocol_family()
  88.         {
  89.                 return DXX_IPv6(PF_INET, PF_INET6);
  90.         }
  91. #undef DXX_IPv6
  92. };
  93.  
  94. // PROTOCOL VARIABLES AND DEFINES
  95. extern int multi_protocol; // set and determinate used protocol
  96.  
  97. }
  98. #define MULTI_PROTO_UDP 1 // UDP protocol
  99.  
  100. // What version of the multiplayer protocol is this? Increment each time something drastic changes in Multiplayer without the version number changes. Reset to 0 each time the version of the game changes
  101. #define MULTI_PROTO_VERSION     static_cast<uint16_t>(11)
  102. // PROTOCOL VARIABLES AND DEFINES - END
  103.  
  104. // limits for Packets (i.e. positional updates) per sec
  105. #define DEFAULT_PPS 30
  106. #define MIN_PPS 5
  107. #define MAX_PPS 40
  108.  
  109. #define MAX_MESSAGE_LEN 35
  110.  
  111.  
  112. #if defined(DXX_BUILD_DESCENT_I)
  113. #define MAX_NET_CREATE_OBJECTS 20
  114. #define MAX_MULTI_MESSAGE_LEN  90 //didn't change it, just moved it up
  115. #elif defined(DXX_BUILD_DESCENT_II)
  116. #define MAX_NET_CREATE_OBJECTS  40
  117. #define MAX_MULTI_MESSAGE_LEN   120
  118.  
  119. #endif
  120.  
  121. #define NETGAME_ANARCHY         0
  122. #define NETGAME_TEAM_ANARCHY    1
  123. #define NETGAME_ROBOT_ANARCHY   2
  124. #define NETGAME_COOPERATIVE     3
  125. #if defined(DXX_BUILD_DESCENT_II)
  126. #define NETGAME_CAPTURE_FLAG    4
  127. #define NETGAME_HOARD           5
  128. #define NETGAME_TEAM_HOARD      6
  129. #endif
  130. #define NETGAME_BOUNTY          7
  131.  
  132. #define NETSTAT_MENU                0
  133. #define NETSTAT_PLAYING             1
  134. #define NETSTAT_BROWSING            2
  135. #define NETSTAT_WAITING             3
  136. #define NETSTAT_STARTING            4
  137. #define NETSTAT_ENDLEVEL            5
  138.  
  139. #define CONNECT_DISCONNECTED        0
  140. #define CONNECT_PLAYING             1
  141. #define CONNECT_WAITING             2
  142. #define CONNECT_DIED_IN_MINE        3
  143. #define CONNECT_FOUND_SECRET        4
  144. #define CONNECT_ESCAPE_TUNNEL       5
  145. #define CONNECT_END_MENU            6
  146. #if defined(DXX_BUILD_DESCENT_II)
  147. #define CONNECT_KMATRIX_WAITING     7 // Like CONNECT_WAITING but used especially in kmatrix.c to seperate "escaped" and "waiting"
  148. #endif
  149.  
  150. // reasons for a packet with type PID_DUMP
  151. #define DUMP_CLOSED     0 // no new players allowed after game started
  152. #define DUMP_FULL       1 // player cound maxed out
  153. #define DUMP_ENDLEVEL   2
  154. #define DUMP_DORK       3
  155. #define DUMP_ABORTED    4
  156. #define DUMP_CONNECTED  5 // never used
  157. #define DUMP_LEVEL      6
  158. #define DUMP_KICKED     7
  159. #define DUMP_PKTTIMEOUT 8
  160.  
  161. #if defined(DXX_BUILD_DESCENT_I) || defined(DXX_BUILD_DESCENT_II)
  162. #define NETFLAG_LABEL_QUAD       "Quad Lasers"
  163. #define NETFLAG_LABEL_VULCAN     "Vulcan cannon"
  164. #define NETFLAG_LABEL_SPREAD     "Spreadfire cannon"
  165. #define NETFLAG_LABEL_PLASMA     "Plasma cannon"
  166. #define NETFLAG_LABEL_FUSION     "Fusion cannon"
  167. #define for_each_netflag_value(VALUE)   \
  168.         VALUE(NETFLAG_DOLASER, "Laser upgrade") \
  169.         VALUE(NETFLAG_DOQUAD, NETFLAG_LABEL_QUAD)       \
  170.         VALUE(NETFLAG_DOVULCAN, NETFLAG_LABEL_VULCAN)   \
  171.         VALUE(NETFLAG_DOSPREAD, NETFLAG_LABEL_SPREAD)   \
  172.         VALUE(NETFLAG_DOPLASMA, NETFLAG_LABEL_PLASMA)   \
  173.         VALUE(NETFLAG_DOFUSION, NETFLAG_LABEL_FUSION)   \
  174.         VALUE(NETFLAG_DOHOMING, "Homing Missiles")      \
  175.         VALUE(NETFLAG_DOPROXIM, "Proximity Bombs")      \
  176.         VALUE(NETFLAG_DOSMART, "Smart Missiles")        \
  177.         VALUE(NETFLAG_DOMEGA, "Mega Missiles")  \
  178.         VALUE(NETFLAG_DOCLOAK, "Cloaking")      \
  179.         VALUE(NETFLAG_DOINVUL, "Invulnerability")       \
  180.         D2X_MP_NETFLAGS(VALUE)  \
  181.  
  182. #define for_each_netgrant_value(VALUE)  \
  183.         VALUE(NETGRANT_QUAD, NETFLAG_LABEL_QUAD)        \
  184.         VALUE(NETGRANT_VULCAN, NETFLAG_LABEL_VULCAN)    \
  185.         VALUE(NETGRANT_SPREAD, NETFLAG_LABEL_SPREAD)    \
  186.         VALUE(NETGRANT_PLASMA, NETFLAG_LABEL_PLASMA)    \
  187.         VALUE(NETGRANT_FUSION, NETFLAG_LABEL_FUSION)    \
  188.         D2X_MP_NETGRANT(VALUE)
  189.  
  190. #define MULTI_GAME_TYPE_COUNT   8
  191. namespace dsx {
  192. #if defined(DXX_BUILD_DESCENT_I)
  193. constexpr std::integral_constant<unsigned, 13> MULTI_GAME_NAME_LENGTH{};
  194. constexpr std::integral_constant<unsigned, 18> MULTI_ALLOW_POWERUP_TEXT_LENGTH{};
  195. #define MULTI_ALLOW_POWERUP_MAX 12
  196. #define D2X_MP_NETFLAGS(VALUE)
  197. #define DXX_GRANT_LASER_LEVEL_BITS      2
  198. #define D2X_MP_NETGRANT(VALUE)
  199. #elif defined(DXX_BUILD_DESCENT_II)
  200. constexpr std::integral_constant<unsigned, 17> MULTI_GAME_NAME_LENGTH{};
  201. constexpr std::integral_constant<unsigned, 21> MULTI_ALLOW_POWERUP_TEXT_LENGTH{};
  202. #define MULTI_ALLOW_POWERUP_MAX 26
  203. #define NETFLAG_LABEL_GAUSS     "Gauss cannon"
  204. #define NETFLAG_LABEL_HELIX     "Helix cannon"
  205. #define NETFLAG_LABEL_PHOENIX   "Phoenix cannon"
  206. #define NETFLAG_LABEL_OMEGA     "Omega cannon"
  207. #define NETFLAG_LABEL_AFTERBURNER       "Afterburners"
  208. #define NETFLAG_LABEL_AMMORACK  "Ammo rack"
  209. #define NETFLAG_LABEL_CONVERTER "Energy Converter"
  210. #define NETFLAG_LABEL_HEADLIGHT "Headlight"
  211. #define D2X_MP_NETFLAGS(VALUE)  \
  212.         VALUE(NETFLAG_DOSUPERLASER, "Super lasers")     \
  213.         VALUE(NETFLAG_DOGAUSS, NETFLAG_LABEL_GAUSS)     \
  214.         VALUE(NETFLAG_DOHELIX, NETFLAG_LABEL_HELIX)     \
  215.         VALUE(NETFLAG_DOPHOENIX, NETFLAG_LABEL_PHOENIX) \
  216.         VALUE(NETFLAG_DOOMEGA, NETFLAG_LABEL_OMEGA)     \
  217.         VALUE(NETFLAG_DOFLASH, "Flash Missiles")        \
  218.         VALUE(NETFLAG_DOGUIDED, "Guided Missiles")      \
  219.         VALUE(NETFLAG_DOSMARTMINE, "Smart Mines")       \
  220.         VALUE(NETFLAG_DOMERCURY, "Mercury Missiles")    \
  221.         VALUE(NETFLAG_DOSHAKER, "Earthshaker Missiles") \
  222.         VALUE(NETFLAG_DOAFTERBURNER, NETFLAG_LABEL_AFTERBURNER) \
  223.         VALUE(NETFLAG_DOAMMORACK, NETFLAG_LABEL_AMMORACK)       \
  224.         VALUE(NETFLAG_DOCONVERTER, NETFLAG_LABEL_CONVERTER)     \
  225.         VALUE(NETFLAG_DOHEADLIGHT, NETFLAG_LABEL_HEADLIGHT)
  226.  
  227. #define DXX_GRANT_LASER_LEVEL_BITS      3
  228. #define D2X_MP_NETGRANT(VALUE)  \
  229.         VALUE(NETGRANT_GAUSS, NETFLAG_LABEL_GAUSS)      \
  230.         VALUE(NETGRANT_HELIX, NETFLAG_LABEL_HELIX)      \
  231.         VALUE(NETGRANT_PHOENIX, NETFLAG_LABEL_PHOENIX)  \
  232.         VALUE(NETGRANT_OMEGA, NETFLAG_LABEL_OMEGA)      \
  233.         VALUE(NETGRANT_AFTERBURNER, NETFLAG_LABEL_AFTERBURNER)  \
  234.         VALUE(NETGRANT_AMMORACK, NETFLAG_LABEL_AMMORACK)        \
  235.         VALUE(NETGRANT_CONVERTER, NETFLAG_LABEL_CONVERTER)      \
  236.         VALUE(NETGRANT_HEADLIGHT, NETFLAG_LABEL_HEADLIGHT)
  237.  
  238. #endif
  239. }
  240.  
  241. #define define_netflag_bit_enum(NAME,STR)       BIT_##NAME,
  242. #define define_netflag_bit_mask(NAME,STR)       static constexpr auto NAME = std::integral_constant<unsigned, (1 << BIT_##NAME)>{};
  243. #define define_netflag_powerup_mask(NAME,STR)   | (NAME)
  244. enum { for_each_netflag_value(define_netflag_bit_enum) };
  245. // Bitmask for netgame_info->AllowedItems to set allowed items in Netgame
  246. for_each_netflag_value(define_netflag_bit_mask);
  247. enum { NETFLAG_DOPOWERUP = 0 for_each_netflag_value(define_netflag_powerup_mask) };
  248. enum {
  249.         BIT_NETGRANT_LASER = DXX_GRANT_LASER_LEVEL_BITS - 1,
  250.         for_each_netgrant_value(define_netflag_bit_enum)
  251.         BIT_NETGRANT_MAXIMUM
  252. };
  253. for_each_netgrant_value(define_netflag_bit_mask);
  254. #undef define_netflag_bit_enum
  255. #undef define_netflag_bit_mask
  256. #undef define_netflag_powerup_mask
  257.  
  258. namespace dsx {
  259.  
  260. struct packed_spawn_granted_items
  261. {
  262. #if defined(DXX_BUILD_DESCENT_I)
  263.         typedef uint8_t mask_type;
  264. #elif defined(DXX_BUILD_DESCENT_II)
  265.         typedef uint16_t mask_type;
  266. #endif
  267.         mask_type mask;
  268.         static_assert(BIT_NETGRANT_MAXIMUM <= sizeof(mask) << 3, "mask too small");
  269.         packed_spawn_granted_items() = default;
  270.         constexpr packed_spawn_granted_items(mask_type m) :
  271.                 mask(m)
  272.         {
  273.         }
  274.         template <unsigned U>
  275.                 constexpr packed_spawn_granted_items(std::integral_constant<unsigned, U>) :
  276.                         mask(U)
  277.         {
  278.                 assert_equal(U, static_cast<mask_type>(U), "truncation error");
  279.         }
  280.         explicit operator bool() const { return mask; }
  281.         bool has_quad_laser() const { return mask & NETGRANT_QUAD; }
  282. #if defined(DXX_BUILD_DESCENT_II)
  283.         bool has_afterburner() const { return mask & NETGRANT_AFTERBURNER; }
  284. #endif
  285. };
  286.  
  287. class packed_netduplicate_items
  288. {
  289. public:
  290.         enum
  291.         {
  292.                 primary_shift = 0,
  293.                 primary_width = 3,
  294.                 secondary_shift = primary_shift + primary_width,
  295.                 secondary_width = 3,
  296. #if defined(DXX_BUILD_DESCENT_II)
  297.                 accessory_shift = secondary_shift + secondary_width,
  298.                 accessory_width = 3,
  299. #endif
  300.         };
  301. private:
  302. #if defined(DXX_BUILD_DESCENT_I)
  303.         typedef uint8_t count_type;
  304. #elif defined(DXX_BUILD_DESCENT_II)
  305.         typedef uint16_t count_type;
  306. #endif
  307.         count_type count;
  308.         template <uint_fast32_t shift, uint_fast32_t width>
  309.         uint_fast32_t get_sub_field() const
  310.         {
  311.                 static_assert(shift + width <= sizeof(count) << 3, "shift+width too big");
  312.                 constexpr auto low_mask = (1 << width) - 1;
  313.                 return (count >> shift) & low_mask;
  314.         }
  315. public:
  316.         template <uint_fast32_t shift, uint_fast32_t width>
  317.         void set_sub_field(uint_fast32_t value)
  318.         {
  319.                 constexpr auto low_mask = (1 << width) - 1;
  320.                 constexpr auto shifted_mask = low_mask << shift;
  321.                 count = (count & ~shifted_mask) | (value << shift);
  322.         }
  323. #define DEFINE_ACCESSOR(N)      \
  324.         uint_fast32_t get_##N##_count() const   \
  325.         {       \
  326.                 return get_sub_field<N##_shift, N##_width>();   \
  327.         }       \
  328.         void set_##N##_count(uint_fast32_t value)       \
  329.         {       \
  330.                 set_sub_field<N##_shift, N##_width>(value);     \
  331.         }
  332.         DEFINE_ACCESSOR(primary);
  333.         DEFINE_ACCESSOR(secondary);
  334. #if defined(DXX_BUILD_DESCENT_II)
  335.         DEFINE_ACCESSOR(accessory);
  336. #endif
  337.         count_type get_packed_field() const
  338.         {
  339.                 return count;
  340.         }
  341.         void set_packed_field(count_type c)
  342.         {
  343.                 count = c;
  344.         }
  345. };
  346.  
  347. static inline laser_level_t map_granted_flags_to_laser_level(const packed_spawn_granted_items &grant)
  348. {
  349.         /* Laser level in lowest bits */
  350.         return laser_level_t(grant.mask & ((1 << DXX_GRANT_LASER_LEVEL_BITS) - 1));
  351. }
  352. player_flags map_granted_flags_to_player_flags(packed_spawn_granted_items grant);
  353. uint_fast32_t map_granted_flags_to_primary_weapon_flags(packed_spawn_granted_items grant);
  354. uint16_t map_granted_flags_to_vulcan_ammo(packed_spawn_granted_items grant);
  355. void multi_digi_link_sound_to_pos(int soundnum, vcsegptridx_t segnum, unsigned sidenum, const vms_vector &pos, int forever, fix max_volume);
  356. void multi_object_to_object_rw(object &obj, object_rw *obj_rw);
  357. void multi_object_rw_to_object(object_rw *obj_rw, object &obj);
  358.  
  359. using GMNames_array = std::array<char[MULTI_GAME_NAME_LENGTH], MULTI_GAME_TYPE_COUNT>;
  360. extern const GMNames_array GMNames;
  361. using multi_allow_powerup_text_array = std::array<char[MULTI_ALLOW_POWERUP_TEXT_LENGTH], MULTI_ALLOW_POWERUP_MAX>;
  362. extern const multi_allow_powerup_text_array multi_allow_powerup_text;
  363. extern const std::array<char[8], MULTI_GAME_TYPE_COUNT> GMNamesShrt;
  364. }
  365.  
  366. namespace dcx {
  367. extern std::array<objnum_t, MAX_NET_CREATE_OBJECTS> Net_create_objnums;
  368. extern unsigned Net_create_loc;
  369. }
  370.  
  371. namespace dsx {
  372.  
  373. void multi_send_fire(int laser_gun, int laser_level, int laser_flags, int laser_fired, objnum_t laser_track, imobjptridx_t is_bomb_objnum);
  374. void multi_send_destroy_controlcen(objnum_t objnum, playernum_t player);
  375. void multi_send_position(object &objnum);
  376. void multi_send_kill(vmobjptridx_t objnum);
  377. void multi_send_remobj(vmobjidx_t objnum);
  378. void multi_send_door_open(vcsegidx_t segnum, unsigned side, uint8_t flag);
  379. void multi_send_drop_weapon(vmobjptridx_t objnum,int seed);
  380. void multi_reset_player_object(object &objp);
  381. int multi_maybe_disable_friendly_fire(const object *killer);
  382. }
  383. #endif
  384.  
  385. enum msgsend_state_t {
  386.         msgsend_none,
  387.         msgsend_typing,
  388.         msgsend_automap,
  389. };
  390.  
  391. enum deres_type_t {
  392.         deres_explode,
  393.         deres_drop,
  394. };
  395.  
  396. // Exported functions
  397.  
  398. struct owned_remote_objnum
  399. {
  400.         int8_t owner;
  401.         uint16_t objnum;
  402. };
  403.  
  404. extern int GetMyNetRanking();
  405. extern void ClipRank (ubyte *rank);
  406. objnum_t objnum_remote_to_local(uint16_t remote_obj, int8_t owner);
  407. uint16_t objnum_local_to_remote(objnum_t local_obj, int8_t *owner);
  408. owned_remote_objnum objnum_local_to_remote(objnum_t local);
  409. void map_objnum_local_to_remote(int local, int remote, int owner);
  410. void map_objnum_local_to_local(objnum_t objnum);
  411. void reset_network_objects();
  412. int multi_objnum_is_past(objnum_t objnum);
  413. void multi_do_ping_frame();
  414.  
  415. void multi_init_objects(void);
  416. void multi_do_protocol_frame(int force, int listen);
  417. window_event_result multi_do_frame();
  418.  
  419. #ifdef dsx
  420. namespace dsx {
  421.  
  422. enum class multi_endlevel_type : bool
  423. {
  424.         normal,
  425. #if defined(DXX_BUILD_DESCENT_I)
  426.         secret,
  427. #endif
  428. };
  429. #if defined(DXX_BUILD_DESCENT_I)
  430. void multi_send_endlevel_start(multi_endlevel_type);
  431. #elif defined(DXX_BUILD_DESCENT_II)
  432. void multi_send_endlevel_start();
  433. static inline void multi_send_endlevel_start(multi_endlevel_type)
  434. {
  435.         multi_send_endlevel_start();
  436. }
  437. #endif
  438. void multi_send_player_deres(deres_type_t type);
  439. void multi_send_create_powerup(powerup_type_t powerup_type, vcsegidx_t segnum, vcobjidx_t objnum, const vms_vector &pos);
  440. }
  441. void multi_send_play_sound(int sound_num, fix volume, sound_stack once);
  442. #endif
  443. void multi_send_reappear();
  444. void multi_send_create_explosion(playernum_t);
  445. void multi_send_controlcen_fire(const vms_vector &to_target, int gun_num, objnum_t objnum);
  446. namespace dcx {
  447. void multi_send_cloak(void);
  448. void multi_send_decloak(void);
  449. }
  450. void multi_digi_play_sample(int sndnum, fix max_volume);
  451. void multi_digi_play_sample_once(int soundnum, fix max_volume);
  452. void multi_send_score(void);
  453. void multi_send_trigger(int trigger);
  454. #if defined(DXX_BUILD_DESCENT_II)
  455. namespace dsx {
  456. extern char Multi_is_guided;
  457. void multi_send_flags(playernum_t);
  458. struct marker_message_text_t;
  459. void multi_send_drop_marker(unsigned player, const vms_vector &position, player_marker_index messagenum, const marker_message_text_t &text);
  460. void multi_send_markers();
  461. void multi_send_guided_info (const object_base &miss, char);
  462. void multi_send_orb_bonus(playernum_t pnum, uint8_t);
  463. void multi_send_got_orb(playernum_t pnum);
  464. void multi_send_effect_blowup(vcsegidx_t segnum, unsigned side, const vms_vector &pnt);
  465. void multi_send_vulcan_weapon_ammo_adjust(const vmobjptridx_t objnum);
  466. }
  467. #ifndef RELEASE
  468. void multi_add_lifetime_kills(int count);
  469. #endif
  470. #endif
  471. void multi_send_bounty( void );
  472.  
  473. void multi_consistency_error(int reset);
  474. window_event_result multi_level_sync();
  475. int multi_endlevel(int *secret);
  476. using multi_endlevel_poll = int(newmenu *menu,const d_event &event, const unused_newmenu_userdata_t *);
  477. multi_endlevel_poll *get_multi_endlevel_poll2();
  478. void multi_send_endlevel_packet();
  479. #ifdef dsx
  480. namespace dsx {
  481. void multi_send_hostage_door_status(vcwallptridx_t wallnum);
  482. void multi_prep_level_objects(const d_vclip_array &Vclip);
  483. void multi_prep_level_player();
  484. void multi_leave_game(void);
  485. }
  486. #endif
  487. void multi_process_bigdata(playernum_t pnum, const ubyte *buf, uint_fast32_t len);
  488. void multi_do_death(int objnum);
  489. #ifdef dsx
  490. namespace dsx {
  491. void multi_make_ghost_player(playernum_t);
  492. void multi_make_player_ghost(playernum_t);
  493. }
  494. #endif
  495. void multi_define_macro(int key);
  496. void multi_send_macro(int key);
  497. int multi_get_kill_list(playernum_array_t &sorted_kills);
  498. void multi_new_game(void);
  499. #ifdef dsx
  500. namespace dsx {
  501. void multi_sort_kill_list(void);
  502. }
  503. #endif
  504. void multi_reset_stuff(void);
  505. int get_team(playernum_t pnum);
  506. void multi_disconnect_player(playernum_t);
  507.  
  508. #ifdef dsx
  509. namespace dsx {
  510. void multi_initiate_save_game();
  511. void multi_initiate_restore_game();
  512. void multi_execute_save_game(d_game_unique_state::save_slot slot, const d_game_unique_state::savegame_description &desc, partial_range_t<const player *> player_range);
  513. #if defined(DXX_BUILD_DESCENT_I)
  514. static inline void multi_send_got_flag (playernum_t) {}
  515. #elif defined(DXX_BUILD_DESCENT_II)
  516. void multi_send_got_flag (playernum_t);
  517. #endif
  518. }
  519. #endif
  520.  
  521. // Exported variables
  522.  
  523. namespace dcx {
  524. extern int Network_status;
  525.  
  526. // IMPORTANT: These variables needed for player rejoining done by protocol-specific code
  527. extern int Network_send_objects;
  528. extern int Network_send_object_mode;
  529. extern int Network_send_objnum;
  530. extern int Network_rejoined;
  531. extern int Network_sending_extras;
  532. extern int VerifyPlayerJoined;
  533. extern int Player_joining_extras;
  534. extern int Network_player_added;
  535.  
  536. extern std::array<std::array<uint16_t, MAX_PLAYERS>, MAX_PLAYERS> kill_matrix;
  537. extern std::array<int16_t, 2> team_kills;
  538.  
  539. extern ushort my_segments_checksum;
  540.  
  541. //do we draw the kill list on the HUD?
  542. extern int Show_kill_list;
  543. extern int Show_reticle_name;
  544. extern fix Show_kill_list_timer;
  545.  
  546. // Used to send network messages
  547.  
  548. extern ntstring<MAX_MESSAGE_LEN - 1> Network_message;
  549. extern int Network_message_reciever;
  550.  
  551. // Which player 'owns' each local object for network purposes
  552. extern std::array<sbyte, MAX_OBJECTS> object_owner;
  553.  
  554. extern int multi_quit_game;
  555.  
  556. extern std::array<msgsend_state_t, MAX_PLAYERS> multi_sending_message;
  557. extern int multi_defining_message;
  558. }
  559. window_event_result multi_message_input_sub(int key);
  560. extern void multi_send_message_start();
  561. void multi_send_msgsend_state(msgsend_state_t state);
  562.  
  563. #if defined(DXX_BUILD_DESCENT_II)
  564. namespace dsx {
  565. extern std::array<grs_main_bitmap, 2> Orb_icons;
  566. struct hoard_highest_record
  567. {
  568.         unsigned points;
  569.         unsigned player = UINT_MAX;
  570. };
  571.  
  572. extern hoard_highest_record hoard_highest_record_stats;
  573. }
  574. #endif
  575. namespace dcx {
  576. extern playernum_t Bounty_target;
  577.  
  578. extern std::array<std::array<bitmap_index, N_PLAYER_SHIP_TEXTURES>, MAX_PLAYERS> multi_player_textures;
  579.  
  580. extern const std::array<char[16], 10> RankStrings;
  581. #define GetRankStringWithSpace(I)       (PlayerCfg.NoRankings ? std::pair<const char *, const char *>("", "") : std::pair<const char *, const char *>(RankStrings[I], " "))
  582.  
  583. // Globals for protocol-bound Refuse-functions
  584. extern char RefuseThisPlayer,WaitForRefuseAnswer,RefuseTeam,RefusePlayerName[12];
  585. extern fix64 RefuseTimeLimit;
  586. #define REFUSE_INTERVAL (F1_0*8)
  587. }
  588.  
  589. #ifdef dsx
  590. namespace dsx {
  591. struct bit_game_flags {
  592.         unsigned closed : 1;
  593.         unsigned : 1;
  594.         unsigned show_on_map : 1;
  595.         /*
  596.          * These #define are written to .NGP files and to the network.
  597.          * Changing them breaks ABI compatibility.
  598.          * The bit flags need not match in value, and are converted below in
  599.          * pack_game_flags / unpack_game_flags.
  600.          */
  601. #define NETGAME_FLAG_CLOSED             1
  602. #define NETGAME_FLAG_SHOW_MAP           4
  603. #if defined(DXX_BUILD_DESCENT_II)
  604.         unsigned hoard : 1;
  605.         unsigned team_hoard : 1;
  606.         unsigned endlevel : 1;
  607.         unsigned forming : 1;
  608. #define NETGAME_FLAG_HOARD              8
  609. #define NETGAME_FLAG_TEAM_HOARD         16
  610. #define NETGAME_FLAG_REALLY_ENDLEVEL    32
  611. #define NETGAME_FLAG_REALLY_FORMING     64
  612. #endif
  613. } __pack__;
  614. }
  615.  
  616. namespace dcx {
  617. struct packed_game_flags
  618. {
  619.         unsigned char value;
  620. };
  621.  
  622. #if DXX_USE_TRACKER
  623. enum TrackerNATHolePunchWarn : uint8_t
  624. {
  625.         Unset,
  626.         UserEnabledHP,
  627.         UserRejectedHP,
  628. };
  629. #endif
  630. }
  631.  
  632. namespace dsx {
  633.  
  634. static inline bit_game_flags unpack_game_flags(const packed_game_flags *p)
  635. {
  636.         bit_game_flags flags;
  637.         flags.closed = !!(p->value & NETGAME_FLAG_CLOSED);
  638.         flags.show_on_map = !!(p->value & NETGAME_FLAG_SHOW_MAP);
  639. #if defined(DXX_BUILD_DESCENT_II)
  640.         flags.hoard = !!(p->value & NETGAME_FLAG_HOARD);
  641.         flags.team_hoard = !!(p->value & NETGAME_FLAG_TEAM_HOARD);
  642.         flags.endlevel = !!(p->value & NETGAME_FLAG_REALLY_ENDLEVEL);
  643.         flags.forming = !!(p->value & NETGAME_FLAG_REALLY_FORMING);
  644. #endif
  645.         return flags;
  646. }
  647.  
  648. static inline packed_game_flags pack_game_flags(const bit_game_flags *flags)
  649. {
  650.         packed_game_flags p;
  651.         p.value =
  652.                 (flags->closed ? NETGAME_FLAG_CLOSED : 0) |
  653.                 (flags->show_on_map ? NETGAME_FLAG_SHOW_MAP : 0) |
  654. #if defined(DXX_BUILD_DESCENT_II)
  655.                 (flags->hoard ? NETGAME_FLAG_HOARD : 0) |
  656.                 (flags->team_hoard ? NETGAME_FLAG_TEAM_HOARD : 0) |
  657.                 (flags->endlevel ? NETGAME_FLAG_REALLY_ENDLEVEL : 0) |
  658.                 (flags->forming ? NETGAME_FLAG_REALLY_FORMING : 0) |
  659. #endif
  660.                 0;
  661.         return p;
  662. }
  663.  
  664. #define NETGAME_NAME_LEN        25
  665.  
  666. extern struct netgame_info Netgame;
  667. }
  668. #endif
  669.  
  670. #define multi_i_am_master()     (Player_num == 0)
  671. void change_playernum_to(playernum_t new_pnum);
  672.  
  673. // Multiplayer powerup capping
  674. void MultiLevelInv_InitializeCount();
  675. void MultiLevelInv_Recount();
  676. #ifdef dsx
  677. namespace dsx {
  678. extern bool MultiLevelInv_AllowSpawn(powerup_type_t powerup_type);
  679. }
  680. #endif
  681. extern void MultiLevelInv_Repopulate(fix frequency);
  682. #ifdef dsx
  683. namespace dsx {
  684. uint_fast32_t multi_powerup_is_allowed(const unsigned id, const unsigned AllowedItems);
  685. uint_fast32_t multi_powerup_is_allowed(const unsigned id, const unsigned AllowedItems, const unsigned SpawnGrantedItems);
  686. void show_netgame_info(const netgame_info &netgame);
  687. extern void multi_send_player_inventory(int priority);
  688. const char *multi_common_deny_save_game(const fvcobjptr &vcobjptr, partial_range_t<const player *> player_range);
  689. const char *multi_interactive_deny_save_game(const fvcobjptr &vcobjptr, partial_range_t<const player *> player_range, const d_level_unique_control_center_state &);
  690. }
  691. #endif
  692. extern void multi_send_kill_goal_counts();
  693. void multi_check_for_killgoal_winner();
  694. #if defined(DXX_BUILD_DESCENT_II)
  695. namespace dsx {
  696. extern void multi_send_stolen_items();
  697. void multi_send_trigger_specific(playernum_t pnum, uint8_t trig);
  698. void multi_send_door_open_specific(playernum_t pnum, vcsegidx_t segnum, unsigned side, uint8_t flag);
  699. void multi_send_wall_status_specific(playernum_t pnum,uint16_t wallnum,ubyte type,ubyte flags,ubyte state);
  700. void multi_send_light_specific (playernum_t pnum, vcsegptridx_t segnum, uint8_t val);
  701. void multi_send_capture_bonus (playernum_t pnum);
  702. int multi_all_players_alive(const fvcobjptr &, partial_range_t<const player *>);
  703. void multi_send_seismic(fix);
  704. void multi_send_drop_blobs(playernum_t);
  705. void multi_send_sound_function (char,char);
  706. void DropFlag();
  707. void multi_send_finish_game ();
  708. void init_hoard_data(d_vclip_array &Vclip);
  709. void multi_apply_goal_textures();
  710. void multi_send_escort_goal(const d_unique_buddy_state &);
  711. void multi_recv_escort_goal(d_unique_buddy_state &, const uint8_t *);
  712.  
  713. int HoardEquipped();
  714. #if DXX_USE_EDITOR
  715. void save_hoard_data(void);
  716. #endif
  717. }
  718. #endif
  719.  
  720. //how to encode missiles & flares in weapon packets
  721. #define MISSILE_ADJUST  100
  722. #define FLARE_ADJUST    127
  723.  
  724. /*
  725.  * The Network Players structure
  726.  * Contains protocol-specific data with designated prefixes and general player-related data.
  727.  * Note that not all of these infos will be sent to other users - some are used and/or set locally, only.
  728.  */
  729. struct netplayer_info : prohibit_void_ptr<netplayer_info>
  730. {
  731. #if DXX_USE_UDP
  732.         union
  733.         {
  734. #if DXX_USE_UDP
  735.                 struct
  736.                 {
  737.                         struct _sockaddr        addr; // IP address of this peer
  738.                 } udp;
  739. #endif
  740.         } protocol;    
  741. #endif
  742.         callsign_t                                      callsign;
  743.         sbyte                                           connected;
  744.         ubyte                                           rank;
  745.         fix                                                     ping;
  746.         fix64                                                   LastPacketTime;
  747. };
  748.  
  749. #ifdef dsx
  750. #if defined(DXX_BUILD_DESCENT_II)
  751. struct ThiefModifier
  752. {
  753.         enum Flags : uint8_t {
  754.                 Absent = 1,
  755.                 NoEnergyWeapons,
  756.         };
  757. };
  758. #endif
  759.  
  760. namespace dsx {
  761. /*
  762.  * The Network Game structure
  763.  * Contains protocol-specific data with designated prefixes and general game-related data.
  764.  * Note that not all of these infos will be sent to clients - some are used and/or set locally, only.
  765.  */
  766. struct netgame_info : prohibit_void_ptr<netgame_info>, ignore_window_pointer_t
  767. {
  768.         using play_time_allowed_abi_ratio = std::ratio<5 * 60>;
  769. #if DXX_USE_UDP
  770.         union
  771.         {
  772. #if DXX_USE_UDP
  773.                 struct
  774.                 {
  775.                         struct _sockaddr                addr; // IP address of this netgame's host
  776.                         std::array<short, 4>                    program_iver; // IVER of program for version checking
  777.                         sbyte                           valid; // Status of Netgame info: -1 = Failed, Wrong version; 0 = No info, yet; 1 = Success
  778.                         uint8_t                         your_index; // Tell player his designated (re)join position in players[]
  779.                         fix                             GameID;
  780.                 } udp;
  781. #endif
  782.         } protocol;    
  783. #endif
  784.         ntstring<NETGAME_NAME_LEN> game_name;
  785.         ntstring<MISSION_NAME_LEN> mission_title;
  786.         ntstring<8> mission_name;
  787.         int                                             levelnum;
  788.         Difficulty_level_type difficulty;
  789.         ubyte                                           gamemode;
  790.         ubyte                                           RefusePlayers;
  791.         ubyte                                           game_status;
  792.         ubyte                                           numplayers;
  793.         ubyte                                           max_numplayers;
  794.         ubyte                                           numconnected;
  795.         bit_game_flags game_flag;
  796.         ubyte                                           team_vector;
  797.         uint8_t                                         SecludedSpawns;
  798.         uint8_t MouselookFlags;
  799.         uint32_t                                        AllowedItems;
  800.         packed_spawn_granted_items SpawnGrantedItems;
  801.         packed_netduplicate_items DuplicatePowerups;
  802.         unsigned ShufflePowerupSeed;
  803.         d_mp_gameplay_options MPGameplayOptions;
  804. #if defined(DXX_BUILD_DESCENT_II)
  805.         uint8_t Allow_marker_view;
  806.         uint8_t AlwaysLighting;
  807.         uint8_t ThiefModifierFlags;
  808.         uint8_t AllowGuidebot;
  809. #endif
  810.         uint8_t ShowEnemyNames;
  811.         uint8_t BrightPlayers;
  812.         uint8_t InvulAppear;
  813.         ushort                                          segments_checksum;
  814.         int                                             KillGoal;
  815.         /* The UI enforces that this steps in units of 5 minutes, but for
  816.          * efficiency, it is stored as ticks (1 second = F1_0).  The UI
  817.          * imposes a maximum value that is small enough that overflow is
  818.          * impossible.
  819.          */
  820.         d_time_fix PlayTimeAllowed;
  821.         fix                                             level_time;
  822.         int                                             control_invul_time;
  823.         int                                             monitor_vector;
  824.         short                                           PacketsPerSec;
  825.         ubyte                                           PacketLossPrevention;
  826.         ubyte                                           NoFriendlyFire;
  827.         std::array<callsign_t, 2>                                       team_name;
  828.         std::array<uint32_t, MAX_PLAYERS>                                               locations;
  829.         std::array<std::array<uint16_t, MAX_PLAYERS>, MAX_PLAYERS>                                              kills;
  830.         std::array<int16_t, 2>                                          team_kills;
  831.         std::array<uint16_t, MAX_PLAYERS>                                               killed;
  832.         std::array<uint16_t, MAX_PLAYERS>                                               player_kills;
  833.         std::array<uint32_t, MAX_PLAYERS>                                               player_score;
  834.         std::array<player_flags, MAX_PLAYERS>                                   net_player_flags;
  835.         std::array<netplayer_info, MAX_PLAYERS>                                 players;
  836. #if DXX_USE_TRACKER
  837.         ubyte                                           Tracker;
  838.         TrackerNATHolePunchWarn TrackerNATWarned;
  839. #endif
  840. };
  841.  
  842.  
  843. /*
  844.  * Structure holding all powerup types we want to keep track of. Used to cap or respawn powerups and keep the level inventory steady.
  845.  * Using uint32_t because we don't count powerup units but what the powerup contains (1 or 4 missiles, vulcam amount, etc) so we can keep track of overhead.
  846.  * I'm sorry if this isn't very optimized but I found this easier to handle than a single variable per powerup.
  847.  */
  848. struct multi_level_inv
  849. {
  850.         std::array<uint32_t, MAX_POWERUP_TYPES> Initial; // initial (level start) count of this powerup type
  851.         std::array<uint32_t, MAX_POWERUP_TYPES> Current; // current count of this powerup type
  852.         std::array<fix, MAX_POWERUP_TYPES> RespawnTimer; // incremented by FrameTime if initial-current > 0 and triggers respawn after 2 seconds. Since we deal with a certain delay from clients, their inventory updates may happen a while after they remove the powerup object and we do not want to respawn it on accident during that time window!
  853. };
  854. }
  855. #endif
  856.  
  857. namespace multi
  858. {
  859.         struct level_checksum_mismatch : std::runtime_error
  860.         {
  861.                 level_checksum_mismatch() :
  862.                         runtime_error("level checksum mismatch")
  863.                 {
  864.                 }
  865.         };
  866.         struct local_player_not_playing : std::runtime_error
  867.         {
  868.                 local_player_not_playing() :
  869.                         runtime_error("local player not playing")
  870.                 {
  871.                 }
  872.         };
  873. }
  874.  
  875. /* Stub for mods that remap player colors */
  876. static inline unsigned get_player_color(unsigned pnum)
  877. {
  878.         return pnum;
  879. }
  880.  
  881. static inline unsigned get_team_color(unsigned tnum)
  882. {
  883.         return tnum;
  884. }
  885.  
  886. static inline unsigned get_player_or_team_color(unsigned pnum)
  887. {
  888.         return Game_mode & GM_TEAM
  889.                 ? get_team_color(get_team(pnum))
  890.                 : get_player_color(pnum);
  891. }
  892.  
  893. #endif
  894.