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.
|
|
|
|
*/
|
2013-12-16 23:44:34 +00:00
|
|
|
#pragma once
|
|
|
|
|
2022-07-30 17:42:59 +00:00
|
|
|
#include <span>
|
2017-06-25 20:46:03 +00:00
|
|
|
#include <type_traits>
|
2014-07-20 01:09:55 +00:00
|
|
|
#include "dxxerror.h"
|
2022-07-23 20:58:10 +00:00
|
|
|
#include "net_udp.h"
|
2013-12-16 23:44:34 +00:00
|
|
|
#include "object.h"
|
|
|
|
#include "powerup.h"
|
2014-05-24 00:20:30 +00:00
|
|
|
#include "serial.h"
|
2016-11-12 18:10:07 +00:00
|
|
|
#include "fwd-player.h"
|
2014-05-24 00:20:30 +00:00
|
|
|
|
|
|
|
#define _UNPACK_MULTIPLAYER_SERIAL_MESSAGE(A,...) A, ## __VA_ARGS__
|
|
|
|
#define DEFINE_MULTIPLAYER_SERIAL_MESSAGE(C,T,V,A) \
|
|
|
|
DEFINE_SERIAL_UDT_TO_MESSAGE(T,V, (multiplayer_command<C>(), _UNPACK_MULTIPLAYER_SERIAL_MESSAGE A)); \
|
|
|
|
ASSERT_SERIAL_UDT_MESSAGE_SIZE(T, command_length<C>::value)
|
2013-12-16 23:44:34 +00:00
|
|
|
|
|
|
|
#define define_multiplayer_command(NAME,SIZE) NAME,
|
|
|
|
|
|
|
|
#if defined(DXX_BUILD_DESCENT_I) || defined(DXX_BUILD_DESCENT_II)
|
|
|
|
#define for_each_multiplayer_command(VALUE) \
|
2018-03-31 21:53:01 +00:00
|
|
|
VALUE(MULTI_POSITION , 1 + quaternionpos::packed_size::value) \
|
2013-12-16 23:44:34 +00:00
|
|
|
VALUE(MULTI_REAPPEAR , 4) \
|
2022-07-09 13:39:29 +00:00
|
|
|
VALUE(MULTI_FIRE , 17) \
|
|
|
|
VALUE(MULTI_FIRE_TRACK , 20) \
|
|
|
|
VALUE(MULTI_FIRE_BOMB , 19) \
|
2013-12-16 23:44:34 +00:00
|
|
|
VALUE(MULTI_REMOVE_OBJECT , 4) \
|
|
|
|
VALUE(MULTI_MESSAGE , 37) /* (MAX_MESSAGE_LENGTH = 40) */ \
|
|
|
|
VALUE(MULTI_QUIT , 2) \
|
2018-05-13 03:14:34 +00:00
|
|
|
VALUE(MULTI_PLAY_SOUND , 8) \
|
2013-12-16 23:44:34 +00:00
|
|
|
VALUE(MULTI_CONTROLCEN , 4) \
|
|
|
|
VALUE(MULTI_ROBOT_CLAIM , 5) \
|
|
|
|
VALUE(MULTI_CLOAK , 2) \
|
2016-11-12 18:10:08 +00:00
|
|
|
VALUE(MULTI_ENDLEVEL_START , DXX_MP_SIZE_ENDLEVEL_START) \
|
2013-12-16 23:44:34 +00:00
|
|
|
VALUE(MULTI_CREATE_EXPLOSION , 2) \
|
|
|
|
VALUE(MULTI_CONTROLCEN_FIRE , 16) \
|
|
|
|
VALUE(MULTI_CREATE_POWERUP , 19) \
|
|
|
|
VALUE(MULTI_DECLOAK , 2) \
|
2018-03-31 21:53:01 +00:00
|
|
|
VALUE(MULTI_ROBOT_POSITION , 5 + quaternionpos::packed_size::value) \
|
2013-12-16 23:44:34 +00:00
|
|
|
VALUE(MULTI_PLAYER_DERES , DXX_MP_SIZE_PLAYER_RELATED) \
|
|
|
|
VALUE(MULTI_DOOR_OPEN , DXX_MP_SIZE_DOOR_OPEN) \
|
2014-09-14 01:14:33 +00:00
|
|
|
VALUE(MULTI_ROBOT_EXPLODE , 7) \
|
2013-12-16 23:44:34 +00:00
|
|
|
VALUE(MULTI_ROBOT_RELEASE , 5) \
|
|
|
|
VALUE(MULTI_ROBOT_FIRE , 18) \
|
|
|
|
VALUE(MULTI_SCORE , 6) \
|
|
|
|
VALUE(MULTI_CREATE_ROBOT , 6) \
|
|
|
|
VALUE(MULTI_TRIGGER , 3) \
|
2014-05-24 00:20:30 +00:00
|
|
|
VALUE(MULTI_BOSS_TELEPORT , 5) \
|
|
|
|
VALUE(MULTI_BOSS_CLOAK , 3) \
|
|
|
|
VALUE(MULTI_BOSS_START_GATE , 3) \
|
|
|
|
VALUE(MULTI_BOSS_STOP_GATE , 3) \
|
|
|
|
VALUE(MULTI_BOSS_CREATE_ROBOT , 8) \
|
2013-12-16 23:44:34 +00:00
|
|
|
VALUE(MULTI_CREATE_ROBOT_POWERUPS, 27) \
|
|
|
|
VALUE(MULTI_HOSTAGE_DOOR , 7) \
|
|
|
|
VALUE(MULTI_SAVE_GAME , 2+24) /* (ubyte slot, uint id, char name[20]) */ \
|
|
|
|
VALUE(MULTI_RESTORE_GAME , 2+4) /* (ubyte slot, uint id) */ \
|
|
|
|
VALUE(MULTI_HEARTBEAT , 5) \
|
2016-11-12 18:10:07 +00:00
|
|
|
VALUE(MULTI_KILLGOALS , 1 + MAX_PLAYERS) \
|
2013-12-16 23:44:34 +00:00
|
|
|
VALUE(MULTI_DO_BOUNTY , 2) \
|
|
|
|
VALUE(MULTI_TYPING_STATE , 3) \
|
|
|
|
VALUE(MULTI_GMODE_UPDATE , 3) \
|
|
|
|
VALUE(MULTI_KILL_HOST , 7) \
|
|
|
|
VALUE(MULTI_KILL_CLIENT , 5) \
|
|
|
|
VALUE(MULTI_RANK , 3) \
|
2015-07-02 02:37:55 +00:00
|
|
|
VALUE(MULTI_DROP_WEAPON , 10) \
|
Improve vulcan/gauss pickup rules
- Change D1X to use D2X rules regarding Vulcan cannon pickup. The D1X
rules were confusing at best, and seem outright wrong in some ways.
- When a Vulcan cannon was picked up, it was treated as containing not
less than VULCAN_WEAPON_AMMO_AMOUNT rounds, regardless of what it
actually contained. D2X respected the actual contained count, even
when running in D1X emulation mode.
- In D1X single player, if the Vulcan cannon was not picked up, then
it could be treated as Vulcan ammo. If at least 1 unit of
ammunition was added to the player, the entire powerup would be
consumed, regardless of how much ammunition remained.
- In D2X single player, if the Vulcan cannon was not picked up, then
ammunition would be taken from it, but the powerup would only be
consumed if all its ammunition was taken.
- In D1X multiplayer, a player who already had a Vulcan cannon could
not get anything from touching a new cannon, and the cannon would
not be changed.
- In D2X multiplayer, a player who already had a Vulcan cannon could
take ammunition from the cannon, but the cannon could not be drained
below VULCAN_AMMO_AMOUNT. If the cannon had VULCAN_AMMO_AMOUNT or
less, then the player could not take ammunition. If the cannon had
more, the player could drain it to that level.
- Replace all that with a simplified version of the D2X rules:
- If the player does not have the cannon, the cannon is picked up
and removed from the mine. The player takes as much of its
ammunition as possible. If the cannon was well stocked, and the
player was nearly full, some ammunition will be lost. This is
unfortunate, but the game has always had this rule, and changing
it would require dropping one or more Vulcan Ammo packs to
represent the untaken ammunition.
- If the player already had that cannon, then the player takes as
much ammunition as the cannon has, while not exceeding the
ammunition cap. Other players, if any, are updated about how much
ammunition remains in the cannon. The cannon remains in the mine.
- Backport to D1X the network message for updating the contained
ammunition in a vulcan cannon. zico added the basic feature in
7684ce92, but only applied it to D2X. With the change to let D1X
multiplayer take ammunition from the cannon, D1X now needs the same
feature.
- Remove the special case to delete an empty cannon. Instead, let the
cannon remain in the mine without ammunition. This allows a player in
single player mode to leave behind a backup cannon, which could be
useful if the player is killed and wishes to rearm before returning to
the death site. Similarly, under the new rule that players in
multiplayer can drain the cannon down to 0 ammunition, this removal
allows the cannon to remain behind for someone else to take, rather
than allowing it to be deleted by a player who already had an instance
of it.
2022-02-05 13:30:56 +00:00
|
|
|
VALUE(MULTI_VULWPN_AMMO_ADJ , 6) \
|
2016-02-25 13:11:08 +00:00
|
|
|
VALUE(MULTI_PLAYER_INV , DXX_MP_SIZE_PLAYER_INVENTORY) \
|
2013-12-16 23:44:34 +00:00
|
|
|
D2X_MP_COMMANDS(VALUE) \
|
|
|
|
|
|
|
|
#if defined(DXX_BUILD_DESCENT_I)
|
2016-11-12 18:10:08 +00:00
|
|
|
#define DXX_MP_SIZE_ENDLEVEL_START 3
|
2013-12-16 23:44:34 +00:00
|
|
|
#define DXX_MP_SIZE_PLAYER_RELATED 58
|
2016-02-25 13:11:08 +00:00
|
|
|
#define DXX_MP_SIZE_PLAYER_INVENTORY 15
|
2013-12-16 23:44:34 +00:00
|
|
|
#define DXX_MP_SIZE_BEGIN_SYNC 37
|
|
|
|
#define DXX_MP_SIZE_DOOR_OPEN 4
|
|
|
|
#define D2X_MP_COMMANDS(VALUE)
|
|
|
|
#elif defined(DXX_BUILD_DESCENT_II)
|
2016-11-12 18:10:08 +00:00
|
|
|
#define DXX_MP_SIZE_ENDLEVEL_START 2
|
2020-08-01 18:29:01 +00:00
|
|
|
#define DXX_MP_SIZE_PLAYER_RELATED (98+10)
|
2016-02-25 13:11:08 +00:00
|
|
|
#define DXX_MP_SIZE_PLAYER_INVENTORY 21
|
2013-12-16 23:44:34 +00:00
|
|
|
#define DXX_MP_SIZE_BEGIN_SYNC 41
|
|
|
|
#define DXX_MP_SIZE_DOOR_OPEN 5
|
|
|
|
#define D2X_MP_COMMANDS(VALUE) \
|
|
|
|
VALUE(MULTI_MARKER , 55) \
|
2019-05-11 20:18:29 +00:00
|
|
|
VALUE(MULTI_GUIDED , 26) \
|
2019-07-16 04:00:50 +00:00
|
|
|
VALUE(MULTI_STOLEN_ITEMS , 1 + std::tuple_size<decltype(d_thief_unique_state::Stolen_items)>::value) \
|
2013-12-16 23:44:34 +00:00
|
|
|
VALUE(MULTI_WALL_STATUS , 6) /* send to new players */ \
|
2015-02-14 22:48:29 +00:00
|
|
|
VALUE(MULTI_SEISMIC , 5) \
|
2016-12-10 17:51:07 +00:00
|
|
|
VALUE(MULTI_LIGHT , 16) \
|
2013-12-16 23:44:34 +00:00
|
|
|
VALUE(MULTI_START_TRIGGER , 2) \
|
|
|
|
VALUE(MULTI_FLAGS , 6) \
|
|
|
|
VALUE(MULTI_DROP_BLOB , 2) \
|
|
|
|
VALUE(MULTI_SOUND_FUNCTION , 4) \
|
|
|
|
VALUE(MULTI_CAPTURE_BONUS , 2) \
|
|
|
|
VALUE(MULTI_GOT_FLAG , 2) \
|
2015-02-14 22:48:30 +00:00
|
|
|
VALUE(MULTI_DROP_FLAG , 8) \
|
2013-12-16 23:44:34 +00:00
|
|
|
VALUE(MULTI_FINISH_GAME , 2) \
|
|
|
|
VALUE(MULTI_ORB_BONUS , 3) \
|
|
|
|
VALUE(MULTI_GOT_ORB , 2) \
|
|
|
|
VALUE(MULTI_EFFECT_BLOWUP , 17) \
|
2019-06-27 03:26:20 +00:00
|
|
|
VALUE(MULTI_UPDATE_BUDDY_STATE, 7) \
|
2013-12-16 23:44:34 +00:00
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "dxxsconf.h"
|
|
|
|
|
2022-07-09 13:39:29 +00:00
|
|
|
namespace dcx {
|
|
|
|
enum class multiplayer_data_priority : uint8_t;
|
|
|
|
}
|
|
|
|
|
2016-08-28 22:41:47 +00:00
|
|
|
enum multiplayer_command_t : uint8_t
|
|
|
|
{
|
2013-12-16 23:44:34 +00:00
|
|
|
for_each_multiplayer_command(define_multiplayer_command)
|
|
|
|
};
|
|
|
|
|
|
|
|
template <multiplayer_command_t>
|
|
|
|
struct command_length;
|
|
|
|
#define define_command_length(NAME,SIZE) \
|
|
|
|
template <> \
|
2017-06-25 20:46:03 +00:00
|
|
|
struct command_length<NAME> : public std::integral_constant<unsigned, SIZE> {};
|
2013-12-16 23:44:34 +00:00
|
|
|
for_each_multiplayer_command(define_command_length);
|
|
|
|
|
2022-07-30 17:42:59 +00:00
|
|
|
namespace dcx {
|
|
|
|
|
2017-08-11 23:43:53 +00:00
|
|
|
template <multiplayer_command_t C>
|
|
|
|
struct multi_command : public std::array<uint8_t, command_length<C>::value>
|
|
|
|
{
|
2022-07-16 15:26:12 +00:00
|
|
|
constexpr multi_command()
|
|
|
|
{
|
|
|
|
this->front() = C;
|
|
|
|
}
|
2017-08-11 23:43:53 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
template <multiplayer_command_t C>
|
2022-07-16 15:26:12 +00:00
|
|
|
static inline void multi_send_data(const multi_command<C> &buf, const multiplayer_data_priority priority)
|
2017-08-11 23:43:53 +00:00
|
|
|
{
|
2022-07-23 20:58:10 +00:00
|
|
|
multi::dispatch->send_data(buf.data(), buf.size(), priority);
|
2017-08-11 23:43:53 +00:00
|
|
|
}
|
|
|
|
|
2014-05-24 00:20:30 +00:00
|
|
|
template <typename T>
|
2017-08-11 23:43:53 +00:00
|
|
|
static inline void multi_serialize_read(const uint8_t *const buf, T &t)
|
2014-05-24 00:20:30 +00:00
|
|
|
{
|
|
|
|
serial::reader::bytebuffer_t b(buf);
|
|
|
|
serial::process_buffer(b, t);
|
|
|
|
}
|
|
|
|
|
2022-07-30 17:42:59 +00:00
|
|
|
template <typename T, std::size_t Extent>
|
|
|
|
static inline void multi_serialize_read(const std::span<const uint8_t, Extent> buf, T &t)
|
|
|
|
{
|
|
|
|
multi_serialize_read(buf.data(), t);
|
|
|
|
}
|
|
|
|
|
2014-05-24 00:20:30 +00:00
|
|
|
template <typename T>
|
2022-07-09 13:39:29 +00:00
|
|
|
static inline void multi_serialize_write(const multiplayer_data_priority priority, const T &t)
|
2014-05-24 00:20:30 +00:00
|
|
|
{
|
2017-08-11 23:43:53 +00:00
|
|
|
constexpr size_t maximum_size = serial::message_type<T>::maximum_size;
|
2014-05-24 00:20:30 +00:00
|
|
|
uint8_t buf[maximum_size];
|
|
|
|
serial::writer::bytebuffer_t b(buf);
|
|
|
|
serial::process_buffer(b, t);
|
2022-07-23 20:58:10 +00:00
|
|
|
multi::dispatch->send_data(buf, maximum_size, priority);
|
2014-05-24 00:20:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <multiplayer_command_t C>
|
2016-08-28 22:41:47 +00:00
|
|
|
using multiplayer_command = serial::pad<1, static_cast<uint8_t>(C)>;
|
2015-07-25 23:10:45 +00:00
|
|
|
|
2022-07-30 17:42:59 +00:00
|
|
|
template <multiplayer_command_t C>
|
|
|
|
using multiplayer_rspan = std::span<const uint8_t, command_length<C>::value>;
|
|
|
|
|
|
|
|
template <multiplayer_command_t C>
|
|
|
|
static constexpr auto multi_subspan_first(const std::span<const uint8_t> &data)
|
|
|
|
{
|
|
|
|
return data.first<command_length<C>::value>();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace dsx {
|
|
|
|
|
2022-07-30 17:42:59 +00:00
|
|
|
void multi_do_robot_explode(const d_robot_info_array &Robot_info, multiplayer_rspan<MULTI_ROBOT_EXPLODE> buf);
|
2022-07-30 17:42:59 +00:00
|
|
|
void multi_do_create_robot(const d_robot_info_array &Robot_info, const d_vclip_array &Vclip, playernum_t pnum, multiplayer_rspan<MULTI_CREATE_ROBOT> buf);
|
2022-07-30 17:42:59 +00:00
|
|
|
void multi_do_claim_robot(playernum_t pnum, const multiplayer_rspan<MULTI_ROBOT_CLAIM> buf);
|
2022-07-30 17:42:59 +00:00
|
|
|
void multi_do_robot_position(playernum_t pnum, const multiplayer_rspan<MULTI_ROBOT_POSITION> buf);
|
2022-07-30 17:42:59 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-07-25 23:10:45 +00:00
|
|
|
#endif
|