253 lines
8.5 KiB
C#
253 lines
8.5 KiB
C#
using LibW4M.Data;
|
|
using LibW4M.Data.Awards;
|
|
using LibW4M.Data.Highscores;
|
|
using LibW4M.Data.InputMapping;
|
|
using LibW4M.Data.Schemes;
|
|
using LibW4M.Data.Stats;
|
|
using LibW4M.Data.Teams;
|
|
using LibW4M.Data.WeaponFactory;
|
|
using LibW4M.Data.WXFE;
|
|
using LibW4M.Data.WXFE.UnlockableItem;
|
|
using LibW4M.Data.X;
|
|
using LibW4M.PS2;
|
|
using LibW4M.XBOX;
|
|
using LibXom;
|
|
using LibXom.Blocks;
|
|
using LibXom.Data;
|
|
using LibXom.Exceptions;
|
|
using LibXom.Streams;
|
|
using System.Reflection;
|
|
using System.Runtime.InteropServices;
|
|
using System.Xml.XPath;
|
|
|
|
namespace LibW4M
|
|
{
|
|
public class W4SaveFile
|
|
{
|
|
|
|
private List<UnlockableItemData> unlockableItems;
|
|
private XomFile xomFile;
|
|
|
|
public DataBank XDataBank;
|
|
|
|
public WeaponsCollective WeaponFactoryCollective;
|
|
public TeamsCollective TeamDataColective;
|
|
public SchemesCollective SchemesCollective;
|
|
public HighscoreCollective HighscoreCollective;
|
|
public StatsCollective StatsCollective;
|
|
public TeamStatsCollective TeamStatsCollective;
|
|
public InputMappingCollective InputMappingCollective;
|
|
|
|
public TeamAwardsData TeamAwardsContainer;
|
|
public XomString Message;
|
|
public XomString FEResourceID;
|
|
|
|
public XomFile OriginalXom
|
|
{
|
|
get
|
|
{
|
|
return this.xomFile;
|
|
}
|
|
}
|
|
public UnlockableItemData[] UnlockableItems
|
|
{
|
|
get
|
|
{
|
|
return unlockableItems.ToArray();
|
|
}
|
|
}
|
|
|
|
|
|
internal WeaponData findWeaponWithContainerId(int containerId)
|
|
{
|
|
if(WeaponFactoryCollective is not null)
|
|
{
|
|
for (int i = 0; i < WeaponFactoryCollective.Length; i++)
|
|
{
|
|
WeaponStore weaponStore = (WeaponStore)WeaponFactoryCollective[i];
|
|
if (weaponStore.Weapon.containerId == containerId) return weaponStore.Weapon;
|
|
if (weaponStore.Cluster.containerId == containerId) return weaponStore.Cluster;
|
|
}
|
|
}
|
|
|
|
return new WeaponData(this, LookupContainerById(containerId));
|
|
}
|
|
|
|
public void Load()
|
|
{
|
|
unlockableItems = new List<UnlockableItemData>();
|
|
XDataBank = new DataBank(this, this.xomFile.GetTypeByName("XDataBank").Containers.First());
|
|
|
|
foreach(ContainerResourceDetail containerResourceDetail in XDataBank.ContainerResourceDetails)
|
|
{
|
|
switch (containerResourceDetail.Name.Value)
|
|
{
|
|
case "DATA.Weapons":
|
|
WeaponFactoryCollective = new WeaponsCollective(this, containerResourceDetail.Value);
|
|
break;
|
|
case "DATA.TeamBarracks":
|
|
TeamDataColective = new TeamsCollective(this, containerResourceDetail.Value);
|
|
HighscoreCollective = new HighscoreCollective(this, containerResourceDetail.Value);
|
|
break;
|
|
case "DATA.Schemes":
|
|
SchemesCollective = new SchemesCollective(this, containerResourceDetail.Value);
|
|
break;
|
|
case "PersistStats":
|
|
StatsCollective = new StatsCollective(this, containerResourceDetail.Value);
|
|
TeamStatsCollective = new TeamStatsCollective(this, containerResourceDetail.Value);
|
|
break;
|
|
case "Awards":
|
|
TeamAwardsContainer = new TeamAwardsData(this, containerResourceDetail.Value);
|
|
break;
|
|
case "InputMapping":
|
|
InputMappingCollective = new InputMappingCollective(this, containerResourceDetail.Value);
|
|
break;
|
|
default:
|
|
|
|
// stupid hack; the only other option is manually hardcoding every unlockable item in the game
|
|
// but this way atleast allows for it to be more generic incase for some reason not all (or more) are present.
|
|
|
|
// Team17, why isnt there a collective for this?
|
|
if (containerResourceDetail.Value.Type.Name.Equals("WXFE_UnlockableItem", StringComparison.InvariantCultureIgnoreCase))
|
|
{
|
|
UnlockableItemData itemData = new UnlockableItemData(this, containerResourceDetail.Value);
|
|
itemData.nameOverride = containerResourceDetail.Name.Value;
|
|
|
|
unlockableItems.Add(itemData);
|
|
}
|
|
else
|
|
{
|
|
#if !DEBUG
|
|
throw new XomException("Unknown container resource: " + containerResourceDetail.Name);
|
|
#else
|
|
Console.Error.WriteLine("Unknown container resource: " + containerResourceDetail.Name);
|
|
#endif
|
|
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
internal void saveData()
|
|
{
|
|
#if !DEBUG
|
|
xomFile.ClearAllStrings();
|
|
#endif
|
|
|
|
XDataBank.Save();
|
|
WeaponFactoryCollective.Save();
|
|
|
|
// Save Teams, Highscores
|
|
TeamDataColective.Save();
|
|
HighscoreCollective.Save();
|
|
|
|
SchemesCollective.Save();
|
|
|
|
// Save Stats, TeamStats
|
|
StatsCollective.Save();
|
|
TeamStatsCollective.Save();
|
|
|
|
TeamAwardsContainer.Save();
|
|
InputMappingCollective.Save();
|
|
|
|
foreach (UnlockableItemData unlockableItem in UnlockableItems)
|
|
unlockableItem.Save();
|
|
}
|
|
public void Save(Stream pcSaveStream)
|
|
{
|
|
saveData();
|
|
using (pcSaveStream)
|
|
{
|
|
using (MemoryStream ms = new MemoryStream())
|
|
{
|
|
XomWriter.WriteXom(xomFile, pcSaveStream);
|
|
|
|
ms.Seek(0, SeekOrigin.Begin);
|
|
ms.CopyTo(pcSaveStream);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
public void ExtractAllContainers(string path)
|
|
{
|
|
foreach(XomType type in xomFile.XomTypes)
|
|
{
|
|
string outfolder = Path.Combine(path, type.Name);
|
|
if (Directory.Exists(outfolder))
|
|
Directory.Delete(outfolder, true);
|
|
Directory.CreateDirectory(outfolder);
|
|
|
|
foreach(XomContainer container in type.Containers)
|
|
{
|
|
while (true)
|
|
{
|
|
try
|
|
{
|
|
File.WriteAllBytes(Path.ChangeExtension(Path.Combine(outfolder, container.Id.ToString("X2")), ".bin"), container.GetData());
|
|
break;
|
|
}
|
|
catch
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
public XomString[] StringArrayToXomStringArray(string[] strings)
|
|
{
|
|
XomString[] xstrings = new XomString[strings.Length];
|
|
for (int i = 0; i < xstrings.Length; i++) xstrings[i] = LookupString(strings[i]);
|
|
return xstrings;
|
|
}
|
|
|
|
public string[] XomStringArrayToStringArray(XomString[] xstrings)
|
|
{
|
|
string[] strings = new string[xstrings.Length];
|
|
for (int i = 0; i < strings.Length; i++) strings[i] = xstrings[i].Value;
|
|
return strings;
|
|
}
|
|
|
|
public int[] XomStringArrayToIntArray(XomString[] strs)
|
|
{
|
|
int[] ids = new int[strs.Length];
|
|
for (int i = 0; i < ids.Length; i++) ids[i] = strs[i].Id;
|
|
return ids;
|
|
}
|
|
|
|
public XomString[] IntArrayToXomStringArray(int[] stringIds)
|
|
{
|
|
XomString[] strings = new XomString[stringIds.Length];
|
|
for (int i = 0; i < strings.Length; i++) strings[i] = this.LookupStringFromId(stringIds[i]);
|
|
return strings;
|
|
}
|
|
|
|
public XomContainer LookupContainerById(int id)
|
|
{
|
|
return xomFile.GetContainerById(id);
|
|
}
|
|
|
|
public XomString LookupStringFromId(int id)
|
|
{
|
|
return xomFile.GetStringById(id);
|
|
}
|
|
public XomString LookupString(string value)
|
|
{
|
|
return xomFile.AddOrGetString(value);
|
|
}
|
|
|
|
public W4SaveFile(XomFile w4Save)
|
|
{
|
|
this.xomFile = w4Save;
|
|
|
|
Load();
|
|
|
|
}
|
|
}
|
|
} |