You don’t need to use a binary formatter. I don’t have time to write you some sample code but what I can do is post some of my current code.
I apologies for the lack of annotation I had to De-compile the binary file after data corruption and have only partial re-anotated it.
Now in the code below I have a class that I am saving and loading.
Now the class BuildingData is what i save to file
I specify the data to save with [datacontract] and [datamember] that is the only data i save
the other area to look at are SaveToFile() and LoadFromFile() the rest is just processing the data before saving and after loading.
Hope this helps you out a bit.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BlockEmpire.Engine.World;
using System.IO;
using System.Runtime.Serialization;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace BlockEmpire.Engine.Design
{
public enum BuildningType { Housing, Rescource, UnitTraining, Defence };
public struct BuildingBlock
{
public Point3D Location; //the locaiton of the block
public BasicBlock Block; //the block data
///wherether this block can be replaced with other blocks of same type
public bool CanUseOtherBlocks;
public BuildingBlock(Point3D location, BasicBlock block, bool canUseOtherBlocks)
{
Location = location;
Block = block;
CanUseOtherBlocks = canUseOtherBlocks;
}
}
[DataContract]
public struct BuildingData
{
[DataMember]
public List<BuildingBlock> Data;
[DataMember]
public string Name; //optional variable for user
[DataMember]
public BuildningType Type;
private bool _haveGeneratedGraphicAssets;//if we have generated the verts list and the HUD_Texture
public bool HaveGeneratedGraphicAssets { get { return _haveGeneratedGraphicAssets; } }
public List<VertexPositionColorTexture> Verts; //list of all verts for the building
public VertexPositionColorTexture[] RenderVerts; //list of all verts for the building
public Texture2D HUD_Texture; //the texture to draw in the menus
private Point3D LastLoc;
public BuildingData(BuildningType type)
{
Type = type;
Name = "";
Data = new List<BuildingBlock>();
_haveGeneratedGraphicAssets = false;
Verts = new List<VertexPositionColorTexture>();
HUD_Texture = null;
RenderVerts = null;
LastLoc = Point3D.Error;
}
public void BlockChanged(Point3D blockLocation, BasicBlock block)
{
BuildingBlock b;
if (block.Id == UserFriendlyBlockIds.Air)
{
//if (blockLocation.Y > 10)
for (int i = 0; i < Data.Count; i++)
{
b = Data[i];
if (b.Location.X == blockLocation.X &&
b.Location.Y == blockLocation.Y &&
b.Location.Z == blockLocation.Z)
{
Data.RemoveAt(i);
return;
}
}
return;
}
for (int i = 0; i < Data.Count; i++)
{
b = Data[i];
if (b.Location.X == blockLocation.X &&
b.Location.Y== blockLocation.Y &&
b.Location.Z == blockLocation.Z)
{
b.Block = block;
Data[i] = b;
return;
}
}
Data.Add(new BuildingBlock(blockLocation, block, true));
}
public void GenerateGraphicAssets()
{
Verts = new List<VertexPositionColorTexture>();
List<BuildingBlock> renderBlocks = new List<BuildingBlock>();
int lowest = int.MaxValue;
int leftmost = int.MaxValue;
int rightmost = int.MinValue;
int nearset = int.MinValue;
int farest = int.MaxValue;
int centerx, centery;
for (int i = 0; i < Data.Count; i++)
{
if (lowest > Data[i].Location.Y)
lowest = Data[i].Location.Y;
if (leftmost > Data[i].Location.X)
leftmost = Data[i].Location.X;
if (rightmost < Data[i].Location.X)
rightmost = Data[i].Location.X;
if (nearset < Data[i].Location.Z)
nearset = Data[i].Location.Z;
if (farest > Data[i].Location.Z)
farest = Data[i].Location.Z;
}
centerx = (rightmost - leftmost) / 2 + leftmost;
centery = (nearset - farest) / 2 + farest;
for (int i = 0; i < Data.Count; i++)
{
BuildingBlock block = Data[i];
block.Location.Y -= lowest;
block.Location.X -= centerx;
block.Location.Z -= centery;
renderBlocks.Add(block);
}
for (int i=0; i < Data.Count; i++) //loop through all blocks
{
for (int side =0; side < 6; side++)
BlockInfo.Blocks[(int)renderBlocks[i].Block.Id].GetSideVerts(side,
new Vector3(renderBlocks[i].Location.X, renderBlocks[i].Location.Y, renderBlocks[i].Location.Z),
ref Verts);
}
_haveGeneratedGraphicAssets = true;
}
public void RenderVertsAssets(ref Camera gameCamera, Point3D loc)
{
if (LastLoc.X != loc.X || LastLoc.Z != loc.Z || LastLoc.Y != loc.Y) //if it has moved
{
RenderVerts = new VertexPositionColorTexture[Verts.Count];
for (int i = 0; i < Verts.Count; i++)
{
RenderVerts[i] = Verts[i];
RenderVerts[i].Position.X += loc.X;
RenderVerts[i].Position.Y += loc.Y;
RenderVerts[i].Position.Z += loc.Z;
}
}
foreach (EffectPass pass in gameCamera._effect.CurrentTechnique.Passes)
{
Engine.graphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleList, RenderVerts, 0, Verts.Count / 3);
}
LastLoc = loc;
}
public void OnCreat()
{
}
public void OnDestroy()
{
}
}
public class BuildingInterface
{
private static List<BuildingData> _buildings;
public static List<BuildingData> Buildings { get { return _buildings; } }
public static BuildingData CurrentBuilding;
public static void Save()
{
if (CurrentBuilding.Name == null || CurrentBuilding.Name == "")
Guide.BeginShowKeyboardInput(Microsoft.Xna.Framework.PlayerIndex.One, "Enter Building Name", "Please enter the name you wish to call this building", "",
OnKeyBoardExit, null);
else
Guide.BeginShowKeyboardInput(Microsoft.Xna.Framework.PlayerIndex.One, "Enter Building Name", "Please enter the name you wish to call this building", CurrentBuilding.Name,
OnKeyBoardExit, null);
}
private static void OnKeyBoardExit(IAsyncResult r)
{
string result = Guide.EndShowKeyboardInput(r);
if (result == null || result.Length < 3)
{
while (Guide.IsVisible) { }
Guide.BeginShowMessageBox("Error Saving", "Design was not saved please enter a building name that is longer than 3 letters",
new List<string> { "Ok" }, 0, MessageBoxIcon.Error, null, null);
return;
}
CurrentBuilding.Name = result;
PostSave();
}
private static int SaveLocation = -1;
private static void PostSave()
{
SaveLocation = -1;
if (_buildings == null)
_buildings = new List<BuildingData>();
for (int i =0;i < _buildings.Count; i++)
if (_buildings[i].Name == CurrentBuilding.Name)
{
SaveLocation = i;
_buildings[i] = CurrentBuilding;
break;
}
if (SaveLocation == -1) //if curretn building does not extis
_buildings.Add(CurrentBuilding);
SaveToFile();
}
private const string FilePath = ".\\buildings.dat"; //the path for the building data
/// <summary>
/// save the build data to file
/// </summary>
private static void SaveToFile()
{
using (FileStream f = File.Create(FilePath))//create the file on pc
{
DataContractSerializer writer = new DataContractSerializer(typeof(List<BuildingData>)); //create the serializer
writer.WriteObject(f, _buildings); //write to file
}
}
/// <summary>
/// load the building data from file
/// </summary>
private static void LoadFromFile()
{
if (_buildings == null)
_buildings = new List<BuildingData>();
_buildings.Clear();
using (FileStream f = File.Open(FilePath, FileMode.OpenOrCreate))//create the file on pc
{
DataContractSerializer reader = new DataContractSerializer(typeof(List<BuildingData>));//create the serializer
_buildings = (List<BuildingData>)reader.ReadObject(f); //load from file
}
}
public static void Load(ref Sector[,] sectors)
{
LoadFromFile();
CurrentBuilding = _buildings[0]; //set the current building
BuildingBlock block;
Point3D blockpos;
Point2D sectorpos;
List<Point2D> reGenerations = new List<Point2D>();
for (int i = 0;i < CurrentBuilding.Data.Count; i++)
{
block = CurrentBuilding.Data[i];
sectorpos = Sector.CalculateSectorFromBlockCord(block.Location); //get the current sector
blockpos = block.Location; //get the block
blockpos.X -= sectorpos.X * Sector.Sector_Size; //workout the block location in sector
blockpos.Z -= sectorpos.Z * Sector.Sector_Size; //workout the block location in sector
sectors[sectorpos.X, sectorpos.Z].WriteblockIds(blockpos, block.Block.Id, block.Block.Data); //write the new block id
if (!reGenerations.Contains(sectorpos)) //if this sectors has not been set to be regenerated
reGenerations.Add(sectorpos); //add to list
}
for (int i=0;i< reGenerations.Count; i++) //regenerate all needed sectors
sectors[reGenerations[i].X, reGenerations[i].Z].CalculateGeomotry();
}
}
}