public static string DetermineMapName(MapFile map, EngineType engine)
{
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(map.FileName);
IniFile.IniSection basic = map.GetSection("Basic");
if (basic.ReadBool("Official") == false)
return StripPlayersFromName(MakeValidFileName(basic.ReadString("Name", fileNameWithoutExtension)));
string mapExt = Path.GetExtension(Settings.InputFile);
string missionName = "";
string mapName = "";
PktFile.PktMapEntry pktMapEntry = null;
MissionsFile.MissionEntry missionEntry = null;
// campaign mission
if (!basic.ReadBool("MultiplayerOnly") && basic.ReadBool("Official")) {
string missionsFile;
switch (engine) {
case EngineType.TiberianSun:
case EngineType.RedAlert2:
missionsFile = "mission.ini";
break;
case EngineType.Firestorm:
missionsFile = "mission1.ini";
break;
case EngineType.YurisRevenge:
missionsFile = "missionmd.ini";
break;
default:
throw new ArgumentOutOfRangeException("engine");
}
var mf = VFS.Open<MissionsFile>(missionsFile);
if (mf != null)
missionEntry = mf.GetMissionEntry(Path.GetFileName(map.FileName));
if (missionEntry != null)
missionName = (engine >= EngineType.RedAlert2) ? missionEntry.UIName : missionEntry.Name;
}
else {
// multiplayer map
string pktEntryName = fileNameWithoutExtension;
PktFile pkt = null;
if (FormatHelper.MixArchiveExtensions.Contains(mapExt)) {
// this is an 'official' map 'archive' containing a PKT file with its name
try {
var mix = new MixFile(File.Open(Settings.InputFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
pkt = mix.OpenFile(fileNameWithoutExtension + ".pkt", FileFormat.Pkt) as PktFile;
// pkt file is cached by default, so we can close the handle to the file
mix.Close();
if (pkt != null && pkt.MapEntries.Count > 0)
pktEntryName = pkt.MapEntries.First().Key;
}
catch (ArgumentException) { }
}
else {
// determine pkt file based on engine
switch (engine) {
case EngineType.TiberianSun:
case EngineType.RedAlert2:
pkt = VFS.Open<PktFile>("missions.pkt");
break;
case EngineType.Firestorm:
pkt = VFS.Open<PktFile>("multi01.pkt");
break;
case EngineType.YurisRevenge:
pkt = VFS.Open<PktFile>("missionsmd.pkt");
break;
default:
throw new ArgumentOutOfRangeException("engine");
}
}
// fallback for multiplayer maps with, .map extension,
// no YR objects so assumed to be ra2, but actually meant to be used on yr
if (mapExt == ".map" && pkt != null && !pkt.MapEntries.ContainsKey(pktEntryName) && engine >= EngineType.RedAlert2) {
var vfs = new VFS();
vfs.AddItem(Settings.InputFile);
pkt = vfs.OpenFile<PktFile>("missionsmd.pkt");
}
if (pkt != null && !string.IsNullOrEmpty(pktEntryName))
pktMapEntry = pkt.GetMapEntry(pktEntryName);
}
// now, if we have a map entry from a PKT file,
// for TS we are done, but for RA2 we need to look in the CSV file for the translated mapname
if (engine <= EngineType.Firestorm) {
if (pktMapEntry != null)
mapName = pktMapEntry.Description;
else if (missionEntry != null) {
if (engine == EngineType.TiberianSun) {
string campaignSide;
string missionNumber;
if (missionEntry.Briefing.Length >= 3) {
campaignSide = missionEntry.Briefing.Substring(0, 3);
missionNumber = missionEntry.Briefing.Length > 3 ? missionEntry.Briefing.Substring(3) : "";
missionName = "";
mapName = string.Format("{0} {1} - {2}", campaignSide, missionNumber.TrimEnd('A').PadLeft(2, '0'), missionName);
}
else if (missionEntry.Name.Length >= 10) {
mapName = missionEntry.Name;
}
}
else {
// FS map names are constructed a bit easier
mapName = missionName.Replace(":", " - ");
}
}
else if (!string.IsNullOrEmpty(basic.ReadString("Name")))
mapName = basic.ReadString("Name", fileNameWithoutExtension);
}
// if this is a RA2/YR mission (csfEntry set) or official map with valid pktMapEntry
else if (missionEntry != null || pktMapEntry != null) {
string csfEntryName = missionEntry != null ? missionName : pktMapEntry.Description;
string csfFile = engine == EngineType.YurisRevenge ? "ra2md.csf" : "ra2.csf";
_logger.Info("Loading csf file {0}", csfFile);
var csf = VFS.Open<CsfFile>(csfFile);
mapName = csf.GetValue(csfEntryName.ToLower());
if (missionEntry != null) {
if (mapName.Contains("Operation: ")) {
string missionMapName = Path.GetFileName(map.FileName);
if (char.IsDigit(missionMapName[3]) && char.IsDigit(missionMapName[4])) {
string missionNr = Path.GetFileName(map.FileName).Substring(3, 2);
mapName = mapName.Substring(0, mapName.IndexOf(":")) + " " + missionNr + " -" +
mapName.Substring(mapName.IndexOf(":") + 1);
}
}
}
else {
// not standard map
if ((pktMapEntry.GameModes & PktFile.GameMode.Standard) == 0) {
if ((pktMapEntry.GameModes & PktFile.GameMode.Megawealth) == PktFile.GameMode.Megawealth)
mapName += " (Megawealth)";
if ((pktMapEntry.GameModes & PktFile.GameMode.Duel) == PktFile.GameMode.Duel)
mapName += " (Land Rush)";
if ((pktMapEntry.GameModes & PktFile.GameMode.NavalWar) == PktFile.GameMode.NavalWar)
mapName += " (Naval War)";
}
}
}
// not really used, likely empty, but if this is filled in it's probably better than guessing
if (mapName == "" && basic.SortedEntries.ContainsKey("Name"))
mapName = basic.ReadString("Name");
if (mapName == "") {
_logger.Warn("No valid mapname given or found, reverting to default filename {0}", fileNameWithoutExtension);
mapName = fileNameWithoutExtension;
}
else {
_logger.Info("Mapname found: {0}", mapName);
}
mapName = StripPlayersFromName(MakeValidFileName(mapName)).Replace(" ", " ");
return mapName;
}