Unstable v0.19.3.0
This commit is contained in:
@@ -1,21 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
public static class IPExtensions
|
||||
{
|
||||
//TODO: remove?
|
||||
//workaround for .NET Framework 4.5 bug; presumably fixed in later versions
|
||||
//see https://stackoverflow.com/questions/23608829/why-does-ipaddress-maptoipv4-throw-argumentoutofrangeexception
|
||||
public static IPAddress MapToIPv4NoThrow(this IPAddress address)
|
||||
{
|
||||
byte[] addressBytes = address.GetAddressBytes();
|
||||
|
||||
return new IPAddress(addressBytes.Skip(addressBytes.Length - 4).ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -231,7 +231,19 @@ namespace Barotrauma.IO
|
||||
|
||||
public static bool IsPathRooted(string path) => System.IO.Path.IsPathRooted(path);
|
||||
|
||||
public static IEnumerable<char> GetInvalidFileNameChars() => System.IO.Path.GetInvalidFileNameChars();
|
||||
private static readonly ImmutableHashSet<char> invalidFileNameChars = ImmutableHashSet.Create
|
||||
(
|
||||
'\"', '<', '>', '|', '\0',
|
||||
(char)1, (char)2, (char)3, (char)4, (char)5, (char)6, (char)7, (char)8, (char)9, (char)10,
|
||||
(char)11, (char)12, (char)13, (char)14, (char)15, (char)16, (char)17, (char)18, (char)19, (char)20,
|
||||
(char)21, (char)22, (char)23, (char)24, (char)25, (char)26, (char)27, (char)28, (char)29, (char)30,
|
||||
(char)31, ':', '*', '?', '\\', '/'
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Returns file name characters that are invalid on any of our supported platforms (essentially the list of invalid characters on Windows)
|
||||
/// </summary>
|
||||
public static ImmutableHashSet<char> GetInvalidFileNameCharsCrossPlatform() => invalidFileNameChars;
|
||||
}
|
||||
|
||||
public static class Directory
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Barotrauma.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Xml.Linq;
|
||||
using Steamworks.Data;
|
||||
using Color = Microsoft.Xna.Framework.Color;
|
||||
using System.Text.RegularExpressions;
|
||||
using Barotrauma.IO;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -20,7 +18,7 @@ namespace Barotrauma
|
||||
|
||||
#if OSX
|
||||
//"/*user*/Library/Application Support/Daedalic Entertainment GmbH/" on Mac
|
||||
public static string SaveFolder = Path.Combine(
|
||||
public static readonly string SaveFolder = Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.Personal),
|
||||
"Library",
|
||||
"Application Support",
|
||||
@@ -29,7 +27,7 @@ namespace Barotrauma
|
||||
#else
|
||||
//"C:/Users/*user*/AppData/Local/Daedalic Entertainment GmbH/" on Windows
|
||||
//"/home/*user*/.local/share/Daedalic Entertainment GmbH/" on Linux
|
||||
public static string SaveFolder = Path.Combine(
|
||||
public static readonly string SaveFolder = Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
|
||||
"Daedalic Entertainment GmbH",
|
||||
"Barotrauma");
|
||||
@@ -165,15 +163,6 @@ namespace Barotrauma
|
||||
return ownedSubmarines;
|
||||
}
|
||||
|
||||
/*public static void LoadMultiplayerCampaignState(string filePath, MultiPlayerCampaign multiplayerCampaign)
|
||||
{
|
||||
DebugConsole.Log("Loading save file for an existing game session (" + filePath + ")");
|
||||
DecompressToDirectory(filePath, TempPath, null);
|
||||
XDocument doc = XMLExtensions.TryLoadXml(Path.Combine(TempPath, "gamesession.xml"));
|
||||
if (doc == null) { return; }
|
||||
gameSession.Load(doc.Root);
|
||||
}*/
|
||||
|
||||
public static XDocument LoadGameSessionDoc(string filePath)
|
||||
{
|
||||
DebugConsole.Log("Loading game session doc: " + filePath);
|
||||
@@ -391,73 +380,69 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
|
||||
public static System.IO.Stream DecompressFiletoStream(string fileName)
|
||||
public static System.IO.Stream DecompressFileToStream(string fileName)
|
||||
{
|
||||
using (FileStream originalFileStream = File.Open(fileName, System.IO.FileMode.Open))
|
||||
{
|
||||
System.IO.MemoryStream decompressedFileStream = new System.IO.MemoryStream();
|
||||
using FileStream originalFileStream = File.Open(fileName, System.IO.FileMode.Open, System.IO.FileAccess.Read);
|
||||
System.IO.MemoryStream streamToReturn = new System.IO.MemoryStream();
|
||||
|
||||
using (GZipStream decompressionStream = new GZipStream(originalFileStream, CompressionMode.Decompress))
|
||||
{
|
||||
decompressionStream.CopyTo(decompressedFileStream);
|
||||
return decompressedFileStream;
|
||||
}
|
||||
}
|
||||
using GZipStream gzipStream = new GZipStream(originalFileStream, CompressionMode.Decompress);
|
||||
gzipStream.CopyTo(streamToReturn);
|
||||
|
||||
streamToReturn.Position = 0;
|
||||
return streamToReturn;
|
||||
}
|
||||
|
||||
private static bool DecompressFile(bool writeFile, string sDir, GZipStream zipStream, ProgressDelegate progress, out string fileName)
|
||||
private static bool IsExtractionPathValid(string rootDir, string fileDir)
|
||||
{
|
||||
string getFullPath(string dir)
|
||||
=> (string.IsNullOrEmpty(dir)
|
||||
? Directory.GetCurrentDirectory()
|
||||
: Path.GetFullPath(dir))
|
||||
.CleanUpPathCrossPlatform(correctFilenameCase: false);
|
||||
|
||||
string rootDirFull = getFullPath(rootDir);
|
||||
string fileDirFull = getFullPath(fileDir);
|
||||
|
||||
return fileDirFull.StartsWith(rootDirFull, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private static bool DecompressFile(bool writeFile, string sDir, System.IO.BinaryReader reader, ProgressDelegate progress, out string fileName)
|
||||
{
|
||||
fileName = null;
|
||||
|
||||
if (reader.PeekChar() < 0) { return false; }
|
||||
|
||||
//Decompress file name
|
||||
byte[] bytes = new byte[sizeof(int)];
|
||||
int Readed = Read(zipStream, bytes, sizeof(int));
|
||||
if (Readed < sizeof(int))
|
||||
return false;
|
||||
|
||||
int iNameLen = BitConverter.ToInt32(bytes, 0);
|
||||
if (iNameLen > 255)
|
||||
int nameLen = reader.ReadInt32();
|
||||
if (nameLen > 255)
|
||||
{
|
||||
throw new Exception("Failed to decompress \"" + sDir + "\" (file name length > 255). The file may be corrupted.");
|
||||
throw new Exception(
|
||||
$"Failed to decompress \"{sDir}\" (file name length > 255). The file may be corrupted.");
|
||||
}
|
||||
|
||||
bytes = new byte[sizeof(char)];
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < iNameLen; i++)
|
||||
{
|
||||
Read(zipStream, bytes, sizeof(char));
|
||||
char c = BitConverter.ToChar(bytes, 0);
|
||||
sb.Append(c);
|
||||
}
|
||||
string sFileName = sb.ToString().Replace('\\', '/');
|
||||
byte[] strBytes = reader.ReadBytes(nameLen * sizeof(char));
|
||||
string sFileName = Encoding.Unicode.GetString(strBytes)
|
||||
.Replace('\\', '/');
|
||||
|
||||
fileName = sFileName;
|
||||
progress?.Invoke(sFileName);
|
||||
|
||||
//Decompress file content
|
||||
bytes = new byte[sizeof(int)];
|
||||
Read(zipStream, bytes, sizeof(int));
|
||||
int iFileLen = BitConverter.ToInt32(bytes, 0);
|
||||
|
||||
bytes = new byte[iFileLen];
|
||||
Read(zipStream, bytes, bytes.Length);
|
||||
int contentLen = reader.ReadInt32();
|
||||
byte[] contentBytes = reader.ReadBytes(contentLen);
|
||||
|
||||
string sFilePath = Path.Combine(sDir, sFileName);
|
||||
string sFinalDir = Path.GetDirectoryName(sFilePath);
|
||||
|
||||
string sDirFull = (string.IsNullOrEmpty(sDir) ? Directory.GetCurrentDirectory() : Path.GetFullPath(sDir)).CleanUpPathCrossPlatform(correctFilenameCase: false);
|
||||
string sFinalDirFull = (string.IsNullOrEmpty(sFinalDir) ? Directory.GetCurrentDirectory() : Path.GetFullPath(sFinalDir)).CleanUpPathCrossPlatform(correctFilenameCase: false);
|
||||
|
||||
if (!sFinalDirFull.StartsWith(sDirFull, StringComparison.OrdinalIgnoreCase))
|
||||
if (!IsExtractionPathValid(sDir, sFinalDir))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"Error extracting \"{sFileName}\": cannot be extracted to parent directory");
|
||||
}
|
||||
|
||||
|
||||
if (!writeFile) { return true; }
|
||||
if (!Directory.Exists(sFinalDir))
|
||||
Directory.CreateDirectory(sFinalDir);
|
||||
|
||||
Directory.CreateDirectory(sFinalDir);
|
||||
int maxRetries = 4;
|
||||
for (int i = 0; i <= maxRetries; i++)
|
||||
{
|
||||
@@ -465,7 +450,7 @@ namespace Barotrauma
|
||||
{
|
||||
using (FileStream outFile = File.Open(sFilePath, System.IO.FileMode.Create, System.IO.FileAccess.Write))
|
||||
{
|
||||
outFile.Write(bytes, 0, iFileLen);
|
||||
outFile.Write(contentBytes, 0, contentLen);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -479,26 +464,6 @@ namespace Barotrauma
|
||||
return true;
|
||||
}
|
||||
|
||||
private static int Read(GZipStream zipStream, byte[] bytes, int amount)
|
||||
{
|
||||
int read = 0;
|
||||
|
||||
// BUG workaround for .NET6 causing save decompression to fail
|
||||
#if NET6_0
|
||||
for (int i = 0; i < amount; i++)
|
||||
{
|
||||
int result = zipStream.ReadByte();
|
||||
if (result < 0) { break; }
|
||||
|
||||
bytes[i] = (byte) result;
|
||||
read++;
|
||||
}
|
||||
#else
|
||||
read = zipStream.Read(bytes, 0, amount);
|
||||
#endif
|
||||
return read;
|
||||
}
|
||||
|
||||
public static void DecompressToDirectory(string sCompressedFile, string sDir, ProgressDelegate progress)
|
||||
{
|
||||
DebugConsole.Log("Decompressing " + sCompressedFile + " to " + sDir + "...");
|
||||
@@ -507,9 +472,9 @@ namespace Barotrauma
|
||||
{
|
||||
try
|
||||
{
|
||||
using (FileStream inFile = File.Open(sCompressedFile, System.IO.FileMode.Open, System.IO.FileAccess.Read))
|
||||
using (GZipStream zipStream = new GZipStream(inFile, CompressionMode.Decompress, true))
|
||||
while (DecompressFile(true, sDir, zipStream, progress, out _)) { };
|
||||
using (var memStream = DecompressFileToStream(sCompressedFile))
|
||||
using (System.IO.BinaryReader reader = new System.IO.BinaryReader(memStream))
|
||||
while (DecompressFile(true, sDir, reader, progress, out _)) { };
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -530,12 +495,12 @@ namespace Barotrauma
|
||||
{
|
||||
try
|
||||
{
|
||||
using FileStream inFile = File.Open(sCompressedFile, System.IO.FileMode.Open, System.IO.FileAccess.Read);
|
||||
using GZipStream zipStream = new GZipStream(inFile, CompressionMode.Decompress, true);
|
||||
while (DecompressFile(false, "", zipStream, null, out string fileName))
|
||||
{
|
||||
paths.Add(fileName);
|
||||
}
|
||||
using (var memStream = DecompressFileToStream(sCompressedFile))
|
||||
using (System.IO.BinaryReader reader = new System.IO.BinaryReader(memStream))
|
||||
while (DecompressFile(false, "", reader, null, out string fileName))
|
||||
{
|
||||
paths.Add(fileName);
|
||||
}
|
||||
}
|
||||
catch (System.IO.IOException e)
|
||||
{
|
||||
|
||||
@@ -3,13 +3,12 @@ using Barotrauma.Networking;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Barotrauma.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -161,7 +160,7 @@ namespace Barotrauma
|
||||
|
||||
public static string RemoveInvalidFileNameChars(string fileName)
|
||||
{
|
||||
var invalidChars = Path.GetInvalidFileNameChars().Concat(new char[] {':', ';', '<', '>', '"', '/', '\\', '|', '?', '*'});
|
||||
var invalidChars = Path.GetInvalidFileNameCharsCrossPlatform().Concat(new char[] {';'});
|
||||
foreach (char invalidChar in invalidChars)
|
||||
{
|
||||
fileName = fileName.Replace(invalidChar.ToString(), "");
|
||||
@@ -424,7 +423,7 @@ namespace Barotrauma
|
||||
for (int i = 0; i < numberOfBits; i++)
|
||||
{
|
||||
bool bit = originalBuffer.ReadBoolean();
|
||||
buffer.Write(bit);
|
||||
buffer.WriteBoolean(bit);
|
||||
}
|
||||
buffer.BitPosition = 0;
|
||||
|
||||
@@ -713,9 +712,14 @@ namespace Barotrauma
|
||||
return e;
|
||||
}
|
||||
|
||||
public static void ThrowIfNull<T>(T o)
|
||||
public static void ThrowIfNull<T>([NotNull] T o)
|
||||
{
|
||||
if (o is null) { throw new ArgumentNullException(); }
|
||||
}
|
||||
|
||||
public static string GetFormattedPercentage(float v)
|
||||
{
|
||||
return TextManager.GetWithVariable("percentageformat", "[value]", ((int)MathF.Round(v * 100)).ToString()).Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user