Non-WinForms launcher with auto updater
This commit is contained in:
@@ -8,7 +8,7 @@ using System.Xml.Linq;
|
||||
|
||||
namespace Subsurface
|
||||
{
|
||||
class SaveUtil
|
||||
public class SaveUtil
|
||||
{
|
||||
private const string SaveFolder = "Content/Data/Saves/";
|
||||
|
||||
|
||||
@@ -11,10 +11,11 @@ namespace Subsurface
|
||||
/// <summary>
|
||||
/// Based on http://jakepoz.com/jake_poznanski__background_load_xna.html
|
||||
/// </summary>
|
||||
public class TextureLoader
|
||||
public static class TextureLoader
|
||||
{
|
||||
static TextureLoader()
|
||||
{
|
||||
|
||||
BlendColorBlendState = new BlendState
|
||||
{
|
||||
ColorDestinationBlend = Blend.Zero,
|
||||
@@ -34,14 +35,14 @@ namespace Subsurface
|
||||
};
|
||||
}
|
||||
|
||||
public TextureLoader(GraphicsDevice graphicsDevice, bool needsBmp = false)
|
||||
public static void Init(GraphicsDevice graphicsDevice, bool needsBmp = false)
|
||||
{
|
||||
_graphicsDevice = graphicsDevice;
|
||||
_needsBmp = needsBmp;
|
||||
_spriteBatch = new SpriteBatch(_graphicsDevice);
|
||||
}
|
||||
|
||||
public Texture2D FromFile(string path, bool preMultiplyAlpha = true)
|
||||
public static Texture2D FromFile(string path, bool preMultiplyAlpha = true)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -68,7 +69,7 @@ namespace Subsurface
|
||||
}
|
||||
|
||||
#if WINDOWS
|
||||
private Texture2D FromStream(Stream stream, bool preMultiplyAlpha = true)
|
||||
private static Texture2D FromStream(Stream stream, bool preMultiplyAlpha = true)
|
||||
{
|
||||
Texture2D texture;
|
||||
|
||||
@@ -97,7 +98,7 @@ namespace Subsurface
|
||||
}
|
||||
#endif
|
||||
|
||||
private Texture2D PreMultiplyAlpha(Texture2D texture)
|
||||
private static Texture2D PreMultiplyAlpha(Texture2D texture)
|
||||
{
|
||||
// Setup a render target to hold our final texture which will have premulitplied alpha values
|
||||
using (RenderTarget2D renderTarget = new RenderTarget2D(_graphicsDevice, texture.Width, texture.Height))
|
||||
@@ -136,8 +137,8 @@ namespace Subsurface
|
||||
private static readonly BlendState BlendColorBlendState;
|
||||
private static readonly BlendState BlendAlphaBlendState;
|
||||
|
||||
private readonly GraphicsDevice _graphicsDevice;
|
||||
private readonly SpriteBatch _spriteBatch;
|
||||
private readonly bool _needsBmp;
|
||||
private static GraphicsDevice _graphicsDevice;
|
||||
private static SpriteBatch _spriteBatch;
|
||||
private static bool _needsBmp;
|
||||
}
|
||||
}
|
||||
@@ -5,11 +5,12 @@ using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Subsurface
|
||||
{
|
||||
static class ToolBox
|
||||
public static class ToolBox
|
||||
{
|
||||
public static XDocument TryLoadXml(string filePath)
|
||||
{
|
||||
@@ -195,6 +196,19 @@ namespace Subsurface
|
||||
return ParseToVector4(val);
|
||||
}
|
||||
|
||||
public static string ElementInnerText(this XElement el)
|
||||
{
|
||||
StringBuilder str = new StringBuilder();
|
||||
foreach (XNode element in el.DescendantNodes().Where(x => x.NodeType == XmlNodeType.Text))
|
||||
{
|
||||
str.Append(element.ToString());
|
||||
}
|
||||
return str.ToString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static Vector2 ParseToVector2(string stringVector2, bool errorMessages = true)
|
||||
{
|
||||
string[] components = stringVector2.Split(',');
|
||||
@@ -284,14 +298,16 @@ namespace Subsurface
|
||||
{
|
||||
if (font.MeasureString(text).X < lineLength) return text;
|
||||
|
||||
string[] words = text.Split(' ', '\n');
|
||||
text = text.Replace("\n", " \n ");
|
||||
|
||||
string[] words = text.Split(' ');//, '\n');
|
||||
|
||||
StringBuilder wrappedText = new StringBuilder();
|
||||
float linePos = 0f;
|
||||
float spaceWidth = font.MeasureString(" ").X;
|
||||
for (int i = 0; i < words.Length; ++i)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(words[i])) continue;
|
||||
if (string.IsNullOrWhiteSpace(words[i]) && words[i]!="\n") continue;
|
||||
|
||||
Vector2 size;
|
||||
string tempWord = words[i];
|
||||
@@ -299,9 +315,8 @@ namespace Subsurface
|
||||
while ((size = font.MeasureString(tempWord)).X > lineLength)
|
||||
{
|
||||
tempWord = tempWord.Remove(tempWord.Length - 1, 1);
|
||||
|
||||
|
||||
}
|
||||
|
||||
words[i] = tempWord;
|
||||
if (prevWord.Length> tempWord.Length)
|
||||
{
|
||||
@@ -315,22 +330,29 @@ namespace Subsurface
|
||||
|
||||
if (linePos + size.X < lineLength)
|
||||
{
|
||||
wrappedText.Append(words[i]);
|
||||
linePos += size.X + spaceWidth;
|
||||
wrappedText.Append(words[i]);
|
||||
if (words[i] == "\n")
|
||||
{
|
||||
linePos = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
linePos += size.X + spaceWidth;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//if (i>0)wrappedText.Remove(wrappedText.Length - 1, 1);
|
||||
wrappedText.Append("\n");
|
||||
wrappedText.Append(words[i]);
|
||||
|
||||
|
||||
|
||||
|
||||
linePos = size.X + spaceWidth;
|
||||
wrappedText.Append("\n");
|
||||
wrappedText.Append(words[i]);
|
||||
|
||||
linePos = size.X + spaceWidth;
|
||||
|
||||
}
|
||||
|
||||
if (i<words.Length-1) wrappedText.Append(" ");
|
||||
|
||||
if (i < words.Length - 1) wrappedText.Append(" ");
|
||||
}
|
||||
|
||||
return wrappedText.ToString();
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Subsurface
|
||||
{
|
||||
public static class UpdaterUtil
|
||||
{
|
||||
public static void SaveFileList(string filePath)
|
||||
{
|
||||
XDocument doc = new XDocument(CreateFileList());
|
||||
|
||||
doc.Save(filePath);
|
||||
}
|
||||
|
||||
public static XElement CreateFileList()
|
||||
{
|
||||
XElement root = new XElement("filelist");
|
||||
string currentDir = Directory.GetCurrentDirectory();
|
||||
|
||||
string[] files = Directory.GetFiles(currentDir, "*", SearchOption.AllDirectories);
|
||||
|
||||
foreach (string file in files)
|
||||
{
|
||||
XElement fileElement = new XElement("file");
|
||||
fileElement.Add(new XAttribute("path", GetRelativePath(file, currentDir)));
|
||||
fileElement.Add(new XAttribute("md5", GetFileMd5Hash(file)));
|
||||
|
||||
root.Add(fileElement);
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
public static List<string> GetFileList(XDocument fileListDoc)
|
||||
{
|
||||
List<string> fileList = new List<string>();
|
||||
|
||||
XElement fileListElement = fileListDoc.Root;
|
||||
|
||||
if (fileListElement == null)
|
||||
{
|
||||
throw new Exception("Received list of new files was corrupted");
|
||||
}
|
||||
|
||||
foreach (XElement file in fileListElement.Elements())
|
||||
{
|
||||
string filePath = ToolBox.GetAttributeString(file, "path", "");
|
||||
|
||||
fileList.Add(filePath);
|
||||
}
|
||||
|
||||
return fileList;
|
||||
}
|
||||
|
||||
public static List<string> GetRequiredFiles(XDocument fileListDoc)
|
||||
{
|
||||
List<string> requiredFiles = new List<string>();
|
||||
|
||||
XElement fileList = fileListDoc.Root;
|
||||
|
||||
if (fileList==null)
|
||||
{
|
||||
throw new Exception("Received list of new files was corrupted");
|
||||
}
|
||||
|
||||
foreach (XElement file in fileList.Elements())
|
||||
{
|
||||
string filePath = ToolBox.GetAttributeString(file, "path", "");
|
||||
|
||||
if (!File.Exists(filePath))
|
||||
{
|
||||
requiredFiles.Add(filePath);
|
||||
continue;
|
||||
}
|
||||
|
||||
string md5 = ToolBox.GetAttributeString(file, "md5", "");
|
||||
|
||||
if (GetFileMd5Hash(filePath) != md5)
|
||||
{
|
||||
requiredFiles.Add(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
return requiredFiles;
|
||||
}
|
||||
|
||||
private static string GetFileMd5Hash(string filePath)
|
||||
{
|
||||
Md5Hash md5Hash = null;
|
||||
var md5 = MD5.Create();
|
||||
using (var stream = File.OpenRead(filePath))
|
||||
{
|
||||
md5Hash = new Md5Hash(md5.ComputeHash(stream));
|
||||
}
|
||||
|
||||
return md5Hash.Hash;
|
||||
}
|
||||
|
||||
public static string GetRelativePath(string filespec, string folder)
|
||||
{
|
||||
Uri pathUri = new Uri(filespec);
|
||||
// Folders must end in a slash
|
||||
if (!folder.EndsWith(Path.DirectorySeparatorChar.ToString()))
|
||||
{
|
||||
folder += Path.DirectorySeparatorChar;
|
||||
}
|
||||
Uri folderUri = new Uri(folder);
|
||||
return Uri.UnescapeDataString(folderUri.MakeRelativeUri(pathUri).ToString().Replace('/', Path.DirectorySeparatorChar));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// moves the files in the updatefolder to the install folder
|
||||
/// if there's an existing file with the same name in the install folder and it can't be removed,
|
||||
/// it will be renamed as "OLD_[filename]"
|
||||
/// </summary>
|
||||
/// <param name="updateFileFolder"></param>
|
||||
public static void InstallUpdatedFiles(string updateFileFolder)
|
||||
{
|
||||
string[] files = Directory.GetFiles(updateFileFolder, "*", SearchOption.AllDirectories);
|
||||
|
||||
string currentDir = Directory.GetCurrentDirectory();
|
||||
|
||||
foreach (string file in files)
|
||||
{
|
||||
string fileRelPath = GetRelativePath(file, updateFileFolder);
|
||||
|
||||
if (File.Exists(fileRelPath))
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(fileRelPath);
|
||||
}
|
||||
|
||||
catch
|
||||
{
|
||||
string oldFileName = currentDir+"\\"+Path.GetDirectoryName(fileRelPath)+"\\OLD_"+Path.GetFileName(fileRelPath);
|
||||
|
||||
if (File.Exists(oldFileName)) File.Delete(oldFileName);
|
||||
|
||||
//couldn't delete file, probably because it's already in use
|
||||
File.Move(fileRelPath, oldFileName);
|
||||
}
|
||||
}
|
||||
|
||||
File.Move(file, fileRelPath);
|
||||
}
|
||||
|
||||
Directory.Delete(updateFileFolder);
|
||||
}
|
||||
|
||||
public static void CleanUnnecessaryFiles(List<string> filesToKeep)
|
||||
{
|
||||
string currentDir = Directory.GetCurrentDirectory();
|
||||
|
||||
string[] files = Directory.GetFiles(currentDir, "*", SearchOption.AllDirectories);
|
||||
|
||||
foreach (string file in files)
|
||||
{
|
||||
if (filesToKeep.Contains(GetRelativePath(file, currentDir))) continue;
|
||||
|
||||
System.Diagnostics.Debug.WriteLine("deleting file "+file);
|
||||
|
||||
try
|
||||
{
|
||||
File.Delete(currentDir + "\\" + file);
|
||||
}
|
||||
|
||||
catch (Exception e)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("Could not delete file ''" + file + "'' (" + e.Message + ")");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user