[Widelands-dev] [Merge] lp:~widelands-dev/widelands/bug-better-syncstreams into lp:widelands

2019-02-12 Thread noreply
The proposal to merge lp:~widelands-dev/widelands/bug-better-syncstreams into 
lp:widelands has been updated.

Status: Needs review => Merged

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/bug-better-syncstreams/+merge/361922
-- 
Your team Widelands Developers is subscribed to branch 
lp:~widelands-dev/widelands/bug-better-syncstreams.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands/bug-better-syncstreams into lp:widelands

2019-02-11 Thread GunChleoc
Looks good to me, let's have it!

@bunnybot merge
-- 
https://code.launchpad.net/~widelands-dev/widelands/bug-better-syncstreams/+merge/361922
Your team Widelands Developers is subscribed to branch 
lp:~widelands-dev/widelands/bug-better-syncstreams.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands/bug-better-syncstreams into lp:widelands

2019-02-10 Thread GunChleoc
I have done some similar testing. I'd like to see a few changes:

1. WLApplication:cleanup_replays() does not clean up old wse files
2. There are no instructions in the Python script.
   I'd like to at least see a usage hint when it's called without parameters.
-- 
https://code.launchpad.net/~widelands-dev/widelands/bug-better-syncstreams/+merge/361922
Your team Widelands Developers is subscribed to branch 
lp:~widelands-dev/widelands/bug-better-syncstreams.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands/bug-better-syncstreams into lp:widelands

2019-02-10 Thread Notabilis
I tested(?) it by enforcing a desync (modifying player.cc and using std::rand() 
as ID for new economies, then changing economy targets ingame). The new *.wse 
files were created and could be parsed by the python script. No idea what else 
can be tested.
-- 
https://code.launchpad.net/~widelands-dev/widelands/bug-better-syncstreams/+merge/361922
Your team Widelands Developers is subscribed to branch 
lp:~widelands-dev/widelands/bug-better-syncstreams.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands/bug-better-syncstreams into lp:widelands

2019-02-09 Thread GunChleoc
Review: Approve

Code LGTM, not tested
-- 
https://code.launchpad.net/~widelands-dev/widelands/bug-better-syncstreams/+merge/361922
Your team Widelands Developers is subscribed to branch 
lp:~widelands-dev/widelands/bug-better-syncstreams.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands/bug-better-syncstreams into lp:widelands

2019-02-09 Thread Notabilis
As far as I am concerned, this branch is ready for review and merge now.
-- 
https://code.launchpad.net/~widelands-dev/widelands/bug-better-syncstreams/+merge/361922
Your team Widelands Developers is requested to review the proposed merge of 
lp:~widelands-dev/widelands/bug-better-syncstreams into lp:widelands.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


[Widelands-dev] [Merge] lp:~widelands-dev/widelands/bug-better-syncstreams into lp:widelands

2019-02-09 Thread Notabilis
The proposal to merge lp:~widelands-dev/widelands/bug-better-syncstreams into 
lp:widelands has been updated.

Description changed to:

[Ready for review and merge]

Since I am not really able to get useful information out of the existing 
syncstream files, this branch adds further information to the syncstream 
describing the type of the syncstream entries.

Additionally, create a smaller syncstream extract file next to the syncstream 
file which contains only the last few seconds. This should be enough to debug 
the desync but reduces the size of the to-be-uploaded files.

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/bug-better-syncstreams/+merge/361922
-- 
Your team Widelands Developers is requested to review the proposed merge of 
lp:~widelands-dev/widelands/bug-better-syncstreams into lp:widelands.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


[Widelands-dev] [Merge] lp:~widelands-dev/widelands/bug-better-syncstreams into lp:widelands

2019-02-09 Thread Notabilis
The proposal to merge lp:~widelands-dev/widelands/bug-better-syncstreams into 
lp:widelands has been updated.

Commit message changed to:

Print more information in syncstreams. Create additional smaller syncstream 
files containing the last few seconds leading to a desync.

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/bug-better-syncstreams/+merge/361922
-- 
Your team Widelands Developers is requested to review the proposed merge of 
lp:~widelands-dev/widelands/bug-better-syncstreams into lp:widelands.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands/bug-better-syncstreams into lp:widelands

