Allow using real addon karts in networking

This commit is contained in:
Benau 2022-09-10 15:49:21 +08:00
parent 39e3c189da
commit ebd380c0bc
22 changed files with 272 additions and 21 deletions

View File

@ -580,5 +580,6 @@
<capabilities name="report_player"/>
<capabilities name="soccer_fixes"/>
<capabilities name="ranking_changes"/>
<capabilities name="real_addon_karts"/>
</network-capabilities>
</config>

View File

@ -46,7 +46,8 @@ AbstractKart::AbstractKart(const std::string& ident,
: Moveable()
{
m_world_kart_id = world_kart_id;
loadKartProperties(ident, handicap, ri);
const RemoteKartInfo& rki = RaceManager::get()->getKartInfo(m_world_kart_id);
loadKartProperties(ident, handicap, ri, rki.getKartData());
} // AbstractKart
// ----------------------------------------------------------------------------
@ -78,12 +79,14 @@ void AbstractKart::reset()
// ----------------------------------------------------------------------------
void AbstractKart::loadKartProperties(const std::string& new_ident,
HandicapLevel handicap,
std::shared_ptr<GE::GERenderInfo> ri)
std::shared_ptr<GE::GERenderInfo> ri,
const KartData& kart_data)
{
m_kart_properties.reset(new KartProperties());
KartProperties* tmp_kp = NULL;
const KartProperties* kp = kart_properties_manager->getKart(new_ident);
const KartProperties* kp_addon = NULL;
const KartProperties* official_kp = NULL;
bool new_hitbox = false;
Vec3 gravity_shift;
if (NetworkConfig::get()->isNetworking() &&
NetworkConfig::get()->useTuxHitboxAddon() && kp && kp->isAddon())
@ -106,16 +109,38 @@ void AbstractKart::loadKartProperties(const std::string& new_ident,
kp = kart_properties_manager->getKart(std::string("tux"));
if (NetworkConfig::get()->isNetworking() && official_kart)
{
official_kp = OfficialKarts::getKartByIdent(new_ident,
&m_kart_width, &m_kart_height, &m_kart_length, &gravity_shift);
const KartProperties* official_kp = OfficialKarts::getKartByIdent(
new_ident, &m_kart_width, &m_kart_height, &m_kart_length,
&gravity_shift);
if (official_kp)
{
kp = official_kp;
new_hitbox = true;
}
}
}
if (NetworkConfig::get()->isNetworking() &&
!kart_data.m_kart_type.empty() &&
kart_properties_manager->hasKartTypeCharacteristic(
kart_data.m_kart_type))
{
tmp_kp = new KartProperties();
tmp_kp->copyFrom(kp);
tmp_kp->initKartWithDifferentType(kart_data.m_kart_type);
kp = tmp_kp;
m_kart_width = kart_data.m_width;
m_kart_height = kart_data.m_height;
m_kart_length = kart_data.m_length;
gravity_shift = kart_data.m_gravity_shift;
new_hitbox = true;
}
m_kart_properties->copyForPlayer(kp, handicap);
if (kp_addon)
m_kart_properties->adjustForOnlineAddonKart(kp_addon);
if (official_kp)
if (new_hitbox)
{
m_kart_properties->updateForOnlineKart(new_ident, gravity_shift,
m_kart_length);
@ -136,7 +161,7 @@ void AbstractKart::loadKartProperties(const std::string& new_ident,
m_kart_model.reset(kp_addon->getKartModelCopy(ri));
else
m_kart_model.reset(m_kart_properties->getKartModelCopy(ri));
if (official_kp == NULL)
if (!new_hitbox)
{
m_kart_width = kp->getMasterKartModel().getWidth();
m_kart_height = kp->getMasterKartModel().getHeight();
@ -144,18 +169,20 @@ void AbstractKart::loadKartProperties(const std::string& new_ident,
}
m_kart_highest_point = m_kart_model->getHighestPoint();
m_wheel_graphics_position = m_kart_model->getWheelsGraphicsPosition();
delete tmp_kp;
} // loadKartProperties
// ----------------------------------------------------------------------------
void AbstractKart::changeKart(const std::string& new_ident,
HandicapLevel handicap,
std::shared_ptr<GE::GERenderInfo> ri)
std::shared_ptr<GE::GERenderInfo> ri,
const KartData& kart_data)
{
// Reset previous kart (including delete old animation above)
reset();
// Remove kart body
Physics::get()->removeKart(this);
loadKartProperties(new_ident, handicap, ri);
loadKartProperties(new_ident, handicap, ri, kart_data);
} // changeKart
// ----------------------------------------------------------------------------

View File

@ -81,7 +81,8 @@ private:
// ------------------------------------------------------------------------
void loadKartProperties(const std::string& new_ident,
HandicapLevel handicap,
std::shared_ptr<GE::GERenderInfo> ri);
std::shared_ptr<GE::GERenderInfo> ri,
const KartData& kart_data);
protected:
btTransform m_starting_transform;
@ -144,7 +145,8 @@ public:
/** Change to new kart instancely (used in network live join). */
virtual void changeKart(const std::string& new_ident,
HandicapLevel handicap,
std::shared_ptr<GE::GERenderInfo> ri);
std::shared_ptr<GE::GERenderInfo> ri,
const KartData& kart_data = KartData());
// ========================================================================
// Access to the handicap.
// ------------------------------------------------------------------------

