diff --git a/TrueCraft.Client/Rendering/TextureMapper.cs b/TrueCraft.Client/Rendering/TextureMapper.cs
new file mode 100644
index 0000000..aac19de
--- /dev/null
+++ b/TrueCraft.Client/Rendering/TextureMapper.cs
@@ -0,0 +1,152 @@
+using System;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+using TrueCraft.Core;
+
+namespace TrueCraft.Client.Rendering
+{
+ ///
+ /// Provides mappings from keys to textures.
+ ///
+ public sealed class TextureMapper : IDisposable
+ {
+ ///
+ ///
+ ///
+ public static readonly IDictionary Defaults =
+ new Dictionary();
+
+ ///
+ ///
+ ///
+ ///
+ public static void LoadDefaults(GraphicsDevice graphicsDevice)
+ {
+ Defaults.Clear();
+
+ Defaults.Add("items.png", Texture2D.FromStream(graphicsDevice, File.OpenRead("Content/items.png")));
+ Defaults.Add("terrain.png", Texture2D.FromStream(graphicsDevice, File.OpenRead("Content/terrain.png")));
+ }
+
+ ///
+ ///
+ ///
+ public TexturePack TexturePack { get; private set; }
+
+ ///
+ ///
+ ///
+ private IDictionary Customs { get; set; }
+
+ ///
+ ///
+ ///
+ public bool IsDisposed { get; private set; }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public TextureMapper(GraphicsDevice graphicsDevice, TexturePack texturePack = null)
+ {
+ if (graphicsDevice == null)
+ throw new ArgumentException();
+
+ TexturePack = texturePack;
+ Customs = new Dictionary();
+ IsDisposed = false;
+
+ if (TexturePack != null)
+ LoadTextures(graphicsDevice);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ private void LoadTextures(GraphicsDevice graphicsDevice)
+ {
+ foreach (var entry in TexturePack.Archive.Entries)
+ {
+ // Make sure to 'silence' errors loading custom texture packs;
+ // they're unimportant as we can just use default textures.
+ try
+ {
+ var key = entry.FileName;
+ using (var stream = entry.OpenReader())
+ Customs.Add(key, Texture2D.FromStream(graphicsDevice, stream));
+ }
+ catch { }
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public Texture2D GetTexture(string key)
+ {
+ Texture2D result = null;
+ TryGetTexture(key, out result);
+ return result;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public bool TryGetTexture(string key, out Texture2D texture)
+ {
+ // -> Try to load from external texture pack
+ // -> Try to load from default texture pack
+ // -> Fail gracefully
+
+ if (string.IsNullOrEmpty(key))
+ throw new ArgumentException();
+
+ bool hasTexture = false;
+ texture = null;
+ if (TexturePack != null)
+ {
+ Texture2D customTexture = null;
+ var inCustom = Customs.TryGetValue(key, out customTexture);
+ texture = (inCustom) ? customTexture : null;
+ hasTexture = inCustom;
+ }
+
+ if (!hasTexture)
+ {
+ Texture2D defaultTexture = null;
+ var inDefault = TextureMapper.Defaults.TryGetValue(key, out defaultTexture);
+ texture = (inDefault) ? defaultTexture : null;
+ hasTexture = inDefault;
+ }
+
+ return hasTexture;
+ }
+
+ ///
+ ///
+ ///
+ public void Dispose()
+ {
+ if (IsDisposed)
+ return;
+
+ foreach (var pair in Customs)
+ pair.Value.Dispose();
+
+ Customs.Clear();
+ Customs = null;
+ TexturePack = null;
+ IsDisposed = true;
+ }
+ }
+}
diff --git a/TrueCraft.Client/TrueCraft.Client.csproj b/TrueCraft.Client/TrueCraft.Client.csproj
index 3a88eea..a01f728 100644
--- a/TrueCraft.Client/TrueCraft.Client.csproj
+++ b/TrueCraft.Client/TrueCraft.Client.csproj
@@ -114,6 +114,7 @@
+
diff --git a/TrueCraft.Client/TrueCraftGame.cs b/TrueCraft.Client/TrueCraftGame.cs
index 35143f5..ad60449 100644
--- a/TrueCraft.Client/TrueCraftGame.cs
+++ b/TrueCraft.Client/TrueCraftGame.cs
@@ -43,6 +43,7 @@ namespace TrueCraft.Client
private GameTime GameTime { get; set; }
private Microsoft.Xna.Framework.Vector3 Delta { get; set; }
private TexturePack TexturePack { get; set; }
+ private TextureMapper TextureMapper { get; set; }
private BasicEffect OpaqueEffect, TransparentEffect;
@@ -126,7 +127,14 @@ namespace TrueCraft.Client
protected override void LoadContent()
{
- TexturePack = new TexturePack(UserSettings.Local.SelectedTexturePack);
+ // Ensure we have default textures loaded.
+ TextureMapper.LoadDefaults(GraphicsDevice);
+
+ // Load any custom textures if needed.
+ TexturePack = (UserSettings.Local.SelectedTexturePack != TexturePack.DefaultID) ?
+ new TexturePack(UserSettings.Local.SelectedTexturePack) : null;
+ TextureMapper = new TextureMapper(GraphicsDevice, TexturePack);
+
DejaVu = new FontRenderer(
new Font(Content, "Fonts/DejaVu", FontStyle.Regular),
new Font(Content, "Fonts/DejaVu", FontStyle.Bold),
@@ -141,7 +149,7 @@ namespace TrueCraft.Client
OpaqueEffect.DirectionalLight1.SpecularColor = Color.Black.ToVector3();
OpaqueEffect.DirectionalLight2.SpecularColor = Color.Black.ToVector3();
OpaqueEffect.TextureEnabled = true;
- OpaqueEffect.Texture = TexturePack.GetTexture(GraphicsDevice, "terrain.png");
+ OpaqueEffect.Texture = TextureMapper.GetTexture("terrain.png");
OpaqueEffect.FogEnabled = true;
OpaqueEffect.FogStart = 512f;
OpaqueEffect.FogEnd = 1000f;
@@ -149,7 +157,7 @@ namespace TrueCraft.Client
TransparentEffect = new BasicEffect(GraphicsDevice);
TransparentEffect.TextureEnabled = true;
- TransparentEffect.Texture = TexturePack.GetTexture(GraphicsDevice, "terrain.png");
+ TransparentEffect.Texture = TextureMapper.GetTexture("terrain.png");
base.LoadContent();
}
diff --git a/TrueCraft.Core/TexturePack.cs b/TrueCraft.Core/TexturePack.cs
index fc5c27d..b0da3f7 100644
--- a/TrueCraft.Core/TexturePack.cs
+++ b/TrueCraft.Core/TexturePack.cs
@@ -12,12 +12,7 @@ namespace TrueCraft.Core
///
///
///
- public const string DescriptionFile = "pack.txt";
-
- ///
- ///
- ///
- public const string ImageFile = "pack.png";
+ public const string DefaultID = "#Default";
///
///
@@ -56,6 +51,16 @@ namespace TrueCraft.Core
///
public MemoryStream Image { get; private set; }
+ ///
+ ///
+ ///
+ public TexturePack()
+ {
+ Path = TexturePack.DefaultID;
+ Name = "Default";
+ Archive = new ZipFile();
+ }
+
///
///
///
@@ -65,7 +70,6 @@ namespace TrueCraft.Core
if (string.IsNullOrEmpty(path) || !File.Exists(path))
throw new ArgumentException();
-
Path = path;
var fileInfo = new FileInfo(path); // A bit weird, but it works.
Name = fileInfo.Name;
@@ -82,7 +86,7 @@ namespace TrueCraft.Core
{
foreach (var entry in Archive.Entries)
{
- if (entry.FileName == TexturePack.DescriptionFile)
+ if (entry.FileName == "pack.txt")
{
using (var stream = entry.OpenReader())
{
@@ -90,7 +94,7 @@ namespace TrueCraft.Core
Description = reader.ReadToEnd();
}
}
- else if (entry.FileName == TexturePack.ImageFile)
+ else if (entry.FileName == "pack.png")
{
using (var stream = entry.OpenReader())
{
@@ -99,6 +103,9 @@ namespace TrueCraft.Core
stream.Read(buffer, 0, buffer.Length);
Image = new MemoryStream((int)entry.UncompressedSize);
Image.Write(buffer, 0, buffer.Length);
+
+ // Fixes 'GLib.GException: Unrecognized image file format' on Linux.
+ Image.Seek(0, SeekOrigin.Begin);
}
}
}
diff --git a/TrueCraft.Core/UserSettings.cs b/TrueCraft.Core/UserSettings.cs
index 63a5364..86a9543 100644
--- a/TrueCraft.Core/UserSettings.cs
+++ b/TrueCraft.Core/UserSettings.cs
@@ -30,7 +30,7 @@ namespace TrueCraft.Core
Username = "";
Password = "";
LastIP = "";
- SelectedTexturePack = "Default.zip";
+ SelectedTexturePack = TexturePack.DefaultID;
FavoriteServers = new FavoriteServer[0];
}
diff --git a/TrueCraft.Launcher/Content/Default.zip b/TrueCraft.Launcher/Content/Default.zip
deleted file mode 100644
index 2fe999f..0000000
Binary files a/TrueCraft.Launcher/Content/Default.zip and /dev/null differ
diff --git a/TrueCraft.Launcher/Content/default-pack.png b/TrueCraft.Launcher/Content/default-pack.png
new file mode 100644
index 0000000..cf893db
Binary files /dev/null and b/TrueCraft.Launcher/Content/default-pack.png differ
diff --git a/TrueCraft.Launcher/Content/default-pack.txt b/TrueCraft.Launcher/Content/default-pack.txt
new file mode 100644
index 0000000..b90cfbc
--- /dev/null
+++ b/TrueCraft.Launcher/Content/default-pack.txt
@@ -0,0 +1 @@
+No description available.
\ No newline at end of file
diff --git a/TrueCraft.Launcher/TrueCraft.Launcher.csproj b/TrueCraft.Launcher/TrueCraft.Launcher.csproj
index bcf50df..b7fb5cc 100644
--- a/TrueCraft.Launcher/TrueCraft.Launcher.csproj
+++ b/TrueCraft.Launcher/TrueCraft.Launcher.csproj
@@ -57,6 +57,12 @@
Xwt.Gtk.dll
PreserveNewest
+
+ PreserveNewest
+
+
+ PreserveNewest
+
PreserveNewest
@@ -85,9 +91,6 @@
-
- PreserveNewest
-
PreserveNewest
diff --git a/TrueCraft.Launcher/Views/OptionView.cs b/TrueCraft.Launcher/Views/OptionView.cs
index cdc42a2..cf2e9b9 100644
--- a/TrueCraft.Launcher/Views/OptionView.cs
+++ b/TrueCraft.Launcher/Views/OptionView.cs
@@ -11,6 +11,8 @@ namespace TrueCraft.Launcher.Views
public class OptionView : VBox
{
public LauncherWindow Window { get; set; }
+ public Image DefaultImage { get; set; }
+ public string DefaultDescription { get; set; }
public Label OptionLabel { get; set; }
public Label TexturePackLabel { get; set; }
@@ -27,6 +29,9 @@ namespace TrueCraft.Launcher.Views
public OptionView(LauncherWindow window)
{
+ DefaultImage = Image.FromFile("Content/default-pack.png");
+ DefaultDescription = File.ReadAllText("Content/default-pack.txt");
+
_texturePacks = new List();
_lastTexturePack = null;
@@ -89,8 +94,8 @@ namespace TrueCraft.Launcher.Views
private void LoadTexturePacks()
{
- // We load Default.zip from a different directory.
- var defaultPack = new TexturePack("Content/Default.zip");
+ // We load the default texture pack specially.
+ var defaultPack = new TexturePack();
_texturePacks.Add(defaultPack);
AddTexturePackRow(defaultPack);
@@ -113,9 +118,9 @@ namespace TrueCraft.Launcher.Views
private void AddTexturePackRow(TexturePack pack)
{
var row = TexturePackStore.AddRow();
- TexturePackStore.SetValue(row, TexturePackImageField, Image.FromStream(pack.Image).WithSize(IconSize.Medium));
+ TexturePackStore.SetValue(row, TexturePackImageField, (pack.Image == null) ? DefaultImage.WithSize(IconSize.Medium) : Image.FromStream(pack.Image).WithSize(IconSize.Medium));
TexturePackStore.SetValue(row, TexturePackNameField, pack.Name);
- TexturePackStore.SetValue(row, TexturePackDescField, pack.Description);
+ TexturePackStore.SetValue(row, TexturePackDescField, pack.Description ?? DefaultDescription);
}
}
}