SignToolsGUI/Form1.cs

339 lines
14 KiB
C#

using LZ4;
using ProtoBuf;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace SignToolsGUI
{
public partial class Form1 : Form
{
WorldSerialization worldSerialization = new WorldSerialization();
uint Version;
Dictionary<string, byte[]> SerializedImageData = new Dictionary<string, byte[]>();
Dictionary<string, byte[]> ModdedSerializedImageData = new Dictionary<string, byte[]>();
uint[] signids = { 1447270506, 4057957010, 120534793, 58270319, 4290170446, 3188315846, 3215377795, 1960724311, 3159642196, 3725754530, 1957158128, 637495597, 1283107100, 4006597758, 3715545584, 3479792512, 3618197174, 550204242 };
private Dictionary<string, SignSize> _signSizes = new Dictionary<string, SignSize>
{
{"4006597758", new SignSize(512, 512)},
{"3215377795", new SignSize(256, 128)},
{"3159642196", new SignSize(128, 512)},
{"1960724311", new SignSize(128, 256)},
{"3725754530", new SignSize(1024, 512)},
{"1957158128", new SignSize(512, 512)},
{"1447270506", new SignSize(128, 64)},
{"3715545584", new SignSize(256, 128)},
{"3479792512", new SignSize(256, 128)},
{"3618197174", new SignSize(512, 128)},
{"637495597", new SignSize(64, 256)},
{"3188315846", new SignSize(64, 256)},
{"58270319", new SignSize(128, 64)},
{"4290170446", new SignSize(256, 256)},
{"120534793", new SignSize(256, 128)},
{"4057957010", new SignSize(256, 128)},
{"550204242", new SignSize(128, 256)},
{"1283107100", new SignSize(256, 128)},
};
private Dictionary<string, string> _Names = new Dictionary<string, string>
{
{"4006597758", "spinner.wheel"},
{"3215377795", "sign.pictureframe.landscape"},
{"3159642196", "sign.pictureframe.tall"},
{"1960724311", "sign.pictureframe.portrait"},
{"3725754530", "sign.pictureframe.xxl"},
{"1957158128", "sign.pictureframe.xl"},
{"1447270506", "sign.small.wood"},
{"3715545584", "sign.medium.wood"},
{"3479792512", "sign.large.wood"},
{"3618197174", "sign.huge.wood"},
{"637495597", "sign.hanging.banner.large"},
{"3188315846", "sign.pole.banner.large"},
{"58270319", "sign.post.single"},
{"4290170446", "sign.post.double"},
{"120534793", "sign.post.town"},
{"4057957010", "sign.post.town.roof"},
{"550204242", "sign.hanging"},
{"1283107100", "sign.hanging.ornate"},
};
private class SignSize
{
public int Width;
public int Height;
public SignSize(int width, int height)
{
Width = width;
Height = height;
}
}
public Form1()
{
InitializeComponent();
}
public static string Base64Encode(string plainText)
{
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
return System.Convert.ToBase64String(plainTextBytes);
}
public static string Base64Decode(string base64EncodedData)
{
var base64EncodedBytes = System.Convert.FromBase64String(base64EncodedData);
return System.Text.Encoding.UTF8.GetString(base64EncodedBytes);
}
void XMLDecode(string SerialData)
{
string[] DataParse = SerialData.Split(new string[] { "<position>" }, StringSplitOptions.None);
foreach (string xmldata in DataParse)
{
if (xmldata.Contains("xml version")) continue;
string x = xmldata.Split(new string[] { "</x><y>" }, StringSplitOptions.None)[0].Replace("<x>", "");
string y = xmldata.Split(new string[] { "</y><z>" }, StringSplitOptions.None)[0].Replace("<x>" + x + "</x><y>", "");
string z = xmldata.Split(new string[] { "</z></position>" }, StringSplitOptions.None)[0].Replace("<x>" + x + "</x><y>" + y + "</y><z>", "");
string texture = xmldata.Split(new string[] { "<texture>" }, StringSplitOptions.None)[1].Replace("</texture>", "").Replace("</SerializedImageData>", "");
byte[] ImageData = Convert.FromBase64String(texture);
SerializedImageData.Add("("+ x+", "+y + ", "+z+")", ImageData);
}
}
string XMLEncode()
{
string XMLData = @"<? xml version=""1.0""?><SerializedImageData>";
string SerialData = "";
foreach (KeyValuePair<string, byte[]> _sign in ModdedSerializedImageData)
{
if (_sign.Value.Length != 0)
{
string[] xmlbreakdown = _sign.Key.Replace("(", "").Replace(" ", "").Replace(")", "").Split(',');
SerialData += ("<position>" +
"<x>" + xmlbreakdown[0] + "</x>" +
"<y>" + xmlbreakdown[1] + "</y>" +
"<z>" + xmlbreakdown[2] + "</z>" +
"</position>" +
"<texture>" +
Convert.ToBase64String(_sign.Value) +
"</texture>");
}
}
XMLData = XMLData + SerialData + "</SerializedImageData>";
return XMLData;
}
private void DisableButtons()
{
SaveMap.Enabled = false;
Locations.Enabled = false;
AddImage.Enabled = false;
ImagePreview.Enabled = false;
RemoveImage.Enabled = false;
}
private bool isSign(PrefabData sign)
{
//Checks prefab has a valid sign id
return (signids.Contains(sign.id));
}
byte[] ImageResize(byte[] imageBytes, int width, int height)
{
//Resize image to sign size.
Bitmap resizedImage = new Bitmap(width, height),
sourceImage = new Bitmap(new MemoryStream(imageBytes));
Graphics.FromImage(resizedImage).DrawImage(sourceImage, new Rectangle(0, 0, width, height),
new Rectangle(0, 0, sourceImage.Width, sourceImage.Height), GraphicsUnit.Pixel);
var ms = new MemoryStream();
resizedImage.Save(ms, ImageFormat.Png);
return ms.ToArray();
}
private void OpenMap_Click(object sender, EventArgs e)
{
Locations.Items.Clear();
SerializedImageData.Clear();
ModdedSerializedImageData.Clear();
OpenFileDialog openFileDialog1 = new OpenFileDialog
{
Title = "Rust Map File",
CheckFileExists = true,
CheckPathExists = true,
DefaultExt = "map",
Filter = "map files (*.map)|*.map",
FilterIndex = 2,
RestoreDirectory = true,
ReadOnlyChecked = true,
ShowReadOnly = true
};
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
mapdir.Text = openFileDialog1.FileName;
try
{
worldSerialization.Load(mapdir.Text);
Version = worldSerialization.Version;
//Check for exsisting
for (int i = worldSerialization.world.maps.Count - 1; i >= 0; i--)
{
MapData mapdata = worldSerialization.world.maps[i];
if (mapdata.name == Base64Encode("SerializedImageData"))
{
XMLDecode(System.Text.Encoding.ASCII.GetString(mapdata.data));
}
}
//Scan all prefab in map file.
for (int i = worldSerialization.world.prefabs.Count - 1; i >= 0; i--)
{
PrefabData prefabdata = worldSerialization.world.prefabs[i];
if (isSign(prefabdata))
{
string location = "(" + prefabdata.position.x.ToString("0.0") + ", " + prefabdata.position.y.ToString("0.0") + ", " + prefabdata.position.z.ToString("0.0") + ")";
Locations.Items.Add(location + " " + prefabdata.id.ToString());
if(SerializedImageData.ContainsKey(location))
{
ModdedSerializedImageData.Add(location, SerializedImageData[location]);
}
else
{
ModdedSerializedImageData.Add(location, new byte[0]);
}
}
}
if(Locations.Items.Count == 0)
{
MessageBox.Show("No Signs are on this map");
return;
}
Locations.Text = Locations.Items[0].ToString();
SaveMap.Enabled = true;
Locations.Enabled = true;
AddImage.Enabled = true;
ImagePreview.Enabled = true;
SignType.Enabled = true;
RemoveImage.Enabled = true;
}
catch
{
MessageBox.Show("Failed to open map");
DisableButtons();
}
}
}
private void Selection(object sender, EventArgs e)
{
string[] selected = Locations.GetItemText(Locations.SelectedItem).Split(')');
SignType.Text = selected[1].Replace(" ", "");
name.Text = _Names[SignType.Text];
Size size = new Size(_signSizes[SignType.Text].Width, _signSizes[SignType.Text].Height);
ImagePreview.Size = size;
if (ModdedSerializedImageData.ContainsKey(selected[0]+")"))
{
if (ModdedSerializedImageData[selected[0] + ")"].Length != 0)
{
ImagePreview.Image = ByteToImage(ModdedSerializedImageData[selected[0] + ")"]);
}
else
{
ImagePreview.Image = null;
}
}
}
public static Bitmap ByteToImage(byte[] blob)
{
MemoryStream mStream = new MemoryStream();
byte[] pData = blob;
mStream.Write(pData, 0, Convert.ToInt32(pData.Length));
Bitmap bm = new Bitmap(mStream, false);
mStream.Dispose();
return bm;
}
private void AddImage_Click(object sender, EventArgs e)
{
OpenFileDialog openFileDialog1 = new OpenFileDialog
{
Title = "Image File",
CheckFileExists = true,
CheckPathExists = true,
DefaultExt = "png",
Filter = "png files (*.png)|*.png",
FilterIndex = 2,
RestoreDirectory = true,
ReadOnlyChecked = true,
ShowReadOnly = true
};
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
byte[] NewImage = ImageResize(File.ReadAllBytes(openFileDialog1.FileName), ImagePreview.Width, ImagePreview.Height);
string[] selected = Locations.GetItemText(Locations.SelectedItem).Split(')');
if (ModdedSerializedImageData.ContainsKey(selected[0] + ")"))
{
ModdedSerializedImageData[selected[0] + ")"] = NewImage;
ImagePreview.Image = ByteToImage(ModdedSerializedImageData[selected[0] + ")"]);
}
}
}
private void SaveMap_Click(object sender, EventArgs e)
{
string XMLData = XMLEncode();
//Check if mapdata already has image data
MapData sd = worldSerialization.GetMap(Base64Encode("SerializedImageData"));
if (sd == null)
{
worldSerialization.AddMap(Base64Encode("SerializedImageData"), Encoding.ASCII.GetBytes(XMLData));
}
else
{
sd.data = Encoding.ASCII.GetBytes(XMLData);
}
string mapfile = mapdir.Text.Replace(".map",".signs.map");
if (File.Exists(mapfile))
{
File.Delete(mapfile);
}
using (FileStream fileStream = new FileStream(mapfile, FileMode.CreateNew, FileAccess.Write, FileShare.None))
{
using (BinaryWriter binaryWriter = new BinaryWriter(fileStream))
{
binaryWriter.Write(Version);
using (LZ4Stream stream = new LZ4Stream(fileStream, LZ4StreamMode.Compress))
{
WorldData.Serialize(stream, worldSerialization.world);
}
}
}
MessageBox.Show("Saved");
}
private void RemoveImage_Click(object sender, EventArgs e)
{
string[] selected = Locations.GetItemText(Locations.SelectedItem).Split(')');
ModdedSerializedImageData[selected[0] + ")"] = new byte[0];
ImagePreview.Image = null;
}
}
}