View File

@ -223,9 +223,10 @@ void Kart::initSound()
// ----------------------------------------------------------------------------
void Kart::changeKart(const std::string& new_ident,
HandicapLevel handicap,
std::shared_ptr<GE::GERenderInfo> ri)
std::shared_ptr<GE::GERenderInfo> ri,
const KartData& kart_data)
{
AbstractKart::changeKart(new_ident, handicap, ri);
AbstractKart::changeKart(new_ident, handicap, ri, kart_data);
m_kart_model->setKart(this);
scene::ISceneNode* old_node = m_node;

View File

@ -338,7 +338,8 @@ public:
virtual void setXYZ(const Vec3& a) OVERRIDE;
virtual void changeKart(const std::string& new_ident,
HandicapLevel handicap,
std::shared_ptr<GE::GERenderInfo> ri) OVERRIDE;
std::shared_ptr<GE::GERenderInfo> ri,
const KartData& kart_data = KartData()) OVERRIDE;
// ========================================================================================
// SPEED and speed-boost related functions

View File

@ -416,6 +416,7 @@ void KartProperties::adjustForOnlineAddonKart(const KartProperties* source)
m_icon_material = source->m_icon_material;
m_minimap_icon = source->m_minimap_icon;
m_engine_sfx_type = source->m_engine_sfx_type;
m_skid_sound = source->m_skid_sound;
m_color = source->m_color;
} // adjustForOnlineAddonKart
@ -430,6 +431,14 @@ void KartProperties::combineCharacteristics(HandicapLevel handicap)
RaceManager::get()->getDifficulty())));
// Try to get the kart type
if (!kart_properties_manager->hasKartTypeCharacteristic(m_kart_type))
{
Log::warn("KartProperties",
"Can't find kart type '%s' for kart '%s', defaulting to '%s'.",
m_kart_type.c_str(), m_name.c_str(),
kart_properties_manager->getDefaultKartType().c_str());
m_kart_type = kart_properties_manager->getDefaultKartType();
}
const AbstractCharacteristic *characteristic = kart_properties_manager->
getKartTypeCharacteristic(m_kart_type, m_name);

View File

@ -233,6 +233,12 @@ public:
bool isInGroup (const std::string &group) const;
bool operator<(const KartProperties &other) const;
// ------------------------------------------------------------------------
void initKartWithDifferentType(const std::string& type)
{
m_kart_type = type;
combineCharacteristics(HANDICAP_NONE);
}
// ------------------------------------------------------------------------
/** Returns the characteristics for this kart. */
const AbstractCharacteristic* getCharacteristic() const;

View File

