From bd6c699d5e93fb6f7bb774309b88f78b96b4f418 Mon Sep 17 00:00:00 2001 From: afwbkbc Date: Thu, 15 Feb 2024 21:07:59 +0200 Subject: [PATCH 1/2] gse callable group parsing fix --- gse/default/main.gls.js | 7 +- gse/tests/functions.gls.js | 20 +++ src/gse/parser/JS.cpp | 284 ++++++++++++++++++++----------------- src/gse/program/Element.h | 1 - 4 files changed, 172 insertions(+), 140 deletions(-) diff --git a/gse/default/main.gls.js b/gse/default/main.gls.js index 907b56ec..c0ae4684 100644 --- a/gse/default/main.gls.js +++ b/gse/default/main.gls.js @@ -44,8 +44,7 @@ while (i < #size(units)) { let sz = #size(neighbours); let nearby_units_count = 0; while (i < sz) { - let neighbour = neighbours[i]; - if (!#is_empty(neighbour.get_units())) { + if (!#is_empty(neighbours[i].get_units())) { nearby_units_count++; } i++; @@ -57,9 +56,7 @@ while (i < #size(units)) { }); #game.on.despawn_unit((unit) => { - let def = unit.get_def(); - #print(#to_string(def)); - if (def.name == 'SporeLauncher') { + if (unit.get_def() == 'SporeLauncher') { #game.units.spawn('MindWorms', unit.get_tile()); } }); diff --git a/gse/tests/functions.gls.js b/gse/tests/functions.gls.js index 3802487f..4ba329c4 100644 --- a/gse/tests/functions.gls.js +++ b/gse/tests/functions.gls.js @@ -22,3 +22,23 @@ let lambda3 = (f1, f2) => { test.assert(lambda3(lambda2, lambda1) == 292); test.assert( (a, b, c) => { return a + b + c; }( 1, 2, 3 ) == 6 ); + +let arr_of_func_objs = [ + { + v: () => { + return 'A'; + } + }, + { + v: () => { + return 'B'; + } + }, +]; +test.assert(arr_of_func_objs[0].v() == 'A'); +test.assert(arr_of_func_objs[1].v() == 'B'); + +let f = () => { + return 'Y' +}; +test.assert('X' + f() == 'XY'); diff --git a/src/gse/parser/JS.cpp b/src/gse/parser/JS.cpp index caaf7aeb..974a3565 100644 --- a/src/gse/parser/JS.cpp +++ b/src/gse/parser/JS.cpp @@ -361,6 +361,132 @@ const program::Operand* JS::GetExpressionOrOperand( const source_elements_t::con bool var_hints_allowed = true; Variable::variable_hints_t next_var_hints = Variable::VH_NONE; const Expression* condition; + + // split by operator priority + const std::function< + program::Operand*( + const elements_t::const_iterator&, + const elements_t::const_iterator& + ) + > get_operand = [ + this, + &get_operand + ]( + const elements_t::const_iterator& begin, + const elements_t::const_iterator& end + ) -> program::Operand* { + if ( begin + 1 == end ) { + // only one operand present, wrap if needed and return + if ( ( *begin )->m_element_type != Element::ET_OPERAND ) { + throw gse::Exception( EC.PARSE_ERROR, "Unexpected: " + ( *begin )->ToString(), nullptr, ( *begin )->m_si ); + } + return (program::Operand*)*begin; + } + // find most important operator + const program::Operator* op; + uint8_t last_priority = 255; + elements_t::const_iterator split_it = end; + const operator_info_t* info; + operator_link_t link; + const Element* el; + for ( auto it = begin ; it != end ; it++ ) { + el = *it; + if ( el->m_element_type == Element::ET_OPERATOR ) { + op = (program::Operator*)( *it ); + info = &OPERATOR_INFO.at( op->op ); + if ( info->priority <= last_priority ) { + last_priority = info->priority; + split_it = it; + link = info->link; + } + } + } + if ( split_it == end ) { + throw gse::Exception( EC.PARSE_ERROR, "Could not parse expression (forgot ; or operator?)", nullptr, ( *begin )->m_si ); + } + + bool has_a = split_it > begin; + bool has_b = split_it + 1 != end; + + si_t si = ( *split_it )->m_si; + + for ( auto it = begin ; it != end ; it++ ) { + el = *it; + if ( + it < split_it && + ( + el->m_si.from.line < si.from.line || + ( + el->m_si.from.line == si.from.line && + el->m_si.from.col < si.from.col + ) + ) + ) { + si.from = el->m_si.from; + } + if ( + it > split_it && + ( el->m_si.to.line > si.to.line || + ( + el->m_si.to.line == si.to.line && + el->m_si.to.col > si.to.col + ) + ) ) { + si.to = el->m_si.to; + } + } + switch ( link ) { + case OL_LEFT: { + if ( !has_a ) { + throw gse::Exception( EC.PARSE_ERROR, "Left operand missing for operator: " + ( *split_it )->ToString(), nullptr, ( *split_it )->m_si ); + } + if ( has_b ) { + throw gse::Exception( EC.PARSE_ERROR, "Right operand unexpected for operator: " + ( *split_it )->ToString(), nullptr, ( *split_it )->m_si ); + } + return new program::Expression( si, get_operand( begin, split_it ), (program::Operator*)*split_it ); + } + case OL_RIGHT: { + if ( !has_b ) { + throw gse::Exception( EC.PARSE_ERROR, "Right operand missing for operator: " + ( *split_it )->ToString(), nullptr, ( *split_it )->m_si ); + } + if ( has_a ) { + throw gse::Exception( EC.PARSE_ERROR, "Left operand unexpected for operator: " + ( *split_it )->ToString(), nullptr, ( *split_it )->m_si ); + } + return new program::Expression( si, nullptr, (program::Operator*)*split_it, get_operand( split_it + 1, end ) ); + } + case OL_BOTH: { + if ( !has_a ) { + throw gse::Exception( EC.PARSE_ERROR, "Left operand missing for operator: " + ( *split_it )->ToString(), nullptr, ( *split_it )->m_si ); + } + if ( !has_b ) { + throw gse::Exception( EC.PARSE_ERROR, "Right operand missing for operator: " + ( *split_it )->ToString(), nullptr, ( *split_it )->m_si ); + } + return new program::Expression( si, get_operand( begin, split_it ), (program::Operator*)*split_it, get_operand( split_it + 1, end ) ); + } + case OL_ANY: { + if ( has_a && has_b ) { + throw gse::Exception( EC.PARSE_ERROR, "Either left or right operand is expected, both found, for operator: " + ( *split_it )->ToString(), nullptr, ( *split_it )->m_si ); + } + case OL_ANY_OR_BOTH: + if ( !has_a && !has_b ) { + throw gse::Exception( EC.PARSE_ERROR, "Neither left nor right operand is found, for operator: " + ( *split_it )->ToString(), nullptr, ( *split_it )->m_si ); + } + return new program::Expression( + si, + has_a + ? get_operand( begin, split_it ) + : nullptr, + (program::Operator*)*split_it, + has_b + ? get_operand( split_it + 1, end ) + : nullptr + ); + } + default: + THROW( "unexpected operator link type: " + std::to_string( link ) ); + } + }; + while ( it != end ) { switch ( ( *it )->m_type ) { case SourceElement::ET_COMMENT: { @@ -539,10 +665,24 @@ const program::Operand* JS::GetExpressionOrOperand( const source_elements_t::con throw gse::Exception( EC.PARSE_ERROR, "Expected { after =>", nullptr, ( *it )->m_si ); } - auto* element = elements.back(); // use last element as callable - ASSERT( element->m_element_type == Element::ET_OPERAND, "callable is not operand" ); - auto* operand = (Operand*)element; - elements.pop_back(); + // combine last child/at chain before using it as callable + auto callable_begin = elements.end(); + while ( callable_begin != elements.begin() ) { + callable_begin--; + if ( + (*callable_begin)->m_element_type != Element::ET_OPERAND && ( + (*callable_begin)->m_element_type != Element::ET_OPERATOR || ( + ((program::Operator*)(*callable_begin))->op != program::Operator::OT_CHILD && + ((program::Operator*)(*callable_begin))->op != program::Operator::OT_AT + ) + ) + ) { + callable_begin++; + break; + } + } + const auto* expr = (Expression*)get_operand( callable_begin, elements.end() ); + elements.erase( callable_begin, elements.end() ); std::vector< const Expression* > arguments = {}; it_end = GetBracketsEnd( it, end ); @@ -572,13 +712,14 @@ const program::Operand* JS::GetExpressionOrOperand( const source_elements_t::con elements.push_back( new Call( { - element->m_si.file, - element->m_si.from, + expr->m_si.file, + expr->m_si.from, ( *it_end )->m_si.to }, - operand->type == Operand::OT_EXPRESSION - ? (Expression*)operand - : new Expression( operand->m_si, operand ), arguments + expr->type == Operand::OT_EXPRESSION + ? (Expression*)expr + : new Expression( expr->m_si, expr ), + arguments ) ); } @@ -644,131 +785,6 @@ const program::Operand* JS::GetExpressionOrOperand( const source_elements_t::con } } - // split by operator priority - const std::function< - program::Operand*( - const elements_t::const_iterator&, - const elements_t::const_iterator& - ) - > get_operand = [ - this, - &get_operand - ]( - const elements_t::const_iterator& begin, - const elements_t::const_iterator& end - ) -> program::Operand* { - if ( begin + 1 == end ) { - // only one operand present, wrap if needed and return - if ( ( *begin )->m_element_type != Element::ET_OPERAND ) { - throw gse::Exception( EC.PARSE_ERROR, "Unexpected: " + ( *begin )->ToString(), nullptr, ( *begin )->m_si ); - } - return (program::Operand*)*begin; - } - // find most important operator - const program::Operator* op; - uint8_t last_priority = 255; - elements_t::const_iterator split_it = end; - const operator_info_t* info; - operator_link_t link; - const Element* el; - for ( auto it = begin ; it != end ; it++ ) { - el = *it; - if ( el->m_element_type == Element::ET_OPERATOR ) { - op = (program::Operator*)( *it ); - info = &OPERATOR_INFO.at( op->op ); - if ( info->priority <= last_priority ) { - last_priority = info->priority; - split_it = it; - link = info->link; - } - } - } - if ( split_it == end ) { - throw gse::Exception( EC.PARSE_ERROR, "Could not parse expression (forgot ; or operator?)", nullptr, ( *begin )->m_si ); - } - - bool has_a = split_it > begin; - bool has_b = split_it + 1 != end; - - si_t si = ( *split_it )->m_si; - - for ( auto it = begin ; it != end ; it++ ) { - el = *it; - if ( - it < split_it && - ( - el->m_si.from.line < si.from.line || - ( - el->m_si.from.line == si.from.line && - el->m_si.from.col < si.from.col - ) - ) - ) { - si.from = el->m_si.from; - } - if ( - it > split_it && - ( el->m_si.to.line > si.to.line || - ( - el->m_si.to.line == si.to.line && - el->m_si.to.col > si.to.col - ) - ) ) { - si.to = el->m_si.to; - } - } - switch ( link ) { - case OL_LEFT: { - if ( !has_a ) { - throw gse::Exception( EC.PARSE_ERROR, "Left operand missing for operator: " + ( *split_it )->ToString(), nullptr, ( *split_it )->m_si ); - } - if ( has_b ) { - throw gse::Exception( EC.PARSE_ERROR, "Right operand unexpected for operator: " + ( *split_it )->ToString(), nullptr, ( *split_it )->m_si ); - } - return new program::Expression( si, get_operand( begin, split_it ), (program::Operator*)*split_it ); - } - case OL_RIGHT: { - if ( !has_b ) { - throw gse::Exception( EC.PARSE_ERROR, "Right operand missing for operator: " + ( *split_it )->ToString(), nullptr, ( *split_it )->m_si ); - } - if ( has_a ) { - throw gse::Exception( EC.PARSE_ERROR, "Left operand unexpected for operator: " + ( *split_it )->ToString(), nullptr, ( *split_it )->m_si ); - } - return new program::Expression( si, nullptr, (program::Operator*)*split_it, get_operand( split_it + 1, end ) ); - } - case OL_BOTH: { - if ( !has_a ) { - throw gse::Exception( EC.PARSE_ERROR, "Left operand missing for operator: " + ( *split_it )->ToString(), nullptr, ( *split_it )->m_si ); - } - if ( !has_b ) { - throw gse::Exception( EC.PARSE_ERROR, "Right operand missing for operator: " + ( *split_it )->ToString(), nullptr, ( *split_it )->m_si ); - } - return new program::Expression( si, get_operand( begin, split_it ), (program::Operator*)*split_it, get_operand( split_it + 1, end ) ); - } - case OL_ANY: { - if ( has_a && has_b ) { - throw gse::Exception( EC.PARSE_ERROR, "Either left or right operand is expected, both found, for operator: " + ( *split_it )->ToString(), nullptr, ( *split_it )->m_si ); - } - case OL_ANY_OR_BOTH: - if ( !has_a && !has_b ) { - throw gse::Exception( EC.PARSE_ERROR, "Neither left nor right operand is found, for operator: " + ( *split_it )->ToString(), nullptr, ( *split_it )->m_si ); - } - return new program::Expression( - si, - has_a - ? get_operand( begin, split_it ) - : nullptr, - (program::Operator*)*split_it, - has_b - ? get_operand( split_it + 1, end ) - : nullptr - ); - } - default: - THROW( "unexpected operator link type: " + std::to_string( link ) ); - } - }; - return get_operand( elements.begin(), elements.end() ); } diff --git a/src/gse/program/Element.h b/src/gse/program/Element.h index 3a8954ae..fc84378e 100644 --- a/src/gse/program/Element.h +++ b/src/gse/program/Element.h @@ -26,7 +26,6 @@ class Element { ET_OPERAND, ET_OPERATOR, ET_CONDITIONAL, - ET_INCLUDE, }; Element( const si_t& si, const element_type_t element_type ) : m_si( si ) From dab7fabccea626885abf7a4d08f1782aa90935e5 Mon Sep 17 00:00:00 2001 From: afwbkbc Date: Thu, 15 Feb 2024 23:10:17 +0200 Subject: [PATCH 2/2] send units with map upon connecting --- gse/default/main.gls.js | 17 +++-- src/game/Game.cpp | 114 ++++++++++++++++++++++++----- src/game/Game.h | 5 ++ src/game/bindings/Units.cpp | 12 +-- src/game/connection/Client.cpp | 100 ++++++++++++------------- src/game/connection/Client.h | 10 +-- src/game/connection/Connection.cpp | 1 + src/game/connection/Connection.h | 2 +- src/game/connection/Server.cpp | 68 ++++++++--------- src/game/connection/Server.h | 8 +- src/game/event/CMakeLists.txt | 1 + src/game/event/DefineUnit.cpp | 29 ++++++++ src/game/event/DefineUnit.h | 27 +++++++ src/game/event/Event.cpp | 7 ++ src/game/event/Event.h | 2 + src/game/map/Map.cpp | 13 ++-- src/game/map/Map.h | 4 +- src/game/unit/Unit.cpp | 3 + src/game/unit/Unit.h | 1 + src/types/Packet.cpp | 36 ++++----- src/types/Packet.h | 10 +-- 21 files changed, 312 insertions(+), 158 deletions(-) create mode 100644 src/game/event/DefineUnit.cpp create mode 100644 src/game/event/DefineUnit.h diff --git a/gse/default/main.gls.js b/gse/default/main.gls.js index c0ae4684..d9fa9fb8 100644 --- a/gse/default/main.gls.js +++ b/gse/default/main.gls.js @@ -1,13 +1,14 @@ -const rules = #include('rules'); -const units = #include('units'); +#game.on.start(() => { -let i = 0; -while (i < #size(units)) { - #game.units.define(units[i][0], units[i][1]); - i++; -} + const rules = #include('rules'); + const units = #include('units'); + + let i = 0; + while (i < #size(units)) { + #game.units.define(units[i][0], units[i][1]); + i++; + } -#game.on.start(() => { let y = 0; while (y < #game.map.height) { let x = 0; diff --git a/src/game/Game.cpp b/src/game/Game.cpp index 40d7e911..5a295e50 100644 --- a/src/game/Game.cpp +++ b/src/game/Game.cpp @@ -291,6 +291,10 @@ void Game::Iterate() { if ( m_game_state == GS_RUNNING ) { + for ( auto& it : m_unprocessed_units ) { + SpawnUnit( it ); + } + m_unprocessed_units.clear(); for ( auto& it : m_unprocessed_events ) { ProcessGameEvent( it ); } @@ -873,8 +877,7 @@ void Game::AddUnitDef( const std::string& name, const unit::Def* def, gse::Conte delete def; throw gse::Exception( gse::EC.GAME_ERROR, "Unit definition '" + name + "' already exists", ctx, si ); } - m_unit_defs.insert_or_assign( name, def ); - Log( "Added unit def '" + name + "'" ); + DefineUnit( def ); } const unit::Def* Game::GetUnitDef( const std::string& name ) const { @@ -891,14 +894,22 @@ const gse::Value Game::AddGameEvent( const event::Event* event, gse::Context* ct if ( m_connection ) { m_connection->SendGameEvent( event ); } - const auto result = ProcessGameEvent( event ); - return result; + return ProcessGameEvent( event ); +} + +void Game::DefineUnit( const unit::Def* def ) { + Log( "Defining unit ('" + def->m_name + "')" ); + + ASSERT( m_unit_defs.find( def->m_name ) == m_unit_defs.end(), "Unit definition '" + def->m_name + "' already exists" ); + + m_unit_defs.insert_or_assign( def->m_name, def ); } void Game::SpawnUnit( unit::Unit* unit ) { - ASSERT( m_units.find( unit->m_id ) == m_units.end(), "duplicate unit id" ); Log( "Spawning unit ('" + unit->m_def->m_name + "') at [ " + std::to_string( unit->m_pos_x ) + " " + std::to_string( unit->m_pos_y ) + " ]" ); + ASSERT( m_units.find( unit->m_id ) == m_units.end(), "duplicate unit id" ); + auto* tile = m_map->GetTile( unit->m_pos_x, unit->m_pos_y ); const auto* ts = m_map->GetTileState( tile ); @@ -961,6 +972,45 @@ const gse::Value Game::ProcessGameEvent( const event::Event* event ) { return event->Apply( this ); } +void Game::SerializeUnits( types::Buffer& buf ) const { + Log( "Serializing " + std::to_string( m_unit_defs.size() ) + " unit defs" ); + buf.WriteInt( m_unit_defs.size() ); + for ( const auto& it : m_unit_defs ) { + buf.WriteString( it.first ); + buf.WriteString( unit::Def::Serialize( it.second ).ToString() ); + } + buf.WriteInt( m_units.size() ); + Log( "Serializing " + std::to_string( m_units.size() ) + " units" ); + for ( const auto& it : m_units ) { + buf.WriteInt( it.first ); + buf.WriteString( unit::Unit::Serialize( it.second ).ToString() ); + } + buf.WriteInt( unit::Unit::GetNextId() ); + Log( "Saved next unit id: " + std::to_string( unit::Unit::GetNextId() ) ); +} + +void Game::UnserializeUnits( types::Buffer& buf ) { + ASSERT( m_unit_defs.empty(), "unit defs not empty" ); + ASSERT( m_units.empty(), "units not empty" ); + size_t sz = buf.ReadInt(); + Log( "Unserializing " + std::to_string( sz ) + " unit defs" ); + for ( size_t i = 0 ; i < sz ; i++ ) { + const auto name = buf.ReadString(); + auto b = Buffer( buf.ReadString() ); + DefineUnit( unit::Def::Unserialize( b ) ); + } + sz = buf.ReadInt(); + Log( "Unserializing " + std::to_string( sz ) + " units" ); + ASSERT( m_unprocessed_units.empty(), "unprocessed units not empty" ); + for ( size_t i = 0 ; i < sz ; i++ ) { + const auto unit_id = buf.ReadInt(); + auto b = Buffer( buf.ReadString() ); + m_unprocessed_units.push_back( unit::Unit::Unserialize( b ) ); + } + unit::Unit::SetNextId( buf.ReadInt() ); + Log( "Restored next unit id: " + std::to_string( unit::Unit::GetNextId() ) ); +} + void Game::AddEvent( const Event& event ) { Log( "Sending event (type=" + std::to_string( event.type ) + ")" ); m_pending_events->push_back( event ); @@ -1008,13 +1058,25 @@ void Game::InitGame( MT_Response& response, MT_CANCELABLE ) { connection->GlobalMessage( player->GetFullName() + " left the game." ); }; - connection->m_on_map_request = [ this ]() -> const std::string { + connection->m_on_download_request = [ this ]() -> const std::string { if ( !m_map ) { // map not generated yet return ""; } - Log( "Snapshotting map for download" ); - return m_map->SaveToBuffer().ToString(); + Log( "Preparing snapshot for download" ); + types::Buffer buf; + + // map + m_map->SaveToBuffer( buf ); + + // units + { + types::Buffer b; + SerializeUnits( b ); + buf.WriteString( b.ToString() ); + } + + return buf.ToString(); }; connection->SetGameState( Connection::GS_INITIALIZING ); @@ -1149,26 +1211,35 @@ void Game::InitGame( MT_Response& response, MT_CANCELABLE ) { const auto f_download_map = [ this, ui, connection ] { - ui->SetLoaderText( "Downloading map" ); + ui->SetLoaderText( "Downloading world snapshot" ); - connection->m_on_map_progress = [ ui ]( const float progress ) -> void { - ui->SetLoaderText( "Downloading map: " + std::to_string( (size_t)std::round( progress * 100 ) ) + "%" ); + connection->m_on_download_progress = [ ui ]( const float progress ) -> void { + ui->SetLoaderText( "Downloading world snapshot: " + std::to_string( (size_t)std::round( progress * 100 ) ) + "%" ); }; - connection->m_on_map_data = [ this, connection ]( const std::string serialized_tiles ) -> void { - connection->m_on_map_data = nullptr; - connection->m_on_map_progress = nullptr; - Log( "Unpacking map" ); + connection->m_on_download_complete = [ this, connection ]( const std::string serialized_snapshot ) -> void { + connection->m_on_download_complete = nullptr; + connection->m_on_download_progress = nullptr; + Log( "Unpacking world snapshot" ); + auto buf = types::Buffer( serialized_snapshot ); + + // map + auto b = types::Buffer( buf.ReadString() ); NEW( m_map, map::Map, this ); - const auto ec = m_map->LoadFromBuffer( serialized_tiles ); + const auto ec = m_map->LoadFromBuffer( b ); if ( ec == map::Map::EC_NONE ) { + + // units + auto b = types::Buffer( buf.ReadString() ); + UnserializeUnits( b ); + m_game_state = GS_INITIALIZING; } else { - Log( "WARNING: failed to unpack map (code=" + std::to_string( ec ) + ")" ); - connection->Disconnect( "Map format mismatch" ); + Log( "WARNING: failed to unpack world snapshot (code=" + std::to_string( ec ) + ")" ); + connection->Disconnect( "Snapshot format mismatch" ); } }; - connection->RequestMap(); + connection->RequestDownload(); }; if ( connection->GetGameState() == Connection::GS_RUNNING ) { // server already initialized @@ -1202,6 +1273,11 @@ void Game::ResetGame() { m_slot_num = 0; m_slot = nullptr; + for ( auto& it : m_unprocessed_units ) { + delete it; + } + m_unprocessed_units.clear(); + for ( auto& it : m_unprocessed_events ) { delete it; } diff --git a/src/game/Game.h b/src/game/Game.h index c2ae3e9a..3090f1cd 100644 --- a/src/game/Game.h +++ b/src/game/Game.h @@ -264,6 +264,7 @@ CLASS( Game, MTModule ) void AddUnitDef( const std::string& name, const unit::Def* def, gse::Context* ctx, const gse::si_t& si ); const unit::Def* GetUnitDef( const std::string& name ) const; const gse::Value AddGameEvent( const event::Event* event, gse::Context* ctx, const gse::si_t& si ); + void DefineUnit( const unit::Def* def ); void SpawnUnit( unit::Unit* unit ); void DespawnUnit( const size_t unit_id ); @@ -273,6 +274,8 @@ CLASS( Game, MTModule ) std::unordered_map< std::string, const unit::Def* > m_unit_defs = {}; std::map< size_t, unit::Unit* > m_units = {}; + void SerializeUnits( types::Buffer& buf ) const; + void UnserializeUnits( types::Buffer& buf ); enum game_state_t { GS_NONE, @@ -310,6 +313,8 @@ CLASS( Game, MTModule ) bindings::Bindings* m_bindings = nullptr; std::vector< const game::event::Event* > m_unprocessed_events = {}; + std::vector< unit::Unit* > m_unprocessed_units = {}; + Turn* m_current_turn = nullptr; }; diff --git a/src/game/bindings/Units.cpp b/src/game/bindings/Units.cpp index c0cac95d..cfd951f8 100644 --- a/src/game/bindings/Units.cpp +++ b/src/game/bindings/Units.cpp @@ -7,8 +7,9 @@ #include "game/unit/StaticDef.h" #include "game/unit/SpriteRender.h" -#include "../event/SpawnUnit.h" -#include "../event/DespawnUnit.h" +#include "game/event/DefineUnit.h" +#include "game/event/SpawnUnit.h" +#include "game/event/DespawnUnit.h" namespace game { namespace bindings { @@ -37,8 +38,7 @@ BINDING_IMPL( units ) { name, new unit::SpriteRender( sprite_file, sprite_x, sprite_y, sprite_w, sprite_h, sprite_cx, sprite_cy ) ); - m_game->AddUnitDef( name, def, ctx, call_si ); - return def->Wrap(); + return m_game->AddGameEvent( new event::DefineUnit( def ), ctx, call_si ); } else { ERROR( gse::EC.GAME_ERROR, "Unsupported render type: " + render_type ); @@ -54,9 +54,9 @@ BINDING_IMPL( units ) { "spawn", NATIVE_CALL( this ) { N_EXPECT_ARGS( 2 ); - N_GETVALUE( def, 0, String ); + N_GETVALUE( def_name, 0, String ); N_UNWRAP( tile, 1, map::Tile ); - return m_game->AddGameEvent( new event::SpawnUnit( def, tile->coord.x, tile->coord.y ), ctx, call_si ); + return m_game->AddGameEvent( new event::SpawnUnit( def_name, tile->coord.x, tile->coord.y ), ctx, call_si ); }) }, { diff --git a/src/game/connection/Client.cpp b/src/game/connection/Client.cpp index f292f797..2f5ea0ef 100644 --- a/src/game/connection/Client.cpp +++ b/src/game/connection/Client.cpp @@ -157,58 +157,58 @@ void Client::ProcessEvent( const network::Event& event ) { } break; } - case Packet::PT_MAP_HEADER: { - Log( "Got map data header" ); - if ( !m_map_download_state.is_downloading ) { - Error( "map header received while not downloading" ); + case Packet::PT_DOWNLOAD_RESPONSE: { + Log( "Got download response" ); + if ( !m_download_state.is_downloading ) { + Error( "download response received while not downloading" ); } if ( packet.data.num == 0 ) { - Log( "No map received from server" ); - Disconnect( "No map received from server" ); + Log( "No download response received from server" ); + Disconnect( "No download response received from server" ); } else { - m_map_download_state.total_size = packet.data.num; - Log( "Allocating map buffer (" + std::to_string( m_map_download_state.total_size ) + " bytes)" ); - m_map_download_state.buffer.reserve( m_map_download_state.total_size ); - RequestNextMapChunk(); + m_download_state.total_size = packet.data.num; + Log( "Allocating download buffer (" + std::to_string( m_download_state.total_size ) + " bytes)" ); + m_download_state.buffer.reserve( m_download_state.total_size ); + DownloadNextChunk(); } break; } - case Packet::PT_MAP_CHUNK: { - Log( "Got map chunk ( offset=" + std::to_string( packet.udata.map.offset ) + " size=" + std::to_string( packet.udata.map.size ) + " )" ); - const size_t end = packet.udata.map.offset + packet.udata.map.size; - if ( !m_map_download_state.is_downloading ) { - Error( "map chunk received while not downloading" ); + case Packet::PT_DOWNLOAD_NEXT_CHUNK_RESPONSE: { + Log( "Downloaded next chunk ( offset=" + std::to_string( packet.udata.download.offset ) + " size=" + std::to_string( packet.udata.download.size ) + " )" ); + const size_t end = packet.udata.download.offset + packet.udata.download.size; + if ( !m_download_state.is_downloading ) { + Error( "chunk received while not downloading" ); } - else if ( end > m_map_download_state.total_size ) { - Error( "map chunk overflow ( " + std::to_string( packet.udata.map.offset ) + " + " + std::to_string( packet.udata.map.size ) + " >= " + std::to_string( m_map_download_state.total_size ) + " )" ); + else if ( end > m_download_state.total_size ) { + Error( "chunk overflow ( " + std::to_string( packet.udata.download.offset ) + " + " + std::to_string( packet.udata.download.size ) + " >= " + std::to_string( m_download_state.total_size ) + " )" ); } - else if ( packet.udata.map.offset != m_map_download_state.downloaded_size ) { - Error( "inconsistent map chunk offset ( " + std::to_string( packet.udata.map.offset ) + " != " + std::to_string( m_map_download_state.downloaded_size ) + " )" ); + else if ( packet.udata.download.offset != m_download_state.downloaded_size ) { + Error( "inconsistent chunk offset ( " + std::to_string( packet.udata.download.offset ) + " != " + std::to_string( m_download_state.downloaded_size ) + " )" ); } else if ( - packet.udata.map.size != MAP_DOWNLOAD_CHUNK_SIZE && - end != m_map_download_state.total_size // last chunk can be smaller + packet.udata.download.size != DOWNLOAD_CHUNK_SIZE && + end != m_download_state.total_size // last chunk can be smaller ) { Error( "inconsistent map chunk size ( " ); } else { - ASSERT( packet.data.str.size() == packet.udata.map.size, "map download buffer size mismatch" ); - m_map_download_state.buffer.append( packet.data.str ); - if ( end < m_map_download_state.total_size ) { - if ( m_on_map_progress ) { - m_on_map_progress( (float)m_map_download_state.downloaded_size / m_map_download_state.total_size ); + ASSERT( packet.data.str.size() == packet.udata.download.size, "download buffer size mismatch" ); + m_download_state.buffer.append( packet.data.str ); + if ( end < m_download_state.total_size ) { + if ( m_on_download_progress ) { + m_on_download_progress( (float)m_download_state.downloaded_size / m_download_state.total_size ); } - m_map_download_state.downloaded_size = end; - RequestNextMapChunk(); + m_download_state.downloaded_size = end; + DownloadNextChunk(); } else { - Log( "Map downloaded successfully" ); - if ( m_on_map_data ) { - m_on_map_data( m_map_download_state.buffer ); + Log( "Download completed successfully" ); + if ( m_on_download_complete ) { + m_on_download_complete( m_download_state.buffer ); } - m_map_download_state.buffer.clear(); - m_map_download_state.is_downloading = false; + m_download_state.buffer.clear(); + m_download_state.is_downloading = false; } } break; @@ -288,12 +288,12 @@ const Connection::game_state_t Client::GetGameState() const { return m_game_state; } -void Client::RequestMap() { - Log( "Requesting map from server" ); - ASSERT( !m_map_download_state.is_downloading, "map already being downloaded" ); - ASSERT( m_on_map_data, "map download requested but m_on_map_data is not set" ); - m_map_download_state.is_downloading = true; - Packet p( Packet::PT_GET_MAP_HEADER ); +void Client::RequestDownload() { + Log( "Requesting download from server" ); + ASSERT( !m_download_state.is_downloading, "download already started" ); + ASSERT( m_on_download_complete, "download requested but m_on_download_complete is not set" ); + m_download_state.is_downloading = true; + Packet p( Packet::PT_DOWNLOAD_REQUEST ); m_network->MT_SendPacket( p ); } @@ -301,8 +301,8 @@ void Client::ResetHandlers() { Connection::ResetHandlers(); m_on_players_list_update = nullptr; m_on_game_state_change = nullptr; - m_on_map_progress = nullptr; - m_on_map_data = nullptr; + m_on_download_progress = nullptr; + m_on_download_complete = nullptr; } void Client::Error( const std::string& reason ) { @@ -310,15 +310,15 @@ void Client::Error( const std::string& reason ) { Disconnect( "Network protocol error" ); } -void Client::RequestNextMapChunk() { - ASSERT( m_map_download_state.is_downloading, "map download not initialized" ); - ASSERT( m_map_download_state.buffer.size() == m_map_download_state.downloaded_size, "map buffer size mismatch" ); - ASSERT( m_map_download_state.downloaded_size < m_map_download_state.total_size, "map already downloaded" ); - const size_t size = std::min( MAP_DOWNLOAD_CHUNK_SIZE, m_map_download_state.total_size - m_map_download_state.downloaded_size ); - Log( "Requesting map chunk ( offset=" + std::to_string( m_map_download_state.downloaded_size ) + " size=" + std::to_string( size ) + " )" ); - Packet p( Packet::PT_GET_MAP_CHUNK ); - p.udata.map.offset = m_map_download_state.downloaded_size; - p.udata.map.size = size; +void Client::DownloadNextChunk() { + ASSERT( m_download_state.is_downloading, "download not initialized" ); + ASSERT( m_download_state.buffer.size() == m_download_state.downloaded_size, "download buffer size mismatch" ); + ASSERT( m_download_state.downloaded_size < m_download_state.total_size, "download already finished" ); + const size_t size = std::min( DOWNLOAD_CHUNK_SIZE, m_download_state.total_size - m_download_state.downloaded_size ); + Log( "Requesting next chunk ( offset=" + std::to_string( m_download_state.downloaded_size ) + " size=" + std::to_string( size ) + " )" ); + Packet p( Packet::PT_DOWNLOAD_NEXT_CHUNK_REQUEST ); + p.udata.download.offset = m_download_state.downloaded_size; + p.udata.download.size = size; m_network->MT_SendPacket( p ); } diff --git a/src/game/connection/Client.h b/src/game/connection/Client.h index 339f95da..573f6b49 100644 --- a/src/game/connection/Client.h +++ b/src/game/connection/Client.h @@ -11,14 +11,14 @@ CLASS( Client, Connection ) std::function< void() > m_on_players_list_update = nullptr; std::function< void( const game_state_t game_state ) > m_on_game_state_change = nullptr; - std::function< void( const float progress ) > m_on_map_progress = nullptr; // progress is from 0.0f to 1.0f - std::function< void( const std::string serialized_tiles ) > m_on_map_data = nullptr; + std::function< void( const float progress ) > m_on_download_progress = nullptr; // progress is from 0.0f to 1.0f + std::function< void( const std::string serialized_tiles ) > m_on_download_complete = nullptr; void UpdateSlot( const size_t slot_num, Slot* slot, const bool only_flags = false ) override; void SendMessage( const std::string& message ) override; const game_state_t GetGameState() const; - void RequestMap(); + void RequestDownload(); void ResetHandlers() override; @@ -36,8 +36,8 @@ CLASS( Client, Connection ) int total_size = 0; int downloaded_size = 0; std::string buffer = ""; - } m_map_download_state = {}; - void RequestNextMapChunk(); + } m_download_state = {}; + void DownloadNextChunk(); }; } diff --git a/src/game/connection/Connection.cpp b/src/game/connection/Connection.cpp index e3bc40eb..0833f645 100644 --- a/src/game/connection/Connection.cpp +++ b/src/game/connection/Connection.cpp @@ -21,6 +21,7 @@ void Connection::ResetHandlers() { m_on_flags_update = nullptr; m_on_message = nullptr; m_on_global_settings_update = nullptr; + m_on_game_event = nullptr; if ( m_mt_ids.events ) { m_network->MT_Cancel( m_mt_ids.events ); m_mt_ids.events = 0; diff --git a/src/game/connection/Connection.h b/src/game/connection/Connection.h index cd449cda..0c1116ec 100644 --- a/src/game/connection/Connection.h +++ b/src/game/connection/Connection.h @@ -71,7 +71,7 @@ CLASS( Connection, base::Module ) virtual void SendMessage( const std::string& message ) = 0; protected: - const int MAP_DOWNLOAD_CHUNK_SIZE = 16384; + const int DOWNLOAD_CHUNK_SIZE = 16384; network::Network* const m_network = g_engine->GetNetwork(); diff --git a/src/game/connection/Server.cpp b/src/game/connection/Server.cpp index 30f40eaf..92bf8b35 100644 --- a/src/game/connection/Server.cpp +++ b/src/game/connection/Server.cpp @@ -74,9 +74,9 @@ void Server::ProcessEvent( const network::Event& event ) { m_state->RemovePlayer( player ); // cleanup - const auto& map_data_it = m_map_data.find( event.cid ); - if ( map_data_it != m_map_data.end() ) { - m_map_data.erase( map_data_it ); + const auto& download_data_it = m_download_data.find( event.cid ); + if ( download_data_it != m_download_data.end() ) { + m_download_data.erase( download_data_it ); } ASSERT( m_game_state != GS_NONE, "player disconnected but game state is not set" ); @@ -260,56 +260,56 @@ void Server::ProcessEvent( const network::Event& event ) { GlobalMessage( FormatChatMessage( m_state->m_slots.GetSlot( it->second ).GetPlayer(), packet.data.str ) ); break; } - case Packet::PT_GET_MAP_HEADER: { - Log( "Got map header request from " + std::to_string( event.cid ) ); - Packet p( types::Packet::PT_MAP_HEADER ); - if ( m_on_map_request ) { - m_map_data[ event.cid ] = map_data_t{ // override previous request + case Packet::PT_DOWNLOAD_REQUEST: { + Log( "Got download request from " + std::to_string( event.cid ) ); + Packet p( types::Packet::PT_DOWNLOAD_RESPONSE ); + if ( m_on_download_request ) { + m_download_data[ event.cid ] = download_data_t{ // override previous request 0, - m_on_map_request() + m_on_download_request() }; - p.data.num = m_map_data.at( event.cid ).serialized_tiles.size(); + p.data.num = m_download_data.at( event.cid ).serialized_snapshot.size(); } else { - // no handler set - no map to return - Log( "WARNING: map requested but no map handler was set, sending empty header" ); + // no handler set - no data to return + Log( "WARNING: download requested but no download handler was set, sending empty header" ); p.data.num = 0; } m_network->MT_SendPacket( p, event.cid ); break; } - case Packet::PT_GET_MAP_CHUNK: { - Log( "Got map chunk request from " + std::to_string( event.cid ) + " ( offset=" + std::to_string( packet.udata.map.offset ) + " size=" + std::to_string( packet.udata.map.size ) + " )" ); - const auto& it = m_map_data.find( event.cid ); - const size_t end = packet.udata.map.offset + packet.udata.map.size; - if ( it == m_map_data.end() ) { - Error( event.cid, "map download not initialized" ); + case Packet::PT_DOWNLOAD_NEXT_CHUNK_REQUEST: { + Log( "Got next chunk request from " + std::to_string( event.cid ) + " ( offset=" + std::to_string( packet.udata.download.offset ) + " size=" + std::to_string( packet.udata.download.size ) + " )" ); + const auto& it = m_download_data.find( event.cid ); + const size_t end = packet.udata.download.offset + packet.udata.download.size; + if ( it == m_download_data.end() ) { + Error( event.cid, "download not initialized" ); } - else if ( end > it->second.serialized_tiles.size() ) { - Error( event.cid, "map request overflow ( " + std::to_string( packet.udata.map.offset ) + " + " + std::to_string( packet.udata.map.size ) + " >= " + std::to_string( it->second.serialized_tiles.size() ) + " )" ); + else if ( end > it->second.serialized_snapshot.size() ) { + Error( event.cid, "download offset overflow ( " + std::to_string( packet.udata.download.offset ) + " + " + std::to_string( packet.udata.download.size ) + " >= " + std::to_string( it->second.serialized_snapshot.size() ) + " )" ); } - else if ( packet.udata.map.offset != it->second.next_expected_offset ) { - Error( event.cid, "inconsistent map download offset ( " + std::to_string( packet.udata.map.offset ) + " != " + std::to_string( it->second.next_expected_offset ) + " )" ); + else if ( packet.udata.download.offset != it->second.next_expected_offset ) { + Error( event.cid, "inconsistent download offset ( " + std::to_string( packet.udata.download.offset ) + " != " + std::to_string( it->second.next_expected_offset ) + " )" ); } else if ( - packet.udata.map.size != MAP_DOWNLOAD_CHUNK_SIZE && - end != it->second.serialized_tiles.size() // last chunk can be smaller + packet.udata.download.size != DOWNLOAD_CHUNK_SIZE && + end != it->second.serialized_snapshot.size() // last chunk can be smaller ) { - Error( event.cid, "inconsistent map download size ( " ); + Error( event.cid, "inconsistent download size ( " ); } else { - Packet p( Packet::PT_MAP_CHUNK ); - p.udata.map.offset = packet.udata.map.offset; - p.udata.map.size = packet.udata.map.size; - p.data.str = it->second.serialized_tiles.substr( packet.udata.map.offset, packet.udata.map.size ); + Packet p( Packet::PT_DOWNLOAD_NEXT_CHUNK_RESPONSE ); + p.udata.download.offset = packet.udata.download.offset; + p.udata.download.size = packet.udata.download.size; + p.data.str = it->second.serialized_snapshot.substr( packet.udata.download.offset, packet.udata.download.size ); m_network->MT_SendPacket( p, event.cid ); - if ( end < it->second.serialized_tiles.size() ) { + if ( end < it->second.serialized_snapshot.size() ) { it->second.next_expected_offset = end; } else { - // map was sent fully, can free memory now - Log( "Map was sent successfully to " + std::to_string( event.cid ) + ", cleaning up" ); - m_map_data.erase( it ); + // snapshot was sent fully, can free memory now + Log( "Snapshot was sent successfully to " + std::to_string( event.cid ) + ", cleaning up" ); + m_download_data.erase( it ); } } break; @@ -425,7 +425,7 @@ void Server::SendMessage( const std::string& message ) { void Server::ResetHandlers() { Connection::ResetHandlers(); m_on_listen = nullptr; - m_on_map_request = nullptr; + m_on_download_request = nullptr; } void Server::UpdateGameSettings() { diff --git a/src/game/connection/Server.h b/src/game/connection/Server.h index 8ec44979..ae7cf394 100644 --- a/src/game/connection/Server.h +++ b/src/game/connection/Server.h @@ -13,7 +13,7 @@ CLASS( Server, Connection ) Server( LocalSettings* const settings ); std::function< void() > m_on_listen = nullptr; - std::function< const std::string() > m_on_map_request = nullptr; // return serialized Tiles + std::function< const std::string() > m_on_download_request = nullptr; // return serialized snapshot of world void UpdateSlot( const size_t slot_num, Slot* slot, const bool only_flags = false ) override; void SendMessage( const std::string& message ) override; @@ -43,11 +43,11 @@ CLASS( Server, Connection ) const std::string FormatChatMessage( const Player* player, const std::string& message ) const; void SendGameEventsTo( const std::string& serialized_events, const network::cid_t cid ); - struct map_data_t { + struct download_data_t { size_t next_expected_offset = 0; // for extra consistency checks - std::string serialized_tiles = ""; + std::string serialized_snapshot = ""; }; - std::unordered_map< network::cid_t, map_data_t > m_map_data = {}; // cid -> serialized tiles + std::unordered_map< network::cid_t, download_data_t > m_download_data = {}; // cid -> serialized snapshot of world void ClearReadyFlags(); }; diff --git a/src/game/event/CMakeLists.txt b/src/game/event/CMakeLists.txt index 1dbd8c4c..aabd9d79 100644 --- a/src/game/event/CMakeLists.txt +++ b/src/game/event/CMakeLists.txt @@ -1,6 +1,7 @@ SET( SRC ${SRC} ${PWD}/Event.cpp + ${PWD}/DefineUnit.cpp ${PWD}/SpawnUnit.cpp ${PWD}/DespawnUnit.cpp diff --git a/src/game/event/DefineUnit.cpp b/src/game/event/DefineUnit.cpp new file mode 100644 index 00000000..da26004b --- /dev/null +++ b/src/game/event/DefineUnit.cpp @@ -0,0 +1,29 @@ +#include "DefineUnit.h" + +#include "../Game.h" + +namespace game { +namespace event { + +DefineUnit::DefineUnit( const unit::Def* def ) + : Event( ET_UNIT_DEFINE ) + , m_def( def ) { + // +} + +const gse::Value DefineUnit::Apply( game::Game* game ) const { + game->DefineUnit( m_def ); + return m_def->Wrap(); +} + +void DefineUnit::Serialize( types::Buffer& buf, const DefineUnit* event ) { + buf.WriteString( unit::Def::Serialize( event->m_def ).ToString() ); +} + +DefineUnit* DefineUnit::Unserialize( types::Buffer& buf ) { + auto b = types::Buffer( buf.ReadString() ); + return new DefineUnit( unit::Def::Unserialize( b ) ); +} + +} +} diff --git a/src/game/event/DefineUnit.h b/src/game/event/DefineUnit.h new file mode 100644 index 00000000..ae32cfa2 --- /dev/null +++ b/src/game/event/DefineUnit.h @@ -0,0 +1,27 @@ +#pragma once + +#include "Event.h" + +#include "game/unit/Def.h" + +namespace game { +namespace event { + +class DefineUnit : public Event { +public: + DefineUnit( const unit::Def* def ); + + const gse::Value Apply( game::Game* game ) const override; + +private: + friend class Event; + + static void Serialize( types::Buffer& buf, const DefineUnit* event ); + static DefineUnit* Unserialize( types::Buffer& buf ); + +private: + const unit::Def* m_def; +}; + +} +} diff --git a/src/game/event/Event.cpp b/src/game/event/Event.cpp index faeb550e..288f529e 100644 --- a/src/game/event/Event.cpp +++ b/src/game/event/Event.cpp @@ -1,5 +1,6 @@ #include "Event.h" +#include "DefineUnit.h" #include "SpawnUnit.h" #include "DespawnUnit.h" @@ -15,6 +16,10 @@ const types::Buffer Event::Serialize( const Event* event ) { types::Buffer buf; buf.WriteInt( event->m_type ); switch ( event->m_type ) { + case ET_UNIT_DEFINE: { + DefineUnit::Serialize( buf, (DefineUnit*)event ); + break; + } case ET_UNIT_SPAWN: { SpawnUnit::Serialize( buf, (SpawnUnit*)event ); break; @@ -32,6 +37,8 @@ const types::Buffer Event::Serialize( const Event* event ) { Event* Event::Unserialize( types::Buffer& buf ) { const auto type = buf.ReadInt(); switch ( type ) { + case ET_UNIT_DEFINE: + return DefineUnit::Unserialize( buf ); case ET_UNIT_SPAWN: return SpawnUnit::Unserialize( buf ); case ET_UNIT_DESPAWN: diff --git a/src/game/event/Event.h b/src/game/event/Event.h index a4a85dc1..4c98acff 100644 --- a/src/game/event/Event.h +++ b/src/game/event/Event.h @@ -11,6 +11,8 @@ namespace event { class Event { public: enum event_type_t { + ET_NONE, + ET_UNIT_DEFINE, ET_UNIT_SPAWN, ET_UNIT_DESPAWN, }; diff --git a/src/game/map/Map.cpp b/src/game/map/Map.cpp index ff91a713..daba6ef4 100644 --- a/src/game/map/Map.cpp +++ b/src/game/map/Map.cpp @@ -637,7 +637,7 @@ const Map::error_code_t Map::Generate( return EC_NONE; } -const Map::error_code_t Map::LoadFromBuffer( Buffer buffer ) { +const Map::error_code_t Map::LoadFromBuffer( Buffer& buffer ) { if ( m_tiles ) { DELETE( m_tiles ); } @@ -647,6 +647,7 @@ const Map::error_code_t Map::LoadFromBuffer( Buffer buffer ) { return EC_NONE; } catch ( std::runtime_error& e ) { + Log( e.what() ); DELETE( m_tiles ); m_tiles = nullptr; return EC_MAPFILE_FORMAT_ERROR; @@ -657,17 +658,17 @@ const Map::error_code_t Map::LoadFromFile( const std::string& path ) { ASSERT( FS::FileExists( path ), "map file \"" + path + "\" not found" ); Log( "Loading map from " + path ); - return LoadFromBuffer( FS::ReadFile( path ) ); + auto b = types::Buffer( FS::ReadFile( path ) ); + return LoadFromBuffer( b ); } -const Buffer Map::SaveToBuffer() const { - return m_tiles->Serialize(); +void Map::SaveToBuffer( Buffer& buffer ) const { + buffer.WriteString( m_tiles->Serialize().ToString() ); } const Map::error_code_t Map::SaveToFile( const std::string& path ) const { try { - Buffer buffer = SaveToBuffer(); - FS::WriteFile( path, buffer.ToString() ); + FS::WriteFile( path, m_tiles->Serialize().ToString() ); return EC_NONE; } catch ( std::runtime_error& e ) { diff --git a/src/game/map/Map.h b/src/game/map/Map.h index 64b6abab..d232e608 100644 --- a/src/game/map/Map.h +++ b/src/game/map/Map.h @@ -52,9 +52,9 @@ CLASS( Map, types::Serializable ) #endif , MT_CANCELABLE ); - const error_code_t LoadFromBuffer( Buffer buffer ); + const error_code_t LoadFromBuffer( Buffer& buffer ); const error_code_t LoadFromFile( const std::string& path ); - const Buffer SaveToBuffer() const; + void SaveToBuffer( Buffer& buffer ) const; const error_code_t SaveToFile( const std::string& path ) const; const error_code_t Initialize( MT_CANCELABLE ); diff --git a/src/game/unit/Unit.cpp b/src/game/unit/Unit.cpp index 57fe9f0a..c3f32190 100644 --- a/src/game/unit/Unit.cpp +++ b/src/game/unit/Unit.cpp @@ -11,6 +11,9 @@ static size_t next_id = 1; const size_t Unit::GetNextId() { return next_id; } +const void Unit::SetNextId( const size_t id ) { + next_id = id; +} Unit::Unit( const size_t id, const Def* def, const size_t pos_x, const size_t pos_y ) : m_id( id ) diff --git a/src/game/unit/Unit.h b/src/game/unit/Unit.h index 5ba06817..3b387dca 100644 --- a/src/game/unit/Unit.h +++ b/src/game/unit/Unit.h @@ -13,6 +13,7 @@ class Unit { public: static const size_t GetNextId(); + static const void SetNextId( const size_t id ); Unit( const size_t id, const Def* def, const size_t pos_x, const size_t pos_y ); virtual ~Unit() = default; diff --git a/src/types/Packet.cpp b/src/types/Packet.cpp index afd8f28d..87ec34a0 100644 --- a/src/types/Packet.cpp +++ b/src/types/Packet.cpp @@ -56,23 +56,23 @@ const Buffer Packet::Serialize() const { buf.WriteInt( udata.game_state.state ); break; } - case PT_GET_MAP_HEADER: { + case PT_DOWNLOAD_REQUEST: { // no data break; } - case PT_MAP_HEADER: { + case PT_DOWNLOAD_RESPONSE: { buf.WriteInt( data.num ); // total size of serialized data break; } - case PT_GET_MAP_CHUNK: { - buf.WriteInt( udata.map.offset ); - buf.WriteInt( udata.map.size ); + case PT_DOWNLOAD_NEXT_CHUNK_REQUEST: { + buf.WriteInt( udata.download.offset ); + buf.WriteInt( udata.download.size ); break; } - case PT_MAP_CHUNK: { - buf.WriteInt( udata.map.offset ); - buf.WriteInt( udata.map.size ); - buf.WriteString( data.str ); // serialized tiles part + case PT_DOWNLOAD_NEXT_CHUNK_RESPONSE: { + buf.WriteInt( udata.download.offset ); + buf.WriteInt( udata.download.size ); + buf.WriteString( data.str ); // serialized chunk break; } case PT_GAME_EVENTS: { @@ -140,23 +140,23 @@ void Packet::Unserialize( Buffer buf ) { udata.game_state.state = buf.ReadInt(); break; } - case PT_GET_MAP_HEADER: { + case PT_DOWNLOAD_REQUEST: { // no data break; } - case PT_MAP_HEADER: { + case PT_DOWNLOAD_RESPONSE: { data.num = buf.ReadInt(); // total size of serialized data break; } - case PT_GET_MAP_CHUNK: { - udata.map.offset = buf.ReadInt(); - udata.map.size = buf.ReadInt(); + case PT_DOWNLOAD_NEXT_CHUNK_REQUEST: { + udata.download.offset = buf.ReadInt(); + udata.download.size = buf.ReadInt(); break; } - case PT_MAP_CHUNK: { - udata.map.offset = buf.ReadInt(); - udata.map.size = buf.ReadInt(); - data.str = buf.ReadString(); // serialized tiles part + case PT_DOWNLOAD_NEXT_CHUNK_RESPONSE: { + udata.download.offset = buf.ReadInt(); + udata.download.size = buf.ReadInt(); + data.str = buf.ReadString(); // serialized chunk break; } case PT_GAME_EVENTS: { diff --git a/src/types/Packet.h b/src/types/Packet.h index 800eb638..5b34ced2 100644 --- a/src/types/Packet.h +++ b/src/types/Packet.h @@ -23,10 +23,10 @@ CLASS( Packet, Serializable ) PT_KICK, // S->C PT_MESSAGE, // *->* PT_GAME_STATE, // S->C - PT_GET_MAP_HEADER, // C->S - PT_MAP_HEADER, // S->C - PT_GET_MAP_CHUNK, // C->S - PT_MAP_CHUNK, // S-> + PT_DOWNLOAD_REQUEST, // C->S + PT_DOWNLOAD_RESPONSE, // S->C + PT_DOWNLOAD_NEXT_CHUNK_REQUEST, // C->S + PT_DOWNLOAD_NEXT_CHUNK_RESPONSE, // S->C PT_GAME_EVENTS, // *->* }; @@ -49,7 +49,7 @@ CLASS( Packet, Serializable ) struct { size_t offset; size_t size; - } map; + } download; } udata; // TODO: move this into udata