Перейти к содержанию
Друзья, важная новость! ×

файл реплея .rec


Рекомендуемые сообщения

Итак, переношу сюда дискуссию связанную с особенностями записи игр в файлы повтора .rec

Основная информация представлена в этой теме на официальном форуме игры

"формат файла 2005"

DATASDSC // START OF NEW CHUNK

2 // Chunk version (?)

95 // Chunk data size

0 // A variable string length

2 // (?)

2 // Number of teams (?)

6 // Number of players (?)

513 // Map Size

4 // String length

W40k // Game/engine name

7 // Double-byte string length

$.1.0.0.1.5.0. // Double-byte engine version string (?)

33 // A variable string length

DATA:Scenarios\MP\6P_KASYR_LUTIEN // Map name

4269834555 // Could this be the duration/time (?)

0 // (?)

0 // (?)

0 // (?)

DATABASE // START OF NEW CHUNK

4 // Chunk version (?)

125 // Chunk data size

0 // A variable string length

3 // (?)

8 // (?)

3853256620 // (?)

8 // (?)

1 // AIDF value

FDIA //= AIDF (AI Difficulty) - It took me a while to figure these out...backwards-endian :)

0 // RSST value

TSSR //= RSST (Starting Resources)

0 // LKTM value

MTKL //= LKTM (Lock Teams)

1 // CHEA value

AEHC //= CHEA (Cheats Enabled)

0 // SLOC value

COLS //= SLOC (Starting Location)

2 // GSPD value

DPSG //= GSPD (Game Speed)

0 // RSSH value

HSSR //= RSSH (Resource Sharing)

1 // RSRT value

TRSR //= RSRT (Resource Rate)

0 // NOTE THIS IS A SINGLE ZERO BYTE (NOT A DWORD)

14 // Double-byte string length

3.v.3. .C.a.b.l.e. .O.n.l.y. // Double-byte game name

0 // (?)

1 // This is the number of Win conditions that are set. Each one is a constant DWORD that follows.

4137259138 // Win Condition - Annihilate

FOLDGPLY // START OF NEW CHUNK - GPLY = Game Player? There is one of these chunks for each player.

2 // Chunk version (?)

41330 // Chunk data size

0 // A variable string length

DATAINFO // START OF NEW CHUNK

1 // Chunk version (?)

54 // Chunk data size

0 // A variable string length

12 // Double-byte string length

B.e.e.z.e.r._.S.m.u.r.f. // Double-byte player name

2 // (?)

0 // (?)

10 // A string length

eldar_race // Race name

0 // (?)

FOLDTCUC // START OF NEW CHUNK - TCUC = Team Colors, something, something?

1 // Chunk version (?)

84 // Chunk data size

0 // A variable string length

DATALCIN // START OF NEW CHUNK - LCIN = Local?? NOTE: This section differs for the replay's "local" player

1 // Chunk version (?)

12 // Chunk data size

0 // A variable string length

0 // (?)

0 // (?)

0 // (?)

DATAUNCU // START OF NEW CHUNK - UNCU = ????

1 // Chunk version (?)

32 // Chunk data size

0 // A variable string length

4 // Double-byte string length

T.e.s.t. // Double-byte scheme name

FF FF FF FF // Primary NOTE: Colors are BGRA (blue, green, red, alpha)

FF FF FF FF // Secondary

FF FF FF FF // Trim

FF FF FF FF // Weapons

FF FF FF FF // Eyes

FOLDTCBD // START OF NEW CHUNK - TCBD = Team color Badge?

1 // Chunk version (?)

16460 // Chunk data size - A bigish chunk...hence the transferring badges lag :)

0 // A variable string length

FOLDIMAG // START OF NEW CHUNK - IMAG = Image (badge in this case)

1 // Chunk version (?)

16440 // Chunk data size

0 // A variable string length

DATAATTR // START OF NEW CHUNK - ATTR = Image attribute(s)?

2 // Chunk version (?)

16 // Chunk data size

0 // A variable string length

0 // (?)

64 // Image WIDTH

64 // Image HEIGHT

1 // (?)

DATADATA // START OF NEW CHUNK - DATA = Image data?

2 // Chunk version (?)

1024 // Chunk data size

0 // A variable string length

<image data> // The image color values

FOLDTCBN // START OF NEW CHUNK - TCBN = Team color Banner?

1 // Chunk version (?)

24652 // Chunk data size

0 // A variable string length

FOLDIMAG // START OF NEW CHUNK - IMAG = Image (banner in this case)

1 // Chunk version (?)

1152 // Chunk data size

0 // A variable string length

DATAATTR // START OF NEW CHUNK - ATTR = Image attribute(s)?

2 // Chunk version (?)

16 // Chunk data size

0 // A variable string length

0 // (?)

64 // Image WIDTH

96 // Image HEIGHT

1 // (?)

DATADATA // START OF NEW CHUNK - DATA = Image data?

2 // Chunk version (?)

1536 // Chunk data size

<image data> // The image color values

FOLDGPLY...

"формат файла 2006"

@Pos: 0

[DWORD] // Replay Version 1 < Patch 1.3 with Patch 1.3 it got 2 after Patch 1.4 it goes to 4

[TEXT]->20Byte File Type "W40K_RECRelic Chunky"

[DWORD] // ???

[DWORD] // ???

[DWORD] // ???

[KEYWORD](FOLDPOST) // START OF NEW CHUNK

[DWORD] // Chunk version

[DWORD] // ???

[DWORD] // ???

[DWORD] // ???

[bYTE] // ???

[KEYWORD](DATADATA) // START OF NEW CHUNK

[DWORD] // Chunk version

[DWORD] // ???

[DWORD] // ???

[DWORD] // Total game duration

[TEXT]->12Byte // Relic Chunky

[DWORD] // Chunk version

[DWORD] // ???

[DWORD] // ???

[KEYWORD](FOLDINFO) // START OF NEW CHUNK

[DWORD] // Chunk version

[DWORD] // 4 byte info ?

[DWORD] // ???

[TEXT]->8Byte // GameInfo

[bYTE] // ???

[KEYWORD](FOLDWAN) // START OF NEW CHUNK

[DWORD] // Chunk version

[DWORD] // ???

[DWORD] // ???

[KEYWORD](DATASDSC) // START OF NEW CHUNK

[DWORD] // Chunk version (?) always 1 so far 2 for Version 4

[DWORD] // Chunk data size

[DWORD] // A variable string length

[DWORD] // (?)

[DWORD] // Number of teams (?)

[DWORD] // Number of active players (without spectators)

[DWORD] // Map Size

[DWORD] // String length

[DWORD] // Game/engine name

[DWORD]->%length% // length of additional header infos

[uNICODETEXT] // Double-byte engine version string (%length%*2)

[DWORD]->%length% // lenth of map Name

[TEXT] // Map name (%length%)

[DWORD] // (?)

[DWORD] // (?)

[DWORD] // (?)

[DWORD] // (?)

{REP VERSION 1}

[DWORD] // (?)

[bYTE] // (?)

[KEYWORD](FOLDMODI) // START OF NEW CHUNK

[DWORD] // Chunk version (?) always 1 so far

[DWORD] // (?)

[DWORD] // (?)

[KEYWORD](DATADMOD) // START OF NEW CHUNK

[DWORD] // Chunk version (?) always 4 so far

[DWORD]->%length% // Chunk data size

[TEXT] // (?) (%length%)

[KEYWORD](DATABASE) // START OF NEW CHUNK

[DWORD] // Chunk version (?) always 4 so far

[DWORD] // Chunk data size

{END VERSION 1}

{REP VERSION 2 OR 4}

[KEYWORD](DATABASE) // START OF NEW CHUNK

[DWORD] // Chunk version (?) always 4 so far

[DWORD] // Chunk data size

{END VERSION 2}

[DWORD] // Always 0 so far

[DWORD] // Always 3 so far

[DWORD] // Avavible Slots (after Patch 1.3 always 8 cause spec slots)

[DWORD] // (?)

[DWORD] // Always 8 so far

[DWORD] // (?)

{8 Keytext with 1byte value - not sorted!}

[DWORD] FDIA //= AIDF (AI Difficulty) - It took me a while to figure these out...backwards-endian

[DWORD] // 1. Byte is the value

[DWORD] TSSR //= RSST (Starting Resources)

[DWORD] // 1. Byte is the value

[DWORD] MTKL //= LKTM (Lock Teams)

[DWORD] // 1. Byte is the value

[DWORD] AEHC //= CHEA (Cheats Enabled)

[DWORD] // 1. Byte is the value

[DWORD] COLS //= SLOC (Starting Location)

[DWORD] // 1. Byte is the value

[DWORD] DPSG //= GSPD (Game Speed)

[DWORD] // 1. Byte is the value

[DWORD] HSSR //= RSSH (Resource Sharing)

[DWORD] // 1. Byte is the value

[DWORD] TRSR //= RSRT (Resource Rate)

[bYTE] // The Byte is the value

[DWORD]->%length% // length of ingame Name

[uNICODETEXT] // Double-byte game name (%length% * 2)

[DWORD] // End of Gamename Always 0 so far

[DWORD]->%length% // This is the number of Win conditions that are set. Each one is a constant DWORD that follows.

{%length% win conditions}

[DWORD] // Win conditon

-157708158 Annihilate

-1826760460 SuddenDeath

-1158102879 Assassinate

-779857721 EconomicVictory

735076042 ControlArea

863969525 DestroyHQ

1959084950 TakeandHolde

{END Win Conditions}

{Now for any Slot There come Player data}

[KEYWORD](FOLDGPLY) // START OF NEW CHUNK - GPLY = Game Player? There is one of these chunks for each player.