@ -329,9 +329,9 @@ const AbstractCharacteristic* KartPropertiesManager::getKartTypeCharacteristic(c
if (!type_is_valid)
Log::warn("KartProperties", "Can't find kart type '%s' for kart '%s', defaulting to '%s'.",
type.c_str(), name.c_str(), m_kart_types[0].c_str());
type.c_str(), name.c_str(), getDefaultKartType().c_str());
std::string valid_type = (type_is_valid) ? type : m_kart_types[0];
const std::string& valid_type = (type_is_valid) ? type : getDefaultKartType();
std::map<std::string, std::unique_ptr<AbstractCharacteristic> >::const_iterator
it = m_kart_type_characteristics.find(valid_type);

View File

@ -112,6 +112,14 @@ public:
/** Get a characteristic that holds the values for a kart type. */
const AbstractCharacteristic* getKartTypeCharacteristic(const std::string &type, const std::string &name) const;
// ------------------------------------------------------------------------
const std::string& getDefaultKartType() const { return m_kart_types[0]; }
// ------------------------------------------------------------------------
bool hasKartTypeCharacteristic(const std::string& type) const
{
return m_kart_type_characteristics.find(type) !=
m_kart_type_characteristics.end();
}
// ------------------------------------------------------------------------
/** Get a characteristic that holds the values for a player difficulty. */
const AbstractCharacteristic* getPlayerCharacteristic(const std::string &type) const;
// ------------------------------------------------------------------------

54
src/network/kart_data.cpp Normal file
View File

@ -0,0 +1,54 @@
#include "network/kart_data.hpp"
#include "karts/kart_model.hpp"
#include "karts/kart_properties.hpp"
#include "network/network_string.hpp"
// ----------------------------------------------------------------------------
KartData::KartData(const KartProperties* kp)
{
m_kart_type = kp->getKartType();
if (!m_kart_type.empty())
{
m_width = kp->getMasterKartModel().getWidth();
m_height = kp->getMasterKartModel().getHeight();
m_length = kp->getMasterKartModel().getLength();
m_gravity_shift = kp->getGravityCenterShift();
}
else
{
m_width = 0.0f;
m_height = 0.0f;
m_length = 0.0f;
}
} // KartData(KartProperties*)
// ----------------------------------------------------------------------------
KartData::KartData(const BareNetworkString& ns)
{
ns.decodeString(&m_kart_type);
if (!m_kart_type.empty())
{
m_width = ns.getFloat();
m_height = ns.getFloat();
m_length = ns.getFloat();
m_gravity_shift = ns.getVec3();
}
else
{
m_width = 0.0f;
m_height = 0.0f;
m_length = 0.0f;
}
} // KartData(BareNetworkString&)
// ----------------------------------------------------------------------------
void KartData::encode(BareNetworkString* ns) const
{
ns->encodeString(m_kart_type);
if (!m_kart_type.empty())
{
ns->addFloat(m_width).addFloat(m_height).addFloat(m_length)
.add(m_gravity_shift);
}
} // encode(BareNetworkString*)

34
src/network/kart_data.hpp Normal file
View File

@ -0,0 +1,34 @@
#ifndef KART_DATA_HPP
#define KART_DATA_HPP
#include "utils/vec3.hpp"
#include <string>
class BareNetworkString;
class KartProperties;
class KartData
{
public:
std::string m_kart_type;
float m_width;
float m_height;
float m_length;
Vec3 m_gravity_shift;
// ------------------------------------------------------------------------
KartData()
{
m_width = 0.0f;
m_height = 0.0f;
m_length = 0.0f;
}
// ------------------------------------------------------------------------
KartData(const KartProperties* kp);
// ------------------------------------------------------------------------
KartData(const BareNetworkString& ns);
// ------------------------------------------------------------------------
void encode(BareNetworkString* ns) const;
}; // class KartData
#endif // KART_DATA_HPP

View File

