Worms4Editor/LibW4M/W4SaveFile.cs

288 lines
9.4 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
{
Console.Error.WriteLine("Unknown container resource: " + containerResourceDetail.Name);
}
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 SavePC(Stream pcSaveStream)
{
saveData();
using (pcSaveStream)
{
using (MemoryStream ms = new MemoryStream())
{
XomWriter.WriteXom(xomFile, pcSaveStream);
ms.Seek(0, SeekOrigin.Begin);
ms.CopyTo(pcSaveStream);
}
}
}
public void SavePS2PSU(Stream ps2PsuSaveStream)
{
using (ps2PsuSaveStream)
{
Ps2Save.CreatePSU(this, ps2PsuSaveStream);
}
}
public void SaveXBOX(Stream xboxSaveStream, XboxRegion region)
{
using (xboxSaveStream)
{
XboxSave.CreateSaveFile(this, xboxSaveStream, region);
}
}
public void SavePS2(Stream ps2SaveStream)
{
using (ps2SaveStream)
{
Ps2Save.CreateSaveFile(this, ps2SaveStream);
}
}
public void SaveXBOX(string newXom, XboxRegion region)
{
SaveXBOX(File.OpenWrite(newXom), region);
}
public void SavePS2(string newXom)
{
SavePS2(File.OpenWrite(newXom));
}
public void SavePS2PSU(string newXom)
{
SavePS2PSU(File.OpenWrite(newXom));
}
public void SavePC(string newXom)
{
SavePC(File.OpenWrite(newXom));
}
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();
}
}
}