Unstable 0.17.5.0
This commit is contained in:
@@ -831,7 +831,13 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
List<Point> ruinPositions = new List<Point>();
|
||||
for (int i = 0; i < GenerationParams.RuinCount; i++)
|
||||
int ruinCount = GenerationParams.RuinCount;
|
||||
if (GameMain.GameSession?.GameMode?.Missions.Any(m => m.Prefab.RequireRuin) ?? false)
|
||||
{
|
||||
ruinCount = Math.Max(ruinCount, 1);
|
||||
}
|
||||
|
||||
for (int i = 0; i < ruinCount; i++)
|
||||
{
|
||||
Point ruinSize = new Point(5000);
|
||||
int limitLeft = Math.Max(startPosition.X, ruinSize.X / 2);
|
||||
|
||||
@@ -387,14 +387,14 @@ namespace Barotrauma
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(3, IsPropertySaveable.Yes, description: "Minimum number of resource clusters in the abyss (the actual number is picked between min and max according to the level difficulty)"), Editable(MinValueInt = 0, MaxValueInt = 1000)]
|
||||
[Serialize(10, IsPropertySaveable.Yes, description: "Minimum number of resource clusters in the abyss (the actual number is picked between min and max according to the level difficulty)"), Editable(MinValueInt = 0, MaxValueInt = 1000)]
|
||||
public int AbyssResourceClustersMin
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(20, IsPropertySaveable.Yes, description: "Maximum number of resource clusters in the abyss (the actual number is picked between min and max according to the level difficulty)"), Editable(MinValueInt = 0, MaxValueInt = 1000)]
|
||||
[Serialize(50, IsPropertySaveable.Yes, description: "Maximum number of resource clusters in the abyss (the actual number is picked between min and max according to the level difficulty)"), Editable(MinValueInt = 0, MaxValueInt = 1000)]
|
||||
public int AbyssResourceClustersMax
|
||||
{
|
||||
get;
|
||||
|
||||
@@ -257,7 +257,7 @@ namespace Barotrauma
|
||||
}
|
||||
DailySpecials.Clear();
|
||||
int extraSpecialSalesCount = Location.GetExtraSpecialSalesCount();
|
||||
for (int i = 0; i < DailySpecialsCount + extraSpecialSalesCount; i++)
|
||||
for (int i = 0; i < Location.DailySpecialsCount + extraSpecialSalesCount; i++)
|
||||
{
|
||||
if (availableStock.None()) { break; }
|
||||
var item = ToolBox.SelectWeightedRandom(availableStock.Keys.ToList(), availableStock.Values.ToList(), Rand.RandSync.Unsynced);
|
||||
@@ -266,7 +266,7 @@ namespace Barotrauma
|
||||
availableStock.Remove(item);
|
||||
}
|
||||
RequestedGoods.Clear();
|
||||
for (int i = 0; i < RequestedGoodsCount; i++)
|
||||
for (int i = 0; i < Location.RequestedGoodsCount; i++)
|
||||
{
|
||||
var item = ItemPrefab.Prefabs.GetRandom(p =>
|
||||
p.CanBeSold && !RequestedGoods.Contains(p) &&
|
||||
@@ -359,8 +359,8 @@ namespace Barotrauma
|
||||
/// How many map progress steps it takes before the discounts should be updated.
|
||||
/// </summary>
|
||||
private const int SpecialsUpdateInterval = 3;
|
||||
private const int DailySpecialsCount = 3;
|
||||
private const int RequestedGoodsCount = 3;
|
||||
private int DailySpecialsCount => Type.DailySpecialsCount;
|
||||
private int RequestedGoodsCount => Type.RequestedGoodsCount;
|
||||
private int StepsSinceSpecialsUpdated { get; set; }
|
||||
public HashSet<Identifier> StoreIdentifiers { get; } = new HashSet<Identifier>();
|
||||
|
||||
@@ -1226,7 +1226,7 @@ namespace Barotrauma
|
||||
|
||||
public int GetExtraSpecialSalesCount()
|
||||
{
|
||||
var characters = GameSession.GetSessionCrewCharacters();
|
||||
var characters = GameSession.GetSessionCrewCharacters(CharacterType.Both);
|
||||
if (!characters.Any()) { return 0; }
|
||||
return characters.Max(c => (int)c.GetStatValue(StatTypes.ExtraSpecialSalesCount));
|
||||
}
|
||||
@@ -1252,7 +1252,7 @@ namespace Barotrauma
|
||||
Discovered = true;
|
||||
if (checkTalents)
|
||||
{
|
||||
GameSession.GetSessionCrewCharacters().ForEach(c => c.CheckTalents(AbilityEffectType.OnLocationDiscovered, new AbilityLocation(this)));
|
||||
GameSession.GetSessionCrewCharacters(CharacterType.Both).ForEach(c => c.CheckTalents(AbilityEffectType.OnLocationDiscovered, new AbilityLocation(this)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Barotrauma.IO;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using Barotrauma.IO;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.Extensions;
|
||||
using System.Collections.Immutable;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -21,8 +19,9 @@ namespace Barotrauma
|
||||
//<name, commonness>
|
||||
private readonly ImmutableArray<(Identifier Name, float Commonness)> hireableJobs;
|
||||
private readonly float totalHireableWeight;
|
||||
|
||||
public Dictionary<int, float> CommonnessPerZone = new Dictionary<int, float>();
|
||||
|
||||
public readonly Dictionary<int, float> CommonnessPerZone = new Dictionary<int, float>();
|
||||
public readonly Dictionary<int, int> MinCountPerZone = new Dictionary<int, int>();
|
||||
|
||||
public readonly LocalizedString Name;
|
||||
|
||||
@@ -65,7 +64,7 @@ namespace Barotrauma
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
|
||||
public string ReplaceInRadiation { get; }
|
||||
|
||||
public Sprite Sprite { get; private set; }
|
||||
@@ -86,6 +85,8 @@ namespace Barotrauma
|
||||
/// In percentages
|
||||
/// </summary>
|
||||
public int StorePriceModifierRange { get; } = 5;
|
||||
public int DailySpecialsCount { get; } = 1;
|
||||
public int RequestedGoodsCount { get; } = 1;
|
||||
|
||||
public List<StoreBalanceStatus> StoreBalanceStatuses { get; } = new List<StoreBalanceStatus>()
|
||||
{
|
||||
@@ -144,7 +145,7 @@ namespace Barotrauma
|
||||
names = new List<string>() { "Name file not found" };
|
||||
}
|
||||
|
||||
string[] commonnessPerZoneStrs = element.GetAttributeStringArray("commonnessperzone", new string[] { "" });
|
||||
string[] commonnessPerZoneStrs = element.GetAttributeStringArray("commonnessperzone", Array.Empty<string>());
|
||||
foreach (string commonnessPerZoneStr in commonnessPerZoneStrs)
|
||||
{
|
||||
string[] splitCommonnessPerZone = commonnessPerZoneStr.Split(':');
|
||||
@@ -152,12 +153,26 @@ namespace Barotrauma
|
||||
!int.TryParse(splitCommonnessPerZone[0].Trim(), out int zoneIndex) ||
|
||||
!float.TryParse(splitCommonnessPerZone[1].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out float zoneCommonness))
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to read commonness values for location type \"" + Identifier + "\" - commonness should be given in the format \"zone0index: zone0commonness, zone1index: zone1commonness\"");
|
||||
DebugConsole.ThrowError("Failed to read commonness values for location type \"" + Identifier + "\" - commonness should be given in the format \"zone1index: zone1commonness, zone2index: zone2commonness\"");
|
||||
break;
|
||||
}
|
||||
CommonnessPerZone[zoneIndex] = zoneCommonness;
|
||||
}
|
||||
|
||||
string[] minCountPerZoneStrs = element.GetAttributeStringArray("mincountperzone", Array.Empty<string>());
|
||||
foreach (string minCountPerZoneStr in minCountPerZoneStrs)
|
||||
{
|
||||
string[] splitMinCountPerZone = minCountPerZoneStr.Split(':');
|
||||
if (splitMinCountPerZone.Length != 2 ||
|
||||
!int.TryParse(splitMinCountPerZone[0].Trim(), out int zoneIndex) ||
|
||||
!int.TryParse(splitMinCountPerZone[1].Trim(), out int minCount))
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to read minimum count values for location type \"" + Identifier + "\" - minimum counts should be given in the format \"zone1index: zone1mincount, zone2index: zone2mincount\"");
|
||||
break;
|
||||
}
|
||||
MinCountPerZone[zoneIndex] = minCount;
|
||||
}
|
||||
|
||||
var hireableJobs = new List<(Identifier, float)>();
|
||||
foreach (var subElement in element.Elements())
|
||||
{
|
||||
@@ -205,6 +220,8 @@ namespace Barotrauma
|
||||
StoreBalanceStatuses.Add(new StoreBalanceStatus(percentage, modifier, color));
|
||||
}
|
||||
}
|
||||
DailySpecialsCount = subElement.GetAttributeInt("dailyspecialscount", DailySpecialsCount);
|
||||
RequestedGoodsCount = subElement.GetAttributeInt("requestedgoodscount", RequestedGoodsCount);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,16 +218,24 @@ namespace Barotrauma
|
||||
|
||||
foreach (Location location in Locations)
|
||||
{
|
||||
if (location.Type.Identifier != "city" &&
|
||||
location.Type.Identifier != "outpost")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (location.Type.Identifier != "outpost") { continue; }
|
||||
if (CurrentLocation == null || location.MapPosition.X < CurrentLocation.MapPosition.X)
|
||||
{
|
||||
CurrentLocation = StartLocation = furthestDiscoveredLocation = location;
|
||||
}
|
||||
}
|
||||
//if no outpost was found (using a mod that replaces the outpost location type?), find any type of outpost
|
||||
if (CurrentLocation == null)
|
||||
{
|
||||
foreach (Location location in Locations)
|
||||
{
|
||||
if (!location.Type.HasOutpost) { continue; }
|
||||
if (CurrentLocation == null || location.MapPosition.X < CurrentLocation.MapPosition.X)
|
||||
{
|
||||
CurrentLocation = StartLocation = furthestDiscoveredLocation = location;
|
||||
}
|
||||
}
|
||||
}
|
||||
System.Diagnostics.Debug.Assert(StartLocation != null, "Start location not assigned after level generation.");
|
||||
|
||||
CurrentLocation.Discover(true);
|
||||
@@ -273,6 +281,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
voronoiSites.Clear();
|
||||
Dictionary<int, List<Location>> locationsPerZone = new Dictionary<int, List<Location>>();
|
||||
foreach (GraphEdge edge in edges)
|
||||
{
|
||||
if (edge.Point1 == edge.Point2) { continue; }
|
||||
@@ -301,7 +310,24 @@ namespace Barotrauma
|
||||
Vector2 position = points[positionIndex];
|
||||
if (newLocations[1 - i] != null && newLocations[1 - i].MapPosition == position) { position = points[1 - positionIndex]; }
|
||||
int zone = GetZoneIndex(position.X);
|
||||
newLocations[i] = Location.CreateRandom(position, zone, Rand.GetRNG(Rand.RandSync.ServerAndClient), requireOutpost: false, existingLocations: Locations);
|
||||
if (!locationsPerZone.ContainsKey(zone))
|
||||
{
|
||||
locationsPerZone[zone] = new List<Location>();
|
||||
}
|
||||
|
||||
LocationType forceLocationType = null;
|
||||
foreach (LocationType locationType in LocationType.Prefabs.OrderBy(lt => lt.Identifier))
|
||||
{
|
||||
if (locationType.MinCountPerZone.TryGetValue(zone, out int minCount) && locationsPerZone[zone].Count(l => l.Type == locationType) < minCount)
|
||||
{
|
||||
forceLocationType = locationType;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
newLocations[i] = Location.CreateRandom(position, zone, Rand.GetRNG(Rand.RandSync.ServerAndClient),
|
||||
requireOutpost: false, forceLocationType: forceLocationType, existingLocations: Locations);
|
||||
locationsPerZone[zone].Add(newLocations[i]);
|
||||
Locations.Add(newLocations[i]);
|
||||
}
|
||||
|
||||
@@ -448,8 +474,7 @@ namespace Barotrauma
|
||||
Connections[i].Locations[1];
|
||||
if (!leftMostLocation.Type.HasOutpost || leftMostLocation.Type.Identifier == "abandoned")
|
||||
{
|
||||
#warning TODO: determinism?
|
||||
leftMostLocation.ChangeType(LocationType.Prefabs.First(lt => lt.HasOutpost && lt.Identifier != "abandoned"));
|
||||
leftMostLocation.ChangeType(LocationType.Prefabs.OrderBy(lt => lt.Identifier).First(lt => lt.HasOutpost && lt.Identifier != "abandoned"));
|
||||
}
|
||||
leftMostLocation.IsGateBetweenBiomes = true;
|
||||
Connections[i].Locked = true;
|
||||
|
||||
@@ -1,220 +0,0 @@
|
||||
#nullable enable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Barotrauma.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
public class Md5Hash
|
||||
{
|
||||
public static class Cache
|
||||
{
|
||||
private const string cachePath = "Data/hashcache.txt";
|
||||
|
||||
private readonly static List<(string Path, Md5Hash Hash, DateTime DateTime)> Entries
|
||||
= new List<(string Path, Md5Hash Hash, DateTime DateTime)>();
|
||||
|
||||
public static void Load()
|
||||
{
|
||||
if (!File.Exists(cachePath)) { return; }
|
||||
var lines = File.ReadAllLines(cachePath);
|
||||
if (Version.TryParse(lines[0], out var cacheVersion) && cacheVersion == GameMain.Version)
|
||||
{
|
||||
for (int i = 1; i < lines.Length; i++)
|
||||
{
|
||||
string[] split = lines[i].Split('|');
|
||||
string path = split[0].CleanUpPathCrossPlatform();
|
||||
Md5Hash hash = Md5Hash.StringAsHash(split[1]);
|
||||
DateTime? dateTime = null;
|
||||
if (long.TryParse(split[2], out long dateTimeUlong))
|
||||
{
|
||||
dateTime = DateTime.FromBinary(dateTimeUlong);
|
||||
}
|
||||
|
||||
if (File.Exists(path) && dateTime.HasValue && dateTime >= File.GetLastWriteTime(path))
|
||||
{
|
||||
Entries.Add((path, hash, dateTime.Value));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Add(string path, Md5Hash hash, DateTime dateTime)
|
||||
{
|
||||
path = path.CleanUpPathCrossPlatform();
|
||||
Remove(path);
|
||||
Entries.Add((path, hash, dateTime));
|
||||
}
|
||||
|
||||
public static void Remove(string path)
|
||||
{
|
||||
path = path.CleanUpPathCrossPlatform();
|
||||
Entries.RemoveAll(e => e.Path == path);
|
||||
}
|
||||
}
|
||||
|
||||
public static readonly Md5Hash Blank = new Md5Hash(new string('0', 32));
|
||||
|
||||
private static string RemoveWhitespace(string s)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(s.Length / 2); // Reserve half the size of the original string because
|
||||
// that's probably close enough to the size of the result
|
||||
for (int i = 0; i < s.Length; i++)
|
||||
{
|
||||
if (char.IsWhiteSpace(s[i])) { continue; }
|
||||
sb.Append(s[i]);
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
//thanks to Jlobblet for this regex
|
||||
private static readonly Regex stringHashRegex = new Regex(@"^[0-9a-fA-F]{7,32}$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
|
||||
|
||||
public readonly byte[] ByteRepresentation;
|
||||
public readonly string StringRepresentation;
|
||||
public readonly string ShortRepresentation;
|
||||
|
||||
private static void CalculateHash(byte[] bytes, out string stringRepresentation, out byte[] byteRepresentation)
|
||||
{
|
||||
using (MD5 md5 = MD5.Create())
|
||||
{
|
||||
byte[] byteHash = md5.ComputeHash(bytes);
|
||||
|
||||
byteRepresentation = byteHash;
|
||||
stringRepresentation = ByteRepresentationToStringRepresentation(byteHash);
|
||||
}
|
||||
}
|
||||
|
||||
private static string ByteRepresentationToStringRepresentation(byte[] byteHash)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < byteHash.Length; i++)
|
||||
{
|
||||
sb.Append(byteHash[i].ToString("X2"));
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
private static byte[] StringRepresentationToByteRepresentation(string strHash)
|
||||
{
|
||||
var byteRepresentation = new byte[strHash.Length / 2];
|
||||
for (int i = 0; i < byteRepresentation.Length; i++)
|
||||
{
|
||||
byteRepresentation[i] = Convert.ToByte(strHash.Substring(i * 2, 2), 16);
|
||||
}
|
||||
|
||||
return byteRepresentation;
|
||||
}
|
||||
|
||||
public static string GetShortHash(string fullHash)
|
||||
{
|
||||
return fullHash.Length < 7 ? fullHash : fullHash.Substring(0, 7);
|
||||
}
|
||||
|
||||
private Md5Hash(string md5Hash)
|
||||
{
|
||||
StringRepresentation = md5Hash;
|
||||
ByteRepresentation = StringRepresentationToByteRepresentation(StringRepresentation);
|
||||
|
||||
ShortRepresentation = GetShortHash(md5Hash);
|
||||
}
|
||||
|
||||
private Md5Hash(byte[] bytes, bool calculate)
|
||||
{
|
||||
if (calculate)
|
||||
{
|
||||
CalculateHash(bytes, out StringRepresentation, out ByteRepresentation);
|
||||
}
|
||||
else
|
||||
{
|
||||
StringRepresentation = ByteRepresentationToStringRepresentation(bytes);
|
||||
ByteRepresentation = bytes;
|
||||
}
|
||||
|
||||
ShortRepresentation = GetShortHash(StringRepresentation);
|
||||
}
|
||||
|
||||
public static Md5Hash StringAsHash(string hash)
|
||||
{
|
||||
if (!stringHashRegex.IsMatch(hash)) { throw new ArgumentException($"{hash} is not a valid hash"); }
|
||||
return new Md5Hash(hash);
|
||||
}
|
||||
|
||||
public static Md5Hash CalculateForBytes(byte[] bytes)
|
||||
{
|
||||
return new Md5Hash(bytes, calculate: true);
|
||||
}
|
||||
|
||||
public static Md5Hash BytesAsHash(byte[] bytes)
|
||||
{
|
||||
return new Md5Hash(bytes, calculate: false);
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum StringHashOptions
|
||||
{
|
||||
BytePerfect = 0,
|
||||
IgnoreCase = 0x1,
|
||||
IgnoreWhitespace = 0x2
|
||||
}
|
||||
|
||||
public static Md5Hash CalculateForFile(string path, StringHashOptions options)
|
||||
{
|
||||
if (options.HasFlag(StringHashOptions.IgnoreWhitespace) || options.HasFlag(StringHashOptions.IgnoreCase))
|
||||
{
|
||||
string str = File.ReadAllText(path, Encoding.UTF8);
|
||||
return CalculateForString(str, options);
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] bytes = File.ReadAllBytes(path);
|
||||
return CalculateForBytes(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
public static Md5Hash CalculateForString(string str, StringHashOptions options)
|
||||
{
|
||||
if (options.HasFlag(StringHashOptions.IgnoreCase))
|
||||
{
|
||||
str = str.ToLowerInvariant();
|
||||
}
|
||||
if (options.HasFlag(StringHashOptions.IgnoreWhitespace))
|
||||
{
|
||||
str = RemoveWhitespace(str);
|
||||
}
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(str);
|
||||
return CalculateForBytes(bytes);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return StringRepresentation;
|
||||
}
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
if (obj is Md5Hash { StringRepresentation: { } otherStr })
|
||||
{
|
||||
string selfStr = otherStr.Length < StringRepresentation.Length
|
||||
? StringRepresentation[..otherStr.Length]
|
||||
: StringRepresentation;
|
||||
otherStr = StringRepresentation.Length < otherStr.Length
|
||||
? otherStr[..StringRepresentation.Length]
|
||||
: otherStr;
|
||||
return selfStr.Equals(otherStr, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool operator ==(Md5Hash? a, Md5Hash? b)
|
||||
=> (a is null == b is null) && (a?.Equals(b) ?? true);
|
||||
|
||||
public static bool operator !=(Md5Hash? a, Md5Hash? b) => !(a == b);
|
||||
}
|
||||
}
|
||||
@@ -752,6 +752,7 @@ namespace Barotrauma
|
||||
bool solutionFound = false;
|
||||
foreach (PlacedModule module in movableModules)
|
||||
{
|
||||
if (module.ThisGap.ConnectedDoor == null && module.PreviousGap.ConnectedDoor == null) { continue; }
|
||||
Vector2 moveDir = GetMoveDir(module.ThisGapPosition);
|
||||
Vector2 moveStep = moveDir * 50.0f;
|
||||
Vector2 currentMove = Vector2.Zero;
|
||||
@@ -1093,6 +1094,10 @@ namespace Barotrauma
|
||||
}
|
||||
thisWayPoint.Remove();
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.ThrowError($"Failed to connect waypoints between outpost modules. No waypoint in the {GetOpposingGapPosition(module.ThisGapPosition).ToString().ToLower()} gap of the module \"{module.PreviousModule.Info.Name}\".");
|
||||
}
|
||||
|
||||
gapToRemove.ConnectedDoor?.Item.Remove();
|
||||
if (hallwayLength <= 1.0f) { gapToRemove?.Remove(); }
|
||||
|
||||
@@ -28,8 +28,6 @@ namespace Barotrauma
|
||||
|
||||
partial class SubmarineInfo : IDisposable
|
||||
{
|
||||
public const string SavePath = "Submarines";
|
||||
|
||||
private static List<SubmarineInfo> savedSubmarines = new List<SubmarineInfo>();
|
||||
public static IEnumerable<SubmarineInfo> SavedSubmarines => savedSubmarines;
|
||||
|
||||
@@ -578,58 +576,14 @@ namespace Barotrauma
|
||||
if (File.Exists(savedSubmarines[i].FilePath))
|
||||
{
|
||||
bool isDownloadedSub = Path.GetFullPath(Path.GetDirectoryName(savedSubmarines[i].FilePath)) == Path.GetFullPath(SaveUtil.SubmarineDownloadFolder);
|
||||
bool isInSubmarinesFolder = Path.GetFullPath(Path.GetDirectoryName(savedSubmarines[i].FilePath)) == Path.GetFullPath(SavePath);
|
||||
bool isInContentPackage = contentPackageSubs.Any(f => f.Path == savedSubmarines[i].FilePath);
|
||||
if (isDownloadedSub) { continue; }
|
||||
if (savedSubmarines[i].LastModifiedTime == File.GetLastWriteTime(savedSubmarines[i].FilePath) && (isInSubmarinesFolder || isInContentPackage)) { continue; }
|
||||
if (savedSubmarines[i].LastModifiedTime == File.GetLastWriteTime(savedSubmarines[i].FilePath) && isInContentPackage) { continue; }
|
||||
}
|
||||
savedSubmarines[i].Dispose();
|
||||
}
|
||||
|
||||
if (!Directory.Exists(SavePath))
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(SavePath);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugConsole.ThrowError("Directory \"" + SavePath + "\" not found and creating the directory failed.", e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
List<string> filePaths;
|
||||
string[] subDirectories;
|
||||
|
||||
try
|
||||
{
|
||||
filePaths = Directory.GetFiles(SavePath).ToList();
|
||||
subDirectories = Directory.GetDirectories(SavePath).Where(s =>
|
||||
{
|
||||
DirectoryInfo dir = new DirectoryInfo(s);
|
||||
return !dir.Attributes.HasFlag(System.IO.FileAttributes.Hidden) && !dir.Name.StartsWith(".");
|
||||
}).ToArray();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugConsole.ThrowError("Couldn't open directory \"" + SavePath + "\"!", e);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (string subDirectory in subDirectories)
|
||||
{
|
||||
try
|
||||
{
|
||||
filePaths.AddRange(Directory.GetFiles(subDirectory).ToList());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugConsole.ThrowError("Couldn't open subdirectory \"" + subDirectory + "\"!", e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
List<string> filePaths = new List<string>();
|
||||
foreach (BaseSubFile subFile in contentPackageSubs)
|
||||
{
|
||||
if (!filePaths.Any(fp => fp == subFile.Path))
|
||||
@@ -643,34 +597,7 @@ namespace Barotrauma
|
||||
foreach (string path in filePaths)
|
||||
{
|
||||
var subInfo = new SubmarineInfo(path);
|
||||
if (subInfo.IsFileCorrupted)
|
||||
{
|
||||
#if CLIENT
|
||||
if (DebugConsole.IsOpen) { DebugConsole.Toggle(); }
|
||||
var deleteSubPrompt = new GUIMessageBox(
|
||||
TextManager.Get("Error"),
|
||||
TextManager.GetWithVariable("SubLoadError", "[subname]", subInfo.Name) + "\n" +
|
||||
TextManager.GetWithVariable("DeleteFileVerification", "[filename]", subInfo.Name),
|
||||
new LocalizedString[] { TextManager.Get("Yes"), TextManager.Get("No") });
|
||||
|
||||
string filePath = path;
|
||||
deleteSubPrompt.Buttons[0].OnClicked += (btn, userdata) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(filePath);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugConsole.ThrowError($"Failed to delete file \"{filePath}\".", e);
|
||||
}
|
||||
deleteSubPrompt.Close();
|
||||
return true;
|
||||
};
|
||||
deleteSubPrompt.Buttons[1].OnClicked += deleteSubPrompt.Close;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
if (!subInfo.IsFileCorrupted)
|
||||
{
|
||||
savedSubmarines.Add(subInfo);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user