@ -22,6 +22,7 @@
#ifndef HEADER_NETWORK_PLAYER_PROFILE
#define HEADER_NETWORK_PLAYER_PROFILE
#include "network/kart_data.hpp"
#include "utils/types.hpp"
#include "irrString.h"
@ -72,6 +73,7 @@ private:
/** 2-letter country code of player. */
std::string m_country_code;
KartData m_kart_data;
public:
// ------------------------------------------------------------------------
static std::shared_ptr<NetworkPlayerProfile>
@ -121,7 +123,11 @@ public:
uint32_t getHostId() const { return m_host_id; }
// ------------------------------------------------------------------------
/** Sets the kart name for this player. */
void setKartName(const std::string &kart_name) { m_kart_name = kart_name; }
void setKartName(const std::string &kart_name)
{
m_kart_name = kart_name;
m_kart_data = KartData();
}
// ------------------------------------------------------------------------
/** Returns the name of the kart this player has selected. */
const std::string &getKartName() const { return m_kart_name; }
@ -164,6 +170,10 @@ public:
KartTeam getTeam() const { return m_team.load(); }
// ------------------------------------------------------------------------
const std::string& getCountryCode() const { return m_country_code; }
// ------------------------------------------------------------------------
void setKartData(const KartData& data) { m_kart_data = data; }
// ------------------------------------------------------------------------
const KartData& getKartData() const { return m_kart_data; }
}; // class NetworkPlayerProfile
#endif // HEADER_NETWORK_PLAYER_PROFILE

View File

