Subversion Repositories Games.Descent

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 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