mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-16 11:06:06 -04:00
redesign how file and directory methods work
This commit is contained in:
parent
c68eb4df4b
commit
533cca344f
@ -13,15 +13,13 @@ namespace ClassicalSharp.Gui.Screens {
|
||||
|
||||
public LoadLevelScreen(Game game) : base(game) {
|
||||
titleText = "Select a level";
|
||||
string dir = Path.Combine(Program.AppDirectory, "maps");
|
||||
string[] rawFiles = Directory.GetFiles(dir);
|
||||
string[] rawFiles = Platform.DirectoryFiles("maps");
|
||||
int count = 0;
|
||||
|
||||
// Only add map files
|
||||
for (int i = 0; i < rawFiles.Length; i++) {
|
||||
string file = rawFiles[i];
|
||||
if (file.EndsWith(".cw") || file.EndsWith(".dat")
|
||||
|| file.EndsWith(".fcm") || file.EndsWith(".lvl")) {
|
||||
if (file.EndsWith(".cw") || file.EndsWith(".dat") || file.EndsWith(".fcm") || file.EndsWith(".lvl")) {
|
||||
count++;
|
||||
} else {
|
||||
rawFiles[i] = null;
|
||||
@ -38,13 +36,9 @@ namespace ClassicalSharp.Gui.Screens {
|
||||
}
|
||||
|
||||
protected override void TextButtonClick(Game game, Widget widget) {
|
||||
string path = Path.Combine(Program.AppDirectory, "maps");
|
||||
path = Path.Combine(path, ((ButtonWidget)widget).Text);
|
||||
if (File.Exists(path))
|
||||
LoadMap(path);
|
||||
}
|
||||
|
||||
void LoadMap(string path) {
|
||||
string path = Path.Combine("maps", ((ButtonWidget)widget).Text);
|
||||
if (!Platform.FileExists(path)) return;
|
||||
|
||||
IMapFormatImporter importer = null;
|
||||
if (path.EndsWith(".dat")) {
|
||||
importer = new MapDatImporter();
|
||||
@ -57,7 +51,7 @@ namespace ClassicalSharp.Gui.Screens {
|
||||
}
|
||||
|
||||
try {
|
||||
using (FileStream fs = File.OpenRead(path)) {
|
||||
using (Stream fs = Platform.FileOpen(path)) {
|
||||
int width, height, length;
|
||||
game.World.Reset();
|
||||
game.WorldEvents.RaiseOnNewMap();
|
||||
|
@ -15,14 +15,30 @@ namespace ClassicalSharp.Gui.Screens {
|
||||
InputWidget input;
|
||||
const int overwriteIndex = 2;
|
||||
static FastColour grey = new FastColour(150, 150, 150);
|
||||
string textPath;
|
||||
|
||||
public override void Render(double delta) {
|
||||
base.Render(delta);
|
||||
int cX = game.Width / 2, cY = game.Height / 2;
|
||||
game.Graphics.Draw2DQuad(cX - 250, cY + 90, 500, 2, grey);
|
||||
|
||||
game.Graphics.Draw2DQuad(cX - 250, cY + 90, 500, 2, grey);
|
||||
if (textPath == null) return;
|
||||
SaveMap(textPath);
|
||||
|
||||
bool classic = textPath.EndsWith(".cw");
|
||||
try {
|
||||
using (Stream fs = Platform.FileCreate(textPath)) {
|
||||
IMapFormatExporter exporter = null;
|
||||
if (classic) exporter = new MapCwExporter();
|
||||
else exporter = new MapSchematicExporter();
|
||||
exporter.Save(fs, game);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ErrorHandler.LogError("saving map", ex);
|
||||
MakeDescWidget("&cError while trying to save map");
|
||||
return;
|
||||
}
|
||||
|
||||
game.Chat.Add("&eSaved map to: " + textPath);
|
||||
game.Gui.SetNewScreen(new PauseScreen(game));
|
||||
textPath = null;
|
||||
}
|
||||
|
||||
@ -79,23 +95,23 @@ namespace ClassicalSharp.Gui.Screens {
|
||||
void SaveSchematic(Game game, Widget widget) { DoSave(widget, ".schematic"); }
|
||||
|
||||
void DoSave(Widget widget, string ext) {
|
||||
string text = input.Text.ToString();
|
||||
if (text.Length == 0) {
|
||||
string file = input.Text.ToString();
|
||||
if (file.Length == 0) {
|
||||
MakeDescWidget("&ePlease enter a filename"); return;
|
||||
}
|
||||
string file = Path.ChangeExtension(text, ext);
|
||||
text = Path.Combine(Program.AppDirectory, "maps");
|
||||
text = Path.Combine(text, file);
|
||||
|
||||
file = Path.ChangeExtension(file, ext);
|
||||
string path = Path.Combine("maps", file);
|
||||
ButtonWidget btn = (ButtonWidget)widget;
|
||||
if (File.Exists(text) && btn.OptName == null) {
|
||||
|
||||
if (Platform.FileExists(path) && btn.OptName == null) {
|
||||
btn.SetText("&cOverwrite existing?");
|
||||
btn.OptName = "O";
|
||||
} else {
|
||||
// NOTE: We don't immediately save here, because otherwise the 'saving...'
|
||||
// will not be rendered in time because saving is done on the main thread.
|
||||
MakeDescWidget("Saving..");
|
||||
textPath = text;
|
||||
textPath = path;
|
||||
RemoveOverwrites();
|
||||
}
|
||||
}
|
||||
@ -113,27 +129,6 @@ namespace ClassicalSharp.Gui.Screens {
|
||||
button.SetText(defaultText);
|
||||
}
|
||||
|
||||
string textPath;
|
||||
void SaveMap(string path) {
|
||||
bool classic = path.EndsWith(".cw");
|
||||
try {
|
||||
if (File.Exists(path))
|
||||
File.Delete(path);
|
||||
using (FileStream fs = new FileStream(path, FileMode.CreateNew, FileAccess.Write)) {
|
||||
IMapFormatExporter exporter = null;
|
||||
if (classic) exporter = new MapCwExporter();
|
||||
else exporter = new MapSchematicExporter();
|
||||
exporter.Save(fs, game);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ErrorHandler.LogError("saving map", ex);
|
||||
MakeDescWidget("&cError while trying to save map");
|
||||
return;
|
||||
}
|
||||
game.Chat.Add("&eSaved map to: " + Path.GetFileName(path));
|
||||
game.Gui.SetNewScreen(new PauseScreen(game));
|
||||
}
|
||||
|
||||
void MakeDescWidget(string text) {
|
||||
DisposeDescWidget();
|
||||
widgets[widgets.Length - 1] = TextWidget.Create(game, text, textFont)
|
||||
|
@ -10,19 +10,18 @@ namespace ClassicalSharp.Gui.Screens {
|
||||
|
||||
public TexturePackScreen(Game game) : base(game) {
|
||||
titleText = "Select a texture pack zip";
|
||||
string dir = Path.Combine(Program.AppDirectory, "texpacks");
|
||||
entries = Directory.GetFiles(dir, "*.zip");
|
||||
entries = Platform.DirectoryFiles("texpacks", "*.zip");
|
||||
|
||||
for (int i = 0; i < entries.Length; i++)
|
||||
for (int i = 0; i < entries.Length; i++) {
|
||||
entries[i] = Path.GetFileName(entries[i]);
|
||||
}
|
||||
Array.Sort(entries);
|
||||
}
|
||||
|
||||
protected override void TextButtonClick(Game game, Widget widget) {
|
||||
string file = ((ButtonWidget)widget).Text;
|
||||
string dir = Path.Combine(Program.AppDirectory, "texpacks");
|
||||
string path = Path.Combine(dir, file);
|
||||
if (!File.Exists(path)) return;
|
||||
string path = Path.Combine("texpacks", file);
|
||||
if (!Platform.FileExists(path)) return;
|
||||
|
||||
int curPage = currentIndex;
|
||||
game.DefaultTexturePack = file;
|
||||
|
@ -17,11 +17,11 @@ namespace ClassicalSharp.Audio {
|
||||
|
||||
public void Init(Game game) {
|
||||
this.game = game;
|
||||
string path = Path.Combine(Program.AppDirectory, "audio");
|
||||
if (Directory.Exists(path))
|
||||
files = Directory.GetFiles(path);
|
||||
else
|
||||
if (Platform.DirectoryExists("audio")) {
|
||||
files = Platform.DirectoryFiles("audio");
|
||||
} else {
|
||||
files = new string[0];
|
||||
}
|
||||
|
||||
game.MusicVolume = GetVolume(OptionsKey.MusicVolume, OptionsKey.UseMusic);
|
||||
SetMusic(game.MusicVolume);
|
||||
@ -60,7 +60,8 @@ namespace ClassicalSharp.Audio {
|
||||
musicFiles = new string[musicCount];
|
||||
for (int i = 0, j = 0; i < files.Length; i++) {
|
||||
if (!Utils.CaselessEnds(files[i], ".ogg")) continue;
|
||||
musicFiles[j] = files[i]; j++;
|
||||
musicFiles[j] = Path.GetFileName(files[i]);
|
||||
j++;
|
||||
}
|
||||
|
||||
disposingMusic = false;
|
||||
@ -75,10 +76,9 @@ namespace ClassicalSharp.Audio {
|
||||
Random rnd = new Random();
|
||||
while (!disposingMusic) {
|
||||
string file = musicFiles[rnd.Next(0, musicFiles.Length)];
|
||||
string path = Path.Combine(Program.AppDirectory, file);
|
||||
Utils.LogDebug("playing music file: " + file);
|
||||
|
||||
using (FileStream fs = File.OpenRead(path)) {
|
||||
using (Stream fs = Platform.FileOpen(file)) {
|
||||
OggContainer container = new OggContainer(fs);
|
||||
try {
|
||||
musicOut.SetVolume(game.MusicVolume / 100.0f);
|
||||
|
@ -65,7 +65,7 @@ namespace ClassicalSharp.Audio {
|
||||
}
|
||||
|
||||
Sound ReadWave(string file) {
|
||||
using (FileStream fs = File.OpenRead(file))
|
||||
using (Stream fs = File.OpenRead(file))
|
||||
using (BinaryReader r = new BinaryReader(fs))
|
||||
{
|
||||
string fourCC = GetFourCC(r);
|
||||
|
@ -126,20 +126,19 @@ namespace ClassicalSharp {
|
||||
}
|
||||
|
||||
void OpenChatFile(DateTime now) {
|
||||
string basePath = Path.Combine(Program.AppDirectory, "logs");
|
||||
if (!Directory.Exists(basePath))
|
||||
Directory.CreateDirectory(basePath);
|
||||
if (!Platform.DirectoryExists("logs")) {
|
||||
Platform.DirectoryCreate("logs");
|
||||
}
|
||||
|
||||
string date = now.ToString("yyyy-MM-dd");
|
||||
// Ensure multiple instances do not end up overwriting each other's log entries.
|
||||
for (int i = 0; i < 20; i++) {
|
||||
string id = i == 0 ? "" : " _" + i;
|
||||
string fileName = date + " " + logName + id + ".log";
|
||||
string path = Path.Combine(basePath, fileName);
|
||||
string path = Path.Combine("logs", date + " " + logName + id + ".log");
|
||||
|
||||
FileStream stream = null;
|
||||
Stream stream = null;
|
||||
try {
|
||||
stream = File.Open(path, FileMode.Append, FileAccess.Write, FileShare.Read);
|
||||
stream = Platform.FileAppend(path);
|
||||
} catch (IOException ex) {
|
||||
int hresult = Marshal.GetHRForException(ex);
|
||||
uint errorCode = (uint)hresult & 0xFFFF;
|
||||
|
@ -161,9 +161,12 @@ namespace ClassicalSharp {
|
||||
defTexturePack = Options.Get(OptionsKey.DefaultTexturePack) ?? "default.zip";
|
||||
TexturePack extractor = new TexturePack();
|
||||
extractor.Extract("default.zip", this);
|
||||
|
||||
// in case the user's default texture pack doesn't have all required textures
|
||||
if (DefaultTexturePack != "default.zip")
|
||||
extractor.Extract(DefaultTexturePack, this);
|
||||
string defTexPack = DefaultTexturePack;
|
||||
if (defTexPack != "default.zip") {
|
||||
extractor.Extract(defTexPack, this);
|
||||
}
|
||||
}
|
||||
|
||||
void LoadOptions() {
|
||||
|
@ -9,7 +9,6 @@ using ClassicalSharp.Commands;
|
||||
using ClassicalSharp.Entities;
|
||||
using ClassicalSharp.Events;
|
||||
using ClassicalSharp.GraphicsAPI;
|
||||
using ClassicalSharp.Gui;
|
||||
using ClassicalSharp.Map;
|
||||
using ClassicalSharp.Mode;
|
||||
using ClassicalSharp.Model;
|
||||
@ -231,9 +230,8 @@ namespace ClassicalSharp {
|
||||
/// this method returns "default.zip". </remarks>
|
||||
public string DefaultTexturePack {
|
||||
get {
|
||||
string path = Path.Combine(Program.AppDirectory, "texpacks");
|
||||
path = Path.Combine(path, defTexturePack);
|
||||
return File.Exists(path) && !ClassicMode ? defTexturePack : "default.zip";
|
||||
string texPath = Path.Combine("texpacks", defTexturePack);
|
||||
return Platform.FileExists(texPath) && !ClassicMode ? defTexturePack : "default.zip";
|
||||
}
|
||||
set {
|
||||
defTexturePack = value;
|
||||
|
@ -202,13 +202,14 @@ namespace ClassicalSharp {
|
||||
}
|
||||
|
||||
void TakeScreenshot() {
|
||||
string path = PathIO.Combine(Program.AppDirectory, "screenshots");
|
||||
if (!Directory.Exists(path))
|
||||
Directory.CreateDirectory(path);
|
||||
if (!Platform.DirectoryExists("screenshots")) {
|
||||
Platform.DirectoryCreate("screenshots");
|
||||
}
|
||||
|
||||
string timestamp = DateTime.Now.ToString("dd-MM-yyyy-HH-mm-ss");
|
||||
string file = "screenshot_" + timestamp + ".png";
|
||||
path = PathIO.Combine(path, file);
|
||||
string path = PathIO.Combine("screenshots", file);
|
||||
|
||||
Graphics.TakeScreenshot(path, Width, Height);
|
||||
Chat.Add("&eTaken screenshot as: " + file);
|
||||
screenshotRequested = false;
|
||||
|
@ -21,20 +21,20 @@ namespace ClassicalSharp {
|
||||
internal static Game game;
|
||||
|
||||
internal static List<string> LoadAll() {
|
||||
string dir = Path.Combine(Program.AppDirectory, "plugins");
|
||||
if (!Directory.Exists(dir))
|
||||
Directory.CreateDirectory(dir);
|
||||
if (!Platform.DirectoryExists("plugins")) {
|
||||
Platform.DirectoryCreate("plugins");
|
||||
}
|
||||
|
||||
Accepted = new EntryList("plugins", "accepted.txt");
|
||||
Denied = new EntryList("plugins", "denied.txt");
|
||||
Accepted.Load();
|
||||
Denied.Load();
|
||||
|
||||
return LoadPlugins(dir);
|
||||
return LoadPlugins();
|
||||
}
|
||||
|
||||
static List<string> LoadPlugins(string dir) {
|
||||
string[] dlls = Directory.GetFiles(dir, "*.dll");
|
||||
static List<string> LoadPlugins() {
|
||||
string[] dlls = Platform.DirectoryFiles("plugins", "*.dll");
|
||||
List<string> nonLoaded = null;
|
||||
|
||||
for (int i = 0; i < dlls.Length; i++) {
|
||||
@ -55,8 +55,7 @@ namespace ClassicalSharp {
|
||||
|
||||
public static void Load(string pluginName, bool needsInit) {
|
||||
try {
|
||||
string dir = Path.Combine(Program.AppDirectory, "plugins");
|
||||
string path = Path.Combine(dir, pluginName + ".dll");
|
||||
string path = Path.Combine("plguins", pluginName + ".dll");
|
||||
Assembly lib = Assembly.LoadFrom(path);
|
||||
Type[] types = lib.GetTypes();
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using OpenTK;
|
||||
@ -172,7 +173,7 @@ namespace ClassicalSharp.GraphicsAPI {
|
||||
|
||||
if (managedPool) {
|
||||
texture = device.CreateTexture(width, height, levels, Usage.None, Format.A8R8G8B8, Pool.Managed);
|
||||
texture.SetData(0, LockFlags.None, scan0, width * height * 4);
|
||||
texture.SetData(0, LockFlags.None, scan0, width * height * 4);
|
||||
if (mipmaps) DoMipmaps(texture, 0, 0, width, height, scan0, false);
|
||||
} else {
|
||||
D3D.Texture sys = device.CreateTexture(width, height, levels, Usage.None, Format.A8R8G8B8, Pool.SystemMemory);
|
||||
@ -180,19 +181,19 @@ namespace ClassicalSharp.GraphicsAPI {
|
||||
if (mipmaps) DoMipmaps(sys, 0, 0, width, height, scan0, false);
|
||||
|
||||
texture = device.CreateTexture(width, height, levels, Usage.None, Format.A8R8G8B8, Pool.Default);
|
||||
device.UpdateTexture(sys, texture);
|
||||
device.UpdateTexture(sys, texture);
|
||||
sys.Dispose();
|
||||
}
|
||||
return GetOrExpand(ref textures, texture, texBufferSize);
|
||||
}
|
||||
|
||||
unsafe void DoMipmaps(D3D.Texture texture, int x, int y, int width,
|
||||
|
||||
unsafe void DoMipmaps(D3D.Texture texture, int x, int y, int width,
|
||||
int height, IntPtr scan0, bool partial) {
|
||||
IntPtr prev = scan0;
|
||||
int lvls = MipmapsLevels(width, height);
|
||||
|
||||
for (int lvl = 1; lvl <= lvls; lvl++) {
|
||||
x /= 2; y /= 2;
|
||||
x /= 2; y /= 2;
|
||||
if (width > 1) width /= 2;
|
||||
if (height > 1) height /= 2;
|
||||
int size = width * height * 4;
|
||||
@ -295,7 +296,7 @@ namespace ClassicalSharp.GraphicsAPI {
|
||||
|
||||
public override int CreateVb(IntPtr vertices, VertexFormat format, int count) {
|
||||
int size = count * strideSizes[(int)format];
|
||||
DataBuffer buffer = device.CreateVertexBuffer(size, Usage.WriteOnly,
|
||||
DataBuffer buffer = device.CreateVertexBuffer(size, Usage.WriteOnly,
|
||||
formatMapping[(int)format], Pool.Default);
|
||||
buffer.SetData(vertices, size, LockFlags.None);
|
||||
return GetOrExpand(ref vBuffers, buffer, vBufferSize);
|
||||
@ -553,9 +554,10 @@ namespace ClassicalSharp.GraphicsAPI {
|
||||
device.GetRenderTargetData(backbuffer, tempSurface);
|
||||
LockedRectangle rect = tempSurface.LockRectangle(LockFlags.ReadOnly | LockFlags.NoDirtyUpdate);
|
||||
|
||||
using (Bitmap bmp = new Bitmap(width, height, width * sizeof(int),
|
||||
PixelFormat.Format32bppRgb, rect.DataPointer)) {
|
||||
bmp.Save(output, ImageFormat.Png);
|
||||
using (Bitmap bmp = new Bitmap(width, height, width * sizeof(int), PixelFormat.Format32bppRgb, rect.DataPointer)) {
|
||||
using (Stream fs = Platform.FileCreate(output)) {
|
||||
Platform.WriteBmp(bmp, fs);
|
||||
}
|
||||
}
|
||||
tempSurface.UnlockRectangle();
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics.OpenGL;
|
||||
@ -551,7 +552,10 @@ namespace ClassicalSharp.GraphicsAPI {
|
||||
using (FastBitmap fastBmp = new FastBitmap(bmp, true, false))
|
||||
GL.ReadPixels(0, 0, width, height, GlPixelFormat.Bgra, PixelType.UnsignedByte, fastBmp.Scan0);
|
||||
bmp.RotateFlip(RotateFlipType.RotateNoneFlipY);
|
||||
bmp.Save(output, ImageFormat.Png);
|
||||
|
||||
using (Stream fs = Platform.FileCreate(output)) {
|
||||
Platform.WriteBmp(bmp, fs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -342,8 +342,9 @@ namespace ClassicalSharp.GraphicsAPI {
|
||||
}
|
||||
}
|
||||
}
|
||||
using (FileStream fs = File.Create(output))
|
||||
using (Stream fs = Platform.FileCreate(output)) {
|
||||
Platform.WriteBmp(bmp, fs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,12 +74,12 @@ namespace ClassicalSharp {
|
||||
|
||||
internal void DownloadTexturePack(string url) {
|
||||
if (game.DeniedUrls.Has(url)) return;
|
||||
string path = TextureCache.MakePath(url), etag = null;
|
||||
string etag = null;
|
||||
DateTime lastModified = DateTime.MinValue;
|
||||
|
||||
if (File.Exists(path)) {
|
||||
lastModified = TextureCache.GetLastModified(url, path, game.LastModified);
|
||||
etag = TextureCache.GetETag(url, path, game.ETags);
|
||||
if (TextureCache.HasUrl(url)) {
|
||||
lastModified = TextureCache.GetLastModified(url, game.LastModified);
|
||||
etag = TextureCache.GetETag(url, game.ETags);
|
||||
}
|
||||
|
||||
TexturePack.ExtractCurrent(game, url);
|
||||
|
@ -41,13 +41,14 @@ namespace ClassicalSharp {
|
||||
}
|
||||
|
||||
public void LoadIcon() {
|
||||
string launcherPath = Path.Combine(Program.AppDirectory, "Launcher2.exe");
|
||||
if (!File.Exists(launcherPath)) {
|
||||
launcherPath = Path.Combine(Program.AppDirectory, "Launcher.exe");
|
||||
string launcherFile = "Launcher2.exe";
|
||||
if (!Platform.FileExists(launcherFile)) {
|
||||
launcherFile = "Launcher.exe";
|
||||
}
|
||||
if (!File.Exists(launcherPath)) return;
|
||||
if (!Platform.FileExists(launcherFile)) return;
|
||||
|
||||
try {
|
||||
string launcherPath = Path.Combine(Platform.AppDirectory, launcherFile);
|
||||
Icon = Icon.ExtractAssociatedIcon(launcherPath);
|
||||
} catch (Exception ex) {
|
||||
ErrorHandler.LogError("DesktopWindow.LoadIcon()", ex);
|
||||
|
@ -13,6 +13,8 @@ namespace ClassicalSharp {
|
||||
/// <summary> Abstracts away platform specific operations. </summary>
|
||||
public static class Platform {
|
||||
|
||||
public static string AppDirectory;
|
||||
|
||||
public static bool ValidBitmap(Bitmap bmp) {
|
||||
// Mono seems to be returning a bitmap with a native pointer of zero in some weird cases.
|
||||
// We can detect this as property access raises an ArgumentException.
|
||||
@ -70,5 +72,65 @@ namespace ClassicalSharp {
|
||||
return config != null && config == Bitmap.Config.Argb8888;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static FileStream FileOpen(string relPath) {
|
||||
string path = Path.Combine(AppDirectory, relPath);
|
||||
return new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
}
|
||||
|
||||
public static FileStream FileCreate(string relPath) {
|
||||
string path = Path.Combine(AppDirectory, relPath);
|
||||
return new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read);
|
||||
}
|
||||
|
||||
public static FileStream FileAppend(string relPath) {
|
||||
string path = Path.Combine(AppDirectory, relPath);
|
||||
return new FileStream(path, FileMode.Append, FileAccess.Write, FileShare.Read);
|
||||
}
|
||||
|
||||
public static bool FileExists(string relPath) {
|
||||
string path = Path.Combine(AppDirectory, relPath);
|
||||
return File.Exists(path);
|
||||
}
|
||||
|
||||
public static DateTime FileGetWriteTime(string relPath) {
|
||||
string path = Path.Combine(AppDirectory, relPath);
|
||||
return File.GetLastWriteTimeUtc(path);
|
||||
}
|
||||
|
||||
public static void FileSetWriteTime(string relPath, DateTime time) {
|
||||
string path = Path.Combine(AppDirectory, relPath);
|
||||
File.SetLastWriteTimeUtc(path, time);
|
||||
}
|
||||
|
||||
public static bool DirectoryExists(string relPath) {
|
||||
string path = Path.Combine(AppDirectory, relPath);
|
||||
return Directory.Exists(path);
|
||||
}
|
||||
|
||||
public static void DirectoryCreate(string relPath) {
|
||||
string path = Path.Combine(AppDirectory, relPath);
|
||||
Directory.CreateDirectory(path);
|
||||
}
|
||||
|
||||
public static string[] DirectoryFiles(string relPath) {
|
||||
string path = Path.Combine(AppDirectory, relPath);
|
||||
return Directory.GetFiles(relPath);
|
||||
}
|
||||
|
||||
public static string[] DirectoryFiles(string relPath, string filter) {
|
||||
string path = Path.Combine(AppDirectory, relPath);
|
||||
return Directory.GetFiles(relPath, filter);
|
||||
}
|
||||
|
||||
public static void WriteAllText(string relPath, string text) {
|
||||
string path = Path.Combine(AppDirectory, relPath);
|
||||
File.WriteAllText(path, text);
|
||||
}
|
||||
|
||||
public static void WriteAllBytes(string relPath, byte[] data) {
|
||||
string path = Path.Combine(AppDirectory, relPath);
|
||||
File.WriteAllBytes(path, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Windows.Forms;
|
||||
using ClassicalSharp.Textures;
|
||||
using OpenTK;
|
||||
|
||||
namespace ClassicalSharp {
|
||||
@ -12,21 +11,21 @@ namespace ClassicalSharp {
|
||||
|
||||
public const string AppName = "ClassicalSharp 0.99.9.94";
|
||||
|
||||
public static string AppDirectory;
|
||||
#if !LAUNCHER
|
||||
[STAThread]
|
||||
static void Main(string[] args) {
|
||||
AppDirectory = AppDomain.CurrentDomain.BaseDirectory;
|
||||
Platform.AppDirectory = AppDomain.CurrentDomain.BaseDirectory;
|
||||
CleanupMainDirectory();
|
||||
|
||||
string path = Path.Combine(Program.AppDirectory, "texpacks");
|
||||
if (!File.Exists(Path.Combine(path, "default.zip"))) {
|
||||
Message("default.zip not found, try running the launcher first."); return;
|
||||
string defPath = Path.Combine("texpacks", "default.zip");
|
||||
if (!Platform.FileExists(defPath)) {
|
||||
ErrorHandler.ShowDialog("Missing file", "default.zip not found, try running the launcher first.");
|
||||
return;
|
||||
}
|
||||
|
||||
path = Path.Combine(AppDirectory, "OpenTK.dll");
|
||||
if (!File.Exists(path)) {
|
||||
Message("OpenTK.dll needs to be in the same folder as the game"); return;
|
||||
if (!Platform.FileExists("OpenTK.dll")) {
|
||||
ErrorHandler.ShowDialog("Missing file", "OpenTK.dll needs to be in the same folder as the game");
|
||||
return;
|
||||
}
|
||||
|
||||
// NOTE: we purposely put this in another method, as we need to ensure
|
||||
@ -36,8 +35,7 @@ namespace ClassicalSharp {
|
||||
}
|
||||
|
||||
static void RunGame(string[] args) {
|
||||
string logPath = Path.Combine(AppDirectory, "client.log");
|
||||
ErrorHandler.InstallHandler(logPath);
|
||||
ErrorHandler.InstallHandler("client.log");
|
||||
OpenTK.Configuration.SkipPerfCountersHack();
|
||||
Utils.LogDebug("Starting " + AppName + "..");
|
||||
|
||||
@ -70,9 +68,6 @@ namespace ClassicalSharp {
|
||||
}
|
||||
}
|
||||
|
||||
// put in separate function, because we don't want to load winforms assembly if possible
|
||||
static void Message(string message) { MessageBox.Show(message, "Missing file"); }
|
||||
|
||||
static void RunMultiplayer(string[] args, bool nullContext, int width, int height) {
|
||||
IPAddress ip = null;
|
||||
if (!IPAddress.TryParse(args[2], out ip)) {
|
||||
@ -97,14 +92,14 @@ namespace ClassicalSharp {
|
||||
}
|
||||
#endif
|
||||
|
||||
internal static void CleanupMainDirectory() {
|
||||
string mapPath = Path.Combine(Program.AppDirectory, "maps");
|
||||
if (!Directory.Exists(mapPath))
|
||||
Directory.CreateDirectory(mapPath);
|
||||
|
||||
string texPath = Path.Combine(Program.AppDirectory, "texpacks");
|
||||
if (!Directory.Exists(texPath))
|
||||
Directory.CreateDirectory(texPath);
|
||||
public static void CleanupMainDirectory() {
|
||||
if (!Platform.DirectoryExists("maps")) {
|
||||
Platform.DirectoryCreate("maps");
|
||||
}
|
||||
|
||||
if (!Platform.DirectoryExists("texpacks")) {
|
||||
Platform.DirectoryCreate("texpacks");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -43,7 +43,7 @@ namespace ClassicalSharp.Textures {
|
||||
animsBuffer = new FastBitmap(animBmp, true, true);
|
||||
} else if (e.Name == "animations.txt" || e.Name == "animation.txt") {
|
||||
MemoryStream stream = new MemoryStream(e.Data);
|
||||
StreamReader reader = new StreamReader(stream);
|
||||
StreamReader reader = new StreamReader(stream, false);
|
||||
ReadAnimationsDescription(reader);
|
||||
} else if (e.Name == "uselavaanim") {
|
||||
useLavaAnim = true;
|
||||
|
@ -25,12 +25,11 @@ namespace ClassicalSharp.Textures {
|
||||
}
|
||||
|
||||
public bool Load() {
|
||||
string path = Path.Combine(Program.AppDirectory, folder);
|
||||
path = Path.Combine(path, file);
|
||||
if (!File.Exists(path)) return true;
|
||||
string path = Path.Combine(folder, file);
|
||||
if (!Platform.FileExists(path)) return true;
|
||||
|
||||
try {
|
||||
using (Stream fs = File.OpenRead(path))
|
||||
using (Stream fs = Platform.FileOpen(path))
|
||||
using (StreamReader reader = new StreamReader(fs, false))
|
||||
{
|
||||
string line;
|
||||
@ -48,12 +47,13 @@ namespace ClassicalSharp.Textures {
|
||||
}
|
||||
|
||||
public bool Save() {
|
||||
try {
|
||||
string path = Path.Combine(Program.AppDirectory, folder);
|
||||
if (!Directory.Exists(path))
|
||||
Directory.CreateDirectory(path);
|
||||
try {
|
||||
if (!Platform.DirectoryExists(folder)) {
|
||||
Platform.DirectoryCreate(folder);
|
||||
}
|
||||
|
||||
using (Stream fs = File.Create(Path.Combine(path, file)))
|
||||
string path = Path.Combine(folder, file);
|
||||
using (Stream fs = Platform.FileCreate(path))
|
||||
using (StreamWriter writer = new StreamWriter(fs))
|
||||
{
|
||||
for (int i = 0; i < Entries.Count; i++)
|
||||
|
@ -14,18 +14,16 @@ namespace ClassicalSharp.Textures {
|
||||
public static class TextureCache {
|
||||
|
||||
/// <summary> Gets whether the given url has data associated with it in the cache. </summary>
|
||||
public static bool HasUrl(string url) {
|
||||
return File.Exists(MakePath(url));
|
||||
}
|
||||
public static bool HasUrl(string url) { return Platform.FileExists(MakePath(url)); }
|
||||
|
||||
/// <summary> Gets the stream of data associated with the url from the cache, returning null if the
|
||||
/// data for the url was not found in the cache. </summary>
|
||||
public static FileStream GetStream(string url) {
|
||||
string path = MakePath(url);
|
||||
if (!File.Exists(path)) return null;
|
||||
if (!Platform.FileExists(path)) return null;
|
||||
|
||||
try {
|
||||
return File.OpenRead(path);
|
||||
return Platform.FileOpen(path);
|
||||
} catch (IOException ex) {
|
||||
ErrorHandler.LogError("Cache.GetData", ex);
|
||||
return null;
|
||||
@ -34,17 +32,18 @@ namespace ClassicalSharp.Textures {
|
||||
|
||||
/// <summary> Gets the time the data associated with the url from the cache was last modified,
|
||||
/// returning DateTime.MinValue if data for the url was not found in the cache. </summary>
|
||||
public static DateTime GetLastModified(string url, string path, EntryList tags) {
|
||||
public static DateTime GetLastModified(string url, EntryList tags) {
|
||||
string entry = GetFromTags(url, tags);
|
||||
long ticks = 0;
|
||||
if (entry != null && long.TryParse(entry, out ticks)) {
|
||||
return new DateTime(ticks, DateTimeKind.Utc);
|
||||
} else {
|
||||
return File.GetLastWriteTimeUtc(path);
|
||||
string path = MakePath(url);
|
||||
return Platform.FileGetWriteTime(path);
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetETag(string url, string path, EntryList tags) {
|
||||
public static string GetETag(string url, EntryList tags) {
|
||||
return GetFromTags(url, tags);
|
||||
}
|
||||
|
||||
@ -67,12 +66,13 @@ namespace ClassicalSharp.Textures {
|
||||
public static void Add(string url, Bitmap bmp) {
|
||||
string path = MakePath(url);
|
||||
try {
|
||||
string basePath = PathIO.Combine(Program.AppDirectory, Folder);
|
||||
if (!Directory.Exists(basePath))
|
||||
Directory.CreateDirectory(basePath);
|
||||
if (!Platform.DirectoryExists(Folder)) {
|
||||
Platform.DirectoryCreate(Folder);
|
||||
}
|
||||
|
||||
using (FileStream fs = File.Create(path))
|
||||
using (Stream fs = Platform.FileCreate(path)) {
|
||||
Platform.WriteBmp(bmp, fs);
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
ErrorHandler.LogError("Cache.AddToCache", ex);
|
||||
}
|
||||
@ -82,10 +82,11 @@ namespace ClassicalSharp.Textures {
|
||||
public static void Add(string url, byte[] data) {
|
||||
string path = MakePath(url);
|
||||
try {
|
||||
string basePath = PathIO.Combine(Program.AppDirectory, Folder);
|
||||
if (!Directory.Exists(basePath))
|
||||
Directory.CreateDirectory(basePath);
|
||||
File.WriteAllBytes(path, data);
|
||||
if (!Platform.DirectoryExists(Folder)) {
|
||||
Platform.DirectoryCreate(Folder);
|
||||
}
|
||||
|
||||
Platform.WriteAllBytes(path, data);
|
||||
} catch (IOException ex) {
|
||||
ErrorHandler.LogError("Cache.AddToCache", ex);
|
||||
}
|
||||
@ -113,13 +114,8 @@ namespace ClassicalSharp.Textures {
|
||||
}
|
||||
|
||||
|
||||
const string Folder = "texturecache";
|
||||
|
||||
public static string MakePath(string url) {
|
||||
string crc32 = CRC32(url);
|
||||
string basePath = PathIO.Combine(Program.AppDirectory, Folder);
|
||||
return PathIO.Combine(basePath, crc32);
|
||||
}
|
||||
const string Folder = "texturecache";
|
||||
public static string MakePath(string url) { return PathIO.Combine(Folder, CRC32(url)); }
|
||||
|
||||
static string CRC32(string url) {
|
||||
byte[] data = Encoding.UTF8.GetBytes(url);
|
||||
|
@ -17,11 +17,11 @@ namespace ClassicalSharp.Textures {
|
||||
|
||||
Game game;
|
||||
|
||||
public void Extract(string path, Game game) {
|
||||
path = PathIO.Combine("texpacks", path);
|
||||
path = PathIO.Combine(Program.AppDirectory, path);
|
||||
using (Stream fs = File.OpenRead(path))
|
||||
public void Extract(string file, Game game) {
|
||||
string path = PathIO.Combine("texpacks", file);
|
||||
using (Stream fs = Platform.FileOpen(path)) {
|
||||
Extract(fs, game);
|
||||
}
|
||||
}
|
||||
|
||||
public void Extract(Stream stream, Game game) {
|
||||
|
@ -11,14 +11,12 @@ namespace ClassicalSharp {
|
||||
/// and also logs it to a specified log file. </summary>
|
||||
public static class ErrorHandler {
|
||||
|
||||
static string logFile = "crash.log";
|
||||
static string fileName = "crash.log";
|
||||
|
||||
/// <summary> Adds a handler for when a unhandled exception occurs, unless
|
||||
/// a debugger is attached to the process in which case this does nothing. </summary>
|
||||
public static void InstallHandler(string logFile) {
|
||||
ErrorHandler.logFile = logFile;
|
||||
fileName = Path.GetFileName(logFile);
|
||||
fileName = logFile;
|
||||
if (!Debugger.IsAttached)
|
||||
AppDomain.CurrentDomain.UnhandledException += UnhandledException;
|
||||
}
|
||||
@ -40,7 +38,9 @@ namespace ClassicalSharp {
|
||||
Exception ex = (Exception)e.ExceptionObject;
|
||||
bool wroteToCrashLog = true;
|
||||
try {
|
||||
using (StreamWriter w = new StreamWriter(logFile, true)) {
|
||||
using (Stream fs = Platform.FileAppend(fileName))
|
||||
using (StreamWriter w = new StreamWriter(fs))
|
||||
{
|
||||
w.WriteLine("=== crash occurred ===");
|
||||
w.WriteLine("Time: " + DateTime.Now);
|
||||
|
||||
@ -72,12 +72,12 @@ namespace ClassicalSharp {
|
||||
|
||||
string line1 = "ClassicalSharp crashed.";
|
||||
if (wroteToCrashLog) {
|
||||
line1 += " The cause has also been logged to \"" + fileName + "\" in " + Program.AppDirectory;
|
||||
line1 += " The cause has also been logged to \"" + fileName + "\" in " + Platform.AppDirectory;
|
||||
}
|
||||
string line2 = "Please report the crash to github.com/UnknownShadow200/ClassicalSharp/issues so we can fix it.";
|
||||
line2 += Environment.NewLine + Environment.NewLine + Format(ex);
|
||||
|
||||
MessageBox.Show(line1 + Environment.NewLine + Environment.NewLine + line2, "We're sorry");
|
||||
ShowDialog("We're sorry", line1 + Environment.NewLine + Environment.NewLine + line2);
|
||||
Environment.Exit(1);
|
||||
}
|
||||
|
||||
@ -93,16 +93,23 @@ namespace ClassicalSharp {
|
||||
/// <summary> Logs an error that occured at the specified location to the log file. </summary>
|
||||
public static bool LogError(string location, string text) {
|
||||
try {
|
||||
using (StreamWriter writer = new StreamWriter(logFile, true)) {
|
||||
writer.WriteLine("=== handled error ===");
|
||||
writer.WriteLine("Occured when: " + location);
|
||||
writer.WriteLine(text);
|
||||
writer.WriteLine();
|
||||
using (Stream fs = Platform.FileAppend(fileName))
|
||||
using (StreamWriter w = new StreamWriter(fs))
|
||||
{
|
||||
w.WriteLine("=== handled error ===");
|
||||
w.WriteLine("Occured when: " + location);
|
||||
w.WriteLine(text);
|
||||
w.WriteLine();
|
||||
}
|
||||
} catch (Exception) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// put in separate function, because we don't want to load winforms assembly if possible
|
||||
public static void ShowDialog(string title, string msg) {
|
||||
MessageBox.Show(msg, title);
|
||||
}
|
||||
}
|
||||
}
|
@ -190,14 +190,8 @@ namespace ClassicalSharp {
|
||||
|
||||
|
||||
public static bool Load() {
|
||||
// Both of these are from when running from the launcher
|
||||
if (Program.AppDirectory == null)
|
||||
Program.AppDirectory = AppDomain.CurrentDomain.BaseDirectory;
|
||||
Program.CleanupMainDirectory();
|
||||
|
||||
try {
|
||||
string path = Path.Combine(Program.AppDirectory, Filename);
|
||||
using (Stream fs = File.OpenRead(path))
|
||||
using (Stream fs = Platform.FileOpen(Filename))
|
||||
using (StreamReader reader = new StreamReader(fs, false))
|
||||
{
|
||||
LoadFrom(reader);
|
||||
@ -239,8 +233,7 @@ namespace ClassicalSharp {
|
||||
|
||||
public static bool Save() {
|
||||
try {
|
||||
string path = Path.Combine(Program.AppDirectory, Filename);
|
||||
using (Stream fs = File.Create(path))
|
||||
using (Stream fs = Platform.FileCreate(Filename))
|
||||
using (StreamWriter writer = new StreamWriter(fs))
|
||||
{
|
||||
SaveTo(writer);
|
||||
|
@ -1,6 +1,6 @@
|
||||
// ClassicalSharp copyright 2014-2016 UnknownShadow200 | Licensed under MIT
|
||||
using System;
|
||||
using System.IO;
|
||||
using ClassicalSharp;
|
||||
using ClassicalSharp.Network;
|
||||
using Launcher.Gui.Views;
|
||||
using Launcher.Patcher;
|
||||
@ -90,7 +90,7 @@ namespace Launcher.Gui.Screens {
|
||||
|
||||
void GotoNextMenu(int x, int y) {
|
||||
game.Downloader.Clear();
|
||||
if (File.Exists("options.txt")) {
|
||||
if (Platform.FileExists("options.txt")) {
|
||||
game.SetScreen(new MainScreen(game));
|
||||
} else {
|
||||
game.SetScreen(new ChooseModeScreen(game, true));
|
||||
|
@ -39,11 +39,11 @@ namespace Launcher.Gui.Views {
|
||||
const string dateFormat = "dd-MM-yyyy HH:mm";
|
||||
protected override void MakeWidgets() {
|
||||
widgetIndex = 0;
|
||||
string exePath = Path.Combine(Program.AppDirectory, "ClassicalSharp.exe");
|
||||
DateTime writeTime = Platform.FileGetWriteTime("ClassicalSharp.exe");
|
||||
|
||||
Makers.Label(this, "Your build:", textFont)
|
||||
.SetLocation(Anchor.Centre, Anchor.Centre, -55, -120);
|
||||
string yourBuild = File.GetLastWriteTime(exePath).ToString(dateFormat);
|
||||
string yourBuild = writeTime.ToLocalTime().ToString(dateFormat);
|
||||
Makers.Label(this, yourBuild, textFont)
|
||||
.SetLocation(Anchor.Centre, Anchor.Centre, 70, -120);
|
||||
|
||||
|
@ -17,28 +17,31 @@ namespace Launcher {
|
||||
fontPng = false; terrainPng = false;
|
||||
Options.Load();
|
||||
LauncherSkin.LoadFromOptions();
|
||||
if (Options.Get("nostalgia-classicbg") != null)
|
||||
|
||||
if (Options.Get("nostalgia-classicbg") != null) {
|
||||
ClassicBackground = Options.GetBool("nostalgia-classicbg", false);
|
||||
else
|
||||
} else {
|
||||
ClassicBackground = Options.GetBool("mode-classic", false);
|
||||
}
|
||||
|
||||
string texDir = Path.Combine(Program.AppDirectory, "texpacks");
|
||||
string texPack = Options.Get(OptionsKey.DefaultTexturePack) ?? "default.zip";
|
||||
texPack = Path.Combine(texDir, texPack);
|
||||
string texPath = Path.Combine("texpacks", texPack);
|
||||
|
||||
if (!File.Exists(texPack))
|
||||
texPack = Path.Combine(texDir, "default.zip");
|
||||
if (!File.Exists(texPack)) return;
|
||||
if (!Platform.FileExists(texPath)) {
|
||||
texPath = Path.Combine("texpacks", "default.zip");
|
||||
}
|
||||
if (!Platform.FileExists(texPath)) return;
|
||||
|
||||
ExtractTexturePack(texPack);
|
||||
ExtractTexturePack(texPath);
|
||||
// user selected texture pack is missing some required .png files
|
||||
if (!fontPng || !terrainPng) {
|
||||
texPack = Path.Combine(texDir, "default.zip");
|
||||
ExtractTexturePack(texPack);
|
||||
texPath = Path.Combine("texpacks", "default.zip");
|
||||
ExtractTexturePack(texPath);
|
||||
}
|
||||
}
|
||||
|
||||
void ExtractTexturePack(string texPack) {
|
||||
using (Stream fs = new FileStream(texPack, FileMode.Open, FileAccess.Read, FileShare.Read)) {
|
||||
void ExtractTexturePack(string relPath) {
|
||||
using (Stream fs = Platform.FileOpen(relPath)) {
|
||||
ZipReader reader = new ZipReader();
|
||||
reader.SelectZipEntry = SelectZipEntry;
|
||||
reader.ProcessZipEntry = ProcessZipEntry;
|
||||
|
@ -74,6 +74,8 @@ namespace Launcher {
|
||||
Window.FocusedChanged += FocusedChanged;
|
||||
Window.WindowStateChanged += Resize;
|
||||
Window.Keyboard.KeyDown += KeyDown;
|
||||
|
||||
ClassicalSharp.Program.CleanupMainDirectory();
|
||||
LoadFont();
|
||||
logoFont = new Font(FontName, 32, FontStyle.Regular);
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
// ClassicalSharp copyright 2014-2016 UnknownShadow200 | Licensed under MIT
|
||||
using System;
|
||||
using System.IO;
|
||||
using ClassicalSharp;
|
||||
using ClassicalSharp.Textures;
|
||||
|
||||
namespace Launcher.Patcher {
|
||||
@ -8,21 +9,21 @@ namespace Launcher.Patcher {
|
||||
public sealed class ResourceChecker {
|
||||
|
||||
public void CheckResourceExistence() {
|
||||
string audioPath = Path.Combine(Program.AppDirectory, "audio");
|
||||
if (!Directory.Exists(audioPath))
|
||||
Directory.CreateDirectory(audioPath);
|
||||
if (!Platform.DirectoryExists("audio")) {
|
||||
Platform.DirectoryCreate("audio");
|
||||
}
|
||||
|
||||
DigSoundsExist = CheckDigSoundsExist();
|
||||
StepSoundsExist = CheckStepSoundsExist();
|
||||
AllResourcesExist = DigSoundsExist && StepSoundsExist;
|
||||
|
||||
string texDir = Path.Combine(Program.AppDirectory, "texpacks");
|
||||
string zipPath = Path.Combine(texDir, "default.zip");
|
||||
bool defaultZipExists = File.Exists(zipPath);
|
||||
if (File.Exists(zipPath))
|
||||
CheckDefaultZip(zipPath);
|
||||
string defPath = Path.Combine("texpacks", "default.zip");
|
||||
if (Platform.FileExists(defPath)) {
|
||||
CheckDefaultZip(defPath);
|
||||
}
|
||||
|
||||
CheckTexturePack();
|
||||
CheckMusic(audioPath);
|
||||
CheckMusic();
|
||||
CheckSounds();
|
||||
}
|
||||
|
||||
@ -44,11 +45,11 @@ namespace Launcher.Patcher {
|
||||
}
|
||||
}
|
||||
|
||||
void CheckMusic(string audioPath) {
|
||||
void CheckMusic() {
|
||||
string[] files = ResourceList.MusicFiles;
|
||||
for (int i = 0; i < files.Length; i++) {
|
||||
string file = Path.Combine(audioPath, files[i]);
|
||||
musicExists[i] = File.Exists(file);
|
||||
string path = Path.Combine("audio", files[i]);
|
||||
musicExists[i] = Platform.FileExists(path);
|
||||
if (musicExists[i]) continue;
|
||||
|
||||
DownloadSize += musicSizes[i] / 1024f;
|
||||
@ -73,13 +74,14 @@ namespace Launcher.Patcher {
|
||||
public int ResourcesCount;
|
||||
internal bool[] musicExists = new bool[7];
|
||||
|
||||
void CheckDefaultZip(string path) {
|
||||
void CheckDefaultZip(string relPath) {
|
||||
ZipReader reader = new ZipReader();
|
||||
reader.SelectZipEntry = SelectZipEntry;
|
||||
reader.ProcessZipEntry = ProcessZipEntry;
|
||||
|
||||
using (Stream src = new FileStream(path, FileMode.Open, FileAccess.Read))
|
||||
using (Stream src = Platform.FileOpen(relPath)) {
|
||||
reader.Extract(src);
|
||||
}
|
||||
}
|
||||
|
||||
bool SelectZipEntry(string filename) {
|
||||
@ -98,20 +100,18 @@ namespace Launcher.Patcher {
|
||||
|
||||
bool CheckDigSoundsExist() {
|
||||
string[] files = ResourceList.DigSounds;
|
||||
string path = Path.Combine(Program.AppDirectory, "audio");
|
||||
for (int i = 0; i < files.Length; i++) {
|
||||
string file = "dig_" + files[i] + ".wav";
|
||||
if (!File.Exists(Path.Combine(path, file))) return false;
|
||||
string path = Path.Combine("audio", "dig_" + files[i] + ".wav");
|
||||
if (!Platform.FileExists(path)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CheckStepSoundsExist() {
|
||||
string[] files = ResourceList.StepSounds;
|
||||
string path = Path.Combine(Program.AppDirectory, "audio");
|
||||
for (int i = 0; i < files.Length; i++) {
|
||||
string file = "step_" + files[i] + ".wav";
|
||||
if (!File.Exists(Path.Combine(path, file))) return false;
|
||||
string path = Path.Combine("audio", "step_" + files[i] + ".wav");
|
||||
if (!Platform.FileExists(path)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -128,9 +128,8 @@ namespace Launcher.Patcher {
|
||||
return false;
|
||||
|
||||
if (data == null) continue;
|
||||
string path = Path.Combine(Program.AppDirectory, "audio");
|
||||
path = Path.Combine(path, file);
|
||||
File.WriteAllBytes(path, data);
|
||||
string path = Path.Combine("audio", file);
|
||||
Platform.WriteAllBytes(path, data);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -32,11 +32,16 @@ namespace Launcher.Patcher {
|
||||
reader = new ZipReader();
|
||||
reader.SelectZipEntry = SelectZipEntry_Classic;
|
||||
reader.ProcessZipEntry = ProcessZipEntry_Classic;
|
||||
string texDir = Path.Combine(Program.AppDirectory, "texpacks");
|
||||
string path = Path.Combine(texDir, "default.zip");
|
||||
ExtractExisting(path);
|
||||
string defPath = Path.Combine("texpacks", "default.zip");
|
||||
|
||||
using (Stream dst = new FileStream(path, FileMode.Create, FileAccess.Write)) {
|
||||
if (Platform.FileExists(defPath)) {
|
||||
using (Stream src = Platform.FileOpen(defPath)) {
|
||||
reader.ProcessZipEntry = ExtractExisting;
|
||||
reader.Extract(src);
|
||||
}
|
||||
}
|
||||
|
||||
using (Stream dst = Platform.FileCreate(defPath)) {
|
||||
writer = new ZipWriter(dst);
|
||||
writer.entries = new ZipEntry[100];
|
||||
for (int i = 0; i < entries.Count; i++)
|
||||
@ -60,14 +65,6 @@ namespace Launcher.Patcher {
|
||||
|
||||
List<ZipEntry> entries = new List<ZipEntry>();
|
||||
List<byte[]> datas = new List<byte[]>();
|
||||
void ExtractExisting(string path) {
|
||||
if (!File.Exists(path)) return;
|
||||
|
||||
using (Stream src = new FileStream(path, FileMode.Open, FileAccess.Read)) {
|
||||
reader.ProcessZipEntry = ExtractExisting;
|
||||
reader.Extract(src);
|
||||
}
|
||||
}
|
||||
|
||||
void ExtractExisting(string filename, byte[] data, ZipEntry entry) {
|
||||
filename = ResourceList.GetFile(filename);
|
||||
@ -114,7 +111,7 @@ namespace Launcher.Patcher {
|
||||
|
||||
CopyTile( 0, 16, 5 * 16, 3 * 16, mask, terrainBmp);
|
||||
CopyTile(16, 16, 6 * 16, 5 * 16, mask, terrainBmp);
|
||||
CopyTile(32, 16, 11 * 16, 0 * 16, mask, terrainBmp);
|
||||
CopyTile(32, 16, 11 * 16, 0 * 16, mask, terrainBmp);
|
||||
patchedTerrain = true;
|
||||
}
|
||||
}
|
||||
|
@ -57,10 +57,9 @@ namespace Launcher.Patcher {
|
||||
}
|
||||
|
||||
void DecodeSound(string name, byte[] rawData) {
|
||||
string path = Path.Combine(Program.AppDirectory, "audio");
|
||||
path = Path.Combine(path, prefix + name + ".wav");
|
||||
string path = Path.Combine("audio", prefix + name + ".wav");
|
||||
|
||||
using (FileStream dst = File.Create(path))
|
||||
using (FileStream dst = Platform.FileCreate(path))
|
||||
using (MemoryStream src = new MemoryStream(rawData))
|
||||
{
|
||||
dst.SetLength(44);
|
||||
|
@ -10,22 +10,20 @@ namespace Launcher {
|
||||
|
||||
public const string AppName = "ClassicalSharp Launcher 0.99.9.94";
|
||||
|
||||
public static string AppDirectory;
|
||||
|
||||
public static bool ShowingErrorDialog = false;
|
||||
|
||||
[STAThread]
|
||||
static void Main(string[] args) {
|
||||
AppDirectory = AppDomain.CurrentDomain.BaseDirectory;
|
||||
|
||||
string path = Path.Combine(AppDirectory, "ClassicalSharp.exe");
|
||||
if (!File.Exists(path)) {
|
||||
Message("ClassicalSharp.exe needs to be in the same folder as the launcher."); return;
|
||||
Platform.AppDirectory = AppDomain.CurrentDomain.BaseDirectory;
|
||||
|
||||
if (!Platform.FileExists("ClassicalSharp.exe")) {
|
||||
ErrorHandler.ShowDialog("Missing file", "ClassicalSharp.exe needs to be in the same folder as the launcher.");
|
||||
return;
|
||||
}
|
||||
|
||||
path = Path.Combine(AppDirectory, "OpenTK.dll");
|
||||
if (!File.Exists(path)) {
|
||||
Message("OpenTK.dll needs to be in the same folder as the launcher."); return;
|
||||
|
||||
if (!Platform.FileExists("OpenTK.dll")) {
|
||||
ErrorHandler.ShowDialog("Missing file", "OpenTK.dll needs to be in the same folder as the launcher.");
|
||||
return;
|
||||
}
|
||||
|
||||
// NOTE: we purposely put this in another method, as we need to ensure
|
||||
@ -34,13 +32,9 @@ namespace Launcher {
|
||||
RunLauncher();
|
||||
}
|
||||
|
||||
// put in separate function, because we don't want to load winforms assembly if possible
|
||||
static void Message(string message) { MessageBox.Show(message, "Missing file"); }
|
||||
|
||||
static void RunLauncher() {
|
||||
string logPath = Path.Combine(AppDirectory, "launcher.log");
|
||||
AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionHandler;
|
||||
ErrorHandler.InstallHandler(logPath);
|
||||
ErrorHandler.InstallHandler("launcher.log");
|
||||
OpenTK.Configuration.SkipPerfCountersHack();
|
||||
LauncherWindow window = new LauncherWindow();
|
||||
window.Run();
|
||||
|
@ -27,16 +27,16 @@ namespace Launcher.Updater {
|
||||
ProcessStartInfo info = new ProcessStartInfo();
|
||||
info.CreateNoWindow = false;
|
||||
info.UseShellExecute = true;
|
||||
info.WorkingDirectory = Program.AppDirectory;
|
||||
info.WorkingDirectory = Platform.AppDirectory;
|
||||
|
||||
if (OpenTK.Configuration.RunningOnWindows) {
|
||||
string path = Path.Combine(Program.AppDirectory, "update.bat");
|
||||
File.WriteAllText(path, Scripts.BatchFile);
|
||||
Platform.WriteAllText("update.bat", Scripts.BatchFile);
|
||||
info.FileName = "cmd"; info.Arguments = "/C start cmd /C update.bat";
|
||||
Process.Start(info);
|
||||
} else {
|
||||
string path = Path.Combine(Program.AppDirectory, "update.sh");
|
||||
File.WriteAllText(path, Scripts.BashFile.Replace("\r\n", "\n"));
|
||||
string path = Path.Combine(Platform.AppDirectory, "update.sh");
|
||||
Platform.WriteAllText("update.sh", Scripts.BashFile.Replace("\r\n", "\n"));
|
||||
|
||||
const int flags = 0x7;// read | write | executable
|
||||
int code = chmod(path, (flags << 6) | (flags << 3) | 4);
|
||||
if (code != 0)
|
||||
@ -55,23 +55,20 @@ namespace Launcher.Updater {
|
||||
internal static extern int chmod(string path, int mode);
|
||||
|
||||
static void MakeUpdatesFolder(byte[] zipData) {
|
||||
Platform.DirectoryCreate("CS_Update");
|
||||
using (MemoryStream stream = new MemoryStream(zipData)) {
|
||||
ZipReader reader = new ZipReader();
|
||||
string path = Path.Combine(Program.AppDirectory, "CS_Update");
|
||||
Directory.CreateDirectory(path);
|
||||
|
||||
ZipReader reader = new ZipReader();
|
||||
reader.ProcessZipEntry = ProcessZipEntry;
|
||||
reader.Extract(stream);
|
||||
}
|
||||
}
|
||||
|
||||
static void ProcessZipEntry(string filename, byte[] data, ZipEntry entry) {
|
||||
string path = Path.Combine(Program.AppDirectory, "CS_Update");
|
||||
path = Path.Combine(path, Path.GetFileName(filename));
|
||||
File.WriteAllBytes(path, data);
|
||||
string path = Path.Combine("CS_Update", Path.GetFileName(filename));
|
||||
Platform.WriteAllBytes(path, data);
|
||||
|
||||
try {
|
||||
File.SetLastWriteTimeUtc(path, PatchTime);
|
||||
Platform.FileSetWriteTime(path, PatchTime);
|
||||
} catch (IOException ex) {
|
||||
ErrorHandler.LogError("I/O exception when trying to set modified time for: " + filename, ex);
|
||||
} catch (UnauthorizedAccessException ex) {
|
||||
|
@ -28,15 +28,12 @@ namespace Launcher {
|
||||
return StartImpl(null, true, args, ref shouldExit);
|
||||
}
|
||||
|
||||
static bool StartImpl(ClientStartData data, bool classicubeSkins,
|
||||
string args, ref bool shouldExit) {
|
||||
string path = Path.Combine(Program.AppDirectory, "ClassicalSharp.exe");
|
||||
if (!File.Exists(path))
|
||||
return false;
|
||||
static bool StartImpl(ClientStartData data, bool ccSkins, string args, ref bool shouldExit) {
|
||||
if (!Platform.FileExists("ClassicalSharp.exe")) return false;
|
||||
|
||||
CheckSettings(data, classicubeSkins, out shouldExit);
|
||||
CheckSettings(data, ccSkins, out shouldExit);
|
||||
try {
|
||||
StartProcess(path, args);
|
||||
StartProcess(args);
|
||||
} catch (Win32Exception ex) {
|
||||
if ((uint)ex.ErrorCode != 0x80004005)
|
||||
throw; // HRESULT when user clicks 'cancel' to 'are you sure you want to run ClassicalSharp.exe'
|
||||
@ -46,7 +43,8 @@ namespace Launcher {
|
||||
return true;
|
||||
}
|
||||
|
||||
static void StartProcess(string path, string args) {
|
||||
static void StartProcess(string args) {
|
||||
string path = Path.Combine(Platform.AppDirectory, "ClassicalSharp.exe");
|
||||
if (Configuration.RunningOnMono) {
|
||||
// We also need to handle the case of running Mono through wine
|
||||
if (Configuration.RunningOnWindows) {
|
||||
|
@ -80,7 +80,7 @@ void Chat_OpenLog(DateTime* now) {
|
||||
String_AppendConst(&path, ".log");
|
||||
|
||||
void* file;
|
||||
ReturnCode code = Platform_FileOpen(&file, &path, false);
|
||||
ReturnCode code = Platform_FileAppend(&file, &path);
|
||||
if (code != 0 && code != ReturnCode_FileShareViolation) {
|
||||
ErrorHandler_FailWithCode(code, "Chat - opening log file");
|
||||
}
|
||||
|
@ -13,4 +13,5 @@ void ErrorHandler_Log(STRING_PURE String* msg);
|
||||
void ErrorHandler_Fail(const UInt8* raw_msg);
|
||||
void ErrorHandler_FailWithCode(ReturnCode returnCode, const UInt8* raw_msg);
|
||||
#define ErrorHandler_CheckOrFail(returnCode, raw_msg) if (returnCode != 0) { ErrorHandler_FailWithCode(returnCode, raw_msg); }
|
||||
void ErrorHandler_ShowDialog(const UInt8* title, const UInt8* msg);
|
||||
#endif
|
@ -1275,7 +1275,7 @@ void LoadLevelScreen_EntryClick(GuiElement* screenElem, GuiElement* w) {
|
||||
if (!Platform_FileExists(&path)) return;
|
||||
|
||||
void* file;
|
||||
ReturnCode code = Platform_FileOpen(&file, &path, true);
|
||||
ReturnCode code = Platform_FileOpen(&file, &path);
|
||||
ErrorHandler_CheckOrFail(code, "Failed to open map file");
|
||||
Stream stream; Stream_FromFile(&stream, file, &path);
|
||||
|
||||
@ -1504,7 +1504,7 @@ void ClassicHacksKeyBindingsScreen_ContextRecreated(void* obj) {
|
||||
KeyBindingsScreen_MakeWidgets(screen, -90, -40, 3, "Hacks controls", 260);
|
||||
}
|
||||
|
||||
Screen* ClassicHackKeyBindingsScreen_MakeInstance(void) {
|
||||
Screen* ClassicHacksKeyBindingsScreen_MakeInstance(void) {
|
||||
static KeyBind binds[6] = { KeyBind_Speed, KeyBind_NoClip, KeyBind_HalfSpeed, KeyBind_Fly, KeyBind_FlyUp, KeyBind_FlyDown };
|
||||
static const UInt8* descs[6] = { "Speed", "Noclip", "Half speed", "Fly", "Fly up", "Fly down" };
|
||||
static ButtonWidget buttons[6];
|
||||
|
@ -141,7 +141,7 @@ void Options_Set(const UInt8* keyRaw, STRING_PURE String* value) {
|
||||
void Options_Load(void) {
|
||||
void* file = NULL;
|
||||
String path = String_FromConst("options.txt");
|
||||
ReturnCode result = Platform_FileOpen(&file, &path, true);
|
||||
ReturnCode result = Platform_FileOpen(&file, &path);
|
||||
|
||||
if (result == ReturnCode_FileNotFound) return;
|
||||
/* TODO: Should we just log failure to open? */
|
||||
@ -182,7 +182,7 @@ void Options_Load(void) {
|
||||
void Options_Save(void) {
|
||||
void* file = NULL;
|
||||
String path = String_FromConst("options.txt");
|
||||
ReturnCode result = Platform_FileOpen(&file, &path, true);
|
||||
ReturnCode result = Platform_FileOpen(&file, &path);
|
||||
|
||||
/* TODO: Should we just log failure to save? */
|
||||
ErrorHandler_CheckOrFail(result, "Options - Saving");
|
||||
|
@ -31,7 +31,8 @@ typedef void Platform_EnumFilesCallback(STRING_PURE String* path, void* obj);
|
||||
ReturnCode Platform_EnumFiles(STRING_PURE String* path, void* obj, Platform_EnumFilesCallback callback);
|
||||
|
||||
ReturnCode Platform_FileCreate(void** file, STRING_PURE String* path);
|
||||
ReturnCode Platform_FileOpen(void** file, STRING_PURE String* path, bool readOnly);
|
||||
ReturnCode Platform_FileOpen(void** file, STRING_PURE String* path);
|
||||
ReturnCode Platform_FileAppend(void** file, STRING_PURE String* path);
|
||||
ReturnCode Platform_FileRead(void* file, UInt8* buffer, UInt32 count, UInt32* bytesRead);
|
||||
ReturnCode Platform_FileWrite(void* file, UInt8* buffer, UInt32 count, UInt32* bytesWritten);
|
||||
ReturnCode Platform_FileClose(void* file);
|
||||
|
@ -24,7 +24,7 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
/*void* file;
|
||||
String path = String_FromConstant("H:\\PortableApps\\GitPortable\\App\\Git\\ClassicalSharp\\output\\release\\texpacks\\skybox.png");
|
||||
ReturnCode openCode = Platform_FileOpen(&file, &path, true);
|
||||
ReturnCode openCode = Platform_FileOpen(&file, &path);
|
||||
Stream fileStream;
|
||||
Stream_FromFile(&fileStream, file, &path);
|
||||
Bitmap bmp;
|
||||
@ -61,7 +61,7 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
/*void* file;
|
||||
String path = String_FromConstant("H:\\PortableApps\\GitPortable\\App\\Git\\ClassicalSharp\\output\\release\\texpacks\\default.zip");
|
||||
ReturnCode openCode = Platform_FileOpen(&file, &path, true);
|
||||
ReturnCode openCode = Platform_FileOpen(&file, &path);
|
||||
Stream fileStream;
|
||||
Stream_FromFile(&fileStream, file, &path);
|
||||
ZipState state;
|
||||
@ -71,7 +71,7 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
void* file;
|
||||
String path = String_FromConst("H:\\PortableApps\\GitPortable\\App\\Git\\ClassicalSharp\\src\\x64\\Release\\canyon.lvl");
|
||||
ReturnCode openCode = Platform_FileOpen(&file, &path, true);
|
||||
ReturnCode openCode = Platform_FileOpen(&file, &path);
|
||||
Stream fileStream;
|
||||
Stream_FromFile(&fileStream, file, &path);
|
||||
Lvl_Load(&fileStream);
|
||||
@ -79,7 +79,7 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
/*void* file;
|
||||
String path = String_FromConstant("H:\\PortableApps\\GitPortable\\App\\Git\\\ClassicalSharp\\src\\Debug\\gunzip.c.gz");
|
||||
ReturnCode openCode = Platform_FileOpen(&file, &path, true);
|
||||
ReturnCode openCode = Platform_FileOpen(&file, &path);
|
||||
Stream fileStream;
|
||||
Stream_FromFile(&fileStream, file, &path);
|
||||
|
||||
|
@ -32,8 +32,7 @@ void ErrorHandler_Fail(const UInt8* raw_msg) {
|
||||
ErrorHandler_WriteLogBody(raw_msg);
|
||||
ErrorHandler_WriteLogEnd();
|
||||
|
||||
HWND win = GetActiveWindow();
|
||||
MessageBoxA(win, logMsg.buffer, "We're sorry", 0);
|
||||
ErrorHandler_ShowDialog("We're sorry", logMsg.buffer);
|
||||
ExitProcess(1);
|
||||
}
|
||||
|
||||
@ -45,7 +44,11 @@ void ErrorHandler_FailWithCode(ReturnCode code, const UInt8* raw_msg) {
|
||||
String_AppendConst(&logMsg, "\r\n");
|
||||
ErrorHandler_WriteLogEnd();
|
||||
|
||||
HWND win = GetActiveWindow(); /* TODO: It's probably wrong to use GetActiveWindow() here */
|
||||
MessageBoxA(win, logMsg.buffer, "We're sorry", 0);
|
||||
ErrorHandler_ShowDialog("We're sorry", logMsg.buffer);
|
||||
ExitProcess(code);
|
||||
}
|
||||
|
||||
void ErrorHandler_ShowDialog(const UInt8* title, const UInt8* msg) {
|
||||
HWND win = GetActiveWindow(); /* TODO: It's probably wrong to use GetActiveWindow() here */
|
||||
MessageBoxA(win, msg, title, 0);
|
||||
}
|
@ -151,23 +151,28 @@ ReturnCode Platform_EnumFiles(STRING_PURE String* path, void* obj, Platform_Enum
|
||||
}
|
||||
|
||||
|
||||
ReturnCode Platform_FileOpen(void** file, STRING_PURE String* path, bool readOnly) {
|
||||
UINT32 access = GENERIC_READ;
|
||||
if (!readOnly) access |= GENERIC_WRITE;
|
||||
HANDLE handle = CreateFileA(path->buffer, access, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
ReturnCode Platform_FileOpen(void** file, STRING_PURE String* path) {
|
||||
HANDLE handle = CreateFileA(path->buffer, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
*file = (void*)handle;
|
||||
|
||||
return handle != INVALID_HANDLE_VALUE ? 0 : GetLastError();
|
||||
}
|
||||
|
||||
ReturnCode Platform_FileCreate(void** file, STRING_PURE String* path) {
|
||||
UINT32 access = GENERIC_READ | GENERIC_WRITE;
|
||||
HANDLE handle = CreateFileA(path->buffer, access, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
HANDLE handle = CreateFileA(path->buffer, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
*file = (void*)handle;
|
||||
|
||||
return handle != INVALID_HANDLE_VALUE ? 0 : GetLastError();
|
||||
}
|
||||
|
||||
ReturnCode Platform_FileAppend(void** file, STRING_PURE String* path) {
|
||||
HANDLE handle = CreateFileA(path->buffer, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
*file = (void*)handle;
|
||||
|
||||
if (handle == INVALID_HANDLE_VALUE) return GetLastError();
|
||||
return Platform_FileSeek(*file, 0, STREAM_SEEKFROM_END);
|
||||
}
|
||||
|
||||
ReturnCode Platform_FileRead(void* file, UInt8* buffer, UInt32 count, UInt32* bytesRead) {
|
||||
BOOL success = ReadFile((HANDLE)file, buffer, count, bytesRead, NULL);
|
||||
return success ? 0 : GetLastError();
|
||||
@ -187,11 +192,11 @@ ReturnCode Platform_FileSeek(void* file, Int32 offset, Int32 seekType) {
|
||||
DWORD pos;
|
||||
switch (seekType) {
|
||||
case STREAM_SEEKFROM_BEGIN:
|
||||
pos = SetFilePointer(file, offset, NULL, 0); break;
|
||||
pos = SetFilePointer(file, offset, NULL, FILE_BEGIN); break;
|
||||
case STREAM_SEEKFROM_CURRENT:
|
||||
pos = SetFilePointer(file, offset, NULL, 1); break;
|
||||
pos = SetFilePointer(file, offset, NULL, FILE_CURRENT); break;
|
||||
case STREAM_SEEKFROM_END:
|
||||
pos = SetFilePointer(file, offset, NULL, 2); break;
|
||||
pos = SetFilePointer(file, offset, NULL, FILE_END); break;
|
||||
default:
|
||||
ErrorHandler_Fail("Invalid SeekType provided when seeking file");
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user