@ -252,6 +252,22 @@ bool ClientLobby::notifyEventAsynchronous(Event* event)
return true;
} // notifyEventAsynchronous
//-----------------------------------------------------------------------------
void ClientLobby::getPlayersAddonKartType(const BareNetworkString& data,
std::vector<std::shared_ptr<NetworkPlayerProfile> >& players) const
{
if (NetworkConfig::get()->getServerCapabilities().find(
"real_addon_karts") ==
NetworkConfig::get()->getServerCapabilities().end() ||
data.size() == 0)
return;
for (unsigned i = 0; i < players.size(); i++)
{
KartData kart_data(data);
players[i]->setKartData(kart_data);
}
} // getPlayersAddonKartType
//-----------------------------------------------------------------------------
void ClientLobby::addAllPlayers(Event* event)
{
@ -316,6 +332,7 @@ void ClientLobby::addAllPlayers(Event* event)
unsigned flag_deactivated_time = data.getUInt16();
RaceManager::get()->setFlagDeactivatedTicks(flag_deactivated_time);
}
getPlayersAddonKartType(data, players);
configRemoteKart(players, isSpectator() ? 1 :
(int)NetworkConfig::get()->getNetworkPlayers().size());
loadWorld();
@ -1307,6 +1324,7 @@ void ClientLobby::liveJoinAcknowledged(Event* event)
// player connection or disconnection
std::vector<std::shared_ptr<NetworkPlayerProfile> > players =
decodePlayers(data);
getPlayersAddonKartType(data, players);
w->resetElimination();
for (unsigned i = 0; i < players.size(); i++)
{
@ -1389,6 +1407,12 @@ void ClientLobby::handleKartInfo(Event* event)
data.decodeString(&kart_name);
std::string country_code;
data.decodeString(&country_code);
KartData kart_data;
if (NetworkConfig::get()->getServerCapabilities().find(
"real_addon_karts") !=
NetworkConfig::get()->getServerCapabilities().end() &&
data.size() > 0)
kart_data = KartData(data);
RemoteKartInfo& rki = RaceManager::get()->getKartInfo(kart_id);
rki.setPlayerName(player_name);
@ -1399,6 +1423,7 @@ void ClientLobby::handleKartInfo(Event* event)
rki.setLocalPlayerId(local_id);
rki.setKartName(kart_name);
rki.setCountryCode(country_code);
rki.setKartData(kart_data);
addLiveJoiningKart(kart_id, rki, live_join_util_ticks);
core::stringw msg;

View File

@ -148,6 +148,8 @@ private:
decodePlayers(const BareNetworkString& data,
std::shared_ptr<STKPeer> peer = nullptr,
bool* is_spectator = NULL) const;
void getPlayersAddonKartType(const BareNetworkString& data,
std::vector<std::shared_ptr<NetworkPlayerProfile> >& players) const;
void getKartsTracksNetworkString(BareNetworkString* ns);
void doInstallAddonsPack();
public:

View File

@ -153,6 +153,7 @@ void LobbyProtocol::configRemoteKart(
if (RaceManager::get()->teamEnabled())
rki.setKartTeam(profile->getTeam());
rki.setCountryCode(profile->getCountryCode());
rki.setKartData(profile->getKartData());
rki.setNetworkPlayerProfile(profile);
// Inform the race manager about the data for this kart.
RaceManager::get()->setPlayerKart(i, rki);
@ -236,7 +237,8 @@ void LobbyProtocol::addLiveJoiningKart(int kart_id, const RemoteKartInfo& rki,
std::make_shared<GE::GERenderInfo>(1.0f) :
rki.getKartTeam() == KART_TEAM_BLUE ?
std::make_shared<GE::GERenderInfo>(0.66f) :
std::make_shared<GE::GERenderInfo>(rki.getDefaultKartColor()));
std::make_shared<GE::GERenderInfo>(rki.getDefaultKartColor()),
rki.getKartData());
k->setLiveJoinKart(live_join_util_ticks);
World::getWorld()->initTeamArrows(k);
if (!k->getController()->isLocalPlayerController())

View File

@ -1736,6 +1736,8 @@ NetworkString* ServerLobby::getLoadWorldMessage(
ServerConfig::m_flag_deactivated_time);
load_world_message->addUInt16(flag_deactivated_time);
}
for (unsigned i = 0; i < players.size(); i++)
players[i]->getKartData().encode(load_world_message);
return load_world_message;
} // getLoadWorldMessage
@ -2065,6 +2067,8 @@ void ServerLobby::finishedLoadingLiveJoinClient(Event* event)
std::vector<std::shared_ptr<NetworkPlayerProfile> > players =
getLivePlayers();
encodePlayers(ns, players);
for (unsigned i = 0; i < players.size(); i++)
players[i]->getKartData().encode(ns);
}
m_peers_ready[peer] = false;
@ -5337,6 +5341,35 @@ void ServerLobby::setPlayerKarts(const NetworkString& ns, STKPeer* peer) const
peer->getPlayerProfiles()[i]->setKartName(kart);
}
}
if (peer->getClientCapabilities().find("real_addon_karts") ==
peer->getClientCapabilities().end() || ns.size() == 0)
return;
for (unsigned i = 0; i < player_count; i++)
{
KartData kart_data(ns);
std::string type = kart_data.m_kart_type;
auto& player = peer->getPlayerProfiles()[i];
const std::string& kart_id = player->getKartName();
if (NetworkConfig::get()->useTuxHitboxAddon() &&
StringUtils::startsWith(kart_id, "addon_") &&
kart_properties_manager->hasKartTypeCharacteristic(type))
{
const KartProperties* real_addon =
kart_properties_manager->getKart(kart_id);
if (ServerConfig::m_real_addon_karts && real_addon)
{
kart_data = KartData(real_addon);
}
else
{
const KartProperties* tux_kp =
kart_properties_manager->getKart("tux");
kart_data = KartData(tux_kp);
kart_data.m_kart_type = type;
}
player->setKartData(kart_data);
}
}
} // setPlayerKarts
//-----------------------------------------------------------------------------
@ -5368,6 +5401,9 @@ void ServerLobby::handleKartInfo(Event* event)
.addUInt32(rki.getOnlineId()).addUInt8(rki.getHandicap())
.addUInt8((uint8_t)rki.getLocalPlayerId())
.encodeString(rki.getKartName()).encodeString(rki.getCountryCode());
if (peer->getClientCapabilities().find("real_addon_karts") !=
peer->getClientCapabilities().end())
rki.getKartData().encode(ns);
peer->sendPacket(ns, true/*reliable*/);
delete ns;
} // handleKartInfo

View File

