mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/PCK-Studio.git
synced 2026-05-29 10:24:34 +00:00
-"Move Up" and "Move Down" functions finally work properly and with folders! -Animation Editor can import Java block and item animations -Animation Editor has a built-in Change Tile function where every single block and item that can be animated is listed (clock and compass are excluded since they have animations based on game data). When selected, it will automatically set your animation to that tile for you. If a required folder is missing, the function will create the folder for you and place the file inside. Happy animating! (: -Removed the old "Create Animated Texture" function and replaced it with the new Animation Editor -Moved the Audio Editor and Animation Editor into their own folders in the Utilities folder to keep things a little more organized in the solution.
3896 lines
183 KiB
C#
3896 lines
183 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Windows.Forms;
|
|
using System.Drawing.Drawing2D;
|
|
using System.IO.Compression;
|
|
using System.Net;
|
|
using System.Diagnostics;
|
|
using PckStudio.Properties;
|
|
using Ohana3DS_Rebirth.Ohana;
|
|
using PckStudio.Forms;
|
|
using System.Drawing.Imaging;
|
|
using RichPresenceClient;
|
|
|
|
namespace PckStudio
|
|
{
|
|
public partial class FormMain : MetroFramework.Forms.MetroForm
|
|
{
|
|
#region Variables
|
|
string saveLocation;//Save location for pck file
|
|
int fileCount = 0;//variable for number of minefiles
|
|
string Version = Classes.Network.Version;//template for program version
|
|
string hosturl = "";
|
|
string basurl = "";
|
|
string PCKFile = "";
|
|
string PCKFileBCKUP = "x";
|
|
loadedTexture tex = new loadedTexture(); //3DS feature variable
|
|
|
|
|
|
PCK.MineFile mf;//Template minefile variable
|
|
PCK currentPCK;//currently opened pck
|
|
LOC l;//Locdata
|
|
PCK.MineFile mfLoc;//LOC minefile
|
|
Dictionary<int, string> types;//Template list for metadata of a individual minefiles metadata
|
|
PCK.MineFile file;//template for a selected minefile
|
|
bool needsUpdate = false;
|
|
bool saved = true;
|
|
string appData = System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "/PCK Studio/";
|
|
public static bool correct = false;
|
|
bool isdebug = false;
|
|
|
|
public class displayId
|
|
{
|
|
public string id;
|
|
public string defaultName;
|
|
}
|
|
#endregion
|
|
|
|
#region form startup page
|
|
public FormMain()
|
|
{
|
|
|
|
|
|
Directory.CreateDirectory(appData + "\\template");
|
|
if (!File.Exists(appData + "\\template\\UntitledSkinPCK.pck"))
|
|
File.WriteAllBytes(appData + "\\template\\UntitledSkinPCK.pck", Resources.UntitledSkinPCK);
|
|
if (!File.Exists(appData + "\\settings.ini"))
|
|
File.WriteAllText(appData + "\\settings.ini", Resources.settings);
|
|
hosturl = File.ReadAllText(appData + "\\settings.ini").Split(new[] { "\r\n", "\n" }, StringSplitOptions.None)[0];
|
|
|
|
|
|
InitializeComponent();
|
|
|
|
if (Program.IsDev)
|
|
isdebug = true;
|
|
|
|
FormBorderStyle = FormBorderStyle.None;
|
|
labelVersion.Text += Version;
|
|
pckOpen.AllowDrop = true;
|
|
}
|
|
#endregion
|
|
|
|
#region opens and loads pck file
|
|
|
|
private void openToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
try
|
|
{
|
|
using (var ofd = new OpenFileDialog())
|
|
{
|
|
ofd.CheckFileExists = true; //makes sure opened pck exists
|
|
ofd.Filter = "PCK (Minecraft Console Package)|*.pck";
|
|
|
|
if (ofd.ShowDialog() == DialogResult.OK)
|
|
{
|
|
PCKFile = Path.GetFileName(ofd.FileName);
|
|
openPck(ofd.FileName);
|
|
}
|
|
}
|
|
}
|
|
catch (Exception err)
|
|
{
|
|
MessageBox.Show("The PCK you're trying to use currently isn't supported\n" + err.StackTrace + "\n\n" + err.Message);//Error handling for PCKs that give errors when trying to be opened
|
|
}
|
|
}
|
|
|
|
private void openPck(string filePath)
|
|
{
|
|
new TabPage();
|
|
treeViewMain.Nodes.Clear();
|
|
treeViewMain.LabelEdit = false;
|
|
PCK pCK = (currentPCK = new PCK(filePath));
|
|
foreach (PCK.MineFile mineFile in pCK.mineFiles)
|
|
{
|
|
Console.WriteLine(mineFile.name);
|
|
if (!(mineFile.name == "0"))
|
|
{
|
|
continue;
|
|
}
|
|
foreach (object[] entry in mineFile.entries)
|
|
{
|
|
if (entry[0].ToString() == "LOCK")
|
|
{
|
|
if((new pckLocked(entry[1].ToString(), correct).ShowDialog() != DialogResult.OK || !correct))
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
addPasswordToolStripMenuItem.Enabled = true;
|
|
openedPCKS.SelectedTab.Text = Path.GetFileName(filePath);
|
|
saveLocation = filePath;
|
|
_ = treeViewMain;
|
|
_ = pictureBoxImagePreview;
|
|
_ = treeMeta;
|
|
_ = textBox1;
|
|
_ = label1;
|
|
_ = label2;
|
|
_ = tabDataDisplay;
|
|
ImageList imageList = new ImageList();
|
|
imageList.ColorDepth = ColorDepth.Depth32Bit;
|
|
imageList.ImageSize = new Size(20, 20);
|
|
imageList.Images.Add(Resources.ZZFolder);
|
|
imageList.Images.Add(Resources.BINKA_ICON);
|
|
imageList.Images.Add(Resources.IMAGE_ICON);
|
|
imageList.Images.Add(Resources.LOC_ICON);
|
|
imageList.Images.Add(Resources.PCK_ICON);
|
|
imageList.Images.Add(Resources.ZUnknown);
|
|
treeViewMain.ImageList = imageList;
|
|
foreach (PCK.MineFile mineFile2 in pCK.mineFiles)
|
|
{
|
|
TreeNode treeNode = new TreeNode();
|
|
treeNode.Text = mineFile2.name;
|
|
treeNode.Tag = mineFile2;
|
|
string text = "";
|
|
int num = 0;
|
|
new List<string>();
|
|
TreeNodeCollection nodes = treeViewMain.Nodes;
|
|
do
|
|
{
|
|
text = "";
|
|
string name = mineFile2.name;
|
|
for (int i = 0; i < name.Length; i++)
|
|
{
|
|
char c = name[i];
|
|
bool flag = false;
|
|
if (c == '/')
|
|
{
|
|
foreach (TreeNode item in nodes)
|
|
{
|
|
if (item.Text == text)
|
|
{
|
|
nodes = nodes[item.Index].Nodes;
|
|
flag = true;
|
|
}
|
|
}
|
|
if (!flag)
|
|
{
|
|
nodes.Add(text);
|
|
nodes = nodes[nodes.Count - 1].Nodes;
|
|
}
|
|
flag = false;
|
|
text = "";
|
|
}
|
|
else
|
|
{
|
|
text += c;
|
|
}
|
|
num++;
|
|
}
|
|
}
|
|
while (num != mineFile2.name.Length);
|
|
if (Path.GetExtension(text) == ".binka")
|
|
{
|
|
treeNode.ImageIndex = 1;
|
|
treeNode.SelectedImageIndex = 1;
|
|
}
|
|
else if (Path.GetExtension(text) == ".png")
|
|
{
|
|
treeNode.ImageIndex = 2;
|
|
treeNode.SelectedImageIndex = 2;
|
|
}
|
|
else if (Path.GetExtension(text) == ".loc")
|
|
{
|
|
treeNode.ImageIndex = 3;
|
|
treeNode.SelectedImageIndex = 3;
|
|
}
|
|
else if (Path.GetExtension(text) == ".pck")
|
|
{
|
|
treeNode.ImageIndex = 4;
|
|
treeNode.SelectedImageIndex = 4;
|
|
}
|
|
else
|
|
{
|
|
treeNode.ImageIndex = 5;
|
|
treeNode.SelectedImageIndex = 5;
|
|
}
|
|
treeNode.Text = text;
|
|
nodes.Add(treeNode);
|
|
saved = false;
|
|
}
|
|
myTablePanelStartScreen.Visible = false;
|
|
pckOpen.Visible = false;
|
|
label5.Visible = false;
|
|
labelAmount.Visible = true;
|
|
richTextBoxChangelog.Visible = false;
|
|
openedPCKS.Visible = true;
|
|
openedPCKS.AllowDrop = true;
|
|
foreach (ToolStripMenuItem dropDownItem in fileToolStripMenuItem.DropDownItems)
|
|
{
|
|
dropDownItem.Enabled = true;
|
|
}
|
|
foreach (ToolStripMenuItem dropDownItem2 in editToolStripMenuItem.DropDownItems)
|
|
{
|
|
dropDownItem2.Enabled = true;
|
|
}
|
|
foreach (TreeNode node in treeViewMain.Nodes)
|
|
{
|
|
if (node.Text == "languages.loc")
|
|
{
|
|
mfLoc = (PCK.MineFile)treeViewMain.Nodes[node.Index].Tag;
|
|
}
|
|
if (node.Text == "localisation.loc")
|
|
{
|
|
mfLoc = (PCK.MineFile)treeViewMain.Nodes[node.Index].Tag;
|
|
}
|
|
}
|
|
fileCount = 0;
|
|
foreach (PCK.MineFile mineFile3 in currentPCK.mineFiles)
|
|
{
|
|
_ = mineFile3;
|
|
fileCount++;
|
|
}
|
|
labelAmount.Text = "Files:" + fileCount;
|
|
saved = false;
|
|
LittleEndianCheckBox.Visible = true;
|
|
LittleEndianCheckBox.Checked = currentPCK.IsLittleEndian;
|
|
}
|
|
#endregion
|
|
|
|
#region deciphers what happens when certain pck entries are selected
|
|
private void selectNode(object sender, TreeViewEventArgs e)
|
|
{
|
|
treeMeta.Enabled = true;
|
|
int pictureBoxMaxHeight = (tabPage1.Height / 2) - (tabPage1.Height / 10);
|
|
if (treeViewMain.SelectedNode.Tag != null) //"Selects" node if it has data/isn't a folder
|
|
{
|
|
fileCount = 0;//Resets file count
|
|
//Gets file count based of all existing minefiles
|
|
foreach (PCK.MineFile file in currentPCK.mineFiles)
|
|
{
|
|
fileCount += 1;
|
|
}
|
|
labelAmount.Text = "Files:" + fileCount;//Displays amount
|
|
Dictionary<int, string> pckTypes = currentPCK.types; //Retrieves metadatabase
|
|
|
|
PCK.MineFile mf = (PCK.MineFile)e.Node.Tag; //Sets current minefile being read
|
|
|
|
types = currentPCK.types; //metadatabase
|
|
file = mf; //minefile
|
|
|
|
treeMeta.Nodes.Clear(); //clears minefile metadata treeview
|
|
|
|
comboBox1.Items.Clear(); //clears metacombo(entry name)
|
|
textBox1.Text = ""; //clears metatextbox(entry value)
|
|
|
|
foreach (int type in types.Keys)
|
|
comboBox1.Items.Add(types[type]); //Adds available metadata names from metadatabase to the metacombo
|
|
|
|
//Retrieves metadata for currently selected mineifile and displays it within metatreeview
|
|
int boxes = 0;
|
|
foreach (object[] entry in file.entries) //object = metadata entry(name:value)
|
|
{
|
|
object[] strings = (object[])entry;
|
|
TreeNode meta = new TreeNode();
|
|
|
|
foreach (object[] entryy in file.entries)
|
|
meta.Text = (string)strings[0];
|
|
meta.Tag = entry;
|
|
treeMeta.Nodes.Add(meta);
|
|
|
|
//Check for if file contains model data
|
|
if (entry[0].ToString()=="BOX")
|
|
{
|
|
boxes += 1;
|
|
buttonEdit.Text = "EDIT BOXES";
|
|
buttonEdit.Visible = true;
|
|
}
|
|
else if (entry[0].ToString() == "ANIM")
|
|
{
|
|
Console.WriteLine(entry[1]);
|
|
Console.WriteLine((entry[1].ToString() == "0x80000").ToString() + " - " + entry[1]);
|
|
Console.WriteLine((entry[1].ToString() == "0x40000").ToString() + " - "+ entry[1]);
|
|
|
|
|
|
if ((entry[1].ToString() == "0x40000") || (entry[1].ToString() == "0x80000"))
|
|
{
|
|
buttonEdit.Text = "View Skin";
|
|
boxes += 1;
|
|
buttonEdit.Visible = true;
|
|
}
|
|
}
|
|
else if(boxes == 0)
|
|
{
|
|
buttonEdit.Visible = false;
|
|
}
|
|
}
|
|
|
|
//Check for Animated Texture
|
|
if ((mf.name.StartsWith("res/textures/blocks/") || mf.name.StartsWith("res/textures/items/")) && (!mf.name.EndsWith("clock.png") && (!mf.name.EndsWith("compass.png"))))
|
|
{
|
|
buttonEdit.Text = "EDIT TEXTURE ANIMATION";
|
|
buttonEdit.Visible = true;
|
|
}
|
|
else
|
|
{
|
|
buttonEdit.Visible = false;
|
|
}
|
|
|
|
//If selected item is a image, its displayed with proper dimensions in image box
|
|
if (Path.GetExtension(mf.name) == ".png")
|
|
{
|
|
pictureBoxImagePreview.SizeMode = PictureBoxSizeMode.StretchImage;
|
|
pictureBoxImagePreview.InterpolationMode = InterpolationMode.NearestNeighbor;
|
|
MemoryStream png = new MemoryStream(mf.data); //Gets image data from minefile data
|
|
Image skinPicture = Image.FromStream(png); //Constructs image data into image
|
|
pictureBoxImagePreview.Image = skinPicture; //Sets image preview to image
|
|
|
|
|
|
if (skinPicture.Size.Height == skinPicture.Size.Width / 2)
|
|
{
|
|
pictureBoxImagePreview.Size = new Size(pictureBoxMaxHeight * 2, pictureBoxMaxHeight); //Sets 64x32 ratio images to appear at largest relative size to program window size
|
|
labelImageSize.Text = skinPicture.Size.Width.ToString() + "x" + skinPicture.Size.Height.ToString();
|
|
return;
|
|
}
|
|
else if (skinPicture.Size.Height == skinPicture.Size.Width)
|
|
{
|
|
pictureBoxImagePreview.Size = new Size(pictureBoxMaxHeight, pictureBoxMaxHeight); //SWets 64x64 ratio images to appear at largest relative size to program window size
|
|
labelImageSize.Text = skinPicture.Size.Width.ToString() + "x" + skinPicture.Size.Height.ToString();
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
//Sets images to appear at largest relative size to program window size
|
|
Size maxDisplay = new Size((tabPage1.Size.Width / 2 - 5) / 3, (tabPage1.Size.Height / 2 - 5) / 3);
|
|
if (skinPicture.Size.Width > maxDisplay.Width)
|
|
{
|
|
//calculate aspect ratio
|
|
float aspect = skinPicture.Width / (float)skinPicture.Height;
|
|
int newWidth, newHeight;
|
|
|
|
//calculate new dimensions based on aspect ratio
|
|
newWidth = (int)(maxDisplay.Height * aspect);
|
|
newHeight = (int)(newWidth / aspect);
|
|
|
|
//if one of the two dimensions exceed the box dimensions
|
|
if (newWidth > skinPicture.Width || newHeight > skinPicture.Height)
|
|
{
|
|
//depending on which of the two exceeds the box dimensions set it as the box dimension and calculate the other one based on the aspect ratio
|
|
if (newWidth > newHeight)
|
|
{
|
|
newWidth = maxDisplay.Width;
|
|
newHeight = (int)(newWidth / aspect);
|
|
}
|
|
else
|
|
{
|
|
newHeight = maxDisplay.Height;
|
|
newWidth = (int)(newHeight * aspect);
|
|
}
|
|
}
|
|
pictureBoxImagePreview.Size = new Size(newWidth, newHeight);
|
|
}
|
|
else if (skinPicture.Size.Height > maxDisplay.Height)
|
|
{
|
|
//calculate aspect ratio
|
|
float aspect = skinPicture.Width / (float)skinPicture.Height;
|
|
int newWidth, newHeight;
|
|
|
|
//calculate new dimensions based on aspect ratio
|
|
newWidth = (int)(maxDisplay.Width * aspect);
|
|
newHeight = (int)(newWidth / aspect);
|
|
|
|
//if one of the two dimensions exceed the box dimensions
|
|
if (newWidth > skinPicture.Width || newHeight > skinPicture.Height)
|
|
{
|
|
//depending on which of the two exceeds the box dimensions set it as the box dimension and calculate the other one based on the aspect ratio
|
|
if (newWidth > newHeight)
|
|
{
|
|
newWidth = maxDisplay.Width;
|
|
newHeight = (int)(newWidth / aspect);
|
|
}
|
|
else
|
|
{
|
|
newHeight = maxDisplay.Height;
|
|
newWidth = (int)(newHeight * aspect);
|
|
}
|
|
}
|
|
pictureBoxImagePreview.Size = new Size(newWidth, newHeight);
|
|
}
|
|
else
|
|
{
|
|
pictureBoxImagePreview.Size = new Size(skinPicture.Size.Width, skinPicture.Size.Height);
|
|
}
|
|
labelImageSize.Text = skinPicture.Size.Width.ToString() + "x" + skinPicture.Size.Height.ToString();
|
|
return;
|
|
}
|
|
}
|
|
else if (Path.GetExtension(mf.name) == ".loc")
|
|
{
|
|
buttonEdit.Text = "EDIT LOC";
|
|
buttonEdit.Visible = true;
|
|
}
|
|
else if (Path.GetExtension(mf.name) == ".col")
|
|
{
|
|
buttonEdit.Text = "EDIT COLORS";
|
|
buttonEdit.Visible = true;
|
|
}
|
|
else if (Path.GetFileName(mf.name) == "audio.pck")
|
|
{
|
|
buttonEdit.Text = "EDIT MUSIC CUES";
|
|
buttonEdit.Visible = true;
|
|
}
|
|
else
|
|
{
|
|
buttonEdit.Visible = false;
|
|
//Sets preview image to "NO IMAGE" if selected file data isn't image data
|
|
pictureBoxImagePreview.Image = (Image)Resources.NoImageFound;
|
|
pictureBoxImagePreview.Size = new Size(pictureBoxMaxHeight, pictureBoxMaxHeight);
|
|
labelImageSize.Text = "";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
buttonEdit.Visible = false;
|
|
//Sets preview image to "NO IMAGE" if selected file data isn't image data
|
|
pictureBoxImagePreview.Image = (Image)Resources.NoImageFound;
|
|
pictureBoxImagePreview.Size = new Size(pictureBoxMaxHeight, pictureBoxMaxHeight);
|
|
}
|
|
labelImageSize.Text = "";//Resets image size display if theres no image
|
|
}
|
|
#endregion
|
|
|
|
#region Parses boxes and opens model generator
|
|
public void editModel(PCK.MineFile skin)
|
|
{
|
|
List<object[]> otherData = new List<object[]>();//Creates list for backup data to be added to
|
|
List<object[]> generatedData = new List<object[]>();//Creates list for model data to be added to
|
|
foreach (object[] entry in skin.entries) //object = metadata entry(name:value)
|
|
{
|
|
//parses and sorts
|
|
if (entry[0].ToString() == "BOX")
|
|
{
|
|
generatedData.Add(entry);
|
|
}
|
|
else if (entry[0].ToString() == "OFFSET")
|
|
{
|
|
generatedData.Add(entry);
|
|
}
|
|
else if (entry[0].ToString() != "BOX" && entry[0].ToString() != "OFFSET")
|
|
{
|
|
otherData.Add(entry);
|
|
}
|
|
}
|
|
skin.entries = otherData;
|
|
generateModel generate = new generateModel(generatedData, new PictureBox());
|
|
generate.ShowDialog();//Opens Model Generator Dialog
|
|
//Adds model data
|
|
foreach (object[] entry in generatedData) //object = metadata entry(name:value)
|
|
{
|
|
skin.entries.Add(entry);
|
|
}
|
|
|
|
treeMeta.Nodes.Clear(); //clears minefile metadata treeview
|
|
|
|
comboBox1.Items.Clear(); //clears metacombo(entry name)
|
|
textBox1.Text = ""; //clears metatextbox(entry value)
|
|
|
|
foreach (int type in types.Keys)
|
|
comboBox1.Items.Add(types[type]); //Adds available metadata names from metadatabase to the metacombo
|
|
|
|
//Retrieves metadata for currently selected mineifile and displays it within metatreeview
|
|
foreach (object[] entry in file.entries) //object = metadata entry(name:value)
|
|
{
|
|
object[] strings = (object[])entry;
|
|
TreeNode meta = new TreeNode();
|
|
|
|
foreach (object[] entryy in file.entries)
|
|
meta.Text = (string)strings[0];
|
|
meta.Tag = entry;
|
|
treeMeta.Nodes.Add(meta);
|
|
}
|
|
saved = false;
|
|
}
|
|
#endregion
|
|
|
|
#region extracts pck entry
|
|
private void extractToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
|
|
if(treeViewMain.SelectedNode.Nodes.Count > 0)
|
|
{
|
|
MessageBox.Show("Cannot extract folders!");
|
|
return;
|
|
}
|
|
if (treeViewMain.SelectedNode.Tag is PCK.MineFile)//Makes sure item being extracted is minefile and not folder or null item
|
|
{
|
|
SaveFileDialog exFile = new SaveFileDialog();//extract location
|
|
exFile.FileName = treeViewMain.SelectedNode.Text;
|
|
exFile.Filter = Path.GetExtension(treeViewMain.SelectedNode.Text).Replace(".", "") + " File|*" + Path.GetExtension(treeViewMain.SelectedNode.Text);
|
|
exFile.ShowDialog();
|
|
|
|
string appPath = exFile.FileName;//Chosen file path
|
|
string extractPath = exFile.FileName;
|
|
|
|
if (!String.IsNullOrWhiteSpace(Path.GetDirectoryName(extractPath)))//Makes sure chosen directory isn't null or whitespace AKA makes sure its usable
|
|
{
|
|
File.WriteAllBytes(extractPath, ((PCK.MineFile)treeViewMain.SelectedNode.Tag).data);//extracts minefile data to directory
|
|
|
|
//Generates metadata file in form of txt file if metadata for the file exists
|
|
if (treeViewMain.SelectedNode.Tag.ToString() != "")
|
|
{
|
|
try
|
|
{
|
|
string metaData = "";
|
|
types = currentPCK.types;
|
|
file = (PCK.MineFile)treeViewMain.SelectedNode.Tag;
|
|
|
|
var ms = new MemoryStream(File.ReadAllBytes(extractPath).ToArray());
|
|
|
|
MemoryStream ico = new MemoryStream();
|
|
Bitmap bmp = new Bitmap(Image.FromFile(extractPath));
|
|
bmp.Save(ico, System.Drawing.Imaging.ImageFormat.Png);
|
|
|
|
foreach (object[] entry in file.entries)
|
|
{
|
|
object[] strings = (object[])entry;
|
|
metaData += (string)strings[0] + ":" + (string)strings[1] + Environment.NewLine;
|
|
}
|
|
|
|
File.WriteAllText(extractPath + ".txt", metaData);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
|
|
}
|
|
MessageBox.Show("File Extracted");//Verification that file extraction path was successful
|
|
}
|
|
}
|
|
}
|
|
else if (treeViewMain.SelectedNode != null)
|
|
{
|
|
SaveFileDialog exFile = new SaveFileDialog();//extract location
|
|
exFile.ShowDialog();
|
|
string appPath = exFile.FileName;//Chosen file path
|
|
|
|
foreach (TreeNode item in treeViewMain.SelectedNode.Nodes)
|
|
{
|
|
if (item.Tag is PCK.MineFile)//Makes sure item being extracted is minefile and not folder or null item
|
|
{
|
|
string extractPath = Path.Combine(appPath, ((PCK.MineFile)item.Tag).name);//combines file path with file path & name of minefile being extracted
|
|
|
|
if (!String.IsNullOrWhiteSpace(Path.GetDirectoryName(extractPath)))//Makes sure chosen directory isn't null or whitespace AKA makes sure its usable
|
|
{
|
|
Directory.CreateDirectory(Path.GetDirectoryName(extractPath));//Creates directory variable out of generated/chosen extract path
|
|
File.WriteAllBytes(extractPath, ((PCK.MineFile)item.Tag).data);//extracts minefile data to directory
|
|
|
|
//Generates metadata file in form of txt file if metadata for the file exists
|
|
if (item.Tag.ToString() != "")
|
|
{
|
|
try
|
|
{
|
|
string metaData = "";
|
|
types = currentPCK.types;
|
|
file = mf;
|
|
|
|
var ms = new MemoryStream(File.ReadAllBytes(extractPath).ToArray());
|
|
|
|
MemoryStream ico = new MemoryStream();
|
|
Bitmap bmp = new Bitmap(Image.FromFile(extractPath));
|
|
bmp.Save(ico, System.Drawing.Imaging.ImageFormat.Png);
|
|
|
|
foreach (object[] entry in file.entries)
|
|
{
|
|
object[] strings = (object[])entry;
|
|
metaData += (string)strings[0] + ":" + (string)strings[1] + Environment.NewLine;
|
|
}
|
|
|
|
File.WriteAllText(extractPath + ".txt", metaData);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
|
|
}
|
|
MessageBox.Show("Path Extracted");//Verification that file extraction path was successful
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region saves pck
|
|
private void save(string saveType)
|
|
{
|
|
TreeView saveStructure = new TreeView();//Temporary new treeview to properly store minefiles in writable form
|
|
//structures minefile data based on wether it has parent nodes or not and with its proper minefile data
|
|
foreach (TreeNode item in treeViewMain.Nodes)
|
|
{
|
|
TreeNode add = new TreeNode();
|
|
if (item.Parent != null)
|
|
{
|
|
string itemPath = "";//item path template
|
|
List<TreeNode> path = new List<TreeNode>();//directory template
|
|
GetPathToRoot(treeViewMain.SelectedNode, path);//gets all parents nodes
|
|
//generates minefile directory to properly store in minedata
|
|
foreach (TreeNode dire in path)
|
|
{
|
|
itemPath += dire.Text + "/";
|
|
}
|
|
add.Text = itemPath + item.Text;
|
|
}
|
|
else
|
|
{
|
|
add.Text = item.Text;
|
|
}
|
|
add.Tag = item.Tag;
|
|
saveStructure.Nodes.Add(add);
|
|
add.Remove();
|
|
}
|
|
|
|
//Reassignes each node with its minefile data to make sure everything is synced
|
|
foreach (TreeNode item in saveStructure.Nodes)
|
|
{
|
|
currentPCK.mineFiles[item.Index] = (PCK.MineFile)item.Tag;
|
|
}
|
|
|
|
//Syncs minefile name with nodes name
|
|
for (int i = 0; i < saveStructure.Nodes.Count; i++)
|
|
currentPCK.mineFiles[i].name = saveStructure.Nodes[i].Text;
|
|
|
|
if (saveLocation == appData + @"\templates\UntitledSkinPCK.pck")
|
|
{
|
|
//writes pck data if pck is actually opened
|
|
using (var ofd = new SaveFileDialog())
|
|
{
|
|
ofd.Filter = "PCK (Minecraft Console Package)|*.pck";
|
|
|
|
if (ofd.ShowDialog() == DialogResult.OK)
|
|
{
|
|
try
|
|
{
|
|
Console.WriteLine(currentPCK.IsLittleEndian.ToString() + "--");
|
|
if (LittleEndianCheckBox.Checked)
|
|
{
|
|
byte[] oouput = currentPCK.RebuildVita();
|
|
oouput[0] = 0x03;
|
|
File.WriteAllBytes(ofd.FileName, currentPCK.RebuildVita());
|
|
}
|
|
else
|
|
{
|
|
byte[] oouput = currentPCK.Rebuild();
|
|
File.WriteAllBytes(ofd.FileName, currentPCK.Rebuild());
|
|
}
|
|
saveLocation = ofd.FileName;
|
|
openedPCKS.SelectedTab.Text = Path.GetFileName(ofd.FileName);
|
|
saved = true;
|
|
MessageBox.Show("PCK Saved!");
|
|
PCKFile = Path.GetFileName(ofd.FileName);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
MessageBox.Show("No PCK loaded");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (saveType == "Save As")
|
|
{
|
|
//writes pck data if pck is actually opened
|
|
using (var ofd = new SaveFileDialog())
|
|
{
|
|
ofd.Filter = "PCK (Minecraft Console Package)|*.pck";
|
|
|
|
if (ofd.ShowDialog() == DialogResult.OK)
|
|
{
|
|
try
|
|
{
|
|
Console.WriteLine(currentPCK.IsLittleEndian.ToString() + "--");
|
|
if (LittleEndianCheckBox.Checked)
|
|
{
|
|
byte[] oouput = currentPCK.RebuildVita();
|
|
oouput[0] = 0x03;
|
|
File.WriteAllBytes(ofd.FileName, currentPCK.RebuildVita());
|
|
}
|
|
else
|
|
{
|
|
byte[] oouput = currentPCK.Rebuild();
|
|
File.WriteAllBytes(ofd.FileName, currentPCK.Rebuild());
|
|
}
|
|
saveLocation = ofd.FileName;
|
|
openedPCKS.SelectedTab.Text = Path.GetFileName(ofd.FileName);
|
|
saved = true;
|
|
MessageBox.Show("PCK Saved!");
|
|
}
|
|
catch (Exception)
|
|
{
|
|
MessageBox.Show("No PCK loaded");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (MessageBox.Show("Are you sure you wanna save?", "", MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2) == DialogResult.Yes)
|
|
{
|
|
try
|
|
{
|
|
Console.WriteLine(currentPCK.IsLittleEndian.ToString() + "--");
|
|
if (LittleEndianCheckBox.Checked)
|
|
{
|
|
byte[] oouput = currentPCK.RebuildVita();
|
|
oouput[0] = 0x03;
|
|
File.WriteAllBytes(saveLocation, currentPCK.RebuildVita());
|
|
}
|
|
else
|
|
{
|
|
byte[] oouput = currentPCK.Rebuild();
|
|
File.WriteAllBytes(saveLocation, currentPCK.Rebuild());
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
for (int i = 0; i < saveStructure.Nodes.Count; i++)
|
|
currentPCK.mineFiles[i].name = saveStructure.Nodes[i].Text;
|
|
|
|
using (var ofd = new SaveFileDialog())
|
|
{
|
|
ofd.Filter = "PCK (Minecraft Console Package)|*.pck";
|
|
|
|
if (ofd.ShowDialog() == DialogResult.OK)
|
|
{
|
|
try
|
|
{
|
|
File.WriteAllBytes(ofd.FileName, currentPCK.Rebuild());
|
|
saved = true;
|
|
MessageBox.Show("PCK Saved!");
|
|
}
|
|
catch (Exception)
|
|
{
|
|
MessageBox.Show("No PCK loaded");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
saveStructure.Dispose();//disposes temporarily made treeview
|
|
}
|
|
#endregion
|
|
|
|
#region replaces pck entry with selected file
|
|
private void replaceToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
if (treeViewMain.SelectedNode.Tag is PCK.MineFile)//Makes sure file being replaced is an actual minefile or not null
|
|
{
|
|
PCK.MineFile mf = (PCK.MineFile)treeViewMain.SelectedNode.Tag;//backups minefile data for node
|
|
using (var ofd = new OpenFileDialog())
|
|
{
|
|
if (ofd.ShowDialog() == DialogResult.OK)
|
|
{
|
|
mf.data = File.ReadAllBytes(ofd.FileName);//overwrites minefile data with chosen files data
|
|
mf.filesize = mf.data.Length;//updates file size
|
|
}
|
|
}
|
|
}
|
|
saved = false;
|
|
}
|
|
#endregion
|
|
|
|
#region ignore
|
|
private void treeView1_AfterLabelEdit(object sender, NodeLabelEditEventArgs e)
|
|
{
|
|
//Does not work as intended. Renaming moved to save function
|
|
saved = false;
|
|
}
|
|
#endregion
|
|
|
|
#region deletes pck entry from treeview and pck.minefiles
|
|
private void deleteFileToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
//Removes selected from current pcks minefiles list and nodes
|
|
if (treeViewMain.SelectedNode.Tag is PCK.MineFile)
|
|
{
|
|
PCK.MineFile mf = (PCK.MineFile)treeViewMain.SelectedNode.Tag;
|
|
treeViewMain.Nodes.Remove(treeViewMain.SelectedNode);
|
|
currentPCK.mineFiles.Remove(mf);
|
|
}
|
|
else
|
|
{
|
|
if (MessageBox.Show("Are you sure want to delete this folder? All contents will be deleted", "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
|
|
{
|
|
foreach (TreeNode item in treeViewMain.SelectedNode.Nodes)
|
|
{
|
|
if (item.Tag == null)
|
|
{
|
|
MessageBox.Show("Can't fully delete directory with subdirectories");
|
|
return;
|
|
}
|
|
if (item.Tag is PCK.MineFile)//makes sure selected node is a minefile
|
|
{
|
|
//removes minefile from minefile list
|
|
PCK.MineFile mf = (PCK.MineFile)item.Tag;
|
|
currentPCK.mineFiles.Remove(mf);
|
|
//removes minefile node
|
|
item.Remove();
|
|
}
|
|
}
|
|
treeViewMain.SelectedNode.Remove();
|
|
}
|
|
}
|
|
saved = false;
|
|
}
|
|
#endregion
|
|
|
|
#region renames pck entry from treeview and pck.minefiles
|
|
private void renameFileToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
TreeNode node = treeViewMain.SelectedNode;
|
|
PckStudio.rename diag = new PckStudio.rename(node);
|
|
diag.ShowDialog(this);
|
|
diag.Dispose();//diposes generated metadata adding dialog data
|
|
treeViewMain.SelectedNode.Text = Path.GetFileName(node.Name);
|
|
treeViewToMineFiles(treeViewMain);
|
|
}
|
|
#endregion
|
|
|
|
#region clones pck entry from treeview and pck.minefiles
|
|
private void cloneFileToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
if (treeViewMain.SelectedNode.Tag == null) return;
|
|
|
|
PCK.MineFile mfO = (PCK.MineFile)treeViewMain.SelectedNode.Tag;
|
|
FileInfo mfCO = new FileInfo(mfO.name);
|
|
|
|
PCK.MineFile mf = new PCK.MineFile();//Creates new minefile template
|
|
mf.data = mfO.data;//adds file data to minefile
|
|
mf.filesize = mfO.data.Length;//gets filesize for minefile
|
|
mf.name = Path.GetDirectoryName(mfO.name).Replace("\\", "/") + "/" + Path.GetFileNameWithoutExtension(mfO.name) + "_clone" + mfCO.Extension;//sets minfile name to file name
|
|
if (treeViewMain.SelectedNode.Parent == null && mf.name.StartsWith("/")) mf.name = mf.name.Remove(0, 1);
|
|
mf.entries = mfO.entries;
|
|
mf.type = 0;//sets minefile type to default
|
|
TreeNode add = new TreeNode(Path.GetFileName(mf.name)) { Tag = mf };//creates node for minefile
|
|
|
|
//Gets proper file icon for minefile
|
|
if (Path.GetExtension(add.Text) == ".binka")
|
|
{
|
|
add.ImageIndex = 1;
|
|
add.SelectedImageIndex = 1;
|
|
}
|
|
else if (Path.GetExtension(add.Text) == ".png")
|
|
{
|
|
add.ImageIndex = 2;
|
|
add.SelectedImageIndex = 2;
|
|
}
|
|
else if (Path.GetExtension(add.Text) == ".loc")
|
|
{
|
|
add.ImageIndex = 3;
|
|
add.SelectedImageIndex = 3;
|
|
}
|
|
else if (Path.GetExtension(add.Text) == ".pck")
|
|
{
|
|
add.ImageIndex = 4;
|
|
add.SelectedImageIndex = 4;
|
|
}
|
|
else
|
|
{
|
|
add.ImageIndex = 5;
|
|
add.SelectedImageIndex = 5;
|
|
}
|
|
|
|
currentPCK.mineFiles.Insert(currentPCK.mineFiles.IndexOf(mfO) + 1, mf); //inserts minefile into proper list index
|
|
if (treeViewMain.SelectedNode.Parent == null) treeViewMain.Nodes.Insert(treeViewMain.SelectedNode.Index + 1, add); //adds generated minefile node
|
|
else treeViewMain.SelectedNode.Parent.Nodes.Insert(treeViewMain.SelectedNode.Index + 1, add);//adds generated minefile node to selected folder
|
|
}
|
|
#endregion
|
|
|
|
#region adds file to treeview and pck.minefiles
|
|
private void addFileToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
using (var ofd = new OpenFileDialog())
|
|
{
|
|
if (ofd.ShowDialog() == DialogResult.OK)
|
|
{
|
|
PCK.MineFile mf = new PCK.MineFile();//Creates new minefile template
|
|
mf.data = File.ReadAllBytes(ofd.FileName);//adds file data to minefile
|
|
mf.filesize = mf.data.Length;//gets filesize for minefile
|
|
mf.name = Path.GetFileName(ofd.FileName);//sets minfile name to file name
|
|
mf.type = 0;//sets minefile type to default
|
|
TreeNode add = new TreeNode(mf.name) { Tag = mf };//creates node for minefile
|
|
|
|
//Gets proper file icon for minefile
|
|
if (Path.GetExtension(add.Text) == ".binka")
|
|
{
|
|
add.ImageIndex = 1;
|
|
add.SelectedImageIndex = 1;
|
|
}
|
|
else if (Path.GetExtension(add.Text) == ".png")
|
|
{
|
|
add.ImageIndex = 2;
|
|
add.SelectedImageIndex = 2;
|
|
}
|
|
else if (Path.GetExtension(add.Text) == ".loc")
|
|
{
|
|
add.ImageIndex = 3;
|
|
add.SelectedImageIndex = 3;
|
|
}
|
|
else if (Path.GetExtension(add.Text) == ".pck")
|
|
{
|
|
add.ImageIndex = 4;
|
|
add.SelectedImageIndex = 4;
|
|
}
|
|
else
|
|
{
|
|
add.ImageIndex = 5;
|
|
add.SelectedImageIndex = 5;
|
|
}
|
|
|
|
if (treeViewMain.SelectedNode.Tag == null)//Detects if user selected a folder to add file to
|
|
{
|
|
treeViewMain.SelectedNode.Nodes.Add(add);//adds generated minefile node to selected folder
|
|
currentPCK.mineFiles.Insert(treeViewMain.SelectedNode.Nodes.Count - 1, mf);//inserts minefile into proper list index
|
|
|
|
string itemPath = "";//item path template
|
|
List<TreeNode> path = new List<TreeNode>();//directory template
|
|
GetPathToRoot(treeViewMain.SelectedNode, path);//gets all parents nodes
|
|
//generates minefile directory to properly store in minedata
|
|
foreach (TreeNode dire in path)
|
|
{
|
|
itemPath += dire.Text + "/";
|
|
}
|
|
|
|
currentPCK.mineFiles[treeViewMain.SelectedNode.Nodes.Count - 1].name = itemPath + treeViewMain.SelectedNode.Nodes[treeViewMain.SelectedNode.Nodes.Count - 1].Text;//updates minefile name with directory
|
|
}
|
|
else//adds minefile to root of the pck
|
|
{
|
|
currentPCK.mineFiles.Add(mf);
|
|
treeViewMain.Nodes.Add(add);
|
|
}
|
|
}
|
|
}
|
|
saved = false;
|
|
}
|
|
|
|
|
|
private void GetPathToRoot(TreeNode node, List<TreeNode> path)
|
|
{
|
|
//gets all parents nodes of a file
|
|
if (node == null) return; // previous node was the root.
|
|
else
|
|
{
|
|
path.Insert(0, node);
|
|
GetPathToRoot(node.Parent, path);
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region starts up form to create and add a new skin
|
|
private void createSkinToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
int i = treeViewMain.Nodes.Count - 1;//Gets index of last item in treeview
|
|
int tempIDD;//sets variables for a temporary skin/cape id
|
|
|
|
try
|
|
{
|
|
string tempID = treeViewMain.Nodes[i].Text.Remove(treeViewMain.Nodes[i].Text.Length - 4, 4);//gets id of last skin/cape in treeview if the last item is a skin or cape
|
|
|
|
tempID = tempID.Remove(0, 8);//removes text from id
|
|
|
|
tempIDD = int.Parse(tempID) + 1;//adds to skin/cape id index to presets the next skin/cape id
|
|
}
|
|
catch (Exception)
|
|
{
|
|
tempIDD = 00000000;//sets temporary id to 0 if an id can't be generated off the treeviews last item
|
|
}
|
|
PCK.MineFile mf = mfLoc;//Sets loc minefile
|
|
|
|
try
|
|
{
|
|
l = new LOC(mf.data);//sets loc data
|
|
}
|
|
catch
|
|
{
|
|
//error handling for if pck doesn't have a loc file
|
|
MessageBox.Show("No localization data found.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
return;
|
|
}
|
|
PckStudio.addnewskin add = new PckStudio.addnewskin(currentPCK, treeViewMain, tempIDD.ToString(), l);//Sets dialog data for skin creator
|
|
add.ShowDialog();//opens skin creator
|
|
mf.data = l.Rebuild();//rebuilds loc data
|
|
add.Dispose();//disposes generated skin creator data
|
|
saved = false;
|
|
}
|
|
#endregion
|
|
|
|
#region starts up form to create and add a animated texture
|
|
private void createAnimatedTextureToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
using (var ofd = new OpenFileDialog())
|
|
{
|
|
ofd.Filter = "PNG Files | *.png";
|
|
ofd.Title = "Select a PNG File";
|
|
|
|
if (ofd.ShowDialog() == DialogResult.OK)
|
|
{
|
|
try
|
|
{
|
|
AnimationEditor diag = new AnimationEditor(treeViewMain, ofd.FileName);
|
|
diag.ShowDialog(this);
|
|
diag.Dispose();
|
|
|
|
treeViewToMineFiles(treeViewMain);
|
|
|
|
treeMeta.Nodes.Clear();
|
|
foreach (int type in types.Keys)
|
|
comboBox1.Items.Add(types[type]);
|
|
|
|
//loads all of selected minefiles metadata into metadata treeview
|
|
foreach (object[] entry in file.entries)
|
|
{
|
|
object[] strings = (object[])entry; TreeNode meta = new TreeNode();
|
|
|
|
foreach (object[] entryy in file.entries)
|
|
meta.Text = (string)strings[0];
|
|
meta.Tag = entry;
|
|
treeMeta.Nodes.Add(meta);
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
MessageBox.Show("Invalid animation data.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
saved = false;
|
|
}
|
|
#endregion
|
|
|
|
#region deciphers what happens when certain pck entries are double clicked
|
|
private void treeView1_DoubleClick(object sender, EventArgs e)
|
|
{
|
|
if (treeViewMain.SelectedNode != null && treeViewMain.SelectedNode.Tag != null)
|
|
{
|
|
mf = (PCK.MineFile)treeViewMain.SelectedNode.Tag;
|
|
|
|
//Checks to see if selected minefile is a loc file
|
|
if (Path.GetExtension(mf.name) == ".loc")
|
|
{
|
|
if (treeViewMain.SelectedNode.Tag is PCK.MineFile)
|
|
{
|
|
LOC l;
|
|
try
|
|
{
|
|
l = new LOC(mf.data);
|
|
}
|
|
catch
|
|
{
|
|
MessageBox.Show("No localization data found.", "Error", MessageBoxButtons.OK,
|
|
MessageBoxIcon.Error);
|
|
return;
|
|
}
|
|
(new LOCEditor(l)).ShowDialog();//Opens LOC Editor
|
|
mf.data = l.Rebuild();//Rebuilds loc file with locdata in grid view after closing dialog
|
|
}
|
|
}
|
|
|
|
//Checks to see if selected minefile is an audio file
|
|
if (Path.GetFileName(mf.name) == "audio.pck")
|
|
{
|
|
if (treeViewMain.SelectedNode.Tag is PCK.MineFile)
|
|
{
|
|
try
|
|
{
|
|
PckStudio.Forms.Utilities.AudioEditor diag = new PckStudio.Forms.Utilities.AudioEditor(mf.data, mf);
|
|
diag.ShowDialog(this);
|
|
diag.Dispose();
|
|
}
|
|
catch(Exception ex)
|
|
{
|
|
MessageBox.Show("Error", ex.Message, MessageBoxButtons.OK,
|
|
MessageBoxIcon.Error);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
//Checks to see if selected minefile is a col file
|
|
if (Path.GetExtension(mf.name) == ".col")
|
|
{
|
|
//MessageBox.Show(".COL Editor Coming Soon!");
|
|
|
|
if (treeViewMain.SelectedNode.Tag is PCK.MineFile)
|
|
{
|
|
try
|
|
{
|
|
PckStudio.Forms.Utilities.COLEditor diag = new PckStudio.Forms.Utilities.COLEditor(mf.data, mf);
|
|
diag.ShowDialog(this);
|
|
diag.Dispose();
|
|
}
|
|
catch
|
|
{
|
|
MessageBox.Show("No Color data found.", "Error", MessageBoxButtons.OK,
|
|
MessageBoxIcon.Error);
|
|
return;
|
|
}
|
|
//mf.data = l.Rebuild();//Rebuilds loc file with locdata in grid view after closing dialog
|
|
}
|
|
}
|
|
|
|
//Checks to see if selected minefile is a binka file
|
|
System.Threading.ThreadStart starter;
|
|
|
|
System.Threading.Thread binkam;
|
|
if (Path.GetExtension(mf.name) == ".binka")
|
|
{
|
|
MessageBox.Show(".binka Editor Coming Soon!");
|
|
}
|
|
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region updates combo and text boxes for metadata when a metadata entry is selected
|
|
private void treeMeta_AfterSelect(object sender, TreeViewEventArgs e)
|
|
{
|
|
comboBox1.Items.Clear();//Resets metadata combobox of selectable entry names
|
|
object[] strings = (object[])e.Node.Tag;
|
|
foreach (int type in types.Keys)
|
|
comboBox1.Items.Add(types[type]);//fills combobox with metadata from the main metadatabase
|
|
comboBox1.Text = (string)strings[0];//Sets currently selected metadata type to type selected in selected metadata node
|
|
textBox1.Text = (string)strings[1];//Sets currently selected metadata value to value selected in selected metadata node
|
|
}
|
|
#endregion
|
|
|
|
#region updates metadata when combo option is selected
|
|
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
if (treeMeta.SelectedNode != null)
|
|
{
|
|
//Sets metadata type to new chosen one
|
|
object[] strings = (object[])treeMeta.SelectedNode.Tag;
|
|
strings[0] = comboBox1.Text;
|
|
}
|
|
saved = false;
|
|
}
|
|
#endregion
|
|
|
|
#region updates metadata value when text box value changes
|
|
private void textBox1_TextChanged(object sender, EventArgs e)
|
|
{
|
|
if (treeMeta.SelectedNode != null)
|
|
{
|
|
//sets metadata value to new value
|
|
object[] strings = (object[])treeMeta.SelectedNode.Tag;
|
|
strings[1] = textBox1.Text;
|
|
}
|
|
saved = false;
|
|
}
|
|
#endregion
|
|
|
|
#region deletes metadata entry
|
|
private void deleteEntryToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
if (treeMeta.SelectedNode != null)//Makes sure selected node is a minefile
|
|
{
|
|
object[] temp = (object[])treeMeta.SelectedNode.Tag;
|
|
file.entries.Remove(temp);//removes minefile from minefile list
|
|
treeMeta.Nodes.Remove(treeMeta.SelectedNode);//removes minefile node
|
|
|
|
// treeMeta.Nodes.Clear();//Resets metadata treeview
|
|
}
|
|
saved = false;
|
|
}
|
|
#endregion
|
|
|
|
#region adds metadata entry
|
|
private void addEntryToolStripMenuItem_Click_1(object sender, EventArgs e)
|
|
{
|
|
mf = (PCK.MineFile)treeViewMain.SelectedNode.Tag;//Sets minefile to selected node
|
|
PckStudio.addMeta add = new PckStudio.addMeta(mf, currentPCK);//sets metadata adding dialog
|
|
add.ShowDialog();//displays metadata adding dialog
|
|
add.Dispose();//diposes generated metadata adding dialog data
|
|
|
|
//Sets up combobox for metadata entries from main metadatabase
|
|
treeMeta.Nodes.Clear();
|
|
foreach (int type in types.Keys)
|
|
comboBox1.Items.Add(types[type]);
|
|
|
|
//loads all of selected minefiles metadata into metadata treeview
|
|
foreach (object[] entry in file.entries)
|
|
{
|
|
object[] strings = (object[])entry; TreeNode meta = new TreeNode();
|
|
|
|
foreach (object[] entryy in file.entries)
|
|
meta.Text = (string)strings[0];
|
|
meta.Tag = entry;
|
|
treeMeta.Nodes.Add(meta);
|
|
}
|
|
saved = false;
|
|
}
|
|
#endregion
|
|
|
|
#region moves node up and arranges minefile indexes
|
|
private void moveUpToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
TreeNode move = (TreeNode)treeViewMain.SelectedNode.Clone();
|
|
|
|
if (treeViewMain.SelectedNode.Parent == null)
|
|
{
|
|
if (treeViewMain.SelectedNode.PrevNode == null) return;
|
|
treeViewMain.Nodes.Insert(treeViewMain.SelectedNode.PrevNode.Index, move);
|
|
//removes node because a clone was inserted into its new index
|
|
treeViewMain.SelectedNode.Remove();
|
|
}
|
|
else
|
|
{
|
|
if (treeViewMain.SelectedNode.PrevNode == null) return;
|
|
treeViewMain.SelectedNode.Parent.Nodes.Insert(treeViewMain.SelectedNode.PrevNode.Index, move);
|
|
//removes node because a clone was inserted into its new index
|
|
treeViewMain.SelectedNode.Remove();
|
|
}
|
|
|
|
treeViewToMineFiles(treeViewMain);
|
|
|
|
saved = false;
|
|
}
|
|
#endregion
|
|
|
|
#region moves node down and arranges minefile indexes
|
|
private void moveDownToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
TreeNode move = (TreeNode)treeViewMain.SelectedNode.Clone();
|
|
|
|
if (treeViewMain.SelectedNode.Parent == null)
|
|
{
|
|
if (treeViewMain.SelectedNode.NextNode == null) return;
|
|
treeViewMain.Nodes.Insert(treeViewMain.SelectedNode.NextNode.Index + 1, move);
|
|
//removes node because a clone was inserted into its new index
|
|
treeViewMain.SelectedNode.Remove();
|
|
}
|
|
else
|
|
{
|
|
if (treeViewMain.SelectedNode.NextNode == null) return;
|
|
treeViewMain.SelectedNode.Parent.Nodes.Insert(treeViewMain.SelectedNode.NextNode.Index + 1, move);
|
|
//removes node because a clone was inserted into its new index
|
|
treeViewMain.SelectedNode.Remove();
|
|
}
|
|
|
|
treeViewToMineFiles(treeViewMain);
|
|
|
|
saved = false;
|
|
}
|
|
#endregion
|
|
|
|
#region drag and drop for main tree node
|
|
|
|
public void getChildren(List<TreeNode> Nodes, TreeNode Node)
|
|
{
|
|
foreach (TreeNode thisNode in Node.Nodes)
|
|
{
|
|
Nodes.Add(thisNode);
|
|
getChildren(Nodes, thisNode);
|
|
}
|
|
}
|
|
|
|
public string getFullMineFilePath(TreeNode node)
|
|
{
|
|
try
|
|
{
|
|
string path = Path.GetDirectoryName(node.FullPath);
|
|
string fullNew = path + "/" + Path.GetFileName(node.Text);
|
|
fullNew = fullNew.Replace("\\", "/");
|
|
return fullNew.TrimStart('/');
|
|
}
|
|
catch (System.ArgumentException e)
|
|
{
|
|
return node.Text;
|
|
}
|
|
}
|
|
|
|
public void treeViewToMineFiles(TreeView tree)
|
|
{
|
|
int i = 1;
|
|
List<TreeNode> children = new List<TreeNode>();
|
|
List<PCK.MineFile> newMineFiles = new List<PCK.MineFile>();
|
|
foreach (TreeNode node in tree.Nodes)
|
|
{
|
|
string nodePath = getFullMineFilePath(node);
|
|
|
|
if(node.Tag == null)
|
|
{
|
|
getChildren(children, node);
|
|
foreach (TreeNode child in children)
|
|
{
|
|
string childPath = getFullMineFilePath(child);
|
|
|
|
if(child.Tag != null)
|
|
{
|
|
PCK.MineFile mf = (PCK.MineFile)child.Tag;
|
|
mf.name = childPath;
|
|
if (!newMineFiles.Contains(mf))
|
|
{
|
|
newMineFiles.Add((PCK.MineFile)child.Tag);
|
|
//Console.WriteLine("Minefile " + i + ": " + childPath);
|
|
i++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PCK.MineFile mf = (PCK.MineFile)node.Tag;
|
|
mf.name = nodePath;
|
|
if (!newMineFiles.Contains(mf))
|
|
{
|
|
newMineFiles.Add((PCK.MineFile)node.Tag);
|
|
//Console.WriteLine("Minefile " + i + ": " + nodePath);
|
|
i++;
|
|
}
|
|
}
|
|
}
|
|
currentPCK.mineFiles = newMineFiles;
|
|
}
|
|
|
|
// Most of the code below is modified code from this link: https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.treeview.itemdrag?view=windowsdesktop-6.0
|
|
// - MattNL
|
|
|
|
private void treeViewMain_ItemDrag(object sender, ItemDragEventArgs e)
|
|
{
|
|
// Move the dragged node when the left mouse button is used.
|
|
if (e.Button == MouseButtons.Left)
|
|
{
|
|
DoDragDrop(e.Item, DragDropEffects.Move);
|
|
}
|
|
}
|
|
|
|
// Set the target drop effect to the effect
|
|
// specified in the ItemDrag event handler.
|
|
private void treeViewMain_DragEnter(object sender, DragEventArgs e)
|
|
{
|
|
e.Effect = e.AllowedEffect;
|
|
}
|
|
|
|
// Select the node under the mouse pointer to indicate the
|
|
// expected drop location.
|
|
private void treeViewMain_DragOver(object sender, DragEventArgs e)
|
|
{
|
|
// Retrieve the client coordinates of the mouse position.
|
|
Point targetPoint = treeViewMain.PointToClient(new Point(e.X, e.Y));
|
|
|
|
// Select the node at the mouse position.
|
|
treeViewMain.SelectedNode = treeViewMain.GetNodeAt(targetPoint);
|
|
}
|
|
|
|
private void treeViewMain_DragDrop(object sender, DragEventArgs e)
|
|
{
|
|
// Retrieve the client coordinates of the drop location.
|
|
Point targetPoint = treeViewMain.PointToClient(new Point(e.X, e.Y));
|
|
|
|
// Retrieve the node at the drop location.
|
|
TreeNode targetNode = treeViewMain.GetNodeAt(targetPoint);
|
|
|
|
// Retrieve the node that was dragged.
|
|
TreeNode draggedNode = (TreeNode)e.Data.GetData(typeof(TreeNode));
|
|
|
|
// Confirm that the node at the drop location is not
|
|
// the dragged node or a descendant of the dragged node.
|
|
if (targetNode == null)
|
|
{
|
|
draggedNode.Remove();
|
|
treeViewMain.Nodes.Add(draggedNode);
|
|
}
|
|
else if (!draggedNode.Equals(targetNode) && !ContainsNode(draggedNode, targetNode))
|
|
{
|
|
// If it is a move operation, remove the node from its current
|
|
// location and add it to the node at the drop location.
|
|
|
|
if (e.Effect == DragDropEffects.Move)
|
|
{
|
|
int draggedIndex = draggedNode.Index;
|
|
int targetIndex = targetNode.Index;
|
|
draggedNode.Remove();
|
|
|
|
if (targetNode.Tag == null) // Add to folder
|
|
{
|
|
targetNode.Nodes.Add(draggedNode);
|
|
}
|
|
else // Move file aside
|
|
{
|
|
if (targetNode.Parent != null)
|
|
{
|
|
targetNode.Parent.Nodes.Insert(targetIndex, draggedNode);
|
|
}
|
|
else
|
|
{
|
|
treeViewMain.Nodes.Insert(targetIndex, draggedNode);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Expand the node at the location
|
|
// to show the dropped node.
|
|
targetNode.Expand();
|
|
}
|
|
|
|
treeViewToMineFiles(treeViewMain);
|
|
}
|
|
|
|
// Determine whether one node is a parent
|
|
// or ancestor of a second node.
|
|
private bool ContainsNode(TreeNode node1, TreeNode node2)
|
|
{
|
|
// Check the parent node of the second node.
|
|
if (node2.Parent == null) return false;
|
|
if (node2.Parent.Equals(node1)) return true;
|
|
|
|
// If the parent node is not null or equal to the first node,
|
|
// call the ContainsNode method recursively using the parent of
|
|
// the second node.
|
|
return ContainsNode(node1, node2.Parent);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Loads all pck metadata into a main metadatabase and opens manageable dialog for it
|
|
private void metaToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
try
|
|
{
|
|
PckStudio.meta edit = new PckStudio.meta(currentPCK);
|
|
edit.TopMost = true;
|
|
edit.TopLevel = true;
|
|
edit.Show();
|
|
}
|
|
catch (Exception)
|
|
{
|
|
MessageBox.Show("No PCK Data Loaded");
|
|
}
|
|
saved = false;
|
|
}
|
|
#endregion
|
|
|
|
#region opens presets
|
|
private void addPresetToolStripMenuItem1_Click(object sender, EventArgs e)
|
|
{
|
|
mf = (PCK.MineFile)treeViewMain.SelectedNode.Tag;//Sets selected minefile from node
|
|
PckStudio.presetMeta add = new PckStudio.presetMeta(mf, currentPCK);//sets data for preset adding dialog
|
|
add.ShowDialog();//displays preset adding dialog
|
|
add.Dispose();//disposes generated preset adding data
|
|
|
|
//reloads treemeta data
|
|
treeMeta.Nodes.Clear();
|
|
foreach (int type in types.Keys)
|
|
comboBox1.Items.Add(types[type]);
|
|
|
|
foreach (object[] entry in file.entries)
|
|
{
|
|
object[] strings = (object[])entry;
|
|
TreeNode meta = new TreeNode();
|
|
|
|
foreach (object[] entryy in file.entries)
|
|
meta.Text = (string)strings[0];
|
|
meta.Tag = entry;
|
|
treeMeta.Nodes.Add(meta);
|
|
}
|
|
saved = false;
|
|
}
|
|
#endregion
|
|
|
|
#region loads empty pck template
|
|
private void skinPackToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
//Loads skin pack template
|
|
PCKFile = Path.GetFileName(appData + "\\template\\UntitledSkinPCK.pck");
|
|
openPck(appData + "\\template\\UntitledSkinPCK.pck");
|
|
saveLocation = "";
|
|
saved = false;
|
|
}
|
|
#endregion
|
|
|
|
#region open advanced metadata bulk editing window
|
|
private void advancedMetaAddingToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
if (openedPCKS.Visible == true)
|
|
{
|
|
//opens dialog for bulk minefile editing
|
|
PckStudio.AdvancedOptions advanced = new PckStudio.AdvancedOptions(currentPCK);
|
|
advanced.ShowDialog();
|
|
advanced.Dispose();
|
|
saved = false;
|
|
}
|
|
else if (openedPCKS.Visible == false)
|
|
{
|
|
MessageBox.Show("Open PCK file first!");
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region closes tool
|
|
private void buttonShutdown_Click(object sender, EventArgs e)
|
|
{
|
|
this.Close();//closes PCK Studio
|
|
}
|
|
#endregion
|
|
|
|
#region open program info/credits window
|
|
private void programInfoToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
//open program info dialog
|
|
PckStudio.programInfo info = new PckStudio.programInfo();
|
|
info.ShowDialog();
|
|
info.Dispose();
|
|
}
|
|
#endregion
|
|
|
|
#region checks for updates
|
|
private void Form1_Load(object sender, EventArgs e)
|
|
{
|
|
try
|
|
{
|
|
RPC.SetRPC("825875166574673940", "Sitting alone", "Program by PhoenixARC", "pcklgo", "PCK Studio", "pcklgo");
|
|
timer1.Start();
|
|
timer1.Enabled = true;
|
|
}
|
|
catch
|
|
{
|
|
Console.WriteLine("ERROR WITH RPC");
|
|
}
|
|
try
|
|
{
|
|
label1.Theme = this.Theme;
|
|
labelVersion.Theme = this.Theme;
|
|
label2.Theme = this.Theme;
|
|
label3.Theme = this.Theme;
|
|
labelImageSize.Theme = this.Theme;
|
|
labelImageSize.Text = "";
|
|
labelAmount.Theme = this.Theme;
|
|
labelEntryType.Theme = this.Theme;
|
|
labelEntryData.Theme = this.Theme;
|
|
DBGLabel.Theme = this.Theme;
|
|
label4.Theme = this.Theme;
|
|
label6.Theme = this.Theme;
|
|
label7.Theme = this.Theme;
|
|
label8.Theme = this.Theme;
|
|
label9.Theme = this.Theme;
|
|
label10.Theme = this.Theme;
|
|
label11.Theme = this.Theme;
|
|
ChangeURL.Theme = this.Theme;
|
|
label5.Theme = this.Theme;
|
|
openedPCKS.Theme = this.Theme;
|
|
tabPage1.Theme = this.Theme;
|
|
metroTabControl1.Theme = this.Theme;
|
|
metroTabPage1.Theme = this.Theme;
|
|
LittleEndianCheckBox.Theme = this.Theme;
|
|
|
|
new WebClient().DownloadString(Program.baseurl + ChangeURL.Text);
|
|
basurl = Program.baseurl;
|
|
Console.WriteLine(basurl + ChangeURL.Text);
|
|
}
|
|
catch
|
|
{
|
|
try
|
|
{
|
|
new WebClient().DownloadString(Program.backurl + ChangeURL.Text);
|
|
basurl = Program.backurl;
|
|
Console.WriteLine(basurl + ChangeURL.Text);
|
|
}
|
|
catch
|
|
{
|
|
try
|
|
{
|
|
new WebClient().DownloadString("https://google.com");
|
|
MessageBox.Show("PCK Studio Service is offline, the domain may have changed.\nOpening website");
|
|
Process.Start("https://phoenixarc.github.io/pckstudio.tk/");
|
|
}
|
|
catch
|
|
{
|
|
MessageBox.Show("Could not connect to service, internet may be offline");
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
Directory.CreateDirectory(appData + "\\template");
|
|
if (!File.Exists(appData + "\\template\\UntitledSkinPCK.pck"))
|
|
File.WriteAllBytes(appData + "\\template\\UntitledSkinPCK.pck", Resources.UntitledSkinPCK);
|
|
|
|
|
|
if (isdebug)
|
|
DBGLabel.Visible = true;
|
|
//runs creator spotlight once per day
|
|
//if (!File.Exists(appData + "date.txt"))
|
|
//{
|
|
// File.WriteAllText(appData + "date.txt", DateTime.Now.ToString("MM/dd/yyyy"));
|
|
// creatorSpotlight shoutout = new creatorSpotlight();
|
|
// shoutout.ShowDialog();
|
|
//}
|
|
//else if (DateTime.Now.ToString("MM/dd/yyyy") != File.ReadAllText(appData + "date.txt"))
|
|
//{
|
|
// creatorSpotlight shoutout = new creatorSpotlight();
|
|
// File.WriteAllText(appData + "date.txt", DateTime.Now.ToString("MM/dd/yyyy"));
|
|
// shoutout.ShowDialog();
|
|
//}
|
|
|
|
|
|
//Promo shoutout = new Promo();
|
|
//shoutout.ShowDialog();
|
|
|
|
|
|
//Makes sure appdata exists
|
|
if (!Directory.Exists(appData))
|
|
{
|
|
Directory.CreateDirectory(appData);
|
|
}
|
|
|
|
if (!Directory.Exists(appData + "\\cache\\mods\\"))
|
|
{
|
|
Directory.CreateDirectory(appData + "\\cache\\mods\\");
|
|
}
|
|
|
|
|
|
//Checks to see if program version file exists, and creates one if it doesn't
|
|
//Latest changelog on program start-up
|
|
try
|
|
{
|
|
using (WebClient client = new WebClient())
|
|
{
|
|
if (Classes.Network.Beta)
|
|
{
|
|
if (isdebug)
|
|
File.WriteAllText(appData + "pckStudioChangelog.txt", File.ReadAllText("C:\\WEBSITES\\PCKStudio\\studio\\PCK\\api\\" + ChangeURL.Text.Replace("ChangeLog", "BetaChangeLog"))) ;
|
|
else
|
|
File.WriteAllText(appData + "pckStudioChangelog.txt", client.DownloadString(basurl + ChangeURL.Text.Replace("ChangeLog", "BetaChangeLog")));
|
|
richTextBoxChangelog.Text = File.ReadAllText(appData + "pckStudioChangelog.txt");
|
|
|
|
}
|
|
else
|
|
{
|
|
if (isdebug)
|
|
File.WriteAllText(appData + "pckStudioChangelog.txt", File.ReadAllText("C:\\WEBSITES\\PCKStudio\\studio\\PCK\\api\\" + ChangeURL.Text));
|
|
else
|
|
File.WriteAllText(appData + "pckStudioChangelog.txt", client.DownloadString(basurl + ChangeURL.Text));
|
|
richTextBoxChangelog.Text = File.ReadAllText(appData + "pckStudioChangelog.txt");
|
|
}
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
MessageBox.Show("Could not load changelog");
|
|
}
|
|
|
|
if (!File.Exists(appData + @"\ver.txt"))
|
|
{
|
|
File.WriteAllText(appData + @"\ver.txt", Version);
|
|
}
|
|
try
|
|
{
|
|
Classes.Network.CheckUpdate();
|
|
}
|
|
catch
|
|
{
|
|
MessageBox.Show("Could not load Version Information");
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region deletes pck entires through the del key
|
|
private void treeViewMain_KeyDown(object sender, KeyEventArgs e)
|
|
{
|
|
if (e.KeyData == Keys.Delete)//checks to make sure pressed key was del
|
|
{
|
|
if (treeViewMain.SelectedNode.Tag is PCK.MineFile)//makes sure selected node is a minefile
|
|
{
|
|
//removes minefile from minefile list
|
|
PCK.MineFile mf = (PCK.MineFile)treeViewMain.SelectedNode.Tag;
|
|
currentPCK.mineFiles.Remove(mf);
|
|
//removes minefile node
|
|
treeViewMain.Nodes.Remove(treeViewMain.SelectedNode);
|
|
}
|
|
else
|
|
{
|
|
if (MessageBox.Show("Are you sure want to delete this folder? All contents will be deleted", "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
|
|
{
|
|
foreach (TreeNode item in treeViewMain.SelectedNode.Nodes)
|
|
{
|
|
if (item.Tag == null)
|
|
{
|
|
MessageBox.Show("Can't fully delete directory with subdirectories");
|
|
return;
|
|
}
|
|
if (item.Tag is PCK.MineFile)//makes sure selected node is a minefile
|
|
{
|
|
//removes minefile from minefile list
|
|
PCK.MineFile mf = (PCK.MineFile)item.Tag;
|
|
currentPCK.mineFiles.Remove(mf);
|
|
//removes minefile node
|
|
item.Remove();
|
|
}
|
|
}
|
|
treeViewMain.SelectedNode.Remove();
|
|
}
|
|
}
|
|
}
|
|
saved = false;
|
|
}
|
|
#endregion
|
|
|
|
#region extracts a selected pck without opening the pck
|
|
private void extractToolStripMenuItem1_Click(object sender, EventArgs e)
|
|
{
|
|
try
|
|
{
|
|
//Extracts a chosen pck file to a chosen destincation
|
|
OpenFileDialog ofd = new OpenFileDialog();
|
|
FolderBrowserDialog sfd = new FolderBrowserDialog();
|
|
ofd.CheckFileExists = true;
|
|
ofd.Filter = "PCK (Minecraft Wii U Package)|*.pck";
|
|
|
|
if (ofd.ShowDialog() == DialogResult.OK)
|
|
{
|
|
if (sfd.ShowDialog() == DialogResult.OK)
|
|
{
|
|
foreach (PCK.MineFile mf in new PCK(ofd.FileName).mineFiles)
|
|
{
|
|
foreach (object[] entry in mf.entries)
|
|
{
|
|
if (entry[0].ToString() == "LOCK") // Check for lock on PCK File
|
|
{
|
|
if ((new pckLocked(entry[1].ToString(), correct).ShowDialog() != DialogResult.OK || !correct))
|
|
{
|
|
return; // cancel extraction if password not provided
|
|
}
|
|
}
|
|
}
|
|
System.IO.FileInfo file = new System.IO.FileInfo(sfd.SelectedPath + @"\" + mf.name);
|
|
file.Directory.Create(); // If the directory already exists, this method does nothing.
|
|
File.WriteAllBytes(sfd.SelectedPath + @"\" + mf.name, mf.data); //writes minefile to file
|
|
//attempts to generate reimportable metadata file out of minefiles metadata
|
|
string metaData = "";
|
|
|
|
foreach (object[] entry in mf.entries)
|
|
{
|
|
object[] strings = (object[])entry;
|
|
metaData += (string)strings[0] + ":" + (string)strings[1] + Environment.NewLine;
|
|
}
|
|
|
|
File.WriteAllText(sfd.SelectedPath + @"\" + mf.name + ".txt", metaData);
|
|
}
|
|
}
|
|
}
|
|
} catch (Exception)
|
|
{
|
|
MessageBox.Show("Unsupported PCK");
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region deletes metadata entries through the del key
|
|
private void treeMeta_KeyDown(object sender, KeyEventArgs e)
|
|
{
|
|
if (e.KeyData == Keys.Delete)//makes sure pressed key was del
|
|
{
|
|
if (treeMeta.SelectedNode != null)//makes sure selected node is a minefile
|
|
{
|
|
//removes selected treemeta entry
|
|
object[] temp = (object[])treeMeta.SelectedNode.Tag;
|
|
file.entries.Remove(temp);
|
|
treeMeta.Nodes.Remove(treeMeta.SelectedNode);
|
|
|
|
//reloads treemeta data
|
|
treeMeta.Nodes.Clear();
|
|
foreach (int type in types.Keys)
|
|
comboBox1.Items.Add(types[type]);
|
|
|
|
foreach (object[] entry in file.entries)
|
|
{
|
|
object[] strings = (object[])entry;
|
|
TreeNode meta = new TreeNode();
|
|
|
|
foreach (object[] entryy in file.entries)
|
|
meta.Text = (string)strings[0];
|
|
meta.Tag = entry;
|
|
treeMeta.Nodes.Add(meta);
|
|
}
|
|
}
|
|
}
|
|
saved = false;
|
|
}
|
|
#endregion
|
|
|
|
#region imports a folder of skins to pck
|
|
private void importExtractedSkinsFolder(object sender, EventArgs e)
|
|
{
|
|
FolderBrowserDialog contents = new FolderBrowserDialog();//Creates folder browser instance
|
|
|
|
if (contents.ShowDialog() == DialogResult.OK)
|
|
{
|
|
//checks to make sure selected path exist
|
|
if (!Directory.Exists(contents.SelectedPath))
|
|
{
|
|
MessageBox.Show("Directory Lost");
|
|
return;
|
|
}
|
|
|
|
string filepath = contents.SelectedPath;//sets filepath to selected path
|
|
DirectoryInfo d = new DirectoryInfo(contents.SelectedPath);//sets directory info
|
|
|
|
bool mashupStructure = false;//creates variable to indicate wether current pck skin structure is mashup or regular skin
|
|
int skinsFolder = 0;//temporary index for skins folder for if structure is mashup
|
|
|
|
//checks to see if pck contains a skins folder
|
|
foreach (TreeNode item in treeViewMain.Nodes)
|
|
{
|
|
if (item.Text == "Skins")
|
|
{
|
|
mashupStructure = true;//sets mashup structure to true
|
|
skinsFolder = item.Index;//keeps note of skins folder index
|
|
}
|
|
}
|
|
|
|
//gets all png files in selected path
|
|
foreach (var file in d.GetFiles("*.png"))
|
|
{
|
|
PCK.MineFile mfNew = new PCK.MineFile();//new minefile template
|
|
ListViewItem Import = new ListViewItem();//listviewitem to store temporary data
|
|
Import.Text = file.Name.Remove(file.Name.Length - 4, 4);//gets file name without extension
|
|
mfNew.data = File.ReadAllBytes(contents.SelectedPath + @"\" + file.Name.Remove(file.Name.Length - 4, 4) + ".png");//sets minefile data to image data of current skin
|
|
|
|
TreeNode skin = new TreeNode();//create template treenode for minefile
|
|
|
|
currentPCK.mineFiles.Add(mfNew);//adds new minefile to minefile list for skin
|
|
mfNew.filesize = mfNew.data.Length;//gets filesize of the skin image
|
|
|
|
//Sets minefile directory based on pcks structure/type
|
|
if (mashupStructure == true)
|
|
{
|
|
mfNew.name = "Skins/" + Import.Text + ".png";
|
|
}
|
|
else
|
|
{
|
|
mfNew.name = Import.Text + ".png";
|
|
}
|
|
|
|
//sets minefile type based on wether cape or skin
|
|
if (Import.Text.Remove(7, Import.Text.Length - 7) == "dlccape")
|
|
{
|
|
mfNew.type = 1;
|
|
}
|
|
else if (Import.Text.Remove(7, Import.Text.Length - 7) == "DLCCAPE")
|
|
{
|
|
mfNew.type = 1;
|
|
}
|
|
else
|
|
{
|
|
mfNew.type = 0;
|
|
}
|
|
skin.Text = Import.Text + ".png";//adds file extension to minefile
|
|
skin.Tag = mfNew;//sets nodes minefile data
|
|
|
|
//presest variables for minefile skin data about to be imported
|
|
string entryName = "";
|
|
string entryValue = "";
|
|
string locNameId = "";
|
|
string locName = "";
|
|
string locThemeId = "";
|
|
string locTheme = "";
|
|
bool entryStart = true;//assistant for parcing through metadata file data to import
|
|
int i = 0;
|
|
|
|
foreach (char entry in File.ReadAllText(contents.SelectedPath + @"\" + Import.Text + ".png.txt").ToList())
|
|
{
|
|
//imports current skins metadata from metadata file
|
|
if (entry.ToString() != ":" && entry.ToString() != "\n" && entryStart == true)
|
|
{
|
|
entryName += entry.ToString();
|
|
}
|
|
else if (entry.ToString() != ":" && entry.ToString() != "\n" && entryStart == false)
|
|
{
|
|
entryValue += entry.ToString();
|
|
}
|
|
else if (entry.ToString() == ":" && entryStart == true)
|
|
{
|
|
entryStart = false;
|
|
}
|
|
else
|
|
{
|
|
//adds minefiles metadata and presets loc data for minefile
|
|
object[] ENTRY = { entryName, entryValue };
|
|
mfNew.entries.Add(ENTRY);
|
|
|
|
if (entryName == "DISPLAYNAMEID")
|
|
{
|
|
locNameId = entryValue;
|
|
}
|
|
|
|
if (entryName == "DISPLAYNAME")
|
|
{
|
|
locName = entryValue;
|
|
}
|
|
|
|
if (entryName == "THEMENAMEID")
|
|
{
|
|
locThemeId = entryValue;
|
|
}
|
|
|
|
if (entryName == "THEMENAME")
|
|
{
|
|
locTheme = entryValue;
|
|
}
|
|
|
|
//creates displayname id in loc file
|
|
if (locNameId != "" && locName != "")
|
|
{
|
|
LOC l;
|
|
|
|
try
|
|
{
|
|
l = new LOC(mfLoc.data);
|
|
}
|
|
catch
|
|
{
|
|
MessageBox.Show("No localization data found.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
return;
|
|
}
|
|
|
|
displayId dis = new displayId();
|
|
dis.id = locNameId;
|
|
dis.defaultName = locName;
|
|
|
|
l.ids.names.Add(dis.id);
|
|
|
|
foreach (LOC.Language lo in l.langs)
|
|
lo.names.Add(dis.defaultName);
|
|
mfLoc.data = l.Rebuild();
|
|
locNameId = "";
|
|
locName = "";
|
|
}
|
|
|
|
//creates metadata id in loc file
|
|
if (locThemeId != "" && locTheme != "")
|
|
{
|
|
LOC l;
|
|
|
|
try
|
|
{
|
|
l = new LOC(mfLoc.data);
|
|
}
|
|
catch
|
|
{
|
|
MessageBox.Show("No localization data found.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
return;
|
|
}
|
|
|
|
displayId b = new displayId();
|
|
b.id = locThemeId;
|
|
b.defaultName = locTheme;
|
|
|
|
l.ids.names.Add(b.id);
|
|
|
|
foreach (LOC.Language lo in l.langs)
|
|
lo.names.Add(b.defaultName);
|
|
|
|
mfLoc.data = l.Rebuild();
|
|
locThemeId = "";
|
|
locTheme = "";
|
|
}
|
|
entryName = "";
|
|
entryValue = "";
|
|
entryStart = true;
|
|
}
|
|
}
|
|
//sets file icon
|
|
skin.ImageIndex = 2;
|
|
skin.SelectedImageIndex = 2;
|
|
//Adds new minefile node to a destination based on pcks skin structure type
|
|
if (mashupStructure == true)
|
|
{
|
|
treeViewMain.Nodes[skinsFolder].Nodes.Add(skin);
|
|
}
|
|
else
|
|
{
|
|
treeViewMain.Nodes.Add(skin);
|
|
}
|
|
}
|
|
}
|
|
contents.Dispose();//disposes temporary data
|
|
saved = false;
|
|
}
|
|
#endregion
|
|
|
|
#region imports individual skin to pck
|
|
private void importSkin(object sender, EventArgs e)
|
|
{
|
|
OpenFileDialog contents = new OpenFileDialog();
|
|
contents.Title = "Select Extracted Skin Data File";
|
|
contents.Filter = "Text Files (*.txt)|*.txt";
|
|
|
|
if (contents.ShowDialog() == DialogResult.OK)
|
|
{
|
|
try
|
|
{
|
|
string skinNameImport = System.IO.Path.GetFileName(contents.FileName);//Gets skin name
|
|
PCK.MineFile mfNew = new PCK.MineFile();//new minefile template
|
|
ListViewItem Import = new ListViewItem();//listviewitem to store temporary data
|
|
Import.Text = skinNameImport.Remove(skinNameImport.Length - 4, 4);//gets file name without extension
|
|
mfNew.data = File.ReadAllBytes(contents.FileName.Remove(contents.FileName.Length - 4, 4));//sets minefile data to image data of current skin
|
|
|
|
bool mashupStructure = false;//creates variable to indicate wether current pck skin structure is mashup or regular skin
|
|
int skinsFolder = 0;//temporary index for skins folder for if structure is mashup
|
|
|
|
//checks to see if pck contains a skins folder
|
|
foreach (TreeNode item in treeViewMain.Nodes)
|
|
{
|
|
if (item.Text == "Skins")
|
|
{
|
|
mashupStructure = true;
|
|
skinsFolder = item.Index;
|
|
}
|
|
}
|
|
|
|
TreeNode skin = new TreeNode();//create template treenode for minefile
|
|
|
|
currentPCK.mineFiles.Add(mfNew);//Adds minefile to minefile list
|
|
mfNew.filesize = mfNew.data.Length;//gets and sets minefile filesize
|
|
if (mashupStructure == true)
|
|
{
|
|
mfNew.name = "Skins/" + Import.Text;
|
|
}
|
|
else
|
|
{
|
|
mfNew.name = Import.Text;
|
|
}
|
|
mfNew.type = 0;//sets file type to default
|
|
|
|
skin.Text = Import.Text;//sets nodes minefile name
|
|
skin.Tag = mfNew;//sets nodes minefile data
|
|
|
|
//presest variables for minefile skin data about to be imported
|
|
string entryName = "";
|
|
string entryValue = "";
|
|
string locNameId = "";
|
|
string locName = "";
|
|
string locThemeId = "";
|
|
string locTheme = "";
|
|
bool entryStart = true;//assistant for parcing through metadata file data to import
|
|
int i = 0;
|
|
|
|
foreach (char entry in File.ReadAllText(contents.FileName).ToList())
|
|
{
|
|
//imports current skins metadata from metadata file
|
|
if (entry.ToString() != ":" && entry.ToString() != "\n" && entryStart == true)
|
|
{
|
|
entryName += entry.ToString();
|
|
}
|
|
else if (entry.ToString() != ":" && entry.ToString() != "\n" && entryStart == false)
|
|
{
|
|
entryValue += entry.ToString();
|
|
}
|
|
else if (entry.ToString() == ":" && entryStart == true)
|
|
{
|
|
entryStart = false;
|
|
}
|
|
else
|
|
{
|
|
//adds minefiles metadata and presets loc data for minefile
|
|
object[] ENTRY = { entryName, entryValue };
|
|
mfNew.entries.Add(ENTRY);
|
|
|
|
if (entryName == "DISPLAYNAMEID")
|
|
{
|
|
locNameId = entryValue;
|
|
}
|
|
|
|
if (entryName == "DISPLAYNAME")
|
|
{
|
|
locName = entryValue;
|
|
}
|
|
|
|
if (entryName == "THEMENAMEID")
|
|
{
|
|
locThemeId = entryValue;
|
|
}
|
|
|
|
if (entryName == "THEMENAME")
|
|
{
|
|
locTheme = entryValue;
|
|
}
|
|
|
|
//creates displayname id in loc file
|
|
if (locNameId != "" && locName != "")
|
|
{
|
|
LOC l;
|
|
|
|
try
|
|
{
|
|
l = new LOC(mfLoc.data);
|
|
}
|
|
catch
|
|
{
|
|
MessageBox.Show("No localization data found.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
return;
|
|
}
|
|
|
|
displayId dis = new displayId();
|
|
dis.id = locNameId;
|
|
dis.defaultName = locName;
|
|
|
|
l.ids.names.Add(dis.id);
|
|
|
|
foreach (LOC.Language lo in l.langs)
|
|
lo.names.Add(dis.defaultName);
|
|
mfLoc.data = l.Rebuild();
|
|
locNameId = "";
|
|
locName = "";
|
|
}
|
|
|
|
//creates metadata id in loc file
|
|
if (locThemeId != "" && locTheme != "")
|
|
{
|
|
LOC l;
|
|
|
|
try
|
|
{
|
|
l = new LOC(mfLoc.data);
|
|
}
|
|
catch
|
|
{
|
|
MessageBox.Show("No localization data found.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
return;
|
|
}
|
|
|
|
displayId b = new displayId();
|
|
b.id = locThemeId;
|
|
b.defaultName = locTheme;
|
|
|
|
l.ids.names.Add(b.id);
|
|
|
|
foreach (LOC.Language lo in l.langs)
|
|
lo.names.Add(b.defaultName);
|
|
|
|
mfLoc.data = l.Rebuild();
|
|
locThemeId = "";
|
|
locTheme = "";
|
|
}
|
|
entryName = "";
|
|
entryValue = "";
|
|
entryStart = true;
|
|
}
|
|
}
|
|
//sets file icon
|
|
skin.ImageIndex = 2;
|
|
skin.SelectedImageIndex = 2;
|
|
//Adds new minefile node to a destination based on pcks skin structure type
|
|
if (mashupStructure == true)
|
|
{
|
|
treeViewMain.Nodes[skinsFolder].Nodes.Add(skin);
|
|
}
|
|
else
|
|
{
|
|
treeViewMain.Nodes.Add(skin);
|
|
}
|
|
} catch (Exception)
|
|
{
|
|
MessageBox.Show("Something went wrong");//error handling
|
|
}
|
|
}
|
|
contents.Dispose();//disposes temporary data
|
|
saved = false;
|
|
}
|
|
#endregion
|
|
|
|
#region adds folder/directory entry to pck
|
|
private void folderToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
TreeNode NEW = new TreeNode();
|
|
NEW.ImageIndex = 0;
|
|
NEW.SelectedImageIndex = 0;
|
|
NEW.Text = "New Folder";
|
|
if (treeViewMain.SelectedNode != null && treeViewMain.SelectedNode.Tag == null)
|
|
{
|
|
treeViewMain.SelectedNode.Nodes.Add(NEW);
|
|
}
|
|
else
|
|
{
|
|
treeViewMain.Nodes.Add(NEW);
|
|
}
|
|
saved = false;
|
|
}
|
|
#endregion
|
|
|
|
#region opens pck installation page
|
|
private void installationToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
System.Diagnostics.Process.Start(hosturl + "pckStudio#install");
|
|
}
|
|
#endregion
|
|
|
|
#region opens pck binka tutorial video
|
|
private void binkaConversionToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
System.Diagnostics.Process.Start("https://www.youtube.com/watch?v=v6EYr4zc7rI");
|
|
}
|
|
#endregion
|
|
|
|
#region opens pck donation page
|
|
private void donateToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
}
|
|
#endregion
|
|
|
|
#region opens pck faq page
|
|
private void fAQToolStripMenuItem1_Click(object sender, EventArgs e)
|
|
{
|
|
System.Diagnostics.Process.Start(hosturl + "pckStudio#faq");
|
|
}
|
|
#endregion
|
|
|
|
#region items class for use in bedrock skin conversion
|
|
public class Item
|
|
{
|
|
public string Id { get; set; }
|
|
public string Name { get; set; }
|
|
}
|
|
#endregion
|
|
|
|
#region converts and ports all skins in pck to mc bedrock format
|
|
private void convertToBedrockToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
if (openedPCKS.Visible == true && MessageBox.Show("Convert " + openedPCKS.SelectedTab.Text + " to a Bedrock Edition format?", "Convert", MessageBoxButtons.YesNo, MessageBoxIcon.None) == DialogResult.Yes)
|
|
{
|
|
try
|
|
{
|
|
bool latest = true;
|
|
|
|
string packName = openedPCKS.SelectedTab.Text.Remove(openedPCKS.SelectedTab.Text.Count() - 4, 4);//Determines skin packs name off of pck file name
|
|
|
|
//Lets user choose were to put generated pack
|
|
SaveFileDialog convert = new SaveFileDialog();
|
|
convert.Filter = "PCK (Minecarft Bedrock DLC)|*.mcpack";
|
|
convert.FileName = packName;
|
|
|
|
if (convert.ShowDialog() == DialogResult.OK)
|
|
{
|
|
//creates directory for conversion
|
|
string root = Path.GetDirectoryName(convert.FileName) + "\\" + packName;
|
|
string rootFinal = Path.GetDirectoryName(convert.FileName) + "\\";
|
|
|
|
//creates pack uuid off of the last skin id detected
|
|
string uuid = "99999999";//default
|
|
|
|
//creates list of skin display names
|
|
List<Item> skinDisplayNames = new List<Item>();
|
|
|
|
//MessageBox.Show(root);//debug thingy to make sure filepath is correct
|
|
|
|
//add all skins to a list
|
|
List<PCK.MineFile> skinsList = new List<PCK.MineFile>();
|
|
List<PCK.MineFile> capesList = new List<PCK.MineFile>();
|
|
foreach (PCK.MineFile skin in currentPCK.mineFiles)
|
|
{
|
|
if (skin.name.Count() == 19)
|
|
{
|
|
if (skin.name.Remove(7, skin.name.Count() - 7) == "dlcskin")
|
|
{
|
|
skinsList.Add(skin);
|
|
uuid = skin.name.Remove(12, 7);
|
|
uuid = uuid.Remove(0, 7);
|
|
uuid = "abcdefa" + uuid;
|
|
}
|
|
if (skin.name.Remove(7, skin.name.Count() - 7) == "dlccape")
|
|
{
|
|
capesList.Add(skin);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (skinsList.Count() == 0)
|
|
{
|
|
MessageBox.Show("No skins were found");
|
|
return;
|
|
}
|
|
|
|
Directory.CreateDirectory(root);//Creates directory for skin pack
|
|
Directory.CreateDirectory(root + "/texts");//create directory for skin pack text files
|
|
|
|
//create skins json file
|
|
using (StreamWriter writeSkins = new StreamWriter(root + "/skins.json"))
|
|
{
|
|
writeSkins.WriteLine("{");
|
|
writeSkins.WriteLine(" \"skins\": [");
|
|
|
|
int skinAmount = 0;
|
|
foreach (PCK.MineFile newSkin in skinsList)
|
|
{
|
|
skinAmount += 1;
|
|
string skinName = "skinName";
|
|
string capePath = "";
|
|
bool hasCape = false;
|
|
|
|
foreach (Object[] entry in newSkin.entries)
|
|
{
|
|
if (entry[0].ToString() == "DISPLAYNAME")
|
|
{
|
|
skinName = entry[1].ToString();
|
|
skinDisplayNames.Add(new Item() { Id = newSkin.name.Remove(15, 4), Name = entry[1].ToString() });
|
|
}
|
|
if (entry[0].ToString() == "CAPEPATH")
|
|
{
|
|
hasCape = true;
|
|
capePath = entry[1].ToString();
|
|
}
|
|
}
|
|
|
|
writeSkins.WriteLine(" {");
|
|
writeSkins.WriteLine(" \"localization_name\": " + "\"" + newSkin.name.Remove(15, 4) + "\",");
|
|
|
|
MemoryStream png = new MemoryStream(newSkin.data); //Gets image data from minefile data
|
|
Image skinPicture = Image.FromStream(png); //Constructs image data into image
|
|
if (skinPicture.Height == skinPicture.Width)
|
|
{
|
|
writeSkins.WriteLine(" \"geometry\": \"geometry." + packName + "." + newSkin.name.Remove(15, 4) + "\",");
|
|
}
|
|
writeSkins.WriteLine(" \"texture\": " + "\"" + newSkin.name + "\",");
|
|
if (hasCape == true)
|
|
{
|
|
writeSkins.WriteLine(" \"cape\":" + "\"" + capePath + "\",");
|
|
}
|
|
writeSkins.WriteLine(" \"type\": \"free\"");
|
|
if (skinAmount != skinsList.Count)
|
|
{
|
|
writeSkins.WriteLine(" },");
|
|
}
|
|
else
|
|
{
|
|
writeSkins.WriteLine(" }");
|
|
}
|
|
}
|
|
|
|
writeSkins.WriteLine(" ],");
|
|
writeSkins.WriteLine(" \"serialize_name\": \"" + packName + "\",");
|
|
writeSkins.WriteLine(" \"localization_name\": \"" + packName + "\"");
|
|
writeSkins.WriteLine("}");
|
|
}
|
|
|
|
//Create geometry file
|
|
using (StreamWriter writeSkins = new StreamWriter(root + "/geometry.json"))
|
|
{
|
|
writeSkins.WriteLine("{");
|
|
int newSkinCount = 0;
|
|
foreach (PCK.MineFile newSkin in skinsList)
|
|
{
|
|
|
|
newSkinCount += 1;
|
|
string skinType = "steve";
|
|
MemoryStream png = new MemoryStream(newSkin.data); //Gets image data from minefile data
|
|
Image skinPicture = Image.FromStream(png); //Constructs image data into image
|
|
|
|
if (skinPicture.Height == skinPicture.Width / 2)
|
|
{
|
|
skinType = "64x32";
|
|
continue;
|
|
}
|
|
|
|
double offsetHead = 0;
|
|
double offsetBody = 0;
|
|
double offsetArms = 0;
|
|
double offsetLegs = 0;
|
|
|
|
//creates list of skin model data
|
|
List<Item> modelDataHead = new List<Item>();
|
|
List<Item> modelDataBody = new List<Item>();
|
|
List<Item> modelDataLeftArm = new List<Item>();
|
|
List<Item> modelDataRightArm = new List<Item>();
|
|
List<Item> modelDataLeftLeg = new List<Item>();
|
|
List<Item> modelDataRightLeg = new List<Item>();
|
|
List<Item> modelData = new List<Item>();
|
|
|
|
|
|
if (skinPicture.Height == skinPicture.Width)
|
|
{
|
|
//determines skin type based on image dimensions, existence of BOX tags, and the ANIM value
|
|
foreach (Object[] entry in newSkin.entries)
|
|
{
|
|
if (entry[0].ToString() == "BOX")
|
|
{
|
|
string mClass = "";
|
|
string mData = "";
|
|
foreach (char dCheck in entry[1].ToString())
|
|
{
|
|
if (dCheck.ToString() != " ")
|
|
{
|
|
mClass += dCheck.ToString();
|
|
}
|
|
else
|
|
{
|
|
mData = entry[1].ToString().Remove(0, mClass.Count() + 1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (mClass == "HEAD")
|
|
{
|
|
mClass = "head";
|
|
modelDataHead.Add(new Item() { Id = mClass, Name = mData });
|
|
}
|
|
else if (mClass == "BODY")
|
|
{
|
|
mClass = "body";
|
|
modelDataBody.Add(new Item() { Id = mClass, Name = mData });
|
|
}
|
|
else if (mClass == "ARM0")
|
|
{
|
|
mClass = "rightArm";
|
|
modelDataRightArm.Add(new Item() { Id = mClass, Name = mData });
|
|
}
|
|
else if (mClass == "ARM1")
|
|
{
|
|
mClass = "leftArm";
|
|
modelDataLeftArm.Add(new Item() { Id = mClass, Name = mData });
|
|
}
|
|
else if (mClass == "LEG0")
|
|
{
|
|
mClass = "leftLeg";
|
|
modelDataLeftLeg.Add(new Item() { Id = mClass, Name = mData });
|
|
}
|
|
else if (mClass == "LEG1")
|
|
{
|
|
mClass = "rightLeg";
|
|
modelDataRightLeg.Add(new Item() { Id = mClass, Name = mData });
|
|
}
|
|
}
|
|
|
|
if (entry[0].ToString() == "OFFSET")
|
|
{
|
|
string oClass = "";
|
|
string oData = "";
|
|
foreach (char oCheck in entry[1].ToString())
|
|
{
|
|
oData = entry[1].ToString();
|
|
if (oCheck.ToString() != " ")
|
|
{
|
|
oClass += oCheck.ToString();
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (oClass == "HEAD")
|
|
{
|
|
offsetHead += Double.Parse(oData.Remove(0, 7)) * -1;
|
|
}
|
|
else if (oClass == "BODY")
|
|
{
|
|
offsetBody += Double.Parse(oData.Remove(0, 7)) * -1;
|
|
}
|
|
else if (oClass == "ARM0")
|
|
{
|
|
offsetArms += Double.Parse(oData.Remove(0, 7)) * -1;
|
|
}
|
|
else if (oClass == "LEG0")
|
|
{
|
|
offsetLegs += Double.Parse(oData.Remove(0, 7)) * -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (entry[0].ToString() == "ANIM")
|
|
{
|
|
if (entry[1].ToString() == "0x40000")
|
|
{
|
|
|
|
}
|
|
else if (entry[1].ToString() == "0x80000")
|
|
{
|
|
skinType = "alex";
|
|
}
|
|
}
|
|
}
|
|
|
|
if (modelDataHead.Count + modelDataBody.Count + modelDataLeftArm.Count + modelDataRightArm.Count + modelDataLeftLeg.Count + modelDataRightLeg.Count > 0)
|
|
{
|
|
skinType = "custom";
|
|
}
|
|
}
|
|
|
|
writeSkins.WriteLine(" \"" + "geometry." + packName + "." + newSkin.name.Remove(15, 4) + "\": {");
|
|
|
|
//makes skin model depending on what skin type the skin is
|
|
if (skinType == "custom")
|
|
{
|
|
writeSkins.WriteLine(" \"bones\": [");
|
|
|
|
//Head Data
|
|
writeSkins.WriteLine(" {");
|
|
writeSkins.WriteLine(" \"pivot\": [ 0, 24, 0 ],");
|
|
writeSkins.WriteLine(" \"rotation\": [ 0, 0, 0 ],");
|
|
writeSkins.WriteLine(" \"cubes\": [ ");
|
|
//Creates bones for each head box
|
|
int modelAmount = 0;
|
|
foreach (Item model in modelDataHead)
|
|
{
|
|
modelAmount += 1;
|
|
|
|
string xo = "";
|
|
string yo = "";
|
|
string zo = "";
|
|
string xs = "";
|
|
string ys = "";
|
|
string zs = "";
|
|
string xv = "";
|
|
string yv = "";
|
|
|
|
int spaceCheck = 0;
|
|
|
|
foreach (char value in model.Name.ToString())
|
|
{
|
|
//0X1Y2Z3X4Y5Z6X7Y
|
|
if (value.ToString() != " " && spaceCheck == 0)
|
|
{
|
|
xo += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 1)
|
|
{
|
|
yo += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 2)
|
|
{
|
|
zo += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 3)
|
|
{
|
|
xs += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 4)
|
|
{
|
|
ys += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 5)
|
|
{
|
|
zs += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 6)
|
|
{
|
|
xv += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 7)
|
|
{
|
|
yv += value.ToString();
|
|
}
|
|
else if (value.ToString() == " ")
|
|
{
|
|
spaceCheck += 1;
|
|
}
|
|
}
|
|
|
|
writeSkins.WriteLine(" {");
|
|
try
|
|
{
|
|
writeSkins.WriteLine(" \"origin\": [ " + (Double.Parse(xo)) + ", " + ((Double.Parse(yo) + 0) * -1 + offsetHead + 24 - Double.Parse(ys)) + ", " + (Double.Parse(zo)) + " ],");
|
|
writeSkins.WriteLine(" \"size\": [ " + Double.Parse(xs) + ", " + (Double.Parse(ys)) + ", " + Double.Parse(zs) + " ],");
|
|
writeSkins.WriteLine(" \"uv\": [ " + Double.Parse(xv) + ", " + Double.Parse(yv) + " ],");
|
|
writeSkins.WriteLine(" \"inflate\": 0,");
|
|
writeSkins.WriteLine(" \"mirror\": false");
|
|
}
|
|
catch (Exception)
|
|
{
|
|
MessageBox.Show("A HEAD BOX tag in " + newSkin.name + " has an invalid value!");
|
|
}
|
|
if (modelAmount != modelDataHead.Count)
|
|
{
|
|
writeSkins.WriteLine(" },");
|
|
}
|
|
else
|
|
{
|
|
writeSkins.WriteLine(" }");
|
|
}
|
|
}
|
|
writeSkins.WriteLine(" ],");
|
|
writeSkins.WriteLine(" \"META_BoneType\": \"" + "clothing" + "\",");
|
|
writeSkins.WriteLine(" \"name\": \"" + "head" + "\",");
|
|
writeSkins.WriteLine(" \"parent\":" + " null");
|
|
writeSkins.WriteLine(" },");
|
|
|
|
|
|
//Body Data
|
|
writeSkins.WriteLine(" {");
|
|
writeSkins.WriteLine(" \"pivot\": [ 0, 12, 0 ],");
|
|
writeSkins.WriteLine(" \"rotation\": [ 0, 0, 0 ],");
|
|
writeSkins.WriteLine(" \"cubes\": [ ");
|
|
//Creates bones for each body box
|
|
modelAmount = 0;
|
|
foreach (Item model in modelDataBody)
|
|
{
|
|
modelAmount += 1;
|
|
|
|
string xo = "";
|
|
string yo = "";
|
|
string zo = "";
|
|
string xs = "";
|
|
string ys = "";
|
|
string zs = "";
|
|
string xv = "";
|
|
string yv = "";
|
|
|
|
int spaceCheck = 0;
|
|
|
|
foreach (char value in model.Name.ToString())
|
|
{
|
|
//0X1Y2Z3X4Y5Z6X7Y
|
|
if (value.ToString() != " " && spaceCheck == 0)
|
|
{
|
|
xo += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 1)
|
|
{
|
|
yo += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 2)
|
|
{
|
|
zo += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 3)
|
|
{
|
|
xs += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 4)
|
|
{
|
|
ys += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 5)
|
|
{
|
|
zs += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 6)
|
|
{
|
|
xv += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 7)
|
|
{
|
|
yv += value.ToString();
|
|
}
|
|
else if (value.ToString() == " ")
|
|
{
|
|
spaceCheck += 1;
|
|
}
|
|
}
|
|
writeSkins.WriteLine(" {");
|
|
try
|
|
{
|
|
writeSkins.WriteLine(" \"origin\": [ " + (Double.Parse(xo)) + ", " + ((Double.Parse(yo) + 0) * -1 + offsetBody + 24 - Double.Parse(ys)) + ", " + (Double.Parse(zo)) + " ],");
|
|
writeSkins.WriteLine(" \"size\": [ " + Double.Parse(xs) + ", " + Double.Parse(ys) + ", " + Double.Parse(zs) + " ],");
|
|
writeSkins.WriteLine(" \"uv\": [ " + Double.Parse(xv) + ", " + Double.Parse(yv) + " ],");
|
|
writeSkins.WriteLine(" \"inflate\": 0,");
|
|
writeSkins.WriteLine(" \"mirror\": false");
|
|
}
|
|
catch (Exception)
|
|
{
|
|
MessageBox.Show("A BODY BOX tag in " + newSkin.name + " has an invalid value!");
|
|
}
|
|
if (modelAmount != modelDataBody.Count)
|
|
{
|
|
writeSkins.WriteLine(" },");
|
|
}
|
|
else
|
|
{
|
|
writeSkins.WriteLine(" }");
|
|
}
|
|
}
|
|
writeSkins.WriteLine(" ],");
|
|
writeSkins.WriteLine(" \"META_BoneType\": \"" + "base" + "\",");
|
|
writeSkins.WriteLine(" \"name\": \"" + "body" + "\",");
|
|
writeSkins.WriteLine(" \"parent\":" + " null");
|
|
writeSkins.WriteLine(" },");
|
|
|
|
|
|
//LeftArm Data
|
|
writeSkins.WriteLine(" {");
|
|
writeSkins.WriteLine(" \"pivot\": [ 5, 22, 0 ],");
|
|
writeSkins.WriteLine(" \"rotation\": [ 0, 0, 0 ],");
|
|
writeSkins.WriteLine(" \"cubes\": [ ");
|
|
//Creates bones for each arm1 box
|
|
modelAmount = 0;
|
|
foreach (Item model in modelDataLeftArm)
|
|
{
|
|
modelAmount += 1;
|
|
|
|
string xo = "";
|
|
string yo = "";
|
|
string zo = "";
|
|
string xs = "";
|
|
string ys = "";
|
|
string zs = "";
|
|
string xv = "";
|
|
string yv = "";
|
|
|
|
int spaceCheck = 0;
|
|
|
|
foreach (char value in model.Name.ToString())
|
|
{
|
|
//0X1Y2Z3X4Y5Z6X7Y
|
|
if (value.ToString() != " " && spaceCheck == 0)
|
|
{
|
|
xo += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 1)
|
|
{
|
|
yo += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 2)
|
|
{
|
|
zo += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 3)
|
|
{
|
|
xs += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 4)
|
|
{
|
|
ys += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 5)
|
|
{
|
|
zs += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 6)
|
|
{
|
|
xv += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 7)
|
|
{
|
|
yv += value.ToString();
|
|
}
|
|
else if (value.ToString() == " ")
|
|
{
|
|
spaceCheck += 1;
|
|
}
|
|
}
|
|
writeSkins.WriteLine(" {");
|
|
try
|
|
{
|
|
writeSkins.WriteLine(" \"origin\": [ " + (Double.Parse(xo) + 5) + ", " + ((Double.Parse(yo)) * -1 + offsetArms + 22 - Double.Parse(ys)) + ", " + (Double.Parse(zo)) + " ],");
|
|
writeSkins.WriteLine(" \"size\": [ " + Double.Parse(xs) + ", " + Double.Parse(ys) + ", " + Double.Parse(zs) + " ],");
|
|
writeSkins.WriteLine(" \"uv\": [ " + Double.Parse(xv) + ", " + Double.Parse(yv) + " ],");
|
|
writeSkins.WriteLine(" \"inflate\": 0,");
|
|
writeSkins.WriteLine(" \"mirror\": false");
|
|
}
|
|
catch (Exception)
|
|
{
|
|
MessageBox.Show("A ARM0 BOX tag in " + newSkin.name + " has an invalid value!");
|
|
}
|
|
if (modelAmount != modelDataLeftArm.Count)
|
|
{
|
|
writeSkins.WriteLine(" },");
|
|
}
|
|
else
|
|
{
|
|
writeSkins.WriteLine(" }");
|
|
}
|
|
}
|
|
writeSkins.WriteLine(" ],");
|
|
writeSkins.WriteLine(" \"META_BoneType\": \"" + "base" + "\",");
|
|
writeSkins.WriteLine(" \"name\": \"" + "leftArm" + "\",");
|
|
writeSkins.WriteLine(" \"parent\":" + " null");
|
|
writeSkins.WriteLine(" },");
|
|
|
|
//RightArm Data
|
|
writeSkins.WriteLine(" {");
|
|
writeSkins.WriteLine(" \"pivot\": [ -5, 22, 0 ],");
|
|
writeSkins.WriteLine(" \"rotation\": [ 0, 0, 0 ],");
|
|
writeSkins.WriteLine(" \"cubes\": [ ");
|
|
//Creates bones for each arm0 box
|
|
modelAmount = 0;
|
|
foreach (Item model in modelDataRightArm)
|
|
{
|
|
modelAmount += 1;
|
|
|
|
string xo = "";
|
|
string yo = "";
|
|
string zo = "";
|
|
string xs = "";
|
|
string ys = "";
|
|
string zs = "";
|
|
string xv = "";
|
|
string yv = "";
|
|
|
|
int spaceCheck = 0;
|
|
|
|
foreach (char value in model.Name.ToString())
|
|
{
|
|
//0X1Y2Z3X4Y5Z6X7Y
|
|
if (value.ToString() != " " && spaceCheck == 0)
|
|
{
|
|
xo += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 1)
|
|
{
|
|
yo += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 2)
|
|
{
|
|
zo += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 3)
|
|
{
|
|
xs += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 4)
|
|
{
|
|
ys += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 5)
|
|
{
|
|
zs += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 6)
|
|
{
|
|
xv += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 7)
|
|
{
|
|
yv += value.ToString();
|
|
}
|
|
else if (value.ToString() == " ")
|
|
{
|
|
spaceCheck += 1;
|
|
}
|
|
}
|
|
writeSkins.WriteLine(" {");
|
|
try
|
|
{
|
|
writeSkins.WriteLine(" \"origin\": [ " + (Double.Parse(xo) - 5) + ", " + ((Double.Parse(yo)) * -1 + offsetArms + 22 - Double.Parse(ys)) + ", " + (Double.Parse(zo)) + " ],");
|
|
writeSkins.WriteLine(" \"size\": [ " + Double.Parse(xs) + ", " + Double.Parse(ys) + ", " + Double.Parse(zs) + " ],");
|
|
writeSkins.WriteLine(" \"uv\": [ " + Double.Parse(xv) + ", " + Double.Parse(yv) + " ],");
|
|
writeSkins.WriteLine(" \"inflate\": 0,");
|
|
writeSkins.WriteLine(" \"mirror\": false");
|
|
}
|
|
catch (Exception)
|
|
{
|
|
MessageBox.Show("A ARM1 BOX tag in " + newSkin.name + " has an invalid value!");
|
|
}
|
|
if (modelAmount != modelDataRightArm.Count)
|
|
{
|
|
writeSkins.WriteLine(" },");
|
|
}
|
|
else
|
|
{
|
|
writeSkins.WriteLine(" }");
|
|
}
|
|
}
|
|
writeSkins.WriteLine(" ],");
|
|
writeSkins.WriteLine(" \"META_BoneType\": \"" + "base" + "\",");
|
|
writeSkins.WriteLine(" \"name\": \"" + "rightArm" + "\",");
|
|
writeSkins.WriteLine(" \"parent\":" + " null");
|
|
writeSkins.WriteLine(" },");
|
|
|
|
//LeftLeg Data
|
|
writeSkins.WriteLine(" {");
|
|
writeSkins.WriteLine(" \"pivot\": [ 1.9, 12, 0 ],");
|
|
writeSkins.WriteLine(" \"rotation\": [ 0, 0, 0 ],");
|
|
writeSkins.WriteLine(" \"cubes\": [ ");
|
|
//Creates bones for each leg1 box
|
|
modelAmount = 0;
|
|
foreach (Item model in modelDataLeftLeg)
|
|
{
|
|
modelAmount += 1;
|
|
|
|
string xo = "";
|
|
string yo = "";
|
|
string zo = "";
|
|
string xs = "";
|
|
string ys = "";
|
|
string zs = "";
|
|
string xv = "";
|
|
string yv = "";
|
|
|
|
int spaceCheck = 0;
|
|
|
|
foreach (char value in model.Name.ToString())
|
|
{
|
|
//0X1Y2Z3X4Y5Z6X7Y
|
|
if (value.ToString() != " " && spaceCheck == 0)
|
|
{
|
|
xo += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 1)
|
|
{
|
|
yo += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 2)
|
|
{
|
|
zo += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 3)
|
|
{
|
|
xs += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 4)
|
|
{
|
|
ys += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 5)
|
|
{
|
|
zs += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 6)
|
|
{
|
|
xv += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 7)
|
|
{
|
|
yv += value.ToString();
|
|
}
|
|
else if (value.ToString() == " ")
|
|
{
|
|
spaceCheck += 1;
|
|
}
|
|
}
|
|
writeSkins.WriteLine(" {");
|
|
try
|
|
{
|
|
writeSkins.WriteLine(" \"origin\": [ " + (Double.Parse(xo) - 1.9) + ", " + ((Double.Parse(yo)) * -1 + offsetLegs + 12 - Double.Parse(ys)) + ", " + (Double.Parse(zo)) + " ],");
|
|
writeSkins.WriteLine(" \"size\": [ " + Double.Parse(xs) + ", " + Double.Parse(ys) + ", " + Double.Parse(zs) + " ],");
|
|
writeSkins.WriteLine(" \"uv\": [ " + Double.Parse(xv) + ", " + Double.Parse(yv) + " ],");
|
|
writeSkins.WriteLine(" \"inflate\": 0,");
|
|
writeSkins.WriteLine(" \"mirror\": false");
|
|
}
|
|
catch (Exception)
|
|
{
|
|
MessageBox.Show("A LEG1 BOX tag in " + newSkin.name + " has an invalid value!");
|
|
}
|
|
if (modelAmount != modelDataLeftLeg.Count)
|
|
{
|
|
writeSkins.WriteLine(" },");
|
|
}
|
|
else
|
|
{
|
|
writeSkins.WriteLine(" }");
|
|
}
|
|
}
|
|
writeSkins.WriteLine(" ],");
|
|
writeSkins.WriteLine(" \"META_BoneType\": \"" + "base" + "\",");
|
|
writeSkins.WriteLine(" \"name\": \"" + "leftLeg" + "\",");
|
|
writeSkins.WriteLine(" \"parent\":" + " null");
|
|
writeSkins.WriteLine(" },");
|
|
|
|
//RightLeg Data
|
|
writeSkins.WriteLine(" {");
|
|
writeSkins.WriteLine(" \"pivot\": [ -1.9, 12, 0 ],");
|
|
writeSkins.WriteLine(" \"rotation\": [ 0, 0, 0 ],");
|
|
writeSkins.WriteLine(" \"cubes\": [ ");
|
|
//Creates bones for each leg0 box
|
|
modelAmount = 0;
|
|
foreach (Item model in modelDataRightLeg)
|
|
{
|
|
modelAmount += 1;
|
|
|
|
string xo = "";
|
|
string yo = "";
|
|
string zo = "";
|
|
string xs = "";
|
|
string ys = "";
|
|
string zs = "";
|
|
string xv = "";
|
|
string yv = "";
|
|
|
|
int spaceCheck = 0;
|
|
|
|
foreach (char value in model.Name.ToString())
|
|
{
|
|
//0X1Y2Z3X4Y5Z6X7Y
|
|
if (value.ToString() != " " && spaceCheck == 0)
|
|
{
|
|
xo += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 1)
|
|
{
|
|
yo += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 2)
|
|
{
|
|
zo += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 3)
|
|
{
|
|
xs += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 4)
|
|
{
|
|
ys += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 5)
|
|
{
|
|
zs += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 6)
|
|
{
|
|
xv += value.ToString();
|
|
}
|
|
else if (value.ToString() != " " && spaceCheck == 7)
|
|
{
|
|
yv += value.ToString();
|
|
}
|
|
else if (value.ToString() == " ")
|
|
{
|
|
spaceCheck += 1;
|
|
}
|
|
}
|
|
writeSkins.WriteLine(" {");
|
|
try
|
|
{
|
|
writeSkins.WriteLine(" \"origin\": [ " + (Double.Parse(xo) + 1.9) + ", " + ((Double.Parse(yo)) * -1 + offsetLegs + 12 - Double.Parse(ys)) + ", " + (Double.Parse(zo)) + " ],");
|
|
writeSkins.WriteLine(" \"size\": [ " + Double.Parse(xs) + ", " + Double.Parse(ys) + ", " + Double.Parse(zs) + " ],");
|
|
writeSkins.WriteLine(" \"uv\": [ " + Double.Parse(xv) + ", " + Double.Parse(yv) + " ],");
|
|
writeSkins.WriteLine(" \"inflate\": 0,");
|
|
writeSkins.WriteLine(" \"mirror\": false");
|
|
}
|
|
catch (Exception)
|
|
{
|
|
MessageBox.Show("A LEG0 BOX tag in " + newSkin.name + " has an invalid value!");
|
|
}
|
|
if (modelAmount != modelDataRightLeg.Count)
|
|
{
|
|
writeSkins.WriteLine(" },");
|
|
}
|
|
else
|
|
{
|
|
writeSkins.WriteLine(" }");
|
|
}
|
|
}
|
|
writeSkins.WriteLine(" ],");
|
|
writeSkins.WriteLine(" \"META_BoneType\": \"" + "base" + "\",");
|
|
writeSkins.WriteLine(" \"name\": \"" + "rightLeg" + "\",");
|
|
writeSkins.WriteLine(" \"parent\":" + " null");
|
|
writeSkins.WriteLine(" }");
|
|
writeSkins.WriteLine(" ],");
|
|
}
|
|
else if (skinType == "64x32")
|
|
{
|
|
writeSkins.Write(" \"bones\": [ ],");
|
|
}
|
|
else if (skinType == "steve")
|
|
{
|
|
writeSkins.Write(" \"bones\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 0, 24, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"origin\": [ -4, 12, -2 ], " + Environment.NewLine + " " + Environment.NewLine + " \"size\": [ 8, 12, 4 ], " + Environment.NewLine + " " + Environment.NewLine + " \"uv\": [ 16, 16 ], " + Environment.NewLine + " " + Environment.NewLine + " \"inflate\": 0, " + Environment.NewLine + " " + Environment.NewLine + " \"mirror\": false " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"base\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"body\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": null " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 0, 24, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"origin\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"size\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"uv\": [ 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"inflate\": 0, " + Environment.NewLine + " " + Environment.NewLine + " \"mirror\": false " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"armor\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"bodyArmor\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"body\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 0, 12, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"origin\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"size\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"uv\": [ 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"inflate\": 0, " + Environment.NewLine + " " + Environment.NewLine + " \"mirror\": false " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"armor\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"belt\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"body\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 0, 24, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"origin\": [ -4, 24, -4 ], " + Environment.NewLine + " " + Environment.NewLine + " \"size\": [ 8, 8, 8 ], " + Environment.NewLine + " " + Environment.NewLine + " \"uv\": [ 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"inflate\": 0, " + Environment.NewLine + " " + Environment.NewLine + " \"mirror\": false " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"base\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"head\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": null " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 0, 24, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"origin\": [ -4, 24, -4 ], " + Environment.NewLine + " " + Environment.NewLine + " \"size\": [ 8, 8, 8 ], " + Environment.NewLine + " " + Environment.NewLine + " \"uv\": [ 32, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"inflate\": 0.5, " + Environment.NewLine + " " + Environment.NewLine + " \"mirror\": false " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"clothing\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"hat\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"head\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 0, 24, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"origin\": [ 0, 24, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"size\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"uv\": [ 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"inflate\": 0, " + Environment.NewLine + " " + Environment.NewLine + " \"mirror\": false " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"armor\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"helmet\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"head\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 5, 22, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"origin\": [ 4, 12, -2 ], " + Environment.NewLine + " " + Environment.NewLine + " \"size\": [ 4, 12, 4 ], " + Environment.NewLine + " " + Environment.NewLine + " \"uv\": [ 32, 48 ], " + Environment.NewLine + " " + Environment.NewLine + " \"inflate\": 0, " + Environment.NewLine + " " + Environment.NewLine + " \"mirror\": false " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"base\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"leftArm\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": null " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ -5, 22, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"origin\": [ -8, 12, -2 ], " + Environment.NewLine + " " + Environment.NewLine + " \"size\": [ 4, 12, 4 ], " + Environment.NewLine + " " + Environment.NewLine + " \"uv\": [ 40, 16 ], " + Environment.NewLine + " " + Environment.NewLine + " \"inflate\": 0, " + Environment.NewLine + " " + Environment.NewLine + " \"mirror\": false " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"base\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"rightArm\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": null " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 5, 22, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"origin\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"size\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"uv\": [ 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"inflate\": 0, " + Environment.NewLine + " " + Environment.NewLine + " \"mirror\": false " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"armor\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"leftArmArmor\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"leftArm\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ -5, 22, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"origin\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"size\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"uv\": [ 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"inflate\": 0, " + Environment.NewLine + " " + Environment.NewLine + " \"mirror\": false " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"armor\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"rightArmArmor\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"rightArm\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 5, 22, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"origin\": [ 4, 12, -2 ], " + Environment.NewLine + " " + Environment.NewLine + " \"size\": [ 4, 12, 4 ], " + Environment.NewLine + " " + Environment.NewLine + " \"uv\": [ 48, 48 ], " + Environment.NewLine + " " + Environment.NewLine + " \"inflate\": 0.25, " + Environment.NewLine + " " + Environment.NewLine + " \"mirror\": false " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"clothing\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"leftSleeve\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"leftArm\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ -5, 22, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"origin\": [ -8, 12, -2 ], " + Environment.NewLine + " " + Environment.NewLine + " \"size\": [ 4, 12, 4 ], " + Environment.NewLine + " " + Environment.NewLine + " \"uv\": [ 40, 32 ], " + Environment.NewLine + " " + Environment.NewLine + " \"inflate\": 0.25, " + Environment.NewLine + " " + Environment.NewLine + " \"mirror\": false " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"clothing\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"rightSleeve\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"rightArm\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 1.9, 12, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"origin\": [ -0.1, 0, -2 ], " + Environment.NewLine + " " + Environment.NewLine + " \"size\": [ 4, 12, 4 ], " + Environment.NewLine + " " + Environment.NewLine + " \"uv\": [ 16, 48 ], " + Environment.NewLine + " " + Environment.NewLine + " \"inflate\": 0, " + Environment.NewLine + " " + Environment.NewLine + " \"mirror\": false " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"base\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"leftLeg\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": null " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ -1.9, 12, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"origin\": [ -3.9, 0, -2 ], " + Environment.NewLine + " " + Environment.NewLine + " \"size\": [ 4, 12, 4 ], " + Environment.NewLine + " " + Environment.NewLine + " \"uv\": [ 0, 16 ], " + Environment.NewLine + " " + Environment.NewLine + " \"inflate\": 0, " + Environment.NewLine + " " + Environment.NewLine + " \"mirror\": false " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"base\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"rightLeg\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": null " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 1.9, 12, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"origin\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"size\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"uv\": [ 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"inflate\": 0, " + Environment.NewLine + " " + Environment.NewLine + " \"mirror\": false " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"armor\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"leftLegging\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"leftLeg\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ -1.9, 12, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"origin\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"size\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"uv\": [ 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"inflate\": 0, " + Environment.NewLine + " " + Environment.NewLine + " \"mirror\": false " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"armor\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"rightLegging\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"rightLeg\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 1.9, 12, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"origin\": [ -0.1, 0, -2 ], " + Environment.NewLine + " " + Environment.NewLine + " \"size\": [ 4, 12, 4 ], " + Environment.NewLine + " " + Environment.NewLine + " \"uv\": [ 0, 48 ], " + Environment.NewLine + " " + Environment.NewLine + " \"inflate\": 0.25, " + Environment.NewLine + " " + Environment.NewLine + " \"mirror\": false " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"clothing\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"leftPants\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"leftLeg\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ -1.9, 12, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"origin\": [ -3.9, 0, -2 ], " + Environment.NewLine + " " + Environment.NewLine + " \"size\": [ 4, 12, 4 ], " + Environment.NewLine + " " + Environment.NewLine + " \"uv\": [ 0, 32 ], " + Environment.NewLine + " " + Environment.NewLine + " \"inflate\": 0.25, " + Environment.NewLine + " " + Environment.NewLine + " \"mirror\": false " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"clothing\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"rightPants\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"rightLeg\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 0, 24, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"origin\": [ -4, 12, -2 ], " + Environment.NewLine + " " + Environment.NewLine + " \"size\": [ 8, 12, 4 ], " + Environment.NewLine + " " + Environment.NewLine + " \"uv\": [ 16, 32 ], " + Environment.NewLine + " " + Environment.NewLine + " \"inflate\": 0.25, " + Environment.NewLine + " " + Environment.NewLine + " \"mirror\": false " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"clothing\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"jacket\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"body\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 0, 24, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"armor_offset\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"helmetArmorOffset\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"head\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 0, 24, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"armor_offset\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"bodyArmorOffset\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"body\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ -5, 22, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"armor_offset\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"rightArmArmorOffset\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"rightArm\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 5, 22, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"armor_offset\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"leftArmArmorOffset\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"leftArm\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 0, 12, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"armor_offset\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"waist\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"body\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ -1.9, 12, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"armor_offset\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"rightLegArmorOffset\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"rightLeg\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 1.9, 12, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"armor_offset\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"leftLegArmorOffset\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"leftLeg\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ -1.9, 12, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"armor_offset\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"rightBootArmorOffset\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"rightLeg\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 1.9, 12, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"armor_offset\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"leftBootArmorOffset\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"leftLeg\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ -6, 15, 1 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"item\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"rightItem\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"rightArm\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 6, 15, 1 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"item\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"leftItem\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"leftArm\" " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ],");
|
|
}
|
|
else if (skinType == "alex")
|
|
{
|
|
writeSkins.Write(" \"bones\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 0, 24, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"origin\": [ -4, 12, -2 ], " + Environment.NewLine + " " + Environment.NewLine + " \"size\": [ 8, 12, 4 ], " + Environment.NewLine + " " + Environment.NewLine + " \"uv\": [ 16, 16 ], " + Environment.NewLine + " " + Environment.NewLine + " \"inflate\": 0, " + Environment.NewLine + " " + Environment.NewLine + " \"mirror\": false " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"base\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"body\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": null " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 0, 24, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"origin\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"size\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"uv\": [ 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"inflate\": 0, " + Environment.NewLine + " " + Environment.NewLine + " \"mirror\": false " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"armor\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"bodyArmor\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"body\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 0, 12, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"origin\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"size\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"uv\": [ 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"inflate\": 0, " + Environment.NewLine + " " + Environment.NewLine + " \"mirror\": false " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"armor\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"belt\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"body\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 0, 24, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"origin\": [ -4, 24, -4 ], " + Environment.NewLine + " " + Environment.NewLine + " \"size\": [ 8, 8, 8 ], " + Environment.NewLine + " " + Environment.NewLine + " \"uv\": [ 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"inflate\": 0, " + Environment.NewLine + " " + Environment.NewLine + " \"mirror\": false " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"base\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"head\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": null " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 0, 24, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"origin\": [ -4, 24, -4 ], " + Environment.NewLine + " " + Environment.NewLine + " \"size\": [ 8, 8, 8 ], " + Environment.NewLine + " " + Environment.NewLine + " \"uv\": [ 32, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"inflate\": 0.5, " + Environment.NewLine + " " + Environment.NewLine + " \"mirror\": false " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"clothing\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"hat\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"head\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 0, 24, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"origin\": [ 0, 24, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"size\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"uv\": [ 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"inflate\": 0, " + Environment.NewLine + " " + Environment.NewLine + " \"mirror\": false " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"armor\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"helmet\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"head\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 5, 21.5, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"origin\": [ 4, 11.5, -2 ], " + Environment.NewLine + " " + Environment.NewLine + " \"size\": [ 3, 12, 4 ], " + Environment.NewLine + " " + Environment.NewLine + " \"uv\": [ 32, 48 ], " + Environment.NewLine + " " + Environment.NewLine + " \"inflate\": 0, " + Environment.NewLine + " " + Environment.NewLine + " \"mirror\": false " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"base\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"leftArm\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": null " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ -5, 21.5, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"origin\": [ -7, 11.5, -2 ], " + Environment.NewLine + " " + Environment.NewLine + " \"size\": [ 3, 12, 4 ], " + Environment.NewLine + " " + Environment.NewLine + " \"uv\": [ 40, 16 ], " + Environment.NewLine + " " + Environment.NewLine + " \"inflate\": 0, " + Environment.NewLine + " " + Environment.NewLine + " \"mirror\": false " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"base\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"rightArm\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": null " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 5, 21.5, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"origin\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"size\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"uv\": [ 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"inflate\": 0, " + Environment.NewLine + " " + Environment.NewLine + " \"mirror\": false " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"armor\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"leftArmArmor\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"leftArm\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ -5, 21.5, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"origin\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"size\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"uv\": [ 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"inflate\": 0, " + Environment.NewLine + " " + Environment.NewLine + " \"mirror\": false " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"armor\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"rightArmArmor\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"rightArm\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 5, 21.5, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"origin\": [ 4, 11.5, -2 ], " + Environment.NewLine + " " + Environment.NewLine + " \"size\": [ 3, 12, 4 ], " + Environment.NewLine + " " + Environment.NewLine + " \"uv\": [ 48, 48 ], " + Environment.NewLine + " " + Environment.NewLine + " \"inflate\": 0.25, " + Environment.NewLine + " " + Environment.NewLine + " \"mirror\": false " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"clothing\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"leftSleeve\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"leftArm\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ -5, 21.5, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"origin\": [ -7, 11.5, -2 ], " + Environment.NewLine + " " + Environment.NewLine + " \"size\": [ 3, 12, 4 ], " + Environment.NewLine + " " + Environment.NewLine + " \"uv\": [ 40, 32 ], " + Environment.NewLine + " " + Environment.NewLine + " \"inflate\": 0.25, " + Environment.NewLine + " " + Environment.NewLine + " \"mirror\": false " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"clothing\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"rightSleeve\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"rightArm\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 1.9, 12, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"origin\": [ -0.1, 0, -2 ], " + Environment.NewLine + " " + Environment.NewLine + " \"size\": [ 4, 12, 4 ], " + Environment.NewLine + " " + Environment.NewLine + " \"uv\": [ 16, 48 ], " + Environment.NewLine + " " + Environment.NewLine + " \"inflate\": 0, " + Environment.NewLine + " " + Environment.NewLine + " \"mirror\": false " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"base\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"leftLeg\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": null " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ -1.9, 12, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"origin\": [ -3.9, 0, -2 ], " + Environment.NewLine + " " + Environment.NewLine + " \"size\": [ 4, 12, 4 ], " + Environment.NewLine + " " + Environment.NewLine + " \"uv\": [ 0, 16 ], " + Environment.NewLine + " " + Environment.NewLine + " \"inflate\": 0, " + Environment.NewLine + " " + Environment.NewLine + " \"mirror\": false " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"base\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"rightLeg\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": null " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 1.9, 12, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"origin\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"size\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"uv\": [ 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"inflate\": 0, " + Environment.NewLine + " " + Environment.NewLine + " \"mirror\": false " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"armor\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"leftLegArmor\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"leftLeg\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ -1.9, 12, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"origin\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"size\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"uv\": [ 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"inflate\": 0, " + Environment.NewLine + " " + Environment.NewLine + " \"mirror\": false " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"armor\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"rightLegging\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"rightLeg\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 1.9, 12, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"origin\": [ -0.1, 0, -2 ], " + Environment.NewLine + " " + Environment.NewLine + " \"size\": [ 4, 12, 4 ], " + Environment.NewLine + " " + Environment.NewLine + " \"uv\": [ 0, 48 ], " + Environment.NewLine + " " + Environment.NewLine + " \"inflate\": 0.25, " + Environment.NewLine + " " + Environment.NewLine + " \"mirror\": false " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"clothing\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"leftPants\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"leftLeg\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ -1.9, 12, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"origin\": [ -3.9, 0, -2 ], " + Environment.NewLine + " " + Environment.NewLine + " \"size\": [ 4, 12, 4 ], " + Environment.NewLine + " " + Environment.NewLine + " \"uv\": [ 0, 32 ], " + Environment.NewLine + " " + Environment.NewLine + " \"inflate\": 0.25, " + Environment.NewLine + " " + Environment.NewLine + " \"mirror\": false " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"clothing\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"rightPants\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"rightLeg\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 0, 24, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [ " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"origin\": [ -4, 12, -2 ], " + Environment.NewLine + " " + Environment.NewLine + " \"size\": [ 8, 12, 4 ], " + Environment.NewLine + " " + Environment.NewLine + " \"uv\": [ 16, 32 ], " + Environment.NewLine + " " + Environment.NewLine + " \"inflate\": 0.25, " + Environment.NewLine + " " + Environment.NewLine + " \"mirror\": false " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"clothing\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"jacket\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"body\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 0, 24, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"armor_offset\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"helmetArmorOffset\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"head\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 0, 24, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"armor_offset\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"bodyArmorOffset\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"body\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ -5, 21.5, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"armor_offset\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"rightArmArmorOffset\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"rightArm\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 5, 21.5, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"armor_offset\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"leftArmArmorOffset\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"leftArm\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 0, 12, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"armor_offset\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"waist\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"body\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ -1.9, 12, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"armor_offset\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"rightLegArmorOffset\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"rightLeg\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 1.9, 12, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"armor_offset\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"leftLegArmorOffset\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"leftLeg\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ -1.9, 12, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"armor_offset\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"rightBootArmorOffset\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"rightLeg\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 1.9, 12, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"armor_offset\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"leftBootArmorOffset\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"leftLeg\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ -6, 14.5, 1 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"item\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"rightItem\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"rightArm\" " + Environment.NewLine + " " + Environment.NewLine + " }, " + Environment.NewLine + " " + Environment.NewLine + " { " + Environment.NewLine + " " + Environment.NewLine + " \"pivot\": [ 6, 14.5, 1 ], " + Environment.NewLine + " " + Environment.NewLine + " \"rotation\": [ 0, 0, 0 ], " + Environment.NewLine + " " + Environment.NewLine + " \"cubes\": [], " + Environment.NewLine + " " + Environment.NewLine + " \"META_BoneType\": \"item\", " + Environment.NewLine + " " + Environment.NewLine + " \"name\": \"leftItem\", " + Environment.NewLine + " " + Environment.NewLine + " \"parent\": \"leftArm\" " + Environment.NewLine + " " + Environment.NewLine + " } " + Environment.NewLine + " " + Environment.NewLine + " ],");
|
|
}
|
|
|
|
|
|
writeSkins.WriteLine(" \"texturewidth\": 64 , ");
|
|
writeSkins.WriteLine(" \"textureheight\": 64,");
|
|
writeSkins.WriteLine(" \"META_ModelVersion\": \"1.0.6\",");
|
|
writeSkins.WriteLine(" \"rigtype\": \"normal\",");
|
|
writeSkins.WriteLine(" \"animationArmsDown\": false,");
|
|
writeSkins.WriteLine(" \"animationArmsOutFront\": false,");
|
|
writeSkins.WriteLine(" \"animationStatueOfLibertyArms\": false,");
|
|
writeSkins.WriteLine(" \"animationSingleArmAnimation\": false,");
|
|
writeSkins.WriteLine(" \"animationStationaryLegs\": false,");
|
|
writeSkins.WriteLine(" \"animationSingleLegAnimation\": false,");
|
|
writeSkins.WriteLine(" \"animationNoHeadBob\": false,");
|
|
writeSkins.WriteLine(" \"animationDontShowArmor\": false,");
|
|
writeSkins.WriteLine(" \"animationUpsideDown\": false,");
|
|
writeSkins.WriteLine(" \"animationInvertedCrouch\": false");
|
|
if (newSkinCount != skinsList.Count)
|
|
{
|
|
writeSkins.WriteLine(" },");
|
|
}
|
|
else
|
|
{
|
|
writeSkins.WriteLine(" }");
|
|
}
|
|
}
|
|
Console.WriteLine(writeSkins);
|
|
}
|
|
Random rnd = new Random();
|
|
int month = rnd.Next(1, 13); // creates a number between 1 and 12
|
|
int dice = rnd.Next(1, 7); // creates a number between 1 and 6
|
|
int card = rnd.Next(52);
|
|
|
|
string randomPlus = month.ToString() + dice.ToString() + card.ToString();
|
|
if (randomPlus.Count() > 12)
|
|
{
|
|
randomPlus.Remove(0, randomPlus.Count() - 12);
|
|
}
|
|
else if (randomPlus.Count() < 12)
|
|
{
|
|
int ii = 12 - randomPlus.Count();
|
|
for (int i = 0; i < ii; i++)
|
|
{
|
|
randomPlus += 0;
|
|
}
|
|
}
|
|
else if (randomPlus.Count() == 12)
|
|
{
|
|
}
|
|
|
|
//Create Manifest file
|
|
using (StreamWriter writeSkins = new StreamWriter(root + "/manifest.json"))
|
|
{
|
|
writeSkins.WriteLine("{");
|
|
writeSkins.WriteLine(" \"header\": {");
|
|
writeSkins.WriteLine(" \"version\": [");
|
|
writeSkins.WriteLine(" 1,");
|
|
writeSkins.WriteLine(" 0,");
|
|
writeSkins.WriteLine(" 0");
|
|
writeSkins.WriteLine(" ],");
|
|
writeSkins.WriteLine(" \"description\": \"Template by Ultmate_Mario, Conversion by Nobledez\",");
|
|
writeSkins.WriteLine(" \"name\": \"" + packName + "\",");
|
|
writeSkins.WriteLine(" \"uuid\": \"" + uuid.Remove(0, 4) + "-" + uuid.Remove(0, 8) + "-" + uuid.Remove(1, 8) + "-" + uuid.Remove(2, 8) + "-" + randomPlus + "\""); //8-4-4-4-12
|
|
writeSkins.WriteLine(" },");
|
|
writeSkins.WriteLine(" \"modules\": [");
|
|
writeSkins.WriteLine(" {");
|
|
writeSkins.WriteLine(" \"version\": [");
|
|
writeSkins.WriteLine(" 1,");
|
|
writeSkins.WriteLine(" 0,");
|
|
writeSkins.WriteLine(" 0");
|
|
writeSkins.WriteLine(" ],");
|
|
writeSkins.WriteLine(" \"type\": \"skin_pack\",");
|
|
writeSkins.WriteLine(" \"uuid\": \"8dfd1d65-b3ca-4726-b9e0-9b46a40b72a4\"");
|
|
writeSkins.WriteLine(" }");
|
|
writeSkins.WriteLine(" ],");
|
|
writeSkins.WriteLine(" \"format_version\": 1");
|
|
writeSkins.WriteLine("}");
|
|
}
|
|
|
|
//create lang file
|
|
using (StreamWriter writeSkins = new StreamWriter(root + "/texts/en_US.lang"))
|
|
{
|
|
writeSkins.WriteLine("skinpack." + packName + "=" + Path.GetFileNameWithoutExtension(convert.FileName));
|
|
foreach (Item displayName in skinDisplayNames)
|
|
{
|
|
writeSkins.WriteLine("skin." + packName + "." + displayName.Id + "=" + displayName.Name);
|
|
}
|
|
}
|
|
|
|
//adds skin textures
|
|
foreach (PCK.MineFile skinTexture in skinsList)
|
|
{
|
|
var ms = new MemoryStream(skinTexture.data);
|
|
Bitmap saveSkin = new Bitmap(Image.FromStream(ms));
|
|
if (saveSkin.Width == saveSkin.Height)
|
|
{
|
|
ResizeImage(saveSkin, 64, 64);
|
|
}
|
|
else if (saveSkin.Height == saveSkin.Width / 2)
|
|
{
|
|
ResizeImage(saveSkin, 64, 32);
|
|
}
|
|
else
|
|
{
|
|
ResizeImage(saveSkin, 64, 64);
|
|
}
|
|
saveSkin.Save(root + "/" + skinTexture.name, ImageFormat.Png);
|
|
}
|
|
|
|
//adds cape textures
|
|
foreach (PCK.MineFile capeTexture in capesList)
|
|
{
|
|
File.WriteAllBytes(root + "/" + capeTexture.name, capeTexture.data);
|
|
}
|
|
|
|
string startPath = root;
|
|
string zipPath = rootFinal + "content.zipe";
|
|
|
|
try
|
|
{
|
|
ZipFile.CreateFromDirectory(startPath, zipPath);//Creates contents zipe
|
|
}catch (Exception)
|
|
{
|
|
File.Delete(zipPath);
|
|
ZipFile.CreateFromDirectory(startPath, zipPath);//Creates contents zipe
|
|
}
|
|
|
|
rootFinal = root + "temp/";
|
|
Directory.CreateDirectory(rootFinal);
|
|
File.Move(zipPath, rootFinal + "content.zipe");
|
|
File.Copy(root + "/manifest.json", rootFinal + "/manifest.json");
|
|
ZipFile.CreateFromDirectory(rootFinal, convert.FileName);//Creates mcpack
|
|
Directory.Delete(root, true);
|
|
Directory.Delete(rootFinal, true);
|
|
|
|
MessageBox.Show("Conversion Complete");
|
|
}
|
|
}
|
|
catch (Exception convertEr)
|
|
{
|
|
MessageBox.Show(convertEr.ToString());
|
|
}
|
|
}
|
|
else if (openedPCKS.Visible == false)
|
|
{
|
|
MessageBox.Show("Open PCK file first!");
|
|
}
|
|
}
|
|
|
|
|
|
public static Bitmap ResizeImage(Image image, int width, int height)
|
|
{
|
|
var destRect = new Rectangle(0, 0, width, height);
|
|
var destImage = new Bitmap(width, height);
|
|
|
|
destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
|
|
|
|
using (var graphics = Graphics.FromImage(destImage))
|
|
{
|
|
graphics.CompositingMode = CompositingMode.SourceCopy;
|
|
graphics.CompositingQuality = CompositingQuality.HighQuality;
|
|
graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
|
|
graphics.SmoothingMode = SmoothingMode.HighQuality;
|
|
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
|
|
|
using (var wrapMode = new ImageAttributes())
|
|
{
|
|
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
|
|
graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
|
|
}
|
|
}
|
|
|
|
return destImage;
|
|
}
|
|
#endregion
|
|
|
|
#region 3ds feature in testing
|
|
|
|
private struct loadedTexture
|
|
{
|
|
public bool modified;
|
|
public uint gpuCommandsOffset;
|
|
public uint gpuCommandsWordCount;
|
|
public uint offset;
|
|
public int length;
|
|
public RenderBase.OTexture texture;
|
|
}
|
|
|
|
private struct loadedMaterial
|
|
{
|
|
public string texture0;
|
|
public string texture1;
|
|
public string texture2;
|
|
public uint gpuCommandsOffset;
|
|
public uint gpuCommandsWordCount;
|
|
}
|
|
|
|
private class loadedBCH
|
|
{
|
|
public uint mainHeaderOffset;
|
|
public uint gpuCommandsOffset;
|
|
public uint dataOffset;
|
|
public uint relocationTableOffset;
|
|
public uint relocationTableLength;
|
|
public List<loadedTexture> textures;
|
|
public List<loadedMaterial> materials;
|
|
|
|
public loadedBCH()
|
|
{
|
|
textures = new List<loadedTexture>();
|
|
materials = new List<loadedMaterial>();
|
|
}
|
|
}
|
|
|
|
private byte[] align(byte[] input)
|
|
{
|
|
int length = input.Length;
|
|
while ((length & 0x7f) > 0) length++;
|
|
byte[] output = new byte[length];
|
|
Buffer.BlockCopy(input, 0, output, 0, input.Length);
|
|
return output;
|
|
}
|
|
|
|
private void replaceData(Stream data, uint offset, int length, byte[] newData)
|
|
{
|
|
data.Seek(offset + length, SeekOrigin.Begin);
|
|
byte[] after = new byte[data.Length - data.Position];
|
|
data.Read(after, 0, after.Length);
|
|
data.SetLength(offset);
|
|
data.Seek(offset, SeekOrigin.Begin);
|
|
data.Write(newData, 0, newData.Length);
|
|
data.Write(after, 0, after.Length);
|
|
}
|
|
|
|
private void updateTexture(int index, loadedTexture newTex)
|
|
{
|
|
bch.textures.RemoveAt(index);
|
|
bch.textures.Insert(index, newTex);
|
|
}
|
|
|
|
private void replaceCommand(Stream data, BinaryWriter output, uint newVal)
|
|
{
|
|
data.Seek(-8, SeekOrigin.Current);
|
|
output.Write(newVal);
|
|
data.Seek(4, SeekOrigin.Current);
|
|
}
|
|
|
|
private void updateAddress(Stream data, BinaryReader input, BinaryWriter output, int diff)
|
|
{
|
|
uint offset = input.ReadUInt32();
|
|
offset = (uint)(offset + diff);
|
|
data.Seek(-4, SeekOrigin.Current);
|
|
output.Write(offset);
|
|
}
|
|
|
|
loadedBCH bch;
|
|
|
|
private void create3dstToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
if (treeViewMain.SelectedNode != null)
|
|
{
|
|
|
|
SaveFileDialog exportDs = new SaveFileDialog();
|
|
exportDs.ShowDialog();
|
|
string currentFile = exportDs.FileName;
|
|
|
|
bch = new loadedBCH();
|
|
|
|
using (FileStream data = new FileStream(currentFile, FileMode.Open))
|
|
{
|
|
BinaryReader input = new BinaryReader(data);
|
|
BinaryWriter output = new BinaryWriter(data);
|
|
|
|
MemoryStream png = new MemoryStream(((PCK.MineFile)(treeViewMain.SelectedNode.Tag)).data); //Gets image data from minefile data
|
|
Image skinPicture = Image.FromStream(png); //Constructs image data into image
|
|
pictureBoxImagePreview.Image = skinPicture; //Sets image preview to image
|
|
|
|
byte[] buffer = new byte[skinPicture.Width * skinPicture.Height * 4];
|
|
input.Read(buffer, 0, buffer.Length);
|
|
Bitmap texture = TextureCodec.decode(buffer, skinPicture.Width, skinPicture.Height, RenderBase.OTextureFormat.rgba8);
|
|
tex.texture = new RenderBase.OTexture(texture, "Texure");
|
|
|
|
//tex.texture = treeViewMain.SelectedNode.Tag;
|
|
|
|
for (int i = 0; i < bch.textures.Count; i++)
|
|
{
|
|
tex = bch.textures[i];
|
|
tex.modified = true;
|
|
|
|
if (tex.modified)
|
|
{
|
|
byte[] bufferx = align(TextureCodec.encode(tex.texture.texture, RenderBase.OTextureFormat.rgba8));
|
|
int diff = bufferx.Length - tex.length;
|
|
|
|
replaceData(data, tex.offset, tex.length, bufferx);
|
|
|
|
//Update offsets of next textures
|
|
tex.length = bufferx.Length;
|
|
tex.modified = false;
|
|
updateTexture(i, tex);
|
|
for (int j = i; j < bch.textures.Count; j++)
|
|
{
|
|
loadedTexture next = bch.textures[j];
|
|
next.offset = (uint)(next.offset + diff);
|
|
updateTexture(j, next);
|
|
}
|
|
|
|
//Update all addresses poiting after the replaced data
|
|
bch.relocationTableOffset = (uint)(bch.relocationTableOffset + diff);
|
|
for (int index = 0; index < bch.relocationTableLength; index += 4)
|
|
{
|
|
data.Seek(bch.relocationTableOffset + index, SeekOrigin.Begin);
|
|
uint value = input.ReadUInt32();
|
|
uint offset = value & 0x1ffffff;
|
|
byte flags = (byte)(value >> 25);
|
|
|
|
if ((flags & 0x20) > 0 || flags == 7 || flags == 0xc)
|
|
{
|
|
if ((flags & 0x20) > 0)
|
|
data.Seek((offset * 4) + bch.gpuCommandsOffset, SeekOrigin.Begin);
|
|
else
|
|
data.Seek((offset * 4) + bch.mainHeaderOffset, SeekOrigin.Begin);
|
|
|
|
uint address = input.ReadUInt32();
|
|
if (address + bch.dataOffset > tex.offset)
|
|
{
|
|
address = (uint)(address + diff);
|
|
data.Seek(-4, SeekOrigin.Current);
|
|
output.Write(address);
|
|
}
|
|
}
|
|
}
|
|
|
|
uint newSize = (uint)((tex.texture.texture.Width << 16) | tex.texture.texture.Height);
|
|
|
|
//Update texture format
|
|
data.Seek(tex.gpuCommandsOffset, SeekOrigin.Begin);
|
|
for (int index = 0; index < tex.gpuCommandsWordCount * 3; index++)
|
|
{
|
|
uint command = input.ReadUInt32();
|
|
|
|
switch (command)
|
|
{
|
|
case 0xf008e:
|
|
case 0xf0096:
|
|
case 0xf009e:
|
|
replaceCommand(data, output, 0); //Set texture format to 0 = RGBA8888
|
|
break;
|
|
case 0xf0082:
|
|
case 0xf0092:
|
|
case 0xf009a:
|
|
replaceCommand(data, output, newSize); //Set new texture size
|
|
break;
|
|
}
|
|
}
|
|
|
|
//Update material texture format
|
|
foreach (loadedMaterial mat in bch.materials)
|
|
{
|
|
data.Seek(mat.gpuCommandsOffset, SeekOrigin.Begin);
|
|
for (int index = 0; index < mat.gpuCommandsWordCount; index++)
|
|
{
|
|
uint command = input.ReadUInt32();
|
|
|
|
switch (command)
|
|
{
|
|
case 0xf008e: if (mat.texture0 == tex.texture.name || mat.texture0 == "") replaceCommand(data, output, 0); break;
|
|
case 0xf0096: if (mat.texture1 == tex.texture.name || mat.texture1 == "") replaceCommand(data, output, 0); break;
|
|
case 0xf009e: if (mat.texture2 == tex.texture.name || mat.texture2 == "") replaceCommand(data, output, 0); break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//Patch up BCH header for new offsets and lengths
|
|
data.Seek(4, SeekOrigin.Begin);
|
|
byte backwardCompatibility = input.ReadByte();
|
|
byte forwardCompatibility = input.ReadByte();
|
|
|
|
//Update Data Extended and Relocation Table offsets
|
|
data.Seek(18, SeekOrigin.Current);
|
|
if (backwardCompatibility > 0x20) updateAddress(data, input, output, diff);
|
|
updateAddress(data, input, output, diff);
|
|
|
|
//Update data length
|
|
data.Seek(12, SeekOrigin.Current);
|
|
updateAddress(data, input, output, diff);
|
|
}
|
|
}
|
|
using (Stream file = File.Create(currentFile + ".tmp"))
|
|
{
|
|
CopyStream(output.BaseStream, file);
|
|
}
|
|
|
|
}
|
|
|
|
MessageBox.Show("Done!", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
public static void CopyStream(Stream input, Stream output)
|
|
{
|
|
byte[] buffer = new byte[8 * 1024];
|
|
int len;
|
|
while ((len = input.Read(buffer, 0, buffer.Length)) > 0)
|
|
{
|
|
output.Write(buffer, 0, len);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Tool/MenuStrips
|
|
|
|
private void openToolStripMenuItem1_Click(object sender, EventArgs e)
|
|
{
|
|
pckCenter open = new pckCenter();
|
|
open.Show();
|
|
}
|
|
|
|
private void tutorialsToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
System.Diagnostics.Process.Start(hosturl + "pckStudio#tutorials");
|
|
}
|
|
|
|
private void wiiUPCKInstallerToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
installWiiU install = new installWiiU(null);
|
|
install.ShowDialog();
|
|
}
|
|
|
|
private void howToMakeABasicSkinPackToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
System.Diagnostics.Process.Start("https://www.youtube.com/watch?v=A43aHRHkKxk");
|
|
}
|
|
|
|
private void howToMakeACustomSkinModelToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
System.Diagnostics.Process.Start("https://www.youtube.com/watch?v=pEC_ug55lag");
|
|
}
|
|
|
|
private void howToMakeCustomSkinModelsbedrockToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
System.Diagnostics.Process.Start("https://www.youtube.com/watch?v=6z8NTogw5x4");
|
|
}
|
|
|
|
private void howToMakeCustomMusicToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
System.Diagnostics.Process.Start("https://www.youtube.com/watch?v=v6EYr4zc7rI");
|
|
}
|
|
|
|
private void howToInstallPcksDirectlyToWiiUToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
System.Diagnostics.Process.Start("https://www.youtube.com/watch?v=hRQagnEplec");
|
|
}
|
|
|
|
private void pCKCenterReleaseToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
System.Diagnostics.Process.Start("https://www.youtube.com/watch?v=E_6bXSh6yqw");
|
|
}
|
|
|
|
private void howPCKsWorkToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
System.Diagnostics.Process.Start("https://www.youtube.com/watch?v=hTlImrRrCKQ");
|
|
}
|
|
|
|
private void PS3PCKInstallerToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
|
|
installPS3 install = new installPS3(null);
|
|
install.ShowDialog();
|
|
}
|
|
|
|
private void settingsToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
Pref setting = new Pref();
|
|
setting.Show();
|
|
}
|
|
|
|
private void administrativeToolsToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
PCK_Manager pckm = new PCK_Manager();
|
|
pckm.Show();
|
|
}
|
|
|
|
private void uPDATEToolStripMenuItem1_Click(object sender, EventArgs e)
|
|
{
|
|
try
|
|
{
|
|
Classes.Network.CheckUpdate();
|
|
uPDATEToolStripMenuItem1.Visible = false;
|
|
}
|
|
catch
|
|
{
|
|
MessageBox.Show("Could not load Version Information");
|
|
uPDATEToolStripMenuItem1.Visible = false;
|
|
}
|
|
}
|
|
|
|
private void VitaPCKInstallerToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
|
|
installVita install = new installVita(null);
|
|
install.ShowDialog();
|
|
}
|
|
|
|
private void toPhoenixARCDeveloperToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
System.Diagnostics.Process.Start("https://cash.app/$PhoenixARC");
|
|
}
|
|
|
|
private void toNobledezJackToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
System.Diagnostics.Process.Start("https://www.paypal.me/realnobledez");
|
|
}
|
|
|
|
private void addPasswordToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
treeViewMain.SelectedNode = treeViewMain.Nodes[0];
|
|
mf = (PCK.MineFile)treeViewMain.Nodes[0].Tag;//Sets minefile to selected node
|
|
foreach (object[] entry in mf.entries)
|
|
{
|
|
if (entry[0].ToString() == "LOCK")
|
|
{
|
|
MessageBox.Show("Remove current LOCK before adding a new one!");
|
|
return;
|
|
}
|
|
}
|
|
AddPCKPassword add = new AddPCKPassword(mf, currentPCK);//sets metadata adding dialog
|
|
add.ShowDialog();//displays metadata adding dialog
|
|
add.Dispose();//diposes generated metadata adding dialog data
|
|
|
|
//Sets up combobox for metadata entries from main metadatabase
|
|
treeMeta.Nodes.Clear();
|
|
foreach (int type in types.Keys)
|
|
comboBox1.Items.Add(types[type]);
|
|
|
|
//loads all of selected minefiles metadata into metadata treeview
|
|
foreach (object[] entry in file.entries)
|
|
{
|
|
object[] strings = (object[])entry; TreeNode meta = new TreeNode();
|
|
|
|
foreach (object[] entryy in file.entries)
|
|
meta.Text = (string)strings[0];
|
|
meta.Tag = entry;
|
|
treeMeta.Nodes.Add(meta);
|
|
}
|
|
saved = false;
|
|
}
|
|
|
|
private void joinDevelopmentDiscordToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
System.Diagnostics.Process.Start("https://discord.gg/aJtZNFVQTv");
|
|
}
|
|
|
|
private void tSTToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
Testx_12 form1 = new Testx_12();
|
|
form1.Show();
|
|
}
|
|
|
|
private void convertPCTextrurePackToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
PckStudio.Forms.Utilities.TextureConverterUtility tex = new PckStudio.Forms.Utilities.TextureConverterUtility(treeViewMain, currentPCK);
|
|
tex.ShowDialog();
|
|
}
|
|
|
|
#endregion
|
|
|
|
|
|
private void buttonEditModel_Click(object sender, EventArgs e)
|
|
{
|
|
PCK.MineFile mf = (PCK.MineFile)treeViewMain.SelectedNode.Tag;
|
|
|
|
if (Path.GetExtension(mf.name) == ".png")
|
|
{
|
|
if (buttonEdit.Text == "EDIT BOXES")
|
|
editModel(mf);
|
|
else if (buttonEdit.Text == "View Skin")
|
|
{
|
|
using (var ms = new MemoryStream(mf.data))
|
|
{
|
|
SkinPreview frm = new SkinPreview(Image.FromStream(ms));
|
|
frm.ShowDialog(this);
|
|
frm.Dispose();
|
|
}
|
|
}
|
|
}
|
|
|
|
//Check for Animated Texture
|
|
if (mf.name.StartsWith("res/textures/blocks/") || mf.name.StartsWith("res/textures/items/"))
|
|
{
|
|
try
|
|
{
|
|
AnimationEditor diag = new AnimationEditor(treeViewMain);
|
|
diag.ShowDialog(this);
|
|
diag.Dispose();
|
|
|
|
treeViewToMineFiles(treeViewMain);
|
|
|
|
MemoryStream png = new MemoryStream(mf.data); //Gets image data from minefile data
|
|
Image skinPicture = Image.FromStream(png); //Constructs image data into image
|
|
pictureBoxImagePreview.Image = skinPicture;
|
|
|
|
treeMeta.Nodes.Clear();
|
|
foreach (int type in types.Keys)
|
|
comboBox1.Items.Add(types[type]);
|
|
|
|
//loads all of selected minefiles metadata into metadata treeview
|
|
foreach (object[] entry in file.entries)
|
|
{
|
|
object[] strings = (object[])entry; TreeNode meta = new TreeNode();
|
|
|
|
foreach (object[] entryy in file.entries)
|
|
meta.Text = (string)strings[0];
|
|
meta.Tag = entry;
|
|
treeMeta.Nodes.Add(meta);
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
MessageBox.Show("Invalid animation data.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (Path.GetFileName(mf.name) == "audio.pck")
|
|
{
|
|
try
|
|
{
|
|
PckStudio.Forms.Utilities.AudioEditor diag = new PckStudio.Forms.Utilities.AudioEditor(mf.data, mf);
|
|
diag.ShowDialog(this);
|
|
diag.Dispose();
|
|
}
|
|
catch
|
|
{
|
|
MessageBox.Show("Invalid data", "Error", MessageBoxButtons.OK,MessageBoxIcon.Error);
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (Path.GetExtension(mf.name) == ".loc")
|
|
{
|
|
LOC l;
|
|
try
|
|
{
|
|
l = new LOC(mf.data);
|
|
}
|
|
catch
|
|
{
|
|
MessageBox.Show("No localization data found.", "Error", MessageBoxButtons.OK,
|
|
MessageBoxIcon.Error);
|
|
return;
|
|
}
|
|
(new LOCEditor(l)).ShowDialog();//Opens LOC Editor
|
|
mf.data = l.Rebuild();//Rebuilds loc file with locdata in grid view after closing dialog
|
|
}
|
|
|
|
//Checks to see if selected minefile is a col file
|
|
if (Path.GetExtension(mf.name) == ".col")
|
|
{
|
|
//MessageBox.Show(".COL Editor Coming Soon!");
|
|
|
|
if (treeViewMain.SelectedNode.Tag is PCK.MineFile)
|
|
{
|
|
try
|
|
{
|
|
PckStudio.Forms.Utilities.COLEditor diag = new PckStudio.Forms.Utilities.COLEditor(mf.data, mf);
|
|
diag.ShowDialog(this);
|
|
diag.Dispose();
|
|
}
|
|
catch
|
|
{
|
|
MessageBox.Show("No Color data found.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
return;
|
|
}
|
|
//mf.data = l.Rebuild();//Rebuilds loc file with locdata in grid view after closing dialog
|
|
}
|
|
}
|
|
}
|
|
|
|
private void OpenPck_MouseEnter(object sender, EventArgs e)
|
|
{
|
|
pckOpen.Image = Resources.pckOpen;
|
|
}
|
|
|
|
private void OpenPck_MouseLeave(object sender, EventArgs e)
|
|
{
|
|
pckOpen.Image = Resources.pckClosed;
|
|
}
|
|
|
|
private void FormMain_FormClosed(object sender, FormClosedEventArgs e)
|
|
{
|
|
if (saved == false)
|
|
{
|
|
if (MessageBox.Show("Save PCK?", "Unsaved PCK", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
|
|
{
|
|
if (saveLocation == appData + @"\templates\UntitledSkinPCK.pck")
|
|
{
|
|
save("Save As");
|
|
}
|
|
else
|
|
{
|
|
save("Save");
|
|
}
|
|
}
|
|
}
|
|
if (needsUpdate)
|
|
{
|
|
Process UPDATE = new Process();//sets up updater
|
|
UPDATE.StartInfo.FileName = appData + @"\nobleUpdater.exe";//updater program path
|
|
UPDATE.Start();//starts updater
|
|
Application.Exit();//closes PCK Studio to let updatear finish the job
|
|
}
|
|
}
|
|
|
|
private void OpenPck_DragEnter(object sender, DragEventArgs e)
|
|
{
|
|
pckOpen.Image = Resources.pckDrop;
|
|
string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
|
|
foreach (var file in files)
|
|
{
|
|
var ext = System.IO.Path.GetExtension(file);
|
|
if (ext.Equals(".pck", StringComparison.CurrentCultureIgnoreCase))
|
|
e.Effect = DragDropEffects.Copy;
|
|
return;
|
|
}
|
|
}
|
|
|
|
private void OpenPck_DragDrop(object sender, DragEventArgs e)
|
|
{
|
|
string[] FileList = (string[])e.Data.GetData(DataFormats.FileDrop, false);
|
|
|
|
foreach (string pck in FileList)
|
|
{
|
|
openPck(pck);
|
|
}
|
|
}
|
|
|
|
private void OpenPck_DragLeave(object sender, EventArgs e)
|
|
{
|
|
pckOpen.Image = Resources.pckClosed;
|
|
}
|
|
|
|
private void savePCK(object sender, EventArgs e)
|
|
{
|
|
save("Save");
|
|
}
|
|
|
|
private void saveAsPCK(object sender, EventArgs e)
|
|
{
|
|
save("Save As");
|
|
}
|
|
|
|
private void timer1_Tick(object sender, EventArgs e)
|
|
{
|
|
if (PCKFile != PCKFileBCKUP)
|
|
{
|
|
RPC.CloseRPC();
|
|
if (string.IsNullOrWhiteSpace(PCKFile))
|
|
try
|
|
{
|
|
RPC.SetRPC("825875166574673940", "Sitting alone", "Program by PhoenixARC", "pcklgo", "PCK Studio", "pcklgo");
|
|
}
|
|
catch
|
|
{
|
|
Console.WriteLine("ERROR WITH RPC");
|
|
}
|
|
else
|
|
|
|
try
|
|
{
|
|
RPC.SetRPC("825875166574673940", "Developing " + PCKFile, "Program by PhoenixARC", "pcklgo", "PCK Studio", "pcklgo");
|
|
}
|
|
catch
|
|
{
|
|
Console.WriteLine("ERROR WITH RPC");
|
|
}
|
|
PCKFileBCKUP = PCKFile;
|
|
}
|
|
}
|
|
|
|
private void FormMain_FormClosing(object sender, FormClosingEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
RPC.CloseRPC();
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
private void FormMain_Deactivate(object sender, EventArgs e)
|
|
{
|
|
try
|
|
{
|
|
RPC.CloseRPC();
|
|
timer1.Stop();
|
|
timer1.Enabled = false;
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
private void FormMain_Activated(object sender, EventArgs e)
|
|
{
|
|
try
|
|
{
|
|
RPC.SetRPC("825875166574673940", "Sitting alone", "Program by PhoenixARC", "pcklgo", "PCK Studio", "pcklgo");
|
|
timer1.Start();
|
|
timer1.Enabled = true;
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
private void forMattNLContributorToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
System.Diagnostics.Process.Start("https://www.paypal.com/donate?business=X7Z3PMXC4L5LY&no_recurring=1&item_name=Consider+this+my+tip+jar.+It%27s+completely+optional+but+is+absolutely+appreciated.+%28%3A¤cy_code=USD");
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|