[DWORD] 2 // Chunk version (?) Always 2 so far

[DWORD] 41330 // Chunk data size

[DWORD] 0 // A variable string length Always 0 so far

[KEYWORD](DATAINFO) // START OF NEW CHUNK

[DWORD] 1 // Chunk version (?) Always 1 so far

[DWORD] 54 // Chunk data size

[DWORD] 0 // A variable string length Always 0 so far

[DWORD]->%length% // length of Plyer Name

[uNICODETEXT] // Double-byte player name (%length% * 2)

[DWORD] // Type of Slot (0 Host/2 player/4 specc/7 empty/11 computer)

[DWORD] // Team of the Player (counter starts with 0)

[DWORD]->%length% // lengt of race string

[TEXT] // Race Name (%length%)

[DWORD] // (?) Always 0 so far

{REP VERSION 4}

//[DWORD]->%length% // (?) Always 0 so far

//[TEXT] // ? (%length%)

//After Version 1.5 there was this new Flag.

//[bYTE] ??? //It is only present in Version > 1.5

{END VERSION 4}

[KEYWORD](FOLDTCUC) // START OF NEW CHUNK - TCUC = Team Colors, something, something?

{Also Possible: FOLDGPLY -> New Player beginns (happens with spec slots)}

[DWORD] 1 // Chunk version (?) Always 1 so far

[DWORD] 84 // Chunk data size

[DWORD] 0 // A variable string length Always 0 so far

[KEYWORD](DATALCIN) // START OF NEW CHUNK - LCIN = Local?? NOTE: This section differs for the replay's "local" player

[DWORD] 1 // Chunk version (?) Always 1 so far

[DWORD]->%length% 12 // Chunk data size

[TEXT] // (?) (%length%)

[DWORD] // (?) Always 0 so far

[KEYWORD](DATAUNCU) // START OF NEW CHUNK - UNCU = ????

[DWORD] 1 // Chunk version (?) Always 1 so far

[DWORD] 32 // Chunk data size

[DWORD] 0 // A variable string length Always 0 so far

[DWORD]->%length% // length of ColorScheme

[uNICODETEXT] // Double-byte scheme name (%length% * 2)

[DWORD] // Primary NOTE: Colors are BGRA (blue, green, red, alpha)

[DWORD] // Secondary

[DWORD] // Trim

[DWORD] // Weapons

[DWORD] // Eyes

[KEYWORD](FOLDTCBD) // START OF NEW CHUNK - TCBD = Team color Badge?

{Also Possible: FOLDGPLY -> New Player beginns (happens sometimes...)}

{Another keyword FOLDTCBD -> Badge/Banner sometimes change their position in the Replay}

{If none of this Keywords is matchetd it seams like an broken header.. So ignore the 8byte keyword and go on with action data}

[DWORD] 1 // Chunk version (?) Always 1 so far

[DWORD] 16460 // Chunk data size - A bigish chunk...hence the transferring badges lag

[DWORD] 0 // A variable string length

[KEYWORD](FOLDIMAG) // START OF NEW CHUNK - IMAG = Image (badge in this case)

[DWORD] 1 // Chunk version (?) Always 1 so far

[DWORD] 16460 // Chunk data size

[DWORD]->%length% // A variable string length

{IF %length% GT 0 then the Badge has a special Name}

[TEXT] // Name of the Badge (%length%)

{END}

[KEYWORD](DATAATTR) // START OF NEW CHUNK - ATTR = Image attribute(s)?

[DWORD] 2 // Chunk version (?) Always 2 so far

[DWORD] 16 // Chunk data size

[DWORD] 0 // (?)

[DWORD] 0 // (?)

[DWORD] 64 // Image WIDTH

[DWORD] 64 ´ // Image HEIGHT

[DWORD] 1 // (?) Always 1 so far

[KEYWORD](DATADATA) // START OF NEW CHUNK - DATA = Image data?

[DWORD] 2 // Chunk version (?) Always 2 so far

[DWORD] 16 // Chunk data size

[DWORD] 0 // (?)

{Now comes the image data. Pixel by pixel form heigth to width in RGBA colors - you also have to mirror the picture}

[KEYWORD](FOLDTCBN) // START OF NEW CHUNK - TCBN = Team color Banner?

[DWORD] 1 // Chunk version (?) Always 1 so far

[DWORD] 24652 // Chunk data size

[DWORD] 0 // (?)

[KEYWORD](FOLDIMAG ) // START OF NEW CHUNK - IMAG = Image (banner in this case)

[DWORD] 1 // Chunk version (?) Always 1 so far

[DWORD] 1152 // Chunk data size

[DWORD] 0 // (?)

[KEYWORD](DATAATTR) // START OF NEW CHUNK - ATTR = Image attribute(s)?

[DWORD] 2 // Chunk version (?) Always 2 so far

[DWORD] 16 // Chunk data size

[DWORD] 0 // (?)

[DWORD] 0 // (?)

[DWORD] 64 // Image WIDTH

[DWORD] 96 ´ // Image HEIGHT

[DWORD] 1 // (?) Always 1 so far

[KEYWORD](DATADATA) // START OF NEW CHUNK - DATA = Image data?

[DWORD] 2 // Chunk version (?) Always 2 so far

[DWORD] 1536 // Chunk data size

[DWORD] 0 // (?)

{Now comes the image data. Pixel by pixel form heigth to width in RGBA colors - you also have to turn the picture}

{End of Player Data}

{Now The acion Data starts.. DoW is working with 8Ticks per second}

[DWORD] // Action 1 Key - Action Key 1 identefies an Chat msg so far

[DWORD] // Action 1 Length

{IF second action key is 1}

[DWORD] // Action 2 Key

{IF this action key is also 1 its an chat msg}

[DWORD] // Action 2 Length of Chat chunk

[bYTE] // Also length of Chat chunk so far

{IF REP Version 1}

[bYTE] // Player ID (As same orders as they are listed bevore)

[bYTE] // Reciver 0 All/1 Team/2 System

[bYTE] // (?)

{IF Rep Version 2 OR 4}

[DWORD]->%len% // Length of Player Name

[uNICODETEXT] // Double-byte player name (%len% * 2)

[DWORD] // Player ID > 1000 are normal players blow the IDs of the Spectators

[DWORD] // Msg Type 0 Player/1 Spec/2 System

[DWORD] // Reciver 0 All/1 Team/2 System

{End of Version spec Data}

[DWORD]->%len% // Length of Chat MSG

[uNICODETEXT] // Double-byte chat msg (%len% * 2)

{If second Action Key is not 1}

[DWORD]->%length% // length of action

[bYTE] // (?)

[TEXT] // (?) (%length%)

{If action key is 0}

[bYTE]

{IF REP version 2}

[bYTE] // Indicatios if the action block has action (1) or not (0)

{END Version depanding handling}

[DWORD] // Number of this tick (8 per second!)

"исходник менеджера реплеев на C#"

/*

* Created by SharpDevelop.

* User: Norbert 'GoWa' Laenger

* Date: 23.02.2006

* Time: 13:04

*/

// DoW/DoW:WA Replay Reader. Analyse and Show informatios from replay files.

// Copyright © Norbert 'GoWa' Laenger name of author

//

// 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 2

// 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.

using System;

using System.IO;

using System.Collections;

using System.Text;

using System.Drawing;

using System.Windows.Forms;

using System.Threading;

namespace DoWRepReader