@ -30,5 +30,6 @@ void RemoteKartInfo::copyFrom(std::shared_ptr<NetworkPlayerProfile> p,
m_default_kart_color = p->getDefaultKartColor();
m_online_id = p->getOnlineId();
m_country_code = p->getCountryCode();
m_kart_data = p->getKartData();
m_profile = p;
} // copyFrom

View File

@ -22,6 +22,8 @@
#ifndef HEADER_REMOTE_KART_INFO_HPP
#define HEADER_REMOTE_KART_INFO_HPP
#include "network/kart_data.hpp"
#include <limits>
#include <memory>
#include <string>
@ -59,6 +61,7 @@ class RemoteKartInfo
uint32_t m_online_id;
std::string m_country_code;
std::weak_ptr<NetworkPlayerProfile> m_profile;
KartData m_kart_data;
public:
RemoteKartInfo(int player_id, const std::string& kart_name,
const irr::core::stringw& user_name, uint32_t host_id,
@ -107,6 +110,8 @@ public:
uint32_t getOnlineId() const { return m_online_id; }
void setCountryCode(const std::string& id) { m_country_code = id; }
const std::string& getCountryCode() const { return m_country_code; }
void setKartData(const KartData& data) { m_kart_data = data; }
const KartData& getKartData() const { return m_kart_data; }
void setNetworkPlayerProfile(
std::weak_ptr<NetworkPlayerProfile> npp) { m_profile = npp; }
std::weak_ptr<NetworkPlayerProfile> getNetworkPlayerProfile() const

View File

@ -273,6 +273,13 @@ namespace ServerConfig
"will be made 1.0. If false addon karts will use their original "
"hitbox other than tux, all players having it restriction applies."));
SERVER_CFG_PREFIX BoolServerConfigParam m_real_addon_karts
SERVER_CFG_DEFAULT(BoolServerConfigParam(true, "real-addon-karts",
"If true, server will send its addon karts real phyics (kart size, "
"length, type, etc) to client. If false or client chooses an addon "
"kart which server is missing, tux's kart physics and kart type of "
"the original addon is sent."));
SERVER_CFG_PREFIX FloatServerConfigParam m_flag_return_timeout
SERVER_CFG_DEFAULT(FloatServerConfigParam(20.0f, "flag-return-timeout",
"Time in seconds when a flag is dropped a by player in CTF "

View File

@ -882,9 +882,11 @@ void KartSelectionScreen::updateKartStats(uint8_t widget_id,
const KartProperties *kp =
kart_properties_manager->getKart(selection);
NetworkConfig* nc = NetworkConfig::get();
// Adjust for online addon karts
if (kp && kp->isAddon() && NetworkConfig::get()->isNetworking() &&
NetworkConfig::get()->useTuxHitboxAddon())
if (kp && kp->isAddon() && nc->isNetworking() && nc->useTuxHitboxAddon() &&
nc->getServerCapabilities().find(
"real_addon_karts") == nc->getServerCapabilities().end())
kp = kart_properties_manager->getKart("tux");
if (kp != NULL)
{

View File

@ -19,6 +19,8 @@
#include "config/user_config.hpp"
#include "guiengine/widgets/progress_bar_widget.hpp"
#include "karts/kart_properties.hpp"
#include "karts/kart_properties_manager.hpp"
#include "input/device_manager.hpp"
#include "network/network_config.hpp"
#include "network/network_string.hpp"
@ -137,6 +139,22 @@ void NetworkKartSelectionScreen::allPlayersDone()
// kart
kart.encodeString(m_kart_widgets[n].m_kart_internal_name);
}
NetworkConfig* nc = NetworkConfig::get();
if (nc->useTuxHitboxAddon() &&
nc->getServerCapabilities().find(
"real_addon_karts") != nc->getServerCapabilities().end())
{
for (unsigned n = 0; n < kart_count; n++)
{
KartData kart_data;
const KartProperties* kp = kart_properties_manager
->getKart(m_kart_widgets[n].m_kart_internal_name);
if (kp && kp->isAddon())
kart_data = KartData(kp);
kart_data.encode(&kart);
}
}
STKHost::get()->sendToServer(&kart, true);
// ---- Switch to assign mode