AGS.Editor.DataFileWriter.SaveThisGameToFile C# (CSharp) Метод

SaveThisGameToFile() публичный статический Метод

public static SaveThisGameToFile ( string fileName, Game game, CompileMessages errors ) : bool
fileName string
game AGS.Types.Game
errors CompileMessages
Результат bool
        public static bool SaveThisGameToFile(string fileName, Game game, CompileMessages errors)
        {
            FileStream ostream = File.Create(fileName);
            if (ostream == null)
            {
                errors.Add(new CompileError(string.Format("Cannot open file {0} for writing", fileName)));
                return false;
            }
            BinaryWriter writer = new BinaryWriter(ostream);
            WriteString(NativeConstants.GAME_FILE_SIG, NativeConstants.GAME_FILE_SIG.Length, writer);
            writer.Write(NativeConstants.GAME_DATA_VERSION_CURRENT);
            writer.Write(AGS.Types.Version.AGS_EDITOR_VERSION.Length);
            WriteString(AGS.Types.Version.AGS_EDITOR_VERSION, AGS.Types.Version.AGS_EDITOR_VERSION.Length, writer);
            // Write extended engine caps; none for this version
            writer.Write((int)0);
            // An example of writing caps (pseduo-code):
            //   writer.Write(caps.Count);
            //   foreach (cap in caps)
            //       FilePutString(cap.Name);
            //
            WriteGameSetupStructBase_Aligned(writer, game);
            WriteString(game.Settings.GUIDAsString, NativeConstants.MAX_GUID_LENGTH, writer);
            WriteString(game.Settings.SaveGameFileExtension, NativeConstants.MAX_SG_EXT_LENGTH, writer);
            WriteString(game.Settings.SaveGameFolderName, NativeConstants.MAX_SG_FOLDER_LEN, writer);
            if (game.Fonts.Count > NativeConstants.MAX_FONTS)
            {
                errors.Add(new CompileError("Too many fonts"));
                return false;
            }
            for (int i = 0; i < game.Fonts.Count; ++i)
            {
                writer.Write((byte)(game.Fonts[i].PointSize & NativeConstants.FFLG_SIZEMASK));
            }
            for (int i = 0; i < game.Fonts.Count; ++i)
            {
                if (game.Fonts[i].OutlineStyle == FontOutlineStyle.None)
                {
                    writer.Write((sbyte)-1);
                }
                else if (game.Fonts[i].OutlineStyle == FontOutlineStyle.Automatic)
                {
                    writer.Write(NativeConstants.FONT_OUTLINE_AUTO);
                }
                else
                {
                    writer.Write((byte)game.Fonts[i].OutlineFont);
                }
            }
            for (int i = 0; i < game.Fonts.Count; ++i)
            {
                writer.Write(game.Fonts[i].VerticalOffset);
            }
            writer.Write(NativeConstants.MAX_SPRITES);
            byte[] spriteFlags = new byte[NativeConstants.MAX_SPRITES];
            UpdateSpriteFlags(game.RootSpriteFolder, spriteFlags);
            for (int i = 0; i < NativeConstants.MAX_SPRITES; ++i)
            {
                writer.Write(spriteFlags[i]);
            }
            if (game.InventoryItems.Count > NativeConstants.MAX_INV)
            {
                errors.Add(new CompileError("Too many inventory items"));
                return false;
            }
            writer.Write(new byte[68]); // inventory item slot 0 is unused
            for (int i = 0; i < game.InventoryItems.Count; ++i)
            {
                WriteString(game.InventoryItems[i].Description, 24, writer);
                writer.Write(new byte[4]); // null terminator plus 3 bytes padding
                writer.Write(game.InventoryItems[i].Image);
                writer.Write(game.InventoryItems[i].CursorImage);
                writer.Write(game.InventoryItems[i].HotspotX);
                writer.Write(game.InventoryItems[i].HotspotY);
                for (int j = 0; j < 5; ++j) // write "reserved", currently unused
                {
                    writer.Write(0);
                }
                writer.Write(game.InventoryItems[i].PlayerStartsWithItem ? NativeConstants.IFLG_STARTWITH : (char)0);
                writer.Write(new byte[3]); // 3 bytes padding
            }
            if (game.Cursors.Count > NativeConstants.MAX_CURSOR)
            {
                errors.Add(new CompileError("Too many cursors"));
                return false;
            }
            for (int i = 0; i < game.Cursors.Count; ++i)
            {
                char flags = (char)0;
                writer.Write(game.Cursors[i].Image);
                writer.Write((short)game.Cursors[i].HotspotX);
                writer.Write((short)game.Cursors[i].HotspotY);
                if (game.Cursors[i].Animate)
                {
                    writer.Write((short)(game.Cursors[i].View - 1));
                    if (game.Cursors[i].AnimateOnlyOnHotspots) flags |= NativeConstants.MCF_HOTSPOT;
                    if (game.Cursors[i].AnimateOnlyWhenMoving) flags |= NativeConstants.MCF_ANIMMOVE;
                }
                else writer.Write((short)-1);
                WriteString(game.Cursors[i].Name, 9, writer);
                writer.Write((byte)0); // null terminator
                if (game.Cursors[i].StandardMode) flags |= NativeConstants.MCF_STANDARD;
                writer.Write(flags);
                writer.Write(new byte[3]); // 3 bytes padding
            }
            for (int i = 0; i < game.Characters.Count; ++i)
            {
                SerializeInteractionScripts(game.Characters[i].Interactions, writer);
            }
            for (int i = 1; i <= game.InventoryItems.Count; ++i)
            {
                SerializeInteractionScripts(game.InventoryItems[i - 1].Interactions, writer);
            }
            writer.Write(game.TextParser.Words.Count);
            for (int i = 0; i < game.TextParser.Words.Count; ++i)
            {
                WriteStringEncrypted(writer, SafeTruncate(game.TextParser.Words[i].Word, NativeConstants.MAX_PARSER_WORD_LENGTH));
                writer.Write((short)game.TextParser.Words[i].WordGroup);
            }
            if (!WriteCompiledScript(ostream, game.ScriptsToCompile.GetScriptByFilename(Script.GLOBAL_SCRIPT_FILE_NAME), errors) ||
                !WriteCompiledScript(ostream, game.ScriptsToCompile.GetScriptByFilename(Script.DIALOG_SCRIPTS_FILE_NAME), errors))
            {
                return false;
            }
            // Extract all the scripts we want to persist (all the non-headers, except
            // the global script which was already written)
            List<Script> scriptsToWrite = new List<Script>();
            foreach (ScriptAndHeader scriptAndHeader in game.ScriptsToCompile)
            {
                Script script = scriptAndHeader.Script;
                if (script != null)
                {
                    if ((!script.FileName.Equals(Script.GLOBAL_SCRIPT_FILE_NAME)) &&
                        (!script.FileName.Equals(Script.DIALOG_SCRIPTS_FILE_NAME)))
                    {
                        scriptsToWrite.Add(script);
                    }
                }
            }
            writer.Write(scriptsToWrite.Count);
            foreach (Script script in scriptsToWrite)
            {
                if (!WriteCompiledScript(ostream, script, errors))
                {
                    return false;
                }
            }
            ViewsWriter viewsWriter = new ViewsWriter(writer, game);
            if (!viewsWriter.WriteViews(FolderHelper.GetRootViewFolder(game), game, errors))
            {
                return false;
            }
            foreach (Character character in game.Characters)
            {
                int flags = 0;
                if (character.AdjustSpeedWithScaling) flags |= NativeConstants.CHF_SCALEMOVESPEED;
                if (character.AdjustVolumeWithScaling) flags |= NativeConstants.CHF_SCALEVOLUME;
                if (!character.Clickable) flags |= NativeConstants.CHF_NOINTERACT;
                if (!character.DiagonalLoops) flags |= NativeConstants.CHF_NODIAGONAL;
                if (character.MovementLinkedToAnimation) flags |= NativeConstants.CHF_ANTIGLIDE;
                if (!character.Solid) flags |= NativeConstants.CHF_NOBLOCKING;
                if (!character.TurnBeforeWalking) flags |= NativeConstants.CHF_NOTURNING;
                if (!character.UseRoomAreaLighting) flags |= NativeConstants.CHF_NOLIGHTING;
                if (!character.UseRoomAreaScaling) flags |= NativeConstants.CHF_MANUALSCALING;
                writer.Write(character.NormalView - 1);                // defview
                writer.Write(character.SpeechView - 1);                // talkview
                writer.Write(character.NormalView - 1);                // view
                writer.Write(character.StartingRoom);                  // room
                writer.Write(0);                                       // prevroom
                writer.Write(character.StartX);                        // x
                writer.Write(character.StartY);                        // y
                writer.Write(0);                                       // wait
                writer.Write(flags);                                   // flags
                writer.Write((short)0);                                // following
                writer.Write((short)0);                                // followinfo
                writer.Write(character.IdleView - 1);                  // idleview
                writer.Write((short)0);                                // idletime
                writer.Write((short)0);                                // idleleft
                writer.Write((short)0);                                // transparency
                writer.Write((short)0);                                // baseline
                writer.Write(0);                                       // activeinv
                writer.Write(character.SpeechColor);                   // talkcolor
                writer.Write(character.ThinkingView - 1);              // thinkview
                writer.Write((short)(character.BlinkingView - 1));     // blinkview
                writer.Write((short)0);                                // blinkinterval
                writer.Write((short)0);                                // blinktimer
                writer.Write((short)0);                                // blinkframe
                writer.Write(character.UniformMovementSpeed ?          // walkspeed_y
                    NativeConstants.UNIFORM_WALK_SPEED :
                    (short)character.MovementSpeedY);
                writer.Write((short)0);                                // pic_yoffs
                writer.Write(0);                                       // z
                writer.Write(0);                                       // walkwait
                writer.Write((short)character.SpeechAnimationDelay);   // speech_anim_speed
                writer.Write((short)0);                                // reserved1
                writer.Write((short)0);                                // blocking_width
                writer.Write((short)0);                                // blocking_height
                writer.Write(0);                                       // index_id
                writer.Write((short)0);                                // pic_xoffs
                writer.Write((short)0);                                // walkwaitcounter
                writer.Write((short)0);                                // loop
                writer.Write((short)0);                                // frame
                writer.Write((short)0);                                // walking
                writer.Write((short)0);                                // animating
                writer.Write(character.UniformMovementSpeed ?          // walkspeed
                    (short)character.MovementSpeed :
                    (short)character.MovementSpeedX);
                writer.Write((short)character.AnimationDelay);         // animspeed
                bool isPlayer = (character == game.PlayerCharacter);
                foreach (InventoryItem invItem in game.InventoryItems) // inv[MAX_INV]
                {
                    if ((isPlayer) && (invItem.PlayerStartsWithItem)) writer.Write((short)1);
                    else writer.Write((short)0);
                }
                if (game.InventoryItems.Count < NativeConstants.MAX_INV)
                {
                    writer.Write(new byte[(NativeConstants.MAX_INV - game.InventoryItems.Count) * sizeof(short)]);
                }
                writer.Write((short)0);                                // actx
                writer.Write((short)0);                                // acty
                WriteString(character.RealName, 40, writer);           // name
                WriteString(character.ScriptName, NativeConstants.MAX_SCRIPT_NAME_LEN, writer); // scrname
                writer.Write((char)1);                                 // on
                writer.Write((byte)0);                                 // alignment padding
            }
            for (int i = 0; i < NativeConstants.MAXLIPSYNCFRAMES; ++i)
            {
                WriteString(game.LipSync.CharactersPerFrame[i], 50, writer);
            }
            for (int i = 0; i < NativeConstants.MAXGLOBALMES; ++i)
            {
                if (string.IsNullOrEmpty(game.GlobalMessages[i])) continue;
                WriteStringEncrypted(writer, game.GlobalMessages[i]);
            }
            if (game.Dialogs.Count > NativeConstants.MAX_DIALOG)
            {
                errors.Add(new CompileError("Too many dialogs"));
                return false;
            }
            foreach (Dialog curDialog in game.Dialogs)
            {
                for (int i = 0; (i < NativeConstants.MAXTOPICOPTIONS) && (i < curDialog.Options.Count); ++i)
                {
                    WriteString(curDialog.Options[i].Text, 150, writer); // optionnames
                }
                for (int i = curDialog.Options.Count; i < NativeConstants.MAXTOPICOPTIONS; ++i)
                {
                    WriteString("", 150, writer);
                }
                for (int i = 0; (i < NativeConstants.MAXTOPICOPTIONS) && (i < curDialog.Options.Count); ++i)
                {
                    DialogOption option = curDialog.Options[i];
                    int flags = 0;
                    if (!option.Say) flags |= NativeConstants.DFLG_NOREPEAT;
                    if (option.Show) flags |= NativeConstants.DFLG_ON;
                    writer.Write(flags); // optionflags
                }
                for (int i = curDialog.Options.Count; i < NativeConstants.MAXTOPICOPTIONS; ++i)
                {
                    writer.Write(0);
                }
                writer.Write(new byte[4]); // optionscripts
                writer.Write(new byte[NativeConstants.MAXTOPICOPTIONS * sizeof(short)]); // entrypoints
                writer.Write((short)0); // startupentrypoint
                writer.Write((short)0); // codesize
                writer.Write(curDialog.Options.Count); // numoptions
                writer.Write(curDialog.ShowTextParser ? NativeConstants.DTFLG_SHOWPARSER : 0); // topicflags
            }
            GUIsWriter guisWriter = new GUIsWriter(writer, game);
            guisWriter.WriteAllGUIs();
            if (!WritePluginsToDisk(writer, game, errors))
            {
                return false;
            }
            writer.Write(NativeConstants.CustomPropertyVersion.Current);
            writer.Write(game.PropertySchema.PropertyDefinitions.Count);
            foreach (CustomPropertySchemaItem schemaItem in game.PropertySchema.PropertyDefinitions)
            {
                FilePutString(schemaItem.Name, writer);
                writer.Write((int)schemaItem.Type);
                FilePutString(schemaItem.Description, writer);
                FilePutString(schemaItem.DefaultValue, writer);
            }
            for (int i = 0; i < game.Characters.Count; ++i)
            {
                CustomPropertiesWriter.Write(writer, game.Characters[i].Properties);
            }
            writer.Write(1); // inv slot 0 is unused, write the property header (int 1)
            writer.Write(0); // then write the number of props used by this inv item (int 0)
            for (int i = 0; i < game.InventoryItems.Count; ++i)
            {
                CustomPropertiesWriter.Write(writer, game.InventoryItems[i].Properties);
            }
            for (int i = 0; i < game.ViewCount; ++i) // ViewCount is highest numbered view
            {
                View view = game.FindViewByID(i + 1);
                if (view != null)
                    FilePutNullTerminatedString(view.Name, view.Name.Length + 1, writer);
                else
                    writer.Write((byte)0); // view is null, so its name is just a single NUL byte
            }
            writer.Write((byte)0); // inventory slot 0 is unused, so its name is just a single NUL byte
            for (int i = 0; i < game.InventoryItems.Count; ++i)
            {
                string buffer = game.InventoryItems[i].Name;
                FilePutNullTerminatedString(buffer, buffer.Length + 1, writer);
            }
            for (int i = 0; i < game.Dialogs.Count; ++i)
            {
                string buffer = game.Dialogs[i].Name;
                FilePutNullTerminatedString(buffer, buffer.Length + 1, writer);
            }
            writer.Write(game.AudioClipTypes.Count + 1);
            // hard coded SPEECH audio type 0
            writer.Write(0); // id
            writer.Write(1); // reservedChannels
            writer.Write(0); // volume_reduction_while_speech_playing
            writer.Write(0); // crossfadeSpeed
            writer.Write(0); // reservedForFuture
            for (int i = 1; i < (game.AudioClipTypes.Count + 1); ++i)
            {
                writer.Write(i); // id
                writer.Write(game.AudioClipTypes[i - 1].MaxChannels); // reservedChannels
                writer.Write(game.AudioClipTypes[i - 1].VolumeReductionWhileSpeechPlaying); // volume_reduction_while_speech_playing
                writer.Write((int)game.AudioClipTypes[i - 1].CrossfadeClips); // crossfadeSpeed
                writer.Write(0);
            }
            IList<AudioClip> allClips = game.CachedAudioClipListForCompile;
            writer.Write(allClips.Count);
            for (int i = 0; i < allClips.Count; ++i)
            {
                AudioClip clip = allClips[i];
                writer.Write(0); // id
                WriteString(SafeTruncate(clip.ScriptName, 29), 30, writer); // scriptName
                WriteString(SafeTruncate(clip.CacheFileNameWithoutPath, 14), 15, writer); // fileName
                writer.Write((byte)clip.BundlingType); // bundlingType
                writer.Write((byte)clip.Type); // type
                writer.Write((byte)clip.FileType); // fileType
                writer.Write(clip.ActualRepeat ? (byte)1 : (byte)0); // defaultRepeat
                writer.Write((byte)0); // struct alignment padding
                writer.Write((short)clip.ActualPriority); // defaultPriority
                writer.Write((short)clip.ActualVolume); // defaultVolume
                writer.Write(new byte[2]); // struct alignment padding
                writer.Write(0); // reserved
            }
            writer.Write(game.GetAudioArrayIndexFromAudioClipIndex(game.Settings.PlaySoundOnScore));
            if (game.Settings.DebugMode)
            {
                writer.Write(game.Rooms.Count);
                for (int i = 0; i < game.Rooms.Count; ++i)
                {
                    IRoom room = game.Rooms[i];
                    writer.Write(room.Number);
                    if (room.Description != null)
                    {
                        FilePutNullTerminatedString(room.Description, 500, writer);
                    }
                    else writer.Write((byte)0);
                }
            }
            writer.Close();
            GC.Collect();
            return true;
        }