1#ifndef ASTEROIDS_NET_MULTIPLAYER_HPP
2#define ASTEROIDS_NET_MULTIPLAYER_HPP
61 std::array<NetworkProjectile, NETWORK_PROJECTILE_COUNT>
projectiles{};
62 std::array<NetworkAsteroid, NETWORK_ASTEROID_COUNT>
asteroids{};
63 std::array<std::uint32_t, NETWORK_PLAYER_COUNT>
kills{};
85 std::vector<NetworkPlayerUpdate>
players{};
106 void host(
const std::string &port,
const std::string &player_name);
114 void join(
const std::string &address,
const std::string &port,
const std::string &player_name,
const std::string &
join_code);
126 [[nodiscard]]
bool active()
const;
130 [[nodiscard]]
bool is_host()
const;
136 [[nodiscard]]
const std::array<std::string, NETWORK_PLAYER_COUNT> &
player_names()
const;
138 [[nodiscard]]
const std::array<bool, NETWORK_PLAYER_COUNT> &
player_connected()
const;
140 [[nodiscard]]
const std::string &
join_code()
const;
146 std::uint32_t magic = 0x4D584E54U;
147 std::uint16_t version = 2;
148 std::uint16_t size =
sizeof(Packet);
149 std::uint32_t sequence = 0;
150 std::uint8_t player_id = 0xFFU;
151 std::uint8_t assigned_player_id = 0xFFU;
152 std::uint8_t connected_mask = 0;
154 std::array<char, 32> player_name{};
157 static_assert(
sizeof(Packet) <= 1200,
"Multiplayer UDP packet must stay below the conservative MTU payload budget");
159 mxnetwork::MXNetworkInit network_init{};
160 mxnetwork::Socket socket{};
161 bool session_active =
false;
162 bool host_role =
false;
164 mxnetwork::SocketAddress address{};
165 NetworkState state{};
167 std::uint32_t receive_sequence = 0;
168 float idle_seconds = 0.0f;
169 bool connected =
false;
171 std::array<Peer, NETWORK_PLAYER_COUNT> peers{};
172 std::array<std::string, NETWORK_PLAYER_COUNT> names{};
173 std::array<bool, NETWORK_PLAYER_COUNT> connected_players{};
174 std::uint8_t assigned_player_id = 0xFFU;
175 float send_accumulator = 0.0f;
176 std::uint32_t send_sequence = 0;
177 std::string local_player_name{};
178 std::string session_join_code{};
179 std::unique_ptr<PortMapping> port_mapping{};
181 void send_client_state(
const NetworkState &state);
182 void send_host_relay(std::uint8_t source_player, std::uint8_t destination_player);
183 std::optional<std::uint8_t> find_or_assign_peer(
const mxnetwork::SocketAddress &address);
MultiplayerSession()
Initializes the networking subsystem.
void host(const std::string &port, const std::string &player_name)
Starts hosting a session.
MultiplayerSession & operator=(const MultiplayerSession &)=delete
MultiplayerSession(const MultiplayerSession &)=delete
~MultiplayerSession()
Stops the session and releases networking resources.
void join(const std::string &address, const std::string &port, const std::string &player_name, const std::string &join_code)
Joins a hosted session.
bool is_host() const
Returns whether this session is the host.
NetworkExchange exchange(const NetworkState &local_state, float delta_time)
Sends local state and receives remote updates.
bool connected() const
Returns whether the local player has an established peer connection.
const std::array< bool, NETWORK_PLAYER_COUNT > & player_connected() const
Returns connection flags indexed by player slot.
void stop()
Stops the active host or client session.
bool active() const
Returns whether a host or client session is active.
std::uint8_t local_player_id() const
Returns the assigned local player slot.
std::size_t player_count() const
Returns the number of connected players.
const std::string & port_mapping_status() const
Returns the automatic router port-mapping status.
const std::array< std::string, NETWORK_PLAYER_COUNT > & player_names() const
Returns display names indexed by player slot.
const std::string & join_code() const
Returns the session join code.
Owns an automatically created UPnP or NAT-PMP port mapping.
constexpr std::size_t NETWORK_ASTEROID_COUNT
Maximum asteroid snapshots carried in one network state.
constexpr std::size_t NETWORK_PLAYER_COUNT
Maximum number of players in a session.
constexpr std::size_t NETWORK_PROJECTILE_COUNT
Maximum projectile snapshots carried in one network state.
Serialized gameplay state for one asteroid.
std::uint8_t slot
Source asteroid slot.
std::array< float, 3 > position
World-space position.
std::array< float, 3 > rotation
Euler rotation in degrees.
float radius
Collision radius.
std::uint8_t active
Nonzero when the asteroid is active.
Collection of remote player updates produced by one exchange tick.
std::vector< NetworkPlayerUpdate > players
Updates received during the tick.
State received for a specific player slot.
std::uint8_t player_id
Player slot owning the state.
NetworkState state
Most recently received state.
Serialized gameplay state for one projectile.
std::uint8_t active
Nonzero when the projectile is active.
float lifetime
Remaining lifetime in seconds.
std::array< float, 3 > velocity
World-space velocity.
std::array< float, 3 > position
World-space position.
Complete replicated gameplay state published by one player.
std::uint8_t exploding
Nonzero while the ship is exploding.
std::array< std::uint32_t, NETWORK_PLAYER_COUNT > consumed_projectile_ids
Last consumed projectile per player.
std::array< std::uint32_t, NETWORK_PLAYER_COUNT > kills
Kill counters by player slot.
std::array< float, 3 > rotation
Ship Euler rotation in degrees.
std::array< NetworkAsteroid, NETWORK_ASTEROID_COUNT > asteroids
Host-authoritative asteroids.
std::array< std::uint32_t, NETWORK_PLAYER_COUNT > death_serials
Monotonic death events by player slot.
std::array< NetworkProjectile, NETWORK_PROJECTILE_COUNT > projectiles
Locally owned projectiles.
std::array< float, 3 > position
Ship world-space position.
float current_speed
Ship forward speed.
std::uint8_t winner
Winning player identifier, or zero if unset.
std::uint8_t match_started
Nonzero after the host starts the match.