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"
2009-11-24 09:48:53 +00:00
2012-11-11 22:12:51 +00:00
# ifdef __cplusplus
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"
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
{
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 ;
2020-12-20 20:39:07 +00:00
virtual void kick_player ( const _sockaddr & dump_addr , int 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 ) ;
2022-07-09 13:39:29 +00:00
void net_udp_send_data ( const uint8_t * ptr , unsigned len , multiplayer_data_priority priority ) ;
2017-01-10 05:02:59 +00:00
window_event_result net_udp_level_sync ( ) ;
2014-10-17 02:23:40 +00:00
void net_udp_send_mdata_direct ( const ubyte * data , int data_len , int pnum , int priority ) ;
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
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 ;
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
namespace dcx {
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
2014-06-24 12:49:18 +00:00
# define UDP_MDATA_STOR_QUEUE_SIZE 1024 // Store up to 1024 MDATA packets
# define UDP_MDATA_STOR_MIN_FREE_2JOIN 384 // have at least this many free packet slots before we let someone join the game
# 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_VERSION_DENY 1 // Netgame join or info has been denied due to version difference.
2011-11-02 00:04:38 +00:00
# define UPID_VERSION_DENY_SIZE 9
2011-04-12 22:19:46 +00:00
# define UPID_GAME_INFO_REQ 2 // Requesting all info about a netgame.
2011-11-02 00:04:38 +00:00
# define UPID_GAME_INFO_REQ_SIZE 13
2015-03-20 21:31:22 +00:00
# define UPID_GAME_INFO_LITE_REQ_SIZE 13
2011-04-12 22:19:46 +00:00
# define UPID_GAME_INFO 3 // Packet containing all info about a netgame.
# define UPID_GAME_INFO_LITE_REQ 4 // Requesting lite info about a netgame. Used for discovering games.
# define UPID_GAME_INFO_LITE 5 // Packet containing lite netgame info.
2015-02-21 17:21:34 +00:00
# define UPID_GAME_INFO_SIZE_MAX (sizeof(netgame_info))
# define UPID_GAME_INFO_LITE_SIZE_MAX (sizeof(UDP_netgame_info_lite))
2011-04-12 22:19:46 +00:00
# define UPID_DUMP 6 // Packet containing why player cannot join this game.
# define UPID_DUMP_SIZE 2
# define UPID_ADDPLAYER 7 // Packet from Host containing info about a new player.
# define UPID_REQUEST 8 // New player says: "I want to be inside of you!" (haha, sorry I could not resist) / Packet containing request to join the game actually.
# define UPID_QUIT_JOINING 9 // Packet from a player who suddenly quits joining.
2013-04-18 13:14:16 +00:00
# define UPID_SEQUENCE_SIZE (3 + (CALLSIGN_LEN+1))
2011-04-12 22:19:46 +00:00
# define UPID_SYNC 10 // Packet from host containing full netgame info to sync players up.
# define UPID_OBJECT_DATA 11 // Packet from host containing object buffer.
# define UPID_PING 12 // Packet from host containing his GameTime and the Ping list. Client returns this time to host as UPID_PONG and adapts the ping list.
# define UPID_PING_SIZE 37
# define UPID_PONG 13 // Packet answer from client to UPID_PING. Contains the time the initial ping packet was sent.
# define UPID_PONG_SIZE 10
# define UPID_ENDLEVEL_H 14 // Packet from Host to all Clients containing connect-states and kills information about everyone in the game.
# define UPID_ENDLEVEL_C 15 // Packet from Client to Host containing connect-state and kills information from this Client.
2012-03-29 08:15:58 +00:00
# define UPID_PDATA 16 // Packet from player containing his movement data.
2013-12-09 13:00:23 +00:00
# define UPID_PDATA_SIZE 49
2012-03-29 08:15:58 +00:00
# define UPID_MDATA_PNORM 17 // Packet containing multi buffer from a player. Priority 0,1 - no ACK needed.
# define UPID_MDATA_PNEEDACK 18 // Packet containing multi buffer from a player. Priority 2 - ACK needed. Also contains pkt_num
# define UPID_MDATA_ACK 19 // ACK packet for UPID_MDATA_P1.
2011-04-12 22:19:46 +00:00
# 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.
# define UPID_TRACKER_GAMEINFO 24 // Packet containing info about a game
2016-11-02 03:20:41 +00:00
# define UPID_TRACKER_ACK 25 // An ACK packet from the tracker
# define UPID_TRACKER_HOLEPUNCH 26 // Hole punching process. Sent from client to tracker to request hole punching from game host and received by host from tracker to initiate hole punching to requesting client
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 ;
2016-11-02 03:20:41 +00:00
uint16_t TrackerGameID ;
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
} ;
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
2020-05-02 21:18:42 +00:00
std : : array < fix64 , MAX_PLAYERS > pkt_timestamp ; // Packet timestamp
std : : array < uint32_t , MAX_PLAYERS > 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 ;
2020-05-02 21:18:42 +00:00
std : : array < uint8_t , MAX_PLAYERS > player_ack ; // 0 if player has not ACK'd this packet, 1 if ACK'd or not connected
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
} ;
2012-11-11 22:12:51 +00:00
# endif