2019-02-09 Thread GunChleoc
Answered.

Diff comments:

> 
> === modified file 'src/logic/game.cc'
> --- src/logic/game.cc 2018-12-13 07:24:01 +
> +++ src/logic/game.cc 2019-01-20 23:22:08 +
> @@ -603,6 +608,47 @@
>  }
>  
>  /**
> + * Switches to the next part of the syncstream excerpt.
> + */
> +void Game::report_sync_request() {
> + syncwrapper_.current_excerpt_id_ = (syncwrapper_.current_excerpt_id_ + 
> 1) % SyncWrapper::kExcerptSize;
> + syncwrapper_.excerpts_buffer_[syncwrapper_.current_excerpt_id_].clear();
> +}
> +
> +/**
> + * Triggers writing of syncstream excerpt and adds the playernumber of the 
> desynced player
> + * to the stream.
> + * Playernumber should be negative when called by network clients
> + */
> +void Game::report_desync(int32_t playernumber) {
> + std::string filename = syncwrapper_.dumpfname_;
> + filename.replace(filename.length() - kSyncstreamExtension.length(), 
> kSyncstreamExtension.length(), kSyncstreamExcerptExtension);

No, too complicated. Just leave it like it is.

> + std::unique_ptr file(g_fs->open_stream_write(filename));
> + assert(file != nullptr);
> + // Write revision, branch and build type of this build to the file
> + file->unsigned_32(build_id().length());
> + file->text(build_id());
> + file->unsigned_32(build_type().length());
> + file->text(build_type());
> + file->signed_32(playernumber);
> + // Write our buffers to the file. Start with the oldest one
> + const size_t i2 = (syncwrapper_.current_excerpt_id_ + 1) % 
> SyncWrapper::kExcerptSize;
> + size_t i = i2;
> + for (;;) {
> + file->text(syncwrapper_.excerpts_buffer_[i]);
> + syncwrapper_.excerpts_buffer_[i].clear();
> + i = (i + 1) % SyncWrapper::kExcerptSize;
> + if (i == i2) {
> + break;
> + }
> + }
> + file->unsigned_8(Syncstream::Desync);
> + file->signed_32(playernumber);
> + // Restart buffers
> + syncwrapper_.current_excerpt_id_ = 0;
> +}
> +
> +/**
>   * Calculate the current synchronization checksum and copy
>   * it into the given array, without affecting the subsequent
>   * checksumming process.
> 
> === modified file 'src/logic/game.h'
> --- src/logic/game.h  2018-12-13 07:24:01 +
> +++ src/logic/game.h  2019-01-20 23:22:08 +
> @@ -63,6 +63,51 @@
>   gs_ending
>  };
>  
> +// The entry types that are written to the syncstream
> +// The IDs are a number in the higher 4 bits and the length in bytes in the 
> lower 4 bits
> +namespace Syncstream {
> + // game.cc Game::report_desync()

If you're getting a nightmare of static_cast calls, you can use an enum instead 
of an enum class. Plain enum has no type safety vs. int, so you won't need to 
cast.

> + // s32 id of desynced user, -1 when written on client
> + constexpr uint8_t Desync = 0x14;
> + // map_object.cc CmdDestroyMapObject::execute()
> + // u32 object serial
> + constexpr uint8_t DestroyObject = 0x24;
> + // economy.cc Economy::process_requests()
> + // u8 request type
> + // u8 request index
> + // u32 target serial
> + constexpr uint8_t ProcessRequests = 0x36;
> + // economy.cc Economy::handle_active_supplies()
> + // u32 assignments size
> + constexpr uint8_t HandleActiveSupplies = 0x44;
> + // request.cc Request::start_transfer()
> + // u32 target serial
> + // u32 source(?) serial
> + constexpr uint8_t StartTransfer = 0x58;
> + // cmd_queue.cc CmdQueue::run_queue()
> + // u32 duetime
> + // u32 command id
> + constexpr uint8_t RunQueue = 0x68;
> + // game.h Game::logic_rand_seed()
> + // u32 random seed
> + constexpr uint8_t RandomSeed = 0x74;
> + // game.cc Game::logic_rand()
> + // u32 random value
> + constexpr uint8_t Random = 0x84;
> + // map_object.cc CmdAct::execute()
> + // u32 object serial
> + constexpr uint8_t CmdAct = 0x94;
> + // battle.cc Battle::Battle()
> + // u32 first soldier serial
> + // u32 second soldier serial
> + constexpr uint8_t Battle = 0xA8;
> + // bob.cc Bob::set_position()
> + // u32 bob serial
> + // s16 position x
> + // s16 position y
> + constexpr uint8_t BobSetPosition = 0xB8;
> +}
> +
>  class Player;
>  class MapLoader;
>  class PlayerCommand;


-- 
https://code.launchpad.net/~widelands-dev/widelands/bug-better-syncstreams/+merge/361922
Your team Widelands Developers is requested to review the proposed merge of 
lp:~widelands-dev/widelands/bug-better-syncstreams into lp:widelands.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands/bug-better-syncstreams into lp:widelands

2019-02-09 Thread Notabilis
Thanks for the review. I answered some of your comments below and will push a 
merge-ready version later on.

Diff comments:

> 
> === modified file 'src/logic/game.cc'
> --- src/logic/game.cc 2018-12-13 07:24:01 +
> +++ src/logic/game.cc 2019-01-20 23:22:08 +
> @@ -603,6 +608,47 @@
>  }
>  
>  /**
> + * Switches to the next part of the syncstream excerpt.
> + */
> +void Game::report_sync_request() {
> + syncwrapper_.current_excerpt_id_ = (syncwrapper_.current_excerpt_id_ + 
> 1) % SyncWrapper::kExcerptSize;
> + syncwrapper_.excerpts_buffer_[syncwrapper_.current_excerpt_id_].clear();
> +}
> +
> +/**
> + * Triggers writing of syncstream excerpt and adds the playernumber of the 
> desynced player
> + * to the stream.
> + * Playernumber should be negative when called by network clients
> + */
> +void Game::report_desync(int32_t playernumber) {
> + std::string filename = syncwrapper_.dumpfname_;
> + filename.replace(filename.length() - kSyncstreamExtension.length(), 
> kSyncstreamExtension.length(), kSyncstreamExcerptExtension);

That function is also stripping the directory from the path, so I would have to 
add it again as well. Do you want me to do so? Using that function might be a 
bit easier to read, apart from that I don't see any advantage.

> + std::unique_ptr file(g_fs->open_stream_write(filename));
> + assert(file != nullptr);
> + // Write revision, branch and build type of this build to the file
> + file->unsigned_32(build_id().length());
> + file->text(build_id());
> + file->unsigned_32(build_type().length());
> + file->text(build_type());
> + file->signed_32(playernumber);
> + // Write our buffers to the file. Start with the oldest one
> + const size_t i2 = (syncwrapper_.current_excerpt_id_ + 1) % 
> SyncWrapper::kExcerptSize;
> + size_t i = i2;
> + for (;;) {
> + file->text(syncwrapper_.excerpts_buffer_[i]);
> + syncwrapper_.excerpts_buffer_[i].clear();
> + i = (i + 1) % SyncWrapper::kExcerptSize;
> + if (i == i2) {

Right... I totally forgot about this loop type, thanks!

> + break;
> + }
> + }
> + file->unsigned_8(Syncstream::Desync);
> + file->signed_32(playernumber);
> + // Restart buffers
> + syncwrapper_.current_excerpt_id_ = 0;
> +}
> +
> +/**
>   * Calculate the current synchronization checksum and copy
>   * it into the given array, without affecting the subsequent
>   * checksumming process.
> 
> === modified file 'src/logic/game.h'
> --- src/logic/game.h  2018-12-13 07:24:01 +
> +++ src/logic/game.h  2019-01-20 23:22:08 +
> @@ -63,6 +63,51 @@
>   gs_ending
>  };
>  
> +// The entry types that are written to the syncstream
> +// The IDs are a number in the higher 4 bits and the length in bytes in the 
> lower 4 bits
> +namespace Syncstream {
> + // game.cc Game::report_desync()

I would like to have an enum, but that would result in explicit static_cast's 
each time one of these values is written to the syncstream, so I decided 
against it. Do you want me to change it?

> + // s32 id of desynced user, -1 when written on client
> + constexpr uint8_t Desync = 0x14;
> + // map_object.cc CmdDestroyMapObject::execute()
> + // u32 object serial
> + constexpr uint8_t DestroyObject = 0x24;
> + // economy.cc Economy::process_requests()
> + // u8 request type
> + // u8 request index
> + // u32 target serial
> + constexpr uint8_t ProcessRequests = 0x36;
> + // economy.cc Economy::handle_active_supplies()
> + // u32 assignments size
> + constexpr uint8_t HandleActiveSupplies = 0x44;
> + // request.cc Request::start_transfer()
> + // u32 target serial
> + // u32 source(?) serial
> + constexpr uint8_t StartTransfer = 0x58;
> + // cmd_queue.cc CmdQueue::run_queue()
> + // u32 duetime
> + // u32 command id
> + constexpr uint8_t RunQueue = 0x68;
> + // game.h Game::logic_rand_seed()
> + // u32 random seed
> + constexpr uint8_t RandomSeed = 0x74;
> + // game.cc Game::logic_rand()
> + // u32 random value
> + constexpr uint8_t Random = 0x84;
> + // map_object.cc CmdAct::execute()
> + // u32 object serial
> + constexpr uint8_t CmdAct = 0x94;
> + // battle.cc Battle::Battle()
> + // u32 first soldier serial
> + // u32 second soldier serial
> + constexpr uint8_t Battle = 0xA8;
> + // bob.cc Bob::set_position()
> + // u32 bob serial
> + // s16 position x
> + // s16 position y
> + 

Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands/bug-better-syncstreams into lp:widelands

2019-02-08 Thread GunChleoc
00
> +++ utils/syncstream/syncexcerpt-to-text.py   2019-01-20 23:22:08 +
> @@ -0,0 +1,99 @@
> +#!/usr/bin/env python3
> +
> +import struct
> +import sys
> +
> +# WARNING!!
> +# Keep this file in sync with namespace Syncstream in src/logic/game.h

Add a comment to game.h as well

> +
> +def handle_1(f):
> + print("Desync:")
> + # Read 4 bytes and interprete them as an signed 32 bit integer
> + print("  Desynced player:", struct.unpack(' +
> +def handle_2(f):
> + print("DestroyObject:")
> + print("  Serial:", struct.unpack(' +
> +def handle_3(f):
> + print("ProcessRequests:")
> + print("  Type:", struct.unpack(' + print("  Index:", struct.unpack(' + print("  Serial:", struct.unpack(' +
> +def handle_4(f):
> + print("HandleActiveSupplies:")
> + print("  Size:", struct.unpack(' +
> +def handle_5(f):
> + print("StartTransfer:")
> + print("  Target serial:", struct.unpack(' + print("  Source serial:", struct.unpack(' +
> +def handle_6(f):
> + print("RunQueue:")
> + print("  Duetime:", struct.unpack(' + print("  Command:", struct.unpack(' +
> +def handle_7(f):
> + print("RandomSeed:")
> + print("  Seed:", struct.unpack(' +
> +def handle_8(f):
> + print("Random:")
> + print("  Number:", struct.unpack(' +
> +def handle_9(f):
> + print("CmdAct:")
> + print("  Serial:", struct.unpack(' +
> +def handle_A(f):
> + print("Battle:")
> + print("  Serial first soldier:", struct.unpack(' + print("  Serial second soldier:", struct.unpack(' +
> +def handle_B(f):
> + print("BobSetPosition:")
> + print("  Serial:", struct.unpack(' + print("  Position X:", struct.unpack(' + print("  Position y:", struct.unpack(' +
> +handlers = {
> + 1: handle_1,
> + 2: handle_2,
> + 3: handle_3,
> + 4: handle_4,
> + 5: handle_5,
> + 6: handle_6,
> + 7: handle_7,
> + 8: handle_8,
> + 9: handle_9,
> + 10: handle_A,
> + 11: handle_B
> + }
> +
> +
> +with open(sys.argv[1], "rb") as f:
> + print("Created with %s(%s)"
> + % (str(f.read(struct.unpack(' +str(f.read(struct.unpack(' + end='')
> + playernumber = struct.unpack(' + if playernumber < 0:
> +     print(" as client")
> +     else:
> +     print(" as host, desynced client = %i" % playernumber)
> + byte = f.read(1)
> + while byte:
> + # Parse byte
> + b = ord(byte)
> + cmd = b >> 4
> + length = b & 0x0F
> + if cmd in handlers:
> + handlers[cmd](f)
> + else:
> + # Unknown command. Skip as many bytes as the entry is 
> long
> + print("Warning: Unknown command code '%s', skipping %i 
> bytes" % (cmd, length))
> + for i in range(0, length):
> + byte = f.read(1)
> + byte = f.read(1)


-- 
https://code.launchpad.net/~widelands-dev/widelands/bug-better-syncstreams/+merge/361922
Your team Widelands Developers is requested to review the proposed merge of 
lp:~widelands-dev/widelands/bug-better-syncstreams into lp:widelands.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


[Widelands-dev] [Merge] lp:~widelands-dev/widelands/bug-better-syncstreams into lp:widelands

2019-01-20 Thread bunnybot
Continuous integration builds have changed state:

Travis build 4411. State: passed. Details: 
https://travis-ci.org/widelands/widelands/builds/482186977.
Appveyor build 4201. State: success. Details: 
https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_bug_better_syncstreams-4201.
-- 
https://code.launchpad.net/~widelands-dev/widelands/bug-better-syncstreams/+merge/361922
Your team Widelands Developers is requested to review the proposed merge of 
lp:~widelands-dev/widelands/bug-better-syncstreams into lp:widelands.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


[Widelands-dev] [Merge] lp:~widelands-dev/widelands/bug-better-syncstreams into lp:widelands

2019-01-20 Thread bunnybot
Continuous integration builds have changed state:

Travis build 4409. State: failed. Details: 
https://travis-ci.org/widelands/widelands/builds/481989790.
Appveyor build 4200. State: success. Details: 
https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_bug_better_syncstreams-4200.
-- 
https://code.launchpad.net/~widelands-dev/widelands/bug-better-syncstreams/+merge/361922
Your team Widelands Developers is requested to review the proposed merge of 
lp:~widelands-dev/widelands/bug-better-syncstreams into lp:widelands.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


[Widelands-dev] [Merge] lp:~widelands-dev/widelands/bug-better-syncstreams into lp:widelands

2019-01-18 Thread Notabilis
Notabilis has proposed merging 
lp:~widelands-dev/widelands/bug-better-syncstreams into lp:widelands.

Commit message:
Print more information in syncstreams.

Requested reviews:
  Widelands Developers (widelands-dev)

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/bug-better-syncstreams/+merge/361922

Not ready for review and merge yet, only starting merge request for Windows 
builds.
-- 
Your team Widelands Developers is requested to review the proposed merge of 
lp:~widelands-dev/widelands/bug-better-syncstreams into lp:widelands.
=== modified file 'data/tribes/buildings/productionsites/atlanteans/mill/init.lua'
--- data/tribes/buildings/productionsites/atlanteans/mill/init.lua	2018-09-06 08:21:35 +
+++ data/tribes/buildings/productionsites/atlanteans/mill/init.lua	2019-01-17 19:30:44 +
@@ -74,7 +74,7 @@
  }
   },
   produce_blackroot_flour = {
- -- TRANSLATORS: Completed/Skipped/Did not start grinding blackrootbecause ...
+ -- TRANSLATORS: Completed/Skipped/Did not start grinding blackroot because ...
  descname = _"grinding blackroot",
  actions = {
 -- No check whether we need blackroot_flour because blackroots cannot be used for anything else.

=== modified file 'src/economy/economy.cc'
--- src/economy/economy.cc	2018-12-13 07:24:01 +
+++ src/economy/economy.cc	2019-01-17 19:30:44 +
@@ -706,6 +706,7 @@
 		// alerts, so add info to the sync stream here.
 		{
 			::StreamWrite& ss = game.syncstream();
+			ss.unsigned_8(Syncstream::ProcessRequests);
 			ss.unsigned_8(req.get_type());
 			ss.unsigned_8(req.get_index());
 			ss.unsigned_32(req.target().serial());
@@ -1046,7 +1047,7 @@
 	// to avoid potential future problems caused by the supplies_ changing
 	// under us in some way.
 	::StreamWrite& ss = game.syncstream();
-	ss.unsigned_32(0x02decafa);  // appears as facade02 in sync stream
+	ss.unsigned_8(Syncstream::HandleActiveSupplies);
 	ss.unsigned_32(assignments.size());
 
 	for (const auto& temp_assignment : assignments) {

=== modified file 'src/economy/request.cc'
--- src/economy/request.cc	2018-12-13 07:24:01 +
+++ src/economy/request.cc	2019-01-17 19:30:44 +
@@ -380,7 +380,7 @@
 	assert(is_open());
 
 	::StreamWrite& ss = game.syncstream();
-	ss.unsigned_32(0x01decafa);  // appears as facade01 in sync stream
+	ss.unsigned_8(Syncstream::StartTransfer);
 	ss.unsigned_32(target().serial());
 	ss.unsigned_32(supp.get_position(game)->serial());
 

=== modified file 'src/logic/cmd_queue.cc'
--- src/logic/cmd_queue.cc	2018-12-13 07:24:01 +
+++ src/logic/cmd_queue.cc	2019-01-17 19:30:44 +
@@ -114,8 +114,7 @@
 
 			if (dynamic_cast()) {
 StreamWrite& ss = game_.syncstream();
-static uint8_t const tag[] = {0xde, 0xad, 0x00};
-ss.data(tag, 3);  // provide an easy-to-find pattern as debugging aid
+ss.unsigned_8(Syncstream::RunQueue);
 ss.unsigned_32(c.duetime());
 ss.unsigned_32(static_cast(c.id()));
 			}

=== modified file 'src/logic/filesystem_constants.h'
--- src/logic/filesystem_constants.h	2018-11-09 08:00:35 +
+++ src/logic/filesystem_constants.h	2019-01-17 19:30:44 +
@@ -49,6 +49,7 @@
 const std::string kReplayDir = "replays";
 const std::string kReplayExtension = ".wrpl";
 const std::string kSyncstreamExtension = ".wss";
+const std::string kSyncstreamExcerptExtension = ".wse";
 // The time in seconds for how long old replays/syncstreams should be kept
 // around, in seconds. Right now this is 4 weeks.
 constexpr double kReplayKeepAroundTime = 4 * 7 * 24 * 60 * 60;

=== modified file 'src/logic/game.cc'
--- src/logic/game.cc	2018-12-13 07:24:01 +
+++ src/logic/game.cc	2019-01-17 19:30:44 +
@@ -87,6 +87,8 @@
 void Game::SyncWrapper::start_dump(const std::string& fname) {
 	dumpfname_ = fname + kSyncstreamExtension;
 	dump_.reset(g_fs->open_stream_write(dumpfname_));
+	current_excerpt_id_ = 0;
+	excerpts_buffer_[current_excerpt_id_].clear();
 }
 
 void Game::SyncWrapper::data(void const* const sync_data, size_t const size) {
@@ -114,6 +116,8 @@
 			log("Writing to syncstream file %s failed. Stop synctream dump.\n", dumpfname_.c_str());
 			dump_.reset();
 		}
+		assert(current_excerpt_id_ < kExcerptSize);
+		excerpts_buffer_[current_excerpt_id_].append(static_cast(sync_data), size);
 	}
 
 	target_.data(sync_data, size);
@@ -603,6 +607,40 @@
 }
 
 /**
+ * Switches to the next part of the syncstream excerpt.
+ */
+void Game::report_sync_request() {
+	syncwrapper_.current_excerpt_id_ = (syncwrapper_.current_excerpt_id_ + 1) % SyncWrapper::kExcerptSize;
+	syncwrapper_.excerpts_buffer_[syncwrapper_.current_excerpt_id_].clear();
+}
+
+/**
+ * Triggers writing of syncstream excerpt and adds the playernumber of the desynced player
+ * to the stream.
+ */
+void Game::report_desync(uint32_t playernumber) {
+	std::string filename