{

/// <summary>

/// Description of Class1.

/// </summary>

// Methods

public class RepReader

{

#region Variable deklaration

public Replay Replay;

private UnicodeEncoding encoding1;

private int counter;

private byte[] buffer;

private int num;

private char[] chr;

private string str;

private byte wincondvalue;

private int LastTick;

private ChatMessage Chat;

private Player Player;

private Analyse Cache;

private BinaryReader BinReader;

private BinaryWriter BinWriter;

#endregion

#region Events

// Events

public event EventHandler ReplayChanged;

#endregion

#region RepReader

public RepReader()

{

this.Chat = new ChatMessage();

this.Player = new Player();

this.encoding1 = new UnicodeEncoding();

}

#endregion

#region TickToTime

public static string TickToTime(int Tick)

{

Tick = Tick / 8;

int sec = Tick % 60;

int min = (Tick - sec) / 60;

return (min.ToString("D2") + ":" + sec.ToString("D2"));

}

#endregion

#region RenameIngame

public bool RenameIngame(string FileName, string name)

{

if(this.Replay.NameStart > 0)

{

if(this.OpenFile(FileName))

{

if(this.WriteFile(FileName + "rename.rec"))

{

this.BinReader.BaseStream.Position = 0;

this.BinWriter.BaseStream.Position = 0;

while(this.BinWriter.BaseStream.Position < this.Replay.BeginFOLDINFO)

{

this.BinWriter.Write(this.BinReader.ReadByte());

}

this.BinReader.BaseStream.Position = this.BinReader.BaseStream.Position + 4;

int len = this.Replay.LengthFOLDINFO - (this.Replay.Name.Length * 2) + (name.Length * 2);

this.BinWriter.Write(len);

while(this.BinWriter.BaseStream.Position < this.Replay.BeginDATABASE)

{

this.BinWriter.Write(this.BinReader.ReadByte());

}

//this.BinWriter.BaseStream.Position = this.Replay.BeginDATABASE;

this.BinReader.BaseStream.Position = this.BinReader.BaseStream.Position + 4;

len = this.Replay.LengthDATABASE - (this.Replay.Name.Length * 2) + (name.Length * 2);

this.BinWriter.Write(len);

while(this.BinWriter.BaseStream.Position < this.Replay.NameStart)

{

this.BinWriter.Write(this.BinReader.ReadByte());

}

//this.BinWriter.BaseStream.Position = this.Replay.NameStart;

this.BinReader.BaseStream.Position = this.BinReader.BaseStream.Position + 4;

len = name.Length;

this.BinWriter.Write(len);

for(int i=0; i < name.Length; i++)

{

Int16 ka = (Int16) name;

this.BinWriter.Write(ka);

}

this.BinReader.BaseStream.Position = this.BinReader.BaseStream.Position + (this.Replay.Name.Length * 2);

while (BinReader.BaseStream.Position < BinReader.BaseStream.Length)

{

this.BinWriter.Write(this.BinReader.ReadByte());

}

this.BinReader.Close();

this.BinWriter.Close();

File.Delete(FileName);

File.Move(FileName + "rename.rec", FileName);

return true;

}

else

{

this.BinReader.Close();

this.BinWriter.Close();

return false;

}

}

else

{

this.BinReader.Close();

this.BinWriter.Close();

return false;

}

}

else {

this.BinReader.Close();

this.BinWriter.Close();

return false;

}

}

#endregion

#region OpenFile

private bool OpenFile(string FileName)

{

try

{

Stream ReplayFile = File.OpenRead(FileName);

this.BinReader = new BinaryReader(ReplayFile, Encoding.ASCII);

return true;

}

catch (Exception)

{

this.BinReader.Close();

return false;

}

}

#endregion

#region WriteFile

private bool WriteFile(string FileName)

{

try

{

Stream ReplayFile = File.OpenWrite(FileName);

this.BinWriter = new BinaryWriter(ReplayFile, Encoding.ASCII);

return true;

}

catch (Exception)

{

this.BinWriter.Close();

return false;

}

}

#endregion

#region ReadHeaderOnly

public bool ReadHeaderOnly(string FileName)

{

bool ret = this.ReadHeader(FileName);

BinReader.Close();

return ret;

}

#endregion

#region ReadHeader

public bool ReadHeader(string FileName)

{

this.Replay = new Replay();

//MessageBox.Show("Header Start...");

if(this.OpenFile(FileName))

{

this.Replay.FileName = FileName;

//@Pos: 0

//[DWORD] // Replay Version 1 < Patch 1.3 with Patch 1.3 it got 2 after Patch 1.4 it goes to 4

this.Replay.Version = BinReader.ReadInt32();

//[TEXT]->20Byte File Type "W40K_RECRelic Chunky"

BinReader.ReadChars(20);

//[DWORD] // ???

BinReader.ReadInt32();

//[DWORD] // ???

BinReader.ReadInt32(); // 1

//[DWORD] // ???

BinReader.ReadInt32(); // 1

//[KEYWORD](FOLDPOST) // START OF NEW CHUNK

BinReader.ReadChars(8); // FOLDPOST

//[DWORD] // ???

BinReader.ReadInt32(); // 1

//[DWORD] // ???

BinReader.ReadInt32();

//[DWORD] // ???

BinReader.ReadInt32();

//[DWORD] // ???

BinReader.ReadChars(12); // PostGameInfo

//[bYTE] // ???

BinReader.ReadByte();

//[KEYWORD](DATADATA) // START OF NEW CHUNK

BinReader.ReadChars(8); // DATADATA

//[DWORD] // ???

BinReader.ReadInt32(); // 1

//[DWORD] // ???

BinReader.ReadInt32(); // 4

//[DWORD] // ???

BinReader.ReadInt32(); // 0

//[DWORD] // Total game duration

int TotalTicks = BinReader.ReadInt32();

this.Replay.Duration = TickToTime(TotalTicks);

//[TEXT]->12Byte

BinReader.ReadChars(12); // Relic Chunky

//[DWORD] // ???

BinReader.ReadInt32();

//[DWORD] // ???

BinReader.ReadInt32(); // 1

//[DWORD] // ???

BinReader.ReadInt32(); // 1

//[KEYWORD](FOLDINFO) // START OF NEW CHUNK

BinReader.ReadChars(8); // FOLDINFO

//[DWORD] // ???

BinReader.ReadInt32(); // 1

//[DWORD] // 4 byte info ?

this.Replay.BeginFOLDINFO = this.BinReader.BaseStream.Position;

this.Replay.LengthFOLDINFO = BinReader.ReadInt32();

//[DWORD] // ???

BinReader.ReadInt32(); // 9

//[TEXT]->8Byte

BinReader.ReadChars(8); // GameInfo

//[bYTE] // ???

BinReader.ReadByte();

//[KEYWORD](FOLDWAN) // START OF NEW CHUNK

BinReader.ReadChars(8); // FOLDWMAN

//[DWORD] // ???

BinReader.ReadInt32(); // 1

//[DWORD] // ???

BinReader.ReadInt32();

//[DWORD] // ???

BinReader.ReadInt32();

//[KEYWORD](DATASDSC) // START OF NEW CHUNK

BinReader.ReadInt64();

//[DWORD] // Chunk version (?) always 1 so far 2 for Version 4

BinReader.ReadInt32();

//[DWORD] // Chunk data size

BinReader.ReadInt32();

//[DWORD] // A variable string length

BinReader.ReadInt32();

//[DWORD] // (?)

BinReader.ReadInt32();

//[DWORD] // Number of teams (?)

BinReader.ReadInt32();

//[DWORD] // Number of active players (without spectators)

this.Replay.PlayerCount = BinReader.ReadInt32();

//[DWORD] // Map Size

this.Replay.Size = BinReader.ReadInt32();

//[DWORD] // String length

num = BinReader.ReadInt32();

if(num > 0)

{

//[TEXT] // Game/engine name

chr = BinReader.ReadChars(num);

this.Replay.MOD = str = new string(chr);

}

else

{

//[DWORD] // Game/engine name

BinReader.ReadInt32();

}

//[DWORD]->%length% // length of additional header infos

num = BinReader.ReadInt32();

//[uNICODETEXT] // Double-byte engine version string (%length%*2)

buffer = BinReader.ReadBytes(num * 2);

this.Replay.Engine = encoding1.GetString(buffer);

//[DWORD]->%length% // lenth of map Name

num = BinReader.ReadInt32();

//[TEXT] // Map name (%length%)

chr = BinReader.ReadChars(num);

this.Replay.Map = str = new string(chr);

//[DWORD] // (?)

BinReader.ReadInt32();

//[DWORD] // (?)

BinReader.ReadInt32();

//[DWORD] // (?)

BinReader.ReadInt32();

//[DWORD] // (?)

BinReader.ReadInt32();

//

//{REP VERSION 1}

if(this.Replay.Version == 1)

{

//[DWORD] // (?)

BinReader.ReadInt32();

//[bYTE] // (?)

BinReader.ReadByte();

//[KEYWORD](FOLDMODI) // START OF NEW CHUNK

BinReader.ReadInt64();

//[DWORD] // Chunk version (?) always 1 so far

BinReader.ReadInt32();

//[DWORD] // (?)

BinReader.ReadInt32();

//[DWORD] // (?)

BinReader.ReadInt32();

//[KEYWORD](DATADMOD) // START OF NEW CHUNK

BinReader.ReadInt64();

//[DWORD] // Chunk version (?) always 4 so far

BinReader.ReadInt32();

//[DWORD]->%length% // Chunk data size

num = BinReader.ReadInt32();

//[TEXT] // (?) (%length%)

chr = BinReader.ReadChars(num);

str = new string(chr);

//[TEXT] // (?)

BinReader.ReadInt32();

//[KEYWORD](DATABASE) // START OF NEW CHUNK

BinReader.ReadInt64();

//[DWORD] // Chunk version (?) always 4 so far

BinReader.ReadInt32();

//{END VERSION 1}

//

}

else if(this.Replay.Version == 2 || this.Replay.Version == 4)

{

//{REP VERSION 2}

//[KEYWORD](DATABASE) // START OF NEW CHUNK

BinReader.ReadInt64();

//[DWORD] // Chunk version (?) always 4 so far

BinReader.ReadInt32();

//{END VERSION 2}

//

}

//[DWORD] // Chunk data size

this.Replay.BeginDATABASE = BinReader.BaseStream.Position;

this.Replay.LengthDATABASE = BinReader.ReadInt32();

//[DWORD] // Always 0 so far

BinReader.ReadInt32();

//[DWORD] // Always 3 so far

BinReader.ReadInt32();

//[DWORD] // Avavible Slots (after Patch 1.3 always 8 cause spec slots)

this.Replay.Slots = BinReader.ReadInt32();

//[DWORD] // (?)

int gr = BinReader.ReadInt32();

//[DWORD] // Always 8 so far

BinReader.ReadInt32();

//[DWORD] // (?)

int um = BinReader.ReadInt32();

//MessageBox.Show(this.Replay.Slots.ToString() + ": " + um.ToString());

//

for(counter=0;counter < 8;counter++)

{

//{8 Keytext with 1byte value - not sorted!}

//[DWORD] FDIA //= AIDF (AI Difficulty) - It took me a while to figure these out...backwards-endian

//[DWORD] // 1. Byte is the value

//[DWORD] TSSR //= RSST (Starting Resources)

//[DWORD] // 1. Byte is the value

//[DWORD] MTKL //= LKTM (Lock Teams)

//[DWORD] // 1. Byte is the value

//[DWORD] AEHC //= CHEA (Cheats Enabled)

//[DWORD] // 1. Byte is the value

//[DWORD] COLS //= SLOC (Starting Location)

//[DWORD] // 1. Byte is the value

//[DWORD] DPSG //= GSPD (Game Speed)

//[DWORD] // 1. Byte is the value

//[DWORD] HSSR //= RSSH (Resource Sharing)

//[DWORD] // 1. Byte is the value

//[DWORD] TRSR //= RSRT (Resource Rate)

//[bYTE] // The Byte is the value

chr = BinReader.ReadChars(4);

str = new string(chr);

if(counter == 7)

{

// Warum auch immer aber im letzen durchgang ist es eben nur ein byte

wincondvalue = BinReader.ReadByte();

}

else

{

wincondvalue = Convert.ToByte(BinReader.ReadInt32());

}

switch (str)

{

case "FDIA":

this.Replay.GameSetting.AIDiff = wincondvalue;

break;

case "TSSR":

this.Replay.GameSetting.StartRes = wincondvalue;

break;

case "MTKL":

this.Replay.GameSetting.LockTeams = wincondvalue;

break;

case "AEHC":

this.Replay.GameSetting.CheatsON = wincondvalue;

break;

case "COLS":

this.Replay.GameSetting.StartLocation = wincondvalue;

break;

case "DPSG":

this.Replay.GameSetting.GameSpeed = wincondvalue;

break;

case "HSSR":

this.Replay.GameSetting.ResShare = wincondvalue;

break;

case "TRSR":

this.Replay.GameSetting.ResRate = wincondvalue;

break;

}

}

//

this.Replay.NameStart = BinReader.BaseStream.Position;

//[DWORD]->%length% // length of ingame Name

num = BinReader.ReadInt32();

//[uNICODETEXT] // Double-byte game name (%length% * 2)

buffer = BinReader.ReadBytes(num * 2);

this.Replay.Name = encoding1.GetString(buffer);

//[DWORD] // End of Gamename Always 0 so far

BinReader.ReadInt32();

//MessageBox.Show("Header Done...");

//[DWORD]->%length% // This is the number of Win conditions that are set. Each one is a constant DWORD that follows.

counter = BinReader.ReadInt32();

//

for(int win_count=0;win_count < counter;win_count++)

{

//{%length% win conditions}

//[DWORD] // Win conditon

//767227721 Annihilate

//-1826760460 SuddenDeath

//200405640 Assassinate

//-242444938 EconomicVictory

//735076042 ControlArea

//1509920563 DestroyHQ

//1959084950 TakeandHolde

//69421273 GameTime

num = BinReader.ReadInt32();

if(num.Equals(WinCondition.WinConditions.Annihilate)) // Annihilate

{

this.Replay.WinCondition.Annihilate = true;

}

else if(num.Equals(WinCondition.WinConditions.SuddenDeath)) // SuddenDeath

{

this.Replay.WinCondition.SuddenDeath = true;

}

else if(num.Equals(WinCondition.WinConditions.Assassinate)) // Assassinate

{

this.Replay.WinCondition.Assassinate = true;

}

else if(num.Equals(WinCondition.WinConditions.EconomicVictory)) // EconomicVictory

{

this.Replay.WinCondition.EconomicVictory = true;

}

else if(num.Equals(WinCondition.WinConditions.ControlArea)) // ControlArea

{

this.Replay.WinCondition.ControlArea = true;

}

else if(num.Equals(WinCondition.WinConditions.DestroyHQ)) // DestroyHQ

{

this.Replay.WinCondition.DestroyHQ = true;

}

else if(num.Equals(WinCondition.WinConditions.TakeandHolde)) // TakeandHolde

{

this.Replay.WinCondition.TakeandHolde = true;

}

else if(num.Equals(WinCondition.WinConditions.GameTime)) // GameTime

{

this.Replay.WinCondition.GameTime = true;

}

//{END Win Conditions}

}

this.Replay.PlayerStart = BinReader.BaseStream.Position;

return true;

}

else

{

return false;

}

}

#endregion

#region ReadPlayer

private void ReadPlayer()

{

this.Player = new Player();

//{Now for any Slot There come Player data

//[KEYWORD](FOLDGPLY) // START OF NEW CHUNK - GPLY = Game Player? There is one of these chunks for each player.

//MessageBox.Show("New Player at: " + BinReader.BaseStream.Position.ToString() + " (" + str + ")");

chr = BinReader.ReadChars(8);

str = new string(chr);

if(str.Equals("FOLDGPLY"))

{

//[DWORD] 2 // Chunk version (?) Always 2 so far

BinReader.ReadInt32();

//[DWORD] 41330 // Chunk data size

int zzz = BinReader.ReadInt32();

//MessageBox.Show(zzz.ToString() + " / " + BinReader.BaseStream.Position.ToString());

//[DWORD] 0 // A variable string length Always 0 so far

BinReader.ReadInt32();

//[KEYWORD](DATAINFO) // START OF NEW CHUNK

BinReader.ReadInt64();

//[DWORD] 1 // Chunk version (?) Always 1 so far

BinReader.ReadInt32();

//[DWORD] 54 // Chunk data size

BinReader.ReadInt32();

//[DWORD] 0 // A variable string length Always 0 so far

BinReader.ReadInt32();

//[DWORD]->%length% // length of Plyer Name

num = BinReader.ReadInt32();

//[uNICODETEXT] // Double-byte player name (%length% * 2)

buffer = BinReader.ReadBytes(num * 2);

this.Player.Name = encoding1.GetString(buffer);

//[DWORD] // Type of Slot (0 Host/2 player/4 specc/7 empty/1,3,11 computer)

this.Player.Type = BinReader.ReadInt32();

//[DWORD] // Team of the Player (counter starts with 0)

this.Player.Team = (BinReader.ReadInt32() + 1);

//[DWORD]->%length% // lengt of race string

num = BinReader.ReadInt32();

//[TEXT] // Race Name (%length%)

chr = BinReader.ReadChars(num);

this.Player.Race = new string(chr);

//[DWORD] // (?) Always 0 so far

BinReader.ReadInt32();

//

if(this.Replay.Version == 4)

{

//[DWORD] // (?) Always 0 so far

num = BinReader.ReadInt32();

//[TEXT] // ?

chr = BinReader.ReadChars(num);

//After Version 1.5 there was this new Flag.

//It is only present in Version > 1.5

//[bYTE] ???

byte tmp = BinReader.ReadByte();

if(tmp > 0)

{

BinReader.BaseStream.Seek(-1, System.IO.SeekOrigin.Current);

}

}

// If there are Empty Slots don't read to fare for the last slot

if(this.Player.Type != 7)

{

//[KEYWORD](FOLDTCUC) // START OF NEW CHUNK - TCUC = Team Colors, something, something?

chr = BinReader.ReadChars(8);

str = new string(chr);

//{Also Possible: FOLDGPLY -> New Player beginns (happens with spec slots)}

if(str == "FOLDTCUC")

{

//

//[DWORD] 1 // Chunk version (?) Always 1 so far

BinReader.ReadInt32();

//[DWORD] 84 // Chunk data size

BinReader.ReadInt32();

//[DWORD] 0 // A variable string length Always 0 so far

BinReader.ReadInt32();

//[KEYWORD](DATALCIN) // START OF NEW CHUNK - LCIN = Local?? NOTE: This section differs for the replay's "local" player

BinReader.ReadChars(8);

//[DWORD] 1 // Chunk version (?) Always 1 so far

BinReader.ReadInt32();

//[DWORD]->%length% 12 // Chunk data size

num = BinReader.ReadInt32();

//[TEXT] // (?) (%length%)

chr = BinReader.ReadChars(num);

//[DWORD] // (?) Always 0 so far

BinReader.ReadInt32();

//[KEYWORD](DATAUNCU) // START OF NEW CHUNK - UNCU = ????

BinReader.ReadChars(8);

//[DWORD] 1 // Chunk version (?) Always 1 so far

BinReader.ReadInt32();

//[DWORD] 32 // Chunk data size

BinReader.ReadInt32();

//[DWORD] 0 // A variable string length Always 0 so far

BinReader.ReadInt32();

//[DWORD]->%length% // length of ColorScheme

num = BinReader.ReadInt32();

//[uNICODETEXT] // Double-byte scheme name (%length% * 2)

buffer = BinReader.ReadBytes(num * 2);

str = encoding1.GetString(buffer);

//[DWORD] // Primary NOTE: Colors are BGRA (blue, green, red, alpha)

buffer = BinReader.ReadBytes(4);

this.Player.Primary = Color.FromArgb(buffer[3], buffer[2], buffer[1], buffer[0]);

//[DWORD] // Secondary

buffer = BinReader.ReadBytes(4);

this.Player.Secondary = Color.FromArgb(buffer[3], buffer[2], buffer[1], buffer[0]);

//[DWORD] // Trim

buffer = BinReader.ReadBytes(4);

this.Player.Trim = Color.FromArgb(buffer[3], buffer[2], buffer[1], buffer[0]);

//[DWORD] // Weapons

buffer = BinReader.ReadBytes(4);

this.Player.Weapons = Color.FromArgb(buffer[3], buffer[2], buffer[1], buffer[0]);

//[DWORD] // Eyes

buffer = BinReader.ReadBytes(4);

this.Player.Eyes = Color.FromArgb(buffer[3], buffer[2], buffer[1], buffer[0]);

//

for(int bannerbadge=0; bannerbadge < 2 ;bannerbadge++)

{

//[KEYWORD](FOLDTCBD) // START OF NEW CHUNK - TCBD = Team color Badge?

chr = BinReader.ReadChars(8);

str = new string(chr);

//{Also Possible: FOLDGPLY -> New Player beginns (happens sometimes...)}

//{Another keyword FOLDTCBD -> Badge/Banner sometimes change their position in the Replay}

//{If none of this Keywords is matchetd it seams like an broken header.. So ignore the 8byte keyword and go on with action data}

//

if(str.Equals("FOLDTCBD"))

{

//[DWORD] 1 // Chunk version (?) Always 1 so far

BinReader.ReadInt32();

//[DWORD] 16460 // Chunk data size - A bigish chunk...hence the transferring badges lag

BinReader.ReadInt32();

//[DWORD] 0 // A variable string length

BinReader.ReadInt32();

//[KEYWORD](FOLDIMAG) // START OF NEW CHUNK - IMAG = Image (badge in this case)

chr = BinReader.ReadChars(8);

str = new string(chr);

//[DWORD] 1 // Chunk version (?) Always 1 so far

BinReader.ReadInt32();

//[DWORD] 16460 // Chunk data size

BinReader.ReadInt32();

//[DWORD]->%length% // A variable string length

num = BinReader.ReadInt32();

//{IF %length% GT 0 then the Badge has a special Name}

//[TEXT] // Name of the Badge (%length%)

chr = BinReader.ReadChars(num);

str = new string(chr);

//{END}

//[KEYWORD](DATAATTR) // START OF NEW CHUNK - ATTR = Image attribute(s)?

chr = BinReader.ReadChars(8);

str = new string(chr);

//[DWORD] 2 // Chunk version (?) Always 2 so far

BinReader.ReadInt32();

//[DWORD] 16 // Chunk data size

BinReader.ReadInt32();

//[DWORD] 0 // (?)

BinReader.ReadInt32();

//[DWORD] 0 // (?)

BinReader.ReadInt32();

//[DWORD] 64 // Image HEIGHT

int height = BinReader.ReadInt32();

//[DWORD] 64 // Image WIDTH

int width = BinReader.ReadInt32();

//[DWORD] 1 // (?) Always 1 so far

BinReader.ReadInt32();

//[KEYWORD](DATADATA) // START OF NEW CHUNK - DATA = Image data?

chr = BinReader.ReadChars(8);

str = new string(chr);

//[DWORD] 2 // Chunk version (?) Always 2 so far

BinReader.ReadInt32();

//[DWORD] 16 // Chunk data size

BinReader.ReadInt32();

//[DWORD] 0 // (?)

BinReader.ReadInt32();

//

//{Now comes the image data. Pixel by pixel form heigth to width in RGBA colors - you also have to mirror the picture}

this.Player.Badge = new Bitmap(width, height);

for(int y =0;y<height;y++)

{

for(int x=0;x<width;x++)

{

buffer = BinReader.ReadBytes(4);

this.Player.Badge.SetPixel(x, y, Color.FromArgb(buffer[3], buffer[2], buffer[1], buffer[0]));

}

}

this.Player.Badge.RotateFlip(RotateFlipType.Rotate180FlipX);

//

}

else if(str.Equals("FOLDTCBN"))

{

//

//[KEYWORD](FOLDTCBN) // START OF NEW CHUNK - TCBN = Team color Banner?

//Already done

//[DWORD] 1 // Chunk version (?) Always 1 so far

BinReader.ReadInt32();

//[DWORD] 24652 // Chunk data size

BinReader.ReadInt32();

//[DWORD] 0 // (?)

BinReader.ReadInt32();

//[KEYWORD](FOLDIMAG ) // START OF NEW CHUNK - IMAG = Image (banner in this case)

BinReader.ReadInt64();

//[DWORD] 1 // Chunk version (?) Always 1 so far

BinReader.ReadInt32();

//[DWORD] 1152 // Chunk data size

BinReader.ReadInt32();

//[DWORD]->%length% // A variable string length

num = BinReader.ReadInt32();

//{IF %length% GT 0 then the Banner has a special Name}

//[TEXT] // Name of the Banner (%length%)

chr = BinReader.ReadChars(num);

str = new string(chr);

//[KEYWORD](DATAATTR) // START OF NEW CHUNK - ATTR = Image attribute(s)?

BinReader.ReadInt64();

//[DWORD] 2 // Chunk version (?) Always 2 so far

BinReader.ReadInt32();

//[Word] 16 // Chunk data size

BinReader.ReadInt32();

//[DWORD] 0 // (?)

BinReader.ReadInt32();

//[DWORD] 0 // (?)

BinReader.ReadInt32();

//[DWORD] 64 // Image WIDTH

int width = BinReader.ReadInt32();

//[DWORD] 96 ´ // Image HEIGHT

int height = BinReader.ReadInt32();

//[DWORD] 1 // (?) Always 1 so far

BinReader.ReadInt32();

//[KEYWORD](DATADATA) // START OF NEW CHUNK - DATA = Image data?

BinReader.ReadInt64();

//[DWORD] 2 // Chunk version (?) Always 2 so far

BinReader.ReadInt32();

//[DWORD] 1536 // Chunk data size

BinReader.ReadInt32();

//[DWORD] 0 // (?)

BinReader.ReadInt32();

//

//{Now comes the image data. Pixel by pixel form heigth to width in RGBA colors - you also have to turn the picture}

this.Player.Banner = new Bitmap(width, height);

for(int y =0;y<height;y++)

{

for(int x=0;x<width;x++)

{

buffer = BinReader.ReadBytes(4);

this.Player.Banner.SetPixel(x, y, Color.FromArgb(buffer[3], buffer[2], buffer[1], buffer[0]));

}

}

this.Player.Banner.RotateFlip(RotateFlipType.Rotate180FlipX);

}

else

{

//Header was not closed correct happend in some replays in <=1.3

//So just leave the loop an say we got a new Player

bannerbadge = 2;

BinReader.BaseStream.Seek(-8, System.IO.SeekOrigin.Current);

}

}

}

else

{

//Header was not closed correct happend in some replays in <=1.3

//So just leave the loop an say we got a new Player

BinReader.BaseStream.Seek(-8, System.IO.SeekOrigin.Current);

}

}

}

else

{

//Header was not closed correct happend in some replays in <=1.3

//So just leave the loop an say we got a new Player

BinReader.BaseStream.Seek(-8, System.IO.SeekOrigin.Current);

}

}

//

//{End of Player Data}

//MessageBox.Show("Next Player at: " + BinReader.BaseStream.Position.ToString());

#endregion

#region ReadActionDetail

// Chat.SndID gleicher text wie bei actions

private void ReadActionDetail()

{

//[DWORD] // Action Key - Action Key 1 identefies an Chat msg so far

int Action1 = BinReader.ReadInt32();

//[DWORD] // Action Length

int Action1Len = BinReader.ReadInt32();

int ReadedActionLen = 0;

//MessageBox.Show(BinReader.BaseStream.Position.ToString() + " / " + Action1Len.ToString());

if(Action1.Equals(1))

{

//[DWORD] // Action Key

int Action2 = BinReader.ReadByte();

//{IF this action key is also 1 its an chat msg}

if(Action2.Equals(1))

{

// [bYTES] 3 empty Bytes

BinReader.ReadBytes(3);

this.Chat = new ChatMessage();

//[DWORD] // Length of Chat chunk

BinReader.ReadInt32();

//[bYTE] // Also length of Chat chunk so far

BinReader.ReadByte();

//{IF REP Version 1}

if(this.Replay.Version == 1)

{

//[bYTE] // Player ID (As same orders as they are listed bevore)

this.Chat.Snd = BinReader.ReadByte();

//[bYTE] // Reciver 0 All/1 Team/2 System

this.Chat.Rec = BinReader.ReadByte();

//[bYTE] // (?)

BinReader.ReadByte();

//{IF Rep Version 2}

}

else if(this.Replay.Version == 2 || this.Replay.Version == 4)

{

//MessageBox.Show(BinReader.BaseStream.Position.ToString());

//[DWORD]->%len% // Length of Player Name

num = BinReader.ReadInt32();

//[uNICODETEXT] // Double-byte player name (%len% * 2)

buffer = BinReader.ReadBytes(num * 2);

this.Chat.SndName = encoding1.GetString(buffer);

//[DWORD] // Player ID > 1000 are normal players blow the IDs of the Spectators

this.Chat.Snd = BinReader.ReadInt32();

//MessageBox.Show(this.Chat.Snd.ToString());

//[DWORD] // Msg Type 0 Player/1 Spec/2 System

this.Chat.Type = BinReader.ReadInt32();

//[DWORD] // Reciver 0 All/1 Team/2 System

this.Chat.Rec = BinReader.ReadInt32();

//{End of Version spec Data}

}

//[DWORD]->%len% // Length of Chat MSG

num = BinReader.ReadInt32();

//[uNICODETEXT] // Double-byte chat msg (%len% * 2)

buffer = BinReader.ReadBytes(num * 2);

this.Chat.Msg = encoding1.GetString(buffer);

//{If second Action Key is not 1}

this.Chat.Zeit = TickToTime(this.LastTick);

this.Replay.ChatMSG.Add(this.Chat);

}

else if(Action2.Equals(Action1Len))

{

// Here was a lag window

//[DWORD]->%length% // length of player

num = BinReader.ReadInt32();

//[uNICODETEXT] // Double-byte player name (%len% * 2)

buffer = BinReader.ReadBytes(num * 2);

//[DWORD] // Player id

num = BinReader.ReadInt32();

//[DWORD] ???

num = BinReader.ReadInt32();

//[DWORD] ???

num = BinReader.ReadInt32();

//[DWORD]->%length% // length of text

num = BinReader.ReadInt32();

//[uNICODETEXT] // Double-byte text ??? (%len% * 2)

buffer = BinReader.ReadBytes(num * 2);

}

else

{

// [bYTES] 3 empty bytes

BinReader.ReadBytes(3);

//[DWORD]->%length% // length of action

num = BinReader.ReadInt32();

//[bYTE] // (?)

BinReader.ReadByte();

//[TEXT] // (?) (%length%)

BinReader.ReadBytes(num);

//BinReader.ReadBytes(num);

}

//{If action key not is 1}

}

else if(Action1 == 0 && Action1Len > 14)

{

//[bYTE] ???

BinReader.ReadByte(); // Always 80 ??

if(this.Replay.Version > 1)

{

//[bYTE] Marks if action block contains actions

BinReader.ReadByte(); // If 1 Action Block has action!

}

//[DWORD] Tick of this action

int Tick = BinReader.ReadInt32();

this.LastTick = Tick;

//[DWORD] Total number of actions so fare

this.Replay.ActionCount = BinReader.ReadInt32(); // ActionCounter

//[DWORD] ??? Move Data ?

BinReader.ReadInt32(); // MoveData

ReadedActionLen = 12; // 12 Bytes Already read

//[DWORD] Length of the complete action part

BinReader.ReadInt32();

//[bYTE] Single byte ???

BinReader.ReadByte();

ReadedActionLen = ReadedActionLen + 5;

// Only read till action ends

while(ReadedActionLen < Action1Len)

{

try

{

// Create new action

Action CurrentAction = new Action();

//[bYTE] length of simple Action

CurrentAction.ActionLen = BinReader.ReadByte();

ReadedActionLen = ReadedActionLen + 1;

//// [bYTES] -> 14 ???

CurrentAction.ActionData = BinReader.ReadBytes(14);

BinReader.BaseStream.Seek(-14, System.IO.SeekOrigin.Current);

// [bYTE] always 0

BinReader.ReadByte();

// [WORD] ???

BinReader.ReadInt32();

// [WORD] Action kind

CurrentAction.Kind = BinReader.ReadInt32();

// [WORD] Action kind value

CurrentAction.KindValue = BinReader.ReadInt32();

// [bYTE] always 0

BinReader.ReadByte();

// [iNT16] Action Player after 1.3 startlocation + 1000

CurrentAction.ActionPlayer = BinReader.ReadInt16();

if(this.Replay.Version < 2 && this.Replay.Version > 1)

{

CurrentAction.ActionPlayer = (Int16) (CurrentAction.ActionPlayer + 1000);

}

// [iNT16] Action Player2 seams to be always the same

CurrentAction.ActionPlayer2 = BinReader.ReadInt16();

// [iNT16] Action Player action counter for this player

Int16 PlayerActionCounter = BinReader.ReadInt16();

// [bYTES] Action Data ??? length = ActionLen - 21

CurrentAction.ActionData2 = BinReader.ReadBytes(CurrentAction.ActionLen - 1 - 14 - 6);

ReadedActionLen = ReadedActionLen + CurrentAction.ActionLen + 1;

if(CurrentAction.ActionPlayer >= 1000)

{

//MessageBox.Show("Fehler ??? bei Sekunde: 1 " + CurrentAction.ActionPlayer.ToString());

//Add reades action to the player (not correct till now!)

Player ThisActionPlayer = (this.Replay.Player[CurrentAction.ActionPlayer - 1000] as Player);

//MessageBox.Show("Fehler ??? bei Sekunde: 2 " + CurrentAction.ActionPlayer.ToString());

ThisActionPlayer.ActionCount = PlayerActionCounter;

ThisActionPlayer.LastActionTick = Tick;

CurrentAction.Tick = Tick;

CurrentAction.Second = System.Convert.ToInt16(Tick / 8);

ThisActionPlayer.Actions.Add(CurrentAction);

this.Replay.Player[CurrentAction.ActionPlayer - 1000] = ThisActionPlayer;

}

else{

//CurrentAction.Second = System.Convert.ToInt16(Tick / 8);

//MessageBox.Show("Fehler ??? bei Sekunde: " + CurrentAction.Second.ToString() + " Player: " + CurrentAction.ActionPlayer.ToString());

}

}

catch

{

//MessageBox.Show("Fehler bei: " + BinReader.BaseStream.Position.ToString() + " Action: " + Action1.ToString() + " (" + Action1Len.ToString() + ")");

}

}

}

else

{

BinReader.ReadBytes(Action1Len);

// If empty action just read the action lenght

//BinReader.ReadBytes(Action1Len);

}

}

#endregion

#region GetReplayInformation

public bool GetReplayInformation(string FileName)

{

if(this.ReadHeader(FileName))

{

for(int players = 0; players < this.Replay.Slots; players++)

{

this.ReadPlayer();

this.Replay.Player.Add(this.Player);

}

this.Cache.Add(FileName,this.Replay);

this.BinReader.Close();

return true;

}

else

{

this.BinReader.Close();

return false;

}

}

#endregion

#region ReadReplay

public bool ReadReplay(string FileName)

{

if(this.ReadReplayOnly(FileName))

{

//Raise Event for Handlers

this.ReplayChanged(this, EventArgs.Empty);

return true;

}

else

{

return false;

}

}

#endregion

#region ReadReplayOnly

public bool ReadReplayOnly(string FileName)

{

if(this.ReadHeader(FileName))

{

if(this.Cache == null)

{

this.Cache = new Analyse(true);

}

//MessageBox.Show("Body Start...");

for(int players = 0; players < this.Replay.Slots; players++)

{

this.ReadPlayer();

this.Replay.Player.Add(this.Player);

}

this.Replay.ActionStart = BinReader.BaseStream.Position;

//MessageBox.Show("Body Done...");

//MessageBox.Show("Actions Start... (AT:" + BinReader.BaseStream.Position.ToString() + ")");

//{Now The acion Data starts.. DoW is working with 8Ticks per second}

while (BinReader.BaseStream.Position < BinReader.BaseStream.Length)

{

this.ReadActionDetail();

}

//MessageBox.Show("Actions Done...");

this.BinReader.Close();

this.Cache.Add(FileName,this.Replay);

return true;

}

else

{

this.BinReader.Close();

return false;

}

}

#endregion

}

}

