/* * SaverLoader.cs * Authors: Mike Dapiran, Mike DeMauro * Copyright (c) 2007-2008 Cornell University 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.Collections.Generic; using System.Text; using System.IO; using Util; using ColonySim.Structures; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Content; using tAC_Engine.Graphics.Entities; using Microsoft.Xna.Framework.Graphics; namespace ColonySim { static class SaverLoader { public static string SAVE_NAME { get { return @"game.csg"; } } private enum StructureCode { Tube = 1, Road = 2, CommandPost = 3, Commercial = 4, Entertainment = 5, Factory = 6, MiningPlant = 7, Residential = 8 } private static string GenerateResourceString(Resource[,] pResourceGrid) { StringBuilder returnString = new StringBuilder(); int width = pResourceGrid.GetLength(0); int height = pResourceGrid.GetLength(1); returnString.Append(width); returnString.Append(" "); returnString.Append(height); returnString.Append("\n"); for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { if (pResourceGrid[i, j] != null) { returnString.Append(i); returnString.Append(" "); returnString.Append(j); returnString.Append(" "); returnString.Append((int)pResourceGrid[i, j].ResourceCode); returnString.Append("\n"); } } } returnString.Append("/"); return returnString.ToString(); } private static Resource[,] LoadResourceGrid(TextReader reader) { string input = reader.ReadLine(); Resource[,] returnGrid = new Resource[Convert.ToInt32(input.Split()[0]), Convert.ToInt32(input.Split()[1])]; input = reader.ReadLine(); while (input != "/") { string[] inputArray = input.Split(); Resource temp = new Resource(); temp.ResourceCode = (ResourceCode)Enum.ToObject(typeof(ResourceCode), Convert.ToInt32(inputArray[2])); returnGrid[Convert.ToInt32(inputArray[0]), Convert.ToInt32(inputArray[1])] = temp; input = reader.ReadLine(); } return returnGrid; } private static string GenerateStructureString(Structure[,] pStructureGrid) { StringBuilder returnString = new StringBuilder(); int xMax = pStructureGrid.GetLength(0); int yMax = pStructureGrid.GetLength(1); List savedStructures = new List(); for (int i = 0; i < xMax; i++) { for (int j = 0; j < yMax; j++) { if (pStructureGrid[i, j] != null && !savedStructures.Contains(pStructureGrid[i,j])) { returnString.Append(pStructureGrid[i,j].GridPosition.X); returnString.Append(" "); returnString.Append(pStructureGrid[i, j].GridPosition.Y); returnString.Append(" "); if (pStructureGrid[i, j] is CommandPost) returnString .Append( (int)StructureCode.CommandPost); if (pStructureGrid[i, j] is Commercial) returnString .Append( (int)StructureCode.Commercial); if (pStructureGrid[i, j] is Entertainment) returnString .Append( (int)StructureCode.Entertainment); if (pStructureGrid[i, j] is Factory) returnString .Append( (int)StructureCode.Factory); if (pStructureGrid[i, j] is MiningPlant) returnString .Append( (int)StructureCode.MiningPlant); if (pStructureGrid[i, j] is Residential) returnString .Append( (int)StructureCode.Residential); if (pStructureGrid[i, j] is Tube) returnString .Append( (int)StructureCode.Tube); if (pStructureGrid[i, j] is Road) returnString .Append( (int)StructureCode.Road); returnString.Append(" "); returnString .Append(pStructureGrid[i,j].ToSaveString()); savedStructures.Add(pStructureGrid[i, j]); } } } returnString .Append("/"); return returnString.ToString(); } private static void LoadStructures(TextReader reader, AddStructureDelegate pAddStructureMethod, Structure[,] pStructureGrid, Resource[,] pResourceGrid, ContentManager pContent) { string input = reader.ReadLine(); while (input != "/") { string[] dataArray = input.Split(); switch (Convert.ToInt32(dataArray[2])) { case (int)StructureCode.Tube: Tube tube = new Tube(pContent, ColonyStrings.MODEL_PATH + ColonyStrings.Tube_Straight_Model, null); if (dataArray[3] != "null") tube.Name = dataArray[3]; tube.FootPrintSize = new Vector2(Convert.ToInt32(dataArray[4]), Convert.ToInt32(dataArray[5])); tube.Cost = Convert.ToInt32(dataArray[6]); tube.BuildRadius = Convert.ToInt32(dataArray[7]); tube.Running = (Tube.Runnings)Enum.ToObject(typeof(Tube.Runnings), Convert.ToInt32(dataArray[8])); tube.DrawOrder = Convert.ToInt32(dataArray[9]); tube.TechniqueName = dataArray[10]; tube.RequiresBuildArea = false; pAddStructureMethod(tube, new Point(Convert.ToInt32(dataArray[0]), Convert.ToInt32(dataArray[1])), pStructureGrid, pResourceGrid); break; case (int)StructureCode.Road: Road road = new Road(pContent, ColonyStrings.MODEL_PATH + ColonyStrings.Road_Straight_Model, null); if (dataArray[3] != "null") road.Name = dataArray[3]; road.FootPrintSize = new Vector2(Convert.ToInt32(dataArray[4]), Convert.ToInt32(dataArray[5])); road.Cost = Convert.ToInt32(dataArray[6]); road.BuildRadius = Convert.ToInt32(dataArray[7]); road.Running = (Tube.Runnings)Enum.ToObject(typeof(Tube.Runnings), Convert.ToInt32(dataArray[8])); road.DrawOrder = Convert.ToInt32(dataArray[9]); road.TechniqueName = dataArray[10]; road.RequiresBuildArea = false; pAddStructureMethod(road, new Point(Convert.ToInt32(dataArray[0]), Convert.ToInt32(dataArray[1])), pStructureGrid, pResourceGrid); break; case (int)StructureCode.Residential: Residential residential = new Residential(pContent, ColonyStrings.MODEL_PATH + ColonyStrings.Residential_Model, null); if (dataArray[3] != "null") residential.Name = dataArray[3]; residential.FootPrintSize = new Vector2(Convert.ToInt32(dataArray[4]), Convert.ToInt32(dataArray[5])); residential.Cost = Convert.ToInt32(dataArray[6]); residential.BuildRadius = Convert.ToInt32(dataArray[7]); residential.MaximumPopulation = Convert.ToInt32(dataArray[8]); residential.CurrentPopulation = Convert.ToInt32(dataArray[9]); residential.DrawOrder = Convert.ToInt32(dataArray[10]); residential.TechniqueName = dataArray[11]; residential.RequiresBuildArea = false; pAddStructureMethod(residential, new Point(Convert.ToInt32(dataArray[0]), Convert.ToInt32(dataArray[1])), pStructureGrid, pResourceGrid); break; case (int)StructureCode.MiningPlant: MiningPlant miningPlant = new MiningPlant(pContent, ColonyStrings.MODEL_PATH + ColonyStrings.Mining_Plant_Model, null); if (dataArray[3] != "null") miningPlant.Name = dataArray[3]; miningPlant.FootPrintSize = new Vector2(Convert.ToInt32(dataArray[4]), Convert.ToInt32(dataArray[5])); miningPlant.Cost = Convert.ToInt32(dataArray[6]); miningPlant.BuildRadius = Convert.ToInt32(dataArray[7]); miningPlant.DrawOrder = Convert.ToInt32(dataArray[8]); miningPlant.TechniqueName = dataArray[9]; miningPlant.RequiresBuildArea = false; pAddStructureMethod(miningPlant, new Point(Convert.ToInt32(dataArray[0]), Convert.ToInt32(dataArray[1])), pStructureGrid, pResourceGrid); break; case (int)StructureCode.Factory: Factory factory = new Factory(pContent, ColonyStrings.MODEL_PATH + ColonyStrings.Factory_Model, null); if (dataArray[3] != "null") factory.Name = dataArray[3]; factory.FootPrintSize = new Vector2(Convert.ToInt32(dataArray[4]), Convert.ToInt32(dataArray[5])); factory.Cost = Convert.ToInt32(dataArray[6]); factory.BuildRadius = Convert.ToInt32(dataArray[7]); factory.DrawOrder = Convert.ToInt32(dataArray[8]); factory.TechniqueName = dataArray[9]; if (dataArray[10] != "-1") { // Get the sub-strings string[] temp = dataArray[10].Split(';'); // Go through the array foreach (string value in temp) { // If it's not null if(value.Length == 3) { // Split the sub string on the comma and get the two values string[] values = value.Split(','); // Write it out factory.ResourceConversions.Add( (ResourceCode)Enum.ToObject(typeof(ResourceCode), Int32.Parse(values[0])), (ResourceCode)Enum.ToObject(typeof(ResourceCode), Int32.Parse(values[1]))); } } } if (Convert.ToInt32(dataArray[11]) != -1) { int temp = Convert.ToInt32(dataArray[11]); factory.OutputValue = temp; } factory.RequiresBuildArea = false; // Create the factory billboard sprites SpriteData data = new SpriteData(); data.color = Color.White.ToVector4(); data.position = Vector3.Zero; data.size = new Vector2(150, 150); factory.LoadConnectionAlert(@"Textures\GUI\01b_blueTransportUp", @"Textures\GUI\01a_redTransportUp", data); foreach (EntityBillboardSprite e in factory.BillboardRefs) { e.DrawOrder = factory.DrawOrder + 4; } pAddStructureMethod(factory, new Point(Convert.ToInt32(dataArray[0]), Convert.ToInt32(dataArray[1])), pStructureGrid, pResourceGrid); break; case (int)StructureCode.Entertainment: EntityModel transparentEntertainment = new EntityModel(pContent, @"Models\entertainmentDome_01", @"Textures\BluePixel"); transparentEntertainment.TechniqueName = "SpecularAndDiffuseTransparent"; Entertainment entertainment = new Entertainment(pContent, ColonyStrings.MODEL_PATH + ColonyStrings.Entertainment_Model, null, transparentEntertainment); if (dataArray[3] != "null") entertainment.Name = dataArray[3]; entertainment.FootPrintSize = new Vector2(Convert.ToInt32(dataArray[4]), Convert.ToInt32(dataArray[5])); entertainment.Cost = Convert.ToInt32(dataArray[6]); entertainment.BuildRadius = Convert.ToInt32(dataArray[7]); entertainment.HappinessModifier = (float)Convert.ToDouble(dataArray[8]); entertainment.MaxSupported = Convert.ToInt32(dataArray[9]); entertainment.DrawOrder = Convert.ToInt32(dataArray[10]); transparentEntertainment.DrawOrder = entertainment.DrawOrder + 3; entertainment.TechniqueName = dataArray[11]; entertainment.RequiresBuildArea = false; // Create the entertainment icons SpriteData entertainmentData = new SpriteData(); entertainmentData.color = Color.White.ToVector4(); entertainmentData.position = Vector3.Zero; entertainmentData.size = new Vector2(150, 150); entertainment.LoadConnectionAlert(@"Textures\GUI\01b_blueTransportUp", @"Textures\GUI\01a_redTransportUp", entertainmentData); foreach (EntityBillboardSprite e in entertainment.BillboardRefs) { e.DrawOrder = entertainment.DrawOrder + 4; } pAddStructureMethod(entertainment, new Point(Convert.ToInt32(dataArray[0]), Convert.ToInt32(dataArray[1])), pStructureGrid, pResourceGrid); break; case (int)StructureCode.Commercial: Commercial commercial = new Commercial(pContent, ColonyStrings.MODEL_PATH + ColonyStrings.Commercial_Model, null); if (dataArray[3] != "null") commercial.Name = dataArray[3]; commercial.FootPrintSize = new Vector2(Convert.ToInt32(dataArray[4]), Convert.ToInt32(dataArray[5])); commercial.Cost = Convert.ToInt32(dataArray[6]); commercial.BuildRadius = Convert.ToInt32(dataArray[7]); commercial.MoneyGenerated = Convert.ToInt32(dataArray[8]); commercial.DrawOrder = Convert.ToInt32(dataArray[9]); commercial.TechniqueName = dataArray[10]; commercial.RequiresBuildArea = false; // Create the commercial structure icons SpriteData commerceData = new SpriteData(); commerceData.color = Color.White.ToVector4(); commerceData.position = Vector3.Zero; commerceData.size = new Vector2(150, 150); commercial.LoadConnectionAlert(@"Textures\GUI\01b_blueTransportUp", @"Textures\GUI\01a_redTransportUp", commerceData); //commercial.UpdateIconCamera(mPlayerCam.View, mPlayerCam.Projection); foreach (EntityBillboardSprite e in commercial.BillboardRefs) { e.DrawOrder = commercial.DrawOrder + 4; ; } pAddStructureMethod(commercial, new Point(Convert.ToInt32(dataArray[0]), Convert.ToInt32(dataArray[1])), pStructureGrid, pResourceGrid); break; case (int)StructureCode.CommandPost: #warning model needs to be added to string database CommandPost commandPost = new CommandPost(pContent, ColonyStrings.MODEL_PATH + ColonyStrings.Command_Model, null); if (dataArray[3] != "null") commandPost.Name = dataArray[3]; commandPost.FootPrintSize = new Vector2(Convert.ToInt32(dataArray[4]), Convert.ToInt32(dataArray[5])); commandPost.Cost = Convert.ToInt32(dataArray[6]); commandPost.BuildRadius = Convert.ToInt32(dataArray[7]); commandPost.DrawOrder = Convert.ToInt32(dataArray[8]); commandPost.TechniqueName = dataArray[9]; pAddStructureMethod(commandPost, new Point(Convert.ToInt32(dataArray[0]), Convert.ToInt32(dataArray[1])), pStructureGrid, pResourceGrid); break; } input = reader.ReadLine(); } } public static bool Save(string pFilePath, string pFileName, GameState currentGameState) { try { if (!Directory.Exists(pFilePath)) Directory.CreateDirectory(pFilePath); using (FileStream stream = new FileStream(pFilePath + pFileName, FileMode.Create, FileAccess.Write, FileShare.Read)) using (TextWriter writer = new StreamWriter(stream)) { writer.WriteLine(GenerateResourceString(currentGameState.ResourceGrid)); writer.WriteLine(GenerateStructureString(currentGameState.StructureGrid)); writer.WriteLine(currentGameState.PlayerStatusInfo.Money); // For each of the resources, write out the code and value foreach (ResourceCode code in currentGameState.PlayerStatusInfo.Resources.Keys) { // Write out the values writer.Write((int)code + "," + currentGameState.PlayerStatusInfo.Resources[code] + ";"); } writer.WriteLine(); } return true; } catch (Exception ioe) { MainGame.LogError(ioe.Message); return false; } } public static GameState Load(string pFileName, AddStructureDelegate pAddStructure, Structure[,] pStructureGrid, ContentManager pContent) { GameState returnState; try { using (FileStream stream = new FileStream(pFileName, FileMode.Open, FileAccess.Read, FileShare.Read)) using (TextReader reader = new StreamReader(stream)) { returnState = new GameState(); returnState.PlayerStatusInfo = new ColonySimStatusInformation(); returnState.ResourceGrid = LoadResourceGrid(reader); LoadStructures(reader, pAddStructure, pStructureGrid, returnState.ResourceGrid, pContent); returnState.PlayerStatusInfo.Money = Int32.Parse(reader.ReadLine()); // Go through the next line and add each of the resources string[] resources = reader.ReadLine().Split(';'); foreach (string resource in resources) { // Split it into it's two parts string[] values = resource.Split(','); // Add the resource if (values.Length == 2) { returnState.PlayerStatusInfo.Resources.Add((ResourceCode)Int32.Parse(values[0]), Int32.Parse(values[1])); } } } } catch (Exception e) { MainGame.LogError(e.Message); returnState = null; } return returnState; } } class GameState { Resource[,] mResourceGrid; public Resource[,] ResourceGrid { get { return mResourceGrid; } set { mResourceGrid = value; } } public Structure[,] mStructureGrid; public Structure[,] StructureGrid { get { return mStructureGrid; } set { mStructureGrid = value; } } ColonySimStatusInformation mPlayerStatusInfo; public ColonySimStatusInformation PlayerStatusInfo { get { return mPlayerStatusInfo; } set { mPlayerStatusInfo = value; } } } delegate bool AddStructureDelegate(Structure pStructureToAdd, Point pPoint, Structure[,] pReferenceGrid, Resource[,] pResourceGrid); }