diff --git a/src/items/flyable.cpp b/src/items/flyable.cpp index cef9dcfded6..5268f76d52c 100644 --- a/src/items/flyable.cpp +++ b/src/items/flyable.cpp @@ -664,58 +664,77 @@ void Flyable::moveToInfinity(bool set_moveable_trans) } // moveToInfinity // ---------------------------------------------------------------------------- -BareNetworkString* Flyable::saveState(std::vector* ru) + +FlyablePacket Flyable::saveState(std::vector* ru) { + FlyablePacket packet; + if (m_has_hit_something) - return NULL; + return packet; ru->push_back(getUniqueIdentity()); - BareNetworkString* buffer = new BareNetworkString(); - uint16_t ticks_since_thrown_animation = (m_ticks_since_thrown & 32767) | - (hasAnimation() ? 32768 : 0); - buffer->addUInt16(ticks_since_thrown_animation); + packet.ticks_since_thrown_animation = + (m_ticks_since_thrown & 32767) | (hasAnimation() ? 32768 : 0); + if (m_do_terrain_info) - buffer->addUInt32(m_compressed_gravity_vector); + packet.compressed_gravity_vector = m_compressed_gravity_vector; if (hasAnimation()) - m_animation->saveState(buffer); + { + AbstractKartAnimationPacket subpacket = m_animation->saveState(); + packet.animation = subpacket; + } else { - CompressNetworkBody::compress( - m_body.get(), m_motion_state.get(), buffer); + packet.compressed_network_body = CompressNetworkBody::compress( + m_body.get(), m_motion_state.get()); } - return buffer; -} // saveState + return packet; +} // saveState // ---------------------------------------------------------------------------- -void Flyable::restoreState(BareNetworkString *buffer, int count) + +void Flyable::restoreState(const FlyablePacket& packet, int count) { - uint16_t ticks_since_thrown_animation = buffer->getUInt16(); + // kimden: nonvirtual: in which cases there can be nothing? + if (!packet.ticks_since_thrown_animation.has_value()) + return; + + uint16_t ticks_since_thrown_animation = packet.ticks_since_thrown_animation.get_value(); bool has_animation_in_state = (ticks_since_thrown_animation >> 15 & 1) == 1; + if (m_do_terrain_info) - m_compressed_gravity_vector = buffer->getUInt32(); + { + // kimden: nonvirtual: what if there's no value + if (packet.compressed_gravity_vector.has_value()) + m_compressed_gravity_vector = packet.compressed_gravity_vector.get_value(); + } if (has_animation_in_state) { + // kimden: nonvirtual: what if there's no value + AbstractKartAnimationPacket subpacket; + if (packet.animation.has_value()) + subpacket = packet.animation.get_value(); + // At the moment we only have cannon animation for rubber ball if (!m_animation) { try { - CannonAnimation* ca = new CannonAnimation(this, buffer); + CannonAnimation* ca = new CannonAnimation(this, subpacket); setAnimation(ca); } - catch (const KartAnimationCreationException& kace) + catch (const std::exception& kace) { Log::error("Flyable", "Kart animation creation error: %s", kace.what()); - buffer->skip(kace.getSkippingOffset()); } } else - m_animation->restoreState(buffer); + m_animation->restoreState(subpacket); } else { @@ -725,8 +744,14 @@ void Flyable::restoreState(BareNetworkString *buffer, int count) // will set m_animation to null delete m_animation; } + + // kimden: nonvirtual: what if there's no value + CompressedNetworkBodyPacket subpacket; + if (packet.compressed_network_body.has_value()) + subpacket = packet.compressed_network_body.get_value(); + CompressNetworkBody::decompress( - buffer, m_body.get(), m_motion_state.get()); + subpacket, m_body.get(), m_motion_state.get()); m_transform = m_body->getWorldTransform(); } m_ticks_since_thrown = ticks_since_thrown_animation & 32767; diff --git a/src/items/flyable.hpp b/src/items/flyable.hpp index e2734f60bbf..5dd827a1adf 100644 --- a/src/items/flyable.hpp +++ b/src/items/flyable.hpp @@ -22,11 +22,14 @@ #ifndef HEADER_FLYABLE_HPP #define HEADER_FLYABLE_HPP +#define nonvirtual + #include "items/powerup_manager.hpp" #include "karts/moveable.hpp" #include "network/rewinder.hpp" #include "tracks/terrain_info.hpp" #include "utils/cpp2011.hpp" +#include "network/packet_types.hpp" #include namespace irr @@ -259,10 +262,9 @@ class Flyable : public Moveable, public TerrainInfo, // ------------------------------------------------------------------------ virtual void computeError() OVERRIDE; // ------------------------------------------------------------------------ - virtual BareNetworkString* saveState(std::vector* ru) - OVERRIDE; + nonvirtual FlyablePacket saveState(std::vector* ru); // ------------------------------------------------------------------------ - virtual void restoreState(BareNetworkString *buffer, int count) OVERRIDE; + nonvirtual void restoreState(const FlyablePacket& packet, int count); // ------------------------------------------------------------------------ /* Return true if still in game state, or otherwise can be deleted. */ bool hasServerState() const { return m_has_server_state; } diff --git a/src/items/item.cpp b/src/items/item.cpp index b08d87ead20..fd69228d6a1 100644 --- a/src/items/item.cpp +++ b/src/items/item.cpp @@ -28,6 +28,7 @@ #include "items/item_manager.hpp" #include "karts/abstract_kart.hpp" #include "modes/world.hpp" +#include "network/packet_types.hpp" #include "network/network_string.hpp" #include "network/rewind_manager.hpp" #include "tracks/arena_graph.hpp" @@ -67,21 +68,21 @@ ItemState::ItemState(ItemType type, const AbstractKart *owner, int id) //----------------------------------------------------------------------------- /** Constructor to restore item state at current ticks in client for live join */ -ItemState::ItemState(const BareNetworkString& buffer) +ItemState::ItemState(const ItemStatePacket& packet) { - m_type = (ItemType)buffer.getUInt8(); - m_original_type = (ItemType)buffer.getUInt8(); - m_ticks_till_return = buffer.getUInt32(); - m_item_id = buffer.getUInt32(); - m_deactive_ticks = buffer.getUInt32(); - m_used_up_counter = buffer.getUInt32(); - m_xyz = buffer.getVec3(); - m_original_rotation = buffer.getQuat(); + m_type = (ItemType)packet.type; + m_original_type = (ItemType)packet.original_type; + m_ticks_till_return = packet.ticks_till_return; + m_item_id = packet.item_id; + m_deactive_ticks = packet.deactive_ticks; + m_used_up_counter = packet.used_up_counter; + m_xyz = packet.original_xyz_rotation.xyz; + m_original_rotation = packet.original_xyz_rotation.rotation; m_previous_owner = NULL; - int8_t kart_id = buffer.getUInt8(); + int8_t kart_id = packet.previous_owner; if (kart_id != -1) m_previous_owner = World::getWorld()->getKart(kart_id); -} // ItemState(const BareNetworkString& buffer) +} // ItemState(const ItemStatePacket& packet) // ------------------------------------------------------------------------ /** Sets the disappear counter depending on type. */ @@ -185,24 +186,31 @@ void ItemState::collected(const AbstractKart *kart) // ---------------------------------------------------------------------------- /** Returns the graphical type of this item should be using (takes nolok into * account). */ -Item::ItemType ItemState::getGrahpicalType() const +Item::ItemType ItemState::getGraphicalType() const { return m_previous_owner && m_previous_owner->getIdent() == "nolok" && getType() == ITEM_BUBBLEGUM ? ITEM_BUBBLEGUM_NOLOK : getType(); -} // getGrahpicalType +} // getGraphicalType //----------------------------------------------------------------------------- /** Save item state at current ticks in server for live join */ -void ItemState::saveCompleteState(BareNetworkString* buffer) const +ItemStatePacket ItemState::saveCompleteState() const { - buffer->addUInt8((uint8_t)m_type).addUInt8((uint8_t)m_original_type) - .addUInt32(m_ticks_till_return).addUInt32(m_item_id) - .addUInt32(m_deactive_ticks).addUInt32(m_used_up_counter) - .add(m_xyz).add(m_original_rotation) - .addUInt8(m_previous_owner ? - (int8_t)m_previous_owner->getWorldKartId() : (int8_t)-1); + ItemStatePacket packet; + packet.type = m_type; + packet.original_type = m_original_type; + packet.ticks_till_return = m_ticks_till_return; + packet.item_id = m_item_id; + packet.deactive_ticks = m_deactive_ticks; + packet.used_up_counter = m_used_up_counter; + packet.original_xyz_rotation.xyz = m_xyz; + packet.original_xyz_rotation.rotation = m_original_rotation; + packet.previous_owner = m_previous_owner ? + m_previous_owner->getWorldKartId() : -1; + + return packet; } // saveCompleteState // ============================================================================ @@ -228,7 +236,7 @@ Item::Item(ItemType type, const Vec3& xyz, const Vec3& normal, m_animation_start_ticks = -9999; m_distance_2 = 1.2f; initItem(type, xyz, normal); - m_graphical_type = getGrahpicalType(); + m_graphical_type = getGraphicalType(); m_node = NULL; if (mesh && !GUIEngine::isNoGraphics()) @@ -256,7 +264,7 @@ Item::Item(ItemType type, const Vec3& xyz, const Vec3& normal, m_appear_anime_node = irr_driver->getSceneManager()->addEmptySceneNode(m_node); } setType(type); - handleNewMesh(getGrahpicalType()); + handleNewMesh(getGraphicalType()); if (!m_node) return; @@ -442,10 +450,10 @@ void Item::updateGraphics(float dt) if (m_node == NULL) return; - if (m_graphical_type != getGrahpicalType()) + if (m_graphical_type != getGraphicalType()) { - handleNewMesh(getGrahpicalType()); - m_graphical_type = getGrahpicalType(); + handleNewMesh(getGraphicalType()); + m_graphical_type = getGraphicalType(); } auto& stk_config = STKConfig::get(); diff --git a/src/items/item.hpp b/src/items/item.hpp index 6e319cf4fd4..a91da4b2180 100644 --- a/src/items/item.hpp +++ b/src/items/item.hpp @@ -32,9 +32,9 @@ #include -class BareNetworkString; class AbstractKart; class LODNode; +class ItemStatePacket; namespace irr { @@ -145,9 +145,9 @@ class ItemState public: // ------------------------------------------------------------------------ - ItemState(ItemType type, const AbstractKart *owner=NULL, int id = -1); + ItemState(ItemType type, const AbstractKart *owner=NULL, int id = -1); // ------------------------------------------------------------------------ - ItemState(const BareNetworkString& buffer); + ItemState(const ItemStatePacket& packet); // ------------------------------------------------------------------------ void initItem(ItemType type, const Vec3& xyz, const Vec3& normal); void update(int ticks); @@ -266,7 +266,7 @@ class ItemState /** Returns the type of this item. */ ItemType getType() const { return m_type; } // ------------------------------------------------------------------------ - ItemType getGrahpicalType() const; + ItemType getGraphicalType() const; // ------------------------------------------------------------------------ /** Returns the original type of this item. */ ItemType getOriginalType() const { return m_original_type; } @@ -313,7 +313,7 @@ class ItemState return m_original_rotation; } // ------------------------------------------------------------------------ - void saveCompleteState(BareNetworkString* buffer) const; + ItemStatePacket saveCompleteState() const; }; // class ItemState // ============================================================================ diff --git a/src/items/network_item_manager.cpp b/src/items/network_item_manager.cpp index 63af067085d..d7d7fb56a5e 100644 --- a/src/items/network_item_manager.cpp +++ b/src/items/network_item_manager.cpp @@ -22,6 +22,7 @@ #include "modes/world.hpp" #include "network/network_config.hpp" #include "network/network_string.hpp" +#include "network/packet_types.hpp" #include "network/protocols/game_protocol.hpp" #include "network/rewind_manager.hpp" #include "network/stk_host.hpp" @@ -519,32 +520,36 @@ void NetworkItemManager::restoreState(BareNetworkString *buffer, int count) //----------------------------------------------------------------------------- /** Save all current items at current ticks in server for live join */ -void NetworkItemManager::saveCompleteState(BareNetworkString* buffer) const +NimCompleteStatePacket NetworkItemManager::saveCompleteState() const { + NimCompleteStatePacket packet; const uint32_t all_items = (uint32_t)m_all_items.size(); - buffer->addUInt32(World::getWorld()->getTicksSinceStart()) - .addUInt32(m_switch_ticks).addUInt32(all_items); + packet.ticks_since_start = World::getWorld()->getTicksSinceStart(); + packet.switch_ticks = m_switch_ticks; + packet.all_items_size = all_items; for (unsigned i = 0; i < all_items; i++) { + packet.all_items.emplace_back(); if (m_all_items[i]) { - buffer->addUInt8(1); - m_all_items[i]->saveCompleteState(buffer); + packet.all_items.back().has_item = true; + packet.all_items.back().item_state = m_all_items[i]->saveCompleteState(); } else - buffer->addUInt8(0); + packet.all_items.back().has_item = false; } + return packet; } // saveCompleteState //----------------------------------------------------------------------------- /** Restore all current items at current ticks in client for live join * or at the start of a race. */ -void NetworkItemManager::restoreCompleteState(const BareNetworkString& buffer) +void NetworkItemManager::restoreCompleteState(const NimCompleteStatePacket& packet) { - m_confirmed_state_time = buffer.getUInt32(); - m_confirmed_switch_ticks = buffer.getUInt32(); - uint32_t all_items = buffer.getUInt32(); + m_confirmed_state_time = packet.ticks_since_start; + m_confirmed_switch_ticks = packet.switch_ticks; + uint32_t all_items = packet.all_items_size; for (ItemState* is : m_confirmed_state) { delete is; @@ -552,10 +557,10 @@ void NetworkItemManager::restoreCompleteState(const BareNetworkString& buffer) m_confirmed_state.clear(); for (unsigned i = 0; i < all_items; i++) { - const bool has_item = buffer.getUInt8() == 1; + const bool has_item = packet.all_items[i].has_item; if (has_item) { - ItemState* is = new ItemState(buffer); + ItemState* is = new ItemState(packet.all_items[i].item_state.get_value()); m_confirmed_state.push_back(is); } else diff --git a/src/items/network_item_manager.hpp b/src/items/network_item_manager.hpp index 6fef68284e5..ed6dc5409e3 100644 --- a/src/items/network_item_manager.hpp +++ b/src/items/network_item_manager.hpp @@ -30,6 +30,9 @@ #include class STKPeer; +class NimCompleteStatePacket; + +#define nonvirtual /** \ingroup items * The network item manager is responsible for handling all network related @@ -81,9 +84,8 @@ class NetworkItemManager : public Rewinder, public ItemManager const AbstractKart *kart, const Vec3 *server_xyz = NULL, const Vec3 *server_normal = NULL) OVERRIDE; - virtual BareNetworkString* saveState(std::vector* ru) - OVERRIDE; - virtual void restoreState(BareNetworkString *buffer, int count) OVERRIDE; + nonvirtual BareNetworkString* saveState(std::vector* ru); + nonvirtual void restoreState(BareNetworkString *buffer, int count); // ------------------------------------------------------------------------ virtual void rewindToEvent(BareNetworkString *bns) OVERRIDE {}; // ------------------------------------------------------------------------ @@ -107,9 +109,9 @@ class NetworkItemManager : public Rewinder, public ItemManager m_last_confirmed_item_ticks.erase(peer); } // ------------------------------------------------------------------------ - void saveCompleteState(BareNetworkString* buffer) const; + NimCompleteStatePacket saveCompleteState() const; // ------------------------------------------------------------------------ - void restoreCompleteState(const BareNetworkString& buffer); + void restoreCompleteState(const NimCompleteStatePacket& packet); // ------------------------------------------------------------------------ void initServer(); diff --git a/src/items/plunger.cpp b/src/items/plunger.cpp index 0be206f73e4..b72dc125675 100644 --- a/src/items/plunger.cpp +++ b/src/items/plunger.cpp @@ -254,25 +254,36 @@ void Plunger::hitTrack() } // hitTrack // ---------------------------------------------------------------------------- -BareNetworkString* Plunger::saveState(std::vector* ru) +PlungerPacket Plunger::saveState(std::vector* ru) { - BareNetworkString* buffer = Flyable::saveState(ru); - if (!buffer) - return NULL; + PlungerPacket packet; + FlyablePacket subpacket = Flyable::saveState(ru); - buffer->addUInt16(m_keep_alive); + // kimden: it was checking before if BNS is null. + // Temporary solution is below. + if (!subpacket.ticks_since_thrown_animation.has_value()) + return packet; + + packet.flyable_packet = subpacket; + packet.keep_alive = m_keep_alive; + uint8_t state = 255; if (m_rubber_band) - buffer->addUInt8(m_rubber_band->get8BitState()); - else - buffer->addUInt8(255); - return buffer; + state = m_rubber_band->get8BitState(); + packet.rubber_band_state = state; + return packet; } // saveState // ---------------------------------------------------------------------------- -void Plunger::restoreState(BareNetworkString *buffer, int count) +void Plunger::restoreState(const PlungerPacket& packet, int count) { - Flyable::restoreState(buffer, count); - m_keep_alive = buffer->getUInt16(); + // kimden: nonvirtual: in which cases there can be nothing? + // I don't check the presence of other fields for now + // because they are supposed to be there too if flyable_packet is present. + if (!packet.flyable_packet.has_value()) + return; + + Flyable::restoreState(packet.flyable_packet.get_value(), count); + m_keep_alive = packet.keep_alive.get_value(); // Restore position base on m_keep_alive in Plunger::hit if (m_keep_alive == -1) m_moved_to_infinity = false; @@ -282,7 +293,7 @@ void Plunger::restoreState(BareNetworkString *buffer, int count) m_moved_to_infinity = true; } - uint8_t bit_state = buffer->getUInt8(); + uint8_t bit_state = packet.rubber_band_state.get_value(); if (bit_state == 255 && m_rubber_band) { delete m_rubber_band; diff --git a/src/items/plunger.hpp b/src/items/plunger.hpp index de72bae014f..0e51b6d76a7 100644 --- a/src/items/plunger.hpp +++ b/src/items/plunger.hpp @@ -22,6 +22,8 @@ #ifndef HEADER_MISSILE_HPP #define HEADER_MISSILE_HPP +#define nonvirtual + #include using namespace irr; @@ -67,10 +69,9 @@ class Plunger : public Flyable /** No hit effect when it ends. */ virtual HitEffect *getHitEffect() const OVERRIDE { return NULL; } // ------------------------------------------------------------------------ - virtual BareNetworkString* saveState(std::vector* ru) - OVERRIDE; + nonvirtual PlungerPacket saveState(std::vector* ru); // ------------------------------------------------------------------------ - virtual void restoreState(BareNetworkString *buffer, int count) OVERRIDE; + nonvirtual void restoreState(const PlungerPacket& packet, int count); // ------------------------------------------------------------------------ virtual void onFireFlyable() OVERRIDE; // ------------------------------------------------------------------------ diff --git a/src/items/projectile_manager.cpp b/src/items/projectile_manager.cpp index f44e220b1e3..4e817469f19 100644 --- a/src/items/projectile_manager.cpp +++ b/src/items/projectile_manager.cpp @@ -316,19 +316,15 @@ std::string ProjectileManager::getUniqueIdentity(AbstractKart* kart, /* If any flyable is not found in current game state, create it with respect to * its uid as below. */ std::shared_ptr - ProjectileManager::addRewinderFromNetworkState(const std::string& uid) + ProjectileManager::addRewinderFromNetworkState(const ProjectilePacket& packet) { - if (uid.size() != 6) - return nullptr; - BareNetworkString data(uid.data(), (int)uid.size()); - - RewinderName rn = (RewinderName)data.getUInt8(); + RewinderName rn = (RewinderName)packet.rewinder_type; if (!(rn == RN_BOWLING || rn == RN_PLUNGER || rn == RN_CAKE || rn == RN_RUBBERBALL)) return nullptr; - AbstractKart* kart = World::getWorld()->getKart(data.getUInt8()); - int created_ticks = data.getUInt32(); + AbstractKart* kart = World::getWorld()->getKart(packet.kart_id); + int created_ticks = packet.created_ticks; std::shared_ptr f; switch (rn) { @@ -360,7 +356,7 @@ std::shared_ptr assert(f); f->setCreatedTicks(created_ticks); f->onFireFlyable(); - f->addForRewind(uid); + f->addForRewind(packet); Flyable* flyable = f.get(); Log::debug("ProjectileManager", "Missed a firing event, " "add the flyable %s by %s created at %d manually.", @@ -368,7 +364,7 @@ std::shared_ptr StringUtils::wideToUtf8(kart->getController()->getName()).c_str(), created_ticks); - m_active_projectiles[uid] = f; + m_active_projectiles[packet] = f; return f; } // addProjectileFromNetworkState diff --git a/src/items/projectile_manager.hpp b/src/items/projectile_manager.hpp index 52fca14f43e..146164fa93d 100644 --- a/src/items/projectile_manager.hpp +++ b/src/items/projectile_manager.hpp @@ -31,6 +31,7 @@ namespace irr #include "items/powerup_manager.hpp" #include "utils/no_copy.hpp" +#include "network/packet_types.hpp" class AbstractKart; class Flyable; @@ -49,7 +50,7 @@ class ProjectileManager : public NoCopy /** The list of all active projectiles, i.e. projectiles which are * currently moving on the track. */ - std::map > m_active_projectiles; + std::map > m_active_projectiles; /** All active hit effects, i.e. hit effects which are currently * being shown or have a sfx playing. */ @@ -88,7 +89,7 @@ class ProjectileManager : public NoCopy { m_active_hit_effects.push_back(hit_effect); } // ------------------------------------------------------------------------ std::shared_ptr - addRewinderFromNetworkState(const std::string& uid); + addRewinderFromNetworkState(const ProjectilePacket& packet); // ------------------------------------------------------------------------ std::shared_ptr newProjectile(AbstractKart *kart, PowerupManager::PowerupType type); diff --git a/src/items/rubber_ball.cpp b/src/items/rubber_ball.cpp index bb6413e99ac..6a2bd3d2a86 100644 --- a/src/items/rubber_ball.cpp +++ b/src/items/rubber_ball.cpp @@ -886,57 +886,70 @@ bool RubberBall::hit(AbstractKart* kart, PhysicalObject* object) } // hit // ---------------------------------------------------------------------------- -BareNetworkString* RubberBall::saveState(std::vector* ru) +RubberBallPacket RubberBall::saveState(std::vector* ru) { - BareNetworkString* buffer = Flyable::saveState(ru); - if (!buffer) - return NULL; - - buffer->addUInt16((int16_t)m_last_aimed_graph_node); - buffer->add(m_control_points[0]); - buffer->add(m_control_points[1]); - buffer->add(m_control_points[2]); - buffer->add(m_control_points[3]); - buffer->add(m_previous_xyz); - buffer->addFloat(m_previous_height); - buffer->addFloat(m_length_cp_1_2); - buffer->addFloat(m_length_cp_2_3); - buffer->addFloat(m_t); - buffer->addFloat(m_t_increase); - buffer->addFloat(m_interval); - buffer->addFloat(m_height_timer); - buffer->addUInt16(m_delete_ticks); - buffer->addFloat(m_current_max_height); - buffer->addUInt8(m_tunnel_count | (m_aiming_at_target ? (1 << 7) : 0)); - TrackSector::saveState(buffer); - return buffer; + RubberBallPacket packet; + FlyablePacket subpacket = Flyable::saveState(ru); + + // kimden: it was checking before if BNS is null. + // Temporary solution is below. + if (!subpacket.ticks_since_thrown_animation.has_value()) + return packet; + + packet.flyable_packet = subpacket; + + packet.last_aimed_graph_node = (int16_t)m_last_aimed_graph_node; + packet.control_point_0 = m_control_points[0]; + packet.control_point_1 = m_control_points[1]; + packet.control_point_2 = m_control_points[2]; + packet.control_point_3 = m_control_points[3]; + packet.previous_xyz = m_previous_xyz; + packet.previous_height = m_previous_height; + packet.length_cp_1_2 = m_length_cp_1_2; + packet.length_cp_2_3 = m_length_cp_2_3; + packet.t = m_t; + packet.t_increase = m_t_increase; + packet.interval = m_interval; + packet.height_timer = m_height_timer; + packet.delete_ticks = m_delete_ticks; + packet.current_max_height = m_current_max_height; + packet.properties = m_tunnel_count | (m_aiming_at_target ? (1 << 7) : 0); + packet.track_sector = TrackSector::saveState(); + return packet; } // saveState // ---------------------------------------------------------------------------- -void RubberBall::restoreState(BareNetworkString *buffer, int count) +void RubberBall::restoreState(const RubberBallPacket& packet, int count) { - Flyable::restoreState(buffer, count); + // kimden: nonvirtual: in which cases there can be nothing? + // I don't check the presence of other fields for now + // because they are supposed to be there too if flyable_packet is present. + if (!packet.flyable_packet.has_value()) + return; + + Flyable::restoreState(packet.flyable_packet.get_value(), count); + m_restoring_state = true; - int16_t last_aimed_graph_node = buffer->getUInt16(); + int16_t last_aimed_graph_node = packet.last_aimed_graph_node.get_value(); m_last_aimed_graph_node = last_aimed_graph_node; - m_control_points[0] = buffer->getVec3(); - m_control_points[1] = buffer->getVec3(); - m_control_points[2] = buffer->getVec3(); - m_control_points[3] = buffer->getVec3(); - m_previous_xyz = buffer->getVec3(); - m_previous_height = buffer->getFloat(); - m_length_cp_1_2 = buffer->getFloat(); - m_length_cp_2_3 = buffer->getFloat(); - m_t = buffer->getFloat(); - m_t_increase = buffer->getFloat(); - m_interval = buffer->getFloat(); - m_height_timer = buffer->getFloat(); - m_delete_ticks = buffer->getUInt16(); - m_current_max_height = buffer->getFloat(); - uint8_t tunnel_and_aiming = buffer->getUInt8(); + m_control_points[0] = packet.control_point_0.get_value(); + m_control_points[1] = packet.control_point_1.get_value(); + m_control_points[2] = packet.control_point_2.get_value(); + m_control_points[3] = packet.control_point_3.get_value(); + m_previous_xyz = packet.previous_xyz.get_value(); + m_previous_height = packet.previous_height.get_value(); + m_length_cp_1_2 = packet.length_cp_1_2.get_value(); + m_length_cp_2_3 = packet.length_cp_2_3.get_value(); + m_t = packet.t.get_value(); + m_t_increase = packet.t_increase.get_value(); + m_interval = packet.interval.get_value(); + m_height_timer = packet.height_timer.get_value(); + m_delete_ticks = packet.delete_ticks.get_value(); + m_current_max_height = packet.current_max_height.get_value(); + uint8_t tunnel_and_aiming = packet.properties.get_value(); m_tunnel_count = tunnel_and_aiming & 127; m_aiming_at_target = ((tunnel_and_aiming >> 7) & 1) == 1; - TrackSector::rewindTo(buffer); + TrackSector::rewindTo(packet.track_sector.get_value()); } // restoreState // ---------------------------------------------------------------------------- diff --git a/src/items/rubber_ball.hpp b/src/items/rubber_ball.hpp index 034c9229d74..ec0817518c9 100644 --- a/src/items/rubber_ball.hpp +++ b/src/items/rubber_ball.hpp @@ -19,6 +19,8 @@ #ifndef HEADER_RUBBER_BALL_HPP #define HEADER_RUBBER_BALL_HPP +#define nonvirtual + #include #include "items/flyable.hpp" @@ -222,10 +224,9 @@ class RubberBall: public Flyable, public TrackSector * karts are handled by this hit() function. */ //virtual HitEffect *getHitEffect() const {return NULL; } // ------------------------------------------------------------------------ - virtual BareNetworkString* saveState(std::vector* ru) - OVERRIDE; + nonvirtual RubberBallPacket saveState(std::vector* ru); // ------------------------------------------------------------------------ - virtual void restoreState(BareNetworkString *buffer, int count) OVERRIDE; + nonvirtual void restoreState(const RubberBallPacket& packet, int count); // ------------------------------------------------------------------------ virtual void onFireFlyable() OVERRIDE; diff --git a/src/karts/abstract_kart_animation.cpp b/src/karts/abstract_kart_animation.cpp index f6fadc9536a..794b5e8d9a6 100644 --- a/src/karts/abstract_kart_animation.cpp +++ b/src/karts/abstract_kart_animation.cpp @@ -179,25 +179,27 @@ float AbstractKartAnimation::getMaximumHeight(const Vec3& up_vector, } // getMaximumHeight // ---------------------------------------------------------------------------- -void AbstractKartAnimation::saveState(BareNetworkString* buffer) +AbstractKartAnimationPacket AbstractKartAnimation::saveState() { - buffer->addUInt32(m_created_ticks); - buffer->addInt24(m_created_transform_compressed[0]) - .addInt24(m_created_transform_compressed[1]) - .addInt24(m_created_transform_compressed[2]) - .addUInt32(m_created_transform_compressed[3]); + AbstractKartAnimationPacket packet; + packet.created_ticks = m_created_ticks; + packet.transform_compressed_0 = m_created_transform_compressed[0]; + packet.transform_compressed_1 = m_created_transform_compressed[1]; + packet.transform_compressed_2 = m_created_transform_compressed[2]; + packet.transform_compressed_3 = m_created_transform_compressed[3]; + return packet; } // saveState // ---------------------------------------------------------------------------- /** Used in constructor of sub-class as no virtual function can be used there. */ -void AbstractKartAnimation::restoreBasicState(BareNetworkString* buffer) +void AbstractKartAnimation::restoreBasicState(const AbstractKartAnimationPacket& packet) { - m_created_ticks = buffer->getUInt32(); - m_created_transform_compressed[0] = buffer->getInt24(); - m_created_transform_compressed[1] = buffer->getInt24(); - m_created_transform_compressed[2] = buffer->getInt24(); - m_created_transform_compressed[3] = buffer->getUInt32(); + m_created_ticks = packet.created_ticks; + m_created_transform_compressed[0] = (uint32_t)packet.transform_compressed_0; + m_created_transform_compressed[1] = (uint32_t)packet.transform_compressed_1; + m_created_transform_compressed[2] = (uint32_t)packet.transform_compressed_2; + m_created_transform_compressed[3] = packet.transform_compressed_3; m_created_transform = MiniGLM::decompressbtTransform(m_created_transform_compressed); } // restoreBasicState diff --git a/src/karts/abstract_kart_animation.hpp b/src/karts/abstract_kart_animation.hpp index fea5c42f0b6..986fcf9d197 100644 --- a/src/karts/abstract_kart_animation.hpp +++ b/src/karts/abstract_kart_animation.hpp @@ -19,6 +19,8 @@ #ifndef HEADER_ABSTRACT_KART_ANIMATION_HPP #define HEADER_ABSTRACT_KART_ANIMATION_HPP +#define nonvirtual + #include "LinearMath/btTransform.h" #include "config/stk_config.hpp" @@ -39,14 +41,6 @@ enum KartAnimationType : uint8_t KAT_CANNON = 2 }; -/** Exception for kart animation creation in networking, so if thrown it will - * tell the num of bytes skipping in the game state. */ -class KartAnimationCreationException : public std::exception -{ -public: - virtual int getSkippingOffset() const = 0; -}; - /** The base class for all kart animation, like rescue, explosion, or cannon. * Kart animations are done by removing the physics body from the physics * world, and instead modifying the rotation and position of the kart @@ -81,7 +75,7 @@ class AbstractKartAnimation: public NoCopy void resetPowerUp(); // ------------------------------------------------------------------------ - void restoreBasicState(BareNetworkString* buffer); + void restoreBasicState(const AbstractKartAnimationPacket& buffer); // ------------------------------------------------------------------------ float getMaximumHeight(const Vec3& up_vector, float height_remove); @@ -105,11 +99,13 @@ class AbstractKartAnimation: public NoCopy void handleResetRace() { m_end_ticks = std::numeric_limits::max(); } // ------------------------------------------------------------------------ /* Used to recreate animation in \ref KartRewinder. */ - virtual void saveState(BareNetworkString* buffer); + virtual AbstractKartAnimationPacket saveState(); // ------------------------------------------------------------------------ /* Called when kart animation is the same in kart state, which make sure * for example the end or created ticks are the same. */ - virtual void restoreState(BareNetworkString* buffer) + + // AbstractKartAnimationPacket + nonvirtual void restoreState(const AbstractKartAnimationPacket& buffer) { restoreBasicState(buffer); } }; // AbstractKartAnimation diff --git a/src/karts/cannon_animation.cpp b/src/karts/cannon_animation.cpp index 2e56e7355cb..5d508112c0d 100644 --- a/src/karts/cannon_animation.cpp +++ b/src/karts/cannon_animation.cpp @@ -61,14 +61,14 @@ CannonAnimation::CannonAnimation(AbstractKart* kart, CheckCannon* cc, // ---------------------------------------------------------------------------- /** The constructor for the cannon animation for kart during rewind. */ -CannonAnimation::CannonAnimation(AbstractKart* kart, BareNetworkString* buffer) +CannonAnimation::CannonAnimation(AbstractKart* kart, const AbstractKartAnimationPacket& packet) : AbstractKartAnimation(kart, "CannonAnimation") { - restoreBasicState(buffer); + restoreBasicState(packet); m_check_cannon = NULL; m_flyable = NULL; m_skid_rot = 0; - restoreData(buffer); + restoreData(packet); } // CannonAnimation // ---------------------------------------------------------------------------- @@ -89,14 +89,14 @@ CannonAnimation::CannonAnimation(Flyable* flyable, CheckCannon* cc) // ---------------------------------------------------------------------------- /** The constructor for the cannon animation for flyable during rewind. */ -CannonAnimation::CannonAnimation(Flyable* flyable, BareNetworkString* buffer) +CannonAnimation::CannonAnimation(Flyable* flyable, const AbstractKartAnimationPacket& packet) : AbstractKartAnimation(NULL, "CannonAnimation") { m_flyable = flyable; - restoreBasicState(buffer); + restoreBasicState(packet); m_check_cannon = NULL; m_skid_rot = 0; - restoreData(buffer); + restoreData(packet); } // CannonAnimation // ---------------------------------------------------------------------------- @@ -384,34 +384,18 @@ void CannonAnimation::restoreData(BareNetworkString* buffer) // Kart cannon has 2 floats + 1 compressed quaternion // Flyable has 1 float (delta) const int skipping_offset = m_kart ? 12 : 4; - class CannonCreationException : public KartAnimationCreationException - { - private: - const std::string m_error; - - const int m_skipping_offset; - public: - CannonCreationException(const std::string& error, int skipping_offset) - : m_error(error), m_skipping_offset(skipping_offset) {} - // -------------------------------------------------------------------- - virtual int getSkippingOffset() const { return m_skipping_offset; } - // -------------------------------------------------------------------- - virtual const char* what() const throw() { return m_error.c_str(); } - }; int cc_idx = buffer->getInt8(); CheckManager* cm = Track::getCurrentTrack()->getCheckManager(); if ((unsigned)cc_idx > cm->getCheckStructureCount()) { - throw CannonCreationException( - "Server has different check structure size.", skipping_offset); + throw std::logic_error("Server has different check structure size."); } CheckCannon* cc = dynamic_cast (cm->getCheckStructure(cc_idx)); if (!cc) { - throw CannonCreationException( - "Server has different check cannon index.", skipping_offset); + throw std::logic_error("Server has different check cannon index."); } float skid_rot = 0.0f; float fraction_of_line = 0.0f; diff --git a/src/karts/cannon_animation.hpp b/src/karts/cannon_animation.hpp index 721522fe7eb..9fe379b27e2 100644 --- a/src/karts/cannon_animation.hpp +++ b/src/karts/cannon_animation.hpp @@ -41,9 +41,9 @@ class CannonAnimation: public AbstractKartAnimation friend class KartRewinder; friend class Flyable; // ------------------------------------------------------------------------ - CannonAnimation(AbstractKart* kart, BareNetworkString* buffer); + CannonAnimation(AbstractKart* kart, const AbstractKartAnimationPacket& packet); // ------------------------------------------------------------------------ - CannonAnimation(Flyable* flyable, BareNetworkString* buffer); + CannonAnimation(Flyable* flyable, const AbstractKartAnimationPacket& packet); // ------------------------------------------------------------------------ void init(Ipo *ipo, const Vec3 &start_left, const Vec3 &start_right, const Vec3 &end_left, const Vec3 &end_right, float skid_rot); diff --git a/src/karts/kart_rewinder.cpp b/src/karts/kart_rewinder.cpp index 0cb9af76e30..d58761adf33 100644 --- a/src/karts/kart_rewinder.cpp +++ b/src/karts/kart_rewinder.cpp @@ -354,11 +354,10 @@ void KartRewinder::restoreState(BareNetworkString *buffer, int count) break; } } - catch (const KartAnimationCreationException& kace) + catch (const std::exception& kace) { Log::error("KartRewinder", "Kart animation creation error: %s", kace.what()); - buffer->skip(kace.getSkippingOffset()); m_kart_animation = NULL; } } diff --git a/src/karts/max_speed.cpp b/src/karts/max_speed.cpp index 34a3fc10ed8..dfda30c3e90 100644 --- a/src/karts/max_speed.cpp +++ b/src/karts/max_speed.cpp @@ -219,29 +219,23 @@ void MaxSpeed::SpeedIncrease::update(int ticks) } // SpeedIncrease::update // ---------------------------------------------------------------------------- -void MaxSpeed::SpeedIncrease::saveState(BareNetworkString *buffer) const +MaxSpeedSpeedIncreasePacket MaxSpeed::SpeedIncrease::saveState() const { - buffer->addUInt16(m_max_add_speed); - buffer->addUInt16(m_duration); - buffer->addUInt16(m_fade_out_time); - buffer->addUInt16(m_engine_force); + MaxSpeedSpeedIncreasePacket packet; + packet.max_add_speed = m_max_add_speed; + packet.duration = m_duration; + packet.fade_out_time = m_fade_out_time; + packet.engine_force = m_engine_force; + return packet; } // saveState // ---------------------------------------------------------------------------- -void MaxSpeed::SpeedIncrease::rewindTo(BareNetworkString *buffer, - bool is_active) +void MaxSpeed::SpeedIncrease::rewindTo(const MaxSpeedSpeedIncreasePacket& packet) { - if(is_active) - { - m_max_add_speed = buffer->getUInt16(); - m_duration = buffer->getUInt16(); - m_fade_out_time = buffer->getUInt16(); - m_engine_force = buffer->getUInt16(); - } - else // make sure to disable this category - { - reset(); - } + m_max_add_speed = packet.max_add_speed; + m_duration = packet.duration; + m_fade_out_time = packet.fade_out_time; + m_engine_force = packet.engine_force; } // rewindTo // ---------------------------------------------------------------------------- @@ -336,31 +330,25 @@ void MaxSpeed::SpeedDecrease::update(int ticks) * if the speed decrease is not active. * \param buffer Buffer which will store the state information. */ -void MaxSpeed::SpeedDecrease::saveState(BareNetworkString *buffer) const +MaxSpeedSpeedDecreasePacket MaxSpeed::SpeedDecrease::saveState() const { - buffer->addUInt16(m_max_speed_fraction); - buffer->addFloat(m_current_fraction); - buffer->addUInt16(m_fade_in_ticks); - buffer->addUInt16(m_duration); + MaxSpeedSpeedDecreasePacket packet; + packet.max_speed_fraction = m_max_speed_fraction; + packet.current_fraction = m_current_fraction; + packet.fade_in_ticks = m_fade_in_ticks; + packet.duration = m_duration; + return packet; } // saveState // ---------------------------------------------------------------------------- /** Restores a previously saved state for an active speed decrease category. */ -void MaxSpeed::SpeedDecrease::rewindTo(BareNetworkString *buffer, - bool is_active) +void MaxSpeed::SpeedDecrease::rewindTo(const MaxSpeedSpeedDecreasePacket& packet) { - if(is_active) - { - m_max_speed_fraction = buffer->getUInt16(); - m_current_fraction = buffer->getFloat(); - m_fade_in_ticks = buffer->getUInt16(); - m_duration = buffer->getUInt16(); - } - else // make sure it is not active - { - reset(); - } + m_max_speed_fraction = packet.max_speed_fraction; + m_current_fraction = packet.current_fraction; + m_fade_in_ticks = packet.fade_in_ticks; + m_duration = packet.duration; } // rewindTo // ---------------------------------------------------------------------------- @@ -458,8 +446,10 @@ void MaxSpeed::update(int ticks) /** Saves the speed data in a network string for rewind. * \param buffer Pointer to the network string to store the data. */ -void MaxSpeed::saveState(BareNetworkString *buffer) const +MaxSpeedPacket MaxSpeed::saveState() const { + MaxSpeedPacket packet; + // Save the slowdown states // ------------------------ // Get the bit pattern of all active slowdowns @@ -472,7 +462,7 @@ void MaxSpeed::saveState(BareNetworkString *buffer) const if (m_speed_decrease[i].isActive()) active_slowdown |= b; } - buffer->addUInt8(active_slowdown); + packet.slowdown_mask = active_slowdown; for(unsigned int i=MS_DECREASE_MIN, b=1; iaddUInt8(active_speedups); + packet.speedup_mask = active_speedups; for(unsigned int i=MS_INCREASE_MIN, b=1; igetUInt8(); + uint8_t active_slowdown = packet.slowdown_mask; + + unsigned idx = 0; for(unsigned int i=MS_DECREASE_MIN, b=1; igetUInt8(); + idx = 0; + uint8_t active_speedups = packet.speedup_mask; for(unsigned int i=MS_INCREASE_MIN, b=1; iaddUInt8(m_skid_state); - buffer->addUInt16(m_skid_time); - buffer->addFloat(m_skid_factor); - buffer->addFloat(m_visual_rotation); + SkiddingStatePacket packet; + packet.skid_state = m_skid_state; + packet.skid_time = m_skid_time; + packet.skid_factor = m_skid_factor; + packet.visual_rotation = m_visual_rotation; + return packet; } // saveState // ---------------------------------------------------------------------------- /** Restores the skidding state of a kart. * \param buffer Buffer with state information. */ -void Skidding::rewindTo(BareNetworkString *buffer) +void Skidding::rewindTo(const SkiddingStatePacket& packet) { - m_skid_state = (SkidState)buffer->getUInt8(); - m_skid_time = buffer->getUInt16(); - m_skid_factor = buffer->getFloat(); - m_visual_rotation = buffer->getFloat(); + m_skid_state = (SkidState)packet.skid_state; + m_skid_time = packet.skid_time; + m_skid_factor = packet.skid_factor; + m_visual_rotation = packet.visual_rotation; } // rewindTo // ---------------------------------------------------------------------------- diff --git a/src/karts/skidding.hpp b/src/karts/skidding.hpp index c54ca14e674..0f564789c84 100644 --- a/src/karts/skidding.hpp +++ b/src/karts/skidding.hpp @@ -24,7 +24,7 @@ #include "utils/no_copy.hpp" #include "utils/types.hpp" -class BareNetworkString; +class SkiddingStatePacket; class Kart; class ShowCurve; @@ -111,8 +111,8 @@ friend class KartRewinder; float updateGraphics(float dt); void update(int dt, bool is_on_ground, float steer, KartControl::SkidControl skidding); - void saveState(BareNetworkString *buffer); - void rewindTo(BareNetworkString *buffer); + SkiddingStatePacket saveState(); + void rewindTo(const SkiddingStatePacket& packet); // ------------------------------------------------------------------------ /** Determines how much the graphics model of the kart should be rotated * additionally (for skidding), depending on how long the kart has been diff --git a/src/modes/capture_the_flag.cpp b/src/modes/capture_the_flag.cpp index ee05e48ce71..dd8297d2625 100644 --- a/src/modes/capture_the_flag.cpp +++ b/src/modes/capture_the_flag.cpp @@ -35,6 +35,7 @@ #include "states_screens/race_gui.hpp" #include "tracks/track.hpp" #include "tracks/track_object_manager.hpp" +#include "utils/communication.hpp" #include "utils/game_info.hpp" #include "utils/string_utils.hpp" #include "utils/translation.hpp" @@ -340,15 +341,13 @@ void CaptureTheFlag::checkScoring(FlagColor color) m_scores.at(active_holder) = new_kart_score; if (NetworkConfig::get()->isServer()) { - NetworkString p(PROTOCOL_GAME_EVENTS); - p.setSynchronous(true); - p.addUInt8(GameEventsProtocol::GE_CTF_SCORED) - .addUInt8((int8_t)active_holder) - .addUInt8((red_active) ? 0 : 1 /*red_team_scored*/) - .addUInt16((int16_t)new_kart_score) - .addUInt8((uint8_t)new_red_score) - .addUInt8((uint8_t)new_blue_score); - STKHost::get()->sendPacketToAllPeers(&p, PRM_RELIABLE); + InsideCtfPacket packet; + packet.active_holder = (int8_t)active_holder; + packet.red_inactive = !red_active; + packet.kart_score = (int16_t)new_kart_score; + packet.red_score = (uint8_t)new_red_score; + packet.blue_score = (uint8_t)new_blue_score; + Comm::sendPacketToPeers(packet); } ctfScored(active_holder, (red_active) ? false : true /*red_team_scored*/, new_kart_score, new_red_score, new_blue_score); @@ -553,16 +552,23 @@ const std::string& CaptureTheFlag::getIdent() const } // getIdent // ---------------------------------------------------------------------------- -void CaptureTheFlag::saveCompleteState(BareNetworkString* bns, std::shared_ptr peer) +std::shared_ptr CaptureTheFlag::saveCompleteState(std::shared_ptr peer) { - FreeForAll::saveCompleteState(bns, peer); - bns->addUInt32(m_red_scores).addUInt32(m_blue_scores); + auto packet = std::make_shared(); + + auto sp = FreeForAll::saveCompleteState(peer); + packet->ffa_packet = std::dynamic_pointer_cast(sp); + packet->red_score = m_red_scores; + packet->blue_score = m_blue_scores; + return packet; } // saveCompleteState // ---------------------------------------------------------------------------- -void CaptureTheFlag::restoreCompleteState(const BareNetworkString& b) +void CaptureTheFlag::restoreCompleteState(const std::shared_ptr& packet) { - FreeForAll::restoreCompleteState(b); - m_red_scores = b.getUInt32(); - m_blue_scores = b.getUInt32(); + std::shared_ptr ctf_packet = + std::dynamic_pointer_cast(packet); + FreeForAll::restoreCompleteState(ctf_packet->ffa_packet); + m_red_scores = ctf_packet->red_score; + m_blue_scores = ctf_packet->blue_score; } // restoreCompleteState diff --git a/src/modes/capture_the_flag.hpp b/src/modes/capture_the_flag.hpp index da6f090bf5d..64c5148f4e4 100644 --- a/src/modes/capture_the_flag.hpp +++ b/src/modes/capture_the_flag.hpp @@ -157,10 +157,10 @@ class CaptureTheFlag : public FreeForAll return progress; } // ------------------------------------------------------------------------ - virtual void saveCompleteState(BareNetworkString* bns, + virtual std::shared_ptr saveCompleteState( std::shared_ptr peer) OVERRIDE; // ------------------------------------------------------------------------ - virtual void restoreCompleteState(const BareNetworkString& b) OVERRIDE; + virtual void restoreCompleteState(const std::shared_ptr& b) OVERRIDE; }; // CaptureTheFlag #endif diff --git a/src/modes/free_for_all.cpp b/src/modes/free_for_all.cpp index b5ed87be4ef..62cbcd0765b 100644 --- a/src/modes/free_for_all.cpp +++ b/src/modes/free_for_all.cpp @@ -23,6 +23,7 @@ #include "network/protocols/game_events_protocol.hpp" #include "network/stk_host.hpp" #include "tracks/track.hpp" +#include "utils/communication.hpp" #include "utils/string_utils.hpp" #include @@ -123,22 +124,28 @@ void FreeForAll::handleScoreInServer(int kart_id, int hitter) if (NetworkConfig::get()->isNetworking() && NetworkConfig::get()->isServer()) { - NetworkString p(PROTOCOL_GAME_EVENTS); - p.setSynchronous(true); - p.addUInt8(GameEventsProtocol::GE_BATTLE_KART_SCORE); + InsideFfaPacket packet; + if (kart_id == hitter || hitter == -1) - p.addUInt8((uint8_t)kart_id).addUInt16((int16_t)new_score); + { + packet.hitter_kart = (uint8_t)kart_id; + packet.new_score = (int16_t)new_score; + } else - p.addUInt8((uint8_t)hitter).addUInt16((int16_t)new_score); - STKHost::get()->sendPacketToAllPeers(&p, PRM_RELIABLE); + { + packet.hitter_kart = (uint8_t)hitter; + packet.new_score = (int16_t)new_score; + } + + Comm::sendPacketToPeers(packet); } } // handleScoreInServer // ---------------------------------------------------------------------------- -void FreeForAll::setKartScoreFromServer(NetworkString& ns) +void FreeForAll::setKartScoreFromServer(const InsideFfaPacket& packet) { - int kart_id = ns.getUInt8(); - int16_t score = ns.getUInt16(); + int kart_id = packet.hitter_kart; + int16_t score = packet.new_score; m_scores.at(kart_id) = score; } // setKartScoreFromServer @@ -295,17 +302,28 @@ bool FreeForAll::getKartFFAResult(int kart_id) const } // getKartFFAResult // ---------------------------------------------------------------------------- -void FreeForAll::saveCompleteState(BareNetworkString* bns, std::shared_ptr peer) +std::shared_ptr FreeForAll::saveCompleteState(std::shared_ptr peer) { + auto packet = std::make_shared(); for (unsigned i = 0; i < m_scores.size(); i++) - bns->addUInt32(m_scores[i]); + packet->scores.push_back(m_scores[i]); + + return packet; } // saveCompleteState // ---------------------------------------------------------------------------- -void FreeForAll::restoreCompleteState(const BareNetworkString& b) +void FreeForAll::restoreCompleteState(const std::shared_ptr& packet) { + std::shared_ptr ffa_packet = + std::dynamic_pointer_cast(packet); + + // kimden sincerely hopes here nothing will be broken + if (ffa_packet->scores.size() != m_scores.size()) + Log::error("FreeForAll", "Packet incoming scores size = %d, local scores size = %d", + ffa_packet->scores.size(), m_scores.size()); + for (unsigned i = 0; i < m_scores.size(); i++) - m_scores[i] = b.getUInt32(); + m_scores[i] = (i >= ffa_packet->scores.size() ? 0 : ffa_packet->scores[i]); } // restoreCompleteState // ---------------------------------------------------------------------------- @@ -341,10 +359,10 @@ void FreeForAll::notifyAboutScoreIfNonzero(int id) NetworkConfig::get()->isServer() && m_scores[id] != 0) { - NetworkString p(PROTOCOL_GAME_EVENTS); - p.setSynchronous(true); - p.addUInt8(GameEventsProtocol::GE_BATTLE_KART_SCORE); - p.addUInt8((uint8_t)id).addUInt16((int16_t)m_scores[id]); - STKHost::get()->sendPacketToAllPeers(&p, PRM_RELIABLE); + InsideFfaPacket packet; + packet.hitter_kart = (uint8_t)id; + packet.new_score = (int16_t)m_scores[id]; + + Comm::sendPacketToPeers(packet); } } // notifyAboutScoreIfNonzero diff --git a/src/modes/free_for_all.hpp b/src/modes/free_for_all.hpp index e74c36e6c36..98ca93abd2c 100644 --- a/src/modes/free_for_all.hpp +++ b/src/modes/free_for_all.hpp @@ -23,8 +23,6 @@ #include -class NetworkString; - class FreeForAll : public WorldWithRank { protected: @@ -70,7 +68,7 @@ class FreeForAll : public WorldWithRank // ------------------------------------------------------------------------ virtual void terminateRace() OVERRIDE; // ------------------------------------------------------------------------ - void setKartScoreFromServer(NetworkString& ns); + void setKartScoreFromServer(const InsideFfaPacket& packet); // ------------------------------------------------------------------------ int getKartScore(int kart_id) const { return m_scores.at(kart_id); } // ------------------------------------------------------------------------ @@ -85,10 +83,9 @@ class FreeForAll : public WorldWithRank m_scores.at(kart_id) = param; } // ------------------------------------------------------------------------ - virtual void saveCompleteState(BareNetworkString* bns, - std::shared_ptr peer) OVERRIDE; + virtual std::shared_ptr saveCompleteState(std::shared_ptr peer) OVERRIDE; // ------------------------------------------------------------------------ - virtual void restoreCompleteState(const BareNetworkString& b) OVERRIDE; + virtual void restoreCompleteState(const std::shared_ptr& b) OVERRIDE; // ------------------------------------------------------------------------ void notifyAboutScoreIfNonzero(int id); }; // FreeForAll diff --git a/src/modes/linear_world.cpp b/src/modes/linear_world.cpp index 9b170a7c11d..a0fc14f4e56 100644 --- a/src/modes/linear_world.cpp +++ b/src/modes/linear_world.cpp @@ -47,6 +47,7 @@ #include "tracks/drive_node.hpp" #include "tracks/track_sector.hpp" #include "tracks/track.hpp" +#include "utils/communication.hpp" #include "utils/constants.hpp" #include "utils/string_utils.hpp" #include "utils/translation.hpp" @@ -1215,79 +1216,114 @@ std::pair LinearWorld::getGameStartedProgress() const } // getGameStartedProgress // ---------------------------------------------------------------------------- -void LinearWorld::KartInfo::saveCompleteState(BareNetworkString* bns) +KartInfoInGamePacket LinearWorld::KartInfo::saveCompleteState() { - bns->addUInt32(m_finished_laps); - bns->addUInt32(m_ticks_at_last_lap); - bns->addUInt32(m_lap_start_ticks); - bns->addFloat(m_estimated_finish); - bns->addFloat(m_overall_distance); - bns->addFloat(m_wrong_way_timer); + KartInfoInGamePacket packet; + packet.finished_laps = m_finished_laps; + packet.ticks_at_last_lap = m_ticks_at_last_lap; + packet.lap_start_ticks = m_lap_start_ticks; + packet.estimated_finish = m_estimated_finish; + packet.overall_distance = m_overall_distance; + packet.wrong_way_timer = m_wrong_way_timer; + return packet; } // saveCompleteState // ---------------------------------------------------------------------------- -void LinearWorld::KartInfo::restoreCompleteState(const BareNetworkString& b) +void LinearWorld::KartInfo::restoreCompleteState(const KartInfoInGamePacket& packet) { - m_finished_laps = b.getUInt32(); - m_ticks_at_last_lap = b.getUInt32(); - m_lap_start_ticks = b.getUInt32(); - m_estimated_finish = b.getFloat(); - m_overall_distance = b.getFloat(); - m_wrong_way_timer = b.getFloat(); + m_finished_laps = packet.finished_laps; + m_ticks_at_last_lap = packet.ticks_at_last_lap; + m_lap_start_ticks = packet.lap_start_ticks; + m_estimated_finish = packet.estimated_finish; + m_overall_distance = packet.overall_distance; + m_wrong_way_timer = packet.wrong_way_timer; } // restoreCompleteState // ---------------------------------------------------------------------------- -void LinearWorld::saveCompleteState(BareNetworkString* bns, std::shared_ptr peer) +std::shared_ptr LinearWorld::saveCompleteState(std::shared_ptr peer) { - bns->addUInt32(m_fastest_lap_ticks); - bns->addFloat(m_distance_increase); + auto packet = std::make_shared(); + + packet->fastest_lap_ticks = m_fastest_lap_ticks; + packet->distance_increase = m_distance_increase; for (auto& kart : m_karts) { - bns->add(kart->getXYZ()); - bns->add(kart->getRotation()); + PlacementPacket placement_packet; + placement_packet.xyz = kart->getXYZ(); + placement_packet.rotation = kart->getRotation(); + packet->kart_placements.push_back(std::move(placement_packet)); } for (KartInfo& ki : m_kart_info) - ki.saveCompleteState(bns); + packet->kart_infos.push_back(ki.saveCompleteState()); for (TrackSector* ts : m_kart_track_sector) - ts->saveCompleteState(bns); + packet->track_sectors.push_back(ts->saveCompleteState()); CheckManager* cm = Track::getCurrentTrack()->getCheckManager(); const uint8_t cc = (uint8_t)cm->getCheckStructureCount(); - bns->addUInt8(cc); + packet->check_structure_count = cc; for (unsigned i = 0; i < cc; i++) - cm->getCheckStructure(i)->saveCompleteState(bns); + { + const auto& item = cm->getCheckStructure(i)->saveCompleteState(); + packet->check_structures.push_back(std::dynamic_pointer_cast(item)); + } + return packet; } // saveCompleteState // ---------------------------------------------------------------------------- -void LinearWorld::restoreCompleteState(const BareNetworkString& b) +void LinearWorld::restoreCompleteState(const std::shared_ptr& packet) { - m_fastest_lap_ticks = b.getUInt32(); - m_distance_increase = b.getFloat(); + std::shared_ptr linear_packet = + std::dynamic_pointer_cast(packet); + m_fastest_lap_ticks = linear_packet->fastest_lap_ticks; + m_distance_increase = linear_packet->distance_increase; + + // kimden sincerely hopes here nothing will be broken + if (linear_packet->kart_placements.size() != m_karts.size()) + Log::error("LinearWorld", "Packet incoming karts size = %d, local karts size = %d", + linear_packet->kart_placements.size(), m_karts.size()); + + int i = 0; for (auto& kart : m_karts) { btTransform t; - Vec3 xyz = b.getVec3(); + Vec3 xyz = linear_packet->kart_placements[i].xyz; t.setOrigin(xyz); - t.setRotation(b.getQuat()); + t.setRotation(linear_packet->kart_placements[i].rotation); kart->setTrans(t); kart->setXYZ(xyz); + ++i; } + + // kimden sincerely hopes here nothing will be broken + if (linear_packet->kart_infos.size() != m_kart_info.size()) + Log::error("LinearWorld", "Packet incoming kartinfos size = %d, local kartinfos size = %d", + linear_packet->kart_infos.size(), m_kart_info.size()); + + i = 0; for (KartInfo& ki : m_kart_info) - ki.restoreCompleteState(b); + ki.restoreCompleteState(linear_packet->kart_infos[i++]); + + // kimden sincerely hopes here nothing will be broken + if (linear_packet->track_sectors.size() != m_kart_track_sector.size()) + Log::error("LinearWorld", "Packet incoming track sectors size = %d, local track sectors size = %d", + linear_packet->track_sectors.size(), m_kart_track_sector.size()); + + i = 0; for (TrackSector* ts : m_kart_track_sector) - ts->restoreCompleteState(b); + ts->restoreCompleteState(linear_packet->track_sectors[i++]); updateRacePosition(); - const unsigned cc = b.getUInt8(); + const unsigned cc = linear_packet->check_structure_count; CheckManager* cm = Track::getCurrentTrack()->getCheckManager(); if (cc != cm->getCheckStructureCount()) { - Log::warn("LinearWorld", - "Server has different check structures size."); + Log::error("LinearWorld", + "Server has different check structures size: %d incoming, %d locally", + cc, cm->getCheckStructureCount()); return; } for (unsigned i = 0; i < cc; i++) - cm->getCheckStructure(i)->restoreCompleteState(b); + cm->getCheckStructure(i)->restoreCompleteState(linear_packet->check_structures[i]); } // restoreCompleteState // ---------------------------------------------------------------------------- @@ -1304,53 +1340,46 @@ void LinearWorld::updateCheckLinesServer(int check_id, int kart_id) NetworkConfig::get()->isClient()) return; - NetworkString cl(PROTOCOL_GAME_EVENTS); - cl.setSynchronous(true); - cl.addUInt8(GameEventsProtocol::GE_CHECK_LINE).addUInt8((uint8_t)check_id) - .addUInt8((uint8_t)kart_id); - - int8_t finished_laps = (int8_t)m_kart_info[kart_id].m_finished_laps; - cl.addUInt8(finished_laps); + InsideChecklinePacket packet; + packet.kart_id = (uint8_t)kart_id; + packet.finished_laps = (int8_t)m_kart_info[kart_id].m_finished_laps; + packet.last_triggered_checkline = + (int8_t)m_kart_track_sector[kart_id]->getLastTriggeredCheckline(); - int8_t ltcl = - (int8_t)m_kart_track_sector[kart_id]->getLastTriggeredCheckline(); - cl.addUInt8(ltcl); - - cl.addUInt32(m_fastest_lap_ticks); - cl.encodeString(m_fastest_lap_kart_name); + packet.fastest_lap_ticks = m_fastest_lap_ticks; + packet.fastest_kart_name = m_fastest_lap_kart_name; CheckManager* cm = Track::getCurrentTrack()->getCheckManager(); const uint8_t cc = (uint8_t)cm->getCheckStructureCount(); - cl.addUInt8(cc); + packet.check_structure_count = cc; for (unsigned i = 0; i < cc; i++) - cm->getCheckStructure(i)->saveIsActive(kart_id, &cl); + { + packet.check_active.push_back( + cm->getCheckStructure(i)->saveIsActive(kart_id)); + } - STKHost::get()->sendPacketToAllPeers(&cl, PRM_RELIABLE); + Comm::sendPacketToPeers(packet); } // updateCheckLinesServer // ---------------------------------------------------------------------------- /* Synchronize with server from the above data. */ -void LinearWorld::updateCheckLinesClient(const BareNetworkString& b) +void LinearWorld::updateCheckLinesClient(const InsideChecklinePacket& packet) { // Reserve for future auto checkline correction - //int check_id = b.getUInt8(); - b.getUInt8(); - int kart_id = b.getUInt8(); - - int8_t finished_laps = b.getUInt8(); - m_kart_info.at(kart_id).m_finished_laps = finished_laps; - - int8_t ltcl = b.getUInt8(); - m_kart_track_sector.at(kart_id)->setLastTriggeredCheckline(ltcl); + //int check_id = packet.check_id; + + int kart_id = packet.kart_id; + m_kart_info.at(kart_id).m_finished_laps = packet.finished_laps; + m_kart_track_sector.at(kart_id)->setLastTriggeredCheckline(packet.last_triggered_checkline); - m_fastest_lap_ticks = b.getUInt32(); - b.decodeStringW(&m_fastest_lap_kart_name); + m_fastest_lap_ticks = packet.fastest_lap_ticks; + m_fastest_lap_kart_name = packet.fastest_kart_name; - const unsigned cc = b.getUInt8(); + const unsigned cc = packet.check_structure_count; if (cc != Track::getCurrentTrack()->getCheckManager()->getCheckStructureCount()) return; for (unsigned i = 0; i < cc; i++) - Track::getCurrentTrack()->getCheckManager()->getCheckStructure(i)->restoreIsActive(kart_id, b); + Track::getCurrentTrack()->getCheckManager()->getCheckStructure(i)->restoreIsActive(kart_id, packet.check_active[i]); } // updateCheckLinesClient diff --git a/src/modes/linear_world.hpp b/src/modes/linear_world.hpp index 76163de1333..8ac7305e45a 100644 --- a/src/modes/linear_world.hpp +++ b/src/modes/linear_world.hpp @@ -135,9 +135,9 @@ class LinearWorld : public WorldWithRank m_warn_issued = 0; } // reset // -------------------------------------------------------------------- - void saveCompleteState(BareNetworkString* bns); + KartInfoInGamePacket saveCompleteState(); // -------------------------------------------------------------------- - void restoreCompleteState(const BareNetworkString& b); + void restoreCompleteState(const KartInfoInGamePacket& packet); }; // ------------------------------------------------------------------------ @@ -276,14 +276,13 @@ class LinearWorld : public WorldWithRank virtual std::pair getGameStartedProgress() const OVERRIDE; // ------------------------------------------------------------------------ - virtual void saveCompleteState(BareNetworkString* bns, - std::shared_ptr peer) OVERRIDE; + virtual std::shared_ptr saveCompleteState(std::shared_ptr peer) OVERRIDE; // ------------------------------------------------------------------------ - virtual void restoreCompleteState(const BareNetworkString& b) OVERRIDE; + virtual void restoreCompleteState(const std::shared_ptr& b) OVERRIDE; // ------------------------------------------------------------------------ void updateCheckLinesServer(int check_id, int kart_id); // ------------------------------------------------------------------------ - void updateCheckLinesClient(const BareNetworkString& b); + void updateCheckLinesClient(const InsideChecklinePacket& packet); // ------------------------------------------------------------------------ void handleServerCheckStructureCount(unsigned count); // ------------------------------------------------------------------------ diff --git a/src/modes/soccer_world.cpp b/src/modes/soccer_world.cpp index 79937ee0022..7740e191815 100644 --- a/src/modes/soccer_world.cpp +++ b/src/modes/soccer_world.cpp @@ -43,6 +43,7 @@ #include "tracks/track.hpp" #include "tracks/track_object_manager.hpp" #include "tracks/track_sector.hpp" +#include "utils/communication.hpp" #include "utils/constants.hpp" #include "utils/game_info.hpp" #include "utils/translation.hpp" @@ -234,7 +235,42 @@ class BallGoalData } }; // BallGoalData +//============================================================================= + +ScorerDataPacket SoccerWorld::ScorerData::saveCompleteState(bool has_soccer_fixes) +{ + ScorerDataPacket packet; + packet.id = m_id; + packet.correct_goal = m_correct_goal; + packet.time = m_time; + packet.kart = m_kart; + packet.player = m_player; + if (has_soccer_fixes) + { + packet.country_code = m_country_code; + packet.handicap_level = m_handicap_level; + } + return packet; +} // saveCompleteState //----------------------------------------------------------------------------- + +void SoccerWorld::ScorerData::restoreCompleteState(const ScorerDataPacket& packet) +{ + m_id = packet.id; + m_correct_goal = packet.correct_goal; + m_time = packet.time; + m_kart = packet.kart; + m_player = packet.player; + if (NetworkConfig::get()->getServerCapabilities().find("soccer_fixes") + != NetworkConfig::get()->getServerCapabilities().end()) + { + if (packet.country_code.has_value()) + m_country_code = packet.country_code.get_value(); + if (packet.handicap_level.has_value()) + m_handicap_level = (HandicapLevel)packet.handicap_level.get_value(); + } +} // restoreCompleteState +//============================================================================= /** Constructor. Sets up the clock mode etc. */ SoccerWorld::SoccerWorld() : WorldWithRank() @@ -651,17 +687,19 @@ void SoccerWorld::onCheckGoalTriggered(bool first_goal) if (NetworkConfig::get()->isNetworking() && NetworkConfig::get()->isServer()) { - NetworkString p(PROTOCOL_GAME_EVENTS); - p.setSynchronous(true); - p.addUInt8(GameEventsProtocol::GE_PLAYER_GOAL) - .addUInt8((uint8_t)sd.m_id).addUInt8(sd.m_correct_goal) - .addUInt8(first_goal).addFloat(sd.m_time) - .addTime(m_ticks_back_to_own_goal) - .encodeString(sd.m_kart).encodeString(sd.m_player); + InternalGoalPacket packet; + packet.id = (uint8_t)sd.m_id; + packet.correct_goal = sd.m_correct_goal; + packet.first_goal = first_goal; + packet.time = sd.m_time; + packet.ticks_back_to_own_goal = m_ticks_back_to_own_goal; + packet.kart = sd.m_kart; + packet.player = sd.m_player; + // Added in 1.1, add missing handicap info and country code - NetworkString p_1_1 = p; - p_1_1.encodeString(sd.m_country_code) - .addUInt8(sd.m_handicap_level); + InternalGoalPacket packet_1_1 = packet; + packet_1_1.country_code = sd.m_country_code; + packet_1_1.handicap = sd.m_handicap_level; auto peers = STKHost::get()->getPeers(); for (auto& peer : peers) @@ -671,11 +709,11 @@ void SoccerWorld::onCheckGoalTriggered(bool first_goal) if (peer->getClientCapabilities().find("soccer_fixes") != peer->getClientCapabilities().end()) { - peer->sendPacket(&p_1_1, PRM_RELIABLE); + peer->sendPacket(packet_1_1); } else { - peer->sendPacket(&p, PRM_RELIABLE); + peer->sendPacket(packet); } } } @@ -701,10 +739,10 @@ void SoccerWorld::onCheckGoalTriggered(bool first_goal) } // onCheckGoalTriggered //----------------------------------------------------------------------------- -void SoccerWorld::handleResetBallFromServer(const NetworkString& ns) +void SoccerWorld::handleResetBallFromServer(const ResetBallPacket& packet) { int ticks_now = World::getWorld()->getTicksSinceStart(); - int ticks_back_to_own_goal = ns.getTime(); + int ticks_back_to_own_goal = packet.reset_ball_ticks; if (ticks_now >= ticks_back_to_own_goal) { Log::warn("SoccerWorld", "Server ticks %d is too close to client ticks " @@ -715,23 +753,26 @@ void SoccerWorld::handleResetBallFromServer(const NetworkString& ns) } // handleResetBallFromServer //----------------------------------------------------------------------------- -void SoccerWorld::handlePlayerGoalFromServer(const NetworkString& ns) +void SoccerWorld::handlePlayerGoalFromServer(const InternalGoalPacket& packet) { ScorerData sd = {}; - sd.m_id = ns.getUInt8(); - sd.m_correct_goal = ns.getUInt8() == 1; - bool first_goal = ns.getUInt8() == 1; - sd.m_time = ns.getFloat(); + sd.m_id = packet.id; + sd.m_correct_goal = packet.correct_goal; + bool first_goal = packet.first_goal; + sd.m_time = packet.time; int ticks_now = World::getWorld()->getTicksSinceStart(); - int ticks_back_to_own_goal = ns.getTime(); - ns.decodeString(&sd.m_kart); - ns.decodeStringW(&sd.m_player); + int ticks_back_to_own_goal = packet.ticks_back_to_own_goal; + sd.m_kart = packet.kart; + sd.m_player = packet.player; // Added in 1.1, add missing handicap info and country code if (NetworkConfig::get()->getServerCapabilities().find("soccer_fixes") != NetworkConfig::get()->getServerCapabilities().end()) { - ns.decodeString(&sd.m_country_code); - sd.m_handicap_level = (HandicapLevel)ns.getUInt8(); + if (packet.country_code.has_value()) + sd.m_country_code = packet.country_code.get_value(); + + if (packet.handicap.has_value()) + sd.m_handicap_level = (HandicapLevel)(packet.handicap.get_value()); } if (first_goal) @@ -936,11 +977,9 @@ void SoccerWorld::updateBallPosition(int ticks) m_reset_ball_ticks = getTicksSinceStart() + stk_config->time2Ticks(2.0f); - NetworkString p(PROTOCOL_GAME_EVENTS); - p.setSynchronous(true); - p.addUInt8(GameEventsProtocol::GE_RESET_BALL) - .addTime(m_reset_ball_ticks); - STKHost::get()->sendPacketToAllPeers(&p, PRM_RELIABLE); + ResetBallPacket packet; + packet.reset_ball_ticks = m_reset_ball_ticks; + Comm::sendPacketToPeers(packet); } else if (!NetworkConfig::get()->isNetworking()) { @@ -1176,89 +1215,60 @@ void SoccerWorld::enterRaceOverState() } } // enterRaceOverState - // ---------------------------------------------------------------------------- -void SoccerWorld::saveCompleteState(BareNetworkString* bns, std::shared_ptr peer) + +std::shared_ptr SoccerWorld::saveCompleteState(std::shared_ptr peer) { + auto packet = std::make_shared(); + + bool has_soccer_fixes = + peer->getClientCapabilities().find("soccer_fixes") != + peer->getClientCapabilities().end(); + const unsigned red_scorers = (unsigned)m_red_scorers.size(); - bns->addUInt32(red_scorers); + packet->red_scorers_count = red_scorers; for (unsigned i = 0; i < red_scorers; i++) - { - bns->addUInt8((uint8_t)m_red_scorers[i].m_id) - .addUInt8(m_red_scorers[i].m_correct_goal) - .addFloat(m_red_scorers[i].m_time) - .encodeString(m_red_scorers[i].m_kart) - .encodeString(m_red_scorers[i].m_player); - if (peer->getClientCapabilities().find("soccer_fixes") != - peer->getClientCapabilities().end()) - { - bns->encodeString(m_red_scorers[i].m_country_code) - .addUInt8(m_red_scorers[i].m_handicap_level); - } - } + packet->red_scorers.push_back(std::move(m_red_scorers[i].saveCompleteState(has_soccer_fixes))); const unsigned blue_scorers = (unsigned)m_blue_scorers.size(); - bns->addUInt32(blue_scorers); + packet->blue_scorers_count = blue_scorers; for (unsigned i = 0; i < blue_scorers; i++) - { - bns->addUInt8((uint8_t)m_blue_scorers[i].m_id) - .addUInt8(m_blue_scorers[i].m_correct_goal) - .addFloat(m_blue_scorers[i].m_time) - .encodeString(m_blue_scorers[i].m_kart) - .encodeString(m_blue_scorers[i].m_player); - if (peer->getClientCapabilities().find("soccer_fixes") != - peer->getClientCapabilities().end()) - { - bns->encodeString(m_blue_scorers[i].m_country_code) - .addUInt8(m_blue_scorers[i].m_handicap_level); - } - } - bns->addTime(m_reset_ball_ticks).addTime(m_ticks_back_to_own_goal); + packet->blue_scorers.push_back(std::move(m_blue_scorers[i].saveCompleteState(has_soccer_fixes))); + + packet->reser_ball_ticks = m_reset_ball_ticks; + packet->ticks_back_to_own_goal = m_ticks_back_to_own_goal; + return packet; } // saveCompleteState // ---------------------------------------------------------------------------- -void SoccerWorld::restoreCompleteState(const BareNetworkString& b) +void SoccerWorld::restoreCompleteState(const std::shared_ptr& packet) { + std::shared_ptr soccer_packet = + std::dynamic_pointer_cast(packet); + m_red_scorers.clear(); m_blue_scorers.clear(); - const unsigned red_size = b.getUInt32(); + // As we don't know the peer, we assume our has_soccer_fixes based on what + // SERVER has told us. This is wrong. + + const unsigned red_size = soccer_packet->red_scorers_count; for (unsigned i = 0; i < red_size; i++) { ScorerData sd; - sd.m_id = b.getUInt8(); - sd.m_correct_goal = b.getUInt8() == 1; - sd.m_time = b.getFloat(); - b.decodeString(&sd.m_kart); - b.decodeStringW(&sd.m_player); - if (NetworkConfig::get()->getServerCapabilities().find("soccer_fixes") - != NetworkConfig::get()->getServerCapabilities().end()) - { - b.decodeString(&sd.m_country_code); - sd.m_handicap_level = (HandicapLevel)b.getUInt8(); - } + sd.restoreCompleteState(soccer_packet->red_scorers[i]); m_red_scorers.push_back(sd); } - const unsigned blue_size = b.getUInt32(); + const unsigned blue_size = soccer_packet->blue_scorers_count; for (unsigned i = 0; i < blue_size; i++) { ScorerData sd; - sd.m_id = b.getUInt8(); - sd.m_correct_goal = b.getUInt8() == 1; - sd.m_time = b.getFloat(); - b.decodeString(&sd.m_kart); - b.decodeStringW(&sd.m_player); - if (NetworkConfig::get()->getServerCapabilities().find("soccer_fixes") - != NetworkConfig::get()->getServerCapabilities().end()) - { - b.decodeString(&sd.m_country_code); - sd.m_handicap_level = (HandicapLevel)b.getUInt8(); - } + sd.restoreCompleteState(soccer_packet->blue_scorers[i]); m_blue_scorers.push_back(sd); } - m_reset_ball_ticks = b.getTime(); - m_ticks_back_to_own_goal = b.getTime(); + m_reset_ball_ticks = soccer_packet->reser_ball_ticks; + m_ticks_back_to_own_goal = soccer_packet->ticks_back_to_own_goal; } // restoreCompleteState // ---------------------------------------------------------------------------- @@ -1357,37 +1367,36 @@ std::pair SoccerWorld::getCount() const { void SoccerWorld::tellCountToEveryoneInGame() const { auto peers = STKHost::get()->getPeers(); - NetworkString* chat = new NetworkString(PROTOCOL_LOBBY_ROOM); - chat->addUInt8(17); // LE_CHAT - chat->setSynchronous(true); auto real_score = getCount(); int real_red = real_score.first; int real_blue = real_score.second; - std::string real_count = - std::to_string(real_red) + " : " + std::to_string(real_blue); - chat->encodeString16(StringUtils::utf8ToWide(real_count)); + std::string real_count = std::to_string(real_red) + + " : " + std::to_string(real_blue); + + // This should be done using sendStringTo... + ChatPacket packet; + packet.message = StringUtils::utf8ToWide(real_count); + for (auto& peer : peers) if (peer->isValidated() && !peer->isWaitingForGame()) - peer->sendPacket(chat, PRM_RELIABLE); - - delete chat; + peer->sendPacket(packet); } // tellCountToEveryoneInGame // ---------------------------------------------------------------------------- void SoccerWorld::tellCount(std::shared_ptr peer) const { if (!peer->isValidated()) return; - NetworkString* chat = new NetworkString(PROTOCOL_LOBBY_ROOM); - chat->addUInt8(17); // LE_CHAT - chat->setSynchronous(true); + auto real_score = getCount(); int real_red = real_score.first; int real_blue = real_score.second; std::string real_count = std::to_string(real_red) + " : " + std::to_string(real_blue); - chat->encodeString16(StringUtils::utf8ToWide(real_count)); - peer->sendPacket(chat, PRM_RELIABLE); - delete chat; + + // This should be done using sendStringTo... + ChatPacket packet; + packet.message = StringUtils::utf8ToWide(real_count); + peer->sendPacket(packet); } // tellCount // ---------------------------------------------------------------------------- diff --git a/src/modes/soccer_world.hpp b/src/modes/soccer_world.hpp index e0de86fd9f3..17758894efc 100644 --- a/src/modes/soccer_world.hpp +++ b/src/modes/soccer_world.hpp @@ -28,7 +28,6 @@ class AbstractKart; class BallGoalData; class Controller; -class NetworkString; class TrackObject; class TrackSector; @@ -55,6 +54,9 @@ class SoccerWorld : public WorldWithRank std::string m_country_code; /** Handicap of player. */ HandicapLevel m_handicap_level; + + ScorerDataPacket saveCompleteState(bool has_soccer_fixes); + void restoreCompleteState(const ScorerDataPacket& packet); }; // ScorerData private: @@ -234,9 +236,9 @@ class SoccerWorld : public WorldWithRank /** Get the AI who will attack the other team ball chaser. */ int getAttacker(KartTeam team) const; // ------------------------------------------------------------------------ - void handlePlayerGoalFromServer(const NetworkString& ns); + void handlePlayerGoalFromServer(const InternalGoalPacket& packet); // ------------------------------------------------------------------------ - void handleResetBallFromServer(const NetworkString& ns); + void handleResetBallFromServer(const ResetBallPacket& packet); // ------------------------------------------------------------------------ virtual bool hasTeam() const OVERRIDE { return true; } // ------------------------------------------------------------------------ @@ -263,10 +265,9 @@ class SoccerWorld : public WorldWithRank return progress; } // ------------------------------------------------------------------------ - virtual void saveCompleteState(BareNetworkString* bns, - std::shared_ptr peer) OVERRIDE; + virtual std::shared_ptr saveCompleteState(std::shared_ptr peer) OVERRIDE; // ------------------------------------------------------------------------ - virtual void restoreCompleteState(const BareNetworkString& b) OVERRIDE; + virtual void restoreCompleteState(const std::shared_ptr& b) OVERRIDE; // ------------------------------------------------------------------------ virtual bool isGoalPhase() const OVERRIDE { diff --git a/src/modes/world.hpp b/src/modes/world.hpp index de26d82e22b..f2f0c206c1b 100644 --- a/src/modes/world.hpp +++ b/src/modes/world.hpp @@ -376,9 +376,9 @@ class World : public WorldStatus m_eliminated_karts--; } // ------------------------------------------------------------------------ - virtual void saveCompleteState(BareNetworkString* bns, std::shared_ptr peer) {} + virtual std::shared_ptr saveCompleteState(std::shared_ptr peer) { return {}; } // ------------------------------------------------------------------------ - virtual void restoreCompleteState(const BareNetworkString& buffer) {} + virtual void restoreCompleteState(const std::shared_ptr& buffer) {} // ------------------------------------------------------------------------ /** The code that draws the timer should call this first to know * whether the game mode wants a timer drawn. */ diff --git a/src/network/compress_network_body.hpp b/src/network/compress_network_body.hpp index 9071cc521b8..b9f6b281d6d 100644 --- a/src/network/compress_network_body.hpp +++ b/src/network/compress_network_body.hpp @@ -59,7 +59,7 @@ namespace CompressNetworkBody * and server have similar state when saving state if you don't provoide * bns. */ - inline void compress(btRigidBody* body, btMotionState* ms, + inline CompressedNetworkBodyPacket compress(btRigidBody* body, btMotionState* ms, BareNetworkString* bns = NULL) { float x = body->getWorldTransform().getOrigin().x(); @@ -75,29 +75,39 @@ namespace CompressNetworkBody short avz = toFloat16(body->getAngularVelocity().z()); setCompressedValues(x, y, z, compressed_q, lvx, lvy, lvz, avx, avy, avz, body, ms); - // if bns is null, it's locally compress (for rounding values) - if (!bns) - return; - bns->addFloat(x).addFloat(y).addFloat(z).addUInt32(compressed_q); - bns->addUInt16(lvx).addUInt16(lvy).addUInt16(lvz) - .addUInt16(avx).addUInt16(avy).addUInt16(avz); + // if bns is null, it's locally compressed (for rounding values) + // in that case, we simply disregard the result, and before it returned NULL + + CompressedNetworkBodyPacket packet; + packet.x = x; + packet.y = y; + packet.z = z; + packet.compressed_q = compressed_q; + packet.lvx = lvx; + packet.lvy = lvy; + packet.lvz = lvz; + packet.avx = avx; + packet.avy = avy; + packet.avz = avz; + + return packet; } // compress // ------------------------------------------------------------------------ /* Called during rewind when restoring data from game state. */ - inline void decompress(const BareNetworkString* bns, + inline void decompress(const CompressedNetworkBodyPacket& packet, btRigidBody* body, btMotionState* ms) { - float x = bns->getFloat(); - float y = bns->getFloat(); - float z = bns->getFloat(); - uint32_t compressed_q = bns->getUInt32(); - short lvx = bns->getUInt16(); - short lvy = bns->getUInt16(); - short lvz = bns->getUInt16(); - short avx = bns->getUInt16(); - short avy = bns->getUInt16(); - short avz = bns->getUInt16(); + float x = packet.x; + float y = packet.y; + float z = packet.z; + uint32_t compressed_q = packet.compressed_q; + short lvx = packet.lvx; + short lvy = packet.lvy; + short lvz = packet.lvz; + short avx = packet.avx; + short avy = packet.avy; + short avz = packet.avz; setCompressedValues(x, y, z, compressed_q, lvx, lvy, lvz, avx, avy, avz, body, ms); } // decompress diff --git a/src/network/event.cpp b/src/network/event.cpp index 6c5227ef85f..c7b96d51ede 100644 --- a/src/network/event.cpp +++ b/src/network/event.cpp @@ -104,4 +104,4 @@ Event::~Event() { delete m_data; } // ~Event - +//----------------------------------------------------------------------------- \ No newline at end of file diff --git a/src/network/event.hpp b/src/network/event.hpp index 2dab2701c81..0afd089402a 100644 --- a/src/network/event.hpp +++ b/src/network/event.hpp @@ -127,6 +127,14 @@ class Event // ------------------------------------------------------------------------ PeerDisconnectInfo getPeerDisconnectInfo() const { return m_pdi; } // ------------------------------------------------------------------------ + template + T getPacket() + { + T packet; + packet.fromNetworkString(m_data); + return packet; + } // getPacket + // ------------------------------------------------------------------------ }; // class Event diff --git a/src/network/game_setup.cpp b/src/network/game_setup.cpp index 326b0da6e69..f4860db1b95 100644 --- a/src/network/game_setup.cpp +++ b/src/network/game_setup.cpp @@ -24,6 +24,7 @@ #include "network/network_config.hpp" #endif #include "network/network_player_profile.hpp" +#include "network/packet_types.hpp" #include "network/peer_vote.hpp" #include "network/protocols/server_lobby.hpp" #include "network/server_config.hpp" @@ -102,51 +103,68 @@ void GameSetup::loadWorld() } // loadWorld //----------------------------------------------------------------------------- -void GameSetup::addServerInfo(NetworkString* ns) +ServerInfoPacket GameSetup::addServerInfo() { #ifdef DEBUG assert(NetworkConfig::get()->isServer()); #endif - ns->encodeString(m_server_name_utf8); + ServerInfoPacket packet; + + packet.server_name = m_server_name_utf8; + auto sl = LobbyProtocol::get(); assert(sl); - ns->addUInt8((uint8_t)sl->getDifficulty()) - .addUInt8((uint8_t)ServerConfig::m_server_max_players) - // Reserve for extra spectators - .addUInt8(0) - .addUInt8((uint8_t)sl->getGameMode()); + + packet.difficulty = (uint8_t)sl->getDifficulty(); + + // probably getSettings()-> + packet.max_players = (uint8_t)ServerConfig::m_server_max_players; + + packet.extra_spectators_zero = 0; + packet.game_mode = (uint8_t)sl->getGameMode(); + if (hasExtraServerInfo()) { if (isGrandPrix()) { + // has_extra_server_info is used for current track index uint8_t cur_track = (uint8_t)m_tracks.size(); if (!isGrandPrixStarted()) cur_track = 0; - ns->addUInt8((uint8_t)2).addUInt8(cur_track) - .addUInt8(getExtraServerInfo()); + + packet.has_extra_server_info = 2; + packet.extra_server_info.push_back(cur_track); + packet.extra_server_info.push_back(m_extra_server_info); } else { // Soccer mode - ns->addUInt8((uint8_t)1).addUInt8(getExtraServerInfo()); + packet.has_extra_server_info = 1; + packet.extra_server_info.push_back(m_extra_server_info); } } else { - // No extra server info - ns->addUInt8((uint8_t)0); + packet.has_extra_server_info = 0; + packet.extra_server_info = {}; } + if (ServerConfig::m_owner_less) { - ns->addUInt8(ServerConfig::m_min_start_game_players) - .addFloat(std::max(0.0f, getSettings()->getStartGameCounter())); + // probably getSettings()-> also + packet.min_start_game_players = ServerConfig::m_min_start_game_players; + packet.start_game_counter = std::max(0.0f, getSettings()->getStartGameCounter()); } else - ns->addUInt8(0).addFloat(0.0f); + { + packet.min_start_game_players = 0; + packet.start_game_counter = 0.0f; + } - ns->encodeString16(m_message_of_today); - ns->addUInt8((uint8_t)getSettings()->isServerConfigurable()); - ns->addUInt8(getSettings()->isLivePlayers() ? 1 : 0); + packet.motd = m_message_of_today; + packet.is_configurable = getSettings()->isServerConfigurable(); + packet.has_live_players = getSettings()->isLivePlayers(); + return packet; } // addServerInfo //----------------------------------------------------------------------------- diff --git a/src/network/game_setup.hpp b/src/network/game_setup.hpp index 20c4c35c3f7..2fcca78c933 100644 --- a/src/network/game_setup.hpp +++ b/src/network/game_setup.hpp @@ -32,8 +32,8 @@ #include class NetworkPlayerProfile; -class NetworkString; class PeerVote; +class ServerInfoPacket; // ============================================================================ /*! \class GameSetup @@ -94,7 +94,7 @@ class GameSetup: public LobbyContextUser m_extra_server_info = tracks_no; } // ------------------------------------------------------------------------ - void addServerInfo(NetworkString* ns); + ServerInfoPacket addServerInfo(); // ------------------------------------------------------------------------ void loadWorld(); // ------------------------------------------------------------------------ diff --git a/src/network/kart_data.cpp b/src/network/kart_data.cpp index 577b4f479f0..8b3048140f6 100644 --- a/src/network/kart_data.cpp +++ b/src/network/kart_data.cpp @@ -2,7 +2,7 @@ #include "karts/kart_model.hpp" #include "karts/kart_properties.hpp" -#include "network/network_string.hpp" +#include "network/packet_types.hpp" // ---------------------------------------------------------------------------- KartData::KartData(const KartProperties* kp) @@ -24,15 +24,19 @@ KartData::KartData(const KartProperties* kp) } // KartData(KartProperties*) // ---------------------------------------------------------------------------- -KartData::KartData(const BareNetworkString& ns) +KartData::KartData(const KartDataPacket& packet) { - ns.decodeString(&m_kart_type); + m_kart_type = ""; + if (packet.kart_type.has_value()) + m_kart_type = packet.kart_type.get_value(); + if (!m_kart_type.empty()) { - m_width = ns.getFloat(); - m_height = ns.getFloat(); - m_length = ns.getFloat(); - m_gravity_shift = ns.getVec3(); + auto value = packet.parameters.get_value(); + m_width = value.width; + m_height = value.height; + m_length = value.length; + m_gravity_shift = value.gravity_shift; } else { @@ -40,15 +44,24 @@ KartData::KartData(const BareNetworkString& ns) m_height = 0.0f; m_length = 0.0f; } -} // KartData(BareNetworkString&) +} // KartData(KartDataPacket&) // ---------------------------------------------------------------------------- -void KartData::encode(BareNetworkString* ns) const +KartDataPacket KartData::encode() const { - ns->encodeString(m_kart_type); + KartDataPacket packet; + packet.kart_type = m_kart_type; + if (!m_kart_type.empty()) { - ns->addFloat(m_width).addFloat(m_height).addFloat(m_length) - .add(m_gravity_shift); + KartParametersPacket params; + params.width = m_width; + params.height = m_height; + params.length = m_length; + params.gravity_shift = m_gravity_shift; + + packet.parameters = params; } -} // encode(BareNetworkString*) + + return packet; +} // encode() diff --git a/src/network/kart_data.hpp b/src/network/kart_data.hpp index a9c750c234f..e31c757542d 100644 --- a/src/network/kart_data.hpp +++ b/src/network/kart_data.hpp @@ -1,11 +1,11 @@ #ifndef KART_DATA_HPP #define KART_DATA_HPP +#include "network/packet_types.hpp" #include "utils/vec3.hpp" #include -class BareNetworkString; class KartProperties; class KartData @@ -26,9 +26,9 @@ class KartData // ------------------------------------------------------------------------ KartData(const KartProperties* kp); // ------------------------------------------------------------------------ - KartData(const BareNetworkString& ns); + KartData(const KartDataPacket& packet); // ------------------------------------------------------------------------ - void encode(BareNetworkString* ns) const; + KartDataPacket encode() const; }; // class KartData diff --git a/src/network/network_console.cpp b/src/network/network_console.cpp index 2ea5dfdfcea..53c20a100d7 100644 --- a/src/network/network_console.cpp +++ b/src/network/network_console.cpp @@ -210,7 +210,7 @@ void mainLoop(STKHost* host) message.pop_back(); auto sl = LobbyProtocol::get(); if (sl && !message.empty()) - Comm::sendStringToAllPeers(message); + Comm::sendStringToPeers(message); } else { diff --git a/src/network/network_player_profile.cpp b/src/network/network_player_profile.cpp index ac44a2fcc03..266f65c9373 100644 --- a/src/network/network_player_profile.cpp +++ b/src/network/network_player_profile.cpp @@ -22,6 +22,7 @@ #include "utils/string_utils.hpp" #include "utils/name_decorators/generic_decorator.hpp" +#include "network/packet_types.hpp" // ---------------------------------------------------------------------------- /** Returns true if this player is local, i.e. running on this computer. This @@ -43,3 +44,19 @@ core::stringw NetworkPlayerProfile::getDecoratedName(std::shared_ptrdecorate(StringUtils::wideToUtf8(m_player_name))); } // getDecoratedName // ---------------------------------------------------------------------------- + +EncodedSinglePlayerPacket NetworkPlayerProfile::getPacket() const +{ + EncodedSinglePlayerPacket packet; + packet.name = getName(); + packet.host_id = getHostId(); + packet.kart_color = getDefaultKartColor(); + packet.online_id = getOnlineId(); + packet.handicap = getHandicap(); + packet.local_player_id = getLocalPlayerId(); + packet.kart_team = getTeam(); + packet.country_code = getCountryCode(); + packet.kart_name = getKartName(); + return packet; +} // getPacket +//----------------------------------------------------------------------------- diff --git a/src/network/network_player_profile.hpp b/src/network/network_player_profile.hpp index 7df9c6eca40..51ef182fb0a 100644 --- a/src/network/network_player_profile.hpp +++ b/src/network/network_player_profile.hpp @@ -36,6 +36,7 @@ class STKPeer; class GenericDecorator; enum KartTeam : int8_t; enum HandicapLevel : uint8_t; +class EncodedSinglePlayerPacket; /*! \class NetworkPlayerProfile * \brief Contains the profile of a player. @@ -193,6 +194,9 @@ class NetworkPlayerProfile core::stringw getDecoratedName(std::shared_ptr decorator); // ------------------------------------------------------------------------ + // ------------------------------------------------------------------------ + EncodedSinglePlayerPacket getPacket() const; + // ------------------------------------------------------------------------ }; // class NetworkPlayerProfile #endif // HEADER_NETWORK_PLAYER_PROFILE diff --git a/src/network/network_string.cpp b/src/network/network_string.cpp index 8d2a396b994..af3a1766600 100644 --- a/src/network/network_string.cpp +++ b/src/network/network_string.cpp @@ -248,74 +248,160 @@ std::string BareNetworkString::getLogMessage(const std::string &indent) const template<> -void BareNetworkString::encode(const uint32_t& value) +void NetworkString::encodeSpecific(const uint64_t& value) +{ + addUInt64(value); +} // encode(uint64_t) +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +template<> +void NetworkString::decodeSpecific(uint64_t& value) +{ + value = getUInt64(); +} // decodeSpecific(uint64_t) +//----------------------------------------------------------------------------- +template<> +void NetworkString::encodeSpecific(const uint32_t& value) { addUInt32(value); } // encode(uint32_t) //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template<> -void BareNetworkString::decode(uint32_t& value) +void NetworkString::decodeSpecific(uint32_t& value) { value = getUInt32(); -} // decode(uint32_t) +} // decodeSpecific(uint32_t) //----------------------------------------------------------------------------- template<> -void BareNetworkString::encode(const uint8_t& value) +void NetworkString::encodeSpecific(const uint16_t& value) +{ + addUInt16(value); +} // encode(uint16_t) +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +template<> +void NetworkString::decodeSpecific(uint16_t& value) +{ + value = getUInt16(); +} // decodeSpecific(uint16_t) +//----------------------------------------------------------------------------- +template<> +void NetworkString::encodeSpecific(const uint8_t& value) { addUInt8(value); } // encode(uint8_t) //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template<> -void BareNetworkString::decode(uint8_t& value) +void NetworkString::decodeSpecific(uint8_t& value) { value = getUInt8(); -} // decode(uint8_t) +} // decodeSpecific(uint8_t) //----------------------------------------------------------------------------- template<> -void BareNetworkString::encode(const irr::core::stringw& value) +void NetworkString::encodeSpecific(const irr::core::stringw& value) { encodeString(value); } // encode(irr::core::stringw) //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template<> -void BareNetworkString::decode(irr::core::stringw& value) +void NetworkString::decodeSpecific(irr::core::stringw& value) { decodeStringW(&value); -} // decode(irr::core::stringw) +} // decodeSpecific(irr::core::stringw) //----------------------------------------------------------------------------- template<> -void BareNetworkString::encode(const std::string& value) +void NetworkString::encodeSpecific(const std::string& value) { encodeString(value); } // encode(std::string) //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template<> -void BareNetworkString::decode(std::string& value) +void NetworkString::decodeSpecific(std::string& value) { decodeString(&value); -} // decode(std::string) +} // decodeSpecific(std::string) //----------------------------------------------------------------------------- template<> -void BareNetworkString::encode(const bool& value) +void NetworkString::encodeSpecific(const bool& value) { addUInt8(value ? 1 : 0); } // encode(bool) //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template<> -void BareNetworkString::decode(bool& value) +void NetworkString::decodeSpecific(bool& value) { value = getUInt8() == 1; -} // decode(bool) +} // decodeSpecific(bool) +//----------------------------------------------------------------------------- +template<> +void NetworkString::encodeSpecific(const Vec3& value) +{ + add(value); +} // encode(Vec3) +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +template<> +void NetworkString::decodeSpecific(Vec3& value) +{ + value = getVec3(); +} // decodeSpecific(Vec3) +//----------------------------------------------------------------------------- +template<> +void NetworkString::encodeSpecific(const btQuaternion& value) +{ + add(value); +} // encode(btQuaternion) +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +template<> +void NetworkString::decodeSpecific(btQuaternion& value) +{ + value = getQuat(); +} // decodeSpecific(btQuaternion) //----------------------------------------------------------------------------- +template<> +void NetworkString::encodeSpecific(const float& value) +{ + addFloat(value); +} // encodeSpecific(float) +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +template<> +void NetworkString::decodeSpecific(float& value) +{ + value = getFloat(); +} // decodeSpecific(float) +// //----------------------------------------------------------------------------- +template<> +void NetworkString::encodeSpecific(const KartTeam& value) +{ + encodeSpecific((uint8_t)value); +} // encodeSpecific(KartTeam) +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +template<> +void NetworkString::decodeSpecific(KartTeam& value) +{ + uint8_t u8; + decodeSpecific(u8); + value = (KartTeam)u8; +} // decodeSpecific(KartTeam) +// //----------------------------------------------------------------------------- +template<> +void NetworkString::encodeSpecific(const int24_t& value) +{ + addInt24(value.value); +} // encodeSpecific(KartTeam) +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +template<> +void NetworkString::decodeSpecific(int24_t& value) +{ + value.value = getInt24(); +} // decodeSpecific(KartTeam) +// //----------------------------------------------------------------------------- // template<> -// void BareNetworkString::encode(const T& value) +// void NetworkString::encodeSpecific(const T& value) // { -// } // encode(T) +// } // encodeSpecific(T) // //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // template<> -// void BareNetworkString::decode(T& value) +// void NetworkString::decodeSpecific(T& value) // { -// } // decode(T) +// } // decodeSpecific(T) // //----------------------------------------------------------------------------- diff --git a/src/network/network_string.hpp b/src/network/network_string.hpp index fe362af8f82..bca836269eb 100644 --- a/src/network/network_string.hpp +++ b/src/network/network_string.hpp @@ -24,6 +24,7 @@ #define NETWORK_STRING_HPP #include "network/protocol.hpp" +#include "network/packet_types.hpp" #include "utils/leak_check.hpp" #include "utils/types.hpp" #include "utils/vec3.hpp" @@ -38,6 +39,7 @@ #include #include #include +#include typedef unsigned char uchar; @@ -134,6 +136,11 @@ friend class Crypto; encodeString(s); } // BareNetworkString // ------------------------------------------------------------------------ + void reserve(int capacity) + { + m_buffer.reserve(capacity); + } // reserve + // ------------------------------------------------------------------------ /** Initialises the string with a sequence of characters. */ BareNetworkString(const char *data, int len) { @@ -187,6 +194,8 @@ friend class Crypto; // ------------------------------------------------------------------------ int getCurrentOffset() const { return m_current_offset; } // ------------------------------------------------------------------------ + void setCurrentOffset(int value) const { m_current_offset = value; } + // ------------------------------------------------------------------------ /** Returns the remaining length of the network string. */ unsigned int size() const { return (int)m_buffer.size()-m_current_offset; } @@ -398,12 +407,6 @@ friend class Crypto; return q; } // getQuat // ------------------------------------------------------------------------ - template - void encode(const T& value); - // ------------------------------------------------------------------------ - template - void decode(T& value); - // ------------------------------------------------------------------------ }; // class BareNetworkString @@ -428,12 +431,17 @@ class NetworkString : public BareNetworkString { public: static void unitTesting(); - + + NetworkString(): BareNetworkString() + { + m_buffer.push_back(ProtocolType::PROTOCOL_NONE); + } + /** Constructor for a message to be sent. It sets the * protocol type of this message. It adds 1 byte to the capacity: * 1 byte for the protocol type. */ - NetworkString(ProtocolType type, int capacity=16) - : BareNetworkString(capacity+1) + NetworkString(ProtocolType type, int capacity=16) + : BareNetworkString(capacity + 1) { m_buffer.push_back(type); } // NetworkString @@ -462,6 +470,14 @@ class NetworkString : public BareNetworkString return (ProtocolType)(m_buffer.at(0) & ~PROTOCOL_SYNCHRONOUS); } // getProtocolType + // ------------------------------------------------------------------------ + /** Sets the protocol type of this message. */ + void setProtocolType(ProtocolType type) + { + m_buffer.at(0) &= PROTOCOL_SYNCHRONOUS; + m_buffer.at(0) |= (type & (~PROTOCOL_SYNCHRONOUS)); + } // getProtocolType + // ------------------------------------------------------------------------ /** Sets if this message is to be sent synchronous or asynchronous. */ void setSynchronous(bool b) @@ -477,6 +493,49 @@ class NetworkString : public BareNetworkString { return (m_buffer[0] & PROTOCOL_SYNCHRONOUS) == PROTOCOL_SYNCHRONOUS; } // isSynchronous + // ------------------------------------------------------------------------ + template + void encodeSpecific(const T& value); + // ------------------------------------------------------------------------ + template + void decodeSpecific(T& value); + // ------------------------------------------------------------------------ + template + void encodeMaybePacket(const T& value, std::false_type) + { + encodeSpecific(value); + } + // ------------------------------------------------------------------------ + template + void decodeMaybePacket(T& value, std::false_type) + { + decodeSpecific(value); + } + // ------------------------------------------------------------------------ + template + void encodeMaybePacket(const T& value, std::true_type) + { + value.toNetworkString(this); + } + // ------------------------------------------------------------------------ + template + void decodeMaybePacket(T& value, std::true_type) + { + value.fromNetworkString(this); + } + // ------------------------------------------------------------------------ + template + void encode(const T& value) + { + encodeMaybePacket(value, std::is_base_of()); + } // encode + // ------------------------------------------------------------------------ + template + void decode(T& value) + { + decodeMaybePacket(value, std::is_base_of()); + } // decode + // ------------------------------------------------------------------------ }; // class NetworkString diff --git a/src/network/packet_types.cpp b/src/network/packet_types.cpp new file mode 100644 index 00000000000..405f7eab549 --- /dev/null +++ b/src/network/packet_types.cpp @@ -0,0 +1,218 @@ +// +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2025 kimden +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "network/packet_types.hpp" +#include "network/remote_kart_info.hpp" +#include "network/network_string.hpp" + +namespace +{ + template + void setParentMaybePacket(T& value, Packet* pointer, std::true_type) + { + Packet* current = &value; + current->parent = pointer; + for (auto& p: pointer->m_storage) + { + value.m_storage[p.first] = p.second; + } + } + + template + void setParentMaybePacket(T& value, Packet* pointer, std::false_type) + { + // Not a packet, do nothing. + } + + template + void setParent(T& value, Packet* pointer) + { + setParentMaybePacket(value, pointer, std::is_base_of()); + } +} + +//---------------------- To NetworkString ------------------------------------- + +#define DEFINE_CLASS(Name) \ +void Name::toNetworkString(NetworkString* ns) const \ +{ + +#define DEFINE_DERIVED_CLASS(Name, Parent) DEFINE_CLASS(Name) + +#define PROTOCOL_TYPE(Type, Sync) \ + ns->setProtocolType(Type); \ + if (!m_override_synchronous.has_value()) \ + ns->setSynchronous(Sync); \ + else \ + ns->setSynchronous(m_override_synchronous.get_value()); + +#define AUX_STORE(Key, Var) + +#define AUX_VAR(Type, Var) + +#define AUX_VAR_VALUE(Type, Var, Value) + +#define AUX_VAR_FROM_PARENT(Type, Key, Var) + +#define DEFINE_FIELD(Type, Var) \ + ns->encode(Var); + +#define DEFINE_FIELD16(Type, Var) \ + ns->encodeString16(Var); + +#define DEFINE_FIELD_PTR(Type, Var) \ + if (Var) \ + ns->encode(*Var); + +// We send it if it exists, and receive only if the condition is true +#define DEFINE_FIELD_OPTIONAL(Type, Var, Condition) \ + if (Var.has_value()) \ + ns->encode(Var.get_value()); + +#define DEFINE_TYPE(Type, Var, Value) \ + ns->encode(Value); + +#define DEFINE_VECTOR(Type, Size, Value) \ + for (unsigned Value##_cnt = 0; Value##_cnt < Value.size(); ++Value##_cnt) { \ + ns->encode(Value[Value##_cnt]); \ + } + +/* Might have additional size inconsistencies due to nullptrs being omitted. */ +#define DEFINE_VECTOR_PTR(Type, Size, Value) \ + for (unsigned Value##_cnt = 0; Value##_cnt < Value.size(); ++Value##_cnt) { \ + if (Value[Value##_cnt]) \ + ns->encode(*(Value[Value##_cnt])); \ + } + +#define RELIABLE(Value) + +#define END_DEFINE_CLASS(Name) \ +} + +#include "network/packet_types_base.hpp" +#undef DEFINE_CLASS +#undef DEFINE_DERIVED_CLASS +#undef PROTOCOL_TYPE +#undef AUX_STORE +#undef AUX_VAR +#undef AUX_VAR_VALUE +#undef AUX_VAR_FROM_PARENT +#undef DEFINE_FIELD +#undef DEFINE_FIELD16 +#undef DEFINE_FIELD_PTR +#undef DEFINE_TYPE +#undef DEFINE_FIELD_OPTIONAL +#undef DEFINE_VECTOR +#undef DEFINE_VECTOR_PTR +#undef RELIABLE +#undef END_DEFINE_CLASS + + + + +//---------------------- From NetworkString ----------------------------------- + +#define DEFINE_CLASS(Name) \ +void Name::fromNetworkString(NetworkString* ns) \ +{ + +#define DEFINE_DERIVED_CLASS(Name, Parent) DEFINE_CLASS(Name) + +#define PROTOCOL_TYPE(Type, Sync) + +#define AUX_STORE(Key, Var) \ + store(Key, Var); + +#define AUX_VAR(Type, Var) + +#define AUX_VAR_VALUE(Type, Var, Value) \ + Var = (Value); + +#define AUX_VAR_FROM_PARENT(Type, Key, Var) \ + Var = parent->obtain(Key); + +#define DEFINE_FIELD(Type, Var) \ + setParent(Var, this); \ + ns->decode(Var); + +#define DEFINE_FIELD16(Type, Var) \ + ns->decodeString16(&Var); + +// Same as optional but unconditional +#define DEFINE_FIELD_PTR(Type, Var) \ + Type temp_##Var; \ + setParent(temp_##Var, this); \ + ns->decode(temp_##Var); \ + Var = std::make_shared(temp_##Var); \ + +// We send it if it exists, and receive only if the condition is true +#define DEFINE_FIELD_OPTIONAL(Type, Var, Condition) \ + if (Condition) { \ + int temp_prev_offset = ns->getCurrentOffset(); \ + Type temp_##Var; \ + setParent(temp_##Var, this); \ + try { \ + ns->decode(temp_##Var); \ + } catch (...) { \ + ns->setCurrentOffset(temp_prev_offset); \ + } \ + Var = temp_##Var; \ + } + +#define DEFINE_TYPE(Type, Var, Value) + +#define DEFINE_VECTOR(Type, Size, Var) \ + Var.resize(Size); \ + for (unsigned Var##_cnt = 0; Var##_cnt < Size; ++Var##_cnt) { \ + setParent(Var[Var##_cnt], this); \ + ns->decode(Var[Var##_cnt]); \ + } + +#define DEFINE_VECTOR_PTR(Type, Size, Var) \ + Var.resize(Size); \ + for (unsigned Var##_cnt = 0; Var##_cnt < Size; ++Var##_cnt) { \ + Type temp_##Var; \ + setParent(temp_##Var, this); \ + ns->decode(temp_##Var); \ + Var[Var##_cnt] = std::make_shared(temp_##Var); \ + } + +#define RELIABLE(Value) + +#define END_DEFINE_CLASS(Name) \ +} + +#include "network/packet_types_base.hpp" +#undef DEFINE_CLASS +#undef DEFINE_DERIVED_CLASS +#undef PROTOCOL_TYPE +#undef AUX_STORE +#undef AUX_VAR +#undef AUX_VAR_VALUE +#undef AUX_VAR_FROM_PARENT +#undef DEFINE_FIELD +#undef DEFINE_FIELD16 +#undef DEFINE_FIELD_PTR +#undef DEFINE_TYPE +#undef DEFINE_FIELD_OPTIONAL +#undef DEFINE_VECTOR +#undef DEFINE_VECTOR_PTR +#undef RELIABLE +#undef END_DEFINE_CLASS + +//---------------------- End -------------------------------------------------- \ No newline at end of file diff --git a/src/network/packet_types.hpp b/src/network/packet_types.hpp index 37be504b495..2eb83641888 100644 --- a/src/network/packet_types.hpp +++ b/src/network/packet_types.hpp @@ -19,8 +19,25 @@ #ifndef PACKET_TYPES_HPP #define PACKET_TYPES_HPP -#include "network/network_string.hpp" +// #include "network/network_string.hpp" +// #include "network/protocol.hpp" +#include "irrString.h" +#include "network/protocols/game_event_types.hpp" +#include "utils/cpp2011.hpp" +#include "utils/types.hpp" +#include "utils/vec3.hpp" +enum KartTeam: int8_t; +class NetworkString; +class BareNetworkString; + +#include +#include +#include +#include +#include + +using widestr = irr::core::stringw; /** * IMPORTANT! * This class is meant to describe the overall structure of network packets @@ -85,93 +102,201 @@ enum BackLobbyReason : uint8_t BLR_NO_GAME_FOR_LIVE_JOIN = 1, BLR_NO_PLACE_FOR_LIVE_JOIN = 2, BLR_ONE_PLAYER_IN_RANKED_MATCH = 3, - BLR_SERVER_ONWER_QUITED_THE_GAME = 4, + BLR_SERVER_OWNER_QUIT_THE_GAME = 4, BLR_SPECTATING_NEXT_GAME = 5 }; -//---------------------- Initialization --------------------------------------- - -#define DEFINE_CLASS(Name) \ -struct Name { \ - public: \ - void toNetworkString(NetworkString* ns) const; \ - void fromNetworkString(NetworkString* ns); +//---------------------- Basic packet definitions ----------------------------- -#define SYNCHRONOUS(Value) bool isSynchronous() { return Value; } -#define DEFINE_FIELD(Type, Var) Type Var; -#define DEFINE_FIXED_FIELD(Type, Var, Value) Type Var; -#define DEFINE_VECTOR(Type, Size, Var) std::vector Var; -#define END_DEFINE_CLASS(Name) }; +namespace +{ + const std::string SOCCER_FIXES = "soccer_fixes"; + const std::string REAL_ADDON_KARTS = "real_addon_karts"; +} -#include "network/packet_types_base.hpp" -#undef DEFINE_CLASS -#undef SYNCHRONOUS -#undef DEFINE_FIELD -#undef DEFINE_FIXED_FIELD -#undef DEFINE_VECTOR -#undef END_DEFINE_CLASS +class Checkable +{ +private: + uint32_t m_state = 0; +public: + bool check(uint32_t which) const { return (m_state >> which) & 1; } + void set(uint32_t which, bool value) + { + if (value) + m_state |= (1 << which); + else + m_state &= ~(1 << which); + } +}; -//---------------------- To NetworkString ------------------------------------- +template +class Optional +{ +private: + std::shared_ptr m_pointer; -#define DEFINE_CLASS(Name) \ -inline void Name::toNetworkString(NetworkString* ns) const \ -{ +public: + bool has_value() const { return m_pointer != nullptr; } + const T& get_value() const { return *m_pointer; } + void unset() const { m_pointer.reset(); } + const T& operator = (const T& value) + { m_pointer = std::make_shared(value); return value; } -#define SYNCHRONOUS(Value) \ - ns->setSynchronous(Value); + T get_or(const T& rhs) const + { return m_pointer != nullptr ? *m_pointer : rhs; } +}; -#define DEFINE_FIELD(Type, Var) \ - ns->encode(Var); +class Storage +{ +public: + std::map> m_storage; -#define DEFINE_FIXED_FIELD(Type, Var, Value) \ - ns->encode(Value); + template + void store(const std::string& key, const T& value) + { + m_storage[key] = std::static_pointer_cast(std::make_shared(value)); + } -#define DEFINE_VECTOR(Type, Size, Value) \ - for (unsigned Value##_cnt = 0; Value##_cnt < Size; ++Value##_cnt) { \ - Value[Value##_cnt].toNetworkString(ns); \ + template + T obtain(const std::string& key) + { + auto it = m_storage.find(key); + if (it == m_storage.end()) + return T(); // exception? + + auto ptr = std::static_pointer_cast(it->second); + if (!ptr) + return T(); // exception? + + return *ptr; } +}; -#define END_DEFINE_CLASS(Name) \ -} +enum PacketTypeId: uint16_t; + +class Packet: public Checkable, public Storage +{ +public: + std::function m_capability_checker; + + // Needed to dynamic_cast + virtual ~Packet() {} + + // 0 = NONE, but I haven't declared it yet + virtual PacketTypeId packetTypeId() const { return (PacketTypeId)0; } + virtual void toNetworkString(NetworkString* ns) const {} + virtual void fromNetworkString(NetworkString* ns) {} + virtual unsigned expectedCapacity() const { return 0; } + bool cap(const std::string& name) { return m_capability_checker(name); } + + Optional m_override_synchronous; + Optional m_override_reliable; + + Packet* parent = nullptr; +}; + +// temp +constexpr int IDONT_KNOW = 0; +constexpr bool UNUSED = false; + + +//---------------------- Enum type id --------------------------------------- + +#define DEFINE_CLASS(Name) PTID_##Name, \ + +#define DEFINE_DERIVED_CLASS(Name, Parent) PTID_##Name, \ + +#define PROTOCOL_TYPE(Type, Sync) +#define AUX_STORE(Key, Var) +#define AUX_VAR(Type, Var) +#define AUX_VAR_VALUE(Type, Var, Value) +#define AUX_VAR_FROM_PARENT(Type, Key, Var) +#define DEFINE_FIELD(Type, Var) +#define DEFINE_FIELD16(Type, Var) +#define DEFINE_FIELD_PTR(Type, Var) +#define DEFINE_FIELD_OPTIONAL(Type, Var, Condition) +#define DEFINE_TYPE(Type, Var, Value) +#define DEFINE_VECTOR(Type, Size, Var) +#define DEFINE_VECTOR_PTR(Type, Size, Var) +#define RELIABLE(Value) +#define END_DEFINE_CLASS(Name) +enum PacketTypeId: uint16_t +{ + PTID_NONE = 0, #include "network/packet_types_base.hpp" +}; + #undef DEFINE_CLASS -#undef SYNCHRONOUS +#undef DEFINE_DERIVED_CLASS +#undef PROTOCOL_TYPE +#undef AUX_STORE +#undef AUX_VAR +#undef AUX_VAR_VALUE +#undef AUX_VAR_FROM_PARENT #undef DEFINE_FIELD -#undef DEFINE_FIXED_FIELD +#undef DEFINE_FIELD16 +#undef DEFINE_FIELD_PTR +#undef DEFINE_TYPE +#undef DEFINE_FIELD_OPTIONAL #undef DEFINE_VECTOR +#undef DEFINE_VECTOR_PTR +#undef RELIABLE #undef END_DEFINE_CLASS -//---------------------- From NetworkString ----------------------------------- +//---------------------- Initialization --------------------------------------- #define DEFINE_CLASS(Name) \ -inline void Name::fromNetworkString(NetworkString* ns) \ -{ - -#define SYNCHRONOUS(Value) - -#define DEFINE_FIELD(Type, Var) \ - ns->decode(Var); - -#define DEFINE_FIXED_FIELD(Type, Var, Value) +class Name: public Packet { \ + public: \ + virtual ~Name() {} \ + virtual PacketTypeId packetTypeId() const OVERRIDE { return PTID_##Name; } \ + virtual void toNetworkString(NetworkString* ns) const OVERRIDE; \ + virtual void fromNetworkString(NetworkString* ns) OVERRIDE; -#define DEFINE_VECTOR(Type, Size, Var) \ - Var.resize(Size); \ - for (unsigned Var##_cnt = 0; Var##_cnt < Size; ++Var##_cnt) { \ - Var[Var##_cnt].fromNetworkString(ns); \ - } +#define DEFINE_DERIVED_CLASS(Name, Parent) \ +class Name: public Parent { \ + public: \ + virtual ~Name() {} \ + virtual PacketTypeId packetTypeId() const OVERRIDE { return PTID_##Name; } \ + virtual void toNetworkString(NetworkString* ns) const OVERRIDE; \ + virtual void fromNetworkString(NetworkString* ns) OVERRIDE; -#define END_DEFINE_CLASS(Name) \ -} +#define PROTOCOL_TYPE(Type, Sync) +#define AUX_STORE(Key, Var) +#define AUX_VAR(Type, Var) Type Var; +#define AUX_VAR_VALUE(Type, Var, Value) Type Var; +#define AUX_VAR_FROM_PARENT(Type, Key, Var) Type Var; +#define DEFINE_FIELD(Type, Var) Type Var; +#define DEFINE_FIELD16(Type, Var) Type Var; +#define DEFINE_FIELD_PTR(Type, Var) std::shared_ptr Var; +#define DEFINE_FIELD_OPTIONAL(Type, Var, Condition) Optional Var; +#define DEFINE_TYPE(Type, Var, Value) Type Var; +#define DEFINE_VECTOR(Type, Size, Var) std::vector Var; +#define DEFINE_VECTOR_PTR(Type, Size, Var) std::vector> Var; +#define RELIABLE(Value) +#define END_DEFINE_CLASS(Name) }; #include "network/packet_types_base.hpp" #undef DEFINE_CLASS -#undef SYNCHRONOUS +#undef DEFINE_DERIVED_CLASS +#undef PROTOCOL_TYPE +#undef AUX_STORE +#undef AUX_VAR +#undef AUX_VAR_VALUE +#undef AUX_VAR_FROM_PARENT #undef DEFINE_FIELD -#undef DEFINE_FIXED_FIELD +#undef DEFINE_FIELD16 +#undef DEFINE_FIELD_PTR +#undef DEFINE_TYPE +#undef DEFINE_FIELD_OPTIONAL #undef DEFINE_VECTOR +#undef DEFINE_VECTOR_PTR +#undef RELIABLE #undef END_DEFINE_CLASS -//---------------------- End -------------------------------------------------- +/* Don't forget to send RELIABLE(Value) packets with PRM_RELIABLE or PRM_UNRELIABLE if false */ + +//---------------------- End --------------------------------------- #endif // PACKET_TYPES_HPP diff --git a/src/network/packet_types_base.hpp b/src/network/packet_types_base.hpp index 558399d9e9b..e3cd79a6667 100644 --- a/src/network/packet_types_base.hpp +++ b/src/network/packet_types_base.hpp @@ -36,19 +36,18 @@ * For now, for each non-vector type you have in the packets, you have * to define encode and decode for BareNetworkString. * - * If you need to use a type tbhat includes a comma, such as std::map, + * If you need to use a type that includes a comma, such as std::map, * you can use either a #define or using = to pass it anyway. */ -#include "irrString.h" -#include "utils/types.hpp" - -#include -#include +// Note that bools are encoded using int8_t -using widestr = irr::core::stringw; +// Make sure all level 0 packets have protocol set! -// Note that bools are encoded using int8_t +DEFINE_CLASS(EncryptedBuffer) + AUX_VAR_FROM_PARENT(uint32_t, "encrypted_size", size) /* ConnectionRequestedPacket::encrypted_size */ + DEFINE_VECTOR(uint8_t, size, buffer) +END_DEFINE_CLASS(EncryptedBuffer) DEFINE_CLASS(PlayerListProfilePacket) DEFINE_FIELD(uint32_t, host_id) @@ -62,11 +61,829 @@ DEFINE_CLASS(PlayerListProfilePacket) END_DEFINE_CLASS(PlayerListProfilePacket) DEFINE_CLASS(PlayerListPacket) - SYNCHRONOUS(true) - DEFINE_FIXED_FIELD(uint8_t, type, LE_UPDATE_PLAYER_LIST) + PROTOCOL_TYPE(PROTOCOL_LOBBY_ROOM, true) + DEFINE_TYPE(uint8_t, type, LE_UPDATE_PLAYER_LIST) DEFINE_FIELD(bool, game_started) DEFINE_FIELD(uint8_t, all_profiles_size) DEFINE_VECTOR(PlayerListProfilePacket, all_profiles_size, all_profiles) END_DEFINE_CLASS(PlayerListPacket) +DEFINE_CLASS(EncodedSinglePlayerPacket) + DEFINE_FIELD(widestr, name) + DEFINE_FIELD(uint32_t, host_id) + DEFINE_FIELD(float, kart_color) + DEFINE_FIELD(uint32_t, online_id) + DEFINE_FIELD(uint8_t, handicap) + DEFINE_FIELD(uint8_t, local_player_id) + DEFINE_FIELD(uint8_t, kart_team) + DEFINE_FIELD(std::string, country_code) + DEFINE_FIELD(std::string, kart_name) +END_DEFINE_CLASS(EncodedSinglePlayerPacket) + +DEFINE_CLASS(EncodedPlayersPacket) +END_DEFINE_CLASS(EncodedPlayersPacket) + + +DEFINE_CLASS(PeerVotePacket) + DEFINE_FIELD(widestr, player_name) + DEFINE_FIELD(std::string, track_name) + DEFINE_FIELD(uint8_t, num_laps) + DEFINE_FIELD(bool, is_reverse) +END_DEFINE_CLASS(PeerVotePacket) + + +DEFINE_CLASS(DefaultVotePacket) + DEFINE_FIELD(uint32_t, winner_peer_id) + DEFINE_FIELD(PeerVotePacket, default_vote) +END_DEFINE_CLASS(DefaultVotePacket) + +DEFINE_CLASS(BattleInfoPacket) + DEFINE_FIELD(uint32_t, battle_hit_capture_limit) + DEFINE_FIELD(float, battle_time_limit) + DEFINE_FIELD(uint16_t, flag_return_time) + DEFINE_FIELD(uint16_t, flag_deactivated_time) +END_DEFINE_CLASS(BattleInfoPacket) + +DEFINE_CLASS(KartParametersPacket) + DEFINE_FIELD(float, width) + DEFINE_FIELD(float, height) + DEFINE_FIELD(float, length) + DEFINE_FIELD(Vec3, gravity_shift) +END_DEFINE_CLASS(KartParametersPacket) + +/* This is only read in CL when cap(REAL_ADDON_KARTS) in LoadWorldPacket. Is it like that in other packets? */ +DEFINE_CLASS(KartDataPacket) + DEFINE_FIELD_OPTIONAL(std::string, kart_type, check(0)) /* I have no idea when */ + DEFINE_FIELD_OPTIONAL(KartParametersPacket, parameters, check(1) && check(0)) /* check(1) = !kart_type.empty()*/ +END_DEFINE_CLASS(KartDataPacket) + +DEFINE_CLASS(MultipleKartDataPacket) + AUX_VAR_FROM_PARENT(uint8_t, "players_size", players_size) /* LoadWorldPacket::players_size */ + DEFINE_VECTOR(KartDataPacket, players_size, players_kart_data) +END_DEFINE_CLASS(MultipleKartDataPacket) + +DEFINE_CLASS(LoadWorldPacket) + PROTOCOL_TYPE(PROTOCOL_LOBBY_ROOM, true) + DEFINE_TYPE(uint8_t, type, LE_LOAD_WORLD) + DEFINE_FIELD(DefaultVotePacket, default_vote) + DEFINE_FIELD(bool, live_join) + DEFINE_FIELD(uint8_t, players_size) + AUX_STORE("players_size", players_size) + DEFINE_VECTOR(EncodedSinglePlayerPacket, players_size, all_players) + DEFINE_FIELD(uint32_t, item_seed) + DEFINE_FIELD_OPTIONAL(BattleInfoPacket, battle_info, check(0)) // RaceManager::get()->isBattleMode() + DEFINE_FIELD_OPTIONAL(MultipleKartDataPacket, karts_data, cap(REAL_ADDON_KARTS)) + RELIABLE(true) +END_DEFINE_CLASS(LoadWorldPacket) + +DEFINE_CLASS(PlacementPacket) + DEFINE_FIELD(Vec3, xyz) + DEFINE_FIELD(btQuaternion, rotation) +END_DEFINE_CLASS(PlacementPacket) + +DEFINE_CLASS(ItemStatePacket) + DEFINE_FIELD(uint8_t, type) + DEFINE_FIELD(uint8_t, original_type) + DEFINE_FIELD(uint32_t, ticks_till_return) + DEFINE_FIELD(uint32_t, item_id) + DEFINE_FIELD(uint32_t, deactive_ticks) + DEFINE_FIELD(uint32_t, used_up_counter) + DEFINE_FIELD(PlacementPacket, original_xyz_rotation) + DEFINE_FIELD(uint8_t, previous_owner) +END_DEFINE_CLASS(ItemStatePacket) + +DEFINE_CLASS(ItemCompleteStatePacket) + DEFINE_FIELD(bool, has_item) + DEFINE_FIELD_OPTIONAL(ItemStatePacket, item_state, has_item) +END_DEFINE_CLASS(ItemCompleteStatePacket) + +DEFINE_CLASS(NimCompleteStatePacket) + DEFINE_FIELD(uint32_t, ticks_since_start) + DEFINE_FIELD(uint32_t, switch_ticks) + DEFINE_FIELD(uint32_t, all_items_size) + DEFINE_VECTOR(ItemCompleteStatePacket, all_items_size, all_items) +END_DEFINE_CLASS(NimCompleteStatePacket) + +DEFINE_CLASS(KartInfoInGamePacket) + DEFINE_FIELD(uint32_t, finished_laps) + DEFINE_FIELD(uint32_t, ticks_at_last_lap) + DEFINE_FIELD(uint32_t, lap_start_ticks) + DEFINE_FIELD(float, estimated_finish) + DEFINE_FIELD(float, overall_distance) + DEFINE_FIELD(float, wrong_way_timer) +END_DEFINE_CLASS(KartInfoInGamePacket) + +DEFINE_CLASS(TrackSectorCompleteStatePacket) + DEFINE_FIELD(uint32_t, current_graph_node) + DEFINE_FIELD(uint32_t, estimated_valid_graph_node) + DEFINE_FIELD(uint32_t, last_valid_graph_node) + DEFINE_FIELD(Vec3, current_track_coords) + DEFINE_FIELD(Vec3, estimated_valid_track_coords) + DEFINE_FIELD(Vec3, latest_valid_track_coords) + DEFINE_FIELD(bool, on_road) + DEFINE_FIELD(uint32_t, last_triggered_checkline) +END_DEFINE_CLASS(TrackSectorCompleteStatePacket) + +DEFINE_CLASS(CheckPacket) +END_DEFINE_CLASS(CheckPacket) + +DEFINE_CLASS(CheckStructureSubPacket) + DEFINE_FIELD(Vec3, previous_position) + DEFINE_FIELD(bool, is_active) +END_DEFINE_CLASS(CheckStructureSubPacket) + +DEFINE_DERIVED_CLASS(CheckStructurePacket, CheckPacket) + AUX_VAR_FROM_PARENT(uint32_t, "karts_count", karts_count) /* Checklinepacket or Linearworldcompletestatepacket ::karts_count */ + DEFINE_VECTOR(CheckStructureSubPacket, karts_count, player_check_state) +END_DEFINE_CLASS(CheckStructurePacket) + +DEFINE_CLASS(CheckLineSubPacket) + DEFINE_FIELD(bool, previous_sign) +END_DEFINE_CLASS(CheckLineSubPacket) + +DEFINE_DERIVED_CLASS(CheckLinePacket, CheckPacket) + AUX_VAR_FROM_PARENT(uint32_t, "karts_count", karts_count) + DEFINE_FIELD_PTR(CheckStructurePacket, check_structure_packet) + DEFINE_VECTOR(CheckLineSubPacket, karts_count, subpackets) +END_DEFINE_CLASS(CheckLinePacket) + +DEFINE_CLASS(WorldPacket) +END_DEFINE_CLASS(WorldPacket) + +DEFINE_DERIVED_CLASS(LinearWorldCompleteStatePacket, WorldPacket) + AUX_VAR(uint32_t, karts_count) + AUX_VAR(uint32_t, track_sectors_count) + AUX_STORE("karts_count", karts_count) + AUX_STORE("track_sectors_count", track_sectors_count) + DEFINE_FIELD(uint32_t, fastest_lap_ticks) + DEFINE_FIELD(float, distance_increase) + DEFINE_VECTOR(PlacementPacket, karts_count, kart_placements) + DEFINE_VECTOR(KartInfoInGamePacket, karts_count, kart_infos) + DEFINE_VECTOR(TrackSectorCompleteStatePacket, track_sectors_count, track_sectors) + DEFINE_FIELD(uint8_t, check_structure_count) + DEFINE_VECTOR_PTR(CheckStructurePacket, check_structure_count, check_structures) +END_DEFINE_CLASS(LinearWorldCompleteStatePacket) + +DEFINE_CLASS(ScorerDataPacket) + DEFINE_FIELD(uint8_t, id) + DEFINE_FIELD(uint8_t, correct_goal) + DEFINE_FIELD(float, time) + DEFINE_FIELD(std::string, kart) + DEFINE_FIELD(widestr, player) + DEFINE_FIELD_OPTIONAL(std::string, country_code, cap(SOCCER_FIXES)) + DEFINE_FIELD_OPTIONAL(uint8_t, handicap_level, cap(SOCCER_FIXES)) +END_DEFINE_CLASS(ScorerDataPacket) + +DEFINE_DERIVED_CLASS(SoccerWorldCompleteStatePacket, WorldPacket) + AUX_VAR(uint32_t, karts_count) + AUX_VAR(uint32_t, track_sectors_count) + AUX_STORE("karts_count", karts_count) + AUX_STORE("track_sectors_count", track_sectors_count) + DEFINE_FIELD(uint32_t, red_scorers_count) + DEFINE_VECTOR(ScorerDataPacket, red_scorers_count, red_scorers) + DEFINE_FIELD(uint32_t, blue_scorers_count) + DEFINE_VECTOR(ScorerDataPacket, blue_scorers_count, blue_scorers) + DEFINE_FIELD(uint32_t, reser_ball_ticks) + DEFINE_FIELD(uint32_t, ticks_back_to_own_goal) +END_DEFINE_CLASS(SoccerWorldCompleteStatePacket) + +DEFINE_DERIVED_CLASS(FFAWorldCompleteStatePacket, WorldPacket) + AUX_VAR(uint32_t, karts_count) + AUX_VAR(uint32_t, track_sectors_count) + AUX_STORE("karts_count", karts_count) + AUX_STORE("track_sectors_count", track_sectors_count) + DEFINE_VECTOR(uint32_t, karts_count, scores) +END_DEFINE_CLASS(FFAWorldCompleteStatePacket) + +DEFINE_DERIVED_CLASS(CTFWorldCompleteStatePacket, WorldPacket) + DEFINE_FIELD_PTR(FFAWorldCompleteStatePacket, ffa_packet) + DEFINE_FIELD(uint32_t, red_score) + DEFINE_FIELD(uint32_t, blue_score) +END_DEFINE_CLASS(CTFWorldCompleteStatePacket) + +DEFINE_CLASS(WorldCompleteStatePacket) + DEFINE_FIELD_OPTIONAL(LinearWorldCompleteStatePacket, linear_packet, check(0)) + DEFINE_FIELD_OPTIONAL(SoccerWorldCompleteStatePacket, soccer_packet, check(1)) + DEFINE_FIELD_OPTIONAL(FFAWorldCompleteStatePacket, ffa_packet, check(2)) + DEFINE_FIELD_OPTIONAL(CTFWorldCompleteStatePacket, ctf_packet, check(3)) +END_DEFINE_CLASS(WorldCompleteStatePacket) + +DEFINE_CLASS(InsideGameInfoPacket) + DEFINE_FIELD(uint8_t, players_size) + DEFINE_VECTOR(EncodedSinglePlayerPacket, players_size, all_players) + DEFINE_VECTOR(KartDataPacket, players_size, players_kart_data) +END_DEFINE_CLASS(InsideGameInfoPacket) + +DEFINE_CLASS(LiveJoinPacket) + PROTOCOL_TYPE(PROTOCOL_LOBBY_ROOM, true) + DEFINE_TYPE(uint8_t, type, LE_LIVE_JOIN_ACK) + DEFINE_FIELD(uint64_t, client_starting_time) + DEFINE_FIELD(uint8_t, check_count) + DEFINE_FIELD(uint64_t, live_join_start_time) + DEFINE_FIELD(uint32_t, last_live_join_util_ticks) + DEFINE_FIELD(NimCompleteStatePacket, nim_complete_state) + DEFINE_FIELD_PTR(WorldCompleteStatePacket, world_complete_state) + DEFINE_FIELD_OPTIONAL(InsideGameInfoPacket, inside_info, check(0)) // RaceManager::get()->supportsLiveJoining() + RELIABLE(true) +END_DEFINE_CLASS(LiveJoinPacket) + +DEFINE_CLASS(ChatPacket) + PROTOCOL_TYPE(PROTOCOL_LOBBY_ROOM, true) + DEFINE_TYPE(uint8_t, type, LE_CHAT) + DEFINE_FIELD16(widestr, message) // use encodeString16 ! max len is 360 for server, 1000 for client + DEFINE_FIELD_OPTIONAL(KartTeam, kart_team, check(0)) /* KartTeam is uint8_t, I have no idea when */ + RELIABLE(true) +END_DEFINE_CLASS(ChatPacket) + +DEFINE_CLASS(ChangeTeamPacket) + PROTOCOL_TYPE(PROTOCOL_LOBBY_ROOM, false) + DEFINE_TYPE(uint8_t, type, LE_CHANGE_TEAM) + DEFINE_FIELD(uint8_t, local_id) + RELIABLE(true) +END_DEFINE_CLASS(ChangeTeamPacket) + +DEFINE_CLASS(KickHostPacket) + PROTOCOL_TYPE(PROTOCOL_LOBBY_ROOM, false) + DEFINE_TYPE(uint8_t, type, LE_KICK_HOST) + DEFINE_FIELD(uint32_t, host_id) + RELIABLE(true) +END_DEFINE_CLASS(KickHostPacket) + +DEFINE_CLASS(ReportRequestPacket) + PROTOCOL_TYPE(PROTOCOL_LOBBY_ROOM, false) + DEFINE_TYPE(uint8_t, type, LE_REPORT_PLAYER) + DEFINE_FIELD(uint32_t, host_id) + DEFINE_FIELD16(widestr, info) + RELIABLE(true) +END_DEFINE_CLASS(ReportRequestPacket) + +DEFINE_CLASS(ReportSuccessPacket) + PROTOCOL_TYPE(PROTOCOL_LOBBY_ROOM, true) + DEFINE_TYPE(uint8_t, type, LE_REPORT_PLAYER) + DEFINE_FIELD(bool, success) + DEFINE_FIELD(widestr, reported_name) + RELIABLE(true) +END_DEFINE_CLASS(ReportSuccessPacket) + +DEFINE_CLASS(ChangeHandicapPacket) + PROTOCOL_TYPE(PROTOCOL_LOBBY_ROOM, false) + DEFINE_TYPE(uint8_t, type, LE_CHANGE_HANDICAP) + DEFINE_FIELD(uint8_t, local_id) + DEFINE_FIELD(uint8_t, handicap) + RELIABLE(true) +END_DEFINE_CLASS(ChangeHandicapPacket) + +DEFINE_CLASS(BackLobbyPacket) + PROTOCOL_TYPE(PROTOCOL_LOBBY_ROOM, true) + DEFINE_TYPE(uint8_t, type, LE_BACK_LOBBY) + DEFINE_FIELD(uint8_t, reason) + RELIABLE(true) +END_DEFINE_CLASS(BackLobbyPacket) + +DEFINE_CLASS(ServerInfoPacket) + PROTOCOL_TYPE(PROTOCOL_LOBBY_ROOM, true) + DEFINE_TYPE(uint8_t, type, LE_SERVER_INFO) + DEFINE_FIELD(std::string, server_name) + DEFINE_FIELD(uint8_t, difficulty) + DEFINE_FIELD(uint8_t, max_players) + DEFINE_FIELD(uint8_t, extra_spectators_zero) + DEFINE_FIELD(uint8_t, game_mode) + DEFINE_FIELD(uint8_t, has_extra_server_info) /* can be more than 1 - in gp it's current track number, so not bool */ + DEFINE_VECTOR(uint8_t, has_extra_server_info, extra_server_info) + DEFINE_FIELD(uint8_t, min_start_game_players) + DEFINE_FIELD(float, start_game_counter) + DEFINE_FIELD16(widestr, motd) + DEFINE_FIELD(bool, is_configurable) + DEFINE_FIELD(bool, has_live_players) + RELIABLE(true) +END_DEFINE_CLASS(ServerInfoPacket) + +// DEFINE_CLASS(AssetsPacket) +// DEFINE_FIELD(uint16_t, karts_number) +// DEFINE_VECTOR(std::string, karts_number, karts) +// DEFINE_FIELD(uint16_t, maps_number) +// DEFINE_VECTOR(std::string, maps_number, maps) +// END_DEFINE_CLASS(AssetsPacket) + +DEFINE_CLASS(AssetsPacket2) + DEFINE_FIELD(uint16_t, karts_number) + DEFINE_FIELD(uint16_t, maps_number) + DEFINE_VECTOR(std::string, karts_number, karts) + DEFINE_VECTOR(std::string, maps_number, maps) +END_DEFINE_CLASS(AssetsPacket2) + +DEFINE_CLASS(NewAssetsPacket) + PROTOCOL_TYPE(PROTOCOL_LOBBY_ROOM, false) + DEFINE_TYPE(uint8_t, type, LE_ASSETS_UPDATE) + DEFINE_FIELD(AssetsPacket2, assets) + RELIABLE(true) +END_DEFINE_CLASS(NewAssetsPacket) + +DEFINE_CLASS(PlayerKartsPacket) + DEFINE_FIELD(uint8_t, players_count) + DEFINE_VECTOR(std::string, players_count, karts) + + // I don't care about compilation for now but don't want extra macroses yet either. + DEFINE_VECTOR/*_OPTIONAL*/(KartDataPacket, players_count, kart_data/*, cap(REAL_ADDON_KARTS) && IDONTKNOW*/) // if has "real_addon_karts" in cap AND anything is sent +END_DEFINE_CLASS(PlayerKartsPacket) + +DEFINE_CLASS(KartSelectionRequestPacket) + PROTOCOL_TYPE(PROTOCOL_LOBBY_ROOM, false) + DEFINE_TYPE(uint8_t, type, LE_KART_SELECTION) + DEFINE_FIELD(PlayerKartsPacket, karts) + RELIABLE(true) +END_DEFINE_CLASS(KartSelectionRequestPacket) + +DEFINE_CLASS(LiveJoinRequestPacket) + PROTOCOL_TYPE(PROTOCOL_LOBBY_ROOM, true) + DEFINE_TYPE(uint8_t, type, LE_LIVE_JOIN) + DEFINE_FIELD(bool, is_spectator) + DEFINE_FIELD_OPTIONAL(PlayerKartsPacket, player_karts, check(0)) // check client side for condition! + RELIABLE(true) +END_DEFINE_CLASS(LiveJoinRequestPacket) + +DEFINE_CLASS(FinishedLoadingLiveJoinPacket) + PROTOCOL_TYPE(PROTOCOL_LOBBY_ROOM, UNUSED) + DEFINE_TYPE(uint8_t, type, LE_CLIENT_LOADED_WORLD) + RELIABLE(true) +END_DEFINE_CLASS(FinishedLoadingLiveJoinPacket) + +DEFINE_CLASS(KartInfoRequestPacket) + PROTOCOL_TYPE(PROTOCOL_LOBBY_ROOM, true) + DEFINE_TYPE(uint8_t, type, LE_KART_INFO) + DEFINE_FIELD(uint8_t, kart_id) + RELIABLE(true) +END_DEFINE_CLASS(KartInfoRequestPacket) + +DEFINE_CLASS(KartInfoPacket) + PROTOCOL_TYPE(PROTOCOL_LOBBY_ROOM, true) + DEFINE_TYPE(uint8_t, type, LE_KART_INFO) + DEFINE_FIELD(uint32_t, live_join_util_ticks) + DEFINE_FIELD(uint8_t, kart_id) + DEFINE_FIELD(widestr, player_name) + DEFINE_FIELD(uint32_t, host_id) + DEFINE_FIELD(float, default_kart_color) + DEFINE_FIELD(uint32_t, online_id) + DEFINE_FIELD(uint8_t, handicap) + DEFINE_FIELD(uint8_t, local_player_id) + DEFINE_FIELD(std::string, kart_name) + DEFINE_FIELD(std::string, country_code) + // The field below is present if "real_addon_karts" is in capabilities + DEFINE_FIELD_OPTIONAL(KartDataPacket, kart_data, cap(REAL_ADDON_KARTS)) + RELIABLE(true) +END_DEFINE_CLASS(KartInfoPacket) + +DEFINE_CLASS(ConfigServerPacket) + PROTOCOL_TYPE(PROTOCOL_LOBBY_ROOM, false) + DEFINE_TYPE(uint8_t, type, LE_CONFIG_SERVER) + DEFINE_FIELD(uint8_t, difficulty) + DEFINE_FIELD(uint8_t, game_mode) + DEFINE_FIELD(bool, soccer_goal_target) + RELIABLE(true) +END_DEFINE_CLASS(ConfigServerPacket) + +DEFINE_CLASS(ConnectionRefusedPacket) + PROTOCOL_TYPE(PROTOCOL_LOBBY_ROOM, true) + DEFINE_TYPE(uint8_t, type, LE_CONNECTION_REFUSED) + DEFINE_FIELD(uint8_t, reason) + DEFINE_FIELD_OPTIONAL(std::string, message, check(0)) /* I have no idea when */ + RELIABLE(true) + /* warning! can be sent unencrypted despite reliable! */ +END_DEFINE_CLASS(ConnectionRefusedPacket) + +DEFINE_CLASS(StartGamePacket) + PROTOCOL_TYPE(PROTOCOL_LOBBY_ROOM, true) + DEFINE_TYPE(uint8_t, type, LE_START_RACE) + DEFINE_FIELD(uint64_t, start_time) + DEFINE_FIELD(uint8_t, check_count) + DEFINE_FIELD(NimCompleteStatePacket, nim_complete_state) /* this had operator += instead */ + RELIABLE(true) +END_DEFINE_CLASS(StartGamePacket) + +DEFINE_CLASS(VotePacket) /* vote of a player sent to others */ + PROTOCOL_TYPE(PROTOCOL_LOBBY_ROOM, true) + DEFINE_TYPE(uint8_t, type, LE_VOTE) + DEFINE_FIELD(uint32_t, host_id) + DEFINE_FIELD(PeerVotePacket, vote) +END_DEFINE_CLASS(VotePacket) + +DEFINE_CLASS(VoteRequestPacket) + PROTOCOL_TYPE(PROTOCOL_LOBBY_ROOM, false) + DEFINE_TYPE(uint8_t, type, LE_VOTE) + DEFINE_FIELD(PeerVotePacket, vote) + RELIABLE(true) +END_DEFINE_CLASS(VoteRequestPacket) + +DEFINE_CLASS(ServerOwnershipPacket) + PROTOCOL_TYPE(PROTOCOL_LOBBY_ROOM, true) + DEFINE_TYPE(uint8_t, type, LE_SERVER_OWNERSHIP) +END_DEFINE_CLASS(ServerOwnershipPacket) + +DEFINE_CLASS(ConnectionAcceptedPacket) + PROTOCOL_TYPE(PROTOCOL_LOBBY_ROOM, true) + DEFINE_TYPE(uint8_t, type, LE_CONNECTION_ACCEPTED) + DEFINE_FIELD(uint32_t, host_id) + DEFINE_FIELD(uint32_t, server_version) + DEFINE_FIELD(uint16_t, capabilities_size) + DEFINE_VECTOR(std::string, capabilities_size, capabilities) + DEFINE_FIELD(float, auto_start_timer) + DEFINE_FIELD(uint32_t, state_frequency) + DEFINE_FIELD(bool, chat_allowed) + DEFINE_FIELD(bool, reports_allowed) +END_DEFINE_CLASS(ConnectionAcceptedPacket) + +DEFINE_CLASS(PlayerDisconnectedPacket) + PROTOCOL_TYPE(PROTOCOL_LOBBY_ROOM, true) + DEFINE_TYPE(uint8_t, type, LE_PLAYER_DISCONNECTED) + DEFINE_FIELD(uint8_t, players_size) + DEFINE_FIELD(uint32_t, host_id) + DEFINE_VECTOR(std::string, players_size, names) +END_DEFINE_CLASS(PlayerDisconnectedPacket) + +DEFINE_CLASS(PointChangesPacket) + DEFINE_FIELD(uint8_t, player_count) + DEFINE_VECTOR(float, player_count, changes) +END_DEFINE_CLASS(PointChangesPacket) + +DEFINE_CLASS(StartSelectionPacket) + PROTOCOL_TYPE(PROTOCOL_LOBBY_ROOM, true) + DEFINE_TYPE(uint8_t, type, LE_START_SELECTION) + DEFINE_FIELD(float, voting_timeout) + DEFINE_FIELD(bool, no_kart_selection) + DEFINE_FIELD(bool, fixed_length) + DEFINE_FIELD(bool, track_voting) + DEFINE_FIELD(AssetsPacket2, assets) + RELIABLE(true) +END_DEFINE_CLASS(StartSelectionPacket) + +DEFINE_CLASS(BadTeamPacket) + PROTOCOL_TYPE(PROTOCOL_LOBBY_ROOM, true) + DEFINE_TYPE(uint8_t, type, LE_BAD_TEAM) + RELIABLE(true) +END_DEFINE_CLASS(BadTeamPacket) + +DEFINE_CLASS(GPIndividualScorePacket) + DEFINE_FIELD(uint32_t, last_score) + DEFINE_FIELD(uint32_t, cur_score) + DEFINE_FIELD(float, overall_time) +END_DEFINE_CLASS(GPIndividualScorePacket) + +DEFINE_CLASS(GPScoresPacket) + DEFINE_FIELD(uint8_t, total_gp_tracks) + DEFINE_FIELD(uint8_t, all_tracks_size) + DEFINE_VECTOR(std::string, all_tracks_size, all_tracks) + DEFINE_FIELD(uint8_t, num_players) + DEFINE_VECTOR(GPIndividualScorePacket, num_players, scores) +END_DEFINE_CLASS(GPScoresPacket) + +DEFINE_CLASS(RaceFinishedPacket) + PROTOCOL_TYPE(PROTOCOL_LOBBY_ROOM, true) + DEFINE_TYPE(uint8_t, type, LE_RACE_FINISHED) + DEFINE_FIELD_OPTIONAL(uint32_t, fastest_lap, check(0)) /* if linear (incl. gp) */ + DEFINE_FIELD_OPTIONAL(widestr, fastest_kart_name, check(0)) /* if linear (incl. gp) */ + DEFINE_FIELD_OPTIONAL(GPScoresPacket, gp_scores, check(1)) /* if gp */ + DEFINE_FIELD(bool, point_changes_indication) + DEFINE_FIELD_OPTIONAL(PointChangesPacket, point_changes, point_changes_indication) + RELIABLE(true) +END_DEFINE_CLASS(RaceFinishedPacket) + +DEFINE_CLASS(InsideCtfPacket) + PROTOCOL_TYPE(PROTOCOL_GAME_EVENTS, true) + DEFINE_TYPE(uint8_t, type, GE_CTF_SCORED) + DEFINE_FIELD(uint8_t, active_holder) + DEFINE_FIELD(bool, red_inactive) /* actually, red scored */ + DEFINE_FIELD(uint16_t, kart_score) + DEFINE_FIELD(uint8_t, red_score) + DEFINE_FIELD(uint8_t, blue_score) + RELIABLE(true) +END_DEFINE_CLASS(InsideCtfPacket) + +DEFINE_CLASS(InsideFfaPacket) + PROTOCOL_TYPE(PROTOCOL_GAME_EVENTS, true) + DEFINE_TYPE(uint8_t, type, GE_BATTLE_KART_SCORE) + DEFINE_FIELD(uint8_t, hitter_kart) + DEFINE_FIELD(uint16_t, new_score) + RELIABLE(true) +END_DEFINE_CLASS(InsideFfaPacket) + +/* Separation is needed because it's filled in check structure itself */ +DEFINE_CLASS(CheckActivePacket) + DEFINE_FIELD(bool, active) +END_DEFINE_CLASS(CheckActivePacket) + +DEFINE_CLASS(InsideChecklinePacket) + PROTOCOL_TYPE(PROTOCOL_GAME_EVENTS, true) + DEFINE_TYPE(uint8_t, type, GE_CHECK_LINE) + DEFINE_FIELD(uint8_t, check_id) + DEFINE_FIELD(uint8_t, kart_id) + DEFINE_FIELD(uint8_t, finished_laps) + DEFINE_FIELD(uint8_t, last_triggered_checkline) + DEFINE_FIELD(uint32_t, fastest_lap_ticks) + DEFINE_FIELD(widestr, fastest_kart_name) + DEFINE_FIELD(uint8_t, check_structure_count) + DEFINE_VECTOR(CheckActivePacket, check_structure_count, check_active) + RELIABLE(true) +END_DEFINE_CLASS(InsideChecklinePacket) + + +DEFINE_CLASS(InternalGoalPacket) + PROTOCOL_TYPE(PROTOCOL_GAME_EVENTS, true) + DEFINE_TYPE(uint8_t, type, GE_PLAYER_GOAL) + DEFINE_FIELD(uint8_t, id) + DEFINE_FIELD(bool, correct_goal) + DEFINE_FIELD(bool, first_goal) + DEFINE_FIELD(float, time) + DEFINE_FIELD(uint32_t, ticks_back_to_own_goal) + DEFINE_FIELD(std::string, kart) + DEFINE_FIELD(widestr, player) + /* what follows is only since 1.1, that is, when capabilities have "soccer_fixes" */ + DEFINE_FIELD_OPTIONAL(std::string, country_code, cap(SOCCER_FIXES)) + DEFINE_FIELD_OPTIONAL(uint8_t, handicap, cap(SOCCER_FIXES)) + RELIABLE(true) +END_DEFINE_CLASS(InternalGoalPacket) + +DEFINE_CLASS(ResetBallPacket) + PROTOCOL_TYPE(PROTOCOL_GAME_EVENTS, true) + DEFINE_TYPE(uint8_t, type, GE_RESET_BALL) + DEFINE_FIELD(uint32_t, reset_ball_ticks) + RELIABLE(true) +END_DEFINE_CLASS(ResetBallPacket) + +DEFINE_CLASS(BadConnectionPacket) + PROTOCOL_TYPE(PROTOCOL_LOBBY_ROOM, true) + DEFINE_TYPE(uint8_t, type, LobbyEvent::LE_BAD_CONNECTION) + RELIABLE(true) +END_DEFINE_CLASS(BadConnectionPacket) + +DEFINE_CLASS(RaceFinishedAckPacket) + PROTOCOL_TYPE(PROTOCOL_LOBBY_ROOM, true) + DEFINE_TYPE(uint8_t, type, LE_RACE_FINISHED_ACK) + RELIABLE(true) +END_DEFINE_CLASS(RaceFinishedAckPacket) + +DEFINE_CLASS(RequestBeginPacket) + PROTOCOL_TYPE(PROTOCOL_LOBBY_ROOM, false) + DEFINE_TYPE(uint8_t, type, LE_REQUEST_BEGIN) + RELIABLE(true) +END_DEFINE_CLASS(RequestBeginPacket) + +DEFINE_CLASS(ClientBackLobbyPacket) + PROTOCOL_TYPE(PROTOCOL_LOBBY_ROOM, false) + DEFINE_TYPE(uint8_t, type, LE_CLIENT_BACK_LOBBY) + RELIABLE(true) +END_DEFINE_CLASS(ClientBackLobbyPacket) + +DEFINE_CLASS(ItemConfirmationPacket) + PROTOCOL_TYPE(PROTOCOL_CONTROLLER_EVENTS, false) + DEFINE_TYPE(uint8_t, type, GP_ITEM_CONFIRMATION) + DEFINE_FIELD(uint32_t, ticks) + /* This message can be sent unreliable, it's not critical if it doesn't + get delivered, a future update will come through */ + RELIABLE(false) +END_DEFINE_CLASS(ItemConfirmationPacket) + +DEFINE_CLASS(CommandPacket) + PROTOCOL_TYPE(PROTOCOL_LOBBY_ROOM, false) + DEFINE_TYPE(uint8_t, type, LE_COMMAND) + DEFINE_FIELD(std::string, language) + DEFINE_FIELD(std::string, command) + RELIABLE(true) +END_DEFINE_CLASS(CommandPacket) + +DEFINE_CLASS(ConnectingPlayerPacket) + DEFINE_FIELD(widestr, name) + DEFINE_FIELD(float, default_kart_color) + DEFINE_FIELD(uint8_t, handicap) +END_DEFINE_CLASS(ConnectingPlayerPacket) + +DEFINE_CLASS(RestConnectionRequestPacket) + DEFINE_FIELD(std::string, private_server_password) + DEFINE_FIELD(uint8_t, player_count) + DEFINE_VECTOR(ConnectingPlayerPacket, player_count, players) +END_DEFINE_CLASS(RestConnectionRequestPacket) + +DEFINE_CLASS(ConnectionRequestedPacket) + PROTOCOL_TYPE(PROTOCOL_LOBBY_ROOM, false) + DEFINE_TYPE(uint8_t, type, LE_CONNECTION_REQUESTED) + DEFINE_FIELD(uint32_t, server_version) + DEFINE_FIELD(std::string, user_agent) + DEFINE_FIELD(uint16_t, capabilities_size) + DEFINE_VECTOR(std::string, capabilities_size, capabilities) + DEFINE_FIELD(AssetsPacket2, assets) + DEFINE_FIELD(uint8_t, player_count) + + DEFINE_FIELD(uint32_t, id) + DEFINE_FIELD(uint32_t, encrypted_size) // 0 if not encrypted + AUX_STORE("encrypted_size", encrypted_size) + DEFINE_FIELD_OPTIONAL(widestr, player_name, id != 0 && encrypted_size == 0) + DEFINE_FIELD_OPTIONAL(EncryptedBuffer, player_info_encrypted, encrypted_size != 0) + DEFINE_FIELD_OPTIONAL(RestConnectionRequestPacket, player_info_unencrypted, encrypted_size == 0) + +END_DEFINE_CLASS(ConnectionRequestedPacket) + +DEFINE_CLASS(StartupBoostPacket) + PROTOCOL_TYPE(PROTOCOL_GAME_EVENTS, true) + DEFINE_TYPE(uint8_t, type, GE_STARTUP_BOOST) + DEFINE_FIELD(uint8_t, kart_id) + RELIABLE(true) +END_DEFINE_CLASS(StartupBoostPacket) + +DEFINE_CLASS(TrackSectorSmallPacket) + DEFINE_FIELD(uint16_t, cur_graph_mode) + DEFINE_FIELD(float, coord_z) +END_DEFINE_CLASS(TrackSectorSmallPacket) + +DEFINE_CLASS(AbstractKartAnimationPacket) + DEFINE_FIELD(uint32_t, created_ticks) + DEFINE_FIELD(int24_t, transform_compressed_0) + DEFINE_FIELD(int24_t, transform_compressed_1) + DEFINE_FIELD(int24_t, transform_compressed_2) + DEFINE_FIELD(uint32_t, transform_compressed_3) +END_DEFINE_CLASS(AbstractKartAnimationPacket) + +DEFINE_CLASS(MaxSpeedSpeedIncreasePacket) + DEFINE_FIELD(uint16_t, max_add_speed) + DEFINE_FIELD(uint16_t, duration) + DEFINE_FIELD(uint16_t, fade_out_time) + DEFINE_FIELD(uint16_t, engine_force) +END_DEFINE_CLASS(MaxSpeedSpeedIncreasePacket) + +DEFINE_CLASS(MaxSpeedSpeedDecreasePacket) + DEFINE_FIELD(uint16_t, max_speed_fraction) + DEFINE_FIELD(float, current_fraction) + DEFINE_FIELD(uint16_t, fade_in_ticks) + DEFINE_FIELD(uint16_t, duration) +END_DEFINE_CLASS(MaxSpeedSpeedDecreasePacket) + +/* I will search for a proper function later */ +DEFINE_CLASS(MaxSpeedPacket) + DEFINE_FIELD(uint8_t, slowdown_mask) + DEFINE_VECTOR(MaxSpeedSpeedDecreasePacket, __builtin_popcount(slowdown_mask), slowdowns) + DEFINE_FIELD(uint8_t, speedup_mask) + DEFINE_VECTOR(MaxSpeedSpeedIncreasePacket, __builtin_popcount(speedup_mask), speedups) +END_DEFINE_CLASS(MaxSpeedPacket) + +DEFINE_CLASS(SkiddingStatePacket) + DEFINE_FIELD(uint8_t, skid_state) + DEFINE_FIELD(uint16_t, skid_time) + DEFINE_FIELD(float, skid_factor) + DEFINE_FIELD(float, visual_rotation) +END_DEFINE_CLASS(SkiddingStatePacket) + +// DEFINE_CLASS(ItemEventInfoPacket) +// DEFINE_FIELD(uint8_t, type) +// DEFINE_FIELD(uint32_t, ticks) +// DEFINE_FIELD_OPTIONAL(uint8_t, kart_id, type != IEI_SWITCH) +// DEFINE_FIELD_OPTIONAL(uint16_t, index, type != IEI_SWITCH) +// DEFINE_FIELD_OPTIONAL(uint16_t, index, type != IEI_SWITCH && type == IEI_NEW) + +// assert(NetworkConfig::get()->isServer()); +// buffer->addUInt8(m_type).addTime(m_ticks); +// if (m_type != IEI_SWITCH) +// { +// // Only new item and collecting items need the index and kart id: +// buffer->addUInt8(m_kart_id).addUInt16(m_index); +// if (m_type == IEI_NEW) +// { +// buffer->add(m_xyz); +// buffer->add(m_normal); +// } +// else if (m_type == IEI_COLLECT) +// buffer->addUInt16(m_ticks_till_return); +// } +// END_DEFINE_CLASS(ItemEventInfoPacket) + +// todo + +DEFINE_CLASS(PluginStatePacket) +END_DEFINE_CLASS(PluginStatePacket) + +DEFINE_CLASS(AttachmentPacket) + DEFINE_FIELD(uint8_t, type) + DEFINE_FIELD(uint16_t, ticks_left) + DEFINE_FIELD_OPTIONAL(uint8_t, previous_owner, type == (ATTACH_BOMB | 64)) + DEFINE_FIELD_OPTIONAL(uint16_t, initial_speed, (type & 63) == ATTACH_PARACHUTE) + DEFINE_FIELD_OPTIONAL(PluginStatePacket, plugin, ((type >> 7) & 1) == 1) +END_DEFINE_CLASS(AttachmentPacket) + +DEFINE_CLASS(CompressedNetworkBodyPacket) + DEFINE_FIELD(float, x) + DEFINE_FIELD(float, y) + DEFINE_FIELD(float, z) + DEFINE_FIELD(uint32_t, compressed_q) + DEFINE_FIELD(uint16_t, lvx) + DEFINE_FIELD(uint16_t, lvy) + DEFINE_FIELD(uint16_t, lvz) + DEFINE_FIELD(uint16_t, avx) + DEFINE_FIELD(uint16_t, avy) + DEFINE_FIELD(uint16_t, avz) +END_DEFINE_CLASS(CompressedNetworkBodyPacket) + +DEFINE_CLASS(FlyablePacket) + // sometimes nothing??? + DEFINE_FIELD_OPTIONAL(uint16_t, ticks_since_thrown_animation, IHAVENOIDEA) + DEFINE_FIELD_OPTIONAL(uint32_t, compressed_gravity_vector, IHAVENOIDEA) + DEFINE_FIELD_OPTIONAL(AbstractKartAnimationPacket, animation, IHAVENOIDEA) + DEFINE_FIELD_OPTIONAL(CompressedNetworkBodyPacket, compressed_network_body, IHAVENOIDEA) +END_DEFINE_CLASS(FlyablePacket) + +DEFINE_CLASS(RubberBallPacket) + // sometimes nothing, depends on the same condition for FlyablePacket + DEFINE_FIELD_OPTIONAL(FlyablePacket, flyable_packet, IHAVENOIDEA) + DEFINE_FIELD_OPTIONAL(uint16_t, last_aimed_graph_node, IHAVENOIDEA) + DEFINE_FIELD_OPTIONAL(Vec3, control_point_0, IHAVENOIDEA) + DEFINE_FIELD_OPTIONAL(Vec3, control_point_1, IHAVENOIDEA) + DEFINE_FIELD_OPTIONAL(Vec3, control_point_2, IHAVENOIDEA) + DEFINE_FIELD_OPTIONAL(Vec3, control_point_3, IHAVENOIDEA) + DEFINE_FIELD_OPTIONAL(Vec3, previous_xyz, IHAVENOIDEA) + DEFINE_FIELD_OPTIONAL(float, previous_height, IHAVENOIDEA) + DEFINE_FIELD_OPTIONAL(float, length_cp_1_2, IHAVENOIDEA) + DEFINE_FIELD_OPTIONAL(float, length_cp_2_3, IHAVENOIDEA) + DEFINE_FIELD_OPTIONAL(float, t, IHAVENOIDEA) + DEFINE_FIELD_OPTIONAL(float, t_increase, IHAVENOIDEA) + DEFINE_FIELD_OPTIONAL(float, interval, IHAVENOIDEA) + DEFINE_FIELD_OPTIONAL(float, height_timer, IHAVENOIDEA) + DEFINE_FIELD_OPTIONAL(uint16_t, delete_ticks, IHAVENOIDEA) + DEFINE_FIELD_OPTIONAL(float, current_max_height, IHAVENOIDEA) + DEFINE_FIELD_OPTIONAL(uint8_t, properties, IHAVENOIDEA) + DEFINE_FIELD_OPTIONAL(TrackSectorSmallPacket, track_sector, IHAVENOIDEA) +END_DEFINE_CLASS(RubberBallPacket) + +DEFINE_CLASS(PlungerPacket) + // sometimes nothing, depends on the same condition for FlyablePacket + DEFINE_FIELD_OPTIONAL(FlyablePacket, flyable_packet, IHAVENOIDEA) + DEFINE_FIELD_OPTIONAL(uint16_t, keep_alive, IHAVENOIDEA) + DEFINE_FIELD_OPTIONAL(uint8_t, rubber_band_state, IHAVENOIDEA) +END_DEFINE_CLASS(PlungerPacket) + +DEFINE_CLASS(GameEventKartFinishedPacket) + PROTOCOL_TYPE(PROTOCOL_GAME_EVENTS, true) + DEFINE_TYPE(uint8_t, type, GE_KART_FINISHED_RACE) + DEFINE_FIELD(uint8_t, kart_id) + DEFINE_FIELD(float, time) + RELIABLE(true) +END_DEFINE_CLASS(GameEventKartFinishedPacket) + +DEFINE_CLASS(GameEventStartupBoostPacket) + PROTOCOL_TYPE(PROTOCOL_GAME_EVENTS, true) + DEFINE_TYPE(uint8_t, type, GE_STARTUP_BOOST) + DEFINE_FIELD(uint8_t, kart_id) + DEFINE_FIELD(float, value) + RELIABLE(true) +END_DEFINE_CLASS(GameEventStartupBoostPacket) + +DEFINE_CLASS(ControllerActionPacket) + DEFINE_FIELD(uint8_t, kart_id) + DEFINE_FIELD(uint8_t, compressed_action_0) + DEFINE_FIELD(uint16_t, compressed_action_1) + DEFINE_FIELD(uint16_t, compressed_action_2) + DEFINE_FIELD(uint16_t, compressed_action_3) +END_DEFINE_CLASS(ControllerActionPacket) + +DEFINE_CLASS(ControllerActionBigPacket) + PROTOCOL_TYPE(PROTOCOL_GAME_EVENTS, true) + DEFINE_TYPE(uint8_t, type, GP_CONTROLLER_ACTION) + DEFINE_FIELD(uint8_t, count) + DEFINE_VECTOR(ControllerSingleActionPacket, count, actions) + /* We don't specify RELIABLE here as it can be sent both ways. Or maybe I forgot how overriding works here? */ + /*RELIABLE(true)*/ +END_DEFINE_CLASS(ControllerActionBigPacket) + +DEFINE_CLASS(ControllerSingleActionPacket) + DEFINE_FIELD(uint32_t, ticks) + DEFINE_FIELD(ControllerActionPacket, subpacket) +END_DEFINE_CLASS(ControllerSingleActionPacket) + +DEFINE_CLASS(GameEventStatePacket) + DEFINE_TYPE(uint8_t, type, GP_STATE) + DEFINE_FIELD(uint32_t, ticks_since_start) +END_DEFINE_CLASS(GameEventStatePacket) + +DEFINE_CLASS(ProjectilePacket) + DEFINE_FIELD(uint8_t, rewinder_type) /* RewinderName enum */ + DEFINE_FIELD(uint8_t, kart_id) + DEFINE_FIELD(uint32_t, created_ticks) +END_DEFINE_CLASS(ProjectilePacket) + +DEFINE_CLASS(TheRestOfBgsPacket) + DEFINE_FIELD(uint16_t, data_size) + DEFINE_FIELD(IHaveNoIdeaActuallyButItHasSizeEqualToDataSize, something) +END_DEFINE_CLASS(TheRestOfBgsPacket) + +DEFINE_CLASS(BigGameStatesPacket) + PROTOCOL_TYPE(PROTOCOL_GAME_EVENTS, true) + DEFINE_TYPE(uint8_t, type, GP_CONTROLLER_ACTION) + DEFINE_FIELD(uint32_t, ticks) + DEFINE_FIELD(uint8_t, rewinders_size) + DEFINE_FIELD(GameEventStatePacket, state) /* kimden: I'm not sure where this should be located within the packet */ + DEFINE_VECTOR(ProjectilePacket, rewinders_size, rewinders) + /* DEFINE_FIELD(ControllerActionBigPacket, actions) --------- kimden: for now, I have no idea why this is here. Probably a leftover. */ + DEFINE_VECTOR(TheRestOfBgsPacket, rewinders_size, the_rest) + // kimden: I have no idea for now + /* Don't define RELIABLE, can be sent either way */ +END_DEFINE_CLASS(BigGameStatesPacket) + + + + // end \ No newline at end of file diff --git a/src/network/peer_vote.hpp b/src/network/peer_vote.hpp index fdd84f076cf..60f1c6f82cd 100644 --- a/src/network/peer_vote.hpp +++ b/src/network/peer_vote.hpp @@ -20,6 +20,7 @@ #define PEER_VOTE_HPP #include "network/network_string.hpp" +#include "network/packet_types.hpp" #include "irrString.h" #include @@ -51,23 +52,24 @@ class PeerVote // ------------------------------------------------------ /** Initialised this object from a data in a network string. */ - PeerVote(NetworkString &ns) + PeerVote(const PeerVotePacket& packet) { - ns.decodeStringW(&m_player_name); - ns.decodeString(&m_track_name); - m_num_laps = ns.getUInt8(); - m_reverse = ns.getUInt8()!=0; - - } // PeerVote(NetworkString &) + m_player_name = packet.player_name; + m_track_name = packet.track_name; + m_num_laps = packet.num_laps; + m_reverse = packet.is_reverse; + } // PeerVote(PeerVotePacket &) // ------------------------------------------------------ /** Encodes this vote object into a network string. */ - void encode(NetworkString *ns) + PeerVotePacket encode() { - ns->encodeString(m_player_name) - .encodeString(m_track_name) - .addUInt8(m_num_laps) - .addUInt8(m_reverse); + PeerVotePacket packet; + packet.player_name = m_player_name; + packet.track_name = m_track_name; + packet.num_laps = m_num_laps; + packet.is_reverse = m_reverse; + return packet; } // encode }; // class PeerVote diff --git a/src/network/protocol.hpp b/src/network/protocol.hpp index aed9b98b468..241aec46326 100644 --- a/src/network/protocol.hpp +++ b/src/network/protocol.hpp @@ -24,13 +24,16 @@ #define PROTOCOL_HPP #include "utils/no_copy.hpp" +#include "utils/constants.hpp" #include #include +#include class Event; class NetworkString; class STKPeer; +class Packet; /** \enum ProtocolType @@ -119,6 +122,7 @@ class Protocol : public std::enable_shared_from_this, NetworkString* getNetworkString(size_t capacity = 16) const; bool checkDataSize(Event* event, unsigned int minimum_size); + // ---------------------------------------------------------------------------- virtual void requestStart(); virtual void requestTerminate(); // ------------------------------------------------------------------------ diff --git a/src/network/protocols/client_lobby.cpp b/src/network/protocols/client_lobby.cpp index db0f415f1d1..1fa1d3a47cd 100644 --- a/src/network/protocols/client_lobby.cpp +++ b/src/network/protocols/client_lobby.cpp @@ -177,11 +177,8 @@ void ClientLobby::setup() */ void ClientLobby::doneWithResults() { - NetworkString* done = getNetworkString(1); - done->setSynchronous(true); - done->addUInt8(LE_RACE_FINISHED_ACK); - Comm::sendToServer(done, PRM_RELIABLE); - delete done; + RaceFinishedAckPacket packet; + Comm::sendPacketToServer(packet); } // doneWithResults //----------------------------------------------------------------------------- @@ -255,22 +252,6 @@ bool ClientLobby::notifyEventAsynchronous(Event* event) return true; } // notifyEventAsynchronous -//----------------------------------------------------------------------------- -void ClientLobby::getPlayersAddonKartType(const BareNetworkString& data, - std::vector >& 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) { @@ -306,9 +287,9 @@ void ClientLobby::addAllPlayers(Event* event) STKHost::get()->getNetworkTimerSynchronizer()->enableForceSetTimer(); } - NetworkString& data = event->data(); - uint32_t winner_peer_id = data.getUInt32(); - PeerVote winner_vote(data); + auto packet = event->getPacket(); + uint32_t winner_peer_id = packet.default_vote.winner_peer_id; + PeerVote winner_vote(packet.default_vote.default_vote); m_game_setup->setRace(winner_vote); if (!GUIEngine::isNoGraphics()) @@ -316,26 +297,38 @@ void ClientLobby::addAllPlayers(Event* event) std::shared_ptr peer = event->getPeerSP(); peer->cleanPlayerProfiles(); - m_server_send_live_load_world = data.getUInt8() == 1; + m_server_send_live_load_world = packet.live_join; - bool is_specator = true; - std::vector > players = - decodePlayers(data, peer, &is_specator); - setSpectator(is_specator); + bool is_spectator = true; + std::vector > players; + unsigned player_count = packet.players_size; + for (unsigned i = 0; i < player_count; ++i) + players.push_back(decodePlayer(packet.all_players[i], peer, &is_spectator)); + setSpectator(is_spectator); - uint32_t random_seed = data.getUInt32(); - ItemManager::updateRandomSeed(random_seed); + ItemManager::updateRandomSeed(packet.item_seed); if (RaceManager::get()->isBattleMode()) { - int hit_capture_limit = data.getUInt32(); - float time_limit = data.getFloat(); - m_game_setup->setHitCaptureTime(hit_capture_limit, time_limit); - uint16_t flag_return_timeout = data.getUInt16(); - RaceManager::get()->setFlagReturnTicks(flag_return_timeout); - unsigned flag_deactivated_time = data.getUInt16(); - RaceManager::get()->setFlagDeactivatedTicks(flag_deactivated_time); + // kimden: double checking when it's not needed? + if (packet.battle_info.has_value()) + { + BattleInfoPacket subpacket = packet.battle_info.get_value(); + + m_game_setup->setHitCaptureTime(subpacket.battle_hit_capture_limit, + subpacket.battle_time_limit); + + RaceManager::get()->setFlagReturnTicks(subpacket.flag_return_time); + RaceManager::get()->setFlagDeactivatedTicks(subpacket.flag_deactivated_time); + } + } + if (NetworkConfig::get()->getServerCapabilities().find("real_addon_karts") != + NetworkConfig::get()->getServerCapabilities().end() && packet.karts_data.has_value()) + { + for (unsigned i = 0; i < players.size(); i++) + { + players[i]->setKartData(KartData(packet.karts_data.get_value().players_kart_data[i])); + } } - getPlayersAddonKartType(data, players); configRemoteKart(players, isSpectator() ? 1 : (int)NetworkConfig::get()->getNetworkPlayers().size()); loadWorld(); @@ -370,35 +363,27 @@ void ClientLobby::addAllPlayers(Event* event) //----------------------------------------------------------------------------- /* Get list of players from server and see if we are spectating it. */ -std::vector > - ClientLobby::decodePlayers(const BareNetworkString& data, +std::shared_ptr + ClientLobby::decodePlayer(const EncodedSinglePlayerPacket& packet, std::shared_ptr peer, bool* is_spectator) const { - std::vector > players; - unsigned player_count = data.getUInt8(); - for (unsigned i = 0; i < player_count; i++) - { - core::stringw player_name; - data.decodeStringW(&player_name); - uint32_t host_id = data.getUInt32(); - float kart_color = data.getFloat(); - uint32_t online_id = data.getUInt32(); - HandicapLevel handicap = (HandicapLevel)data.getUInt8(); - uint8_t local_id = data.getUInt8(); - KartTeam team = (KartTeam)data.getUInt8(); - std::string country_code; - data.decodeString(&country_code); - if (is_spectator && host_id == STKHost::get()->getMyHostId()) - *is_spectator = false; - auto player = std::make_shared(peer, player_name, - host_id, kart_color, online_id, handicap, local_id, team, country_code); - std::string kart_name; - data.decodeString(&kart_name); - player->setKartName(kart_name); - players.push_back(player); - } - return players; + core::stringw player_name = packet.name; + uint32_t host_id = packet.host_id; + float kart_color = packet.kart_color; + uint32_t online_id = packet.online_id; + HandicapLevel handicap = (HandicapLevel)packet.handicap; + uint8_t local_id = packet.local_player_id; + KartTeam team = (KartTeam)packet.kart_team; + std::string country_code = packet.country_code; + if (is_spectator && host_id == STKHost::get()->getMyHostId()) + *is_spectator = false; + + auto player = std::make_shared(peer, player_name, + host_id, kart_color, online_id, handicap, local_id, team, country_code); + + player->setKartName(packet.kart_name); + return player; } // decodePlayers //----------------------------------------------------------------------------- @@ -410,21 +395,24 @@ void ClientLobby::update(int ticks) case LINKED: { NetworkConfig::get()->clearServerCapabilities(); - std::string ua = StringUtils::getUserAgentString(); + std::string user_agent = StringUtils::getUserAgentString(); if (NetworkConfig::get()->isNetworkAIInstance()) - ua = "AI"; - NetworkString* ns = getNetworkString(); - ns->addUInt8(LE_CONNECTION_REQUESTED) - .addUInt32(ServerConfig::m_server_version).encodeString(ua) - .addUInt16((uint16_t)stk_config->m_network_capabilities.size()); + user_agent = "AI"; + + ConnectionRequestedPacket packet; + packet.server_version = (uint32_t)ServerConfig::m_server_version; + packet.user_agent = user_agent; + packet.capabilities_size = (uint16_t)stk_config->m_network_capabilities.size(); for (const std::string& cap : stk_config->m_network_capabilities) - ns->encodeString(cap); + packet.capabilities.push_back(cap); - getKartsTracksNetworkString(ns); + packet.assets = getKartsTracksPacket(); assert(!NetworkConfig::get()->isAddingNetworkPlayers()); - const uint8_t player_count = - (uint8_t)NetworkConfig::get()->getNetworkPlayers().size(); - ns->addUInt8(player_count); + + auto& all_players = NetworkConfig::get()->getNetworkPlayers(); + + const uint8_t player_count = (uint8_t)all_players.size(); + packet.player_count = player_count; bool encryption = false; // Make sure there is a player before calling getCurrentOnlineId @@ -434,28 +422,27 @@ void ClientLobby::update(int ticks) NetworkConfig::get()->isNetworkAIInstance(); if (lan_ai) id = 0; - BareNetworkString* rest = new BareNetworkString(); if (m_server->supportsEncryption() && id != 0) { - ns->addUInt32(id); + packet.id = id; encryption = true; } else { - ns->addUInt32(id).addUInt32(0); + packet.id = id; + packet.encrypted_size = 0; + if (id != 0) - { - ns->encodeString( - PlayerManager::getCurrentOnlineProfile()->getUserName()); - } + packet.player_name = PlayerManager::getCurrentOnlineProfile()->getUserName(); } - rest->encodeString(ServerConfig::m_private_server_password) - .addUInt8(player_count); - for (unsigned i = 0; - i < NetworkConfig::get()->getNetworkPlayers().size(); i++) + RestConnectionRequestPacket subpacket; + + subpacket.private_server_password = ServerConfig::m_private_server_password; + subpacket.player_count = player_count; + for (unsigned i = 0; i < player_count; i++) { - auto& p = NetworkConfig::get()->getNetworkPlayers()[i]; + auto& p = all_players[i]; PlayerProfile* player = std::get<1>(p); core::stringw name = player->getName(); if (NetworkConfig::get()->isNetworkAIInstance()) @@ -468,13 +455,62 @@ void ClientLobby::update(int ticks) #endif name += core::stringw(" ") + StringUtils::toWString(i + 1); } - rest->encodeString(name). - addFloat(player->getDefaultKartColor()); - // Per-player handicap - rest->addUInt8(std::get<2>(p)); + + ConnectingPlayerPacket player_packet; + player_packet.name = name; + player_packet.default_kart_color = player->getDefaultKartColor(); + player_packet.handicap = std::get<2>(p); + subpacket.players.push_back(player_packet); } - finalizeConnectionRequest(ns, rest, encryption); + if (encryption) + { + auto crypto = Crypto::getClientCrypto(); + Crypto::resetClientAES(); + + NetworkString* rest = new NetworkString(); + subpacket.toNetworkString(rest); + if (!crypto->encryptConnectionRequest(*rest)) + { + // Failed + packet.encrypted_size = 0; + packet.player_info_unencrypted = subpacket; + encryption = false; + + if (id != 0) + packet.player_name = PlayerManager::getCurrentOnlineProfile()->getUserName(); + } + else + { + packet.encrypted_size = rest->getTotalSize(); + Log::info("ClientLobby", "Server will validate this online player."); + + EncryptedBuffer eb; + eb.buffer = rest->getBuffer(); + packet.player_info_encrypted = eb; + } + delete rest; + + Comm::sendPacketToServer(packet); + + if (encryption) + { + STKHost::get()->getServerPeerForClient() + ->setCrypto(std::move(crypto)); + } + } + else + { + packet.player_info_unencrypted = subpacket; + Comm::sendPacketToServer(packet); + } + + + + + + + m_state.store(REQUESTING_CONNECTION); } break; @@ -515,9 +551,8 @@ void ClientLobby::update(int ticks) { // Send a message to the server to start m_auto_started = true; - NetworkString start(PROTOCOL_LOBBY_ROOM); - start.addUInt8(LobbyEvent::LE_REQUEST_BEGIN); - Comm::sendToServer(&start, PRM_RELIABLE); + RequestBeginPacket packet; + Comm::sendPacketToServer(packet); } if (m_background_download.joinable()) { @@ -538,57 +573,14 @@ void ClientLobby::update(int ticks) } } // update -//----------------------------------------------------------------------------- -void ClientLobby::finalizeConnectionRequest(NetworkString* header, - BareNetworkString* rest, - bool encrypt) -{ - if (encrypt) - { - auto crypto = Crypto::getClientCrypto(); - Crypto::resetClientAES(); - BareNetworkString* result = new BareNetworkString(); - if (!crypto->encryptConnectionRequest(*rest)) - { - // Failed - result->addUInt32(0); - *result += BareNetworkString(rest->getData(), rest->getTotalSize()); - encrypt = false; - } - else - { - Log::info("ClientLobby", "Server will validate this online player."); - result->addUInt32(rest->getTotalSize()); - *result += BareNetworkString(rest->getData(), rest->getTotalSize()); - } - delete rest; - *header += *result; - delete result; - Comm::sendToServer(header); - delete header; - if (encrypt) - { - STKHost::get()->getServerPeerForClient() - ->setCrypto(std::move(crypto)); - } - } - else - { - *header += *rest; - delete rest; - Comm::sendToServer(header); - delete header; - } -} // finalizeConnectionRequest - //----------------------------------------------------------------------------- void ClientLobby::receivePlayerVote(Event* event) { if (!checkDataSize(event, 4)) return; - // Get the player name who voted - NetworkString& data = event->data(); - uint32_t host_id = data.getUInt32(); - PeerVote vote(data); + + auto packet = event->getPacket(); + uint32_t host_id = packet.host_id; + PeerVote vote(packet.vote); Log::debug("ClientLobby", "Vote from server: host %d, track %s, laps %d, reverse %d.", host_id, vote.m_track_name.c_str(), vote.m_num_laps, vote.m_reverse); @@ -620,11 +612,9 @@ void ClientLobby::receivePlayerVote(Event* event) */ void ClientLobby::disconnectedPlayer(Event* event) { - if (!checkDataSize(event, 1)) return; - - NetworkString &data = event->data(); - unsigned disconnected_player_count = data.getUInt8(); - uint32_t host_id = data.getUInt32(); + auto packet = event->getPacket(); + unsigned disconnected_player_count = packet.players_size; + uint32_t host_id = packet.host_id; m_peers_votes.erase(host_id); // If in-game world exists the kart rewinder will know which player // disconnects @@ -637,8 +627,7 @@ void ClientLobby::disconnectedPlayer(Event* event) SFXManager::get()->quickSound("appear"); for (unsigned i = 0; i < disconnected_player_count; i++) { - std::string name; - data.decodeString(&name); + std::string name = packet.names[i]; if (in_game_world) continue; core::stringw player_name = StringUtils::utf8ToWide(name); @@ -659,10 +648,7 @@ void ClientLobby::disconnectedPlayer(Event* event) */ void ClientLobby::connectionAccepted(Event* event) { - // At least 8 bytes should remain now - if (!checkDataSize(event, 8)) return; - - NetworkString &data = event->data(); + auto packet = event->getPacket(); // Accepted // ======== Log::info("ClientLobby", "The server accepted the connection."); @@ -678,38 +664,36 @@ void ClientLobby::connectionAccepted(Event* event) MessageQueue::add(MessageQueue::MT_GENERIC, msg); } - uint32_t host_id = data.getUInt32(); + uint32_t host_id = packet.host_id; STKHost::get()->setMyHostId(host_id); if (auto sl = LobbyProtocol::getByType(PT_CHILD)) sl->setClientServerHostId(host_id); assert(!NetworkConfig::get()->isAddingNetworkPlayers()); - uint32_t server_version = data.getUInt32(); + uint32_t server_version = packet.server_version; NetworkConfig::get()->setJoinedServerVersion(server_version); assert(server_version != 0); m_auto_started = false; m_state.store(CONNECTED); - unsigned list_caps = data.getUInt16(); + unsigned list_caps = packet.capabilities_size; std::set caps; for (unsigned i = 0; i < list_caps; i++) { - std::string cap; - data.decodeString(&cap); - caps.insert(cap); + caps.insert(packet.capabilities[i]); } NetworkConfig::get()->setServerCapabilities(caps); - float auto_start_timer = data.getFloat(); - int state_frequency_in_server = data.getUInt32(); + float auto_start_timer = packet.auto_start_timer; + int state_frequency_in_server = packet.state_frequency; NetworkConfig::get()->setStateFrequency(state_frequency_in_server); if (!GUIEngine::isNoGraphics() && auto_start_timer != std::numeric_limits::max()) NetworkingLobby::getInstance()->setStartingTimerTo(auto_start_timer); - m_server_enabled_chat = data.getUInt8() == 1; + m_server_enabled_chat = packet.chat_allowed; if (NetworkConfig::get()->getServerCapabilities().find("report_player") != NetworkConfig::get()->getServerCapabilities().end()) - m_server_enabled_report_player = data.getUInt8() == 1; + m_server_enabled_report_player = packet.reports_allowed; } // connectionAccepted //----------------------------------------------------------------------------- @@ -726,15 +710,15 @@ void ClientLobby::handleServerInfo(Event* event) } m_first_connect = false; - NetworkString &data = event->data(); + auto packet = event->getPacket(); // Add server info uint8_t u_data; - data.decodeStringW(&str); + str = StringUtils::utf8ToWide(packet.server_name); str.removeChars(L"\n\r\t"); NetworkingLobby::getInstance()->setHeader(str); - u_data = data.getUInt8(); + u_data = packet.difficulty; const core::stringw& difficulty_name = RaceManager::get()->getDifficultyName((RaceManager::Difficulty)u_data); RaceManager::get()->setDifficulty((RaceManager::Difficulty)u_data); @@ -742,14 +726,14 @@ void ClientLobby::handleServerInfo(Event* event) total_lines += _("Difficulty: %s", difficulty_name); total_lines += L"\n"; - unsigned max_player = data.getUInt8(); + unsigned max_player = packet.max_players; //I18N: In the networking lobby total_lines += _("Max players: %d", (int)max_player); total_lines += L"\n"; // Reserved for extra spectators - u_data = data.getUInt8(); - u_data = data.getUInt8(); + u_data = packet.extra_spectators_zero; + u_data = packet.game_mode; auto game_mode = ServerConfig::getLocalGameMode(u_data); RaceManager::get()->setMinorMode(game_mode.first); // We use single mode in network even it's grand prix @@ -760,16 +744,16 @@ void ClientLobby::handleServerInfo(Event* event) total_lines += _("Game mode: %s", mode_name); total_lines += L"\n"; - uint8_t extra_server_info = data.getUInt8(); + uint8_t extra_server_info = packet.has_extra_server_info; bool grand_prix_started = false; m_game_setup->resetExtraServerInfo(); switch (extra_server_info) { case 0: break; - case 1: + case 1: // soccer { - u_data = data.getUInt8(); + u_data = packet.extra_server_info[0]; core::stringw tl = _("Time limit"); core::stringw gl = _("Goals limit"); core::stringw sgt = u_data == 0 ? tl : gl; @@ -779,11 +763,11 @@ void ClientLobby::handleServerInfo(Event* event) total_lines += L"\n"; break; } - case 2: + case 2: // GP { - unsigned cur_gp_track = data.getUInt8(); + unsigned cur_gp_track = packet.extra_server_info[0]; grand_prix_started = cur_gp_track != 0; - unsigned total_gp_track = data.getUInt8(); + unsigned total_gp_track = packet.extra_server_info[1]; m_game_setup->setGrandPrixTrack(total_gp_track); total_lines += _("Grand prix progress: %d / %d", cur_gp_track, total_gp_track); @@ -792,8 +776,8 @@ void ClientLobby::handleServerInfo(Event* event) } } // Auto start info - unsigned min_players = data.getUInt8(); - float start_timeout = data.getFloat(); + unsigned min_players = packet.min_start_game_players; + float start_timeout = packet.start_game_counter; if (!GUIEngine::isNoGraphics()) { NetworkingLobby::getInstance()->initAutoStartTimer(grand_prix_started, @@ -801,8 +785,7 @@ void ClientLobby::handleServerInfo(Event* event) } // MOTD - core::stringw motd; - data.decodeString16(&motd); + core::stringw motd = packet.motd; if (!motd.empty()) total_lines += motd; @@ -814,10 +797,10 @@ void ClientLobby::handleServerInfo(Event* event) if (!GUIEngine::isNoGraphics()) NetworkingLobby::getInstance()->addMoreServerInfo(total_lines); - bool server_config = data.getUInt8() == 1; + bool server_config = packet.is_configurable; if (!GUIEngine::isNoGraphics()) NetworkingLobby::getInstance()->toggleServerConfigButton(server_config); - m_server_live_joinable = data.getUInt8() == 1; + m_server_live_joinable = packet.has_live_players; NetworkConfig::get()->setTuxHitboxAddon(m_server_live_joinable); } // handleServerInfo @@ -825,10 +808,8 @@ void ClientLobby::handleServerInfo(Event* event) void ClientLobby::updatePlayerList(Event* event) { if (!checkDataSize(event, 1)) return; - NetworkString& data = event->data(); - PlayerListPacket list_packet; - list_packet.fromNetworkString(&data); + auto list_packet = event->getPacket(); bool waiting = list_packet.game_started; if (m_waiting_for_game && !waiting) @@ -906,6 +887,7 @@ void ClientLobby::updatePlayerList(Event* event) //----------------------------------------------------------------------------- void ClientLobby::handleBadTeam() { + // BadTeamPacket has no more data SFXManager::get()->quickSound("anvil"); //I18N: Display when all players are in red or blue team, which the race //will not be allowed to start @@ -924,6 +906,7 @@ void ClientLobby::handleBadConnection() //----------------------------------------------------------------------------- void ClientLobby::becomingServerOwner() { + // ServerOwnershipPacket is empty otherwise, do nothing if (STKHost::get()->isClientServer()) return; @@ -984,8 +967,8 @@ void ClientLobby::handleChat(Event* event) void ClientLobby::connectionRefused(Event* event) { if (!checkDataSize(event, 1)) return; - const NetworkString &data = event->data(); - switch ((RejectReason)data.getUInt8()) // the second byte + auto packet = event->getPacket(); + switch ((RejectReason)packet.reason) // the second byte { case RR_BUSY: STKHost::get()->setErrorMessage( @@ -995,12 +978,15 @@ void ClientLobby::connectionRefused(Event* event) { core::stringw msg = _("Connection refused: You are banned from the server."); - core::stringw reason; - data.decodeStringW(&reason); - if (!reason.empty()) + + if (packet.message.has_value()) { - msg += L"\n"; - msg += reason; + core::stringw reason = StringUtils::utf8ToWide(packet.message.get_value()); + if (!reason.empty()) + { + msg += L"\n"; + msg += reason; + } } STKHost::get()->setErrorMessage(msg); break; @@ -1036,10 +1022,12 @@ void ClientLobby::connectionRefused(Event* event) void ClientLobby::startGame(Event* event) { World::getWorld()->setPhase(WorldStatus::SERVER_READY_PHASE); - uint64_t start_time = event->data().getUInt64(); + + auto packet = event->getPacket(); + uint64_t start_time = packet.start_time; powerup_manager->setRandomSeed(start_time); - unsigned check_structure_count = event->data().getUInt8(); + unsigned check_structure_count = packet.check_count; LinearWorld* lw = dynamic_cast(World::getWorld()); if (lw) lw->handleServerCheckStructureCount(check_structure_count); @@ -1047,7 +1035,7 @@ void ClientLobby::startGame(Event* event) NetworkItemManager* nim = dynamic_cast (Track::getCurrentTrack()->getItemManager()); assert(nim); - nim->restoreCompleteState(event->data()); + nim->restoreCompleteState(packet.nim_complete_state); core::stringw err_msg = _("Failed to start the network game."); // Different stk process thread may have different stk host @@ -1080,25 +1068,26 @@ void ClientLobby::startGame(Event* event) void ClientLobby::startSelection(Event* event) { SFXManager::get()->quickSound("wee"); - const NetworkString& data = event->data(); - startVotingPeriod(data.getFloat()); - bool skip_kart_screen = data.getUInt8() == 1; - m_server_auto_game_time = data.getUInt8() == 1; - m_server_enabled_track_voting = data.getUInt8() == 1; - const unsigned kart_num = data.getUInt16(); - const unsigned track_num = data.getUInt16(); + auto packet = event->getPacket(); + startVotingPeriod(packet.voting_timeout); + bool skip_kart_screen = packet.no_kart_selection; + m_server_auto_game_time = packet.fixed_length; + m_server_enabled_track_voting = packet.track_voting; + + // kimden: I think this is already decoded somewhere? + // Worth moving to another function anyway. + const unsigned kart_num = packet.assets.karts_number; + const unsigned track_num = packet.assets.maps_number; m_available_karts.clear(); m_available_tracks.clear(); for (unsigned i = 0; i < kart_num; i++) { - std::string kart; - data.decodeString(&kart); + std::string kart = packet.assets.karts[i]; m_available_karts.insert(kart); } for (unsigned i = 0; i < track_num; i++) { - std::string track; - data.decodeString(&track); + std::string track = packet.assets.maps[i]; m_available_tracks.insert(track); } @@ -1162,23 +1151,21 @@ void ClientLobby::startSelection(Event* event) */ void ClientLobby::raceFinished(Event* event) { - NetworkString &data = event->data(); + auto packet = event->getPacket(); Log::info("ClientLobby", "Server notified that the race is finished."); LinearWorld* lw = dynamic_cast(World::getWorld()); if (m_game_setup->isGrandPrix()) { - int t = data.getUInt32(); - core::stringw kart_name; - data.decodeStringW(&kart_name); + int t = packet.fastest_lap.get_value(); + core::stringw kart_name = packet.fastest_kart_name.get_value(); lw->setFastestLapTicks(t); lw->setFastestKartName(kart_name); - RaceManager::get()->configGrandPrixResultFromNetwork(data); + RaceManager::get()->configGrandPrixResultFromNetwork(packet.gp_scores.get_value()); } else if (RaceManager::get()->modeHasLaps()) { - int t = data.getUInt32(); - core::stringw kart_name; - data.decodeStringW(&kart_name); + int t = packet.fastest_lap.get_value(); + core::stringw kart_name = packet.fastest_kart_name.get_value(); lw->setFastestLapTicks(t); lw->setFastestKartName(kart_name); } @@ -1210,12 +1197,12 @@ void ClientLobby::raceFinished(Event* event) if (NetworkConfig::get()->getServerCapabilities().find("ranking_changes") != NetworkConfig::get()->getServerCapabilities().end()) { - bool has_ranking_changes = (data.getUInt8() & 1) != 0; - if (has_ranking_changes) + bool has_ranking_changes = packet.point_changes_indication; + if (has_ranking_changes && packet.point_changes.has_value()) { - unsigned count = data.getUInt8(); - for (unsigned i = 0; i < count; i++) - m_ranking_changes.push_back(data.getFloat()); + PointChangesPacket subpacket = packet.point_changes.get_value(); + // unsigned count = subpacket.player_count; + m_ranking_changes = subpacket.changes; } } @@ -1256,11 +1243,11 @@ void ClientLobby::backToLobby(Event *event) else exitGameState(); - NetworkString &data = event->data(); + auto packet = event->getPacket(); core::stringw msg; MessageQueue::MessageType mt = MessageQueue::MT_ERROR; - switch ((BackLobbyReason)data.getUInt8()) // the second byte + switch ((BackLobbyReason)packet.reason) // the second byte { case BLR_NO_GAME_FOR_LIVE_JOIN: // I18N: Error message shown if live join or spectate failed in network @@ -1274,7 +1261,7 @@ void ClientLobby::backToLobby(Event *event) // I18N: Error message shown if only 1 player remains in network msg = _("Only 1 player remaining, returning to lobby."); break; - case BLR_SERVER_ONWER_QUITED_THE_GAME: + case BLR_SERVER_OWNER_QUIT_THE_GAME: // I18N: Error message shown when all players will go back to lobby // when server owner quited the game if (!STKHost::get()->isClientServer()) @@ -1305,11 +1292,9 @@ void ClientLobby::backToLobby(Event *event) */ void ClientLobby::finishedLoadingWorld() { - NetworkString* ns = getNetworkString(1); - ns->setSynchronous(m_server_send_live_load_world); - ns->addUInt8(LE_CLIENT_LOADED_WORLD); - Comm::sendToServer(ns, PRM_RELIABLE); - delete ns; + FinishedLoadingLiveJoinPacket packet; + packet.m_override_synchronous = m_server_send_live_load_world; + Comm::sendPacketToServer(packet); } // finishedLoadingWorld //----------------------------------------------------------------------------- @@ -1319,17 +1304,17 @@ void ClientLobby::liveJoinAcknowledged(Event* event) if (!w) return; - const NetworkString& data = event->data(); - m_start_live_game_time = data.getUInt64(); + auto packet = event->getPacket(); + m_start_live_game_time = packet.client_starting_time; powerup_manager->setRandomSeed(m_start_live_game_time); - unsigned check_structure_count = event->data().getUInt8(); + unsigned check_structure_count = packet.check_count; LinearWorld* lw = dynamic_cast(World::getWorld()); if (lw) lw->handleServerCheckStructureCount(check_structure_count); - m_start_live_game_time = data.getUInt64(); - m_last_live_join_util_ticks = data.getUInt32(); + m_start_live_game_time = packet.live_join_start_time; + m_last_live_join_util_ticks = packet.last_live_join_util_ticks; for (unsigned i = 0; i < w->getNumKarts(); i++) { AbstractKart* k = w->getKart(i); @@ -1340,16 +1325,27 @@ void ClientLobby::liveJoinAcknowledged(Event* event) NetworkItemManager* nim = dynamic_cast (Track::getCurrentTrack()->getItemManager()); assert(nim); - nim->restoreCompleteState(data); - w->restoreCompleteState(data); + nim->restoreCompleteState(packet.nim_complete_state); + w->restoreCompleteState(std::dynamic_pointer_cast(packet.world_complete_state)); - if (RaceManager::get()->supportsLiveJoining() && data.size() > 0) + if (RaceManager::get()->supportsLiveJoining() && packet.inside_info.has_value()) { + InsideGameInfoPacket subpacket = packet.inside_info.get_value(); // Get and update the players list 1 more time in case the was // player connection or disconnection - std::vector > players = - decodePlayers(data); - getPlayersAddonKartType(data, players); + std::vector > players; + unsigned player_count = subpacket.players_size; + for (unsigned i = 0; i < player_count; ++i) + players.push_back(decodePlayer(subpacket.all_players[i])); + + if (NetworkConfig::get()->getServerCapabilities().find("real_addon_karts") != + NetworkConfig::get()->getServerCapabilities().end()) + { + for (unsigned i = 0; i < players.size(); i++) + { + players[i]->setKartData(KartData(subpacket.players_kart_data[i])); + } + } w->resetElimination(); for (unsigned i = 0; i < players.size(); i++) { @@ -1404,11 +1400,9 @@ void ClientLobby::finishLiveJoin() //----------------------------------------------------------------------------- void ClientLobby::requestKartInfo(uint8_t kart_id) { - NetworkString* ns = getNetworkString(1); - ns->setSynchronous(true); - ns->addUInt8(LE_KART_INFO).addUInt8(kart_id); - Comm::sendToServer(ns, PRM_RELIABLE); - delete ns; + KartInfoRequestPacket packet; + packet.kart_id = kart_id; + Comm::sendPacketToServer(packet); } // requestKartInfo //----------------------------------------------------------------------------- @@ -1418,26 +1412,24 @@ void ClientLobby::handleKartInfo(Event* event) if (!w) return; - const NetworkString& data = event->data(); - int live_join_util_ticks = data.getUInt32(); - uint8_t kart_id = data.getUInt8(); - core::stringw player_name; - data.decodeStringW(&player_name); - uint32_t host_id = data.getUInt32(); - float kart_color = data.getFloat(); - uint32_t online_id = data.getUInt32(); - HandicapLevel h = (HandicapLevel)data.getUInt8(); - uint8_t local_id = data.getUInt8(); - std::string kart_name; - data.decodeString(&kart_name); - std::string country_code; - data.decodeString(&country_code); + auto packet = event->getPacket(); + int live_join_util_ticks = packet.live_join_util_ticks; + uint8_t kart_id = packet.kart_id; + core::stringw player_name = packet.player_name; + uint32_t host_id = packet.host_id; + float kart_color = packet.default_kart_color; + uint32_t online_id = packet.online_id; + HandicapLevel h = (HandicapLevel)packet.handicap; + uint8_t local_id = packet.local_player_id; + std::string kart_name = packet.kart_name; + std::string country_code = packet.country_code; KartData kart_data; - if (NetworkConfig::get()->getServerCapabilities().find( - "real_addon_karts") != - NetworkConfig::get()->getServerCapabilities().end() && - data.size() > 0) - kart_data = KartData(data); + if (NetworkConfig::get()->getServerCapabilities().find("real_addon_karts") != + NetworkConfig::get()->getServerCapabilities().end() + && packet.kart_data.has_value()) + { + kart_data = packet.kart_data.get_value(); + } RemoteKartInfo& rki = RaceManager::get()->getKartInfo(kart_id); rki.setPlayerName(player_name); @@ -1500,8 +1492,7 @@ void ClientLobby::sendChat(irr::core::stringw text, KartTeam team) text = text.trim().removeChars(L"\n\r"); if (text.size() > 0) { - NetworkString* chat = getNetworkString(); - chat->addUInt8(LobbyEvent::LE_CHAT); + ChatPacket packet; core::stringw name; PlayerProfile* player = PlayerManager::getCurrentPlayer(); @@ -1546,13 +1537,12 @@ void ClientLobby::sendChat(irr::core::stringw text, KartTeam team) name = core::stringw(L"\u200E") + name; } #endif - chat->encodeString16(name + L": " + text, 1000/*max_len*/); + packet.message = name + L": " + text; if (team != KART_TEAM_NONE) - chat->addUInt8(team); + packet.kart_team = team; - Comm::sendToServer(chat, PRM_RELIABLE); - delete chat; + Comm::sendPacketToServer(packet); } } // sendChat @@ -1671,9 +1661,11 @@ void ClientLobby::reportSuccess(Event* event) { bool succeeded = false; core::stringw reporting_name; - succeeded = event->data().getUInt8() == 1; + + auto packet = event->getPacket(); + succeeded = packet.success; if (succeeded) - event->data().decodeStringW(&reporting_name); + event->data().decodeStringW(&packet.reported_name); if (succeeded && !reporting_name.empty()) { // I18N: Tell player he has successfully report this named player @@ -1895,17 +1887,16 @@ void ClientLobby::handleClientCommand(const std::string& cmd) else { // Send for server command - NetworkString* cmd_ns = getNetworkString(1); - const std::string& language = UserConfigParams::m_language; - cmd_ns->addUInt8(LE_COMMAND).encodeString(language).encodeString(cmd); - Comm::sendToServer(cmd_ns, PRM_RELIABLE); - delete cmd_ns; + CommandPacket packet; + packet.language = UserConfigParams::m_language; + packet.command = cmd; + Comm::sendPacketToServer(packet); } #endif } // handleClientCommand // ---------------------------------------------------------------------------- -void ClientLobby::getKartsTracksNetworkString(BareNetworkString* ns) +AssetsPacket2 ClientLobby::getKartsTracksPacket() { std::vector all_k; for (unsigned i = 0; i < kart_properties_manager->getNumberOfKarts(); i++) @@ -1923,25 +1914,26 @@ void ClientLobby::getKartsTracksNetworkString(BareNetworkString* ns) auto all_t = TrackManager::get()->getAllTrackIdentifiers(); if (all_t.size() >= 65536) all_t.resize(65535); - ns->addUInt16((uint16_t)all_k.size()).addUInt16((uint16_t)all_t.size()); + + AssetsPacket2 packet; + packet.karts_number = (uint16_t)all_k.size(); + packet.maps_number = (uint16_t)all_t.size(); + for (const std::string& kart : all_k) - { - ns->encodeString(kart); - } + packet.karts.push_back(kart); + for (const std::string& track : all_t) - { - ns->encodeString(track); - } -} // getKartsTracksNetworkString + packet.maps.push_back(track); + + return packet; +} // getKartsTracksPacket // ---------------------------------------------------------------------------- void ClientLobby::updateAssetsToServer() { - NetworkString* ns = getNetworkString(1); - ns->addUInt8(LE_ASSETS_UPDATE); - getKartsTracksNetworkString(ns); - Comm::sendToServer(ns, PRM_RELIABLE); - delete ns; + NewAssetsPacket packet; + packet.assets = getKartsTracksPacket(); + Comm::sendPacketToServer(packet); } // updateAssetsToServer // ---------------------------------------------------------------------------- diff --git a/src/network/protocols/client_lobby.hpp b/src/network/protocols/client_lobby.hpp index 5f50dd8b0de..1216228d4f4 100644 --- a/src/network/protocols/client_lobby.hpp +++ b/src/network/protocols/client_lobby.hpp @@ -34,7 +34,6 @@ enum PeerDisconnectInfo : unsigned int; enum KartTeam : int8_t; enum HandicapLevel : uint8_t; -class BareNetworkString; class Server; namespace Online @@ -126,8 +125,6 @@ class ClientLobby : public LobbyProtocol std::set m_available_tracks; void addAllPlayers(Event* event); - void finalizeConnectionRequest(NetworkString* header, - BareNetworkString* rest, bool encrypt); std::map m_disconnected_msg; @@ -144,13 +141,12 @@ class ClientLobby : public LobbyProtocol void liveJoinAcknowledged(Event* event); void handleKartInfo(Event* event); void finishLiveJoin(); - std::vector > - decodePlayers(const BareNetworkString& data, + std::shared_ptr + decodePlayer(const EncodedSinglePlayerPacket& packet, std::shared_ptr peer = nullptr, bool* is_spectator = NULL) const; - void getPlayersAddonKartType(const BareNetworkString& data, - std::vector >& players) const; - void getKartsTracksNetworkString(BareNetworkString* ns); + + AssetsPacket2 getKartsTracksPacket(); void doInstallAddonsPack(); public: ClientLobby(std::shared_ptr s); diff --git a/src/network/protocols/command_manager.cpp b/src/network/protocols/command_manager.cpp index 1052eac9602..1463d0c239e 100644 --- a/src/network/protocols/command_manager.cpp +++ b/src/network/protocols/command_manager.cpp @@ -691,9 +691,8 @@ void CommandManager::setupContextUser() void CommandManager::handleCommand(Event* event, std::shared_ptr peer) { - NetworkString& data = event->data(); - std::string language; - data.decodeString(&language); + auto packet = event->getPacket(); + std::string language = packet.language; Context context(getLobby(), event, peer); auto& argv = context.m_argv; @@ -704,7 +703,7 @@ void CommandManager::handleCommand(Event* event, std::shared_ptr peer) auto& target_peer = context.m_target_peer; std::shared_ptr target_peer_strong = context.m_target_peer.lock(); - data.decodeString(&cmd); + cmd = packet.command; argv = StringUtils::splitQuoted(cmd, ' ', '"', '"', '\\'); if (argv.empty()) return; @@ -897,7 +896,7 @@ void CommandManager::handleCommand(Event* event, std::shared_ptr peer) first_time = false; } } - Comm::sendStringToAllPeers(msg); + Comm::sendStringToPeers(msg); auto res = response.second; if (!res.empty()) { @@ -909,7 +908,7 @@ void CommandManager::handleCommand(Event* event, std::shared_ptr peer) std::string msg2 = StringUtils::insertValues( "Command \"/%s\" has been successfully voted", new_cmd.c_str()); - Comm::sendStringToAllPeers(msg2); + Comm::sendStringToPeers(msg2); Context new_context(getLobby(), event, std::shared_ptr(nullptr), new_argv, new_cmd, UP_EVERYONE, UP_EVERYONE, false); execute(executed_command, new_context); } @@ -970,7 +969,7 @@ void CommandManager::update() std::string msg = StringUtils::insertValues( "Command \"/%s\" has been successfully voted", new_cmd.c_str()); - Comm::sendStringToAllPeers(msg); + Comm::sendStringToPeers(msg); // Happily the name of the votable coincides with the command full name std::shared_ptr command = m_full_name_to_command[votable_pairs.first].lock(); if (!command) @@ -1202,7 +1201,7 @@ void CommandManager::process_replay(Context& context) current_state ^= 1; getSettings()->setConsentOnReplays(current_state); - Comm::sendStringToAllPeers(std::string("Recording ghost replays is now ") + Comm::sendStringToPeers(std::string("Recording ghost replays is now ") + (current_state ? "on" : "off")); } else @@ -2166,12 +2165,12 @@ void CommandManager::process_gnu(Context& context) if (kart == "off") { kart_elimination->disable(); - Comm::sendStringToAllPeers("Gnu Elimination is now off"); + Comm::sendStringToPeers("Gnu Elimination is now off"); } else { kart_elimination->enable(kart); - Comm::sendStringToAllPeers(kart_elimination->getStartingMessage()); + Comm::sendStringToPeers(kart_elimination->getStartingMessage()); } } // process_gnu // ======================================================================== @@ -2377,7 +2376,7 @@ void CommandManager::process_length_multi(Context& context) } double value = std::max(0.0, temp_double); getSettings()->setMultiplier(value); - Comm::sendStringToAllPeers(StringUtils::insertValues( + Comm::sendStringToPeers(StringUtils::insertValues( "Game length is now %f x default", value)); } // process_length_multi // ======================================================================== @@ -2393,20 +2392,20 @@ void CommandManager::process_length_fixed(Context& context) } int value = std::max(0, temp_int); getSettings()->setFixedLapCount(value); - Comm::sendStringToAllPeers(StringUtils::insertValues( + Comm::sendStringToPeers(StringUtils::insertValues( "Game length is now %d", value)); } // process_length_fixed // ======================================================================== void CommandManager::process_length_clear(Context& context) { getSettings()->resetLapRestrictions(); - Comm::sendStringToAllPeers("Game length will be chosen by players"); + Comm::sendStringToPeers("Game length will be chosen by players"); } // process_length_clear // ======================================================================== void CommandManager::process_direction(Context& context) { - Comm::sendStringToAllPeers(getSettings()->getDirectionAsString()); + Comm::sendStringToPeers(getSettings()->getDirectionAsString()); } // process_direction // ======================================================================== @@ -2424,7 +2423,7 @@ void CommandManager::process_direction_assign(Context& context) error(context); return; } - Comm::sendStringToAllPeers(getSettings()->getDirectionAsString(true)); + Comm::sendStringToPeers(getSettings()->getDirectionAsString(true)); } // process_direction_assign // ======================================================================== @@ -2538,7 +2537,7 @@ void CommandManager::process_queue_push(Context& context) } msg.pop_back(); - Comm::sendStringToAllPeers(msg); + Comm::sendStringToPeers(msg); getLobby()->updatePlayerList(); } // process_queue_push // ======================================================================== @@ -2588,7 +2587,7 @@ void CommandManager::process_queue_pop(Context& context) } } msg.pop_back(); - Comm::sendStringToAllPeers(msg); + Comm::sendStringToPeers(msg); getLobby()->updatePlayerList(); } // process_queue_pop // ======================================================================== @@ -2616,7 +2615,7 @@ void CommandManager::process_queue_clear(Context& context) } } msg.pop_back(); - Comm::sendStringToAllPeers(msg); + Comm::sendStringToPeers(msg); getLobby()->updatePlayerList(); } // process_queue_clear // ======================================================================== @@ -2656,7 +2655,7 @@ void CommandManager::process_queue_shuffle(Context& context) } } msg.pop_back(); - Comm::sendStringToAllPeers(msg); + Comm::sendStringToPeers(msg); getLobby()->updatePlayerList(); } // process_queue_shuffle // ======================================================================== @@ -2679,7 +2678,7 @@ void CommandManager::process_allowstart_assign(Context& context) return; } getSettings()->setAllowedToStart(argv[1] != "0"); - Comm::sendStringToAllPeers(getSettings()->getAllowedToStartAsString(true)); + Comm::sendStringToPeers(getSettings()->getAllowedToStartAsString(true)); } // process_allowstart_assign // ======================================================================== @@ -2699,7 +2698,7 @@ void CommandManager::process_shuffle_assign(Context& context) return; } getSettings()->setGPGridShuffled(argv[1] != "0"); - Comm::sendStringToAllPeers(getSettings()->getWhetherShuffledGPGridAsString(true)); + Comm::sendStringToPeers(getSettings()->getWhetherShuffledGPGridAsString(true)); } // process_shuffle_assign // ======================================================================== @@ -2861,7 +2860,7 @@ void CommandManager::process_resetgp(Context& context) getGameSetupFromCtx()->setGrandPrixTrack(number_of_games); } getGPManager()->resetGrandPrix(); - Comm::sendStringToAllPeers("GP is now reset"); + Comm::sendStringToPeers("GP is now reset"); } // process_resetgp // ======================================================================== @@ -2953,7 +2952,7 @@ void CommandManager::process_troll_assign(Context& context) hit_processor->setAntiTroll(true); msg = "Trolls will be kicked"; } - Comm::sendStringToAllPeers(msg); + Comm::sendStringToPeers(msg); } // process_troll_assign // ======================================================================== @@ -2988,7 +2987,7 @@ void CommandManager::process_hitmsg_assign(Context& context) hit_processor->setShowTeammateHits(true); msg = "Teammate hits will be sent to all players"; } - Comm::sendStringToAllPeers(msg); + Comm::sendStringToPeers(msg); } // process_hitmsg_assign // ======================================================================== @@ -3025,7 +3024,7 @@ void CommandManager::process_teamhit_assign(Context& context) hit_processor->setTeammateHitMode(true); msg = "Teammate hits are punished now"; } - Comm::sendStringToAllPeers(msg); + Comm::sendStringToPeers(msg); } // process_teamhit_assign // ======================================================================== @@ -3043,7 +3042,7 @@ void CommandManager::process_scoring_assign(Context& context) std::string cmd2; CommandManager::restoreCmdByArgv(cmd2, argv, ' ', '"', '"', '\\', 1); if (getGPManager()->trySettingGPScoring(cmd2)) - Comm::sendStringToAllPeers("Scoring set to \"" + cmd2 + "\""); + Comm::sendStringToPeers("Scoring set to \"" + cmd2 + "\""); else context.say("Scoring could not be parsed from \"" + cmd2 + "\""); } // process_scoring_assign @@ -3177,7 +3176,7 @@ void CommandManager::process_game(Context& context) msg += StringUtils::insertValues(" %d seconds", new_addition); getSettings()->setFixedLapCount(getSettings()->getFixedLapCount() + 1); } - Comm::sendStringToAllPeers(msg); + Comm::sendStringToPeers(msg); Log::info("CommandManager", "SoccerMatchLog: Game number changed from %d to %d", old_game_number, new_game_number); } // process_game @@ -3338,7 +3337,7 @@ void CommandManager::process_stop(Context& context) return; SoccerWorld *sw = dynamic_cast(w); sw->stop(); - Comm::sendStringToAllPeers("The game is stopped."); + Comm::sendStringToPeers("The game is stopped."); Log::info("CommandManager", "SoccerMatchLog: The game is stopped"); } // process_stop // ======================================================================== @@ -3355,7 +3354,7 @@ void CommandManager::process_go(Context& context) return; SoccerWorld *sw = dynamic_cast(w); sw->resume(); - Comm::sendStringToAllPeers("The game is resumed."); + Comm::sendStringToPeers("The game is resumed."); Log::info("CommandManager", "SoccerMatchLog: The game is resumed"); } // process_go // ======================================================================== @@ -3372,7 +3371,7 @@ void CommandManager::process_lobby(Context& context) return; SoccerWorld *sw = dynamic_cast(w); sw->allToLobby(); - Comm::sendStringToAllPeers("The game will be restarted."); + Comm::sendStringToPeers("The game will be restarted."); } // process_lobby // ======================================================================== @@ -3446,7 +3445,7 @@ void CommandManager::process_test(Context& context) acting_peer->getMainProfile(), acting_peer.get()); } username = "{" + argv[1].substr(4) + "} " + username; - Comm::sendStringToAllPeers(username + ", " + argv[2] + ", " + argv[3]); + Comm::sendStringToPeers(username + ", " + argv[2] + ", " + argv[3]); } // process_test // ======================================================================== @@ -3485,7 +3484,7 @@ void CommandManager::process_slots_assign(Context& context) } getSettings()->setCurrentMaxPlayersInGame((unsigned)number); getLobby()->updatePlayerList(); - Comm::sendStringToAllPeers(StringUtils::insertValues( + Comm::sendStringToPeers(StringUtils::insertValues( "Number of playable slots is now %s", number)); } // process_slots_assign @@ -3551,7 +3550,7 @@ void CommandManager::process_preserve_assign(Context& context) "'%s' is now preserved on server reset", argv[1].c_str()); getSettings()->insertIntoPreserved(argv[1]); } - Comm::sendStringToAllPeers(msg); + Comm::sendStringToPeers(msg); } // process_preserve_assign // ======================================================================== diff --git a/src/network/protocols/game_event_types.hpp b/src/network/protocols/game_event_types.hpp new file mode 100644 index 00000000000..19e1ce1f181 --- /dev/null +++ b/src/network/protocols/game_event_types.hpp @@ -0,0 +1,45 @@ +// +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2025 kimden +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef GAME_EVENT_TYPES_H +#define GAME_EVENT_TYPES_H + +#include "utils/types.hpp" + +enum GameEventType : uint8_t +{ + GE_KART_FINISHED_RACE = 1, + GE_STARTUP_BOOST = 2, + GE_BATTLE_KART_SCORE = 3, + GE_CTF_SCORED = 4, + GE_RESET_BALL = 5, + GE_PLAYER_GOAL = 6, + GE_CHECK_LINE = 7 +}; // GameEventType + +/** The type of game events to be forwarded to the server. */ +enum GameProtocolEventType: uint8_t +{ + GP_CONTROLLER_ACTION, + GP_STATE, + GP_ITEM_UPDATE, + GP_ITEM_CONFIRMATION, + GP_ADJUST_TIME +}; + +#endif // GAME_EVENT_TYPES_H diff --git a/src/network/protocols/game_events_protocol.cpp b/src/network/protocols/game_events_protocol.cpp index 1e39aae4580..64a6183e736 100644 --- a/src/network/protocols/game_events_protocol.cpp +++ b/src/network/protocols/game_events_protocol.cpp @@ -64,42 +64,51 @@ bool GameEventsProtocol::notifyEvent(Event* event) FreeForAll* ffa = dynamic_cast(World::getWorld()); SoccerWorld* sw = dynamic_cast(World::getWorld()); LinearWorld* lw = dynamic_cast(World::getWorld()); + + // Scopes are added to allow initializing variables inside switch (type) { case GE_KART_FINISHED_RACE: - kartFinishedRace(data); break; + { + auto packet = event->getPacket(); + kartFinishedRace(packet); + break; + } case GE_RESET_BALL: { if (!sw) throw std::invalid_argument("No soccer world"); - sw->handleResetBallFromServer(data); + + auto packet = event->getPacket(); + sw->handleResetBallFromServer(packet); break; } case GE_PLAYER_GOAL: { if (!sw) throw std::invalid_argument("No soccer world"); - sw->handlePlayerGoalFromServer(data); + + auto packet = event->getPacket(); + sw->handlePlayerGoalFromServer(packet); break; } case GE_BATTLE_KART_SCORE: { if (!ffa) throw std::invalid_argument("No free-for-all world"); - ffa->setKartScoreFromServer(data); + + auto packet = event->getPacket(); + ffa->setKartScoreFromServer(packet); break; } case GE_CTF_SCORED: { if (!ctf) throw std::invalid_argument("No CTF world"); - uint8_t kart_id = data.getUInt8(); - bool red_team_scored = data.getUInt8() == 1; - int16_t new_kart_scores = data.getUInt16(); - int new_red_scores = data.getUInt8(); - int new_blue_scores = data.getUInt8(); - ctf->ctfScored(kart_id, red_team_scored, new_kart_scores, - new_red_scores, new_blue_scores); + + auto packet = event->getPacket(); + ctf->ctfScored(packet.active_holder, packet.red_inactive, packet.kart_score, + packet.red_score, packet.blue_score); break; } case GE_STARTUP_BOOST: @@ -116,11 +125,11 @@ bool GameEventsProtocol::notifyEvent(Event* event) float f = LobbyProtocol::get() ->getStartupBoostOrPenaltyForKart( event->getPeer()->getAveragePing(), kart_id); - NetworkString *ns = getNetworkString(); - ns->setSynchronous(true); - ns->addUInt8(GE_STARTUP_BOOST).addUInt8(kart_id).addFloat(f); - Comm::sendMessageToPeers(ns, PRM_RELIABLE); - delete ns; + + GameEventStartupBoostPacket packet; + packet.kart_id = kart_id; + packet.value = f; + Comm::sendPacketToPeers(packet); } else { @@ -142,8 +151,10 @@ bool GameEventsProtocol::notifyEvent(Event* event) { if (!lw) throw std::invalid_argument("No linear world"); + + auto packet = event->getPacket(); if (NetworkConfig::get()->isClient()) - lw->updateCheckLinesClient(data); + lw->updateCheckLinesClient(packet); break; } default: @@ -161,12 +172,10 @@ bool GameEventsProtocol::notifyEvent(Event* event) */ void GameEventsProtocol::kartFinishedRace(AbstractKart *kart, float time) { - NetworkString *ns = getNetworkString(20); - ns->setSynchronous(true); - ns->addUInt8(GE_KART_FINISHED_RACE).addUInt8(kart->getWorldKartId()) - .addFloat(time); - Comm::sendMessageToPeers(ns, PRM_RELIABLE); - delete ns; + GameEventKartFinishedPacket packet; + packet.kart_id = kart->getWorldKartId(); + packet.time = time; + Comm::sendPacketToPeers(packet); } // kartFinishedRace // ---------------------------------------------------------------------------- @@ -174,16 +183,10 @@ void GameEventsProtocol::kartFinishedRace(AbstractKart *kart, float time) * event from the server. It updates the game with this information. * \param ns The message from the server. */ -void GameEventsProtocol::kartFinishedRace(const NetworkString &ns) +void GameEventsProtocol::kartFinishedRace(const GameEventKartFinishedPacket& packet) { - if (ns.size() < 5) - { - Log::warn("GameEventsProtocol", "kartFinisheRace: Too short message."); - return; - } - - uint8_t kart_id = ns.getUInt8(); - float time = ns.getFloat(); + uint8_t kart_id = packet.kart_id; + float time = packet.time; if (RaceManager::get()->modeHasLaps()) { World::getWorld()->getKart(kart_id) @@ -196,9 +199,7 @@ void GameEventsProtocol::kartFinishedRace(const NetworkString &ns) // ---------------------------------------------------------------------------- void GameEventsProtocol::sendStartupBoost(uint8_t kart_id) { - NetworkString *ns = getNetworkString(); - ns->setSynchronous(true); - ns->addUInt8(GE_STARTUP_BOOST).addUInt8(kart_id); - Comm::sendToServer(ns, PRM_RELIABLE); - delete ns; + StartupBoostPacket packet; + packet.kart_id = kart_id; + Comm::sendPacketToServer(packet); } // sendStartupBoost diff --git a/src/network/protocols/game_events_protocol.hpp b/src/network/protocols/game_events_protocol.hpp index 0cc05fcf616..60009559df7 100644 --- a/src/network/protocols/game_events_protocol.hpp +++ b/src/network/protocols/game_events_protocol.hpp @@ -8,29 +8,16 @@ class AbstractKart; class GameEventsProtocol : public Protocol { -public: - enum GameEventType : uint8_t - { - GE_KART_FINISHED_RACE = 1, - GE_STARTUP_BOOST = 2, - GE_BATTLE_KART_SCORE = 3, - GE_CTF_SCORED = 4, - GE_RESET_BALL = 5, - GE_PLAYER_GOAL = 6, - GE_CHECK_LINE = 7 - }; // GameEventType private: int m_last_finished_position; - void eliminatePlayer(const NetworkString &ns); - public: GameEventsProtocol(); virtual ~GameEventsProtocol(); virtual bool notifyEvent(Event* event) OVERRIDE; void kartFinishedRace(AbstractKart *kart, float time); - void kartFinishedRace(const NetworkString &ns); + void kartFinishedRace(const GameEventKartFinishedPacket& packet); void sendStartupBoost(uint8_t kart_id); virtual void setup() OVERRIDE {} virtual void update(int ticks) OVERRIDE; diff --git a/src/network/protocols/game_protocol.cpp b/src/network/protocols/game_protocol.cpp index ed3144d202d..0826114c19d 100644 --- a/src/network/protocols/game_protocol.cpp +++ b/src/network/protocols/game_protocol.cpp @@ -63,13 +63,12 @@ GameProtocol::GameProtocol() { m_network_item_manager = static_cast (Track::getCurrentTrack()->getItemManager()); - m_data_to_send = getNetworkString(); + m_packet_to_send = std::make_shared(); } // GameProtocol //----------------------------------------------------------------------------- GameProtocol::~GameProtocol() { - delete m_data_to_send; } // ~GameProtocol //----------------------------------------------------------------------------- @@ -82,15 +81,14 @@ void GameProtocol::sendActions() // Clear left-over data from previous frame. This way the network // string will increase till it reaches maximum size necessary - m_data_to_send->clear(); if (m_all_actions.size() > 255) { Log::warn("GameProtocol", "Too many actions unsent %d.", (int)m_all_actions.size()); m_all_actions.resize(255); } - m_data_to_send->addUInt8(GP_CONTROLLER_ACTION) - .addUInt8(uint8_t(m_all_actions.size())); + ControllerActionBigPacket big_packet; + big_packet.count = m_all_actions.size(); // Add all actions for (auto& a : m_all_actions) @@ -102,15 +100,22 @@ void GameProtocol::sendActions() a.m_ticks, a.m_kart_id, a.m_action, a.m_value, a.m_value_l, a.m_value_r); } - m_data_to_send->addUInt32(a.m_ticks); - m_data_to_send->addUInt8(a.m_kart_id); const auto& c = compressAction(a); - m_data_to_send->addUInt8(std::get<0>(c)).addUInt16(std::get<1>(c)) - .addUInt16(std::get<2>(c)).addUInt16(std::get<3>(c)); + + ControllerSingleActionPacket packet; + packet.ticks = a.m_ticks; + packet.subpacket.kart_id = a.m_kart_id; + packet.subpacket.compressed_action_0 = std::get<0>(c); + packet.subpacket.compressed_action_1 = std::get<1>(c); + packet.subpacket.compressed_action_2 = std::get<2>(c); + packet.subpacket.compressed_action_3 = std::get<3>(c); + big_packet.actions.push_back(packet); } // for a in m_all_actions - // FIXME: for now send reliable - Comm::sendToServer(m_data_to_send, PRM_RELIABLE); + Comm::sendPacketToServer(big_packet, PRM_RELIABLE); + + m_packet_to_send = std::make_shared(big_packet); + m_all_actions.clear(); } // sendActions @@ -169,11 +174,15 @@ void GameProtocol::controllerAction(int kart_id, PlayerAction action, const auto& c = compressAction(a); // Store the event in the rewind manager, which is responsible // for freeing the allocated memory - BareNetworkString *s = new BareNetworkString(4); - s->addUInt8(kart_id).addUInt8(std::get<0>(c)).addUInt16(std::get<1>(c)) - .addUInt16(std::get<2>(c)).addUInt16(std::get<3>(c)); - RewindManager::get()->addEvent(this, s, /*confirmed*/true, + ControllerActionPacket packet; + packet.kart_id = kart_id; + packet.compressed_action_0 = std::get<0>(c); + packet.compressed_action_1 = std::get<1>(c); + packet.compressed_action_2 = std::get<2>(c); + packet.compressed_action_3 = std::get<3>(c); + + RewindManager::get()->addEvent(this, packet, /*confirmed*/true, World::getWorld()->getTicksSinceStart()); } // controllerAction @@ -189,15 +198,17 @@ void GameProtocol::handleControllerAction(Event *event) if (NetworkConfig::get()->isServer() && (peer->isWaitingForGame() || peer->getAvailableKartIDs().empty())) return; - NetworkString &data = event->data(); - uint8_t count = data.getUInt8(); + + auto packet = event->getPacket(); + uint8_t count = packet.count; bool will_trigger_rewind = false; //int rewind_delta = 0; int cur_ticks = 0; const int not_rewound = RewindManager::get()->getNotRewoundWorldTicks(); for (unsigned int i = 0; i < count; i++) { - cur_ticks = data.getUInt32(); + auto& action_packet = packet.actions[i]; + cur_ticks = action_packet.ticks; // Since this is running in a thread, it might be called during // a rewind, i.e. with an incorrect world time. So the event // time needs to be compared with the World time independent @@ -207,7 +218,7 @@ void GameProtocol::handleControllerAction(Event *event) will_trigger_rewind = true; //rewind_delta = not_rewound - cur_ticks; } - uint8_t kart_id = data.getUInt8(); + uint8_t kart_id = action_packet.subpacket.kart_id; if (NetworkConfig::get()->isServer() && !peer->availableKartID(kart_id)) { @@ -216,10 +227,10 @@ void GameProtocol::handleControllerAction(Event *event) return; } - uint8_t w = data.getUInt8(); - uint16_t x = data.getUInt16(); - uint16_t y = data.getUInt16(); - uint16_t z = data.getUInt16(); + uint8_t w = action_packet.subpacket.compressed_action_0; + uint16_t x = action_packet.subpacket.compressed_action_1; + uint16_t y = action_packet.subpacket.compressed_action_2; + uint16_t z = action_packet.subpacket.compressed_action_3; if (Network::m_connection_debug) { const auto& a = decompressAction(w, x, y, z); @@ -228,24 +239,16 @@ void GameProtocol::handleControllerAction(Event *event) cur_ticks, kart_id, std::get<0>(a), std::get<1>(a), std::get<2>(a), std::get<3>(a)); } - BareNetworkString *s = new BareNetworkString(3); - s->addUInt8(kart_id).addUInt8(w).addUInt16(x).addUInt16(y) - .addUInt16(z); - RewindManager::get()->addNetworkEvent(this, s, cur_ticks); + RewindManager::get()->addNetworkEvent(this, action_packet.subpacket, cur_ticks); } - if (data.size() > 0) - { - Log::warn("GameProtocol", - "Received invalid controller data - remains %d",data.size()); - } if (NetworkConfig::get()->isServer()) { // Send update to all clients except the original sender if the event // is after the server time peer->updateLastActivity(); if (!will_trigger_rewind) - STKHost::get()->sendPacketExcept(peer, &data, PRM_UNRELIABLE); + Comm::sendPacketExcept(peer, packet, PRM_UNRELIABLE); } // if server } // handleControllerAction @@ -258,12 +261,11 @@ void GameProtocol::handleControllerAction(Event *event) void GameProtocol::sendItemEventConfirmation(int ticks) { assert(NetworkConfig::get()->isClient()); - NetworkString *ns = getNetworkString(5); - ns->addUInt8(GP_ITEM_CONFIRMATION).addUInt32(ticks); - // This message can be sent unreliable, it's not critical if it doesn't - // get delivered, a future update will come through - Comm::sendToServer(ns, PRM_UNRELIABLE); - delete ns; + + ItemConfirmationPacket packet; + packet.ticks = ticks; + + Comm::sendPacketToServer(packet); } // sendItemEventConfirmation // ---------------------------------------------------------------------------- @@ -275,7 +277,8 @@ void GameProtocol::sendItemEventConfirmation(int ticks) void GameProtocol::handleItemEventConfirmation(Event *event) { assert(NetworkConfig::get()->isServer()); - int ticks = event->data().getTime(); + auto packet = event->getPacket(); + int ticks = packet.ticks; m_network_item_manager->setItemConfirmationTime(event->getPeerSP(), ticks); } // handleItemEventConfirmation @@ -286,9 +289,11 @@ void GameProtocol::handleItemEventConfirmation(Event *event) void GameProtocol::startNewState() { assert(NetworkConfig::get()->isServer()); - m_data_to_send->clear(); - m_data_to_send->addUInt8(GP_STATE) - .addUInt32(World::getWorld()->getTicksSinceStart()); + m_packet_to_send = std::make_shared(); + + GameEventStatePacket packet; + packet.ticks_since_start = World::getWorld()->getTicksSinceStart(); + m_packet_to_send->state = packet; } // startNewState // ---------------------------------------------------------------------------- @@ -296,11 +301,11 @@ void GameProtocol::startNewState() * is copied, so the data can be freed after this call/. * \param buffer Adds the data in the buffer to the current state. */ -void GameProtocol::addState(BareNetworkString *buffer) +void GameProtocol::addState(TheRestOfBgsPacket packet) { assert(NetworkConfig::get()->isServer()); - m_data_to_send->addUInt16(buffer->size()); - (*m_data_to_send) += *buffer; + + m_packet_to_send->the_rest.push_back(std::move(packet)); } // addState // ---------------------------------------------------------------------------- @@ -308,23 +313,12 @@ void GameProtocol::addState(BareNetworkString *buffer) * names of rewinder using to the beginning of state buffer * \param cur_rewinder List of current rewinder using. */ -void GameProtocol::finalizeState(std::vector& cur_rewinder) +void GameProtocol::finalizeState(const std::vector& cur_rewinder) { assert(NetworkConfig::get()->isServer()); - auto& buffer = m_data_to_send->getBuffer(); - auto pos = buffer.begin() + 1/*protocol type*/ + 1 /*gp event type*/+ - 4/*time*/; - - m_data_to_send->reset(); - std::vector names; - names.push_back((uint8_t)cur_rewinder.size()); - for (std::string& name : cur_rewinder) - { - names.push_back((uint8_t)name.size()); - std::vector rewinder(name.begin(), name.end()); - names.insert(names.end(), rewinder.begin(), rewinder.end()); - } - buffer.insert(pos, names.begin(), names.end()); + + m_packet_to_send->rewinders_size = cur_rewinder.size(); + m_packet_to_send->rewinders = cur_rewinder; // they should be after time } // finalizeState // ---------------------------------------------------------------------------- @@ -334,7 +328,7 @@ void GameProtocol::finalizeState(std::vector& cur_rewinder) void GameProtocol::sendState() { assert(NetworkConfig::get()->isServer()); - Comm::sendMessageToPeers(m_data_to_send, PRM_UNRELIABLE); + Comm::sendPacketToPeers(*m_packet_to_send, PRM_UNRELIABLE); } // sendState // ---------------------------------------------------------------------------- @@ -344,22 +338,16 @@ void GameProtocol::handleState(Event *event) { if (!NetworkConfig::get()->isClient()) return; - NetworkString &data = event->data(); - int ticks = data.getUInt32(); + + auto packet = event->getPacket(); + + int ticks = packet.ticks; // Check for updated rewinder using - unsigned rewinder_size = data.getUInt8(); - std::vector rewinder_using; - for (unsigned i = 0; i < rewinder_size; i++) - { - std::string name; - data.decodeString(&name); - rewinder_using.push_back(name); - } + unsigned rewinder_size = packet.rewinders_size; // The memory for bns will be handled in the RewindInfoState object - RewindInfoState* ris = new RewindInfoState(ticks, data.getCurrentOffset(), - rewinder_using, data.getBuffer()); + RewindInfoState* ris = new RewindInfoState(ticks, packet.rewinders, packet.the_rest); RewindManager::get()->addNetworkRewindInfo(ris); } // handleState @@ -377,13 +365,15 @@ void GameProtocol::undo(BareNetworkString *buffer) * events. * \param buffer Pointer to the saved state information. */ -void GameProtocol::rewind(BareNetworkString *buffer) +void GameProtocol::rewind(const ControllerActionPacket& packet) { - int kart_id = buffer->getUInt8(); - uint8_t w = buffer->getUInt8(); - uint16_t x = buffer->getUInt16(); - uint16_t y = buffer->getUInt16(); - uint16_t z = buffer->getUInt16(); + // kimden: I think the packet type is correct. + // I will likely have to change it to shared_ptr though. + int kart_id = packet.kart_id; + uint8_t w = packet.compressed_action_0; + uint16_t x = packet.compressed_action_1; + uint16_t y = packet.compressed_action_2; + uint16_t z = packet.compressed_action_3; const auto& a = decompressAction(w, x, y, z); Controller *c = World::getWorld()->getKart(kart_id)->getController(); PlayerController *pc = dynamic_cast(c); diff --git a/src/network/protocols/game_protocol.hpp b/src/network/protocols/game_protocol.hpp index fa4c28d9f3e..f9c14652ec9 100644 --- a/src/network/protocols/game_protocol.hpp +++ b/src/network/protocols/game_protocol.hpp @@ -21,6 +21,7 @@ #include "network/event_rewinder.hpp" #include "network/protocol.hpp" +#include "network/packet_types.hpp" #include "input/input.hpp" // for PlayerAction #include "utils/cpp2011.hpp" @@ -33,7 +34,6 @@ class BareNetworkString; class NetworkItemManager; -class NetworkString; class STKPeer; class GameProtocol : public Protocol @@ -44,17 +44,9 @@ class GameProtocol : public Protocol * asynchronous event update. */ mutable std::mutex m_world_deleting_mutex; - /** The type of game events to be forwarded to the server. */ - enum { GP_CONTROLLER_ACTION, - GP_STATE, - GP_ITEM_UPDATE, - GP_ITEM_CONFIRMATION, - GP_ADJUST_TIME - }; - /** A network string that collects all information from the server to be sent * next. */ - NetworkString *m_data_to_send; + std::shared_ptr m_packet_to_send; /** The server might request that the world clock of a client is adjusted * to reduce number of rollbacks. */ @@ -112,13 +104,15 @@ class GameProtocol : public Protocol void controllerAction(int kart_id, PlayerAction action, int value, int val_l, int val_r); void startNewState(); - void addState(BareNetworkString *buffer); + void addState(TheRestOfBgsPacket packet); void sendState(); - void finalizeState(std::vector& cur_rewinder); + void finalizeState(std::vector& cur_rewinder); void sendItemEventConfirmation(int ticks); +#define nonvirtual + virtual void undo(BareNetworkString *buffer) OVERRIDE; - virtual void rewind(BareNetworkString *buffer) OVERRIDE; + nonvirtual void rewind(const ControllerActionPacket& packet) /*OVERRIDE*/; // ------------------------------------------------------------------------ virtual void setup() OVERRIDE {}; // ------------------------------------------------------------------------ @@ -138,8 +132,8 @@ class GameProtocol : public Protocol return m_game_protocol[pt].lock(); } // lock // ------------------------------------------------------------------------ - /** Returns the NetworkString in which a state was saved. */ - NetworkString* getState() const { return m_data_to_send; } + /** Returns the packet ptr in which a state was saved. */ + std::shared_ptr getState() const { return m_packet_to_send; } // ------------------------------------------------------------------------ std::unique_lock acquireWorldDeletingMutex() const { return std::unique_lock(m_world_deleting_mutex); } diff --git a/src/network/protocols/server_lobby.cpp b/src/network/protocols/server_lobby.cpp index 2b47cd2b50c..a49e72a998b 100644 --- a/src/network/protocols/server_lobby.cpp +++ b/src/network/protocols/server_lobby.cpp @@ -77,25 +77,21 @@ // Helper functions. namespace { - void encodePlayers(BareNetworkString* bns, - std::vector >& players, + EncodedSinglePlayerPacket encodePlayer(std::shared_ptr player, const std::shared_ptr& decorator) { - bns->addUInt8((uint8_t)players.size()); - for (unsigned i = 0; i < players.size(); i++) - { - std::shared_ptr& player = players[i]; - bns->encodeString(player->getDecoratedName(decorator)) - .addUInt32(player->getHostId()) - .addFloat(player->getDefaultKartColor()) - .addUInt32(player->getOnlineId()) - .addUInt8(player->getHandicap()) - .addUInt8(player->getLocalPlayerId()) - .addUInt8(player->getTeam()) - .encodeString(player->getCountryCode()); - bns->encodeString(player->getKartName()); - } - } // encodePlayers + EncodedSinglePlayerPacket packet; + packet.name = player->getDecoratedName(decorator); + packet.host_id = player->getHostId(); + packet.kart_color = player->getDefaultKartColor(); + packet.online_id = player->getOnlineId(); + packet.handicap = player->getHandicap(); + packet.local_player_id = player->getLocalPlayerId(); + packet.kart_team = player->getTeam(); + packet.country_code = player->getCountryCode(); + packet.kart_name = player->getKartName(); + return packet; + } //------------------------------------------------------------------------- /** Returns true if world is active for clients to live join, spectate or * going back to lobby live @@ -144,29 +140,6 @@ namespace return players; } // getLivePlayers //------------------------------------------------------------------------- - - void getClientAssetsFromNetworkString(const NetworkString& ns, - std::set& client_karts, - std::set& client_maps) - { - client_karts.clear(); - client_maps.clear(); - const unsigned kart_num = ns.getUInt16(); - const unsigned maps_num = ns.getUInt16(); - for (unsigned i = 0; i < kart_num; i++) - { - std::string kart; - ns.decodeString(&kart); - client_karts.insert(kart); - } - for (unsigned i = 0; i < maps_num; i++) - { - std::string map; - ns.decodeString(&map); - client_maps.insert(map); - } - } // getClientAssetsFromNetworkString - //------------------------------------------------------------------------- } // anonymous namespace // ============================================================================ @@ -242,7 +215,7 @@ ServerLobby::ServerLobby() : LobbyProtocol() m_ranking = std::make_shared(); } m_name_decorator = std::make_shared(); - m_items_complete_state = new BareNetworkString(); + m_nim_complete_state = NimCompleteStatePacket(); m_server_id_online.store(0); m_difficulty.store(ServerConfig::m_server_difficulty); m_game_mode.store(ServerConfig::m_server_mode); @@ -261,7 +234,6 @@ ServerLobby::~ServerLobby() // For child process the request manager will keep on running unregisterServer(m_process_type == PT_MAIN ? true : false/*now*/); } - delete m_items_complete_state; if (getSettings()->isSavingServerConfig()) ServerConfig::writeServerConfigToDisk(); @@ -367,35 +339,12 @@ void ServerLobby::handleChat(Event* event) if (!checkDataSize(event, 1) || !getChatManager()->getChat()) return; auto peer = event->getPeerSP(); + auto packet = event->getPacket(); - core::stringw message; - event->data().decodeString16(&message, 360/*max_len*/); - - // Check if the message starts with "(the name of main profile): " to prevent - // impersonation, see #5121. - std::string message_utf8 = StringUtils::wideToUtf8(message); - std::string prefix = StringUtils::wideToUtf8( - event->getPeer()->getPlayerProfiles()[0]->getName()) + ": "; - - if (!StringUtils::startsWith(message_utf8, prefix)) - { - NetworkString* chat = getNetworkString(); - chat->setSynchronous(true); - // This string is not set to be translatable, because it is - // currently written by the server. The server would have - // to send a warning for interpretation by the client to - // allow proper translation. Also, this string can only be - // triggered with modified STK clients anyways. - core::stringw warn = "Don't try to impersonate others!"; - chat->addUInt8(LE_CHAT).encodeString16(warn); - event->getPeer()->sendPacket(chat, PRM_RELIABLE); - delete chat; - return; - } - + core::stringw message = packet.message; KartTeam target_team = KART_TEAM_NONE; - if (event->data().size() > 0) - target_team = (KartTeam)event->data().getUInt8(); + if (packet.kart_team.has_value()) + target_team = packet.kart_team.get_value(); getChatManager()->handleNormalChatMessage(peer, StringUtils::wideToUtf8(message), target_team, m_name_decorator); @@ -407,10 +356,10 @@ void ServerLobby::changeTeam(Event* event) if (!checkDataSize(event, 1)) return; - NetworkString& data = event->data(); - uint8_t local_id = data.getUInt8(); - auto& player = event->getPeer()->getPlayerProfiles().at(local_id); + auto packet = event->getPacket(); + uint8_t local_id = packet.local_id; + auto& player = event->getPeer()->getPlayerProfiles().at(local_id); getTeamManager()->changeTeam(player); } // changeTeam @@ -420,8 +369,8 @@ void ServerLobby::kickHost(Event* event) if (!checkDataSize(event, 4)) return; - NetworkString& data = event->data(); - uint32_t host_id = data.getUInt32(); + auto packet = event->getPacket(); + uint32_t host_id = packet.host_id; std::shared_ptr target = STKHost::get()->findPeerByHostId(host_id); auto initiator = event->getPeerSP(); @@ -585,9 +534,9 @@ void ServerLobby::writePlayerReport(Event* event) return; auto reporter_npp = reporter->getMainProfile(); - uint32_t reporting_host_id = event->data().getUInt32(); - core::stringw info; - event->data().decodeString16(&info); + auto packet = event->getPacket(); + uint32_t reporting_host_id = packet.host_id; + core::stringw info = packet.info; if (info.empty()) return; @@ -600,12 +549,10 @@ void ServerLobby::writePlayerReport(Event* event) reporting_peer, reporting_npp, info); if (written) { - NetworkString* success = getNetworkString(); - success->setSynchronous(true); - success->addUInt8(LE_REPORT_PLAYER).addUInt8(1) - .encodeString(reporting_npp->getName()); - event->getPeer()->sendPacket(success, PRM_RELIABLE); - delete success; + ReportSuccessPacket packet2; + packet2.success = 1; + packet2.reported_name = reporting_npp->getName(); + event->getPeer()->sendPacket(packet2); } #endif } // writePlayerReport @@ -947,8 +894,6 @@ void ServerLobby::asynchronousUpdate() auto& stk_config = STKConfig::get(); - NetworkString* load_world_message = getLoadWorldMessage(players, - false/*live_join*/); m_game_setup->setHitCaptureTime(getSettings()->getBattleHitCaptureLimit(), getSettings()->getBattleTimeLimit()); uint16_t flag_return_time = (uint16_t)stk_config->time2Ticks( @@ -968,12 +913,12 @@ void ServerLobby::asynchronousUpdate() resetPeersReady(); m_state = LOAD_WORLD; - Comm::sendMessageToPeers(load_world_message); + LoadWorldPacket packet = getLoadWorldMessage(players, false/*live_join*/); + Comm::sendPacketToPeers(packet); // updatePlayerList so the in lobby players (if any) can see always // spectators join the game if (has_always_on_spectators || !previous_spectate_mode.empty()) updatePlayerList(); - delete load_world_message; if (RaceManager::get()->getMinorMode() == RaceManager::MINOR_MODE_SOCCER) @@ -1004,33 +949,38 @@ void ServerLobby::asynchronousUpdate() } // asynchronousUpdate //----------------------------------------------------------------------------- -NetworkString* ServerLobby::getLoadWorldMessage( +LoadWorldPacket ServerLobby::getLoadWorldMessage( std::vector >& players, bool live_join) const { - NetworkString* load_world_message = getNetworkString(); - load_world_message->setSynchronous(true); - load_world_message->addUInt8(LE_LOAD_WORLD); - getSettings()->encodeDefaultVote(load_world_message); - load_world_message->addUInt8(live_join ? 1 : 0); - encodePlayers(load_world_message, players, m_name_decorator); - load_world_message->addUInt32(m_item_seed); + LoadWorldPacket packet; + packet.default_vote = getSettings()->encodeDefaultVote(); + packet.live_join = live_join; + packet.players_size = players.size(); + for (auto& player: players) + packet.all_players.push_back(encodePlayer(player, m_name_decorator)); + packet.item_seed = m_item_seed; + + auto& stk_config = STKConfig::get(); + if (RaceManager::get()->isBattleMode()) { - auto& stk_config = STKConfig::get(); - - load_world_message->addUInt32(getSettings()->getBattleHitCaptureLimit()) - .addFloat(getSettings()->getBattleTimeLimit()); - uint16_t flag_return_time = (uint16_t)stk_config->time2Ticks( - getSettings()->getFlagReturnTimeout()); - load_world_message->addUInt16(flag_return_time); - uint16_t flag_deactivated_time = (uint16_t)stk_config->time2Ticks( - getSettings()->getFlagDeactivatedTime()); - load_world_message->addUInt16(flag_deactivated_time); + BattleInfoPacket battle_packet; + battle_packet.battle_hit_capture_limit = getSettings()->getBattleHitCaptureLimit(); + battle_packet.battle_time_limit = getSettings()->getBattleTimeLimit(); + battle_packet.flag_return_time = (uint16_t)stk_config->time2Ticks( + getSettings()->getFlagReturnTimeout()); + battle_packet.flag_deactivated_time = (uint16_t)stk_config->time2Ticks( + getSettings()->getFlagDeactivatedTime()); + packet.battle_info = battle_packet; } + MultipleKartDataPacket multi_packet; for (unsigned i = 0; i < players.size(); i++) - players[i]->getKartData().encode(load_world_message); - return load_world_message; + multi_packet.players_kart_data.push_back(players[i]->getKartData().encode()); + + packet.karts_data = multi_packet; + + return packet; } // getLoadWorldMessage //----------------------------------------------------------------------------- @@ -1077,20 +1027,14 @@ bool ServerLobby::canLiveJoinNow() const */ void ServerLobby::rejectLiveJoin(std::shared_ptr peer, BackLobbyReason blr) { - NetworkString* reset = getNetworkString(2); - reset->setSynchronous(true); - reset->addUInt8(LE_BACK_LOBBY).addUInt8(blr); - peer->sendPacket(reset, PRM_RELIABLE); - delete reset; + BackLobbyPacket packet1; + packet1.reason = blr; + peer->sendPacket(packet1); updatePlayerList(); - NetworkString* server_info = getNetworkString(); - server_info->setSynchronous(true); - server_info->addUInt8(LE_SERVER_INFO); - m_game_setup->addServerInfo(server_info); - peer->sendPacket(server_info, PRM_RELIABLE); - delete server_info; + ServerInfoPacket packet2 = m_game_setup->addServerInfo(); + peer->sendPacket(packet2); peer->updateLastActivity(); } // rejectLiveJoin @@ -1105,8 +1049,8 @@ void ServerLobby::liveJoinRequest(Event* event) // in general, but you know what caused it if smth goes wrong. std::shared_ptr peer = event->getPeerSP(); - const NetworkString& data = event->data(); - bool spectator = data.getUInt8() == 1; + auto packet = event->getPacket(); + bool spectator = packet.is_spectator; if (!canLiveJoinNow()) { @@ -1124,7 +1068,7 @@ void ServerLobby::liveJoinRequest(Event* event) if (!spectator) { auto& spectators_by_limit = getCrownManager()->getSpectatorsByLimit(); - setPlayerKarts(data, peer); + setPlayerKarts(packet.player_karts.get_value(), peer); std::vector used_id; for (unsigned i = 0; i < peer->getPlayerProfiles().size(); i++) @@ -1165,10 +1109,10 @@ void ServerLobby::liveJoinRequest(Event* event) std::vector > players = getLivePlayers(); - NetworkString* load_world_message = getLoadWorldMessage(players, - true/*live_join*/); - peer->sendPacket(load_world_message, PRM_RELIABLE); - delete load_world_message; + + LoadWorldPacket load_world_packet = getLoadWorldMessage(players, true/*live_join*/); + peer->sendPacket(load_world_packet); + peer->updateLastActivity(); } // liveJoinRequest @@ -1242,6 +1186,7 @@ int ServerLobby::getReservedId(std::shared_ptr& p, void ServerLobby::finishedLoadingLiveJoinClient(Event* event) { std::shared_ptr peer = event->getPeerSP(); + auto unused = event->getPacket(); if (!canLiveJoinNow()) { rejectLiveJoin(peer, BLR_NO_GAME_FOR_LIVE_JOIN); @@ -1311,36 +1256,46 @@ void ServerLobby::finishedLoadingLiveJoinClient(Event* event) } const uint8_t cc = (uint8_t)Track::getCurrentTrack()->getCheckManager()->getCheckStructureCount(); - NetworkString* ns = getNetworkString(10); - ns->setSynchronous(true); - ns->addUInt8(LE_LIVE_JOIN_ACK).addUInt64(m_client_starting_time) - .addUInt8(cc).addUInt64(live_join_start_time) - .addUInt32(m_last_live_join_util_ticks); + + LiveJoinPacket packet; + + packet.client_starting_time = m_client_starting_time; + packet.check_count = cc; + packet.live_join_start_time = live_join_start_time; + packet.last_live_join_util_ticks = m_last_live_join_util_ticks; NetworkItemManager* nim = dynamic_cast (Track::getCurrentTrack()->getItemManager()); assert(nim); - nim->saveCompleteState(ns); + packet.nim_complete_state = nim->saveCompleteState(); nim->addLiveJoinPeer(peer); - w->saveCompleteState(ns, peer); + packet.world_complete_state = std::dynamic_pointer_cast + (w->saveCompleteState(peer)); + if (RaceManager::get()->supportsLiveJoining()) { + InsideGameInfoPacket inside_packet; // Only needed in non-racing mode as no need players can added after // starting of race std::vector > players = getLivePlayers(); - encodePlayers(ns, players, m_name_decorator); + + inside_packet.players_size = players.size(); + + for (auto& player: players) + inside_packet.all_players.push_back(encodePlayer(player, m_name_decorator)); for (unsigned i = 0; i < players.size(); i++) - players[i]->getKartData().encode(ns); + inside_packet.players_kart_data.push_back(players[i]->getKartData().encode()); + + packet.inside_info = inside_packet; } m_peers_ready[peer] = false; peer->setWaitingForGame(false); peer->setSpectator(spectator); - peer->sendPacket(ns, PRM_RELIABLE); - delete ns; + peer->sendPacket(packet); updatePlayerList(); peer->updateLastActivity(); } // finishedLoadingLiveJoinClient @@ -1491,11 +1446,9 @@ void ServerLobby::update(int ticks) { // Send a notification to all players who may have start live join // or spectate to go back to lobby - NetworkString* back_to_lobby = getNetworkString(2); - back_to_lobby->setSynchronous(true); - back_to_lobby->addUInt8(LE_BACK_LOBBY).addUInt8(BLR_NONE); - Comm::sendMessageToPeersInServer(back_to_lobby, PRM_RELIABLE); - delete back_to_lobby; + BackLobbyPacket packet; + packet.reason = BLR_NONE; + Comm::sendPacketToPeersInServer(packet); RaceEventManager::get()->stop(); RaceEventManager::get()->getProtocol()->requestTerminate(); @@ -1504,11 +1457,9 @@ void ServerLobby::update(int ticks) else if (auto ai = m_ai_peer.lock()) { // Reset AI peer for empty server, which will delete world - NetworkString* back_to_lobby = getNetworkString(2); - back_to_lobby->setSynchronous(true); - back_to_lobby->addUInt8(LE_BACK_LOBBY).addUInt8(BLR_NONE); - ai->sendPacket(back_to_lobby, PRM_RELIABLE); - delete back_to_lobby; + BackLobbyPacket packet; + packet.reason = BLR_NONE; + ai->sendPacket(packet); } if (all_players_in_world_disconnected) m_game_setup->cancelOneRace(); @@ -1527,12 +1478,10 @@ void ServerLobby::update(int ticks) m_state.load() == SELECTING && STKHost::get()->getPlayersInGame() == 1) { - NetworkString* back_lobby = getNetworkString(2); - back_lobby->setSynchronous(true); - back_lobby->addUInt8(LE_BACK_LOBBY) - .addUInt8(BLR_ONE_PLAYER_IN_RANKED_MATCH); - Comm::sendMessageToPeers(back_lobby, PRM_RELIABLE); - delete back_lobby; + BackLobbyPacket packet; + packet.reason = BLR_ONE_PLAYER_IN_RANKED_MATCH; + Comm::sendPacketToPeers(packet); + resetVotingTime(); // m_game_setup->cancelOneRace(); //m_game_setup->stopGrandPrix(); @@ -1584,21 +1533,22 @@ void ServerLobby::update(int ticks) // result screen and go back to the lobby setTimeoutFromNow(15); m_state = RESULT_DISPLAY; - Comm::sendMessageToPeers(m_result_ns, PRM_RELIABLE); - delete m_result_ns; + + Comm::sendPacketToPeers(m_result_packet); + Log::info("ServerLobby", "End of game message sent"); break; + case RESULT_DISPLAY: if (checkPeersReady(true/*ignore_ai_peer*/, AFTER_GAME) || isTimeoutExpired()) { // Send a notification to all clients to exit // the race result screen - NetworkString* back_to_lobby = getNetworkString(2); - back_to_lobby->setSynchronous(true); - back_to_lobby->addUInt8(LE_BACK_LOBBY).addUInt8(BLR_NONE); - Comm::sendMessageToPeersInServer(back_to_lobby, PRM_RELIABLE); - delete back_to_lobby; + BackLobbyPacket packet; + packet.reason = BLR_NONE; + Comm::sendPacketToPeersInServer(packet); + m_rs_state.store(RS_ASYNC_RESET); } break; @@ -1774,11 +1724,8 @@ void ServerLobby::startSelection(const Event *event) Log::warn("ServerLobby", "Bad team choosing."); if (event) { - NetworkString* bt = getNetworkString(); - bt->setSynchronous(true); - bt->addUInt8(LE_BAD_TEAM); - event->getPeer()->sendPacket(bt, PRM_RELIABLE); - delete bt; + BadTeamPacket packet; + event->getPeer()->sendPacket(packet); } return; } @@ -1915,16 +1862,14 @@ void ServerLobby::startSelection(const Event *event) if (!getCrownManager()->canRace(peer) || peer->isWaitingForGame()) continue; // they are handled below - NetworkString *ns = getNetworkString(1); // Start selection - must be synchronous since the receiver pushes // a new screen, which must be done from the main thread. - ns->setSynchronous(true); - ns->addUInt8(LE_START_SELECTION) - .addFloat(getSettings()->getVotingTimeout()) - .addUInt8(/*m_game_setup->isGrandPrixStarted() ? 1 : */0) - .addUInt8((!getSettings()->hasNoLapRestrictions() ? 1 : 0)) - .addUInt8(getSettings()->hasTrackVoting() ? 1 : 0); + StartSelectionPacket packet; + packet.voting_timeout = getSettings()->getVotingTimeout(); + packet.no_kart_selection = getSettings()->isLegacyGPMode() && m_game_setup->isGrandPrixStarted(); + packet.fixed_length = !getSettings()->hasNoLapRestrictions(); + packet.track_voting = getSettings()->hasTrackVoting(); std::set all_k = peer->getClientAssets().first; std::string username = peer->getMainName(); @@ -1939,10 +1884,8 @@ void ServerLobby::startSelection(const Event *event) all_k = {}; } - getAssetManager()->encodePlayerKartsAndCommonMaps(ns, all_k); - - peer->sendPacket(ns, PRM_RELIABLE); - delete ns; + packet.assets = getAssetManager()->encodePlayerKartsAndCommonMaps(all_k); + peer->sendPacket(packet); if (getQueues()->areKartFiltersIgnoringKarts()) Comm::sendStringToPeer(peer, "The server will ignore your kart choice"); @@ -1951,16 +1894,16 @@ void ServerLobby::startSelection(const Event *event) m_state = SELECTING; if (need_to_update || !always_spectate_peers.empty()) { - NetworkString* back_lobby = getNetworkString(2); - back_lobby->setSynchronous(true); - back_lobby->addUInt8(LE_BACK_LOBBY).addUInt8(BLR_SPECTATING_NEXT_GAME); - STKHost::get()->sendPacketToAllPeersWith( + BackLobbyPacket packet; + packet.reason = BLR_SPECTATING_NEXT_GAME; + + Comm::sendPacketToPeersWith( [always_spectate_peers](std::shared_ptr peer) { return always_spectate_peers.find(peer) != always_spectate_peers.end(); - }, back_lobby, PRM_RELIABLE); - delete back_lobby; + }, packet); + updatePlayerList(); } @@ -2063,35 +2006,34 @@ void ServerLobby::checkRaceFinished() GameProtocol::lock()->requestTerminate(); // Save race result before delete the world - m_result_ns = getNetworkString(); - m_result_ns->setSynchronous(true); - m_result_ns->addUInt8(LE_RACE_FINISHED); + m_result_packet = RaceFinishedPacket(); std::vector gp_changes; - if (m_game_setup->isGrandPrix()) - { - getGPManager()->updateGPScores(gp_changes, m_result_ns); - } - else if (RaceManager::get()->modeHasLaps()) + + if (RaceManager::get()->modeHasLaps()) { int fastest_lap = static_cast(World::getWorld())->getFastestLapTicks(); - m_result_ns->addUInt32(fastest_lap); - m_result_ns->encodeString(static_cast(World::getWorld()) - ->getFastestLapKartName()); + + // kimden: you shouldn't expose packet field type like that + m_result_packet.fastest_lap = fastest_lap; + m_result_packet.fastest_kart_name = static_cast(World::getWorld()) + ->getFastestLapKartName(); } - uint8_t ranking_changes_indication = 0; - if (getSettings()->isRanked() && RaceManager::get()->modeHasLaps()) - ranking_changes_indication = 1; if (m_game_setup->isGrandPrix()) - ranking_changes_indication = 1; - m_result_ns->addUInt8(ranking_changes_indication); + { + m_result_packet.gp_scores = getGPManager()->updateGPScores(gp_changes); + } + + m_result_packet.point_changes_indication = + (getSettings()->isRanked() && RaceManager::get()->modeHasLaps()) || + m_game_setup->isGrandPrix(); if (getKartElimination()->isEnabled()) { std::string msg = getKartElimination()->onRaceFinished(); if (!msg.empty()) - Comm::sendStringToAllPeers(msg); + Comm::sendStringToPeers(msg); } if (getSettings()->isStoringResults()) @@ -2104,17 +2046,20 @@ void ServerLobby::checkRaceFinished() if (getSettings()->isRanked()) { - computeNewRankings(m_result_ns); + m_result_packet.point_changes = computeNewRankings(); submitRankingsToAddons(); } else if (m_game_setup->isGrandPrix()) { + PointChangesPacket subpacket; + unsigned player_count = RaceManager::get()->getNumPlayers(); - m_result_ns->addUInt8((uint8_t)player_count); + subpacket.player_count = (uint8_t)player_count; + for (unsigned i = 0; i < player_count; i++) - { - m_result_ns->addFloat(gp_changes[i]); - } + subpacket.changes.push_back(gp_changes[i]); + + m_result_packet.point_changes = subpacket; } m_state.store(WAIT_FOR_RACE_STOPPED); @@ -2127,17 +2072,22 @@ void ServerLobby::checkRaceFinished() /** Compute the new player's rankings used in ranked servers */ -void ServerLobby::computeNewRankings(NetworkString* ns) +PointChangesPacket ServerLobby::computeNewRankings() { + unsigned player_count = RaceManager::get()->getNumPlayers(); + + // Empty packet for exceptions - unlikely to have though. + PointChangesPacket empty_packet; + empty_packet.player_count = (uint8_t)player_count; + empty_packet.changes = std::vector(player_count, 0.); + // No ranking for battle mode if (!RaceManager::get()->modeHasLaps()) - return; + return empty_packet; World* w = World::getWorld(); assert(w); - unsigned player_count = RaceManager::get()->getNumPlayers(); - // If all players quitted the race, we assume something went wrong // and skip entirely rating and statistics updates. for (unsigned i = 0; i < player_count; i++) @@ -2145,7 +2095,7 @@ void ServerLobby::computeNewRankings(NetworkString* ns) if (!w->getKart(i)->isEliminated()) break; if ((i + 1) == player_count) - return; + return empty_packet; } // Fill the results for the rankings to process @@ -2160,16 +2110,22 @@ void ServerLobby::computeNewRankings(NetworkString* ns) data.push_back(entry); } + // "LOLAND" changes, accidentally merged into supertuxkart/master + // and not noticed for 4 months. + // for (int i = 0; i < 64; ++i) { m_ranking->computeNewRankings(data, RaceManager::get()->isTimeTrialMode()); + // } // Used to display rating change at the end of a race - ns->addUInt8((uint8_t)player_count); + PointChangesPacket packet; + packet.player_count = (uint8_t)player_count; for (unsigned i = 0; i < player_count; i++) { const uint32_t id = RaceManager::get()->getKartInfo(i).getOnlineId(); double change = m_ranking->getDelta(id); - ns->addFloat((float)change); + packet.changes.push_back((float)change); } + return packet; } // computeNewRankings //----------------------------------------------------------------------------- /** Called when a client disconnects. @@ -2193,17 +2149,17 @@ void ServerLobby::clientDisconnected(Event* event) else Log::warn("ServerLobby", "GameInfo is not accessible??"); - NetworkString* msg = getNetworkString(2); + PlayerDisconnectedPacket packet; + packet.players_size = (uint8_t)players_on_peer.size(); + packet.host_id = event->getPeer()->getHostId(); + const bool waiting_peer_disconnected = event->getPeer()->isWaitingForGame(); - msg->setSynchronous(true); - msg->addUInt8(LE_PLAYER_DISCONNECTED); - msg->addUInt8((uint8_t)players_on_peer.size()) - .addUInt32(event->getPeer()->getHostId()); + for (auto p : players_on_peer) { std::string name = StringUtils::wideToUtf8(p->getName()); - msg->encodeString(name); + packet.names.push_back(name); Log::info("ServerLobby", "%s disconnected", name.c_str()); getCommandManager()->deleteUser(name); } @@ -2214,7 +2170,7 @@ void ServerLobby::clientDisconnected(Event* event) resetToDefaultSettings(); // Don't show waiting peer disconnect message to in game player - STKHost::get()->sendPacketToAllPeersWith([waiting_peer_disconnected] + Comm::sendPacketToPeersWith([waiting_peer_disconnected] (std::shared_ptr p) { if (!p->isValidated()) @@ -2222,9 +2178,8 @@ void ServerLobby::clientDisconnected(Event* event) if (!p->isWaitingForGame() && waiting_peer_disconnected) return false; return true; - }, msg); + }, packet); updatePlayerList(); - delete msg; #ifdef ENABLE_SQLITE3 getDbConnector()->writeDisconnectInfoTable(event->getPeerSP()); @@ -2235,17 +2190,16 @@ void ServerLobby::clientDisconnected(Event* event) void ServerLobby::kickPlayerWithReason(std::shared_ptr peer, const char* reason) const { - NetworkString *message = getNetworkString(2); - message->setSynchronous(true); - message->addUInt8(LE_CONNECTION_REFUSED).addUInt8(RR_BANNED); - message->encodeString(std::string(reason)); + ConnectionRefusedPacket packet; + packet.reason = RR_BANNED; + packet.message = reason; + peer->sendPacket(packet, PRM_RELIABLE, PEM_UNENCRYPTED); + peer->cleanPlayerProfiles(); - peer->sendPacket(message, PRM_RELIABLE, PEM_UNENCRYPTED); peer->reset(); - delete message; } // kickPlayerWithReason - //----------------------------------------------------------------------------- + void ServerLobby::saveIPBanTable(const SocketAddress& addr) { #ifdef ENABLE_SQLITE3 @@ -2256,11 +2210,16 @@ void ServerLobby::saveIPBanTable(const SocketAddress& addr) bool ServerLobby::handleAssets(Event* event) { - const NetworkString& ns = event->data(); + auto packet = event->getPacket(); std::shared_ptr peer = event->getPeerSP(); - std::set client_karts, client_maps; - getClientAssetsFromNetworkString(ns, client_karts, client_maps); + std::set client_karts; + for (const std::string& item: packet.assets.karts) + client_karts.insert(item); + + std::set client_maps; + for (const std::string& item: packet.assets.maps) + client_maps.insert(item); return handleAssetsAndAddonScores(peer, client_karts, client_maps); } // handleAssets @@ -2279,34 +2238,18 @@ bool ServerLobby::handleAssetsAndAddonScores(std::shared_ptr peer, } else { - NetworkString *message = getNetworkString(2); - message->setSynchronous(true); - message->addUInt8(LE_CONNECTION_REFUSED) - .addUInt8(RR_INCOMPATIBLE_DATA); - - std::string advice = getSettings()->getIncompatibleAdvice(); - if (!advice.empty()) { - NetworkString *incompatible_reason = getNetworkString(); - incompatible_reason->addUInt8(LE_CHAT); - incompatible_reason->setSynchronous(true); - incompatible_reason->encodeString16( - StringUtils::utf8ToWide(advice)); - peer->sendPacket(incompatible_reason, - PRM_RELIABLE, PEM_UNENCRYPTED); - Log::info("ServerLobby", "Sent advice"); - delete incompatible_reason; - } + ConnectionRefusedPacket packet; + packet.reason = RR_INCOMPATIBLE_DATA; + packet.message = getSettings()->getIncompatibleAdvice(); + peer->sendPacket(packet, PRM_RELIABLE, PEM_UNENCRYPTED); peer->cleanPlayerProfiles(); - peer->sendPacket(message, PRM_RELIABLE, PEM_UNENCRYPTED); peer->reset(); - delete message; } Log::verbose("ServerLobby", "Player has incompatible karts / tracks."); return false; } - std::array addons_scores = getAssetManager()->getAddonScores(client_karts, client_maps); // Save available karts and tracks from clients in STKPeer so if this peer @@ -2332,8 +2275,8 @@ bool ServerLobby::handleAssetsAndAddonScores(std::shared_ptr peer, void ServerLobby::connectionRequested(Event* event) { std::shared_ptr peer = event->getPeerSP(); - NetworkString& data = event->data(); - if (!checkDataSize(event, 14)) return; + auto conn_packet = event->getPacket(); + // if (!checkDataSize(event, 14)) return; peer->cleanPlayerProfiles(); @@ -2342,59 +2285,60 @@ void ServerLobby::connectionRequested(Event* event) (m_state.load() != WAITING_FOR_START_GAME /*|| m_game_setup->isGrandPrixStarted()*/)) { - NetworkString *message = getNetworkString(2); - message->setSynchronous(true); - message->addUInt8(LE_CONNECTION_REFUSED).addUInt8(RR_BUSY); + ConnectionRefusedPacket packet; + packet.reason = RR_BUSY; // send only to the peer that made the request and disconnect it now - peer->sendPacket(message, PRM_RELIABLE, PEM_UNENCRYPTED); + peer->sendPacket(packet, PRM_RELIABLE, PEM_UNENCRYPTED); + peer->reset(); - delete message; Log::verbose("ServerLobby", "Player refused: selection started"); return; } // Check server version - int version = data.getUInt32(); + int version = conn_packet.server_version; auto& stk_config = STKConfig::get(); if (version < stk_config->m_min_server_version || version > stk_config->m_max_server_version) { - NetworkString *message = getNetworkString(2); - message->setSynchronous(true); - message->addUInt8(LE_CONNECTION_REFUSED) - .addUInt8(RR_INCOMPATIBLE_DATA); - peer->sendPacket(message, PRM_RELIABLE, PEM_UNENCRYPTED); + ConnectionRefusedPacket packet; + packet.reason = RR_INCOMPATIBLE_DATA; + peer->sendPacket(packet, PRM_RELIABLE, PEM_UNENCRYPTED); + peer->reset(); - delete message; Log::verbose("ServerLobby", "Player refused: wrong server version"); return; } - std::string user_version; - data.decodeString(&user_version); + std::string user_version = conn_packet.user_agent; event->getPeer()->setUserVersion(user_version); - unsigned list_caps = data.getUInt16(); + unsigned list_caps = conn_packet.capabilities_size; std::set caps; for (unsigned i = 0; i < list_caps; i++) { - std::string cap; - data.decodeString(&cap); + std::string cap = conn_packet.capabilities[i]; caps.insert(cap); } event->getPeer()->setClientCapabilities(caps); - std::set client_karts, client_maps; - getClientAssetsFromNetworkString(data, client_karts, client_maps); + std::set client_karts; + for (const std::string& item: conn_packet.assets.karts) + client_karts.insert(item); + + std::set client_maps; + for (const std::string& item: conn_packet.assets.maps) + client_maps.insert(item); + if (!handleAssetsAndAddonScores(event->getPeerSP(), client_karts, client_maps)) return; - unsigned player_count = data.getUInt8(); + unsigned player_count = conn_packet.player_count; uint32_t online_id = 0; uint32_t encrypted_size = 0; - online_id = data.getUInt32(); - encrypted_size = data.getUInt32(); + online_id = conn_packet.id; + encrypted_size = conn_packet.encrypted_size; // Will be disconnected if banned by IP testBannedForIP(peer); @@ -2407,7 +2351,7 @@ void ServerLobby::connectionRequested(Event* event) if (online_id != 0) testBannedForOnlineId(peer, online_id); - // Will be disconnected if banned by online id + if (peer->isDisconnected()) return; @@ -2416,12 +2360,11 @@ void ServerLobby::connectionRequested(Event* event) if (total_players + player_count + m_ai_profiles.size() > (unsigned)getSettings()->getServerMaxPlayers()) { - NetworkString *message = getNetworkString(2); - message->setSynchronous(true); - message->addUInt8(LE_CONNECTION_REFUSED).addUInt8(RR_TOO_MANY_PLAYERS); - peer->sendPacket(message, PRM_RELIABLE, PEM_UNENCRYPTED); + ConnectionRefusedPacket packet; + packet.reason = RR_TOO_MANY_PLAYERS; + peer->sendPacket(packet, PRM_RELIABLE, PEM_UNENCRYPTED); + peer->reset(); - delete message; Log::verbose("ServerLobby", "Player refused: too many players"); return; } @@ -2457,12 +2400,11 @@ void ServerLobby::connectionRequested(Event* event) if (failed_validation || failed_strictness || failed_anywhere_ai || failed_unhandled_ai) { - NetworkString* message = getNetworkString(2); - message->setSynchronous(true); - message->addUInt8(LE_CONNECTION_REFUSED).addUInt8(RR_INVALID_PLAYER); - peer->sendPacket(message, PRM_RELIABLE, PEM_UNENCRYPTED); + ConnectionRefusedPacket packet; + packet.reason = RR_INVALID_PLAYER; + peer->sendPacket(packet, PRM_RELIABLE, PEM_UNENCRYPTED); + peer->reset(); - delete message; Log::verbose("ServerLobby", "Player refused: invalid player"); return; } @@ -2470,47 +2412,50 @@ void ServerLobby::connectionRequested(Event* event) if (getSettings()->hasAiHandling() && peer->isAIPeer()) m_ai_peer = peer; - if (encrypted_size != 0) + // Second condition was not present before + if (encrypted_size != 0 && conn_packet.player_info_encrypted.has_value()) { - m_pending_connection[peer] = std::make_pair(online_id, - BareNetworkString(data.getCurrentData(), encrypted_size)); + NetworkString* ns = new NetworkString(); + auto encrypted = conn_packet.player_info_encrypted.get_value(); + encrypted.toNetworkString(ns); + m_pending_connection[peer] = std::make_pair(online_id, *(BareNetworkString*)ns); } else { core::stringw online_name; - if (online_id > 0) - data.decodeStringW(&online_name); - handleUnencryptedConnection(peer, data, online_id, online_name, + if (online_id > 0 && /* ??? */ conn_packet.player_name.has_value()) + online_name = conn_packet.player_name.get_value(); + handleUnencryptedConnection(peer, conn_packet.player_info_unencrypted, online_id, online_name, false/*is_pending_connection*/); } } // connectionRequested //----------------------------------------------------------------------------- void ServerLobby::handleUnencryptedConnection(std::shared_ptr peer, - BareNetworkString& data, uint32_t online_id, + const Optional& opt, uint32_t online_id, const core::stringw& online_name, bool is_pending_connection, std::string country_code) { - if (data.size() < 2) return; + if (!opt.has_value()) + return; + + RestConnectionRequestPacket packet = opt.get_value(); // Check for password std::string password; - data.decodeString(&password); + password = packet.private_server_password; const std::string& server_pw = getSettings()->getPrivateServerPassword(); if (online_id > 0) { std::string username = StringUtils::wideToUtf8(online_name); if (getSettings()->isTempBanned(username)) { - NetworkString* message = getNetworkString(2); - message->setSynchronous(true); - message->addUInt8(LE_CONNECTION_REFUSED) - .addUInt8(RR_BANNED); - std::string tempban = "Please behave well next time."; - message->encodeString(tempban); - peer->sendPacket(message, PRM_RELIABLE, PEM_UNENCRYPTED); + ConnectionRefusedPacket packet; + packet.reason = RR_BANNED; + packet.message = std::string("Please behave well next time."); + peer->sendPacket(packet, PRM_RELIABLE, PEM_UNENCRYPTED); + peer->reset(); - delete message; Log::verbose("ServerLobby", "Player refused: invalid player"); return; } @@ -2519,13 +2464,11 @@ void ServerLobby::handleUnencryptedConnection(std::shared_ptr peer, } if (password != server_pw) { - NetworkString *message = getNetworkString(2); - message->setSynchronous(true); - message->addUInt8(LE_CONNECTION_REFUSED) - .addUInt8(RR_INCORRECT_PASSWORD); - peer->sendPacket(message, PRM_RELIABLE, PEM_UNENCRYPTED); + ConnectionRefusedPacket packet; + packet.reason = RR_INCORRECT_PASSWORD; + peer->sendPacket(packet, PRM_RELIABLE, PEM_UNENCRYPTED); + peer->reset(); - delete message; Log::verbose("ServerLobby", "Player refused: incorrect password"); return; } @@ -2533,7 +2476,7 @@ void ServerLobby::handleUnencryptedConnection(std::shared_ptr peer, // Check again max players and duplicated player in ranked server, // if this is a pending connection unsigned total_players = 0; - unsigned player_count = data.getUInt8(); + unsigned player_count = packet.player_count; if (is_pending_connection) { @@ -2541,13 +2484,11 @@ void ServerLobby::handleUnencryptedConnection(std::shared_ptr peer, if (total_players + player_count > (unsigned)getSettings()->getServerMaxPlayers()) { - NetworkString *message = getNetworkString(2); - message->setSynchronous(true); - message->addUInt8(LE_CONNECTION_REFUSED) - .addUInt8(RR_TOO_MANY_PLAYERS); - peer->sendPacket(message, PRM_RELIABLE, PEM_UNENCRYPTED); + ConnectionRefusedPacket packet; + packet.reason = RR_TOO_MANY_PLAYERS; + peer->sendPacket(packet, PRM_RELIABLE, PEM_UNENCRYPTED); + peer->reset(); - delete message; Log::verbose("ServerLobby", "Player refused: too many players"); return; } @@ -2558,13 +2499,11 @@ void ServerLobby::handleUnencryptedConnection(std::shared_ptr peer, all_online_ids.find(online_id) != all_online_ids.end(); if (getSettings()->isRanked() && duplicated_ranked_player) { - NetworkString* message = getNetworkString(2); - message->setSynchronous(true); - message->addUInt8(LE_CONNECTION_REFUSED) - .addUInt8(RR_INVALID_PLAYER); - peer->sendPacket(message, PRM_RELIABLE, PEM_UNENCRYPTED); + ConnectionRefusedPacket packet; + packet.reason = RR_INVALID_PLAYER; + peer->sendPacket(packet, PRM_RELIABLE, PEM_UNENCRYPTED); + peer->reset(); - delete message; Log::verbose("ServerLobby", "Player refused: invalid player"); return; } @@ -2581,8 +2520,9 @@ void ServerLobby::handleUnencryptedConnection(std::shared_ptr peer, std::string utf8_online_name = StringUtils::wideToUtf8(online_name); for (unsigned i = 0; i < player_count; i++) { - core::stringw name; - data.decodeStringW(&name); + ConnectingPlayerPacket player_packet = packet.players[i]; + + core::stringw name = player_packet.name; // 30 to make it consistent with stk-addons max user name length if (name.empty()) name = L"unnamed"; @@ -2590,8 +2530,8 @@ void ServerLobby::handleUnencryptedConnection(std::shared_ptr peer, name = name.subString(0, 30); std::string utf8_name = StringUtils::wideToUtf8(name); - float default_kart_color = data.getFloat(); - HandicapLevel handicap = (HandicapLevel)data.getUInt8(); + float default_kart_color = player_packet.default_kart_color; + HandicapLevel handicap = (HandicapLevel)player_packet.handicap; auto player = std::make_shared (peer, i == 0 && !online_name.empty() && !peer->isAIPeer() ? online_name : name, @@ -2654,34 +2594,27 @@ void ServerLobby::handleUnencryptedConnection(std::shared_ptr peer, peer->setValidated(true); // send a message to the one that asked to connect - NetworkString* server_info = getNetworkString(); - server_info->setSynchronous(true); - server_info->addUInt8(LE_SERVER_INFO); - m_game_setup->addServerInfo(server_info); - peer->sendPacket(server_info); - delete server_info; + peer->sendPacket(m_game_setup->addServerInfo()); peer->updateLastActivity(); const bool game_started = m_state.load() != WAITING_FOR_START_GAME; - NetworkString* message_ack = getNetworkString(4); - message_ack->setSynchronous(true); - // connection success -- return the host id of peer - float auto_start_timer = getTimeUntilExpiration(); - message_ack->addUInt8(LE_CONNECTION_ACCEPTED).addUInt32(peer->getHostId()) - .addUInt32(ServerConfig::m_server_version); auto& stk_config = STKConfig::get(); + ConnectionAcceptedPacket ack_packet; - message_ack->addUInt16( - (uint16_t)stk_config->m_network_capabilities.size()); + // connection success -- return the host id of peer + float auto_start_timer = getTimeUntilExpiration(); + ack_packet.host_id = peer->getHostId(); + ack_packet.server_version = ServerConfig::m_server_version; + ack_packet.capabilities_size = (uint16_t)stk_config->m_network_capabilities.size(); for (const std::string& cap : stk_config->m_network_capabilities) - message_ack->encodeString(cap); - - message_ack->addFloat(auto_start_timer) - .addUInt32(getSettings()->getStateFrequency()) - .addUInt8(getChatManager()->getChat() ? 1 : 0) - .addUInt8(playerReportsTableExists() ? 1 : 0); + ack_packet.capabilities.push_back(cap); + + ack_packet.auto_start_timer = auto_start_timer; + ack_packet.state_frequency = getSettings()->getStateFrequency(); + ack_packet.chat_allowed = getChatManager()->getChat(); + ack_packet.reports_allowed = playerReportsTableExists(); peer->setSpectator(false); @@ -2717,8 +2650,7 @@ void ServerLobby::handleUnencryptedConnection(std::shared_ptr peer, { peer->setWaitingForGame(true); updatePlayerList(); - peer->sendPacket(message_ack); - delete message_ack; + peer->sendPacket(ack_packet); } else { @@ -2737,8 +2669,7 @@ void ServerLobby::handleUnencryptedConnection(std::shared_ptr peer, } } updatePlayerList(); - peer->sendPacket(message_ack); - delete message_ack; + peer->sendPacket(ack_packet); if (getSettings()->isRanked()) { @@ -2762,13 +2693,9 @@ void ServerLobby::handleUnencryptedConnection(std::shared_ptr peer, break; } } - NetworkString* chat = getNetworkString(); - chat->addUInt8(LE_CHAT); - chat->setSynchronous(true); - std::string warning = getKartElimination()->getWarningMessage(hasEliminatedPlayer); - chat->encodeString16(StringUtils::utf8ToWide(warning)); - peer->sendPacket(chat, PRM_RELIABLE); - delete chat; + + // This ns packet wasn't replaced with function immediately, I could mess up then... + Comm::sendStringToPeer(peer, getKartElimination()->getWarningMessage(hasEliminatedPlayer)); } if (getSettings()->isRecordingReplays()) { @@ -2927,11 +2854,8 @@ void ServerLobby::updatePlayerList(bool update_when_reset_server) list_packet.all_profiles.push_back(packet); } - NetworkString* pl = getNetworkString(); - list_packet.toNetworkString(pl); - // Don't send this message to in-game players - STKHost::get()->sendPacketToAllPeersWith([game_started] + Comm::sendPacketToPeersWith([game_started] (std::shared_ptr p) { if (!p->isValidated()) @@ -2939,8 +2863,7 @@ void ServerLobby::updatePlayerList(bool update_when_reset_server) if (!p->isWaitingForGame() && game_started) return false; return true; - }, pl); - delete pl; + }, list_packet); } // updatePlayerList //----------------------------------------------------------------------------- @@ -2992,11 +2915,8 @@ void ServerLobby::updateServerOwner(bool force) std::shared_ptr owner = getCrownManager()->getFirstInCrownOrder(peers); if (m_server_owner.expired() || m_server_owner.lock() != owner) { - NetworkString* ns = getNetworkString(); - ns->setSynchronous(true); - ns->addUInt8(LE_SERVER_OWNERSHIP); - owner->sendPacket(ns); - delete ns; + ServerOwnershipPacket packet; + owner->sendPacket(packet); } m_server_owner = owner; m_server_owner_id.store(owner->getHostId()); @@ -3020,9 +2940,9 @@ void ServerLobby::kartSelectionRequested(Event* event) event->getPeer()->getPlayerProfiles().empty()) return; - const NetworkString& data = event->data(); + auto packet = event->getPacket(); std::shared_ptr peer = event->getPeerSP(); - setPlayerKarts(data, peer); + setPlayerKarts(packet.karts, peer); } // kartSelectionRequested //----------------------------------------------------------------------------- @@ -3048,8 +2968,8 @@ void ServerLobby::handlePlayerVote(Event* event) if (!canVote(event->getPeerSP())) return; - NetworkString& data = event->data(); - PeerVote vote(data); + auto packet = event->getPacket(); + PeerVote vote(packet.vote); Log::debug("ServerLobby", "Vote from client: host %d, track %s, laps %d, reverse %d.", event->getPeer()->getHostId(), vote.m_track_name.c_str(), @@ -3081,19 +3001,16 @@ void ServerLobby::handlePlayerVote(Event* event) vote.m_player_name = event->getPeer()->getMainProfile()->getDecoratedName(m_name_decorator); // Now inform all clients about the vote - NetworkString other = NetworkString(PROTOCOL_LOBBY_ROOM); - other.setSynchronous(true); - other.addUInt8(LE_VOTE); - other.addUInt32(event->getPeer()->getHostId()); - vote.encode(&other); - Comm::sendMessageToPeers(&other); + VotePacket vote_packet; + vote_packet.host_id = event->getPeer()->getHostId(); + vote_packet.vote = vote.encode(); + Comm::sendPacketToPeers(vote_packet); } // handlePlayerVote // ---------------------------------------------------------------------------- /** Select the track to be used based on all votes being received. * \param winner_vote The PeerVote that was picked. - * \param winner_peer_id The host id of winner (unchanged if no vote). * \return True if race can go on, otherwise wait. */ bool ServerLobby::handleAllVotes(PeerVote* winner_vote) @@ -3237,9 +3154,24 @@ bool ServerLobby::decryptConnectionRequest(std::shared_ptr peer, if (crypto->decryptConnectionRequest(data)) { peer->setCrypto(std::move(crypto)); + + RestConnectionRequestPacket packet; + NetworkString* ns = new NetworkString(); + ns->operator+=(data); + try + { + packet.fromNetworkString(ns); + delete ns; + } + catch (...) + { + return false; + } + Optional opt; + opt = packet; Log::info("ServerLobby", "%s validated", StringUtils::wideToUtf8(online_name).c_str()); - handleUnencryptedConnection(peer, data, online_id, + handleUnencryptedConnection(peer, opt, online_id, online_name, true/*is_pending_connection*/, country_code); return true; } @@ -3341,14 +3273,14 @@ void ServerLobby::configPeersStartTime() // (due to packet loss), the start time will still ahead of current time uint64_t start_time = STKHost::get()->getNetworkTimer() + (uint64_t)2500; powerup_manager->setRandomSeed(start_time); - NetworkString* ns = getNetworkString(10); - ns->setSynchronous(true); - ns->addUInt8(LE_START_RACE).addUInt64(start_time); - const uint8_t cc = (uint8_t)Track::getCurrentTrack()->getCheckManager()->getCheckStructureCount(); - ns->addUInt8(cc); - *ns += *m_items_complete_state; + + StartGamePacket packet; + packet.start_time = start_time; + packet.check_count = (uint8_t)Track::getCurrentTrack()->getCheckManager()->getCheckStructureCount(); + packet.nim_complete_state = m_nim_complete_state; // was operator += + Comm::sendPacketToPeers(packet); + m_client_starting_time = start_time; - Comm::sendMessageToPeers(ns, PRM_RELIABLE); const unsigned jitter_tolerance = getSettings()->getJitterTolerance(); Log::info("ServerLobby", "Max ping from peers: %d, jitter tolerance: %d", @@ -3357,7 +3289,6 @@ void ServerLobby::configPeersStartTime() m_server_delay = (uint64_t)(max_ping / 2) + (uint64_t)jitter_tolerance; start_time += m_server_delay; m_server_started_at = start_time; - delete ns; m_state = WAIT_FOR_RACE_STARTED; World::getWorld()->setPhase(WorldStatus::SERVER_READY_PHASE); @@ -3419,12 +3350,8 @@ void ServerLobby::resetServer() addWaitingPlayersToGame(); resetPeersReady(); updatePlayerList(true/*update_when_reset_server*/); - NetworkString* server_info = getNetworkString(); - server_info->setSynchronous(true); - server_info->addUInt8(LE_SERVER_INFO); - m_game_setup->addServerInfo(server_info); - Comm::sendMessageToPeersInServer(server_info); - delete server_info; + + Comm::sendPacketToPeersInServer(m_game_setup->addServerInfo()); for (auto p : m_peers_ready) { @@ -3682,14 +3609,12 @@ void ServerLobby::handleServerConfiguration(std::shared_ptr peer, if (getAssetManager()->checkIfNoCommonMaps(assets)) { - NetworkString *message = getNetworkString(2); - message->setSynchronous(true); - message->addUInt8(LE_CONNECTION_REFUSED) - .addUInt8(RR_INCOMPATIBLE_DATA); + ConnectionRefusedPacket packet; + packet.reason = RR_INCOMPATIBLE_DATA; + peer->sendPacket(packet, PRM_RELIABLE); + peer->cleanPlayerProfiles(); - peer->sendPacket(message, PRM_RELIABLE); peer->reset(); - delete message; Log::verbose("ServerLobby", "Player has incompatible tracks for new game mode."); } @@ -3719,12 +3644,7 @@ void ServerLobby::handleServerConfiguration(std::shared_ptr peer, } } - NetworkString* server_info = getNetworkString(); - server_info->setSynchronous(true); - server_info->addUInt8(LE_SERVER_INFO); - m_game_setup->addServerInfo(server_info); - Comm::sendMessageToPeers(server_info); - delete server_info; + sendServerInfoToEveryone(); updatePlayerList(); @@ -3733,7 +3653,7 @@ void ServerLobby::handleServerConfiguration(std::shared_ptr peer, RaceManager::get()->getMinorMode() != RaceManager::MINOR_MODE_TIME_TRIAL) { getKartElimination()->disable(); - Comm::sendStringToAllPeers("Gnu Elimination is disabled because of non-racing mode"); + Comm::sendStringToPeers("Gnu Elimination is disabled because of non-racing mode"); } } // handleServerConfiguration //----------------------------------------------------------------------------- @@ -3762,10 +3682,10 @@ void ServerLobby::handleServerConfiguration(Event* event) bool new_soccer_goal_target = getSettings()->isSoccerGoalTargetInConfig(); if (event != NULL) { - NetworkString& data = event->data(); - new_difficulty = data.getUInt8(); - new_game_mode = data.getUInt8(); - new_soccer_goal_target = data.getUInt8() == 1; + auto packet = event->getPacket(); + new_difficulty = packet.difficulty; + new_game_mode = packet.game_mode; + new_soccer_goal_target = packet.soccer_goal_target; } handleServerConfiguration( (event ? event->getPeerSP() : std::shared_ptr()), @@ -3785,21 +3705,24 @@ void ServerLobby::handleServerConfiguration(Event* event) */ void ServerLobby::changeHandicap(Event* event) { - NetworkString& data = event->data(); + auto packet = event->getPacket(); + if (m_state.load() != WAITING_FOR_START_GAME && !event->getPeer()->isWaitingForGame()) { Log::warn("ServerLobby", "Set handicap at wrong time."); return; } - uint8_t local_id = data.getUInt8(); + + uint8_t local_id = packet.local_id; + uint8_t handicap_id = packet.handicap; auto& player = event->getPeer()->getPlayerProfiles().at(local_id); - uint8_t handicap_id = data.getUInt8(); if (handicap_id >= HANDICAP_COUNT) { Log::warn("ServerLobby", "Wrong handicap %d.", handicap_id); return; } + HandicapLevel h = (HandicapLevel)handicap_id; player->setHandicap(h); updatePlayerList(); @@ -3935,14 +3858,13 @@ void ServerLobby::addLiveJoinPlaceholder( } // addLiveJoinPlaceholder //----------------------------------------------------------------------------- -void ServerLobby::setPlayerKarts(const NetworkString& ns, std::shared_ptr peer) const +void ServerLobby::setPlayerKarts(const PlayerKartsPacket& packet, std::shared_ptr peer) const { - unsigned player_count = ns.getUInt8(); + unsigned player_count = packet.players_count; player_count = std::min(player_count, (unsigned)peer->getPlayerProfiles().size()); for (unsigned i = 0; i < player_count; i++) { - std::string kart; - ns.decodeString(&kart); + std::string kart = packet.karts[i]; std::string username = StringUtils::wideToUtf8( peer->getPlayerProfiles()[i]->getName()); if (getKartElimination()->isEliminated(username)) @@ -3963,12 +3885,13 @@ void ServerLobby::setPlayerKarts(const NetworkString& ns, std::shared_ptrgetPlayerProfiles()[i]->setKartName( getAssetManager()->getKartForBadKartChoice(peer, name, current_kart)); } + /* packet.kart_data should be a pointer later*/ if (peer->getClientCapabilities().find("real_addon_karts") == - peer->getClientCapabilities().end() || ns.size() == 0) + peer->getClientCapabilities().end() || packet.kart_data.empty()) return; for (unsigned i = 0; i < player_count; i++) { - KartData kart_data(ns); + KartData kart_data(packet.kart_data[i]); std::string type = kart_data.m_kart_type; auto& player = peer->getPlayerProfiles()[i]; const std::string& kart_id = player->getKartName(); @@ -3987,8 +3910,8 @@ void ServerLobby::handleKartInfo(Event* event) return; std::shared_ptr peer = event->getPeerSP(); - const NetworkString& data = event->data(); - uint8_t kart_id = data.getUInt8(); + auto request_packet = event->getPacket(); + uint8_t kart_id = request_packet.kart_id; if (kart_id > RaceManager::get()->getNumPlayers()) return; @@ -3997,19 +3920,23 @@ void ServerLobby::handleKartInfo(Event* event) const RemoteKartInfo& rki = RaceManager::get()->getKartInfo(kart_id); - NetworkString* ns = getNetworkString(1); - ns->setSynchronous(true); - ns->addUInt8(LE_KART_INFO).addUInt32(live_join_util_ticks) - .addUInt8(kart_id) .encodeString(rki.getPlayerName()) - .addUInt32(rki.getHostId()).addFloat(rki.getDefaultKartColor()) - .addUInt32(rki.getOnlineId()).addUInt8(rki.getHandicap()) - .addUInt8((uint8_t)rki.getLocalPlayerId()) - .encodeString(rki.getKartName()).encodeString(rki.getCountryCode()); + KartInfoPacket packet; + packet.live_join_util_ticks = live_join_util_ticks; + packet.kart_id = kart_id; + packet.player_name = rki.getPlayerName(); + packet.host_id = rki.getHostId(); + packet.default_kart_color = rki.getDefaultKartColor(); + packet.online_id = rki.getOnlineId(); + packet.handicap = rki.getHandicap(); + packet.local_player_id = (uint8_t)rki.getLocalPlayerId(); + packet.kart_name = rki.getKartName(); + packet.country_code = rki.getCountryCode(); + if (peer->getClientCapabilities().find("real_addon_karts") != peer->getClientCapabilities().end()) - rki.getKartData().encode(ns); - peer->sendPacket(ns, PRM_RELIABLE); - delete ns; + packet.kart_data = rki.getKartData().encode(); + + peer->sendPacket(packet); FreeForAll* ffa_world = dynamic_cast(World::getWorld()); @@ -4054,12 +3981,11 @@ void ServerLobby::clientInGameWantsToBackLobby(Event* event) } else exitGameState(); - NetworkString* back_to_lobby = getNetworkString(2); - back_to_lobby->setSynchronous(true); - back_to_lobby->addUInt8(LE_BACK_LOBBY) - .addUInt8(BLR_SERVER_ONWER_QUITED_THE_GAME); - Comm::sendMessageToPeersInServer(back_to_lobby, PRM_RELIABLE); - delete back_to_lobby; + + BackLobbyPacket packet; + packet.reason = BLR_SERVER_OWNER_QUIT_THE_GAME; + Comm::sendPacketToPeersInServer(packet); + m_rs_state.store(RS_ASYNC_RESET); return; } @@ -4093,18 +4019,13 @@ void ServerLobby::clientInGameWantsToBackLobby(Event* event) peer->setWaitingForGame(true); peer->setSpectator(false); - NetworkString* reset = getNetworkString(2); - reset->setSynchronous(true); - reset->addUInt8(LE_BACK_LOBBY).addUInt8(BLR_NONE); - peer->sendPacket(reset, PRM_RELIABLE); - delete reset; + BackLobbyPacket packet; + packet.reason = BLR_NONE; + peer->sendPacket(packet, PRM_RELIABLE); + updatePlayerList(); - NetworkString* server_info = getNetworkString(); - server_info->setSynchronous(true); - server_info->addUInt8(LE_SERVER_INFO); - m_game_setup->addServerInfo(server_info); - peer->sendPacket(server_info, PRM_RELIABLE); - delete server_info; + + peer->sendPacket(m_game_setup->addServerInfo()); peer->updateLastActivity(); } // clientInGameWantsToBackLobby @@ -4127,12 +4048,10 @@ void ServerLobby::clientSelectingAssetsWantsToBackLobby(Event* event) if (m_process_type == PT_CHILD && event->getPeer()->getHostId() == m_client_server_host_id.load()) { - NetworkString* back_to_lobby = getNetworkString(2); - back_to_lobby->setSynchronous(true); - back_to_lobby->addUInt8(LE_BACK_LOBBY) - .addUInt8(BLR_SERVER_ONWER_QUITED_THE_GAME); - Comm::sendMessageToPeersInServer(back_to_lobby, PRM_RELIABLE); - delete back_to_lobby; + BackLobbyPacket packet; + packet.reason = BLR_SERVER_OWNER_QUIT_THE_GAME; + Comm::sendPacketToPeersInServer(packet); + resetVotingTime(); resetServer(); m_rs_state.store(RS_NONE); @@ -4143,18 +4062,13 @@ void ServerLobby::clientSelectingAssetsWantsToBackLobby(Event* event) peer->setWaitingForGame(true); peer->setSpectator(false); - NetworkString* reset = getNetworkString(2); - reset->setSynchronous(true); - reset->addUInt8(LE_BACK_LOBBY).addUInt8(BLR_NONE); - peer->sendPacket(reset, PRM_RELIABLE); - delete reset; + BackLobbyPacket packet; + packet.reason = BLR_NONE; + peer->sendPacket(packet); + updatePlayerList(); - NetworkString* server_info = getNetworkString(); - server_info->setSynchronous(true); - server_info->addUInt8(LE_SERVER_INFO); - m_game_setup->addServerInfo(server_info); - peer->sendPacket(server_info, PRM_RELIABLE); - delete server_info; + + peer->sendPacket(m_game_setup->addServerInfo()); peer->updateLastActivity(); } // clientSelectingAssetsWantsToBackLobby @@ -4162,9 +4076,8 @@ void ServerLobby::clientSelectingAssetsWantsToBackLobby(Event* event) //----------------------------------------------------------------------------- void ServerLobby::saveInitialItems(std::shared_ptr nim) { - m_items_complete_state->getBuffer().clear(); - m_items_complete_state->reset(); - nim->saveCompleteState(m_items_complete_state); + // there was m_nim_complete_state->getBuffer().clear(); here + m_nim_complete_state = nim->saveCompleteState(); } // saveInitialItems //----------------------------------------------------------------------------- @@ -4249,16 +4162,14 @@ void ServerLobby::writeOwnReport(std::shared_ptr reporter, std::shared_ reporting, reporting_npp, info_w); if (written) { - NetworkString* success = getNetworkString(); - success->setSynchronous(true); + ReportSuccessPacket packet; + packet.success = 1; if (reporter == reporting) - success->addUInt8(LE_REPORT_PLAYER).addUInt8(1) - .encodeString(m_game_setup->getServerNameUtf8()); + packet.reported_name = StringUtils::utf8ToWide(m_game_setup->getServerNameUtf8()); else - success->addUInt8(LE_REPORT_PLAYER).addUInt8(1) - .encodeString(reporting_npp->getName()); - reporter->sendPacket(success, PRM_RELIABLE); - delete success; + packet.reported_name = reporting_npp->getName(); + + reporter->sendPacket(packet); } #endif } // writeOwnReport @@ -4462,12 +4373,7 @@ bool ServerLobby::playerReportsTableExists() const void ServerLobby::sendServerInfoToEveryone() const { - NetworkString* server_info = getNetworkString(); - server_info->setSynchronous(true); - server_info->addUInt8(LE_SERVER_INFO); - m_game_setup->addServerInfo(server_info); - Comm::sendMessageToPeers(server_info); - delete server_info; + Comm::sendPacketToPeers(m_game_setup->addServerInfo()); } // sendServerInfoToEveryone //----------------------------------------------------------------------------- diff --git a/src/network/protocols/server_lobby.hpp b/src/network/protocols/server_lobby.hpp index 44728e6d4de..12f01c7786b 100644 --- a/src/network/protocols/server_lobby.hpp +++ b/src/network/protocols/server_lobby.hpp @@ -53,7 +53,6 @@ class LobbySettings; class MapVoteHandler; class NetworkItemManager; class NetworkPlayerProfile; -class NetworkString; class Ranking; class SocketAddress; class STKPeer; @@ -149,10 +148,10 @@ class ServerLobby : public LobbyProtocol, public LobbyContextUser std::map m_pending_peer_connection; /* Saved the last game result */ - NetworkString* m_result_ns; + RaceFinishedPacket m_result_packet; /* Used to make sure clients are having same item list at start */ - BareNetworkString* m_items_complete_state; + NimCompleteStatePacket m_nim_complete_state; std::atomic m_server_id_online; @@ -236,7 +235,7 @@ class ServerLobby : public LobbyProtocol, public LobbyContextUser } void handlePendingConnection(); void handleUnencryptedConnection(std::shared_ptr peer, - BareNetworkString& data, + const Optional& opt, uint32_t online_id, const irr::core::stringw& online_name, bool is_pending_connection, @@ -251,7 +250,7 @@ class ServerLobby : public LobbyProtocol, public LobbyContextUser bool handleAllVotes(PeerVote* winner); void getRankingForPlayer(std::shared_ptr p); void submitRankingsToAddons(); - void computeNewRankings(NetworkString* ns); + PointChangesPacket computeNewRankings(); void checkRaceFinished(); void configPeersStartTime(); void resetServer(); @@ -260,10 +259,10 @@ class ServerLobby : public LobbyProtocol, public LobbyContextUser void handlePlayerDisconnection() const; void addLiveJoinPlaceholder( std::vector >& players) const; - NetworkString* getLoadWorldMessage( + LoadWorldPacket getLoadWorldMessage( std::vector >& players, bool live_join) const; - void setPlayerKarts(const NetworkString& ns, std::shared_ptr peer) const; + void setPlayerKarts(const PlayerKartsPacket& packet, std::shared_ptr peer) const; bool handleAssets(Event* event); bool handleAssetsAndAddonScores(std::shared_ptr peer, @@ -336,7 +335,7 @@ class ServerLobby : public LobbyProtocol, public LobbyContextUser // TODO: When using different decorators for everyone, you would need // a structure to store "player profile" placeholders in a string, so that - // you can apply decorators at the very last moment inside sendStringToAllPeers + // you can apply decorators at the very last moment inside sendStringToPeers // and similar functions. std::string encodeProfileNameForPeer( std::shared_ptr npp, @@ -359,7 +358,6 @@ class ServerLobby : public LobbyProtocol, public LobbyContextUser const std::string& type) const; bool playerReportsTableExists() const; - void sendServerInfoToEveryone() const; bool isWorldPicked() const { return m_state.load() >= LOAD_WORLD; } diff --git a/src/network/rewind_info.cpp b/src/network/rewind_info.cpp index a53cb8c7ebd..a63e2e34c2a 100644 --- a/src/network/rewind_info.cpp +++ b/src/network/rewind_info.cpp @@ -47,26 +47,23 @@ void RewindInfo::setTicks(int ticks) } // setTicks // ============================================================================ -RewindInfoState::RewindInfoState(int ticks, int start_offset, - std::vector& rewinder_using, - std::vector& buffer) +RewindInfoState::RewindInfoState(int ticks, + std::vector rewinder_using, + std::vector the_rest) : RewindInfo(ticks, true/*is_confirmed*/) { - std::swap(m_rewinder_using, rewinder_using); - m_start_offset = start_offset; - m_buffer = new BareNetworkString(); - std::swap(m_buffer->getBuffer(), buffer); + m_rewinder_using = std::move(rewinder_using); + m_buffer = std::move(the_rest); } // RewindInfoState // ------------------------------------------------------------------------ /** Constructor used only in unit testing (without list of rewinder using). */ -RewindInfoState::RewindInfoState(int ticks, BareNetworkString* buffer, +RewindInfoState::RewindInfoState(int ticks, std::vector the_rest, bool is_confirmed) : RewindInfo(ticks, is_confirmed) { - m_start_offset = 0; - m_buffer = buffer; + m_buffer = std::move(the_rest); } // RewindInfoState // ------------------------------------------------------------------------ @@ -76,14 +73,12 @@ RewindInfoState::RewindInfoState(int ticks, BareNetworkString* buffer, */ void RewindInfoState::restore() { - m_buffer->reset(); - m_buffer->skip(m_start_offset); - for (const std::string& name : m_rewinder_using) + size_t idx = 0; + for (const ProjectilePacket& name : m_rewinder_using) { - const uint16_t data_size = m_buffer->getUInt16(); - const unsigned current_offset_now = m_buffer->getCurrentOffset(); - std::shared_ptr r = - RewindManager::get()->getRewinder(name); + TheRestOfBgsPacket& subpacket = m_buffer[idx++]; + const uint16_t data_size = subpacket.data_size; + std::shared_ptr r = RewindManager::get()->getRewinder(name); if (!r) { @@ -95,42 +90,31 @@ void RewindInfoState::restore() { if (!RewindManager::get()->hasMissingRewinder(name)) { - Log::error("RewindInfoState", "Missing rewinder %s", - name.c_str()); + Log::error("RewindInfoState", "Missing rewinder (%d, %d, %d)", + name.rewinder_type, name.kart_id, name.created_ticks); RewindManager::get()->addMissingRewinder(name); } - m_buffer->skip(data_size); continue; } try { - r->restoreState(m_buffer, data_size); + r->restoreState(subpacket.something); } catch (std::exception& e) { Log::error("RewindInfoState", "Restore state error: %s", e.what()); - m_buffer->reset(); - m_buffer->skip(current_offset_now + data_size); continue; } - - if (m_buffer->getCurrentOffset() - current_offset_now != data_size) - { - Log::error("RewindInfoState", "Wrong size read when restore " - "state, incompatible binary?"); - m_buffer->reset(); - m_buffer->skip(current_offset_now + data_size); - } } // for all rewinder } // restore // ============================================================================ RewindInfoEvent::RewindInfoEvent(int ticks, EventRewinder *event_rewinder, - BareNetworkString *buffer, bool is_confirmed) + ControllerActionPacket packet, bool is_confirmed) : RewindInfo(ticks, is_confirmed) { m_event_rewinder = event_rewinder; - m_buffer = buffer; + m_buffer = std::move(packet); } // RewindInfoEvent diff --git a/src/network/rewind_info.hpp b/src/network/rewind_info.hpp index b7376d8d567..c4665816e17 100644 --- a/src/network/rewind_info.hpp +++ b/src/network/rewind_info.hpp @@ -21,6 +21,7 @@ #include "network/event_rewinder.hpp" #include "network/network_string.hpp" +#include "network/packet_types.hpp" #include "utils/cpp2011.hpp" #include "utils/leak_check.hpp" #include "utils/ptr_vector.hpp" @@ -92,27 +93,27 @@ class RewindInfo class RewindInfoState: public RewindInfo { private: - std::vector m_rewinder_using; + std::vector m_rewinder_using; int m_start_offset; - /** Pointer to the buffer which stores all states. */ - BareNetworkString *m_buffer; + std::vector m_buffer; public: // ------------------------------------------------------------------------ - RewindInfoState(int ticks, int start_offset, - std::vector& rewinder_using, - std::vector& buffer); + RewindInfoState(int ticks, + std::vector rewinder_using, + std::vector the_rest); // ------------------------------------------------------------------------ - RewindInfoState(int ticks, BareNetworkString *buffer, bool is_confirmed); + RewindInfoState(int ticks, std::vector the_rest, + bool is_confirmed); // ------------------------------------------------------------------------ - virtual ~RewindInfoState() { delete m_buffer; } + virtual ~RewindInfoState() { } // ------------------------------------------------------------------------ virtual void restore(); // ------------------------------------------------------------------------ /** Returns a pointer to the state buffer. */ - BareNetworkString *getBuffer() const { return m_buffer; } + std::vector getBuffer() const { return m_buffer; } // ------------------------------------------------------------------------ virtual bool isState() const { return true; } // ------------------------------------------------------------------------ @@ -139,13 +140,12 @@ class RewindInfoEvent : public RewindInfo EventRewinder *m_event_rewinder; /** Buffer with the event data. */ - BareNetworkString *m_buffer; + ControllerActionPacket m_buffer; public: RewindInfoEvent(int ticks, EventRewinder *event_rewinder, - BareNetworkString *buffer, bool is_confirmed); + ControllerActionPacket packet, bool is_confirmed); virtual ~RewindInfoEvent() { - delete m_buffer; } // ~RewindInfoEvent // ------------------------------------------------------------------------ @@ -158,7 +158,6 @@ class RewindInfoEvent : public RewindInfo * It calls undoEvent in the rewinder. */ virtual void undo() { - m_buffer->reset(); m_event_rewinder->undo(m_buffer); } // undo // ------------------------------------------------------------------------ @@ -167,13 +166,11 @@ class RewindInfoEvent : public RewindInfo */ virtual void replay() { - // Make sure to reset the buffer so we read from the beginning - m_buffer->reset(); m_event_rewinder->rewind(m_buffer); } // rewind // ------------------------------------------------------------------------ /** Returns the buffer with the event information in it. */ - BareNetworkString *getBuffer() { return m_buffer; } + ControllerActionPacket getBuffer() { return m_buffer; } }; // class RewindIndoEvent diff --git a/src/network/rewind_manager.cpp b/src/network/rewind_manager.cpp index e6afe109976..a3d1712278d 100644 --- a/src/network/rewind_manager.cpp +++ b/src/network/rewind_manager.cpp @@ -105,19 +105,18 @@ void RewindManager::reset() * \param buffer Pointer to the event data. */ void RewindManager::addEvent(EventRewinder *event_rewinder, - BareNetworkString *buffer, bool confirmed, + const ControllerActionPacket& packet, bool confirmed, int ticks) { if (m_is_rewinding) { - delete buffer; Log::error("RewindManager", "Adding event when rewinding"); return; } if (ticks < 0) ticks = World::getWorld()->getTicksSinceStart(); - m_rewind_queue.addLocalEvent(event_rewinder, buffer, confirmed, ticks); + m_rewind_queue.addLocalEvent(event_rewinder, packet, confirmed, ticks); } // addEvent // ---------------------------------------------------------------------------- @@ -129,9 +128,9 @@ void RewindManager::addEvent(EventRewinder *event_rewinder, * \param buffer Pointer to the event data. */ void RewindManager::addNetworkEvent(EventRewinder *event_rewinder, - BareNetworkString *buffer, int ticks) + ControllerActionPacket packet, int ticks) { - m_rewind_queue.addNetworkEvent(event_rewinder, buffer, ticks); + m_rewind_queue.addNetworkEvent(event_rewinder, std::move(packet), ticks); } // addNetworkEvent // ---------------------------------------------------------------------------- diff --git a/src/network/rewind_manager.hpp b/src/network/rewind_manager.hpp index ee171260e0f..7c02fca14ae 100644 --- a/src/network/rewind_manager.hpp +++ b/src/network/rewind_manager.hpp @@ -20,6 +20,7 @@ #define HEADER_REWIND_MANAGER_HPP #include "network/rewind_queue.hpp" +#include "network/packet_types.hpp" #include "utils/stk_process.hpp" #include @@ -94,7 +95,7 @@ class RewindManager std::map > > m_local_state; /** A list of all objects that can be rewound. */ - std::map > m_all_rewinder; + std::map > m_all_rewinder; /** The queue that stores all rewind infos. */ RewindQueue m_rewind_queue; @@ -117,7 +118,7 @@ class RewindManager bool m_schedule_reset_network_body; - std::set m_missing_rewinders; + std::set m_missing_rewinders; RewindManager(); ~RewindManager(); @@ -170,16 +171,16 @@ class RewindManager void update(int ticks); void rewindTo(int target_ticks, int ticks_now, bool fast_forward); void playEventsTill(int world_ticks, bool fast_forward); - void addEvent(EventRewinder *event_rewinder, BareNetworkString *buffer, + void addEvent(EventRewinder *event_rewinder, const ControllerActionPacket& packet, bool confirmed, int ticks = -1); void addNetworkEvent(EventRewinder *event_rewinder, - BareNetworkString *buffer, int ticks); + ControllerActionPacket packet, int ticks); void addNetworkState(BareNetworkString *buffer, int ticks); void saveState(); // ------------------------------------------------------------------------ - std::shared_ptr getRewinder(const std::string& name) + std::shared_ptr getRewinder(const ProjectilePacket& packet) { - auto it = m_all_rewinder.find(name); + auto it = m_all_rewinder.find(packet); if (it != m_all_rewinder.end()) { if (auto r = it->second.lock()) @@ -223,11 +224,11 @@ class RewindManager // ------------------------------------------------------------------------ void handleResetSmoothNetworkBody(); // ------------------------------------------------------------------------ - void addMissingRewinder(const std::string& name) - { m_missing_rewinders.insert(name); } + void addMissingRewinder(const ProjectilePacket& packet) + { m_missing_rewinders.insert(packet); } // ------------------------------------------------------------------------ - bool hasMissingRewinder(const std::string& name) const - { return m_missing_rewinders.find(name) != m_missing_rewinders.end(); } + bool hasMissingRewinder(const ProjectilePacket& packet) const + { return m_missing_rewinders.find(packet) != m_missing_rewinders.end(); } }; // RewindManager diff --git a/src/network/rewind_queue.cpp b/src/network/rewind_queue.cpp index d8eeb3f9921..73df6044250 100644 --- a/src/network/rewind_queue.cpp +++ b/src/network/rewind_queue.cpp @@ -120,11 +120,11 @@ void RewindQueue::insertRewindInfo(RewindInfo *ri) * \param ticks Time at which the event happened. */ void RewindQueue::addLocalEvent(EventRewinder *event_rewinder, - BareNetworkString *buffer, bool confirmed, - int ticks ) + const ControllerActionPacket& packet, bool confirmed, + int ticks) { RewindInfo *ri = new RewindInfoEvent(ticks, event_rewinder, - buffer, confirmed); + packet, confirmed); insertRewindInfo(ri); } // addLocalEvent @@ -160,10 +160,10 @@ void RewindQueue::addLocalState(BareNetworkString *buffer, * \param ticks Time at which the event happened. */ void RewindQueue::addNetworkEvent(EventRewinder *event_rewinder, - BareNetworkString *buffer, int ticks) + ControllerActionPacket packet, int ticks) { RewindInfo *ri = new RewindInfoEvent(ticks, event_rewinder, - buffer, /*confirmed*/true); + std::move(packet), /*confirmed*/true); m_network_events.lock(); m_network_events.getData().push_back(ri); diff --git a/src/network/rewind_queue.hpp b/src/network/rewind_queue.hpp index 4daadf4d4db..b1d8aa1128c 100644 --- a/src/network/rewind_queue.hpp +++ b/src/network/rewind_queue.hpp @@ -64,11 +64,11 @@ class RewindQueue RewindQueue(); ~RewindQueue(); void reset(); - void addLocalEvent(EventRewinder *event_rewinder, BareNetworkString *buffer, + void addLocalEvent(EventRewinder *event_rewinder, const ControllerActionPacket& packet, bool confirmed, int ticks); void addLocalState(BareNetworkString *buffer, bool confirmed, int ticks); void addNetworkEvent(EventRewinder *event_rewinder, - BareNetworkString *buffer, int ticks); + ControllerActionPacket packet, int ticks); void addNetworkState(BareNetworkString *buffer, int ticks); void addNetworkRewindInfo(RewindInfo* ri) { diff --git a/src/network/rewinder.hpp b/src/network/rewinder.hpp index c47a960b78b..2e4a895d0fd 100644 --- a/src/network/rewinder.hpp +++ b/src/network/rewinder.hpp @@ -75,7 +75,8 @@ class Rewinder : public std::enable_shared_from_this * \param[out] ru The unique identity of rewinder writing to. * \return The address of the memory buffer with the state. */ - virtual BareNetworkString* saveState(std::vector* ru) = 0; + // kimden: nonvirtual: temporary non-0 + virtual BareNetworkString* saveStateDeprecated(std::vector* ru) {}; /** Called when an event needs to be undone. This is called while going * backwards for rewinding - all stored events will get an 'undo' call. @@ -91,7 +92,8 @@ class Rewinder : public std::enable_shared_from_this * rewind, i.e. when going forward in time again, and only for confirmed * states. */ - virtual void restoreState(BareNetworkString *buffer, int count) = 0; + // kimden: nonvirtual: temporary non-0 + virtual void restoreStateDeprecated(BareNetworkString *buffer, int count) {}; /** Undo the effects of the given state, but do not rewind to that * state (which is done by rewindTo). This is called while going diff --git a/src/network/stk_host.cpp b/src/network/stk_host.cpp index c378114da14..cb0c670a6bb 100644 --- a/src/network/stk_host.cpp +++ b/src/network/stk_host.cpp @@ -922,10 +922,9 @@ void STKHost::mainLoop(ProcessType pt) p.second->getAddress().toString().c_str(), player_name.c_str(), ap, max_ping); p.second->setWarnedForHighPing(true); - NetworkString msg(PROTOCOL_LOBBY_ROOM); - msg.setSynchronous(true); - msg.addUInt8(LobbyEvent::LE_BAD_CONNECTION); - p.second->sendPacket(&msg, PRM_RELIABLE); + + BadConnectionPacket packet; + p.second->sendPacket(packet); } } } @@ -1338,30 +1337,30 @@ std::shared_ptr STKHost::getServerPeerForClient() const * \param data Data to sent. * \param reliable If the data should be sent reliable or now. */ -void STKHost::sendPacketToAllPeersInServer(NetworkString *data, PacketReliabilityMode reliable) +void STKHost::sendNetstringToPeersInServer(NetworkString *data, PacketReliabilityMode reliable) { std::lock_guard lock(m_peers_mutex); for (auto p : m_peers) { if (p.second->isValidated()) - p.second->sendPacket(data, reliable); + p.second->sendNetstring(data, reliable); } -} // sendPacketToAllPeersInServer +} // sendNetstringToPeersInServer //----------------------------------------------------------------------------- /** Sends data to all validated peers currently in game * \param data Data to sent. * \param reliable If the data should be sent reliable or now. */ -void STKHost::sendPacketToAllPeers(NetworkString *data, PacketReliabilityMode reliable) +void STKHost::sendNetstringToPeers(NetworkString *data, PacketReliabilityMode reliable) { std::lock_guard lock(m_peers_mutex); for (auto p : m_peers) { if (p.second->isValidated() && !p.second->isWaitingForGame()) - p.second->sendPacket(data, reliable); + p.second->sendNetstring(data, reliable); } -} // sendPacketToAllPeers +} // sendNetstringToPeers //----------------------------------------------------------------------------- /** Sends data to all validated peers except the specified currently in game @@ -1369,7 +1368,7 @@ void STKHost::sendPacketToAllPeers(NetworkString *data, PacketReliabilityMode re * \param data Data to sent. * \param reliable If the data should be sent reliable or now. */ -void STKHost::sendPacketExcept(std::shared_ptr peer, NetworkString *data, +void STKHost::sendNetstringExcept(std::shared_ptr peer, NetworkString *data, PacketReliabilityMode reliable) { std::lock_guard lock(m_peers_mutex); @@ -1379,10 +1378,10 @@ void STKHost::sendPacketExcept(std::shared_ptr peer, NetworkString *dat if (!stk_peer->isSamePeer(peer.get()) && p.second->isValidated() && !p.second->isWaitingForGame()) { - stk_peer->sendPacket(data, reliable); + stk_peer->sendNetstring(data, reliable); } } -} // sendPacketExcept +} // sendNetstringExcept //----------------------------------------------------------------------------- /** Sends data to peers with custom rule @@ -1390,7 +1389,7 @@ void STKHost::sendPacketExcept(std::shared_ptr peer, NetworkString *dat * \param data Data to sent. * \param reliable If the data should be sent reliable or now. */ -void STKHost::sendPacketToAllPeersWith(std::function)> predicate, +void STKHost::sendNetstringToPeersWith(std::function)> predicate, NetworkString* data, PacketReliabilityMode reliable) { std::lock_guard lock(m_peers_mutex); @@ -1400,9 +1399,9 @@ void STKHost::sendPacketToAllPeersWith(std::functionisValidated()) continue; if (predicate(stk_peer)) - stk_peer->sendPacket(data, reliable); + stk_peer->sendNetstring(data, reliable); } -} // sendPacketToAllPeersWith +} // sendPacketToPeersWith //----------------------------------------------------------------------------- /** Sends a message from a client to the server. */ @@ -1412,7 +1411,7 @@ void STKHost::sendToServer(NetworkString *data, PacketReliabilityMode reliable) if (m_peers.empty()) return; assert(NetworkConfig::get()->isClient()); - m_peers.begin()->second->sendPacket(data, reliable); + m_peers.begin()->second->sendNetstring(data, reliable); } // sendToServer //----------------------------------------------------------------------------- @@ -1671,3 +1670,67 @@ uint16_t STKHost::getPrivatePort() const { return m_network->getPort(); } // getPrivatePort +// ---------------------------------------------------------------------------- + +void STKHost::sendPacketPtrToPeersInServer(std::shared_ptr packet, PacketReliabilityMode reliable) +{ + std::lock_guard lock(m_peers_mutex); + for (auto p : m_peers) + { + if (p.second->isValidated()) + p.second->sendPacketPtr(packet, reliable); + } +} // sendPacketToPeersInServer +//----------------------------------------------------------------------------- + +void STKHost::sendPacketPtrToPeers(std::shared_ptr packet, PacketReliabilityMode reliable) +{ + std::lock_guard lock(m_peers_mutex); + for (auto p : m_peers) + { + if (p.second->isValidated() && !p.second->isWaitingForGame()) + p.second->sendPacketPtr(packet, reliable); + } +} // sendPacketToPeers +//----------------------------------------------------------------------------- + +void STKHost::sendPacketPtrExcept(std::shared_ptr peer, std::shared_ptr packet, + PacketReliabilityMode reliable) +{ + std::lock_guard lock(m_peers_mutex); + for (const auto& p : m_peers) + { + STKPeer* stk_peer = p.second.get(); + if (!stk_peer->isSamePeer(peer.get()) && p.second->isValidated() && + !p.second->isWaitingForGame()) + { + stk_peer->sendPacketPtr(packet, reliable); + } + } +} // sendPacketExcept +//----------------------------------------------------------------------------- + +void STKHost::sendPacketPtrToPeersWith(std::function)> predicate, + std::shared_ptr packet, PacketReliabilityMode reliable) +{ + std::lock_guard lock(m_peers_mutex); + for (auto p : m_peers) + { + std::shared_ptr stk_peer = p.second; + if (!stk_peer->isValidated()) + continue; + if (predicate(stk_peer)) + stk_peer->sendPacketPtr(packet, reliable); + } +} // sendPacketToPeersWith +//----------------------------------------------------------------------------- + +void STKHost::sendPacketPtrToServer(std::shared_ptr packet, PacketReliabilityMode reliable) +{ + std::lock_guard lock(m_peers_mutex); + if (m_peers.empty()) + return; + assert(NetworkConfig::get()->isClient()); + m_peers.begin()->second->sendPacketPtr(packet, reliable); +} // sendPacketToServer +//----------------------------------------------------------------------------- diff --git a/src/network/stk_host.hpp b/src/network/stk_host.hpp index 8191568533c..760076ed753 100644 --- a/src/network/stk_host.hpp +++ b/src/network/stk_host.hpp @@ -60,6 +60,7 @@ class ServerLobby; class ChildLoop; class SocketAddress; class STKPeer; +class Packet; using namespace irr; @@ -244,12 +245,12 @@ class STKHost //------------------------------------------------------------------------- void shutdown(); //------------------------------------------------------------------------- - void sendPacketToAllPeersInServer(NetworkString *data, + void sendNetstringToPeersInServer(NetworkString *data, PacketReliabilityMode reliable = PRM_RELIABLE); // ------------------------------------------------------------------------ - void sendPacketToAllPeers(NetworkString *data, PacketReliabilityMode reliable = PRM_RELIABLE); + void sendNetstringToPeers(NetworkString *data, PacketReliabilityMode reliable = PRM_RELIABLE); // ------------------------------------------------------------------------ - void sendPacketToAllPeersWith(std::function)> predicate, + void sendNetstringTolPeersWith(std::function)> predicate, NetworkString* data, PacketReliabilityMode reliable = PRM_RELIABLE); // ------------------------------------------------------------------------ /** Returns true if this client instance is allowed to control the server. @@ -271,7 +272,7 @@ class STKHost std::shared_ptr findPeerByName(const core::stringw& name) const; std::shared_ptr findPeerByWildcard(const core::stringw& name_pattern, std::string &name_found) const; // ------------------------------------------------------------------------ - void sendPacketExcept(std::shared_ptr peer, NetworkString *data, + void sendNetstringExcept(std::shared_ptr peer, NetworkString *data, PacketReliabilityMode reliable = PRM_RELIABLE); // ------------------------------------------------------------------------ void setupClient(int peer_count, int channel_limit, @@ -398,6 +399,25 @@ class STKHost static BareNetworkString getStunRequest(uint8_t* stun_tansaction_id); // ------------------------------------------------------------------------ ChildLoop* getChildLoop() const { return m_client_loop; } + // ------------------------------------------------------------------------ + + void sendPacketPtrToPeersInServer(std::shared_ptr packet, + PacketReliabilityMode reliable = PRM_RELIABLE); + + void sendPacketPtrToPeers(std::shared_ptr packet, + PacketReliabilityMode reliable = PRM_RELIABLE); + + void sendPacketPtrExcept(std::shared_ptr peer, + std::shared_ptr packet, + PacketReliabilityMode reliable = PRM_RELIABLE); + + void sendPacketPtrToPeersWith(std::function)> predicate, + std::shared_ptr packet, + PacketReliabilityMode reliable = PRM_RELIABLE); + + void sendPacketPtrToServer(std::shared_ptr packet, + PacketReliabilityMode reliable = PRM_RELIABLE); + //------------------------------------------------------------------------- }; // class STKHost #endif // STK_HOST_HPP diff --git a/src/network/stk_peer.cpp b/src/network/stk_peer.cpp index 4b1a978376c..eafbea14d72 100644 --- a/src/network/stk_peer.cpp +++ b/src/network/stk_peer.cpp @@ -99,12 +99,12 @@ void STKPeer::reset() } // reset //----------------------------------------------------------------------------- -/** Sends a packet to this host. +/** Sends a network string to this host. * \param data The data to send. * \param reliable If the data is sent reliable or not. * \param encrypted If the data is sent encrypted or not. */ -void STKPeer::sendPacket(NetworkString *data, PacketReliabilityMode reliable, PacketEncryptionMode encrypted) +void STKPeer::sendNetstring(NetworkString *data, PacketReliabilityMode reliable, PacketEncryptionMode encrypted) { if (m_disconnected.load()) return; @@ -135,7 +135,7 @@ void STKPeer::sendPacket(NetworkString *data, PacketReliabilityMode reliable, Pa encrypted ? EVENT_CHANNEL_NORMAL : EVENT_CHANNEL_UNENCRYPTED, ECT_SEND_PACKET, m_address); } -} // sendPacket +} // sendNetstring //----------------------------------------------------------------------------- /** Returns if the peer is connected or not. diff --git a/src/network/stk_peer.hpp b/src/network/stk_peer.hpp index ebed54e3d92..98a6c16af12 100644 --- a/src/network/stk_peer.hpp +++ b/src/network/stk_peer.hpp @@ -28,6 +28,8 @@ #include "utils/types.hpp" #include "utils/constants.hpp" +#include "network/network_string.hpp" + #include #include @@ -42,6 +44,7 @@ class Crypto; class NetworkPlayerProfile; class NetworkString; +class Packet; class STKHost; class SocketAddress; @@ -145,9 +148,52 @@ class STKPeer : public NoCopy // ------------------------------------------------------------------------ ~STKPeer(); // ------------------------------------------------------------------------ - void sendPacket(NetworkString *data, PacketReliabilityMode reliable = PRM_RELIABLE, + void sendNetstring(NetworkString *data, PacketReliabilityMode reliable = PRM_RELIABLE, PacketEncryptionMode encrypted = PEM_ENCRYPTED); // ------------------------------------------------------------------------ + + // std::is_base_of() + template + void sendPacket(const T& packet, PacketReliabilityMode reliable = PRM_RELIABLE, + PacketEncryptionMode encrypted = PEM_ENCRYPTED) + { + unsigned capacity = packet.expectedCapacity(); + NetworkString* ns = new NetworkString(); + if (capacity != 0) + ns = new NetworkString(ProtocolType::PROTOCOL_NONE, capacity); + else + ns = new NetworkString(); + + packet.toNetworkString(ns); + sendNetstring(ns, + (PacketReliabilityMode)packet.m_override_reliable.get_or((bool)reliable), + encrypted); + + delete ns; + } // sendPacket + //------------------------------------------------------------------------- + + void sendPacketPtr(std::shared_ptr packet, PacketReliabilityMode reliable = PRM_RELIABLE, + PacketEncryptionMode encrypted = PEM_ENCRYPTED) + { + unsigned capacity = packet->expectedCapacity(); + NetworkString* ns = new NetworkString(); + if (capacity != 0) + ns = new NetworkString(ProtocolType::PROTOCOL_NONE, capacity); + else + ns = new NetworkString(); + + packet->toNetworkString(ns); + sendNetstring(ns, + (PacketReliabilityMode)packet->m_override_reliable.get_or((bool)reliable), + encrypted); + + delete ns; + } // sendPacket + //------------------------------------------------------------------------- + // void sendPacket(Packet* packet, PacketReliabilityMode reliable = PRM_RELIABLE, + // PacketEncryptionMode encrypted = PEM_ENCRYPTED); + // ------------------------------------------------------------------------ void disconnect(); // ------------------------------------------------------------------------ void kick(); diff --git a/src/race/race_manager.cpp b/src/race/race_manager.cpp index e2a6e0d4748..de3f185efc5 100644 --- a/src/race/race_manager.cpp +++ b/src/race/race_manager.cpp @@ -1243,7 +1243,7 @@ void RaceManager::startWatchingReplay(const std::string &track_ident, } // startWatchingReplay //--------------------------------------------------------------------------------------------- -void RaceManager::configGrandPrixResultFromNetwork(NetworkString& ns) +void RaceManager::configGrandPrixResultFromNetwork(const GPScoresPacket& packet) { setMajorMode(MAJOR_MODE_GRAND_PRIX); class NetworkGrandPrixData : public GrandPrixData @@ -1261,15 +1261,13 @@ void RaceManager::configGrandPrixResultFromNetwork(NetworkString& ns) }; NetworkGrandPrixData ngpd; - unsigned int track_size = ns.getUInt8(); - unsigned int all_track_size = ns.getUInt8(); + unsigned int track_size = packet.total_gp_tracks; + unsigned int all_track_size = packet.all_tracks_size; assert(all_track_size > 0); m_track_number = all_track_size -1; for (unsigned i = 0; i < all_track_size; i++) { - std::string t; - ns.decodeString(&t); - ngpd.addNetworkTrack(t); + ngpd.addNetworkTrack(packet.all_tracks[i]); } while (all_track_size < track_size) { @@ -1283,13 +1281,14 @@ void RaceManager::configGrandPrixResultFromNetwork(NetworkString& ns) m_reverse_track.resize(track_size, m_reverse_track[0]); m_grand_prix = ngpd; - unsigned int player_size = ns.getUInt8(); + unsigned int player_size = packet.num_players; assert(player_size == m_kart_status.size()); for (unsigned i = 0; i < player_size; i++) { - int last_score = ns.getUInt32(); - int cur_score = ns.getUInt32(); - float overall_time = ns.getFloat(); + const GPIndividualScorePacket& subpacket = packet.scores[i]; + int last_score = subpacket.last_score; + int cur_score = subpacket.cur_score; + float overall_time = subpacket.overall_time; m_kart_status[i].m_last_score = last_score; m_kart_status[i].m_score = cur_score; m_kart_status[i].m_overall_time = overall_time; diff --git a/src/race/race_manager.hpp b/src/race/race_manager.hpp index 35838c03ea2..7dbe56eb8cf 100644 --- a/src/race/race_manager.hpp +++ b/src/race/race_manager.hpp @@ -39,7 +39,6 @@ class AbstractKart; class HitProcessor; -class NetworkString; class SavedGrandPrix; class Track; @@ -927,7 +926,7 @@ class RaceManager return m_num_spare_tire_karts; } // getNumSpareTireKarts // ---------------------------------------------------------------------------------------- - void configGrandPrixResultFromNetwork(NetworkString& ns); + void configGrandPrixResultFromNetwork(const GPScoresPacket& packet); // ---------------------------------------------------------------------------------------- void clearNetworkGrandPrixResult(); // ---------------------------------------------------------------------------------------- diff --git a/src/states_screens/dialogs/network_player_dialog.cpp b/src/states_screens/dialogs/network_player_dialog.cpp index 177915bf9e0..35897e02762 100644 --- a/src/states_screens/dialogs/network_player_dialog.cpp +++ b/src/states_screens/dialogs/network_player_dialog.cpp @@ -27,6 +27,7 @@ #include "guiengine/widgets/text_box_widget.hpp" #include "online/online_profile.hpp" #include "network/network_string.hpp" +#include "network/packet_types.hpp" #include "network/protocols/client_lobby.hpp" #include "network/stk_host.hpp" #include "states_screens/dialogs/general_text_field_dialog.hpp" @@ -203,10 +204,10 @@ void NetworkPlayerDialog::onUpdate(float dt) core::stringw info = tb->getText(); if (info.empty()) return false; - NetworkString report(PROTOCOL_LOBBY_ROOM); - report.addUInt8(LobbyEvent::LE_REPORT_PLAYER) - .addUInt32(host_id).encodeString16(info); - Comm::sendToServer(&report, PRM_RELIABLE); + ReportRequestPacket packet; + packet.host_id = host_id; + packet.info = info; + Comm::sendPacketToServer(packet); return true; }); return; @@ -247,19 +248,18 @@ GUIEngine::EventPropagation } else if (selection == m_kick_widget->m_properties[PROP_ID]) { - NetworkString kick(PROTOCOL_LOBBY_ROOM); - kick.addUInt8(LobbyEvent::LE_KICK_HOST).addUInt32(m_host_id); - Comm::sendToServer(&kick, PRM_RELIABLE); + KickHostPacket packet; + packet.host_id = m_host_id; + Comm::sendPacketToServer(packet); m_self_destroy = true; return GUIEngine::EVENT_BLOCK; } else if (m_change_team_widget && selection == m_change_team_widget->m_properties[PROP_ID]) { - NetworkString change_team(PROTOCOL_LOBBY_ROOM); - change_team.addUInt8(LobbyEvent::LE_CHANGE_TEAM) - .addUInt8(m_local_id); - Comm::sendToServer(&change_team, PRM_RELIABLE); + ChangeTeamPacket packet; + packet.local_id = m_local_id; + Comm::sendPacketToServer(packet); m_self_destroy = true; return GUIEngine::EVENT_BLOCK; } @@ -271,10 +271,10 @@ GUIEngine::EventPropagation { new_handicap = HANDICAP_MEDIUM; } - NetworkString change_handicap(PROTOCOL_LOBBY_ROOM); - change_handicap.addUInt8(LobbyEvent::LE_CHANGE_HANDICAP) - .addUInt8(m_local_id).addUInt8(new_handicap); - Comm::sendToServer(&change_handicap, PRM_RELIABLE); + ChangeHandicapPacket packet; + packet.local_id = m_local_id; + packet.handicap = new_handicap; + Comm::sendPacketToServer(packet); m_self_destroy = true; return GUIEngine::EVENT_BLOCK; } diff --git a/src/states_screens/dialogs/race_paused_dialog.cpp b/src/states_screens/dialogs/race_paused_dialog.cpp index 2c2ed1cfd90..c155b4b765d 100644 --- a/src/states_screens/dialogs/race_paused_dialog.cpp +++ b/src/states_screens/dialogs/race_paused_dialog.cpp @@ -386,10 +386,8 @@ GUIEngine::EventPropagation if (NetworkConfig::get()->isNetworking()) { // back lobby - NetworkString back(PROTOCOL_LOBBY_ROOM); - back.setSynchronous(true); - back.addUInt8(LobbyEvent::LE_CLIENT_BACK_LOBBY); - Comm::sendToServer(&back, PRM_RELIABLE); + ClientBackLobbyPacket packet; + Comm::sendPacketToServer(packet); } else { diff --git a/src/states_screens/dialogs/server_configuration_dialog.cpp b/src/states_screens/dialogs/server_configuration_dialog.cpp index 74fe5d0a577..fdf344ab623 100644 --- a/src/states_screens/dialogs/server_configuration_dialog.cpp +++ b/src/states_screens/dialogs/server_configuration_dialog.cpp @@ -87,35 +87,43 @@ GUIEngine::EventPropagation else if (selection == m_ok_widget->m_properties[PROP_ID]) { m_self_destroy = true; - NetworkString change(PROTOCOL_LOBBY_ROOM); - change.addUInt8(LobbyEvent::LE_CONFIG_SERVER); - change.addUInt8((uint8_t)m_difficulty_widget - ->getSelection(PLAYER_ID_GAME_MASTER)); + + ConfigServerPacket packet; + packet.difficulty = (uint8_t)m_difficulty_widget->getSelection(PLAYER_ID_GAME_MASTER); switch (m_game_mode_widget->getSelection(PLAYER_ID_GAME_MASTER)) { case 0: { - change.addUInt8(3).addUInt8(0); + packet.game_mode = 3; + packet.soccer_goal_target = false; break; } case 1: { - change.addUInt8(4).addUInt8(0); + packet.game_mode = 4; + packet.soccer_goal_target = false; break; } case 2: { int v = m_more_options_spinner->getValue(); if (v == 0) - change.addUInt8(7).addUInt8(0); + { + packet.game_mode = 7; + packet.soccer_goal_target = false; + } else - change.addUInt8(8).addUInt8(0); + { + packet.game_mode = 8; + packet.soccer_goal_target = false; + } break; } case 3: { int v = m_more_options_spinner->getValue(); - change.addUInt8(6).addUInt8((uint8_t)v); + packet.game_mode = 6; + packet.soccer_goal_target = v != 0; break; } default: @@ -123,7 +131,7 @@ GUIEngine::EventPropagation break; } } - Comm::sendToServer(&change, PRM_RELIABLE); + Comm::sendPacketToServer(packet); return GUIEngine::EVENT_BLOCK; } } diff --git a/src/states_screens/online/network_kart_selection.cpp b/src/states_screens/online/network_kart_selection.cpp index 8f64d40b277..be34fe3c600 100644 --- a/src/states_screens/online/network_kart_selection.cpp +++ b/src/states_screens/online/network_kart_selection.cpp @@ -123,22 +123,15 @@ void NetworkKartSelectionScreen::allPlayersDone() } const uint8_t kart_count = (uint8_t)m_kart_widgets.size(); - NetworkString kart(PROTOCOL_LOBBY_ROOM); - if (m_live_join) - { - kart.setSynchronous(true); - kart.addUInt8(LobbyEvent::LE_LIVE_JOIN) - // not spectator - .addUInt8(0); - } - else - kart.addUInt8(LobbyEvent::LE_KART_SELECTION); - kart.addUInt8(kart_count); + + PlayerKartsPacket karts_packet; + karts_packet.players_count = kart_count; + for (unsigned n = 0; n < kart_count; n++) { - // If server recieve an invalid name, it will auto correct to a random + // If server receives an invalid name, it will auto correct to a random // kart - kart.encodeString(m_kart_widgets[n].m_kart_internal_name); + karts_packet.karts.push_back(m_kart_widgets[n].m_kart_internal_name); } NetworkConfig* nc = NetworkConfig::get(); @@ -155,10 +148,24 @@ void NetworkKartSelectionScreen::allPlayersDone() if (kp && kp->isAddon()) kart_data = KartData(kp); } - kart_data.encode(&kart); + karts_packet.kart_data.push_back(kart_data.encode()); } } - Comm::sendToServer(&kart, PRM_RELIABLE); + + if (m_live_join) + { + LiveJoinRequestPacket packet; + packet.is_spectator = false; + packet.player_karts = karts_packet; + Comm::sendPacketToServer(packet); + } + else + { + KartSelectionRequestPacket packet; + packet.karts = karts_packet; + Comm::sendPacketToServer(packet); + } + // ---- Switch to assign mode input_manager->getDeviceManager()->setAssignMode(ASSIGN); @@ -187,9 +194,8 @@ bool NetworkKartSelectionScreen::onEscapePressed() // Send go back lobby event to server with an exit timeout, so if // server doesn't react in time we exit the server m_exit_timeout = StkTime::getMonoTimeMs() + 5000; - NetworkString back(PROTOCOL_LOBBY_ROOM); - back.addUInt8(LobbyEvent::LE_CLIENT_BACK_LOBBY); - Comm::sendToServer(&back, PRM_RELIABLE); + ClientBackLobbyPacket packet; + Comm::sendPacketToServer(packet); } return false; } diff --git a/src/states_screens/online/networking_lobby.cpp b/src/states_screens/online/networking_lobby.cpp index 0f5332e14bc..5a642ee6275 100644 --- a/src/states_screens/online/networking_lobby.cpp +++ b/src/states_screens/online/networking_lobby.cpp @@ -862,9 +862,8 @@ void NetworkingLobby::eventCallback(Widget* widget, const std::string& name, else { // Send a message to the server to start - NetworkString start(PROTOCOL_LOBBY_ROOM); - start.addUInt8(LobbyEvent::LE_REQUEST_BEGIN); - Comm::sendToServer(&start, PRM_RELIABLE); + RequestBeginPacket packet; + Comm::sendPacketToServer(packet); } } else if (name == m_config_button->m_properties[PROP_ID]) @@ -879,12 +878,9 @@ void NetworkingLobby::eventCallback(Widget* widget, const std::string& name, auto cl = LobbyProtocol::get(); if (m_client_live_joinable && cl) { - NetworkString start(PROTOCOL_LOBBY_ROOM); - start.setSynchronous(true); - start.addUInt8(LobbyEvent::LE_LIVE_JOIN) - // is spectating - .addUInt8(1); - Comm::sendToServer(&start, PRM_RELIABLE); + LiveJoinRequestPacket packet; + packet.is_spectator = true; + Comm::sendPacketToServer(packet); return; } if (cl) diff --git a/src/states_screens/online/tracks_screen.cpp b/src/states_screens/online/tracks_screen.cpp index 35ddac920ef..10fc3b52aa9 100644 --- a/src/states_screens/online/tracks_screen.cpp +++ b/src/states_screens/online/tracks_screen.cpp @@ -733,37 +733,45 @@ void TracksScreen::voteForPlayer() else UserConfigParams::m_random_arena_item = m_reversed->getState(); - NetworkString vote(PROTOCOL_LOBBY_ROOM); - vote.addUInt8(LobbyEvent::LE_VOTE); + PeerVotePacket packet; + core::stringw player_name; if (PlayerManager::getCurrentPlayer()) player_name = PlayerManager::getCurrentPlayer()->getName(); - vote.encodeString(player_name); + + packet.player_name = player_name; + packet.track_name = m_selected_track->getIdent(); + if (RaceManager::get()->getMinorMode() == RaceManager::MINOR_MODE_FREE_FOR_ALL) { - vote.encodeString(m_selected_track->getIdent()) - .addUInt8(0).addUInt8(m_reversed->getState() ? 1 : 0); + packet.num_laps = 0; + packet.is_reverse = m_reversed->getState(); } else if (RaceManager::get()->getMinorMode() == RaceManager::MINOR_MODE_CAPTURE_THE_FLAG) { - vote.encodeString(m_selected_track->getIdent()) - .addUInt8(0).addUInt8(0); + packet.num_laps = 0; + packet.is_reverse = false; } else { - vote.encodeString(m_selected_track->getIdent()) - .addUInt8(m_laps->getValue()) - .addUInt8(m_reversed->getState() ? 1 : 0); + packet.num_laps = m_laps->getValue(); + packet.is_reverse = m_reversed->getState(); } + if (auto lp = LobbyProtocol::get()) { - vote.reset(); - vote.skip(2); - PeerVote pvote(vote); + PeerVote pvote(packet); lp->addVote(STKHost::get()->getMyHostId(), pvote); } - Comm::sendToServer(&vote, PRM_RELIABLE); + else + { + // kimden: I'm not sure if this is the right thing, but seems fine. + // Not encoding packet to netstring before if just in case, too. + VoteRequestPacket vr_packet; + vr_packet.vote = packet; + Comm::sendPacketToServer(vr_packet); + } } // voteForPlayer // ----------------------------------------------------------------------------- diff --git a/src/tracks/check_line.cpp b/src/tracks/check_line.cpp index 9c02269f391..1e23525b72e 100644 --- a/src/tracks/check_line.cpp +++ b/src/tracks/check_line.cpp @@ -254,23 +254,36 @@ bool CheckLine::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos, } // isTriggered // ---------------------------------------------------------------------------- -void CheckLine::saveCompleteState(BareNetworkString* bns) +std::shared_ptr CheckLine::saveCompleteState() { - CheckStructure::saveCompleteState(bns); World* world = World::getWorld(); + + auto packet = std::make_shared(); + + auto sp = CheckStructure::saveCompleteState(); + packet->check_structure_packet = std::dynamic_pointer_cast(sp); + for (unsigned int i = 0; i < world->getNumKarts(); i++) - bns->addUInt8(m_previous_sign[i] ? 1 : 0); -} // saveCompleteState + { + CheckLineSubPacket subpacket; + subpacket.previous_sign = m_previous_sign[i]; + packet->subpackets.push_back(subpacket); + } + return packet; +} // saveCompleteState // ---------------------------------------------------------------------------- -void CheckLine::restoreCompleteState(const BareNetworkString& b) +void CheckLine::restoreCompleteState(const std::shared_ptr& packet) { - CheckStructure::restoreCompleteState(b); + std::shared_ptr cl_packet = + std::dynamic_pointer_cast(packet); + CheckStructure::restoreCompleteState(cl_packet->check_structure_packet); + m_previous_sign.clear(); World* world = World::getWorld(); for (unsigned int i = 0; i < world->getNumKarts(); i++) { - bool previous_sign = b.getUInt8() == 1; + bool previous_sign = cl_packet->subpackets[i].previous_sign; m_previous_sign.push_back(previous_sign); } } // restoreCompleteState diff --git a/src/tracks/check_line.hpp b/src/tracks/check_line.hpp index 9857ffb081b..cddf3ca2e22 100644 --- a/src/tracks/check_line.hpp +++ b/src/tracks/check_line.hpp @@ -86,9 +86,9 @@ class CheckLine : public CheckStructure * be too heigh to otherwise trigger he cannon). */ void setIgnoreHeight(bool b) { m_ignore_height = b; } // ------------------------------------------------------------------------ - virtual void saveCompleteState(BareNetworkString* bns) OVERRIDE; + virtual std::shared_ptr saveCompleteState() OVERRIDE; // ------------------------------------------------------------------------ - virtual void restoreCompleteState(const BareNetworkString& b) OVERRIDE; + virtual void restoreCompleteState(const std::shared_ptr& packet) OVERRIDE; // ------------------------------------------------------------------------ const Vec3 &getLeftPoint() const { return m_left_point; } // ------------------------------------------------------------------------ diff --git a/src/tracks/check_structure.cpp b/src/tracks/check_structure.cpp index d2b2106dd32..963cd7998c9 100644 --- a/src/tracks/check_structure.cpp +++ b/src/tracks/check_structure.cpp @@ -247,37 +247,55 @@ void CheckStructure::trigger(unsigned int kart_index) } // trigger // ---------------------------------------------------------------------------- -void CheckStructure::saveCompleteState(BareNetworkString* bns) +std::shared_ptr CheckStructure::saveCompleteState() { + std::shared_ptr packet = std::make_shared(); World* world = World::getWorld(); for (unsigned int i = 0; i < world->getNumKarts(); i++) - bns->add(m_previous_position[i]).addUInt8(m_is_active[i] ? 1 : 0); + { + CheckStructureSubPacket subpacket; + subpacket.previous_position = m_previous_position[i]; + subpacket.is_active = m_is_active[i]; + packet->player_check_state.push_back(std::move(subpacket)); + } + return packet; } // saveCompleteState // ---------------------------------------------------------------------------- -void CheckStructure::restoreCompleteState(const BareNetworkString& b) +void CheckStructure::restoreCompleteState(const std::shared_ptr& packet) { + std::shared_ptr check_packet = + std::dynamic_pointer_cast(packet); + m_previous_position.clear(); m_is_active.clear(); World* world = World::getWorld(); + + if (world->getNumKarts() != check_packet->player_check_state.size()) + Log::error("CheckStructure", "Packet's number of karts are not equal: " + "expected %d, received %d", + world->getNumKarts(), check_packet->player_check_state.size()); + for (unsigned int i = 0; i < world->getNumKarts(); i++) { - Vec3 xyz = b.getVec3(); - bool is_active = b.getUInt8() == 1; + CheckStructureSubPacket subpacket = check_packet->player_check_state[i]; + Vec3 xyz = subpacket.previous_position; + bool is_active = subpacket.is_active; m_previous_position.push_back(xyz); m_is_active.push_back(is_active); } } // restoreCompleteState // ---------------------------------------------------------------------------- -void CheckStructure::saveIsActive(int kart_id, BareNetworkString* bns) +CheckActivePacket CheckStructure::saveIsActive(int kart_id) { - bns->addUInt8(m_is_active[kart_id] ? 1 : 0); + CheckActivePacket packet; + packet.active = m_is_active[kart_id]; + return packet; } // saveIsActive // ---------------------------------------------------------------------------- -void CheckStructure::restoreIsActive(int kart_id, const BareNetworkString& b) +void CheckStructure::restoreIsActive(int kart_id, const CheckActivePacket& packet) { - bool is_active = b.getUInt8() == 1; - m_is_active.at(kart_id) = is_active; + m_is_active.at(kart_id) = packet.active; } // restoreIsActive diff --git a/src/tracks/check_structure.hpp b/src/tracks/check_structure.hpp index ceba9cd24a5..e7f58859f17 100644 --- a/src/tracks/check_structure.hpp +++ b/src/tracks/check_structure.hpp @@ -20,11 +20,12 @@ #define HEADER_CHECK_STRUCTURE_HPP #include +#include +#include "network/packet_types.hpp" #include "utils/aligned_array.hpp" #include "utils/vec3.hpp" -class BareNetworkString; class CheckManager; class Track; class XMLNode; @@ -137,13 +138,13 @@ class CheckStructure // ------------------------------------------------------------------------ virtual bool triggeringCheckline() const { return false; } // ------------------------------------------------------------------------ - virtual void saveCompleteState(BareNetworkString* bns); + virtual std::shared_ptr saveCompleteState(); // ------------------------------------------------------------------------ - virtual void restoreCompleteState(const BareNetworkString& b); + virtual void restoreCompleteState(const std::shared_ptr& packet); // ------------------------------------------------------------------------ - void saveIsActive(int kart_id, BareNetworkString* bns); + CheckActivePacket saveIsActive(int kart_id); // ------------------------------------------------------------------------ - void restoreIsActive(int kart_id, const BareNetworkString& b); + void restoreIsActive(int kart_id, const CheckActivePacket& packet); // ------------------------------------------------------------------------ int getIndex() const { return m_index; } // ------------------------------------------------------------------------ diff --git a/src/tracks/track_sector.cpp b/src/tracks/track_sector.cpp index 54d8cde18b8..b9a8720a04f 100644 --- a/src/tracks/track_sector.cpp +++ b/src/tracks/track_sector.cpp @@ -21,6 +21,7 @@ #include "modes/linear_world.hpp" #include "modes/world.hpp" #include "network/network_string.hpp" +#include "network/packet_types.hpp" #include "tracks/check_manager.hpp" #include "tracks/check_structure.hpp" #include "tracks/arena_graph.hpp" @@ -179,40 +180,44 @@ float TrackSector::getRelativeDistanceToCenter() const // ---------------------------------------------------------------------------- /** Only basket ball is used for rewind for TrackSector so save the minimum. */ -void TrackSector::saveState(BareNetworkString* buffer) const +TrackSectorSmallPacket TrackSector::saveState() const { - buffer->addUInt16((int16_t)m_current_graph_node); - buffer->addFloat(m_current_track_coords.getZ()); + TrackSectorSmallPacket packet; + packet.cur_graph_mode = (int16_t)m_current_graph_node; + packet.coord_z = m_current_track_coords.getZ(); + return packet; } // saveState // ---------------------------------------------------------------------------- -void TrackSector::rewindTo(BareNetworkString* buffer) +void TrackSector::rewindTo(const TrackSectorSmallPacket& packet) { - int16_t node = buffer->getUInt16(); + int16_t node = packet.cur_graph_mode; m_current_graph_node = node; - m_current_track_coords.setZ(buffer->getFloat()); + m_current_track_coords.setZ(packet.coord_z); } // rewindTo // ---------------------------------------------------------------------------- /** Save completely for spectating in linear race */ -void TrackSector::saveCompleteState(BareNetworkString* bns) +TrackSectorCompleteStatePacket TrackSector::saveCompleteState() { - bns->addUInt32(m_current_graph_node); - bns->addUInt32(m_estimated_valid_graph_node); - bns->addUInt32(m_last_valid_graph_node); - bns->add(m_current_track_coords); - bns->add(m_estimated_valid_track_coords); - bns->add(m_latest_valid_track_coords); - bns->addUInt8(m_on_road ? 1 : 0); - bns->addUInt32(m_last_triggered_checkline); + TrackSectorCompleteStatePacket packet; + packet.current_graph_node = m_current_graph_node; + packet.estimated_valid_graph_node = m_estimated_valid_graph_node; + packet.last_valid_graph_node = m_last_valid_graph_node; + packet.current_track_coords = m_current_track_coords; + packet.estimated_valid_track_coords = m_estimated_valid_track_coords; + packet.latest_valid_track_coords = m_latest_valid_track_coords; + packet.on_road = m_on_road; + packet.last_triggered_checkline = m_last_triggered_checkline; + return packet; } // saveCompleteState // ---------------------------------------------------------------------------- -void TrackSector::restoreCompleteState(const BareNetworkString& b) +void TrackSector::restoreCompleteState(const TrackSectorCompleteStatePacket& packet) { const int max_node = Graph::get()->getNumNodes(); - m_current_graph_node = b.getUInt32(); + m_current_graph_node = packet.current_graph_node; if (m_current_graph_node >= max_node) { Log::warn("TrackSector", "Server has different graph node list."); @@ -220,21 +225,21 @@ void TrackSector::restoreCompleteState(const BareNetworkString& b) // again it will have at least a valid node m_current_graph_node = 0; } - m_estimated_valid_graph_node = b.getUInt32(); + m_estimated_valid_graph_node = packet.estimated_valid_graph_node; if (m_estimated_valid_graph_node >= max_node) { Log::warn("TrackSector", "Server has different graph node list."); m_estimated_valid_graph_node = 0; } - m_last_valid_graph_node = b.getUInt32(); + m_last_valid_graph_node = packet.last_valid_graph_node; if (m_last_valid_graph_node >= max_node) { Log::warn("TrackSector", "Server has different graph node list."); m_last_valid_graph_node = 0; } - m_current_track_coords = b.getVec3(); - m_estimated_valid_track_coords = b.getVec3(); - m_latest_valid_track_coords = b.getVec3(); - m_on_road = b.getUInt8() == 1; - m_last_triggered_checkline = b.getUInt32(); + m_current_track_coords = packet.current_track_coords; + m_estimated_valid_track_coords = packet.estimated_valid_track_coords; + m_latest_valid_track_coords = packet.latest_valid_track_coords; + m_on_road = packet.on_road; + m_last_triggered_checkline = packet.last_triggered_checkline; } // restoreCompleteState diff --git a/src/tracks/track_sector.hpp b/src/tracks/track_sector.hpp index c57389faf0a..c56eafe3474 100644 --- a/src/tracks/track_sector.hpp +++ b/src/tracks/track_sector.hpp @@ -21,8 +21,9 @@ #include "utils/vec3.hpp" -class BareNetworkString; class Track; +class TrackSectorCompleteStatePacket; +class TrackSectorSmallPacket; /** This object keeps track of which sector an object is on. A sector is * actually just the graph node (it's called sector to better distinguish @@ -95,13 +96,13 @@ class TrackSector // ------------------------------------------------------------------------ int getLastValidGraphNode() const { return m_last_valid_graph_node; } // ------------------------------------------------------------------------ - void saveState(BareNetworkString* buffer) const; + TrackSectorSmallPacket saveState() const; // ------------------------------------------------------------------------ - void rewindTo(BareNetworkString* buffer); + void rewindTo(const TrackSectorSmallPacket& packet); // ------------------------------------------------------------------------ - void saveCompleteState(BareNetworkString* bns); + TrackSectorCompleteStatePacket saveCompleteState(); // ------------------------------------------------------------------------ - void restoreCompleteState(const BareNetworkString& b); + void restoreCompleteState(const TrackSectorCompleteStatePacket& packet); }; // TrackSector diff --git a/src/utils/chat_manager.cpp b/src/utils/chat_manager.cpp index 2f2abffd8ff..af59b3497ae 100644 --- a/src/utils/chat_manager.cpp +++ b/src/utils/chat_manager.cpp @@ -27,7 +27,6 @@ #include "network/stk_peer.hpp" #include "utils/communication.hpp" #include "utils/string_utils.hpp" -#include "utils/string_utils.hpp" #include "utils/tournament.hpp" namespace @@ -193,6 +192,11 @@ void ChatManager::handleNormalChatMessage(std::shared_ptr peer, if (!StringUtils::startsWith(message, prefix)) { + // This string is not set to be translatable, because it is + // currently written by the server. The server would have + // to send a warning for interpretation by the client to + // allow proper translation. Also, this string can only be + // triggered with modified STK clients anyways. Comm::sendStringToPeer(peer, "Don't try to impersonate others!"); return; } @@ -224,20 +228,18 @@ void ChatManager::handleNormalChatMessage(std::shared_ptr peer, if (target_team == KART_TEAM_BLUE || (team_speaker && team_mode && teams.has(KART_TEAM_BLUE))) message = g_blue_team + message; - NetworkString* chat = getLobby()->getNetworkString(); - chat->setSynchronous(true); - chat->addUInt8(LobbyEvent::LE_CHAT).encodeString16(StringUtils::utf8ToWide(message)); + ChatPacket packet; + packet.message = StringUtils::utf8ToWide(message); - STKHost::get()->sendPacketToAllPeersWith( + Comm::sendPacketToPeersWith( std::bind(&ChatManager::shouldMessageBeSent, this, peer, std::placeholders::_1, game_started, target_team - ), chat + ), packet ); - delete chat; peer->updateLastMessage(); } // handleNormalChatMessage diff --git a/src/utils/communication.cpp b/src/utils/communication.cpp index cc7ee3e5544..5f9de5595b5 100644 --- a/src/utils/communication.cpp +++ b/src/utils/communication.cpp @@ -36,11 +36,12 @@ namespace Comm * \param message The actual message content. * \param reliable Whether it should be in a reliable way or not. */ -void sendMessageToPeers(NetworkString *message, +[[deprecated("You should send packets to Comm::, it will pass NetString to STKHost,")]] +void sendNetstringToPeers(NetworkString *message, PacketReliabilityMode reliable) { - STKHost::get()->sendPacketToAllPeers(message, reliable); -} // sendMessageToPeers + STKHost::get()->sendNetstringToPeers(message, reliable); +} // sendNetstringToPeers // ---------------------------------------------------------------------------- /** Sends a message to all validated peers in server, encrypt the message if @@ -49,17 +50,19 @@ void sendMessageToPeers(NetworkString *message, * \param message The actual message content. * \param reliable Whether it should be in a reliable way or not. */ -void sendMessageToPeersInServer(NetworkString* message, +[[deprecated("You should send packets to Comm::, it will pass NetString to STKHost,")]] +void sendNetstringToPeersInServer(NetworkString* message, PacketReliabilityMode reliable) { - STKHost::get()->sendPacketToAllPeersInServer(message, reliable); -} // sendMessageToPeersInServer + STKHost::get()->sendNetstringToPeersInServer(message, reliable); +} // sendNetstringToPeersInServer // ---------------------------------------------------------------------------- /** Sends a message from a client to the server. * \param message The actual message content. * \param reliable Whether it should be in a reliable way or not. */ +[[deprecated("You should send packets to Comm::, it will pass NetString to STKHost,")]] void sendToServer(NetworkString *message, PacketReliabilityMode reliable) { @@ -71,26 +74,21 @@ void sendStringToPeer(std::shared_ptr peer, const std::string& s) { if (!peer) { - sendStringToAllPeers(s); + sendStringToPeers(s); return; } - NetworkString* chat = new NetworkString(ProtocolType::PROTOCOL_LOBBY_ROOM); - chat->addUInt8(LE_CHAT); - chat->setSynchronous(true); - chat->encodeString16(StringUtils::utf8ToWide(s)); - peer->sendPacket(chat, PRM_RELIABLE); - delete chat; + + ChatPacket packet; + packet.message = StringUtils::utf8ToWide(s); + peer->sendPacket(packet); } // sendStringToPeer //----------------------------------------------------------------------------- -void sendStringToAllPeers(const std::string& s) +void sendStringToPeers(const std::string& s) { - NetworkString* chat = new NetworkString(ProtocolType::PROTOCOL_LOBBY_ROOM); - chat->addUInt8(LE_CHAT); - chat->setSynchronous(true); - chat->encodeString16(StringUtils::utf8ToWide(s)); - sendMessageToPeers(chat, PRM_RELIABLE); - delete chat; -} // sendStringToAllPeers + ChatPacket packet; + packet.message = StringUtils::utf8ToWide(s); + sendPacketToPeers(packet); +} // sendStringToPeers //----------------------------------------------------------------------------- } // namespace Comm diff --git a/src/utils/communication.hpp b/src/utils/communication.hpp index 447a23bae31..9e40092b1b2 100644 --- a/src/utils/communication.hpp +++ b/src/utils/communication.hpp @@ -27,9 +27,9 @@ namespace Comm { - void sendMessageToPeers(NetworkString *message, + void sendNetstringToPeers(NetworkString *message, PacketReliabilityMode reliable = PRM_RELIABLE); - void sendMessageToPeersInServer(NetworkString *message, + void sendNetstringToPeersInServer(NetworkString *message, PacketReliabilityMode reliable = PRM_RELIABLE); void sendToServer(NetworkString *message, PacketReliabilityMode reliable = PRM_RELIABLE); @@ -40,7 +40,59 @@ namespace Comm // Uses PROTOCOL_LOBBY_ROOM as chat is sent from there usually. // Using in non-lobby classes would be strange but seemingly ok. - void sendStringToAllPeers(const std::string& s); + void sendStringToPeers(const std::string& s); + + // ---------------------------------------------------------------------------- + template + typename std::enable_if::value, void>::type + sendPacketToPeers(const T& packet, + PacketReliabilityMode reliable = PRM_RELIABLE) + { + std::shared_ptr ptr1 = std::make_shared(packet); + std::shared_ptr ptr2 = std::dynamic_pointer_cast(ptr1); + return STKHost::get()->sendPacketPtrToPeers(ptr2, reliable); + } + + template + typename std::enable_if::value, void>::type + sendPacketToPeersInServer(const T& packet, + PacketReliabilityMode reliable = PRM_RELIABLE) + { + std::shared_ptr ptr1 = std::make_shared(packet); + std::shared_ptr ptr2 = std::dynamic_pointer_cast(ptr1); + return STKHost::get()->sendPacketPtrToPeersInServer(ptr2, reliable); + } + + template + typename std::enable_if::value, void>::type + sendPacketToServer(const T& packet, + PacketReliabilityMode reliable = PRM_RELIABLE) + { + std::shared_ptr ptr1 = std::make_shared(packet); + std::shared_ptr ptr2 = std::dynamic_pointer_cast(ptr1); + return STKHost::get()->sendPacketPtrToServer(ptr2, reliable); + } + + template + typename std::enable_if::value, void>::type + sendPacketExcept(std::shared_ptr peer, const T& packet, + PacketReliabilityMode reliable = PRM_RELIABLE) + { + std::shared_ptr ptr1 = std::make_shared(packet); + std::shared_ptr ptr2 = std::dynamic_pointer_cast(ptr1); + return STKHost::get()->sendPacketPtrExcept(peer, ptr2, reliable); + } + + template + typename std::enable_if::value, void>::type + sendPacketToPeersWith(std::function)> predicate, + const T& packet, PacketReliabilityMode reliable = PRM_RELIABLE) + { + std::shared_ptr ptr1 = std::make_shared(packet); + std::shared_ptr ptr2 = std::dynamic_pointer_cast(ptr1); + return STKHost::get()->sendPacketPtrToPeersWith(predicate, ptr2, reliable); + } + // ------------------------------------------------------------------------ } diff --git a/src/utils/game_info.cpp b/src/utils/game_info.cpp index 7c441612406..acf004af07d 100644 --- a/src/utils/game_info.cpp +++ b/src/utils/game_info.cpp @@ -453,7 +453,7 @@ void GameInfo::fillAndStoreResults() StringUtils::timeToString(best_result), best_user); } if (!message.empty()) - Comm::sendStringToAllPeers(message); + Comm::sendStringToPeers(message); } } // fillAndStoreResults diff --git a/src/utils/game_info.hpp b/src/utils/game_info.hpp index e827450ffbc..d826173198a 100644 --- a/src/utils/game_info.hpp +++ b/src/utils/game_info.hpp @@ -57,6 +57,12 @@ struct GameInfo: public LobbyContextUser double m_game_duration = -1; int m_handicap = 0; std::string m_country_code = ""; + + // Added with version 3a + std::string m_vote_track_name = ""; + int m_vote_num_laps = -1; + int m_vote_reverse = -1; + std::string m_other_info = ""; PlayerInfo(bool reserved = false, bool game_event = false): diff --git a/src/utils/hit_processor.cpp b/src/utils/hit_processor.cpp index 170356fa2d3..13300cb6f72 100644 --- a/src/utils/hit_processor.cpp +++ b/src/utils/hit_processor.cpp @@ -100,7 +100,7 @@ void HitProcessor::sendTeammateHitMsg(std::string& s) if (ticks - m_last_hit_msg > STKConfig::get()->time2Ticks(g_hit_message_delay)) { m_last_hit_msg = ticks; - Comm::sendStringToAllPeers(s); + Comm::sendStringToPeers(s); } } // sendTeammateHitMsg //----------------------------------------------------------------------------- diff --git a/src/utils/lobby_asset_manager.cpp b/src/utils/lobby_asset_manager.cpp index 5bf11455736..f31492bc795 100644 --- a/src/utils/lobby_asset_manager.cpp +++ b/src/utils/lobby_asset_manager.cpp @@ -293,16 +293,22 @@ std::string LobbyAssetManager::getRandomAvailableMap() } // getRandomAvailableMap //----------------------------------------------------------------------------- -void LobbyAssetManager::encodePlayerKartsAndCommonMaps(NetworkString* ns, +AssetsPacket2 LobbyAssetManager::encodePlayerKartsAndCommonMaps( const std::set& all_k) { const auto& all_t = m_available_kts.second; - ns->addUInt16((uint16_t)all_k.size()).addUInt16((uint16_t)all_t.size()); + AssetsPacket2 packet; + packet.karts_number = (uint16_t)all_k.size(); + packet.maps_number = (uint16_t)all_t.size(); + for (const std::string& kart : all_k) - ns->encodeString(kart); + packet.karts.push_back(kart); + for (const std::string& track : all_t) - ns->encodeString(track); + packet.maps.push_back(track); + + return packet; } // encodePlayerKartsAndCommonMaps //----------------------------------------------------------------------------- diff --git a/src/utils/lobby_asset_manager.hpp b/src/utils/lobby_asset_manager.hpp index 6844ac4a1b6..12a85f6b39c 100644 --- a/src/utils/lobby_asset_manager.hpp +++ b/src/utils/lobby_asset_manager.hpp @@ -30,7 +30,6 @@ #include #include -class NetworkString; class ServerLobby; class STKPeer; @@ -50,8 +49,8 @@ class LobbyAssetManager: public LobbyContextComponent bool tryApplyingMapFilters(); std::string getRandomAvailableMap(); - void encodePlayerKartsAndCommonMaps( - NetworkString* ns, const std::set& all_k); + AssetsPacket2 encodePlayerKartsAndCommonMaps( + const std::set& all_k); bool handleAssetsForPeer(std::shared_ptr peer, const std::set& client_karts, diff --git a/src/utils/lobby_gp_manager.cpp b/src/utils/lobby_gp_manager.cpp index 874122aec36..cf2636e37a1 100644 --- a/src/utils/lobby_gp_manager.cpp +++ b/src/utils/lobby_gp_manager.cpp @@ -163,7 +163,7 @@ void LobbyGPManager::shuffleGPScoresWithPermutation(const std::map& pe } // shuffleGPScoresWithPermutation //----------------------------------------------------------------------------- -void LobbyGPManager::updateGPScores(std::vector& gp_changes, NetworkString* ns) +GPScoresPacket LobbyGPManager::updateGPScores(std::vector& gp_changes) { // fastest lap int fastest_lap = @@ -234,22 +234,24 @@ void LobbyGPManager::updateGPScores(std::vector& gp_changes, NetworkStrin overall_times.push_back(overall_time); } - ns->addUInt32(fastest_lap); - ns->encodeString(fastest_kart_wide); - - ns->addUInt8((uint8_t)game_setup->getTotalGrandPrixTracks()) - .addUInt8((uint8_t)game_setup->getAllTracks().size()); + GPScoresPacket packet; + packet.total_gp_tracks = (uint8_t)game_setup->getTotalGrandPrixTracks(); + packet.all_tracks_size = (uint8_t)game_setup->getAllTracks().size(); for (const std::string& gp_track : game_setup->getAllTracks()) - ns->encodeString(gp_track); + packet.all_tracks.push_back(gp_track); - ns->addUInt8((uint8_t)RaceManager::get()->getNumPlayers()); + packet.num_players = (uint8_t)RaceManager::get()->getNumPlayers(); for (unsigned i = 0; i < RaceManager::get()->getNumPlayers(); i++) { - ns->addUInt32(last_scores[i]) - .addUInt32(cur_scores[i]) - .addFloat(overall_times[i]); + GPIndividualScorePacket subpacket; + subpacket.last_score = last_scores[i]; + subpacket.cur_score = cur_scores[i]; + subpacket.overall_time = overall_times[i]; + packet.scores.push_back(subpacket); } + + return packet; } // updateGPScores //----------------------------------------------------------------------------- diff --git a/src/utils/lobby_gp_manager.hpp b/src/utils/lobby_gp_manager.hpp index aa8f0b1ec99..276ac6c08c3 100644 --- a/src/utils/lobby_gp_manager.hpp +++ b/src/utils/lobby_gp_manager.hpp @@ -20,6 +20,7 @@ #define LOBBY_GP_MANAGER_HPP #include "irrString.h" +#include "network/packet_types.hpp" #include "utils/track_filter.hpp" #include "utils/lobby_context.hpp" @@ -27,7 +28,6 @@ #include class NetworkPlayerProfile; -class NetworkString; class GPScoring; struct GPScore @@ -61,7 +61,7 @@ class LobbyGPManager: public LobbyContextComponent void shuffleGPScoresWithPermutation(const std::map& permutation); - void updateGPScores(std::vector& gp_changes, NetworkString* ns); + GPScoresPacket updateGPScores(std::vector& gp_changes); bool trySettingGPScoring(const std::string& input); diff --git a/src/utils/lobby_settings.cpp b/src/utils/lobby_settings.cpp index 6d8cbc53a06..28246146f8c 100644 --- a/src/utils/lobby_settings.cpp +++ b/src/utils/lobby_settings.cpp @@ -555,10 +555,12 @@ void LobbySettings::applyRestrictionsOnWinnerVote(PeerVote* winner_vote) const } // applyRestrictionsOnWinnerVote //----------------------------------------------------------------------------- -void LobbySettings::encodeDefaultVote(NetworkString* ns) const +DefaultVotePacket LobbySettings::encodeDefaultVote() const { - ns->addUInt32(m_winner_peer_id); - m_default_vote->encode(ns); + DefaultVotePacket packet; + packet.winner_peer_id = m_winner_peer_id; + packet.default_vote = m_default_vote->encode(); + return packet; } // encodeDefaultVote //----------------------------------------------------------------------------- diff --git a/src/utils/lobby_settings.hpp b/src/utils/lobby_settings.hpp index 4f9b227b039..ed3a2826cc4 100644 --- a/src/utils/lobby_settings.hpp +++ b/src/utils/lobby_settings.hpp @@ -29,12 +29,12 @@ class GameSetup; class KartElimination; class LobbyAssetManager; class LobbyQueues; -class NetworkString; class PeerVote; class STKPeer; class Tournament; class Track; struct GameInfo; +class DefaultVotePacket; /** @brief A class that manipulates server settings, such as resetting, * scoring, goal policies, etc. Might be split into a few parts later, @@ -84,7 +84,7 @@ class LobbySettings: public LobbyContextComponent void initializeDefaultVote(); void applyRestrictionsOnVote(PeerVote* vote, Track* t) const; void applyRestrictionsOnWinnerVote(PeerVote* winner_vote) const; - void encodeDefaultVote(NetworkString* ns) const; + DefaultVotePacket encodeDefaultVote() const; void setDefaultVote(PeerVote winner_vote); PeerVote getDefaultVote() const; bool isInWhitelist(const std::string& username) const; diff --git a/src/utils/types.hpp b/src/utils/types.hpp index 082e30e08a0..1fa6339e6ba 100644 --- a/src/utils/types.hpp +++ b/src/utils/types.hpp @@ -38,4 +38,16 @@ #endif #endif + struct int24_t + { + uint32_t value; + operator uint32_t() const { return value; } + + int24_t& operator = (uint32_t rhs) + { + value = rhs; + return *this; + } + }; + #endif