"еще немного информации из инструмента debug менеджера AutoSave replays"

recformat.txt by hype[NZ]

-----------------------------------------------------------------------------

TYPE 0 CHUNK - EMPTY CHUNK

-----------------------------------------------------------------------------

00 00 00 00 \\ type 0 chunk... ordinary chunk

11 00 00 00 \\ length of chunk in this case length 17, implying empty chunk

50 \\ (P or 80) this is followed by the tick number

94 01 00 00 \\ tick number, starts at 01 00 00 00

6B 00 00 00 \\ number of actions performed in total.

\\ Doesn't count messages. Is only incremented after an action

\\ containing chunk has been performed, starts at 00 00 00 00

D6 78 72 72 \\ 'random' number generated during the game to calculate whether projectiles hit etc.

00 00 00 00 \\ no action - in this example this was an empty chunk

-----------------------------------------------------------------------------

TYPE 1 CHUNK - MESSAGING AND CHAT

-----------------------------------------------------------------------------

01 00 00 00 \\ chunk begins, type 1 so chat

3F 00 00 00 \\ length of chunk = 63

01 00 00 00 \\ chat version 1 (haven't seen any others yet)

36 00 00 00 \\ length until end of chunk

36 \\ byte containing same info afaik

0A 00 00 00 \\ length of player name, 10 here

l i n d e l o k s e \\ Player name, 10 double-bytes

EA 03 00 00 \\ Player ID [00 00 00 00 is observer (?)]

00 00 00 00 \\ message type, 0 = player, 1 = observer, 2 = system

00 00 00 00 \\ receiver, 0 = all, 1 = team, 2 = system

07 00 00 00 \\ length of message, 7 here

l i k e m e \\ message, 7 double-bytes

-----------------------------------------------------------------------------

BUILD SCOUT - FULL CHUNK EXAMPLE

-----------------------------------------------------------------------------

hype build scout Yao build scout \\ comments for Yao build scout

00 00 00 00 00 00 00 00 \\ type 0

3A 00 00 00 3A 00 00 00 \\ length 80

50 50 \\ P

A5 01 00 00 51 00 00 00 \\ timestamp 81

03 00 00 00 00 00 00 00 \\ total actions so far, this is the first

83 5E 0E 32 67 B2 68 92 \\ 'random number'

01 00 00 00 01 00 00 00 \\ one action in this chunk

0F 9E 82 29 9B 6A 75 53 \\ true multiplayer ID (in skirmish this is 00 00 00 00)

00 00 00 00 00 00 00 00 \\ all actions seem to have this so far

1C 00 00 00 1C 00 00 00 \\ length remaining

1C 1C 00 1C 1C 00 \\ length remaining byte, length remaining 2byte

B8 25 0D 00 B6 11 0D 00 \\ ??? depends on the player though (resources ???)

03 00 00 00 03 00 00 00 \\ build unit

73 73 \\ unit is scout

03 00 00 00 03 00 00 00 \\ build unit

E9 03 E9 03 E8 03 E8 03 \\ player ID

00 00 00 00 \\ number of actions by player

01 02 01 02 \\ 01 is number of things selected \\ 02 refers to building (01 = builder ???, 02 = building, 03 = unit)

69 67 \\ this is ingame building ID

05 00 00 00 05 00 00 00 \\ ???

\\ footnote: it seems that the scout's ID is not assigned here, rather the game assigns newly built units a specific number based on order built

\\ e.g. in a 1v1,

\\ 1st player servitor would be 50 C3 00 00 (dec 50000)

\\ 2nd player servitor would be 51 C3 00 00 (dec 50001)

\\ next unit built would be 52 C3 00 00 (dec 50002)

\\ etc

-----------------------------------------------------------------------------

UNIT COMMANDS

-----------------------------------------------------------------------------

> moving 4 squads around 2x scouts 2x tacs (subchunk only, west endian)

23 00 \\ length

D2 36 61 00 \\ mystery number

00 00 00 00 \\

00 \\

00 00 00 00 \\ move command

9E 30 9E 30 \\ player ID

32 00 \\ number of player actions so far

40 \\ 4 squads selected

30:95 3C 00 00 \\ unit ID marker:unit ID

30:85 3C 00 00

30:55 3C 00 00

30:65 3C 00 00

10 \\ ???

00 \\ move

3E EF \\ x ???

82 00 \\ y ???

D4 EF \\ z ???

> perform action on target (e.g. squads will attack an enemy, resume building a structure etc)

12 00

0D 31 71 00

00 00 00 00

00

00 00 00 00

9E 30 9E 30

92 00

10 \\ 01 - 1 unit selected

30:95 3C 00 00 \\ unit ID ... builder is 60:xx xx xx xx

10 70 \\ ?? always 01 \\ 07 = perform action on target (e.g. attack, build, repair) ??

57 50

00 00

-----------------------------------------------------------------------------

BUILDING STUFF

-----------------------------------------------------------------------------

------------------------------

GLOBAL STUFF

------------------------------

CANCEL UNIT SUBCHUNK

Each building records the list of units started in order. The code to cancel is just

the order in which the unit was started, even if it was started 20 mins later.

e.g. serv scout scout scout scout-> cancel 3rd scout, wait 20 mins serv -> cancel serv

cancel codes will be 05 and then 06

C1 00 \\length

FB 3E 1B 10 \\ ??? (syncing ???)

40 00 00 00 \\ primary command (cancel unit)

10 \\ cancel first unit in queue, see note above

00 00 00 00 \\ secondary command (none)

8E 30 8E 30 \\ player ID (1001)

40 00 \\ player actions

10 20 \\ 01 selected, 02 = building (for SM)

76 \\ building ID (could be 76 50 00 00, which would imply the next byte 00 means 'nothing to follow'

50 00 00 00 \\ ???

---------------------------------

SPACE MARINE build stuff subchunk

---------------------------------

(west endian)

> SPACE MARINE - build structure subchunk

82 00 \\ length remaining

AB D1 01 00

57 00 00 00 \\ servitor -> build something command (?)

97 \\ 77 = sacred artifact\\ 78 = armoury\\ 79 = rax\\ 7B = gen\\ 7C = HQ\\ 7F = lp

\\ 80 = mines\\ 81 orbital relay\\ 86 Big Gen\\ 87 = turret\\ 89 = machine cult

20 00 00 00 \\ build building command (02)

8E 30 8E 30

00 00 \\ player actions so far

10 10 \\ 1 unit selected \\ builder

8E 30 00 00 \\ Player ID

20

60:05 3C 00 00 \\ servitor ID

00

0A 00 \\

82 00 \\

8B 10 \\ coordinates (x,y,?)

> SPACE MARINE - build unit subchunk (space marine);

C1 00

55 63 01 00

30 00 00 00 \\ build

67 \\ 52 = Apothecary \\ 54 = ASM \\ 5A = Chaplain \\ 5D = Dreadnaught \\ 63 = Force Commander

\\ 65 = Grey Knight \\ 68 = Landraider \\ 69 = landspeeder \\ 6C = Librarian \\ 6F = predator

\\ 71 = rhino \\ 73 = scout \\ 76 = servitor \\ 7C = tac \\ 7F = Terminators\\ 80 = Assault Terminators \\ 89 = whirlwind

30 00 00 00 \\ build unit command (03)

8E 30 8E 30

10 00

10 20 \\ 1 thing selected \\ 02 => building

76 \\ ingame building ID

50 00 00 00

> SPACE MARINE - addons (tier2, tier3, lp2, lp3 etc)

C1 00

17 B0 B0 00

70 00 00 00

92 \\29 = SM tier 2 \\ 2A = SM tier 3 \\ 2B = SM lp2 \\ 2C = SM lp3 \\2E = missile turret addon

C0 00 00 00

8E 30 8E 30

30 00

10 20

11

60 00 00 00

> SPACE MARINE - population increase

C1 00

50 D4 70 00

60 00 00 00

AA \\ AA = inf_01 \\ AB = inf_02 \\ AC = inf_03 \\ AD = inf_04 \\

\\ AE = veh_01 \\ AF = veh_02 \\ B0 = veh_03 \\ B1 = veh_04 \\

E0 00 00 00

9E 30 9E 30

31 00

10 20

EA

E0 00 00 00

> SPACE MARINE - wargear

C1 00

2F F1 C0 00

60 00 00 00 \\ 70 00 00 00 for HQ wargear

70 \\ 07 = Power Sword + Pistol \\ 09 = Daemonhammer + Melta \\ 10 = Champion Cincture \\ 11 = Iron Halo

\\ 12 = Bracers of the Righteous \\ 13 = Heroism Pedestal \\ 14 = Master Armour \\ 15 = Orbital Strike Wargear

E0 00 00 00 \\ C0 00 00 00 for HQ wargear

9E 30 9E 30

F2 00

10 20

4B \\ building ingame ID

E0 00 00 00

---------------------------

NECRON build stuff subchunk

---------------------------

> NECRON - build unit

C1 00

27 FE 94 00

30 00 00 00

2B \\ B2 = NW \\ B8 = Deceiver \\ BB = Destroyer \\ BD = Flayed \\BF = Heavy Destroyer

\\ C1 = Immortal \\ C4 = Destroyer Lord \\ C5 = Necron Lord \\CB = Pariah \\ D7 = Wraith \\

20 00 00 00

8E 30 8E 30

70 00

10 20

4A

E0 00 00 00

> NECRON - build structure

82 00

86 9F E0 00

57 00 00 00 \\ builder unit build

6A \\ A2 = monolith \\ A6 = Forbidden archives \\ A5 = Energy Core \\ A7 = Greater Summoning Core \\ A8 = LP

\\ A9 = Gen \\ AA = Summoning Core \\ AC = Thermogan \\ AE = turret \\ D5 = tombspyder

10 00 00 00 \\ Structure

9E 30 9E 30

00 00

10 10

9E 30 00 00 \\ player ID again

20

60:45 3C 00 00

00

45 10

B4 00

0D DF

> NECRON - addons

C1 00

EB D5 94 00

70 00 00 00

0D \\ D0 = Necron Tier 2 \\ D1 = Necron tier 3 \\ D3 = lp2 \\ D4 = lp3 \\ D5 = Gauss turret II \\

B0 00 00 00

8E 30 8E 30

50 00

10 20

31 \\ building ingame ID

E0 00 00 00 \\ can be different, but the same throughout each rep

> NECRON - wargear (similar to addons)

C1 00

B9 A7 E4 00

70 00 00 00

B1 \\ 16 = Death Mask \\ 17 = Mantle of Doom \\ 18 = Extinction Claw

\\ 19 = Herald of Woe \\ 1A = Raiment End of times \\ 1B = Heart of Darkness \\

C0 00 00 00

8E 30 8E 30

81 00

10 20

5B

E0 00 00 00

C1 00 \\ from different rep (skirmish)

F2 B0 20 00

60 00 00 00

C2 \\ 2A = NL weapon_01 \\ 2C = NL weaponn_02

E0 00 00 00

8E 30 8E 30

91 00

10 20

D7

50 00 00 00

> NECRON - Summon Nightbringer

12 00

45 B9 F4 00

35 00 00 00 \\ ability (?)

00

00 00 00 00

8E 30 8E 30

B1 00

10 \\ number of units selected

30:26 3C 00 00 \\ Necron Lord ingame ID

10 70 \\ ???

1D E0 \\ ???

00 00 \\ ???

________________________________________________________________________________

_________________________________

COORDINATES: Blood River

/|\

/ | \ x -axis

/ | 2\

left crit/ o \right crit (origin) (1270,1270)

\ | /

\1 | /

\ | /y-axis

north A0 BF 38 00 6F 40 \\ 64266 \\ 131 \\ 1270 \\

east 6F 40 C2 10 6F 40 \\ 1270 \\ 300 \\ 1270 \\

south 6F 40 E3 00 A0 BF \\ 1270 \\ 62 \\ 64266 \\

west A0 BF 66 00 A0 BF \\ 64266 \\ 102 \\ 64266 \\

xx xx zz zz yy yy

start at left crit and go clockwise, all these are just rally monolith

note FB 0A + 04 F6 = FF FF + 1

left crit ** _________________

32 00 E3 8A 3C 00 E0 00 00 00 00 00 00 00 00 9E 30 9E 30 00 00 10 20 CA 40 00 00 10 00 A0 BF 76 00 A0 BF

32 00 10 9A 3C 00 E0 00 00 00 00 00 00 00 00 9E 30 9E 30 10 00 10 20 CA 40 00 00 10 00 A0 BF 66 00 A0 BF

32 00 0E 9A 3C 00 E0 00 00 00 00 00 00 00 00 9E 30 9E 30 20 00 10 20 CA 40 00 00 10 00 A0 BF 66 00 A0 BF

32 00 4B AA 3C 00 E0 00 00 00 00 00 00 00 00 9E 30 9E 30 30 00 10 20 CA 40 00 00 10 00 A0 BF 66 00 A0 BF

32 00 DA BA 3C 00 E0 00 00 00 00 00 00 00 00 9E 30 9E 30 40 00 10 20 CA 40 00 00 10 00 A0 BF 66 00 A0 BF

top **

32 00 6D BC 3C 00 E0 00 00 00 00 00 00 00 00 9E 30 9E 30 60 00 10 20 CA 40 00 00 10 00 A0 BF 38 00 6F 40

32 00 1D CC 3C 00 E0 00 00 00 00 00 00 00 00 9E 30 9E 30 70 00 10 20 CA 40 00 00 10 00 A0 BF 38 00 6F 40

32 00 BD DC 3C 00 E0 00 00 00 00 00 00 00 00 9E 30 9E 30 80 00 10 20 CA 40 00 00 10 00 A0 BF 38 00 6F 40

32 00 6C EC 3C 00 E0 00 00 00 00 00 00 00 00 9E 30 9E 30 90 00 10 20 CA 40 00 00 10 00 A0 BF 38 00 6F 40

right crit **

32 00 37 1E 3C 00 E0 00 00 00 00 00 00 00 00 9E 30 9E 30 A0 00 10 20 CA 40 00 00 10 00 6F 40 C2 10 6F 40

32 00 64 2E 3C 00 E0 00 00 00 00 00 00 00 00 9E 30 9E 30 B0 00 10 20 CA 40 00 00 10 00 6F 40 C2 10 6F 40

32 00 02 3E 3C 00 E0 00 00 00 00 00 00 00 00 9E 30 9E 30 C0 00 10 20 CA 40 00 00 10 00 6F 40 C2 10 6F 40

32 00 90 4E 3C 00 E0 00 00 00 00 00 00 00 00 9E 30 9E 30 D0 00 10 20 CA 40 00 00 10 00 6F 40 C2 10 6F 40

32 00 8F 4E 3C 00 E0 00 00 00 00 00 00 00 00 9E 30 9E 30 E0 00 10 20 CA 40 00 00 10 00 6F 40 C2 10 6F 40

harbour **

32 00 5A 8F 3C 00 E0 00 00 00 00 00 00 00 00 9E 30 9E 30 F0 00 10 20 CA 40 00 00 10 00 6F 40 F3 00 A0 BF

32 00 09 9F 3C 00 E0 00 00 00 00 00 00 00 00 9E 30 9E 30 01 00 10 20 CA 40 00 00 10 00 6F 40 E3 00 A0 BF

32 00 26 AF 3C 00 E0 00 00 00 00 00 00 00 00 9E 30 9E 30 11 00 10 20 CA 40 00 00 10 00 6F 40 E3 00 A0 BF

32 00 65 BF 3C 00 E0 00 00 00 00 00 00 00 00 9E 30 9E 30 21 00 10 20 CA 40 00 00 10 00 6F 40 E3 00 A0 BF

32 00 E4 CF 3C 00 E0 00 00 00 00 00 00 00 00 9E 30 9E 30 31 00 10 20 CA 40 00 00 10 00 6F 40 E3 00 A0 BF

32 00 E4 CF 3C 00 E0 00 00 00 00 00 00 00 00 9E 30 9E 30 31 00 10 20 CA 40 00 00 10 00 6F 40 E3 00 A0 BF

left crit going clockwise sort of

32 00 F2 A1 4C 00 E0 00 00 00 00 00 00 00 00 9E 30 9E 30 41 00 10 20 CA 40 00 00 10 00 A0 BF 82 00 E2 BF

32 00 3D A1 4C 00 E0 00 00 00 00 00 00 00 00 9E 30 9E 30 51 00 10 20 CA 40 00 00 10 00 A0 BF 82 00 F2 BF

32 00 DA B1 4C 00 E0 00 00 00 00 00 00 00 00 9E 30 9E 30 61 00 10 20 CA 40 00 00 10 00 A0 BF 82 00 B2 BF

32 00 79 C1 4C 00 E0 00 00 00 00 00 00 00 00 9E 30 9E 30 71 00 10 20 CA 40 00 00 10 00 A0 BF 82 00 A2 BF

32 00 E4 D1 4C 00 E0 00 00 00 00 00 00 00 00 9E 30 9E 30 81 00 10 20 CA 40 00 00 10 00 A0 BF 82 00 D4 BF

32 00 5F D1 4C 00 E0 00 00 00 00 00 00 00 00 9E 30 9E 30 91 00 10 20 CA 40 00 00 10 00 A0 BF 72 00 44 CF

32 00 DA E1 4C 00 E0 00 00 00 00 00 00 00 00 9E 30 9E 30 A1 00 10 20 CA 40 00 00 10 00 A0 BF 82 00 32 CF

Изменено пользователем USSRxAZ
Ссылка на комментарий
Поделиться на другие сайты

Где же перенесенная дискуссия?

А самому слабо?

2 Ламо: Вот тут достаточно всяких примеров.

post-25209-1302637908_thumb.png

Постарайся обойтись без ссылок на г@вносайты. Кидай реплеи с синками без обсов (желательно сразу все одним архивом), или с синками во время простоя прямо сюда.

2 Морти: Считаю, что разрыв цепочки можно восстановить, исключив выпавшее звено.

Похоже с первого раза смысл написанного Морталесом до тебя не дошел. Бывает, но чтобы продолжать дискуссию, тебе необходимо перечитать его сообщение, еще и еще, пока не придет озарение.

Даже без обсов синк эроры происходят. Почему-то они чаще всего происходят, когда в играх есть некроны.

Синки связаны не непосредственно с обсами, а со сворачиваниями игры. Но естественно, что сворачиваются прежде всего обсы. А что касается некронов - видимо в силу особенностей геймплея, они находят время и посредине игры свернуться без ушерба для контроля.

Изменено пользователем переведунец
Ссылка на комментарий
Поделиться на другие сайты

Если ничего не делать - ничего и не получится.

Хотелось бы узнать для начала - как изменяется структура реплея при синк эрроре. Т. е. на каком временном интервале выпадает синхронизация игровых событий? (Для того, чтобы понимать объем работ по посстановлению реплея).

Считаю, что синхронизация - дело восстановимое, иначе бы игра он-лайн также останавливалась при критическом альт-табе :)

Значит остается поднять механизм самовосстановления и использовать его в деле восстановления реплеев.

Да вообще, считаю, что методов решения различных программных задач множество! Даже не стану приводить примеры - сами все знаете.

Надо работать над тем как ЭТО СДЕЛАТЬ, а не "всё потеряно! Мы все умрём!"

Ссылка на комментарий
Поделиться на другие сайты

Хотелось бы узнать для начала - как изменяется структура реплея при синк эрроре.

Ты сам с собой чтоли разговариваешь? Тебе уже несколько раз объяснили это, и если ты не можешь понять настолько элементарных вещей, то не стоит даже грезить о восстановлении своими силами.

Все что мы можем сами - это попробовать разобраться в точных причинах ошибок, и если ты хочешь помочь, то будь добр, закинь сюда примеры реплеев о которых ты столько говорил.

Ссылка на комментарий
Поделиться на другие сайты

Все объяснения заключались в неподтвержденных суждениях. Я бы хотел разобраться в бинарном коде.

Реплеи нужно сначала найти (просмотрев их как минимум и убедившись, что они без обсов), затем выложить. Это как минимум вечером.

Далее. Хотелось бы поработать с самим менеджером реплеев, т. к. мне мало что дает его исходный код (я не силен в программировании).

Ссылка на комментарий
Поделиться на другие сайты

Считаю, что синхронизация - дело восстановимое, иначе бы игра он-лайн также останавливалась при критическом альт-табе

Нет, онлайн игры не при чем. Там ты от сервера все данные получаешь, при чем здесь альт-таб? А тут другая ситуация. Задача, которую ты хочешь решить, мне представляется следующим образом: сначала я зашел в лабиринт, потом повернул налево, потом направо, потом вошел во 2-ой туннель слева, потом опять повернул направо, потом я час блуждал по лабиринту, не запоминая, куда я сворачиваю, потом я покурил у стенки с изображением древнего человека и от того места пошел налево-направо-направо и т. д. Задача: выбраться из лабиринта. Давайте просто восстановим как-нибудь тот фрагмент, когда я блуждал, выбирая случайные направления и не запоминая их, и все будет ок. А если что-то не сойдется, я буду попадать в забавные тупики.

Изменено пользователем mortales
Ссылка на комментарий
Поделиться на другие сайты

я изза этих разговоров почти дописал скрипт аплоада реплея на сайт)
А это поможет делу восстановления реплеев?

