2014-06-01 17:55:23 +00:00
/*
2018-09-02 00:57:29 +00:00
* This file is part of the DXX - Rebirth project < https : //www.dxx-rebirth.com/>.
2014-06-01 17:55:23 +00:00
* It is copyright by its individual contributors , as recorded in the
* project ' s Git history . See COPYING . txt at the top level for license
* terms and a link to the Git history .
*/
2009-11-24 09:48:53 +00:00
/*
*
* Prototypes for UDP - protocol network management functions .
*
*/
2012-11-11 22:12:51 +00:00
# pragma once
2009-11-24 09:48:53 +00:00
# include "multi.h"
2021-02-05 12:54:08 +00:00
# include "newmenu.h"
2014-06-26 02:27:16 +00:00
# include "pack.h"
2014-12-22 04:35:48 +00:00
# include "ntstring.h"
2016-10-27 07:22:41 +00:00
# include "fwd-window.h"
2022-07-16 15:26:12 +00:00
# include "d_array.h"
2022-07-16 15:26:12 +00:00
# include "d_bitset.h"
2020-05-02 21:18:42 +00:00
# include <array>
2012-11-11 22:12:51 +00:00
2009-11-24 09:48:53 +00:00
// Exported functions
2016-08-25 04:05:32 +00:00
# ifdef dsx
namespace dsx {
2020-12-20 20:39:07 +00:00
namespace multi {
namespace udp {
struct dispatch_table final : multi : : dispatch_table
{
2022-09-24 17:47:51 +00:00
virtual void send_data ( std : : span < const uint8_t > data , multiplayer_data_priority priority ) const override ;
2022-09-11 17:00:44 +00:00
virtual void send_data_direct ( std : : span < const uint8_t > data , playernum_t pnum , int needack ) const override ;
2020-12-20 20:39:07 +00:00
virtual int objnum_is_past ( objnum_t objnum ) const override ;
2020-12-20 20:39:07 +00:00
virtual void do_protocol_frame ( int force , int listen ) const override ;
2020-12-20 20:39:07 +00:00
virtual window_event_result level_sync ( ) const override ;
2020-12-20 20:39:07 +00:00
virtual void send_endlevel_packet ( ) const override ;
2022-09-11 17:00:44 +00:00
virtual void kick_player ( const _sockaddr & dump_addr , kick_player_reason why ) const override ;
2020-12-20 20:39:07 +00:00
virtual void disconnect_player ( int playernum ) const override ;
Use enum class for `next_level_request_secret_flag`
Instead of passing a bare `int` named `secret_flag`, define it as an
`enum class : uint8_t` to name the two special values.
Rework the passing of this value, to deal with some confusing
inconsistencies when reading the code.
Before this change:
In D1:
- Multiplayer will always go to the secret level, regardless of which
exit door the player used.
In D2:
- Flying through a D1 secret exit in multiplayer shows the on-HUD error
"Secret Level Teleporter disabled in multiplayer!", and does not exit
the level. This is at best confusing, and at worst dangerous, since
D1 secret exits are only available during the countdown, so the player
has little time to realize that the normal exit must be used instead.
- Like D1, multiplayer will request to go to the secret level regardless
of the exit used. Unlike D1, the caller ignores the flag and always
advances to the next regular level.
After this change:
- No observable differences for the player in-game. The questionable D2
secret exit handling for D1 is retained.
- The code makes clearer that secret exits do not work in D2
multiplayer, by way of `#if defined(DXX_BUILD_DESCENT_I)` guarding the
existence of the parameter and all updates to it.
2022-07-16 15:26:12 +00:00
virtual int end_current_level (
# if defined(DXX_BUILD_DESCENT_I)
next_level_request_secret_flag * secret
# endif
) const override ;
2020-12-20 20:39:07 +00:00
virtual void leave_game ( ) const override ;
2020-12-20 20:39:07 +00:00
} ;
extern const dispatch_table dispatch ;
2020-12-20 20:39:07 +00:00
int kmatrix_poll2 ( newmenu * menu , const d_event & event , const unused_newmenu_userdata_t * ) ;
2020-12-20 20:39:07 +00:00
void leave_game ( ) ;
2020-12-20 20:39:07 +00:00
}
using udp : : dispatch ;
}
2016-10-27 07:22:41 +00:00
window_event_result net_udp_setup_game ( void ) ;
2016-08-25 04:05:32 +00:00
}
# endif
2009-11-24 09:48:53 +00:00
void net_udp_manual_join_game ( ) ;
2021-09-12 16:20:52 +00:00
void net_udp_list_join_game ( grs_canvas & canvas ) ;
2017-01-10 05:02:59 +00:00
window_event_result net_udp_level_sync ( ) ;
2009-11-24 09:48:53 +00:00
// Some defines
2015-02-08 17:43:29 +00:00
// Our default port - easy to remember: D = 4, X = 24, X = 24
2022-09-11 17:00:44 +00:00
namespace dcx {
2016-07-23 04:10:42 +00:00
constexpr uint16_t UDP_PORT_DEFAULT = 42424 ;
2011-06-30 23:01:06 +00:00
# define UDP_MANUAL_ADDR_DEFAULT "localhost"
2016-09-11 18:49:15 +00:00
# if DXX_USE_TRACKER
2015-02-08 17:43:29 +00:00
# ifndef TRACKER_ADDR_DEFAULT
/* Allow an alternate default at compile time */
2019-05-17 13:36:58 +00:00
# define TRACKER_ADDR_DEFAULT "tracker.dxx-rebirth.com"
2015-02-08 17:43:29 +00:00
# endif
2016-10-10 16:19:56 +00:00
constexpr uint16_t TRACKER_PORT_DEFAULT = 9999 ;
2022-09-11 17:00:44 +00:00
enum class tracker_game_id : uint16_t
{
} ;
2011-06-30 23:01:06 +00:00
# endif
2011-07-15 09:46:04 +00:00
# define UDP_MAX_NETGAMES 900
2017-10-14 17:10:30 +00:00
constexpr std : : integral_constant < unsigned , 12 > UDP_NETGAMES_PPAGE { } ; // Netgames on one page of Netlist
}
2011-07-15 09:46:04 +00:00
# define UDP_NETGAMES_PAGES 75 // Pages available on Netlist (UDP_MAX_NETGAMES/UDP_NETGAMES_PPAGE)
2012-05-10 16:53:59 +00:00
# define UDP_TIMEOUT (5*F1_0) // 5 seconds disconnect timeout
2022-07-16 15:26:12 +00:00
# define UDP_MDATA_STOR_QUEUE_SIZE 1024u // Store up to 1024 MDATA packets
# define UDP_MDATA_STOR_MIN_FREE_2JOIN 384u // have at least this many free packet slots before we let someone join the game
2014-06-24 12:49:18 +00:00
# define UDP_MDATA_PKT_NUM_MIN 1 // start from pkt_num 1 (0 is used to initialize the trace list)
# define UDP_MDATA_PKT_NUM_MAX (UDP_MDATA_STOR_QUEUE_SIZE*100) // the max value for pkt_num. roll over when we go any higher. this should be smaller than INT_MAX
2009-11-24 09:48:53 +00:00
2011-04-12 22:19:46 +00:00
// UDP-Packet identificators (ubyte) and their (max. sizes).
# define UPID_MAX_SIZE 1024 // Max size for a packet
# define UPID_MDATA_BUF_SIZE 454
2016-09-11 18:49:15 +00:00
# if DXX_USE_TRACKER
2016-10-10 16:19:56 +00:00
# define UPID_TRACKER_REGISTER 21 // Register or update a game on the tracker.
# define UPID_TRACKER_REMOVE 22 // Remove our game from the tracker.
# define UPID_TRACKER_REQGAMES 23 // Request a list of all games stored on the tracker.
2011-04-05 00:24:30 +00:00
# endif
2009-11-24 09:48:53 +00:00
// Structure keeping lite game infos (for netlist, etc.)
2015-10-13 02:43:24 +00:00
# if defined(DXX_BUILD_DESCENT_I) || defined(DXX_BUILD_DESCENT_II)
2014-06-21 23:55:24 +00:00
struct UDP_netgame_info_lite : public prohibit_void_ptr < UDP_netgame_info_lite >
2009-11-24 09:48:53 +00:00
{
2010-12-22 13:53:23 +00:00
struct _sockaddr game_addr ;
2020-05-02 21:18:42 +00:00
std : : array < short , 3 > program_iver ;
2011-04-11 22:45:06 +00:00
fix GameID ;
2022-09-11 17:00:44 +00:00
# if DXX_USE_TRACKER
tracker_game_id TrackerGameID ;
# endif
2014-12-22 04:35:48 +00:00
ntstring < NETGAME_NAME_LEN > game_name ;
2014-12-22 04:35:48 +00:00
ntstring < MISSION_NAME_LEN > mission_title ;
2015-01-03 23:44:32 +00:00
ntstring < 8 > mission_name ;
2009-11-24 09:48:53 +00:00
int32_t levelnum ;
2021-11-01 03:37:19 +00:00
network_game_type gamemode ;
2010-12-22 13:53:23 +00:00
ubyte RefusePlayers ;
2009-11-24 09:48:53 +00:00
ubyte difficulty ;
2022-07-09 13:39:29 +00:00
network_state game_status ;
2010-07-08 06:37:23 +00:00
ubyte numconnected ;
2009-11-24 09:48:53 +00:00
ubyte max_numplayers ;
2013-08-24 16:33:51 +00:00
bit_game_flags game_flag ;
2014-06-21 23:55:24 +00:00
} ;
2022-07-16 15:26:12 +00:00
struct player_acknowledgement_mask : enumerated_bitset < MAX_PLAYERS , playernum_t >
{
public :
constexpr player_acknowledgement_mask ( ) :
enumerated_bitset ( ( 1u < < MAX_PLAYERS ) - 1 )
{
}
} ;
2015-10-13 02:43:24 +00:00
# endif
2009-11-24 09:48:53 +00:00
// packet structure for multi-buffer
2014-06-26 02:27:16 +00:00
struct UDP_mdata_info : prohibit_void_ptr < UDP_mdata_info >
2009-11-24 09:48:53 +00:00
{
2011-04-12 22:19:46 +00:00
ubyte type ;
ubyte Player_num ;
2015-02-28 19:36:01 +00:00
uint16_t mbuf_size ;
2011-04-12 22:19:46 +00:00
uint32_t pkt_num ;
2020-05-02 21:18:42 +00:00
std : : array < uint8_t , UPID_MDATA_BUF_SIZE > mbuf ;
2014-06-26 02:27:16 +00:00
} ;
2009-11-24 09:48:53 +00:00
// structure to store MDATA to maybe resend
2014-06-26 02:27:16 +00:00
struct UDP_mdata_store : prohibit_void_ptr < UDP_mdata_store >
2009-11-24 09:48:53 +00:00
{
2014-06-24 12:49:18 +00:00
fix64 pkt_initial_timestamp ; // initial timestamp to see if packet is outdated
2022-09-24 17:47:53 +00:00
per_player_array < fix64 > pkt_timestamp ; // Packet timestamp
per_player_array < uint32_t > pkt_num ; // Packet number
2015-02-28 19:36:01 +00:00
sbyte used ;
2014-06-24 12:49:18 +00:00
ubyte Player_num ; // sender of this packet
2015-02-28 19:36:01 +00:00
uint16_t data_size ;
2022-07-16 15:26:12 +00:00
player_acknowledgement_mask player_ack ; // 0 if player has not ACK'd this packet, 1 if ACK'd or not connected
2020-05-02 21:18:42 +00:00
std : : array < uint8_t , UPID_MDATA_BUF_SIZE > data ; // extra data of a packet - contains all multibuf data we don't want to loose
2014-06-26 02:27:16 +00:00
} ;
2009-11-24 09:48:53 +00:00
2014-06-24 12:49:18 +00:00
// structure to keep track of MDATA packets we already got, which we expect from another player and the pkt_num for the next packet we want to send to another player
struct UDP_mdata_check : public prohibit_void_ptr < UDP_mdata_check >
2009-11-24 09:48:53 +00:00
{
2020-05-02 21:18:42 +00:00
std : : array < uint32_t , UDP_MDATA_STOR_QUEUE_SIZE > pkt_num ; // all those we got just recently, so we can ignore them if we get them again
2014-06-24 12:49:18 +00:00
int cur_slot ; // index we can use for a new pkt_num
uint32_t pkt_num_torecv ; // the next pkt_num we await for this player
uint32_t pkt_num_tosend ; // the next pkt_num we want to send to another player
2014-06-21 23:55:24 +00:00
} ;