Skip to content

Commit

Permalink
Merge branch 'main' into stable
Browse files Browse the repository at this point in the history
  • Loading branch information
afwbkbc committed Feb 15, 2024
2 parents 4b04eca + dab7fab commit 85eebe1
Show file tree
Hide file tree
Showing 24 changed files with 484 additions and 298 deletions.
24 changes: 11 additions & 13 deletions gse/default/main.gls.js
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -44,8 +45,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++;
Expand All @@ -57,9 +57,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());
}
});
20 changes: 20 additions & 0 deletions gse/tests/functions.gls.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
114 changes: 95 additions & 19 deletions src/game/Game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
}
Expand Down Expand Up @@ -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 {
Expand All @@ -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 );

Expand Down Expand Up @@ -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 );
Expand Down Expand Up @@ -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 );
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
}
Expand Down
5 changes: 5 additions & 0 deletions src/game/Game.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 );

Expand All @@ -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,
Expand Down Expand Up @@ -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;

};
Expand Down
12 changes: 6 additions & 6 deletions src/game/bindings/Units.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 );
Expand All @@ -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 );
})
},
{
Expand Down
Loading

0 comments on commit 85eebe1

Please sign in to comment.