если что-то не сойдется, я буду попадать в забавные тупики
Лучше попадать в забавные тупики, чем сесть где остановился и умереть.

[ Добавлено спустя 8 минут 29 секунд ]

И еще мне не понятно, действительно ли игрой управляет сервер? По моим наблюдениям создаются пиринговые связи между компьютерами игроков. Это видно из консоли, где коннект создается со всеми игроками, косвенно это подтверждает пропорциональное увеличение потока данных в зависимости от количества присутствующих. Если связи пиринговые - то сервер нужен лишь для ведения статистики и возврата в общий чат. Поправьте, если я не прав.

Изменено пользователем _Master_
Ссылка на комментарий
Поделиться на другие сайты

В ДоВ - пиринговые, наверное, а вообще это от игры зависит. Но и не в этом дело.

Лучше попадать в забавные тупики, чем сесть где остановился и умереть

Это была ирония, при чем тут "остановиться и умереть"? Напишу яснее: если я прав, восстановить реплей невозможно.

Изменено пользователем mortales
Ссылка на комментарий
Поделиться на другие сайты

Кроме того напомню про возможность создания собственных серверов (в меню есть такая функция).

[ Добавлено спустя 14 минуты 2 секунды ]

при чем тут "остановиться и умереть"
Это тоже была ирония. Напишу яснее: чтобы выяснить прав ты или не прав, нужно хоть что-то попытаться реализовать.
Ссылка на комментарий
Поделиться на другие сайты

Пожалуйста, войдите, чтобы комментировать

Вы сможете оставить комментарий после входа в



Войти
×
×
  • Создать...