diff --git a/PCK-Studio/Controls/PckEditor.Designer.cs b/PCK-Studio/Controls/PckEditor.Designer.cs
new file mode 100644
index 00000000..a5351572
--- /dev/null
+++ b/PCK-Studio/Controls/PckEditor.Designer.cs
@@ -0,0 +1,824 @@
+using System.Windows.Forms;
+
+namespace PckStudio.Controls
+{
+ partial class PckEditor
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Component Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.components = new System.ComponentModel.Container();
+ System.Windows.Forms.PictureBox logoPictureBox;
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(PckEditor));
+ this.pckFileLabel = new MetroFramework.Controls.MetroLabel();
+ this.labelImageSize = new MetroFramework.Controls.MetroLabel();
+ this.fileEntryCountLabel = new MetroFramework.Controls.MetroLabel();
+ this.PropertiesTabControl = new MetroFramework.Controls.MetroTabControl();
+ this.MetaTab = new MetroFramework.Controls.MetroTabPage();
+ this.metroLabel2 = new MetroFramework.Controls.MetroLabel();
+ this.entryTypeTextBox = new MetroFramework.Controls.MetroTextBox();
+ this.entryDataTextBox = new MetroFramework.Controls.MetroTextBox();
+ this.buttonEdit = new MetroFramework.Controls.MetroButton();
+ this.metroLabel1 = new MetroFramework.Controls.MetroLabel();
+ this.treeMeta = new System.Windows.Forms.TreeView();
+ this.contextMenuMetaTree = new System.Windows.Forms.ContextMenuStrip(this.components);
+ this.addEntryToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.addEntryToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
+ this.addBOXEntryToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
+ this.addANIMEntryToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
+ this.addMultipleEntriesToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
+ this.deleteEntryToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.editAllEntriesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.label11 = new MetroFramework.Controls.MetroLabel();
+ this.treeViewMain = new System.Windows.Forms.TreeView();
+ this.contextMenuPCKEntries = new System.Windows.Forms.ContextMenuStrip(this.components);
+ this.createToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.folderToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.skinToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.createAnimatedTextureToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.audiopckToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.colourscolToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.CreateSkinsPCKToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
+ this.behavioursbinToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.entityMaterialsbinToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.importSkinsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.importSkinToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.importExtractedSkinsFolderToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.addTextureToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.addFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.exportToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.as3DSTextureFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.setFileTypeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.skinToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
+ this.capeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.textureToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.languagesFileLOCToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.gameRulesFileGRFToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.audioPCKFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.coloursCOLFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.gameRulesHeaderGRHToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.skinsPCKToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.modelsFileBINToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.behavioursFileBINToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.entityMaterialsFileBINToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.toolStripSeparator5 = new System.Windows.Forms.ToolStripSeparator();
+ this.miscFunctionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.generateMipMapTextureToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
+ this.viewFileInfoToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.correctSkinDecimalsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.setSubPCKEndiannessToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.bigEndianXbox360PS3WiiUToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.littleEndianPS4PSVitaSwitchToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.setModelContainerFormatToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.version1ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.version2ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.version3114ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.extractToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.toolStripSeparator6 = new System.Windows.Forms.ToolStripSeparator();
+ this.cloneFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.renameFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.replaceToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.deleteFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.imageList = new System.Windows.Forms.ImageList(this.components);
+ this.addMultipleEntriesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.LittleEndianCheckBox = new MetroFramework.Controls.MetroCheckBox();
+ this.previewPictureBox = new PckStudio.ToolboxItems.InterpolationPictureBox();
+ logoPictureBox = new System.Windows.Forms.PictureBox();
+ ((System.ComponentModel.ISupportInitialize)(logoPictureBox)).BeginInit();
+ this.PropertiesTabControl.SuspendLayout();
+ this.MetaTab.SuspendLayout();
+ this.contextMenuMetaTree.SuspendLayout();
+ this.contextMenuPCKEntries.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.previewPictureBox)).BeginInit();
+ this.SuspendLayout();
+ //
+ // logoPictureBox
+ //
+ resources.ApplyResources(logoPictureBox, "logoPictureBox");
+ logoPictureBox.Name = "logoPictureBox";
+ logoPictureBox.TabStop = false;
+ //
+ // pckFileLabel
+ //
+ this.pckFileLabel.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(20)))), ((int)(((byte)(20)))), ((int)(((byte)(20)))));
+ resources.ApplyResources(this.pckFileLabel, "pckFileLabel");
+ this.pckFileLabel.Name = "pckFileLabel";
+ this.pckFileLabel.Theme = MetroFramework.MetroThemeStyle.Dark;
+ //
+ // labelImageSize
+ //
+ resources.ApplyResources(this.labelImageSize, "labelImageSize");
+ this.labelImageSize.Name = "labelImageSize";
+ this.labelImageSize.Theme = MetroFramework.MetroThemeStyle.Dark;
+ //
+ // fileEntryCountLabel
+ //
+ resources.ApplyResources(this.fileEntryCountLabel, "fileEntryCountLabel");
+ this.fileEntryCountLabel.Name = "fileEntryCountLabel";
+ this.fileEntryCountLabel.Theme = MetroFramework.MetroThemeStyle.Dark;
+ //
+ // PropertiesTabControl
+ //
+ this.PropertiesTabControl.Controls.Add(this.MetaTab);
+ resources.ApplyResources(this.PropertiesTabControl, "PropertiesTabControl");
+ this.PropertiesTabControl.Name = "PropertiesTabControl";
+ this.PropertiesTabControl.SelectedIndex = 0;
+ this.PropertiesTabControl.Style = MetroFramework.MetroColorStyle.Silver;
+ this.PropertiesTabControl.Theme = MetroFramework.MetroThemeStyle.Dark;
+ this.PropertiesTabControl.UseSelectable = true;
+ //
+ // MetaTab
+ //
+ this.MetaTab.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
+ this.MetaTab.Controls.Add(this.metroLabel2);
+ this.MetaTab.Controls.Add(this.entryTypeTextBox);
+ this.MetaTab.Controls.Add(this.entryDataTextBox);
+ this.MetaTab.Controls.Add(this.buttonEdit);
+ this.MetaTab.Controls.Add(this.metroLabel1);
+ this.MetaTab.Controls.Add(this.treeMeta);
+ this.MetaTab.HorizontalScrollbarBarColor = true;
+ this.MetaTab.HorizontalScrollbarHighlightOnWheel = false;
+ this.MetaTab.HorizontalScrollbarSize = 10;
+ resources.ApplyResources(this.MetaTab, "MetaTab");
+ this.MetaTab.Name = "MetaTab";
+ this.MetaTab.Theme = MetroFramework.MetroThemeStyle.Dark;
+ this.MetaTab.VerticalScrollbarBarColor = true;
+ this.MetaTab.VerticalScrollbarHighlightOnWheel = false;
+ this.MetaTab.VerticalScrollbarSize = 10;
+ //
+ // metroLabel2
+ //
+ resources.ApplyResources(this.metroLabel2, "metroLabel2");
+ this.metroLabel2.Name = "metroLabel2";
+ this.metroLabel2.Theme = MetroFramework.MetroThemeStyle.Dark;
+ //
+ // entryTypeTextBox
+ //
+ resources.ApplyResources(this.entryTypeTextBox, "entryTypeTextBox");
+ //
+ //
+ //
+ this.entryTypeTextBox.CustomButton.Image = ((System.Drawing.Image)(resources.GetObject("resource.Image")));
+ this.entryTypeTextBox.CustomButton.ImeMode = ((System.Windows.Forms.ImeMode)(resources.GetObject("resource.ImeMode")));
+ this.entryTypeTextBox.CustomButton.Location = ((System.Drawing.Point)(resources.GetObject("resource.Location")));
+ this.entryTypeTextBox.CustomButton.Name = "";
+ this.entryTypeTextBox.CustomButton.Size = ((System.Drawing.Size)(resources.GetObject("resource.Size")));
+ this.entryTypeTextBox.CustomButton.Style = MetroFramework.MetroColorStyle.Blue;
+ this.entryTypeTextBox.CustomButton.TabIndex = ((int)(resources.GetObject("resource.TabIndex")));
+ this.entryTypeTextBox.CustomButton.Theme = MetroFramework.MetroThemeStyle.Light;
+ this.entryTypeTextBox.CustomButton.UseSelectable = true;
+ this.entryTypeTextBox.CustomButton.Visible = ((bool)(resources.GetObject("resource.Visible")));
+ this.entryTypeTextBox.Lines = new string[0];
+ this.entryTypeTextBox.MaxLength = 32767;
+ this.entryTypeTextBox.Name = "entryTypeTextBox";
+ this.entryTypeTextBox.PasswordChar = '\0';
+ this.entryTypeTextBox.ScrollBars = System.Windows.Forms.ScrollBars.None;
+ this.entryTypeTextBox.SelectedText = "";
+ this.entryTypeTextBox.SelectionLength = 0;
+ this.entryTypeTextBox.SelectionStart = 0;
+ this.entryTypeTextBox.ShortcutsEnabled = true;
+ this.entryTypeTextBox.Theme = MetroFramework.MetroThemeStyle.Dark;
+ this.entryTypeTextBox.UseSelectable = true;
+ this.entryTypeTextBox.WaterMarkColor = System.Drawing.Color.FromArgb(((int)(((byte)(109)))), ((int)(((byte)(109)))), ((int)(((byte)(109)))));
+ this.entryTypeTextBox.WaterMarkFont = new System.Drawing.Font("Segoe UI", 12F, System.Drawing.FontStyle.Italic, System.Drawing.GraphicsUnit.Pixel);
+ //
+ // entryDataTextBox
+ //
+ resources.ApplyResources(this.entryDataTextBox, "entryDataTextBox");
+ //
+ //
+ //
+ this.entryDataTextBox.CustomButton.Image = ((System.Drawing.Image)(resources.GetObject("resource.Image1")));
+ this.entryDataTextBox.CustomButton.ImeMode = ((System.Windows.Forms.ImeMode)(resources.GetObject("resource.ImeMode1")));
+ this.entryDataTextBox.CustomButton.Location = ((System.Drawing.Point)(resources.GetObject("resource.Location1")));
+ this.entryDataTextBox.CustomButton.Name = "";
+ this.entryDataTextBox.CustomButton.Size = ((System.Drawing.Size)(resources.GetObject("resource.Size1")));
+ this.entryDataTextBox.CustomButton.Style = MetroFramework.MetroColorStyle.Blue;
+ this.entryDataTextBox.CustomButton.TabIndex = ((int)(resources.GetObject("resource.TabIndex1")));
+ this.entryDataTextBox.CustomButton.Theme = MetroFramework.MetroThemeStyle.Light;
+ this.entryDataTextBox.CustomButton.UseSelectable = true;
+ this.entryDataTextBox.CustomButton.Visible = ((bool)(resources.GetObject("resource.Visible1")));
+ this.entryDataTextBox.Lines = new string[0];
+ this.entryDataTextBox.MaxLength = 32767;
+ this.entryDataTextBox.Name = "entryDataTextBox";
+ this.entryDataTextBox.PasswordChar = '\0';
+ this.entryDataTextBox.ScrollBars = System.Windows.Forms.ScrollBars.None;
+ this.entryDataTextBox.SelectedText = "";
+ this.entryDataTextBox.SelectionLength = 0;
+ this.entryDataTextBox.SelectionStart = 0;
+ this.entryDataTextBox.ShortcutsEnabled = true;
+ this.entryDataTextBox.Theme = MetroFramework.MetroThemeStyle.Dark;
+ this.entryDataTextBox.UseSelectable = true;
+ this.entryDataTextBox.WaterMarkColor = System.Drawing.Color.FromArgb(((int)(((byte)(109)))), ((int)(((byte)(109)))), ((int)(((byte)(109)))));
+ this.entryDataTextBox.WaterMarkFont = new System.Drawing.Font("Segoe UI", 12F, System.Drawing.FontStyle.Italic, System.Drawing.GraphicsUnit.Pixel);
+ //
+ // buttonEdit
+ //
+ resources.ApplyResources(this.buttonEdit, "buttonEdit");
+ this.buttonEdit.Name = "buttonEdit";
+ this.buttonEdit.Theme = MetroFramework.MetroThemeStyle.Dark;
+ this.buttonEdit.UseSelectable = true;
+ this.buttonEdit.Click += new System.EventHandler(this.buttonEdit_Click);
+ //
+ // metroLabel1
+ //
+ resources.ApplyResources(this.metroLabel1, "metroLabel1");
+ this.metroLabel1.Name = "metroLabel1";
+ this.metroLabel1.Theme = MetroFramework.MetroThemeStyle.Dark;
+ //
+ // treeMeta
+ //
+ this.treeMeta.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(13)))), ((int)(((byte)(13)))), ((int)(((byte)(13)))));
+ this.treeMeta.BorderStyle = System.Windows.Forms.BorderStyle.None;
+ this.treeMeta.ContextMenuStrip = this.contextMenuMetaTree;
+ resources.ApplyResources(this.treeMeta, "treeMeta");
+ this.treeMeta.ForeColor = System.Drawing.SystemColors.Window;
+ this.treeMeta.Name = "treeMeta";
+ this.treeMeta.PathSeparator = "/";
+ this.treeMeta.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.treeMeta_AfterSelect);
+ this.treeMeta.DoubleClick += new System.EventHandler(this.treeMeta_DoubleClick);
+ this.treeMeta.KeyDown += new System.Windows.Forms.KeyEventHandler(this.treeMeta_KeyDown);
+ //
+ // contextMenuMetaTree
+ //
+ this.contextMenuMetaTree.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.addEntryToolStripMenuItem,
+ this.addMultipleEntriesToolStripMenuItem1,
+ this.deleteEntryToolStripMenuItem,
+ this.editAllEntriesToolStripMenuItem});
+ this.contextMenuMetaTree.Name = "contextMenuStrip1";
+ resources.ApplyResources(this.contextMenuMetaTree, "contextMenuMetaTree");
+ //
+ // addEntryToolStripMenuItem
+ //
+ this.addEntryToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.addEntryToolStripMenuItem1,
+ this.addBOXEntryToolStripMenuItem1,
+ this.addANIMEntryToolStripMenuItem1});
+ resources.ApplyResources(this.addEntryToolStripMenuItem, "addEntryToolStripMenuItem");
+ this.addEntryToolStripMenuItem.Name = "addEntryToolStripMenuItem";
+ //
+ // addEntryToolStripMenuItem1
+ //
+ this.addEntryToolStripMenuItem1.Name = "addEntryToolStripMenuItem1";
+ resources.ApplyResources(this.addEntryToolStripMenuItem1, "addEntryToolStripMenuItem1");
+ this.addEntryToolStripMenuItem1.Click += new System.EventHandler(this.addEntryToolStripMenuItem_Click);
+ //
+ // addBOXEntryToolStripMenuItem1
+ //
+ this.addBOXEntryToolStripMenuItem1.Name = "addBOXEntryToolStripMenuItem1";
+ resources.ApplyResources(this.addBOXEntryToolStripMenuItem1, "addBOXEntryToolStripMenuItem1");
+ this.addBOXEntryToolStripMenuItem1.Click += new System.EventHandler(this.addBOXEntryToolStripMenuItem1_Click);
+ //
+ // addANIMEntryToolStripMenuItem1
+ //
+ this.addANIMEntryToolStripMenuItem1.Name = "addANIMEntryToolStripMenuItem1";
+ resources.ApplyResources(this.addANIMEntryToolStripMenuItem1, "addANIMEntryToolStripMenuItem1");
+ this.addANIMEntryToolStripMenuItem1.Click += new System.EventHandler(this.addANIMEntryToolStripMenuItem1_Click);
+ //
+ // addMultipleEntriesToolStripMenuItem1
+ //
+ this.addMultipleEntriesToolStripMenuItem1.Name = "addMultipleEntriesToolStripMenuItem1";
+ resources.ApplyResources(this.addMultipleEntriesToolStripMenuItem1, "addMultipleEntriesToolStripMenuItem1");
+ this.addMultipleEntriesToolStripMenuItem1.Click += new System.EventHandler(this.addMultipleEntriesToolStripMenuItem1_Click);
+ //
+ // deleteEntryToolStripMenuItem
+ //
+ this.deleteEntryToolStripMenuItem.Image = global::PckStudio.Properties.Resources.file_delete;
+ this.deleteEntryToolStripMenuItem.Name = "deleteEntryToolStripMenuItem";
+ resources.ApplyResources(this.deleteEntryToolStripMenuItem, "deleteEntryToolStripMenuItem");
+ this.deleteEntryToolStripMenuItem.Click += new System.EventHandler(this.deleteEntryToolStripMenuItem_Click);
+ //
+ // editAllEntriesToolStripMenuItem
+ //
+ this.editAllEntriesToolStripMenuItem.Name = "editAllEntriesToolStripMenuItem";
+ resources.ApplyResources(this.editAllEntriesToolStripMenuItem, "editAllEntriesToolStripMenuItem");
+ this.editAllEntriesToolStripMenuItem.Click += new System.EventHandler(this.editAllEntriesToolStripMenuItem_Click);
+ //
+ // label11
+ //
+ resources.ApplyResources(this.label11, "label11");
+ this.label11.Name = "label11";
+ //
+ // treeViewMain
+ //
+ this.treeViewMain.AllowDrop = true;
+ this.treeViewMain.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(12)))), ((int)(((byte)(12)))), ((int)(((byte)(12)))));
+ this.treeViewMain.BorderStyle = System.Windows.Forms.BorderStyle.None;
+ this.treeViewMain.ContextMenuStrip = this.contextMenuPCKEntries;
+ resources.ApplyResources(this.treeViewMain, "treeViewMain");
+ this.treeViewMain.ForeColor = System.Drawing.Color.White;
+ this.treeViewMain.ImageList = this.imageList;
+ this.treeViewMain.LabelEdit = true;
+ this.treeViewMain.Name = "treeViewMain";
+ this.treeViewMain.PathSeparator = "/";
+ this.treeViewMain.BeforeLabelEdit += new System.Windows.Forms.NodeLabelEditEventHandler(this.treeViewMain_BeforeLabelEdit);
+ this.treeViewMain.ItemDrag += new System.Windows.Forms.ItemDragEventHandler(this.treeViewMain_ItemDrag);
+ this.treeViewMain.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.treeViewMain_AfterSelect);
+ this.treeViewMain.NodeMouseClick += new System.Windows.Forms.TreeNodeMouseClickEventHandler(this.treeViewMain_NodeMouseClick);
+ this.treeViewMain.DragDrop += new System.Windows.Forms.DragEventHandler(this.treeViewMain_DragDrop);
+ this.treeViewMain.DragEnter += new System.Windows.Forms.DragEventHandler(this.treeViewMain_DragEnter);
+ this.treeViewMain.DragOver += new System.Windows.Forms.DragEventHandler(this.treeViewMain_DragOver);
+ this.treeViewMain.DoubleClick += new System.EventHandler(this.treeViewMain_DoubleClick);
+ this.treeViewMain.KeyDown += new System.Windows.Forms.KeyEventHandler(this.treeViewMain_KeyDown);
+ //
+ // contextMenuPCKEntries
+ //
+ this.contextMenuPCKEntries.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.createToolStripMenuItem,
+ this.importSkinsToolStripMenuItem,
+ this.exportToolStripMenuItem,
+ this.setFileTypeToolStripMenuItem,
+ this.toolStripSeparator5,
+ this.miscFunctionsToolStripMenuItem,
+ this.extractToolStripMenuItem,
+ this.toolStripSeparator6,
+ this.cloneFileToolStripMenuItem,
+ this.renameFileToolStripMenuItem,
+ this.replaceToolStripMenuItem,
+ this.deleteFileToolStripMenuItem});
+ this.contextMenuPCKEntries.Name = "contextMenuStrip1";
+ resources.ApplyResources(this.contextMenuPCKEntries, "contextMenuPCKEntries");
+ this.contextMenuPCKEntries.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuPCKEntries_Opening);
+ //
+ // createToolStripMenuItem
+ //
+ this.createToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.folderToolStripMenuItem,
+ this.skinToolStripMenuItem,
+ this.createAnimatedTextureToolStripMenuItem,
+ this.audiopckToolStripMenuItem,
+ this.colourscolToolStripMenuItem,
+ this.CreateSkinsPCKToolStripMenuItem1,
+ this.behavioursbinToolStripMenuItem,
+ this.entityMaterialsbinToolStripMenuItem});
+ resources.ApplyResources(this.createToolStripMenuItem, "createToolStripMenuItem");
+ this.createToolStripMenuItem.Name = "createToolStripMenuItem";
+ //
+ // folderToolStripMenuItem
+ //
+ resources.ApplyResources(this.folderToolStripMenuItem, "folderToolStripMenuItem");
+ this.folderToolStripMenuItem.Name = "folderToolStripMenuItem";
+ this.folderToolStripMenuItem.Click += new System.EventHandler(this.folderToolStripMenuItem_Click);
+ //
+ // skinToolStripMenuItem
+ //
+ resources.ApplyResources(this.skinToolStripMenuItem, "skinToolStripMenuItem");
+ this.skinToolStripMenuItem.Name = "skinToolStripMenuItem";
+ this.skinToolStripMenuItem.Click += new System.EventHandler(this.createSkinToolStripMenuItem_Click);
+ //
+ // createAnimatedTextureToolStripMenuItem
+ //
+ resources.ApplyResources(this.createAnimatedTextureToolStripMenuItem, "createAnimatedTextureToolStripMenuItem");
+ this.createAnimatedTextureToolStripMenuItem.Name = "createAnimatedTextureToolStripMenuItem";
+ this.createAnimatedTextureToolStripMenuItem.Click += new System.EventHandler(this.createAnimatedTextureToolStripMenuItem_Click);
+ //
+ // audiopckToolStripMenuItem
+ //
+ this.audiopckToolStripMenuItem.Image = global::PckStudio.Properties.Resources.BINKA_ICON;
+ this.audiopckToolStripMenuItem.Name = "audiopckToolStripMenuItem";
+ resources.ApplyResources(this.audiopckToolStripMenuItem, "audiopckToolStripMenuItem");
+ this.audiopckToolStripMenuItem.Click += new System.EventHandler(this.audiopckToolStripMenuItem_Click);
+ //
+ // colourscolToolStripMenuItem
+ //
+ this.colourscolToolStripMenuItem.Image = global::PckStudio.Properties.Resources.COL_ICON;
+ this.colourscolToolStripMenuItem.Name = "colourscolToolStripMenuItem";
+ resources.ApplyResources(this.colourscolToolStripMenuItem, "colourscolToolStripMenuItem");
+ this.colourscolToolStripMenuItem.Click += new System.EventHandler(this.colourscolToolStripMenuItem_Click);
+ //
+ // CreateSkinsPCKToolStripMenuItem1
+ //
+ this.CreateSkinsPCKToolStripMenuItem1.Image = global::PckStudio.Properties.Resources.SKINS_ICON;
+ this.CreateSkinsPCKToolStripMenuItem1.Name = "CreateSkinsPCKToolStripMenuItem1";
+ resources.ApplyResources(this.CreateSkinsPCKToolStripMenuItem1, "CreateSkinsPCKToolStripMenuItem1");
+ this.CreateSkinsPCKToolStripMenuItem1.Click += new System.EventHandler(this.CreateSkinsPCKToolStripMenuItem1_Click);
+ //
+ // behavioursbinToolStripMenuItem
+ //
+ this.behavioursbinToolStripMenuItem.Image = global::PckStudio.Properties.Resources.BEHAVIOURS_ICON;
+ this.behavioursbinToolStripMenuItem.Name = "behavioursbinToolStripMenuItem";
+ resources.ApplyResources(this.behavioursbinToolStripMenuItem, "behavioursbinToolStripMenuItem");
+ this.behavioursbinToolStripMenuItem.Click += new System.EventHandler(this.behavioursbinToolStripMenuItem_Click);
+ //
+ // entityMaterialsbinToolStripMenuItem
+ //
+ this.entityMaterialsbinToolStripMenuItem.Image = global::PckStudio.Properties.Resources.ENTITY_MATERIALS_ICON;
+ this.entityMaterialsbinToolStripMenuItem.Name = "entityMaterialsbinToolStripMenuItem";
+ resources.ApplyResources(this.entityMaterialsbinToolStripMenuItem, "entityMaterialsbinToolStripMenuItem");
+ this.entityMaterialsbinToolStripMenuItem.Click += new System.EventHandler(this.entityMaterialsbinToolStripMenuItem_Click);
+ //
+ // importSkinsToolStripMenuItem
+ //
+ this.importSkinsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.importSkinToolStripMenuItem,
+ this.importExtractedSkinsFolderToolStripMenuItem,
+ this.addTextureToolStripMenuItem,
+ this.addFileToolStripMenuItem});
+ resources.ApplyResources(this.importSkinsToolStripMenuItem, "importSkinsToolStripMenuItem");
+ this.importSkinsToolStripMenuItem.Name = "importSkinsToolStripMenuItem";
+ //
+ // importSkinToolStripMenuItem
+ //
+ resources.ApplyResources(this.importSkinToolStripMenuItem, "importSkinToolStripMenuItem");
+ this.importSkinToolStripMenuItem.Name = "importSkinToolStripMenuItem";
+ this.importSkinToolStripMenuItem.Click += new System.EventHandler(this.importSkinToolStripMenuItem_Click);
+ //
+ // importExtractedSkinsFolderToolStripMenuItem
+ //
+ resources.ApplyResources(this.importExtractedSkinsFolderToolStripMenuItem, "importExtractedSkinsFolderToolStripMenuItem");
+ this.importExtractedSkinsFolderToolStripMenuItem.Name = "importExtractedSkinsFolderToolStripMenuItem";
+ this.importExtractedSkinsFolderToolStripMenuItem.Click += new System.EventHandler(this.importExtractedSkinsFolder);
+ //
+ // addTextureToolStripMenuItem
+ //
+ this.addTextureToolStripMenuItem.Image = global::PckStudio.Properties.Resources.AddTexture;
+ this.addTextureToolStripMenuItem.Name = "addTextureToolStripMenuItem";
+ resources.ApplyResources(this.addTextureToolStripMenuItem, "addTextureToolStripMenuItem");
+ this.addTextureToolStripMenuItem.Click += new System.EventHandler(this.addTextureToolStripMenuItem_Click);
+ //
+ // addFileToolStripMenuItem
+ //
+ this.addFileToolStripMenuItem.Image = global::PckStudio.Properties.Resources.blank;
+ this.addFileToolStripMenuItem.Name = "addFileToolStripMenuItem";
+ resources.ApplyResources(this.addFileToolStripMenuItem, "addFileToolStripMenuItem");
+ this.addFileToolStripMenuItem.Click += new System.EventHandler(this.addFileToolStripMenuItem_Click);
+ //
+ // exportToolStripMenuItem
+ //
+ this.exportToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.as3DSTextureFileToolStripMenuItem});
+ this.exportToolStripMenuItem.Name = "exportToolStripMenuItem";
+ resources.ApplyResources(this.exportToolStripMenuItem, "exportToolStripMenuItem");
+ //
+ // as3DSTextureFileToolStripMenuItem
+ //
+ this.as3DSTextureFileToolStripMenuItem.Name = "as3DSTextureFileToolStripMenuItem";
+ resources.ApplyResources(this.as3DSTextureFileToolStripMenuItem, "as3DSTextureFileToolStripMenuItem");
+ this.as3DSTextureFileToolStripMenuItem.Click += new System.EventHandler(this.as3DSTextureFileToolStripMenuItem_Click);
+ //
+ // setFileTypeToolStripMenuItem
+ //
+ this.setFileTypeToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.skinToolStripMenuItem1,
+ this.capeToolStripMenuItem,
+ this.textureToolStripMenuItem,
+ this.languagesFileLOCToolStripMenuItem,
+ this.gameRulesFileGRFToolStripMenuItem,
+ this.audioPCKFileToolStripMenuItem,
+ this.coloursCOLFileToolStripMenuItem,
+ this.gameRulesHeaderGRHToolStripMenuItem,
+ this.skinsPCKToolStripMenuItem,
+ this.modelsFileBINToolStripMenuItem,
+ this.behavioursFileBINToolStripMenuItem,
+ this.entityMaterialsFileBINToolStripMenuItem});
+ this.setFileTypeToolStripMenuItem.Name = "setFileTypeToolStripMenuItem";
+ resources.ApplyResources(this.setFileTypeToolStripMenuItem, "setFileTypeToolStripMenuItem");
+ //
+ // skinToolStripMenuItem1
+ //
+ this.skinToolStripMenuItem1.Image = global::PckStudio.Properties.Resources.SKIN_ICON;
+ this.skinToolStripMenuItem1.Name = "skinToolStripMenuItem1";
+ resources.ApplyResources(this.skinToolStripMenuItem1, "skinToolStripMenuItem1");
+ //
+ // capeToolStripMenuItem
+ //
+ this.capeToolStripMenuItem.Image = global::PckStudio.Properties.Resources.CAPE_ICON;
+ this.capeToolStripMenuItem.Name = "capeToolStripMenuItem";
+ resources.ApplyResources(this.capeToolStripMenuItem, "capeToolStripMenuItem");
+ //
+ // textureToolStripMenuItem
+ //
+ this.textureToolStripMenuItem.Image = global::PckStudio.Properties.Resources.TEXTURE_ICON;
+ this.textureToolStripMenuItem.Name = "textureToolStripMenuItem";
+ resources.ApplyResources(this.textureToolStripMenuItem, "textureToolStripMenuItem");
+ //
+ // languagesFileLOCToolStripMenuItem
+ //
+ this.languagesFileLOCToolStripMenuItem.Image = global::PckStudio.Properties.Resources.LOC_ICON;
+ this.languagesFileLOCToolStripMenuItem.Name = "languagesFileLOCToolStripMenuItem";
+ resources.ApplyResources(this.languagesFileLOCToolStripMenuItem, "languagesFileLOCToolStripMenuItem");
+ //
+ // gameRulesFileGRFToolStripMenuItem
+ //
+ this.gameRulesFileGRFToolStripMenuItem.Image = global::PckStudio.Properties.Resources.GRF_ICON;
+ this.gameRulesFileGRFToolStripMenuItem.Name = "gameRulesFileGRFToolStripMenuItem";
+ resources.ApplyResources(this.gameRulesFileGRFToolStripMenuItem, "gameRulesFileGRFToolStripMenuItem");
+ //
+ // audioPCKFileToolStripMenuItem
+ //
+ this.audioPCKFileToolStripMenuItem.Image = global::PckStudio.Properties.Resources.BINKA_ICON;
+ this.audioPCKFileToolStripMenuItem.Name = "audioPCKFileToolStripMenuItem";
+ resources.ApplyResources(this.audioPCKFileToolStripMenuItem, "audioPCKFileToolStripMenuItem");
+ //
+ // coloursCOLFileToolStripMenuItem
+ //
+ this.coloursCOLFileToolStripMenuItem.Image = global::PckStudio.Properties.Resources.COL_ICON;
+ this.coloursCOLFileToolStripMenuItem.Name = "coloursCOLFileToolStripMenuItem";
+ resources.ApplyResources(this.coloursCOLFileToolStripMenuItem, "coloursCOLFileToolStripMenuItem");
+ //
+ // gameRulesHeaderGRHToolStripMenuItem
+ //
+ this.gameRulesHeaderGRHToolStripMenuItem.Image = global::PckStudio.Properties.Resources.GRH_ICON;
+ this.gameRulesHeaderGRHToolStripMenuItem.Name = "gameRulesHeaderGRHToolStripMenuItem";
+ resources.ApplyResources(this.gameRulesHeaderGRHToolStripMenuItem, "gameRulesHeaderGRHToolStripMenuItem");
+ //
+ // skinsPCKToolStripMenuItem
+ //
+ this.skinsPCKToolStripMenuItem.Image = global::PckStudio.Properties.Resources.SKINS_ICON;
+ this.skinsPCKToolStripMenuItem.Name = "skinsPCKToolStripMenuItem";
+ resources.ApplyResources(this.skinsPCKToolStripMenuItem, "skinsPCKToolStripMenuItem");
+ //
+ // modelsFileBINToolStripMenuItem
+ //
+ this.modelsFileBINToolStripMenuItem.Image = global::PckStudio.Properties.Resources.MODELS_ICON;
+ this.modelsFileBINToolStripMenuItem.Name = "modelsFileBINToolStripMenuItem";
+ resources.ApplyResources(this.modelsFileBINToolStripMenuItem, "modelsFileBINToolStripMenuItem");
+ //
+ // behavioursFileBINToolStripMenuItem
+ //
+ this.behavioursFileBINToolStripMenuItem.Image = global::PckStudio.Properties.Resources.BEHAVIOURS_ICON;
+ this.behavioursFileBINToolStripMenuItem.Name = "behavioursFileBINToolStripMenuItem";
+ resources.ApplyResources(this.behavioursFileBINToolStripMenuItem, "behavioursFileBINToolStripMenuItem");
+ //
+ // entityMaterialsFileBINToolStripMenuItem
+ //
+ this.entityMaterialsFileBINToolStripMenuItem.Image = global::PckStudio.Properties.Resources.ENTITY_MATERIALS_ICON;
+ this.entityMaterialsFileBINToolStripMenuItem.Name = "entityMaterialsFileBINToolStripMenuItem";
+ resources.ApplyResources(this.entityMaterialsFileBINToolStripMenuItem, "entityMaterialsFileBINToolStripMenuItem");
+ //
+ // toolStripSeparator5
+ //
+ this.toolStripSeparator5.Name = "toolStripSeparator5";
+ resources.ApplyResources(this.toolStripSeparator5, "toolStripSeparator5");
+ //
+ // miscFunctionsToolStripMenuItem
+ //
+ this.miscFunctionsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.generateMipMapTextureToolStripMenuItem1,
+ this.viewFileInfoToolStripMenuItem,
+ this.correctSkinDecimalsToolStripMenuItem,
+ this.setSubPCKEndiannessToolStripMenuItem,
+ this.setModelContainerFormatToolStripMenuItem});
+ this.miscFunctionsToolStripMenuItem.Name = "miscFunctionsToolStripMenuItem";
+ resources.ApplyResources(this.miscFunctionsToolStripMenuItem, "miscFunctionsToolStripMenuItem");
+ //
+ // generateMipMapTextureToolStripMenuItem1
+ //
+ this.generateMipMapTextureToolStripMenuItem1.Name = "generateMipMapTextureToolStripMenuItem1";
+ resources.ApplyResources(this.generateMipMapTextureToolStripMenuItem1, "generateMipMapTextureToolStripMenuItem1");
+ this.generateMipMapTextureToolStripMenuItem1.Click += new System.EventHandler(this.generateMipMapTextureToolStripMenuItem_Click);
+ //
+ // viewFileInfoToolStripMenuItem
+ //
+ this.viewFileInfoToolStripMenuItem.Name = "viewFileInfoToolStripMenuItem";
+ resources.ApplyResources(this.viewFileInfoToolStripMenuItem, "viewFileInfoToolStripMenuItem");
+ this.viewFileInfoToolStripMenuItem.Click += new System.EventHandler(this.viewFileInfoToolStripMenuItem_Click);
+ //
+ // correctSkinDecimalsToolStripMenuItem
+ //
+ this.correctSkinDecimalsToolStripMenuItem.Name = "correctSkinDecimalsToolStripMenuItem";
+ resources.ApplyResources(this.correctSkinDecimalsToolStripMenuItem, "correctSkinDecimalsToolStripMenuItem");
+ this.correctSkinDecimalsToolStripMenuItem.Click += new System.EventHandler(this.correctSkinDecimalsToolStripMenuItem_Click);
+ //
+ // setSubPCKEndiannessToolStripMenuItem
+ //
+ this.setSubPCKEndiannessToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.bigEndianXbox360PS3WiiUToolStripMenuItem,
+ this.littleEndianPS4PSVitaSwitchToolStripMenuItem});
+ this.setSubPCKEndiannessToolStripMenuItem.Name = "setSubPCKEndiannessToolStripMenuItem";
+ resources.ApplyResources(this.setSubPCKEndiannessToolStripMenuItem, "setSubPCKEndiannessToolStripMenuItem");
+ //
+ // bigEndianXbox360PS3WiiUToolStripMenuItem
+ //
+ this.bigEndianXbox360PS3WiiUToolStripMenuItem.Name = "bigEndianXbox360PS3WiiUToolStripMenuItem";
+ resources.ApplyResources(this.bigEndianXbox360PS3WiiUToolStripMenuItem, "bigEndianXbox360PS3WiiUToolStripMenuItem");
+ this.bigEndianXbox360PS3WiiUToolStripMenuItem.Click += new System.EventHandler(this.bigEndianToolStripMenuItem_Click);
+ //
+ // littleEndianPS4PSVitaSwitchToolStripMenuItem
+ //
+ this.littleEndianPS4PSVitaSwitchToolStripMenuItem.Name = "littleEndianPS4PSVitaSwitchToolStripMenuItem";
+ resources.ApplyResources(this.littleEndianPS4PSVitaSwitchToolStripMenuItem, "littleEndianPS4PSVitaSwitchToolStripMenuItem");
+ this.littleEndianPS4PSVitaSwitchToolStripMenuItem.Click += new System.EventHandler(this.littleEndianToolStripMenuItem_Click);
+ //
+ // setModelContainerFormatToolStripMenuItem
+ //
+ this.setModelContainerFormatToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.version1ToolStripMenuItem,
+ this.version2ToolStripMenuItem,
+ this.version3114ToolStripMenuItem});
+ this.setModelContainerFormatToolStripMenuItem.Name = "setModelContainerFormatToolStripMenuItem";
+ resources.ApplyResources(this.setModelContainerFormatToolStripMenuItem, "setModelContainerFormatToolStripMenuItem");
+ //
+ // version1ToolStripMenuItem
+ //
+ this.version1ToolStripMenuItem.Name = "version1ToolStripMenuItem";
+ resources.ApplyResources(this.version1ToolStripMenuItem, "version1ToolStripMenuItem");
+ this.version1ToolStripMenuItem.Click += new System.EventHandler(this.setModelVersion1ToolStripMenuItem_Click);
+ //
+ // version2ToolStripMenuItem
+ //
+ this.version2ToolStripMenuItem.Name = "version2ToolStripMenuItem";
+ resources.ApplyResources(this.version2ToolStripMenuItem, "version2ToolStripMenuItem");
+ this.version2ToolStripMenuItem.Click += new System.EventHandler(this.setModelVersion2ToolStripMenuItem_Click);
+ //
+ // version3114ToolStripMenuItem
+ //
+ this.version3114ToolStripMenuItem.Name = "version3114ToolStripMenuItem";
+ resources.ApplyResources(this.version3114ToolStripMenuItem, "version3114ToolStripMenuItem");
+ this.version3114ToolStripMenuItem.Click += new System.EventHandler(this.setModelVersion3ToolStripMenuItem_Click);
+ //
+ // extractToolStripMenuItem
+ //
+ resources.ApplyResources(this.extractToolStripMenuItem, "extractToolStripMenuItem");
+ this.extractToolStripMenuItem.Name = "extractToolStripMenuItem";
+ this.extractToolStripMenuItem.Click += new System.EventHandler(this.extractToolStripMenuItem_Click);
+ //
+ // toolStripSeparator6
+ //
+ this.toolStripSeparator6.Name = "toolStripSeparator6";
+ resources.ApplyResources(this.toolStripSeparator6, "toolStripSeparator6");
+ //
+ // cloneFileToolStripMenuItem
+ //
+ this.cloneFileToolStripMenuItem.Name = "cloneFileToolStripMenuItem";
+ resources.ApplyResources(this.cloneFileToolStripMenuItem, "cloneFileToolStripMenuItem");
+ this.cloneFileToolStripMenuItem.Click += new System.EventHandler(this.cloneFileToolStripMenuItem_Click);
+ //
+ // renameFileToolStripMenuItem
+ //
+ resources.ApplyResources(this.renameFileToolStripMenuItem, "renameFileToolStripMenuItem");
+ this.renameFileToolStripMenuItem.Name = "renameFileToolStripMenuItem";
+ this.renameFileToolStripMenuItem.Click += new System.EventHandler(this.renameFileToolStripMenuItem_Click);
+ //
+ // replaceToolStripMenuItem
+ //
+ resources.ApplyResources(this.replaceToolStripMenuItem, "replaceToolStripMenuItem");
+ this.replaceToolStripMenuItem.Name = "replaceToolStripMenuItem";
+ this.replaceToolStripMenuItem.Click += new System.EventHandler(this.replaceToolStripMenuItem_Click);
+ //
+ // deleteFileToolStripMenuItem
+ //
+ this.deleteFileToolStripMenuItem.Image = global::PckStudio.Properties.Resources.file_delete;
+ this.deleteFileToolStripMenuItem.Name = "deleteFileToolStripMenuItem";
+ resources.ApplyResources(this.deleteFileToolStripMenuItem, "deleteFileToolStripMenuItem");
+ this.deleteFileToolStripMenuItem.Click += new System.EventHandler(this.deleteFileToolStripMenuItem_Click);
+ //
+ // imageList
+ //
+ this.imageList.ColorDepth = System.Windows.Forms.ColorDepth.Depth32Bit;
+ resources.ApplyResources(this.imageList, "imageList");
+ this.imageList.TransparentColor = System.Drawing.Color.Transparent;
+ //
+ // addMultipleEntriesToolStripMenuItem
+ //
+ resources.ApplyResources(this.addMultipleEntriesToolStripMenuItem, "addMultipleEntriesToolStripMenuItem");
+ this.addMultipleEntriesToolStripMenuItem.Name = "addMultipleEntriesToolStripMenuItem";
+ //
+ // LittleEndianCheckBox
+ //
+ resources.ApplyResources(this.LittleEndianCheckBox, "LittleEndianCheckBox");
+ this.LittleEndianCheckBox.BackColor = System.Drawing.Color.Transparent;
+ this.LittleEndianCheckBox.Name = "LittleEndianCheckBox";
+ this.LittleEndianCheckBox.Style = MetroFramework.MetroColorStyle.White;
+ this.LittleEndianCheckBox.Theme = MetroFramework.MetroThemeStyle.Dark;
+ this.LittleEndianCheckBox.UseSelectable = true;
+ //
+ // previewPictureBox
+ //
+ resources.ApplyResources(this.previewPictureBox, "previewPictureBox");
+ this.previewPictureBox.BackColor = System.Drawing.Color.Transparent;
+ this.previewPictureBox.BackgroundInterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Default;
+ this.previewPictureBox.Image = global::PckStudio.Properties.Resources.NoImageFound;
+ this.previewPictureBox.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
+ this.previewPictureBox.Name = "previewPictureBox";
+ this.previewPictureBox.TabStop = false;
+ //
+ // PckEditor
+ //
+ this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(18)))), ((int)(((byte)(18)))), ((int)(((byte)(18)))));
+ resources.ApplyResources(this, "$this");
+ this.Controls.Add(this.previewPictureBox);
+ this.Controls.Add(this.LittleEndianCheckBox);
+ this.Controls.Add(this.pckFileLabel);
+ this.Controls.Add(this.labelImageSize);
+ this.Controls.Add(this.fileEntryCountLabel);
+ this.Controls.Add(this.PropertiesTabControl);
+ this.Controls.Add(this.label11);
+ this.Controls.Add(this.treeViewMain);
+ this.Controls.Add(logoPictureBox);
+ this.ForeColor = System.Drawing.Color.Transparent;
+ this.Name = "PckEditor";
+ this.Load += new System.EventHandler(this.PckEditor_Load);
+ ((System.ComponentModel.ISupportInitialize)(logoPictureBox)).EndInit();
+ this.PropertiesTabControl.ResumeLayout(false);
+ this.MetaTab.ResumeLayout(false);
+ this.MetaTab.PerformLayout();
+ this.contextMenuMetaTree.ResumeLayout(false);
+ this.contextMenuPCKEntries.ResumeLayout(false);
+ ((System.ComponentModel.ISupportInitialize)(this.previewPictureBox)).EndInit();
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private MetroFramework.Controls.MetroLabel pckFileLabel;
+ private MetroFramework.Controls.MetroLabel labelImageSize;
+ private MetroFramework.Controls.MetroLabel fileEntryCountLabel;
+ private MetroFramework.Controls.MetroTabControl PropertiesTabControl;
+ private MetroFramework.Controls.MetroTabPage MetaTab;
+ private System.Windows.Forms.TreeView treeMeta;
+ private MetroFramework.Controls.MetroLabel label11;
+ private System.Windows.Forms.TreeView treeViewMain;
+ private PckStudio.ToolboxItems.InterpolationPictureBox previewPictureBox;
+ private System.Windows.Forms.ContextMenuStrip contextMenuMetaTree;
+ private System.Windows.Forms.ToolStripMenuItem addEntryToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem addEntryToolStripMenuItem1;
+ private System.Windows.Forms.ToolStripMenuItem addBOXEntryToolStripMenuItem1;
+ private System.Windows.Forms.ToolStripMenuItem addANIMEntryToolStripMenuItem1;
+ private System.Windows.Forms.ToolStripMenuItem addMultipleEntriesToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem deleteEntryToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem editAllEntriesToolStripMenuItem;
+ private System.Windows.Forms.ContextMenuStrip contextMenuPCKEntries;
+ private System.Windows.Forms.ToolStripMenuItem createToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem folderToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem skinToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem createAnimatedTextureToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem audiopckToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem colourscolToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem CreateSkinsPCKToolStripMenuItem1;
+ private System.Windows.Forms.ToolStripMenuItem behavioursbinToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem entityMaterialsbinToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem importSkinsToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem importSkinToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem importExtractedSkinsFolderToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem addTextureToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem addFileToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem exportToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem as3DSTextureFileToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem setFileTypeToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem skinToolStripMenuItem1;
+ private System.Windows.Forms.ToolStripMenuItem capeToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem textureToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem languagesFileLOCToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem gameRulesFileGRFToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem audioPCKFileToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem coloursCOLFileToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem gameRulesHeaderGRHToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem skinsPCKToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem modelsFileBINToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem behavioursFileBINToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem entityMaterialsFileBINToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem miscFunctionsToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem generateMipMapTextureToolStripMenuItem1;
+ private System.Windows.Forms.ToolStripMenuItem viewFileInfoToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem correctSkinDecimalsToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem extractToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem cloneFileToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem renameFileToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem replaceToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem deleteFileToolStripMenuItem;
+ private System.Windows.Forms.ImageList imageList;
+ private System.Windows.Forms.ToolStripMenuItem addMultipleEntriesToolStripMenuItem1;
+ private MetroFramework.Controls.MetroLabel metroLabel2;
+ private MetroFramework.Controls.MetroTextBox entryTypeTextBox;
+ private MetroFramework.Controls.MetroTextBox entryDataTextBox;
+ private MetroFramework.Controls.MetroButton buttonEdit;
+ private MetroFramework.Controls.MetroLabel metroLabel1;
+ private MetroFramework.Controls.MetroCheckBox LittleEndianCheckBox;
+ private System.Windows.Forms.ToolStripMenuItem setSubPCKEndiannessToolStripMenuItem;
+ private ToolStripMenuItem bigEndianXbox360PS3WiiUToolStripMenuItem;
+ private ToolStripMenuItem littleEndianPS4PSVitaSwitchToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem setModelContainerFormatToolStripMenuItem;
+ private ToolStripMenuItem version1ToolStripMenuItem;
+ private ToolStripMenuItem version2ToolStripMenuItem;
+ private ToolStripMenuItem version3114ToolStripMenuItem;
+ private ToolStripSeparator toolStripSeparator5;
+ private ToolStripSeparator toolStripSeparator6;
+ }
+}
diff --git a/PCK-Studio/Controls/PckEditor.cs b/PCK-Studio/Controls/PckEditor.cs
new file mode 100644
index 00000000..dc461bac
--- /dev/null
+++ b/PCK-Studio/Controls/PckEditor.cs
@@ -0,0 +1,2251 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Windows.Forms;
+using System.Drawing.Drawing2D;
+
+using MetroFramework.Forms;
+
+using OMI.Formats.Languages;
+using OMI.Formats.Pck;
+using OMI.Workers.Language;
+using OMI.Workers.Pck;
+
+using OMI.Workers;
+using OMI.Formats.Model;
+using OMI.Workers.Model;
+using OMI.Formats.GameRule;
+using OMI.Workers.GameRule;
+using OMI.Formats.Material;
+using OMI.Workers.Material;
+using OMI.Formats.Behaviour;
+using OMI.Workers.Behaviour;
+using OMI.Formats.Color;
+using OMI.Workers.Color;
+
+using PckStudio.Core.Extensions;
+using PckStudio.Forms.Editor;
+using PckStudio.Forms.Additional_Popups;
+using PckStudio.Forms.Additional_Popups.Animation;
+using PckStudio.Interfaces;
+using PckStudio.Internal;
+using PckStudio.Popups;
+using PckStudio.Properties;
+
+using PckStudio.Core.Deserializer;
+using PckStudio.Core.Serializer;
+using PckStudio.Core.Json;
+using PckStudio.Core.FileFormats;
+using PckStudio.Core.Skin;
+using PckStudio.Rendering;
+using PckStudio.Core;
+using PckStudio.ModelSupport;
+using PckStudio.Json;
+using PckStudio.Core.IO.PckAudio;
+using PckStudio.Core.IO._3DST;
+using PckStudio.Core.Misc;
+
+namespace PckStudio.Controls
+{
+ internal partial class PckEditor : EditorControl
+ {
+
+ private string _location = string.Empty;
+
+ private readonly OMI.ByteOrder _originalEndianness;
+ private OMI.ByteOrder _currentEndianness;
+ private bool __modified = false;
+ private bool _wasModified
+ {
+ get => __modified;
+ set
+ {
+ if (__modified != value)
+ {
+ __modified = value;
+ _onModifiedChangeDelegate?.Invoke(value);
+ }
+ }
+ }
+
+ private delegate void OnModifiedChangeDelegate(bool state);
+ private OnModifiedChangeDelegate _onModifiedChangeDelegate;
+
+ private int _timesSaved = 0;
+
+ private readonly Dictionary> _pckAssetTypeHandler;
+
+ public PckEditor(PackInfo packInfo, ISaveContext saveContext)
+ : base(packInfo, saveContext)
+ {
+ InitializeComponent();
+ _onModifiedChangeDelegate = OnModify;
+ _originalEndianness = packInfo.Endianness;
+ _currentEndianness = packInfo.Endianness;
+
+ LittleEndianCheckBox.Visible = packInfo.AllowEndianSwap;
+
+ treeViewMain.TreeViewNodeSorter = new PckNodeSorter();
+
+ skinToolStripMenuItem1.Click += (sender, e) => SetFileType(PckAssetType.SkinFile);
+ capeToolStripMenuItem.Click += (sender, e) => SetFileType(PckAssetType.CapeFile);
+ textureToolStripMenuItem.Click += (sender, e) => SetFileType(PckAssetType.TextureFile);
+ languagesFileLOCToolStripMenuItem.Click += (sender, e) => SetFileType(PckAssetType.LocalisationFile);
+ gameRulesFileGRFToolStripMenuItem.Click += (sender, e) => SetFileType(PckAssetType.GameRulesFile);
+ audioPCKFileToolStripMenuItem.Click += (sender, e) => SetFileType(PckAssetType.AudioFile);
+ coloursCOLFileToolStripMenuItem.Click += (sender, e) => SetFileType(PckAssetType.ColourTableFile);
+ gameRulesHeaderGRHToolStripMenuItem.Click += (sender, e) => SetFileType(PckAssetType.GameRulesHeader);
+ skinsPCKToolStripMenuItem.Click += (sender, e) => SetFileType(PckAssetType.SkinDataFile);
+ modelsFileBINToolStripMenuItem.Click += (sender, e) => SetFileType(PckAssetType.ModelsFile);
+ behavioursFileBINToolStripMenuItem.Click += (sender, e) => SetFileType(PckAssetType.BehavioursFile);
+ entityMaterialsFileBINToolStripMenuItem.Click += (sender, e) => SetFileType(PckAssetType.MaterialFile);
+
+ imageList.Images.Add(Resources.ZZFolder); // Icon for folders
+ imageList.Images.Add(Resources.BINKA_ICON); // Icon for music cue file (audio.pck)
+ imageList.Images.Add(Resources.IMAGE_ICON); // Icon for images (unused for now)
+ imageList.Images.Add(Resources.LOC_ICON); // Icon for string localization files (languages.loc;localisation.loc)
+ imageList.Images.Add(Resources.PCK_ICON); // Icon for generic PCK files (*.pck)
+ imageList.Images.Add(Resources.ZUnknown); // Icon for Unknown formats
+ imageList.Images.Add(Resources.COL_ICON); // Icon for color palette files (colours.col)
+ imageList.Images.Add(Resources.SKINS_ICON); // Icon for Skin.pck archives (skins.pck)
+ imageList.Images.Add(Resources.MODELS_ICON); // Icon for Model files (models.bin)
+ imageList.Images.Add(Resources.GRF_ICON); // Icon for Game Rule files (*.grf)
+ imageList.Images.Add(Resources.GRH_ICON); // Icon for Game Rule Header files (*.grh)
+ imageList.Images.Add(Resources.INFO_ICON); // Icon for Info files (0)
+ imageList.Images.Add(Resources.SKIN_ICON); // Icon for Skin files (*.png)
+ imageList.Images.Add(Resources.CAPE_ICON); // Icon for Cape files (*.png)
+ imageList.Images.Add(Resources.TEXTURE_ICON); // Icon for Texture files (*.png;*.tga)
+ imageList.Images.Add(Resources.BEHAVIOURS_ICON); // Icon for Behaviour files (behaviours.bin)
+ imageList.Images.Add(Resources.ENTITY_MATERIALS_ICON); // Icon for Entity Material files (entityMaterials.bin)
+
+ _pckAssetTypeHandler = new Dictionary>(15)
+ {
+ [PckAssetType.SkinFile] = HandleSkinFile,
+ [PckAssetType.CapeFile] = null,
+ [PckAssetType.TextureFile] = HandleTextureFile,
+ [PckAssetType.UIDataFile] = _ => throw new NotSupportedException("unused in-game"),
+ [PckAssetType.InfoFile] = null,
+ [PckAssetType.TexturePackInfoFile] = HandleInnerPckFile,
+ [PckAssetType.LocalisationFile] = HandleLocalisationFile,
+ [PckAssetType.GameRulesFile] = HandleGameRuleFile,
+ [PckAssetType.AudioFile] = HandleAudioFile,
+ [PckAssetType.ColourTableFile] = HandleColourFile,
+ [PckAssetType.GameRulesHeader] = HandleGameRuleFile,
+ [PckAssetType.SkinDataFile] = HandleInnerPckFile,
+ [PckAssetType.ModelsFile] = HandleModelsFile,
+ [PckAssetType.BehavioursFile] = HandleBehavioursFile,
+ [PckAssetType.MaterialFile] = HandleMaterialFile,
+ };
+ }
+
+ public new void Save()
+ {
+ base.Save();
+ _timesSaved++;
+ _wasModified = false;
+ }
+
+ public override void SaveAs()
+ {
+ using SaveFileDialog saveFileDialog = new SaveFileDialog
+ {
+ Filter = "PCK (Minecraft Console Package)|*.pck",
+ DefaultExt = ".pck",
+ };
+ if (saveFileDialog.ShowDialog() == DialogResult.OK)
+ {
+ SaveTo(saveFileDialog.FileName);
+ pckFileLabel.Text = "Current PCK File: " + Path.GetFileName(_location);
+ }
+ }
+
+ public override void Close()
+ {
+ if (_wasModified && MessageBox.Show("Save PCK?", "Modified PCK", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
+ Save();
+ }
+
+ private void OnModify(bool state)
+ {
+ pckFileLabel.Text = state && !pckFileLabel.Text.StartsWith("*") ? "*" + pckFileLabel.Text : pckFileLabel.Text.Substring(1);
+ }
+
+ public override void UpdateView()
+ {
+ BuildMainTreeView();
+ }
+
+ private void SaveTo(string filepath)
+ {
+ _location = filepath;
+ Save();
+ }
+
+ private void HandleInnerPckFile(PckAsset asset)
+ {
+ if (asset.Type != PckAssetType.SkinDataFile && asset.Type != PckAssetType.TexturePackInfoFile || asset.Size <= 0 || !Settings.Default.LoadSubPcks)
+ return;
+
+ ISaveContext saveContext = new DelegatedSaveContext(false, (packInfo) =>
+ {
+ if (packInfo.IsValid)
+ {
+ asset.SetData(new PckFileWriter(packInfo.File, _currentEndianness));
+ _wasModified = true;
+ }
+ });
+
+ string caption = Path.GetFileName(asset.Filename);
+ string identifier = _location + Path.GetFileName(asset.Filename);
+ PckFile pckFile = asset.GetData(new PckFileReader(_originalEndianness));
+ PackInfo packInfo = PackInfo.Create(pckFile, _originalEndianness, false);
+
+ // TODO: may change to use a new tab page that will be closed when the main pck is closed
+ //Program.MainInstance.OpenNewPckTab(caption, identifier, packInfo, saveContext);
+ }
+
+ private void HandleTextureFile(PckAsset asset)
+ {
+ _ = asset.IsMipmappedFile() && EditorValue.File.TryGetAsset(asset.GetNormalPath(), PckAssetType.TextureFile, out asset);
+
+ if (asset.Size <= 0)
+ {
+ Trace.TraceInformation($"[{nameof(PckEditor)}:{nameof(HandleTextureFile)}] '{asset.Filename}' size is 0.");
+ return;
+ }
+
+ ResourceLocation resourceLocation = ResourceLocation.GetFromPath(asset.Filename);
+ Debug.WriteLine("Handling Resource file: " + resourceLocation?.ToString());
+
+ switch (resourceLocation.Category)
+ {
+ case ResourceCategory.Unknown:
+ Debug.WriteLine($"Unknown Resource Category.");
+ break;
+ case ResourceCategory.MobEntityTextures:
+ case ResourceCategory.ItemEntityTextures:
+ {
+ string texturePath = asset.Filename.Substring(0, asset.Filename.Length - Path.GetExtension(asset.Filename).Length);
+ string[] modelNames = GameModelImporter.ModelMetaData.Where(kv => kv.Value.TextureLocations.Contains(texturePath)).Select(kv => kv.Key).ToArray();
+
+ if (modelNames.Length == 0)
+ {
+ MessageBox.Show("No Model info found");
+ return;
+ }
+
+ string modelName = modelNames[0];
+ if (modelNames.Length > 1)
+ {
+ using ItemSelectionPopUp itemSelectionPopUp = new ItemSelectionPopUp(modelNames.ToArray());
+ itemSelectionPopUp.ButtonText = "View";
+ itemSelectionPopUp.LabelText = "Models:";
+ if (itemSelectionPopUp.ShowDialog() != DialogResult.OK || !modelNames.IndexInRange(itemSelectionPopUp.SelectedIndex))
+ {
+ return;
+ }
+ modelName = modelNames[itemSelectionPopUp.SelectedIndex];
+ }
+
+ Image texture = asset.GetTexture();
+ string textureName = Path.GetFileName(texturePath);
+
+ NamedData modelTexture = new NamedData(textureName, texture);
+
+ bool hasCustomModel = false;
+ bool hasDefaultModel = TryGetDefaultEntityModel(modelName, out Model model);
+ if (EditorValue.File.TryGetAsset("models.bin", PckAssetType.ModelsFile, out PckAsset modelsAsset))
+ {
+ ModelContainer models = modelsAsset.GetData(new ModelFileReader());
+ hasCustomModel = models.ContainsModel(modelName);
+ if (hasCustomModel)
+ {
+ Debug.WriteLine($"Custom model for '{modelName}' found.");
+ model = models.GetModelByName(modelName);
+ }
+ }
+ if (!hasDefaultModel && !hasCustomModel)
+ {
+ MessageBox.Show(this, $"Not Model found for: {modelName}");
+ return;
+ }
+
+ ShowSimpleModelRender(model, modelTexture);
+ }
+ break;
+
+ case ResourceCategory.ItemAnimation:
+ case ResourceCategory.BlockAnimation:
+ Animation animation = asset.GetDeserializedData(AnimationDeserializer.DefaultDeserializer);
+ string internalName = Path.GetFileNameWithoutExtension(asset.Filename);
+ IList textureInfos = resourceLocation.Category == ResourceCategory.ItemAnimation ? Tiles.ItemTileInfos : Tiles.BlockTileInfos;
+ string displayname = textureInfos.FirstOrDefault(p => p.InternalName == internalName)?.DisplayName ?? internalName;
+
+ string[] specialTileNames = { "clock", "compass" };
+
+ ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (animation) =>
+ {
+ asset.SetSerializedData(animation, AnimationSerializer.DefaultSerializer);
+ });
+
+ using (AnimationEditor animationEditor = new AnimationEditor(animation, saveContext, displayname, !internalName.ToLower().EqualsAny(specialTileNames)))
+ {
+ if (animationEditor.ShowDialog(this) == DialogResult.OK)
+ {
+ _wasModified = true;
+ BuildMainTreeView();
+ }
+ }
+ break;
+ case ResourceCategory.ParticleAtlas:
+ case ResourceCategory.MoonPhaseAtlas:
+ case ResourceCategory.ItemAtlas:
+ case ResourceCategory.BlockAtlas:
+ case ResourceCategory.BannerAtlas:
+ case ResourceCategory.PaintingAtlas:
+ case ResourceCategory.ExplosionAtlas:
+ case ResourceCategory.ExperienceOrbAtlas:
+ case ResourceCategory.MapIconAtlas:
+ case ResourceCategory.AdditionalMapIconsAtlas:
+ Atlas atlas = asset.GetDeserializedData(new AtlasDeserializer(resourceLocation));
+ ColorContainer colorContainer = default;
+ if (EditorValue.File.TryGetAsset("colours.col", PckAssetType.ColourTableFile, out PckAsset colAsset))
+ colorContainer = colAsset.GetData(new COLFileReader());
+
+ ITryGet tryGetAnimation = TryGet.FromDelegate((string key, out Animation animation) =>
+ {
+ bool found = EditorValue.File.TryGetAsset(key + ".png", PckAssetType.TextureFile, out PckAsset foundAsset) ||
+ EditorValue.File.TryGetAsset(key + ".tga", PckAssetType.TextureFile, out foundAsset);
+ if (found)
+ {
+ animation = foundAsset.GetDeserializedData(AnimationDeserializer.DefaultDeserializer);
+ return true;
+ }
+ animation = default;
+ return false;
+ });
+
+ ITryGet> tryGetAnimationSaveContext = TryGet>
+ .FromDelegate((string key, out ISaveContext animationSaveContext) =>
+ {
+ bool found = EditorValue.File.TryGetAsset(key + ".png", PckAssetType.TextureFile, out PckAsset foundAsset) ||
+ EditorValue.File.TryGetAsset(key + ".tga", PckAssetType.TextureFile, out foundAsset);
+
+ if (found)
+ {
+ animationSaveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (animation) =>
+ foundAsset.SetSerializedData(animation, AnimationSerializer.DefaultSerializer));
+ return true;
+ }
+
+ // you could validate the key(animationAssetPath) for validity. -miku
+ animationSaveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (animation) =>
+ {
+ if (animation.FrameCount == 0)
+ {
+ Debug.WriteLine("New animation has 0 frames. Aborting saving.");
+ return;
+ }
+ PckAsset newAnimationAsset = EditorValue.File.CreateNewAsset(key + ".png", PckAssetType.TextureFile);
+ newAnimationAsset.SetSerializedData(animation, AnimationSerializer.DefaultSerializer);
+ BuildMainTreeView();
+ });
+ return true;
+ });
+
+ ISaveContext textureAtlasSaveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, atlas => asset.SetTexture(atlas));
+
+ var viewer = new TextureAtlasEditor(atlas, textureAtlasSaveContext, resourceLocation, colorContainer, tryGetAnimation, tryGetAnimationSaveContext);
+ if (viewer.ShowDialog(this) == DialogResult.OK)
+ {
+ _wasModified = true;
+ BuildMainTreeView();
+ }
+ break;
+ default:
+ Debug.WriteLine($"Unhandled Resource Category: {resourceLocation.Category}");
+ break;
+ }
+ }
+
+ private void HandleGameRuleFile(PckAsset asset)
+ {
+ const string cDEFLATE = "PS3";
+ const string cXMEM = "Xbox 360";
+ const string cZLIB = "Other Platforms";
+
+ ItemSelectionPopUp dialog = new ItemSelectionPopUp(cZLIB, cDEFLATE, cXMEM);
+ dialog.LabelText = "Type";
+ dialog.ButtonText = "Ok";
+ if (dialog.ShowDialog() != DialogResult.OK)
+ return;
+
+ GameRuleFile.CompressionType compressiontype = dialog.SelectedItem switch
+ {
+ cDEFLATE => GameRuleFile.CompressionType.Deflate,
+ cXMEM => GameRuleFile.CompressionType.XMem,
+ cZLIB => GameRuleFile.CompressionType.Zlib,
+ _ => GameRuleFile.CompressionType.Unknown
+ };
+
+ GameRuleFile grf = asset.GetData(new GameRuleFileReader(compressiontype));
+
+ ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (gameRuleFile) =>
+ {
+ asset.SetData(new GameRuleFileWriter(gameRuleFile));
+ });
+
+ using GameRuleFileEditor grfEditor = new GameRuleFileEditor(grf, saveContext);
+ if (grfEditor.ShowDialog(this) == DialogResult.OK)
+ {
+ _wasModified = true;
+ UpdateRichPresence();
+ }
+ }
+
+ private void HandleAudioFile(PckAsset asset)
+ {
+ try
+ {
+ ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (audioFile) =>
+ {
+ asset.SetData(new PckAudioFileWriter(audioFile, _currentEndianness));
+ });
+ PckAudioFile audioFile = asset.GetData(new PckAudioFileReader(_originalEndianness));
+ using AudioEditor audioEditor = new AudioEditor(audioFile, saveContext);
+ _wasModified = audioEditor.ShowDialog(this) == DialogResult.OK;
+ }
+ catch (OverflowException)
+ {
+ MessageBox.Show(this, $"Failed to open {asset.Filename}\n" +
+ "Try converting the file by using the \"Misc. Functions/Set PCK Endianness\" tool and try again.",
+ "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning);
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show($"Failed to open {asset.Filename}\n" + ex.Message,
+ "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+
+ private void HandleLocalisationFile(PckAsset asset)
+ {
+ LOCFile locFile = asset.GetData(new LOCFileReader());
+ ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (locFile) =>
+ {
+ asset.SetData(new LOCFileWriter(locFile, 2));
+ });
+ using LOCEditor locedit = new LOCEditor(locFile, saveContext);
+ _wasModified = locedit.ShowDialog(this) == DialogResult.OK;
+ UpdateRichPresence();
+ }
+
+ private void HandleColourFile(PckAsset asset)
+ {
+ ColorContainer colorContainer = asset.GetData(new COLFileReader());
+ ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (colorContainer) =>
+ {
+ asset.SetData(new COLFileWriter(colorContainer));
+ });
+ using COLEditor diag = new COLEditor(colorContainer, saveContext);
+ _wasModified = diag.ShowDialog(this) == DialogResult.OK;
+ }
+
+ private void HandleSkinFile(PckAsset asset)
+ {
+ Skin skin = asset.GetSkin();
+ if (asset.HasProperty("CAPEPATH"))
+ {
+ string capeAssetPath = asset.GetProperty("CAPEPATH");
+ if (EditorValue.File.TryGetAsset(capeAssetPath, PckAssetType.CapeFile, out PckAsset capeAsset))
+ {
+ skin.CapeTexture = capeAsset.GetTexture();
+ }
+ }
+
+ ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (customSkin) =>
+ {
+ if (!TryGetLocFile(out LOCFile locFile))
+ Debug.WriteLine("Failed to aquire loc file.");
+ asset.SetSkin(customSkin, locFile);
+ });
+
+ using CustomSkinEditor skinEditor = new CustomSkinEditor(skin, saveContext, EditorValue.File.HasVerionString);
+ if (skinEditor.ShowDialog() == DialogResult.OK)
+ {
+ entryDataTextBox.Text = entryTypeTextBox.Text = string.Empty;
+ _wasModified = true;
+ ReloadMetaTreeView();
+ }
+ }
+
+ private void HandleModelsFile(PckAsset asset)
+ {
+ ModelContainer modelContainer = asset.GetData(new ModelFileReader());
+ if (modelContainer.ModelCount == 0)
+ {
+ MessageBox.Show("No models found.", "Empty Model file", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ return;
+ }
+
+ TryGetDelegate tryGetTexture = (string path, out Image img) =>
+ {
+ bool found = EditorValue.File.TryGetAsset(path + ".png", PckAssetType.TextureFile, out PckAsset asset) ||
+ EditorValue.File.TryGetAsset(path + ".tga", PckAssetType.TextureFile, out asset);
+ img = found ? asset.GetTexture() : default;
+ return found;
+ };
+
+ TrySetDelegate trySetTexture = (string path, Image img) =>
+ {
+ bool found = EditorValue.File.TryGetAsset(path + ".png", PckAssetType.TextureFile, out PckAsset foundAsset) ||
+ EditorValue.File.TryGetAsset(path + ".tga", PckAssetType.TextureFile, out foundAsset);
+ PckAsset asset = foundAsset ?? EditorValue.File.CreateNewAsset(path + ".png", PckAssetType.TextureFile);
+ asset.SetTexture(img);
+ return true;
+ };
+
+ bool hasMaterialAsset = EditorValue.File.TryGetAsset("entityMaterials.bin", PckAssetType.MaterialFile, out PckAsset entityMaterialAsset);
+ IReadOnlyDictionary entityMaterials =
+ hasMaterialAsset
+ ? entityMaterialAsset?.GetData(new MaterialFileReader()).ToDictionary(mat => mat.Name)
+ : new Dictionary();
+
+ ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (modelContainer) =>
+ {
+ asset.SetData(new ModelFileWriter(modelContainer, modelContainer.Version));
+ });
+
+ var editor = new ModelEditor(modelContainer, saveContext, TryGetSet.FromDelegates(tryGetTexture, trySetTexture), TryGet.FromDelegate(entityMaterials.TryGetValue));
+ if (editor.ShowDialog() == DialogResult.OK)
+ {
+ BuildMainTreeView();
+ _wasModified = true;
+ return;
+ }
+ }
+
+ private void HandleBehavioursFile(PckAsset asset)
+ {
+ BehaviourFile behaviourFile = asset.GetData(new BehavioursReader());
+ ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (behaviourFile) =>
+ {
+ asset.SetData(new BehavioursWriter(behaviourFile));
+ });
+ using BehaviourEditor edit = new BehaviourEditor(behaviourFile, saveContext);
+ _wasModified = edit.ShowDialog(this) == DialogResult.OK;
+ }
+
+ private void HandleMaterialFile(PckAsset asset)
+ {
+ MaterialContainer materials = asset.GetData(new MaterialFileReader());
+ ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (materials) =>
+ {
+ asset.SetData(new MaterialFileWriter(materials));
+ });
+ using MaterialsEditor edit = new MaterialsEditor(materials, saveContext);
+ _wasModified = edit.ShowDialog(this) == DialogResult.OK;
+ }
+
+ private void CheckForPasswordAndRemove()
+ {
+ if (EditorValue.File.TryGetAsset("0", PckAssetType.InfoFile, out PckAsset asset))
+ {
+ asset.RemoveProperties("LOCK");
+ }
+ }
+
+ ///
+ /// wrapper that allows the use of in TreeNode.Nodes.Find(, ...) and TreeNode.Nodes.ContainsKey()
+ ///
+ ///
+ ///
+ /// new Created TreeNode
+ private static TreeNode CreateNode(string name, object tag = null)
+ {
+ TreeNode node = new TreeNode(name);
+ node.Name = name;
+ node.Tag = tag;
+ return node;
+ }
+
+ private TreeNode BuildNodeTreeBySeperator(TreeNodeCollection root, string path, char seperator)
+ {
+ _ = root ?? throw new ArgumentNullException(nameof(root));
+ if (!path.Contains(seperator))
+ {
+ TreeNode finalNode = CreateNode(path);
+ root.Add(finalNode);
+ return finalNode;
+ }
+ string nodeText = path.Substring(0, path.IndexOf(seperator));
+ string subPath = path.Substring(path.IndexOf(seperator) + 1);
+
+ if (string.IsNullOrWhiteSpace(nodeText))
+ {
+ return BuildNodeTreeBySeperator(root, subPath, seperator);
+ }
+
+ bool alreadyExists = root.ContainsKey(nodeText);
+ TreeNode subNode = alreadyExists ? root[nodeText] : CreateNode(nodeText);
+ if (!alreadyExists)
+ root.Add(subNode);
+ return BuildNodeTreeBySeperator(subNode.Nodes, subPath, seperator);
+ }
+
+ private void BuildPckTreeView(TreeNodeCollection root, PckFile pckFile)
+ {
+ foreach (PckAsset asset in pckFile.GetAssets())
+ {
+ TreeNode node = BuildNodeTreeBySeperator(root, asset.Filename, '/');
+ node.Tag = asset;
+ int nodeIconId = GetNodeIconId(asset.Type);
+ node.ImageIndex = nodeIconId;
+ node.SelectedImageIndex = nodeIconId;
+ }
+ }
+
+ private void BuildMainTreeView()
+ {
+ // In case the Rename function was just used and the selected node name no longer matches the file name
+ string selectedNodeText = treeViewMain.SelectedNode is TreeNode node ? node.FullPath : string.Empty;
+ previewPictureBox.Image = Resources.NoImageFound;
+ treeMeta.Nodes.Clear();
+ treeViewMain.Nodes.Clear();
+ BuildPckTreeView(treeViewMain.Nodes, EditorValue.File);
+ treeViewMain.Sort();
+
+ TreeNode[] selectedNodes = treeViewMain.FindPath(selectedNodeText);
+ if (selectedNodes.Length > 0)
+ {
+ treeViewMain.SelectedNode = selectedNodes[0];
+ }
+ }
+
+ private int GetNodeIconId(PckAssetType type)
+ {
+ return type switch
+ {
+ PckAssetType.AudioFile => 1,
+ PckAssetType.LocalisationFile => 3,
+ PckAssetType.TexturePackInfoFile => 4,
+ PckAssetType.ColourTableFile => 6,
+ PckAssetType.ModelsFile => 8,
+ PckAssetType.SkinDataFile => 7,
+ PckAssetType.GameRulesFile => 9,
+ PckAssetType.GameRulesHeader => 10,
+ PckAssetType.InfoFile => 11,
+ PckAssetType.SkinFile => 12,
+ PckAssetType.CapeFile => 13,
+ PckAssetType.TextureFile => 14,
+ PckAssetType.BehavioursFile => 15,
+ PckAssetType.MaterialFile => 16,
+ // unknown file format
+ _ => 5,
+ };
+ }
+
+ private List GetAllChildNodes(TreeNodeCollection root)
+ {
+ List childNodes = new List();
+ foreach (TreeNode node in root)
+ {
+ childNodes.Add(node);
+ if (node.Nodes.Count > 0)
+ {
+ childNodes.AddRange(GetAllChildNodes(node.Nodes));
+ }
+ }
+ return childNodes;
+ }
+
+ private bool TryGetLocFile(out LOCFile locFile)
+ {
+ if (!EditorValue.File.TryGetAsset("localisation.loc", PckAssetType.LocalisationFile, out PckAsset locAsset) &&
+ !EditorValue.File.TryGetAsset("languages.loc", PckAssetType.LocalisationFile, out locAsset))
+ {
+ locFile = null;
+ return false;
+ }
+
+ try
+ {
+ locFile = locAsset.GetData(new LOCFileReader());
+ return true;
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine(ex.Message);
+ }
+ locFile = null;
+ return false;
+ }
+
+ private bool TrySetLocFile(in LOCFile locFile)
+ {
+ if (!EditorValue.File.TryGetAsset("localisation.loc", PckAssetType.LocalisationFile, out PckAsset locAsset) &&
+ !EditorValue.File.TryGetAsset("languages.loc", PckAssetType.LocalisationFile, out locAsset))
+ {
+ return false;
+ }
+
+ try
+ {
+ locAsset.SetData(new LOCFileWriter(locFile, 2));
+ return true;
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine(ex.Message);
+ }
+ return false;
+ }
+
+ private void ReloadMetaTreeView()
+ {
+ treeMeta.Nodes.Clear();
+ if (treeViewMain.SelectedNode is TreeNode node &&
+ node.Tag is PckAsset asset)
+ {
+ foreach (KeyValuePair property in asset.GetProperties())
+ {
+ treeMeta.Nodes.Add(CreateNode(property.Key, property));
+ }
+ }
+ }
+
+ private void UpdateRichPresence()
+ {
+ if (EditorValue is not null &&
+ TryGetLocFile(out LOCFile locfile) &&
+ locfile.HasLocEntry("IDS_DISPLAY_NAME") &&
+ locfile.Languages.Contains("en-EN"))
+ {
+ RPC.SetPresence("Editing a Pack:", $" > {locfile.GetLocEntry("IDS_DISPLAY_NAME", "en-EN")}");
+ return;
+ }
+ // default
+ RPC.SetPresence("An Open Source .PCK File Editor");
+ }
+
+ private static PckAsset CreateNewAudioAsset(bool isLittle, PckAudioFile audioFile)
+ {
+ PckAsset newAsset = new PckAsset("audio.pck", PckAssetType.AudioFile);
+ newAsset.SetData(new PckAudioFileWriter(audioFile, isLittle ? OMI.ByteOrder.LittleEndian : OMI.ByteOrder.BigEndian));
+ return newAsset;
+ }
+
+ private static PckAudioFile CreateNewAudioFile()
+ {
+ PckAudioFile audioFile = new PckAudioFile();
+ audioFile.AddCategory(PckAudioFile.AudioCategory.EAudioType.Overworld);
+ audioFile.AddCategory(PckAudioFile.AudioCategory.EAudioType.Nether);
+ audioFile.AddCategory(PckAudioFile.AudioCategory.EAudioType.End);
+ return audioFile;
+ }
+
+ private void addFileToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ using var ofd = new OpenFileDialog();
+ // Suddenly, and randomly, this started throwing an exception because it wasn't formatted correctly?
+ // So now it's formatted correctly and now displays the file type name in the dialog.
+ ofd.Filter = "All files (*.*)|*.*";
+ ofd.Multiselect = false;
+
+ if (ofd.ShowDialog(this) == DialogResult.OK)
+ {
+ using AddFilePrompt diag = new AddFilePrompt("res/" + Path.GetFileName(ofd.FileName));
+ if (diag.ShowDialog(this) == DialogResult.OK)
+ {
+ if (EditorValue.File.Contains(diag.Filepath, diag.Filetype))
+ {
+ MessageBox.Show(this, $"'{diag.Filepath}' of type {diag.Filetype} already exists.", "Import failed", MessageBoxButtons.OK, MessageBoxIcon.Warning);
+ return;
+ }
+ PckAsset asset = EditorValue.File.CreateNewAsset(diag.Filepath, diag.Filetype, () => File.ReadAllBytes(ofd.FileName));
+
+ BuildMainTreeView();
+ _wasModified = true;
+ }
+ }
+ return;
+ }
+
+ private void addTextureToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ using OpenFileDialog fileDialog = new OpenFileDialog();
+ fileDialog.Filter = "Texture File(*.png,*.tga)|*.png;*.tga";
+ if (fileDialog.ShowDialog(this) == DialogResult.OK)
+ {
+ using TextPrompt renamePrompt = new TextPrompt(Path.GetFileName(fileDialog.FileName));
+ renamePrompt.LabelText = "Path";
+ if (renamePrompt.ShowDialog(this) == DialogResult.OK && !string.IsNullOrEmpty(renamePrompt.NewText))
+ {
+ if (EditorValue.File.Contains(renamePrompt.NewText, PckAssetType.TextureFile))
+ {
+ MessageBox.Show(this, $"'{renamePrompt.NewText}' already exists.", "Import failed", MessageBoxButtons.OK, MessageBoxIcon.Warning);
+ return;
+ }
+ PckAsset asset = EditorValue.File.CreateNewAsset(renamePrompt.NewText, PckAssetType.TextureFile, () => File.ReadAllBytes(fileDialog.FileName));
+ BuildMainTreeView();
+ _wasModified = true;
+ }
+ }
+ }
+
+ [Obsolete("Refactor or remove this")]
+ private void importSkinToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ using (OpenFileDialog contents = new OpenFileDialog())
+ {
+ contents.Title = "Select Extracted Skin File";
+ contents.Filter = "Skin File (*.png)|*.png";
+
+ if (contents.ShowDialog() == DialogResult.OK)
+ {
+ string skinNameImport = Path.GetFileName(contents.FileName);
+ byte[] data = File.ReadAllBytes(contents.FileName);
+ PckAsset mfNew = EditorValue.File.CreateNewAsset(skinNameImport, PckAssetType.SkinFile);
+ mfNew.SetData(data);
+ string propertyFile = Path.GetFileNameWithoutExtension(contents.FileName) + ".txt";
+ if (File.Exists(propertyFile))
+ {
+ string[] txtProperties = File.ReadAllLines(propertyFile);
+ if ((txtProperties.Contains("DISPLAYNAMEID") && txtProperties.Contains("DISPLAYNAME")) ||
+ txtProperties.Contains("THEMENAMEID") && txtProperties.Contains("THEMENAME") &&
+ TryGetLocFile(out LOCFile locFile))
+ {
+ // do stuff
+ //l.AddLocKey(locThemeId, locTheme);
+ //using (var stream = new MemoryStream())
+ //{
+ // LOCFileWriter.Write(stream, locFile);
+ // locdata.SetData(stream.ToArray());
+ //}
+ }
+
+ try
+ {
+ foreach (string prop in txtProperties)
+ {
+ string[] arg = prop.Split(':');
+ if (arg.Length < 2)
+ continue;
+ string key = arg[0];
+ string value = arg[1];
+ if (key == "DISPLNAMEID" || key == "THEMENAMEID")
+ {
+
+ }
+ mfNew.AddProperty(key, value);
+ }
+ _wasModified = true;
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show(ex.Message);
+ }
+ }
+ }
+ }
+ }
+
+ private void folderToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ TextPrompt folderNamePrompt = new TextPrompt();
+ if (treeViewMain.SelectedNode is not null)
+ folderNamePrompt.contextLabel.Text =
+ $"New folder at the location of \"{(
+ !treeViewMain.SelectedNode.IsTagOfType()
+ ? "/" + treeViewMain.SelectedNode.FullPath
+ : treeViewMain.SelectedNode.Parent == null ? "/" : "/" + treeViewMain.SelectedNode.Parent.FullPath)}\"";
+ folderNamePrompt.OKButtonText = "Add";
+ if (folderNamePrompt.ShowDialog(this) == DialogResult.OK)
+ {
+ TreeNode folerNode = CreateNode(folderNamePrompt.NewText);
+ folerNode.ImageIndex = 0;
+ folerNode.SelectedImageIndex = 0;
+
+ TreeNodeCollection nodeCollection = treeViewMain.Nodes;
+ if (treeViewMain.SelectedNode is TreeNode node)
+ {
+ if (node.Tag is PckAsset asset &&
+ asset.Type != PckAssetType.TexturePackInfoFile &&
+ asset.Type != PckAssetType.SkinDataFile)
+ {
+ if (node.Parent is TreeNode parentNode)
+ {
+ nodeCollection = parentNode.Nodes;
+ }
+ }
+ else
+ nodeCollection = node.Nodes;
+ }
+ nodeCollection.Add(folerNode);
+ }
+ }
+
+ private void SetFileType(PckAssetType type)
+ {
+ if (treeViewMain.SelectedNode.TryGetTagData(out PckAsset asset))
+ {
+ Debug.WriteLine($"Setting {asset.Type} to {type}");
+ asset.Type = type;
+ int nodeIconId = GetNodeIconId(type);
+ treeViewMain.SelectedNode.ImageIndex = nodeIconId;
+ treeViewMain.SelectedNode.SelectedImageIndex = nodeIconId;
+ }
+ }
+
+ private void treeViewMain_AfterSelect(object sender, TreeViewEventArgs e)
+ {
+ ReloadMetaTreeView();
+
+ entryTypeTextBox.Text = entryDataTextBox.Text = labelImageSize.Text = string.Empty;
+ buttonEdit.Visible = false;
+
+ previewPictureBox.Image = Resources.NoImageFound;
+ viewFileInfoToolStripMenuItem.Visible = false;
+
+ if (!e.Node.TryGetTagData(out PckAsset asset))
+ {
+ return;
+ }
+
+ viewFileInfoToolStripMenuItem.Visible = true;
+ if (asset.HasProperty("BOX"))
+ {
+ buttonEdit.Text = "EDIT BOXES";
+ buttonEdit.Visible = true;
+ }
+ else if (asset.HasProperty("ANIM") &&
+ asset.GetProperty("ANIM", s => SkinANIM.FromString(s) == (SkinAnimMask.RESOLUTION_64x64 | SkinAnimMask.SLIM_MODEL)))
+ {
+ buttonEdit.Text = "View Skin";
+ buttonEdit.Visible = true;
+ }
+
+ switch (asset.Type)
+ {
+ case PckAssetType.SkinFile:
+ case PckAssetType.CapeFile:
+ case PckAssetType.TextureFile:
+ {
+ Image img = asset.GetTexture();
+
+ previewPictureBox.Image = img;
+ labelImageSize.Text = $"{previewPictureBox.Image.Size.Width}x{previewPictureBox.Image.Size.Height}";
+
+ if (asset.Type != PckAssetType.TextureFile)
+ break;
+
+ ResourceLocation resourceLocation = ResourceLocation.GetFromPath(asset.Filename);
+ if (resourceLocation is null || resourceLocation.Category == ResourceCategory.Unknown)
+ break;
+
+ if (resourceLocation.Category == ResourceCategory.ItemAnimation ||
+ resourceLocation.Category == ResourceCategory.BlockAnimation &&
+ !asset.IsMipmappedFile())
+ {
+ buttonEdit.Text = "EDIT TILE ANIMATION";
+ buttonEdit.Visible = true;
+ break;
+ }
+
+ buttonEdit.Text = "EDIT TEXTURE ATLAS";
+ buttonEdit.Visible = true;
+ }
+ break;
+
+ case PckAssetType.LocalisationFile:
+ buttonEdit.Text = "EDIT LOC";
+ buttonEdit.Visible = true;
+ break;
+
+ case PckAssetType.AudioFile:
+ buttonEdit.Text = "EDIT MUSIC CUES";
+ buttonEdit.Visible = true;
+ break;
+
+ case PckAssetType.ColourTableFile when asset.Filename == "colours.col":
+ buttonEdit.Text = "EDIT COLORS";
+ buttonEdit.Visible = true;
+ break;
+
+ case PckAssetType.BehavioursFile when asset.Filename == "behaviours.bin":
+ buttonEdit.Text = "EDIT BEHAVIOURS";
+ buttonEdit.Visible = true;
+ break;
+ default:
+ buttonEdit.Visible = false;
+ break;
+ }
+ }
+
+ private void treeViewMain_DoubleClick(object sender, EventArgs e)
+ {
+ if (treeViewMain.SelectedNode is TreeNode t && t.Tag is PckAsset asset)
+ {
+ if (asset.Size <= 0)
+ {
+ Trace.WriteLine($"'{asset.Filename}' has no data attached.", category: nameof(treeViewMain_DoubleClick));
+ return;
+ }
+ _pckAssetTypeHandler[asset.Type]?.Invoke(asset);
+ }
+ }
+
+ // 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)
+ {
+ if (e.Button != MouseButtons.Left || e.Item is not TreeNode node)
+ return;
+
+ if ((node.TryGetTagData(out PckAsset asset) && EditorValue.File.Contains(asset.Filename, asset.Type)) || node.Parent is TreeNode)
+ {
+ // TODO: add (mouse) scrolling while dragging item(s)
+ treeViewMain.DoDragDrop(node, DragDropEffects.Scroll | DragDropEffects.Move);
+ }
+ }
+
+ private void treeViewMain_DragOver(object sender, DragEventArgs e)
+ {
+ Point dragLocation = new Point(e.X, e.Y);
+ TreeNode node = treeViewMain.GetNodeAt(treeViewMain.PointToClient(dragLocation));
+ treeViewMain.SelectedNode = node.IsTagOfType() ? null : node;
+ }
+
+ private void treeViewMain_DragEnter(object sender, DragEventArgs e)
+ {
+ e.Effect = e.Data.GetDataPresent(DataFormats.FileDrop) ? DragDropEffects.Copy : e.AllowedEffect;
+ BringToFront();
+ Focus();
+ treeViewMain.Focus();
+ }
+
+ private void treeViewMain_DragDrop(object sender, DragEventArgs e)
+ {
+ // Retrieve the client coordinates of the drop location.
+ Point dragLocation = new Point(e.X, e.Y);
+ Point targetPoint = treeViewMain.PointToClient(dragLocation);
+
+ if (!treeViewMain.ClientRectangle.Contains(targetPoint))
+ return;
+
+ // Retrieve the node at the drop location.
+ TreeNode targetNode = treeViewMain.GetNodeAt(targetPoint);
+
+ if (e.Data.GetDataPresent(DataFormats.FileDrop) && e.Data.GetData(DataFormats.FileDrop) is string[] filesDropped)
+ {
+ IEnumerable files = filesDropped.Where(File.Exists);
+ IEnumerable directoryFiles = filesDropped
+ .Where(f => (File.GetAttributes(f) & FileAttributes.Directory) != 0)
+ .SelectMany(dir => Directory.GetFiles(dir, "*.*", SearchOption.AllDirectories));
+
+ string baseDirectory = Path.GetDirectoryName(filesDropped.First());
+
+ IEnumerable importPaths = files.Concat(directoryFiles);
+
+ ImportFiles(baseDirectory, importPaths, string.IsNullOrWhiteSpace(targetNode?.FullPath) ? string.Empty : targetNode?.FullPath);
+ return;
+ }
+
+ string dataFormat = typeof(TreeNode).FullName;
+
+ if (targetNode is null)
+ return;
+
+ if (!e.Data.GetDataPresent(dataFormat))
+ return;
+
+ bool isTargetPckFile = targetNode.IsTagOfType();
+ TreeNode draggedNode = e.Data.GetData(dataFormat) as TreeNode;
+ if (draggedNode == null)
+ {
+ Debug.WriteLine("Dragged node is null.");
+ return;
+ }
+
+ if (targetNode.Equals(draggedNode))
+ {
+ Debug.WriteLine("Dragged node was not moved.");
+ return;
+ }
+
+ if (targetNode.Equals(draggedNode.Parent))
+ {
+ Debug.WriteLine("target node is parent of dragged node... nothing done.");
+ return;
+ }
+
+ if (draggedNode.Equals(targetNode.Parent))
+ {
+ Debug.WriteLine("dragged node is parent of target node... nothing done.");
+ return;
+ }
+
+ if (targetNode.Parent == null && isTargetPckFile && draggedNode.Parent == null)
+ {
+ Debug.WriteLine("target node is file and is in the root... nothing done.");
+ return;
+ }
+
+ if ((targetNode.Parent?.Equals(draggedNode.Parent) ?? false) && isTargetPckFile)
+ {
+ Debug.WriteLine("target node and dragged node have the same parent... nothing done.");
+ return;
+ }
+
+ Debug.WriteLine($"Target drop location is {(isTargetPckFile ? "file" : "folder")}.");
+
+ // Retrieve the node that was dragged.
+ if (draggedNode.TryGetTagData(out PckAsset draggedAsset) &&
+ targetNode.FullPath != draggedAsset.Filename)
+ {
+ Debug.WriteLine(draggedAsset.Filename + " was droped onto " + targetNode.FullPath);
+ string newFilePath = Path.Combine(isTargetPckFile
+ ? Path.GetDirectoryName(targetNode.FullPath)
+ : targetNode.FullPath, Path.GetFileName(draggedAsset.Filename));
+ Debug.WriteLine("New filepath: " + newFilePath);
+ draggedAsset.Filename = newFilePath;
+ _wasModified = true;
+ BuildMainTreeView();
+ return;
+ }
+ else
+ {
+ IEnumerable pckFiles = GetAllChildNodes(draggedNode.Nodes).Where(t => t.IsTagOfType()).Select(t => t.Tag as PckAsset);
+ string oldPath = draggedNode.FullPath;
+ string newPath = Path.Combine(isTargetPckFile ? Path.GetDirectoryName(targetNode.FullPath) : targetNode.FullPath, draggedNode.Text).Replace('\\', '/');
+ foreach (PckAsset pckFile in pckFiles)
+ {
+ pckFile.Filename = Path.Combine(newPath, pckFile.Filename.Substring(oldPath.Length + 1)).Replace('\\', '/');
+ }
+ _wasModified = true;
+ BuildMainTreeView();
+ }
+ }
+
+ private void ImportFiles(string baseDirectory, IEnumerable files, string prefix)
+ {
+ int fileCount = files.Count();
+ int addedCount = 0;
+ int skippedFiles = 0;
+ int skipAttempts = 3;
+ int typeDuplication = 0;
+ PckAssetType lastSelectedAssetType = PckAssetType.SkinFile;
+ bool askForAssetType = true;
+ foreach (var filepath in files)
+ {
+ string assetPath = Path.Combine(prefix + filepath.Substring(baseDirectory.Length)).TrimStart('/', '\\');
+ PckAssetType assetType = lastSelectedAssetType;
+
+ if (askForAssetType)
+ {
+ using AddFilePrompt addFile = new AddFilePrompt(assetPath);
+ if (addFile.ShowDialog(this) != DialogResult.OK)
+ {
+ skippedFiles++;
+ skipAttempts--;
+ if (skipAttempts > 0)
+ continue;
+
+ int remainingFileCount = fileCount - addedCount - skippedFiles;
+ DialogResult abortFurtherImport = MessageBox.Show($"Do you wan't to abort further file imports?\n{remainingFileCount} file(s) left.", "Abort further import", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
+ if (abortFurtherImport == DialogResult.Yes)
+ {
+ skippedFiles += remainingFileCount;
+ break;
+ }
+ skipAttempts = 3;
+ continue;
+ }
+
+ assetType = addFile.Filetype;
+ assetPath = addFile.Filepath;
+
+ if (lastSelectedAssetType == assetType)
+ typeDuplication++;
+ lastSelectedAssetType = addFile.Filetype;
+ if (typeDuplication > 1)
+ {
+ DialogResult useSameTypeForRest = MessageBox.Show($"Do you want to import all remaining files as {lastSelectedAssetType}?", "Import all as", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1);
+ if (useSameTypeForRest == DialogResult.Yes)
+ {
+ askForAssetType = false;
+ }
+ }
+ }
+
+ if (EditorValue.File.Contains(filepath, assetType))
+ {
+ if (askForAssetType)
+ MessageBox.Show(this, $"'{assetPath}' of type {assetType} already exists.\nSkiping file.", "File already exists", MessageBoxButtons.OK, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1);
+ Debug.WriteLine($"'{assetPath}' of type {assetType} already exists.\nSkiping file.");
+ continue;
+ }
+ PckAsset importedAsset = EditorValue.File.CreateNewAsset(assetPath, assetType, () => File.ReadAllBytes(filepath));
+ string propertyFile = filepath + ".txt";
+ if (File.Exists(propertyFile))
+ {
+ importedAsset.DeserializeProperties(File.ReadAllLines(propertyFile));
+ }
+ addedCount++;
+ }
+ Trace.TraceInformation("[{0}] Imported {1} file(s).", nameof(ImportFiles), addedCount);
+ Trace.TraceInformation("[{0}] Skipped {1} file(s).", nameof(ImportFiles), skippedFiles);
+ if (addedCount > 0)
+ {
+ _wasModified = true;
+ BuildMainTreeView();
+ }
+ }
+
+ private IEnumerable GetEndingNodes(TreeNodeCollection collection)
+ {
+ List trailingNodes = new List(collection.Count);
+ foreach (TreeNode node in collection)
+ {
+ if (node.Nodes.Count > 0)
+ {
+ trailingNodes.AddRange(GetEndingNodes(node.Nodes));
+ continue;
+ }
+ trailingNodes.Add(node);
+ }
+ return trailingNodes;
+ }
+
+ private void ImportFiles(string[] files)
+ {
+ int addedCount = 0;
+ foreach (var file in files)
+ {
+ using AddFilePrompt addFile = new AddFilePrompt(Path.GetFileName(file));
+ if (addFile.ShowDialog(this) != DialogResult.OK)
+ continue;
+
+ if (EditorValue.File.Contains(addFile.Filepath, addFile.Filetype))
+ {
+ MessageBox.Show(this, $"'{addFile.Filepath}' of type {addFile.Filetype} already exists.", "Import failed", MessageBoxButtons.OK, MessageBoxIcon.Warning);
+ continue;
+ }
+ EditorValue.File.CreateNewAsset(addFile.Filepath, addFile.Filetype, () => File.ReadAllBytes(file));
+ addedCount++;
+
+ BuildMainTreeView();
+ _wasModified = true;
+ }
+ Trace.TraceInformation("[{0}] Imported {1} file(s).", nameof(ImportFiles), addedCount);
+ }
+
+ private void createSkinToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ using (AddSkinPrompt addNewSkinDialog = new AddSkinPrompt())
+ if (addNewSkinDialog.ShowDialog() == DialogResult.OK)
+ {
+ TryGetLocFile(out LOCFile locFile);
+ PckAsset skinAsset = addNewSkinDialog.NewSkin.CreateFile(locFile);
+ EditorValue.File.AddAsset(skinAsset);
+
+ bool hasSkinsFolder = treeViewMain.Nodes.ContainsKey("Skins");
+ if (hasSkinsFolder)
+ skinAsset.Filename = skinAsset.Filename.Insert(0, "Skins/"); // Then Skins folder
+ EditorValue.File.AddAsset(skinAsset);
+
+ if (addNewSkinDialog.NewSkin.HasCape)
+ {
+ PckAsset capeFile = addNewSkinDialog.NewSkin.CreateCapeFile();
+ if (hasSkinsFolder)
+ capeFile.Filename = capeFile.Filename.Insert(0, "Skins/"); // Then Skins folder
+ EditorValue.File.AddAsset(capeFile);
+ }
+
+ TrySetLocFile(locFile);
+ _wasModified = true;
+ BuildMainTreeView();
+ }
+ }
+
+ private void createAnimatedTextureToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ using ChangeTile diag = new ChangeTile();
+ if (diag.ShowDialog(this) != DialogResult.OK)
+ return;
+
+ string animationFilepath = $"{ResourceLocation.GetPathFromCategory(diag.Category)}/{diag.SelectedTile.InternalName}.png";
+
+ if (EditorValue.File.Contains(animationFilepath, PckAssetType.TextureFile))
+ {
+ MessageBox.Show(this, $"{diag.SelectedTile.DisplayName} is already present.", "File already present");
+ return;
+ }
+
+ Animation newAnimation = default;
+ ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (animation) =>
+ {
+ newAnimation = animation;
+ });
+
+ using AnimationEditor animationEditor = new AnimationEditor(Animation.CreateEmpty(), saveContext, diag.SelectedTile.DisplayName, !diag.SelectedTile.InternalName.EqualsAny("clock", "compass"));
+ if (animationEditor.ShowDialog() == DialogResult.OK && newAnimation is not null)
+ {
+ _wasModified = true;
+ PckAsset asset = EditorValue.File.CreateNewAsset(animationFilepath, PckAssetType.TextureFile);
+ asset.SetSerializedData(newAnimation, AnimationSerializer.DefaultSerializer);
+ BuildMainTreeView();
+ ReloadMetaTreeView();
+ }
+ }
+
+ private void audiopckToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (EditorValue.File.Contains(PckAssetType.AudioFile))
+ {
+ // the chance of this happening is really really slim but just in case
+ MessageBox.Show(this, "There is already an audio file in this PCK!", "Can't create audio.pck");
+ return;
+ }
+
+ if (string.IsNullOrEmpty(_location))
+ {
+ MessageBox.Show(this, "You must save your pck before creating or opening a music cues PCK file", "Can't create audio.pck");
+ return;
+ }
+
+ PckAudioFile newAudioFile = CreateNewAudioFile();
+ PckAsset newAudioAsset = CreateNewAudioAsset(LittleEndianCheckBox.Checked, newAudioFile);
+
+ ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (audioFile) =>
+ {
+ newAudioAsset.SetData(new PckAudioFileWriter(audioFile, LittleEndianCheckBox.Checked ? OMI.ByteOrder.LittleEndian : OMI.ByteOrder.BigEndian));
+ });
+
+ AudioEditor diag = new AudioEditor(newAudioFile, saveContext);
+ if (diag.ShowDialog(this) == DialogResult.OK)
+ {
+ EditorValue.File.AddAsset(newAudioAsset);
+ }
+ diag.Dispose();
+ BuildMainTreeView();
+ }
+
+ private void colourscolToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (EditorValue.File.TryGetAsset("colours.col", PckAssetType.ColourTableFile, out _))
+ {
+ MessageBox.Show(this, "A color table file already exists in this PCK and a new one cannot be created.", "Operation aborted");
+ return;
+ }
+ PckAsset newColorAsset = EditorValue.File.CreateNewAsset("colours.col", PckAssetType.ColourTableFile);
+ newColorAsset.SetData(Resources.tu69colours);
+ BuildMainTreeView();
+ }
+
+ private void CreateSkinsPCKToolStripMenuItem1_Click(object sender, EventArgs e)
+ {
+ if (EditorValue.File.TryGetAsset("Skins.pck", PckAssetType.SkinDataFile, out _))
+ {
+ MessageBox.Show(this, "A Skins.pck file already exists in this PCK and a new one cannot be created.", "Operation aborted");
+ return;
+ }
+
+ EditorValue.File.CreateNewAsset("Skins.pck", PckAssetType.SkinDataFile, new PckFileWriter(new PckFile(3, true),
+ LittleEndianCheckBox.Checked ? OMI.ByteOrder.LittleEndian : OMI.ByteOrder.BigEndian));
+
+ BuildMainTreeView();
+ }
+
+ private void behavioursbinToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (EditorValue.File.TryGetAsset("behaviours.bin", PckAssetType.BehavioursFile, out _))
+ {
+ MessageBox.Show(this, "A behaviours file already exists in this PCK and a new one cannot be created.", "Operation aborted");
+ return;
+ }
+
+ EditorValue.File.CreateNewAsset("behaviours.bin", PckAssetType.BehavioursFile, new BehavioursWriter(new BehaviourFile()));
+ BuildMainTreeView();
+ }
+
+ private void entityMaterialsbinToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (EditorValue.File.TryGetAsset("entityMaterials.bin", PckAssetType.MaterialFile, out _))
+ {
+ MessageBox.Show(this, "A behaviours file already exists in this PCK and a new one cannot be created.", "Operation aborted");
+ return;
+ }
+ var materialContainer = new MaterialContainer();
+ materialContainer.InitializeDefault();
+ EditorValue.File.CreateNewAsset("entityMaterials.bin", PckAssetType.MaterialFile, new MaterialFileWriter(materialContainer));
+ BuildMainTreeView();
+ }
+
+ [Obsolete("Refactor or remove this")]
+ private void importExtractedSkinsFolder(object sender, EventArgs e)
+ {
+ OpenFolderDialog contents = new OpenFolderDialog();
+ if (contents.ShowDialog(Handle) == true)
+ {
+ //checks to make sure selected path exist
+ if (!Directory.Exists(contents.ResultPath))
+ {
+ MessageBox.Show("Directory Lost");
+ return;
+ }
+ // creates variable to indicate wether current pck skin structure is mashup or regular skin
+ bool hasSkinsPck = EditorValue.File.HasAsset("Skins.pck", PckAssetType.SkinDataFile);
+
+ foreach (var fullfilename in Directory.GetFiles(contents.ResultPath, "*.png"))
+ {
+ string filename = Path.GetFileNameWithoutExtension(fullfilename);
+ // sets file type based on wether its a cape or skin
+ PckAssetType pckfiletype = filename.StartsWith("dlccape", StringComparison.OrdinalIgnoreCase)
+ ? PckAssetType.CapeFile
+ : PckAssetType.SkinFile;
+ string pckfilepath = (hasSkinsPck ? "Skins/" : string.Empty) + filename + ".png";
+
+
+ PckAsset newFile = new PckAsset(pckfilepath, pckfiletype);
+ byte[] filedata = File.ReadAllBytes(fullfilename);
+ newFile.SetData(filedata);
+
+ if (File.Exists(fullfilename + ".txt"))
+ {
+ string[] properties = File.ReadAllText(fullfilename + ".txt").Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
+ foreach (string property in properties)
+ {
+ string[] param = property.Split(':');
+ if (param.Length < 2)
+ continue;
+ newFile.AddProperty(param[0], param[1]);
+ //switch (param[0])
+ //{
+ // case "DISPLAYNAMEID":
+ // locNameId = param[1];
+ // continue;
+
+ // case "DISPLAYNAME":
+ // locName = param[1];
+ // continue;
+
+ // case "THEMENAMEID":
+ // locThemeId = param[1];
+ // continue;
+
+ // case "THEMENAME":
+ // locTheme = param[1];
+ // continue;
+ //}
+ }
+ }
+ if (hasSkinsPck)
+ {
+ PckAsset skinsFileAsset = EditorValue.File.GetAsset("Skins.pck", PckAssetType.SkinDataFile);
+ using (var ms = new MemoryStream(skinsFileAsset.Data))
+ {
+ //var reader = new PckFileReader(LittleEndianCheckBox.Checked ? OMI.Endianness.LittleEndian : OMI.Endianness.BigEndian);
+ //var skinspck = reader.FromStream(ms);
+ //skinspck.Files.Add(newFile);
+ //ms.Position = 0;
+ //var writer = new PckFileWriter(skinspck, LittleEndianCheckBox.Checked ? OMI.Endianness.LittleEndian : OMI.Endianness.BigEndian);
+ //writer.WriteToStream(ms);
+ //skinsfile.SetData(ms.ToArray());
+ }
+ continue;
+ }
+ EditorValue.File.AddAsset(newFile);
+ }
+ BuildMainTreeView();
+ _wasModified = true;
+ }
+ }
+
+ private void as3DSTextureFileToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (treeViewMain.SelectedNode.TryGetTagData(out PckAsset asset) &&
+ asset.Type == PckAssetType.SkinFile)
+ {
+ SaveFileDialog saveFileDialog = new SaveFileDialog();
+ saveFileDialog.Filter = "3DS Texture|*.3dst";
+ saveFileDialog.DefaultExt = ".3dst";
+ if (saveFileDialog.ShowDialog(this) == DialogResult.OK)
+ {
+ Image img = asset.GetTexture();
+ var writer = new _3DSTextureWriter(img);
+ writer.WriteToFile(saveFileDialog.FileName);
+ }
+ }
+ }
+
+ private void generateMipMapTextureToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (treeViewMain.SelectedNode.Tag is PckAsset asset && asset.Type == PckAssetType.TextureFile)
+ {
+ string textureDirectory = Path.GetDirectoryName(asset.Filename);
+ string textureName = Path.GetFileNameWithoutExtension(asset.Filename);
+
+ if (asset.IsMipmappedFile())
+ return;
+
+ string textureExtension = Path.GetExtension(asset.Filename);
+
+ using NumericPrompt numericPrompt = new NumericPrompt(0);
+ numericPrompt.Minimum = 1;
+ numericPrompt.Maximum = 4; // 5 is the presumed max MipMap level
+ numericPrompt.ToolTipText = "You can enter the amount of MipMap levels that you would like to generate. " +
+ "For example: if you enter 2, MipMapLevel1.png and MipMapLevel2.png will be generated";
+ numericPrompt.TextLabel.Text = "Levels";
+
+ if (numericPrompt.ShowDialog(this) == DialogResult.OK)
+ {
+ for (int i = 2; i < 2 + numericPrompt.SelectedValueAsInt; i++)
+ {
+ string mippedPath = $"{textureDirectory}/{textureName}MipMapLevel{i}{textureExtension}";
+ Debug.WriteLine(mippedPath);
+ if (EditorValue.File.HasAsset(mippedPath, PckAssetType.TextureFile))
+ EditorValue.File.RemoveAsset(EditorValue.File.GetAsset(mippedPath, PckAssetType.TextureFile));
+ PckAsset mipMappedAsset = new PckAsset(mippedPath, PckAssetType.TextureFile);
+
+ Image originalTexture = asset.GetTexture();
+ int newWidth = Math.Max(originalTexture.Width / (int)Math.Pow(2, i - 1), 1);
+ int newHeight = Math.Max(originalTexture.Height / (int)Math.Pow(2, i - 1), 1);
+
+ Rectangle tileArea = new Rectangle(0, 0, newWidth, newHeight);
+ Image mippedTexture = new Bitmap(newWidth, newHeight);
+ using (Graphics gfx = Graphics.FromImage(mippedTexture))
+ {
+ gfx.SmoothingMode = SmoothingMode.None;
+ gfx.InterpolationMode = InterpolationMode.NearestNeighbor;
+ gfx.PixelOffsetMode = PixelOffsetMode.HighQuality;
+ gfx.DrawImage(originalTexture, tileArea);
+ }
+
+ mipMappedAsset.SetTexture(mippedTexture);
+
+ EditorValue.File.InsertAsset(EditorValue.File.IndexOfAsset(asset) + i - 1, mipMappedAsset);
+ }
+ BuildMainTreeView();
+ }
+ }
+ }
+
+ private void viewFileInfoToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (treeViewMain.SelectedNode.Tag is PckAsset asset)
+ {
+ MessageBox.Show(
+ $"Asset path: {asset.Filename}" +
+ $"\nAsset type: {(int)asset.Type} ({asset.Type})" +
+ $"\nAsset size: {asset.Size}" +
+ $"\nProperties count: {asset.PropertyCount}"
+ , Path.GetFileName(asset.Filename) + " Asset info");
+ }
+ }
+
+ private void correctSkinDecimalsToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (treeViewMain.SelectedNode.TryGetTagData(out PckAsset asset) &&
+ asset.Type == PckAssetType.SkinFile)
+ {
+ foreach (KeyValuePair p in asset.GetProperties().ToList())
+ {
+ if (p.Key == "BOX" || p.Key == "OFFSET")
+ asset.SetProperty(asset.GetPropertyIndex(p), new KeyValuePair(p.Key, p.Value.Replace(',', '.')));
+ }
+ ReloadMetaTreeView();
+ _wasModified = true;
+ }
+ }
+
+ private void extractToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ TreeNode node = treeViewMain.SelectedNode;
+
+ if (node == null)
+ {
+ MessageBox.Show(this, "The selected node was null. Please select a node and try again.", "Node not extracted");
+
+ return;
+ }
+
+ if (node.Tag == null)
+ {
+ OpenFolderDialog dialog = new OpenFolderDialog();
+ dialog.Title = @"Select destination folder";
+
+ if (dialog.ShowDialog(Handle) == true)
+ extractFolder(dialog.ResultPath);
+ }
+ else if (node.TryGetTagData(out PckAsset asset))
+ {
+ using SaveFileDialog exFile = new SaveFileDialog();
+ exFile.FileName = Path.GetFileName(asset.Filename);
+ exFile.Filter = Path.GetExtension(asset.Filename).Replace(".", string.Empty) + " File|*" + Path.GetExtension(asset.Filename);
+ if (exFile.ShowDialog(this) != DialogResult.OK ||
+ // Makes sure chosen directory isn't null or whitespace AKA makes sure its usable
+ string.IsNullOrWhiteSpace(Path.GetDirectoryName(exFile.FileName)))
+ {
+ MessageBox.Show(this, "The chosen directory is invalid. Please choose a different one and try again.", "Node not extracted");
+
+ return;
+ }
+
+ extractFile(exFile.FileName, asset);
+ }
+
+ // Verification that file extraction path was successful
+ MessageBox.Show(this, $"\"{node.Text}\" successfully extracted");
+ }
+
+ private void extractFolder(string outPath)
+ {
+ TreeNode node = treeViewMain.SelectedNode;
+
+ string selectedFolder = node.FullPath;
+
+ foreach (PckAsset asset in EditorValue.File.GetAssets().Where(asset => asset.Filename.StartsWith(selectedFolder)))
+ {
+ extractFolderFile(outPath, asset);
+ }
+ }
+
+ private void extractFolderFile(string outPath, PckAsset asset)
+ {
+ TreeNode node = treeViewMain.SelectedNode;
+
+ // abb = "Abbreviated Path"
+ string abbPath = Path.GetDirectoryName(asset.Filename);
+ int startIndex = abbPath.IndexOf(node.Text);
+ abbPath = abbPath.Substring(startIndex, abbPath.Length - startIndex);
+ string finalPath = ($"{outPath}/{abbPath}/").Replace('\\', '/');
+
+ if (!Directory.Exists(finalPath))
+ Directory.CreateDirectory(finalPath);
+
+ extractFile(finalPath + "/" + Path.GetFileName(asset.Filename), asset);
+ }
+
+ private void extractFile(string outFilePath, PckAsset asset)
+ {
+ File.WriteAllBytes(outFilePath, asset.Data);
+ if (asset.PropertyCount > 0)
+ {
+ File.WriteAllLines($"{outFilePath}.txt", asset.SerializeProperties());
+ }
+ }
+
+ private void cloneFileToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ TreeNode node = treeViewMain.SelectedNode;
+ if (node == null || !node.IsTagOfType())
+ return;
+ string path = node.FullPath;
+
+ using TextPrompt diag = new TextPrompt(node.Tag is null ? Path.GetFileName(node.FullPath) : node.FullPath);
+ diag.contextLabel.Text = $"Creating a clone of \"{path}\". Ensure that the path isn't yet.";
+ diag.OKButtonText = "Clone";
+
+ if (diag.ShowDialog(this) == DialogResult.OK)
+ {
+ if (node.Tag is PckAsset asset)
+ {
+ TreeNode newNode = new TreeNode();
+ newNode.Text = Path.GetFileName(diag.NewText);
+ var newFile = new PckAsset(diag.NewText, asset.Type);
+ foreach (KeyValuePair property in asset.GetProperties())
+ {
+ newFile.AddProperty(property);
+ }
+ newFile.SetData(asset.Data);
+ newFile.Filename = diag.NewText;
+ newNode.Tag = newFile;
+ newNode.ImageIndex = node.ImageIndex;
+ newNode.SelectedImageIndex = node.SelectedImageIndex;
+
+ if (GetAllChildNodes(treeViewMain.Nodes).FirstOrDefault(n => n.FullPath == diag.NewText) is not null)
+ {
+ MessageBox.Show(
+ this,
+ $"A file with the path \"{diag.NewText}\" already exists. " +
+ $"Please try again with a different name.",
+ "Key already exists");
+ return;
+ }
+
+ TreeNodeCollection nodeCollection = node.Parent?.Nodes ?? treeViewMain.Nodes;
+ nodeCollection.Insert(node.Index + 1, newNode);
+
+ EditorValue.File.InsertAsset(node.Index + 1, newFile);
+ BuildMainTreeView();
+ _wasModified = true;
+ }
+ }
+ }
+
+ private void renameFileToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ TreeNode node = treeViewMain.SelectedNode;
+ if (node == null)
+ return;
+ string path = node.FullPath;
+
+ bool isFile = node.TryGetTagData(out PckAsset asset);
+
+ using TextPrompt diag = new TextPrompt(isFile ? asset.Filename : Path.GetFileName(node.FullPath));
+
+ if (diag.ShowDialog(this) == DialogResult.OK)
+ {
+ if (isFile)
+ {
+ if (EditorValue.File.Contains(diag.NewText, asset.Type))
+ {
+ MessageBox.Show(this, $"{diag.NewText} already exists", "File already exists");
+ return;
+ }
+ asset.Filename = diag.NewText;
+ }
+ else // folders
+ {
+ node.Text = diag.NewText;
+ foreach (TreeNode childNode in GetAllChildNodes(node.Nodes))
+ {
+ if (childNode.Tag is PckAsset folderAsset)
+ {
+ if (folderAsset.Filename == diag.NewText)
+ continue;
+ folderAsset.Filename = childNode.FullPath;
+ }
+ }
+ }
+ _wasModified = true;
+ BuildMainTreeView();
+ }
+ }
+
+ private void replaceToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (treeViewMain.SelectedNode.Tag is PckAsset asset)
+ {
+ using var ofd = new OpenFileDialog();
+ // Suddenly, and randomly, this started throwing an exception because it wasn't formatted correctly? So now it's formatted correctly and now displays the file type name in the dialog.
+
+ string extra_extensions = "";
+
+ switch (asset.Type)
+ {
+ case PckAssetType.TextureFile:
+ if (Path.GetExtension(asset.Filename) == ".png")
+ extra_extensions = ";*.tga";
+ else if (Path.GetExtension(asset.Filename) == ".tga")
+ extra_extensions = ";*.png";
+ break;
+ }
+
+ string fileExt = Path.GetExtension(asset.Filename);
+
+ ofd.Filter = $"{asset.Type} (*{fileExt}{extra_extensions})|*{fileExt}{extra_extensions}";
+ if (ofd.ShowDialog(this) == DialogResult.OK)
+ {
+ string newFileExt = Path.GetExtension(ofd.FileName);
+ asset.SetData(File.ReadAllBytes(ofd.FileName));
+ asset.Filename = asset.Filename.Replace(fileExt, newFileExt);
+ _wasModified = true;
+ BuildMainTreeView();
+ }
+ return;
+ }
+ MessageBox.Show(this, "Can't replace a folder.");
+ }
+
+ ///
+ /// Action to run before an asset will be deleted
+ ///
+ /// Asset to remove
+ /// True if the remove should be canceled, otherwise False
+ private bool BeforeFileRemove(PckAsset asset)
+ {
+ string itemPath = ResourceLocation.GetPathFromCategory(ResourceCategory.ItemAnimation);
+
+ // warn the user about deleting compass.png and clock.png
+ if (asset.Type == PckAssetType.TextureFile &&
+ (asset.Filename == itemPath + "/compass.png" || asset.Filename == itemPath + "/clock.png"))
+ {
+ if (MessageBox.Show(this, "Are you sure want to delete this file? If \"compass.png\" or \"clock.png\" are missing, your game will crash upon loading this pack.", "Warning",
+ MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.No)
+ return true;
+ }
+
+ // remove loc key if its a skin/cape
+ if (asset.Type == PckAssetType.SkinFile || asset.Type == PckAssetType.CapeFile)
+ {
+ if (TryGetLocFile(out LOCFile locFile))
+ {
+ if (asset.TryGetProperty("THEMENAMEID", out string value))
+ locFile.RemoveLocKey(value);
+ if (asset.TryGetProperty("DISPLAYNAMEID", out value))
+ locFile.RemoveLocKey(value);
+ TrySetLocFile(locFile);
+ }
+ }
+ return false;
+ }
+
+ private void deleteFileToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ TreeNode node = treeViewMain.SelectedNode;
+ if (node == null)
+ return;
+
+ string path = node.FullPath;
+
+ if (node.TryGetTagData(out PckAsset asset))
+ {
+ if (!BeforeFileRemove(asset) && EditorValue.File.RemoveAsset(asset))
+ {
+ node.Remove();
+ _wasModified = true;
+ }
+ }
+ else if (MessageBox.Show(this, "Are you sure want to delete this folder? All contents will be deleted", "Warning",
+ MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
+ {
+ string pckFolderDir = node.FullPath;
+ EditorValue.File.RemoveAll(file => file.Filename.StartsWith(pckFolderDir) && !BeforeFileRemove(file));
+ node.Remove();
+ _wasModified = true;
+ }
+ }
+
+ private void treeMeta_AfterSelect(object sender, TreeViewEventArgs e)
+ {
+ if (e.Node is TreeNode t && t.Tag is KeyValuePair property)
+ {
+ entryTypeTextBox.Text = property.Key;
+ entryDataTextBox.Text = property.Value;
+ }
+ }
+
+ private void treeViewMain_KeyDown(object sender, KeyEventArgs e)
+ {
+ switch (e.KeyCode)
+ {
+ case Keys.Delete:
+ deleteFileToolStripMenuItem_Click(sender, e);
+ break;
+ case Keys.F2:
+ renameFileToolStripMenuItem_Click(sender, e);
+ break;
+ }
+ }
+
+ private void treeViewMain_BeforeLabelEdit(object sender, NodeLabelEditEventArgs e)
+ {
+ // for now name edits are done through the 'rename' context menu item
+ // TODO: add folder renaming
+ //e.CancelEdit = e.Node.Tag is PckAsset;
+ e.CancelEdit = true;
+ }
+
+ private void editAllEntriesToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (treeViewMain.SelectedNode.TryGetTagData(out PckAsset asset))
+ {
+ IEnumerable props = asset.SerializeProperties(seperater: " ");
+ using (var input = new MultiTextPrompt(props))
+ {
+ if (input.ShowDialog(this) == DialogResult.OK)
+ {
+ asset.ClearProperties();
+ asset.DeserializeProperties(input.TextOutput);
+ ReloadMetaTreeView();
+ _wasModified = true;
+ }
+ }
+ }
+ }
+
+ private void treeMeta_DoubleClick(object sender, EventArgs e)
+ {
+ if (treeMeta.SelectedNode is TreeNode subnode && subnode.Tag is KeyValuePair property &&
+ treeViewMain.SelectedNode is TreeNode node && node.Tag is PckAsset asset)
+ {
+ if (asset.HasProperty(property.Key))
+ {
+ switch (property.Key)
+ {
+ case "ANIM" when asset.Type == PckAssetType.SkinFile:
+ try
+ {
+ using ANIMEditor diag = new ANIMEditor(SkinANIM.FromString(property.Value));
+ if (diag.ShowDialog(this) == DialogResult.OK)
+ {
+ asset.SetProperty(asset.GetPropertyIndex(property), new KeyValuePair("ANIM", diag.ResultAnim.ToString()));
+ ReloadMetaTreeView();
+ _wasModified = true;
+ }
+ return;
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine(ex.Message);
+ Trace.WriteLine("Invalid ANIM value: " + property.Value);
+ MessageBox.Show(this, "Failed to parse ANIM value, aborting to normal functionality. Please make sure the value only includes hexadecimal characters (0-9,A-F) and has no more than 8 characters.");
+ }
+ break;
+
+ case "BOX" when asset.Type == PckAssetType.SkinFile:
+ try
+ {
+ using BoxEditor diag = new BoxEditor(property.Value, false);
+ if (diag.ShowDialog(this) == DialogResult.OK)
+ {
+ asset.SetProperty(asset.GetPropertyIndex(property), new KeyValuePair("BOX", diag.Result.ToString()));
+ ReloadMetaTreeView();
+ _wasModified = true;
+ }
+ return;
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine(ex.Message);
+ Trace.WriteLine("Invalid BOX value: " + property.Value);
+ MessageBox.Show(this, "Failed to parse BOX value, aborting to normal functionality.");
+ }
+ break;
+
+ default:
+ break;
+
+ }
+
+ using (AddPropertyPrompt addProperty = new AddPropertyPrompt(property))
+ {
+ if (addProperty.ShowDialog(this) == DialogResult.OK)
+ {
+ asset.SetProperty(asset.GetPropertyIndex(property), addProperty.Property);
+ ReloadMetaTreeView();
+ _wasModified = true;
+ }
+ }
+ }
+ }
+ }
+
+ private void treeMeta_KeyDown(object sender, KeyEventArgs e)
+ {
+ if (e.KeyData == Keys.Delete)
+ deleteEntryToolStripMenuItem_Click(sender, e);
+ }
+
+ private void addMultipleEntriesToolStripMenuItem1_Click(object sender, EventArgs e)
+ {
+ if (treeViewMain.SelectedNode.TryGetTagData(out PckAsset asset))
+ {
+ using var input = new MultiTextPrompt();
+ if (input.ShowDialog(this) == DialogResult.OK)
+ {
+ asset.DeserializeProperties(input.TextOutput);
+ ReloadMetaTreeView();
+ _wasModified = true;
+ }
+ }
+ }
+
+ private void addBOXEntryToolStripMenuItem1_Click(object sender, EventArgs e)
+ {
+ if (treeViewMain.SelectedNode is TreeNode t && t.Tag is PckAsset asset)
+ {
+ using BoxEditor diag = new BoxEditor(SkinBOX.DefaultHead, false);
+ if (diag.ShowDialog(this) == DialogResult.OK)
+ {
+ asset.AddProperty("BOX", diag.Result);
+ ReloadMetaTreeView();
+ _wasModified = true;
+ }
+ return;
+ }
+ }
+
+ private void addANIMEntryToolStripMenuItem1_Click(object sender, EventArgs e)
+ {
+ if (treeViewMain.SelectedNode.TryGetTagData(out PckAsset asset))
+ {
+ using ANIMEditor diag = new ANIMEditor(SkinANIM.Empty);
+ if (diag.ShowDialog(this) == DialogResult.OK)
+ {
+ asset.AddProperty("ANIM", diag.ResultAnim);
+ ReloadMetaTreeView();
+ _wasModified = true;
+ }
+ return;
+ }
+ }
+
+ private void deleteEntryToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (treeMeta.SelectedNode is TreeNode t && t.Tag is KeyValuePair property &&
+ treeViewMain.SelectedNode is TreeNode main && main.Tag is PckAsset asset &&
+ asset.RemoveProperty(property))
+ {
+ treeMeta.SelectedNode.Remove();
+ _wasModified = true;
+ }
+ }
+
+ private void addEntryToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (treeViewMain.SelectedNode is TreeNode t &&
+ t.Tag is PckAsset asset)
+ {
+ using AddPropertyPrompt addProperty = new AddPropertyPrompt();
+ if (addProperty.ShowDialog(this) == DialogResult.OK)
+ {
+ asset.AddProperty(addProperty.Property);
+ ReloadMetaTreeView();
+ _wasModified = true;
+ }
+ }
+ }
+
+ private static bool TryGetDefaultEntityModel(string modelName, out Model model)
+ {
+ if (!GameModelImporter.DefaultModels.TryGetValue(modelName, out DefaultModel defaultModel) || defaultModel is null)
+ {
+ model = default;
+ return false;
+ }
+ model = new Model(modelName, new Size((int)defaultModel.TextureSize.X, (int)defaultModel.TextureSize.Y));
+
+ foreach (DefaultPart defaultPart in defaultModel.Parts)
+ {
+ ModelPart modelPart = new ModelPart(defaultPart.Name, "", defaultPart.Translation, defaultPart.Rotation, System.Numerics.Vector3.Zero);
+ modelPart.AddBoxes(defaultPart.Boxes.Select(defaultBox => new ModelBox(defaultBox.Position, defaultBox.Size, defaultBox.Uv, defaultBox.Inflate, defaultBox.Mirror)));
+ model.AddPart(modelPart);
+ }
+
+ return true;
+ }
+
+ private void ShowSimpleModelRender(Model model, NamedData modelTexture)
+ {
+ MetroForm form = new MetroForm();
+ form.Icon = Resources.ProjectLogo;
+ form.Theme = MetroFramework.MetroThemeStyle.Dark;
+ form.Style = MetroFramework.MetroColorStyle.Silver;
+ form.StartPosition = FormStartPosition.CenterParent;
+ form.Text = $"{model.Name} - {modelTexture.Name}";
+ form.Size = new Size(600, 500);
+ form.MinimumSize = new Size(300, 300);
+
+ void ExportToolStripItem_Click(object sender, EventArgs e)
+ {
+ GameModelImporter.Default.ExportSettings.CreateModelOutline =
+ MessageBox.Show(
+ $"Do you wish to have all model parts contained in a group called '{model.Name}'?",
+ "Group model parts", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes;
+
+ using SaveFileDialog openFileDialog = new SaveFileDialog();
+ openFileDialog.FileName = model.Name;
+ openFileDialog.Filter = GameModelImporter.Default.SupportedModelFileFormatsFilter;
+
+ if (openFileDialog.ShowDialog(this) == DialogResult.OK)
+ {
+ var modelInfo = new GameModelInfo(model, new NamedData[1] { modelTexture });
+ GameModelImporter.Default.Export(openFileDialog.FileName, modelInfo);
+ }
+ }
+ ToolStripItem exportToolStripItem = new ToolStripButton("Export");
+ exportToolStripItem.Click += ExportToolStripItem_Click;
+
+ MenuStrip menu = new MenuStrip();
+ menu.BackColor = Color.FromArgb(35, 35, 35);
+ menu.ForeColor = Color.WhiteSmoke;
+ menu.Anchor = AnchorStyles.Top;
+ menu.Dock = DockStyle.Top;
+ menu.Items.Add(exportToolStripItem);
+
+ ModelRenderer renderer = new ModelRenderer();
+ form.Controls.Add(menu);
+ form.Controls.Add(renderer);
+
+ renderer.VSync = true;
+ renderer.BackColor = Color.FromArgb(30, 30, 30);
+ renderer.Dock = DockStyle.Fill;
+ renderer.Texture = modelTexture.Value;
+ renderer.LoadModel(model);
+ renderer.ResetCamera();
+
+ form.ShowDialog(this);
+
+ renderer.Dispose();
+ form.Dispose();
+ }
+
+ private void PckEditor_Load(object sender, EventArgs e)
+ {
+ CheckForPasswordAndRemove();
+ BuildMainTreeView();
+ UpdateRichPresence();
+ }
+
+ private void SetEndianess(OMI.ByteOrder endianness)
+ {
+ LittleEndianCheckBox.Checked = endianness == OMI.ByteOrder.LittleEndian;
+ }
+
+ private OMI.ByteOrder GetEndianess()
+ {
+ return LittleEndianCheckBox.Checked ? OMI.ByteOrder.LittleEndian : OMI.ByteOrder.BigEndian;
+ }
+
+ private void buttonEdit_Click(object sender, EventArgs e)
+ {
+ treeViewMain_DoubleClick(sender, e);
+ }
+
+ private void SetPckEndianness(OMI.ByteOrder endianness)
+ {
+ try
+ {
+ if (treeViewMain.SelectedNode.Tag is PckAsset asset && (asset.Type is PckAssetType.AudioFile || asset.Type is PckAssetType.SkinDataFile || asset.Type is PckAssetType.TexturePackInfoFile))
+ {
+ IDataFormatReader reader = asset.Type is PckAssetType.AudioFile
+ ? new PckAudioFileReader(endianness == OMI.ByteOrder.BigEndian ? OMI.ByteOrder.LittleEndian : OMI.ByteOrder.BigEndian)
+ : new PckFileReader(endianness == OMI.ByteOrder.BigEndian ? OMI.ByteOrder.LittleEndian : OMI.ByteOrder.BigEndian);
+ object pck = reader.FromStream(new MemoryStream(asset.Data));
+
+ IDataFormatWriter writer = asset.Type is PckAssetType.AudioFile
+ ? new PckAudioFileWriter((PckAudioFile)pck, endianness)
+ : new PckFileWriter((PckFile)pck, endianness);
+ asset.SetData(writer);
+ _wasModified = true;
+ MessageBox.Show($"\"{asset.Filename}\" successfully converted to {(endianness == OMI.ByteOrder.LittleEndian ? "little" : "big")} endian.", "Converted PCK file");
+ }
+ }
+ catch (OverflowException)
+ {
+ MessageBox.Show(this, $"File was not a valid {(endianness != OMI.ByteOrder.LittleEndian ? "little" : "big")} endian PCK File.", "Not a valid PCK file");
+ return;
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show(this, ex.Message, "Not a valid PCK file");
+ return;
+ }
+ }
+
+ private void littleEndianToolStripMenuItem_Click(object sender, EventArgs e) => SetPckEndianness(OMI.ByteOrder.LittleEndian);
+
+ private void bigEndianToolStripMenuItem_Click(object sender, EventArgs e) => SetPckEndianness(OMI.ByteOrder.BigEndian);
+
+ private void SetModelVersion(int version)
+ {
+ if (treeViewMain.SelectedNode.Tag is PckAsset asset && asset.Type is PckAssetType.ModelsFile)
+ {
+ try
+ {
+ ModelContainer container = asset.GetData(new ModelFileReader());
+
+ if (container.Version == version)
+ {
+ MessageBox.Show(
+ this,
+ $"This model container is already Version {version + 1}.",
+ "Can't convert", MessageBoxButtons.OK, MessageBoxIcon.Error
+ );
+ return;
+ }
+
+ if (version == 2 &&
+ MessageBox.Show(
+ this,
+ "Conversion to 1.14 models.bin format does not yet support parent declaration and may not be 100% accurate.\n" +
+ "Would you like to continue?", "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) != DialogResult.Yes
+ )
+ {
+ return;
+ }
+
+ if (container.Version > 1 &&
+ MessageBox.Show(
+ this,
+ "Conversion from 1.14 models.bin format does not yet support parent parts and may not be 100% accurate.\n" +
+ "Would you like to continue?", "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) != DialogResult.Yes
+ )
+ {
+ return;
+ }
+
+ asset.SetData(new ModelFileWriter(container, version));
+ _wasModified = true;
+ MessageBox.Show(
+ this,
+ $"\"{asset.Filename}\" successfully converted to Version {version + 1} format.",
+ "Converted model container file"
+ );
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show(this, ex.Message, "Not a valid model container file.");
+ return;
+ }
+ }
+ }
+
+ private void setModelVersion1ToolStripMenuItem_Click(object sender, EventArgs e) => SetModelVersion(0);
+
+ private void setModelVersion2ToolStripMenuItem_Click(object sender, EventArgs e) => SetModelVersion(1);
+
+ private void setModelVersion3ToolStripMenuItem_Click(object sender, EventArgs e) => SetModelVersion(2);
+
+ private void treeViewMain_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
+ {
+ if (e.Node is not null)
+ treeViewMain.SelectedNode = e.Node;
+ }
+
+ private void contextMenuPCKEntries_Opening(object sender, System.ComponentModel.CancelEventArgs e)
+ {
+ correctSkinDecimalsToolStripMenuItem.Visible = false;
+ generateMipMapTextureToolStripMenuItem1.Visible = false;
+ setModelContainerFormatToolStripMenuItem.Visible = false;
+ setSubPCKEndiannessToolStripMenuItem.Visible = false;
+ exportToolStripMenuItem.Visible = false;
+ toolStripSeparator5.Visible = false;
+ toolStripSeparator6.Visible = false;
+ if (treeViewMain?.SelectedNode.TryGetTagData(out PckAsset asset) ?? false)
+ {
+ replaceToolStripMenuItem.Visible = true;
+ cloneFileToolStripMenuItem.Visible = true;
+ setFileTypeToolStripMenuItem.Visible = true;
+ toolStripSeparator5.Visible = true;
+ toolStripSeparator6.Visible = true;
+
+ if (asset.Type == PckAssetType.SkinFile)
+ {
+ correctSkinDecimalsToolStripMenuItem.Visible = true;
+ exportToolStripMenuItem.Visible = true;
+ }
+ if (asset.Type == PckAssetType.TextureFile)
+ generateMipMapTextureToolStripMenuItem1.Visible = true;
+ if (asset.Type == PckAssetType.ModelsFile)
+ setModelContainerFormatToolStripMenuItem.Visible = true;
+ if (asset.Type == PckAssetType.SkinDataFile || asset.Type == PckAssetType.TexturePackInfoFile || asset.Type == PckAssetType.AudioFile)
+ setSubPCKEndiannessToolStripMenuItem.Visible = true;
+ }
+ else
+ {
+ replaceToolStripMenuItem.Visible = false;
+ cloneFileToolStripMenuItem.Visible = false;
+ setFileTypeToolStripMenuItem.Visible = false;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/PCK-Studio/Controls/PckEditor.resx b/PCK-Studio/Controls/PckEditor.resx
new file mode 100644
index 00000000..5e94f7c7
--- /dev/null
+++ b/PCK-Studio/Controls/PckEditor.resx
@@ -0,0 +1,2097 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ False
+
+
+
+
+ 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
+ 8+BMiU9xSj9GDDCHwDUcMkHMV8I4YKwwEz0K5TTDbjg/NnbZmEsvwcYuuVQYpxwTXCyU8g2YMaMA9NIJ
+ QlbKc/bsWePhf9yV868cRwU+9urlV49ddc3mO2PQDmDbQrL1wvZLH2n1jwL0m3S/9BN9i3ENH0E3I+Ij
+ 165ePWaFyYNijmQzbk6y88LG0GHSNcktA2RXAwTAVlDG8CCv2hKBdbzbZhRPJilXFq4wuuJh8dIlYxYs
+ Xjhm/sL5Y+fMgz7wYKfjL5ulHyRZNmWXbKCcX4CWVvpbgeTVFkhq0j+BAmI8iTTZBwWAzyt9dNH16gP/
+ HXPlvCvGzJs7Tx9M/ohfjp/5M3zskkuJl5c2/SoAuyjtI8ULoND/ZfgWuhdK9G0bxdkYVm1j0OlYdErs
+ wq+Zk/kS3sJXSkjy8rMGok+SZSlXQL8z3hvLkn6JT+7OLKZwXrZ0KSvWFSNio/3Wb/3Wb/3Wb/3Wb/3W
+ b/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3W
+ b/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3W
+ b/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb1uy/Yf/8P8D4rKD
+ rca4/zIAAAAASUVORK5CYII=
+
+
+
+
+ NoControl
+
+
+ 413, 0
+
+
+ 190, 50
+
+
+ Zoom
+
+
+
+ 14
+
+
+ logoPictureBox
+
+
+ System.Windows.Forms.PictureBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ $this
+
+
+ 10
+
+
+ 8, 27
+
+
+ 241, 23
+
+
+ 2
+
+
+ pckFileLabel
+
+
+ MetroFramework.Controls.MetroLabel, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
+
+
+ $this
+
+
+ 4
+
+
+ Top, Right
+
+
+ True
+
+
+ 1369, 252
+
+
+ 30, 19
+
+
+ 19
+
+
+ aaa
+
+
+ labelImageSize
+
+
+ MetroFramework.Controls.MetroLabel, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
+
+
+ $this
+
+
+ 5
+
+
+ Top, Right
+
+
+ True
+
+
+ 1347, 53
+
+
+ 0, 0
+
+
+ 17
+
+
+ fileEntryCountLabel
+
+
+ MetroFramework.Controls.MetroLabel, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
+
+
+ $this
+
+
+ 6
+
+
+ Bottom, Right
+
+
+ True
+
+
+ 204, 144
+
+
+ 0, 0
+
+
+ 15
+
+
+ metroLabel2
+
+
+ MetroFramework.Controls.MetroLabel, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
+
+
+ MetaTab
+
+
+ 2
+
+
+ Bottom, Right
+
+
+
+
+
+ NoControl
+
+
+ 128, 2
+
+
+ 15, 15
+
+
+ 1
+
+
+ False
+
+
+ False
+
+
+ 215, 114
+
+
+ 146, 20
+
+
+ 21
+
+
+ entryTypeTextBox
+
+
+ MetroFramework.Controls.MetroTextBox, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
+
+
+ MetaTab
+
+
+ 3
+
+
+ Bottom, Right
+
+
+
+
+
+ NoControl
+
+
+ 128, 2
+
+
+ 15, 15
+
+
+ 1
+
+
+ False
+
+
+ False
+
+
+ 215, 146
+
+
+ 146, 20
+
+
+ 16
+
+
+ entryDataTextBox
+
+
+ MetroFramework.Controls.MetroTextBox, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
+
+
+ MetaTab
+
+
+ 4
+
+
+ Bottom, Right
+
+
+ 215, 172
+
+
+ 146, 33
+
+
+ 20
+
+
+ buttonEdit
+
+
+ False
+
+
+ buttonEdit
+
+
+ MetroFramework.Controls.MetroButton, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
+
+
+ MetaTab
+
+
+ 5
+
+
+ Bottom, Right
+
+
+ True
+
+
+ 266, 37
+
+
+ 0, 0
+
+
+ 13
+
+
+ metroLabel1
+
+
+ MetroFramework.Controls.MetroLabel, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
+
+
+ MetaTab
+
+
+ 6
+
+
+ 301, 19
+
+
+ 160, 22
+
+
+ Add Entry
+
+
+ 160, 22
+
+
+ Add BOX Entry
+
+
+ 160, 22
+
+
+ Add ANIM Entry
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+ vAAADrwBlbxySQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xMkMEa+wAAABSSURBVDhP5c0x
+ DsAgDENRxt7/wmkNSpRGf0CCCZAegxNMM7MlGMp3dIU6dxhKf/QMNxRogeQC8ivw5Vn7C0heJlFA+kL5
+ jWAohxRkde4wnGftBS90axNmphIGAAAAAElFTkSuQmCC
+
+
+
+ 181, 22
+
+
+ Add Entry
+
+
+ 181, 22
+
+
+ Add Multiple Entries
+
+
+ 181, 22
+
+
+ Delete Entry
+
+
+ 181, 22
+
+
+ Edit All Entries
+
+
+ 182, 92
+
+
+ contextMenuMetaTree
+
+
+ System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Left
+
+
+ 5, 5
+
+
+ 204, 229
+
+
+ 0
+
+
+ treeMeta
+
+
+ System.Windows.Forms.TreeView, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ MetaTab
+
+
+ 7
+
+
+ 4, 38
+
+
+ 5, 5, 5, 5
+
+
+ 724, 239
+
+
+ 0
+
+
+ Properties
+
+
+ MetaTab
+
+
+ MetroFramework.Controls.MetroTabPage, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
+
+
+ PropertiesTabControl
+
+
+ 0
+
+
+ Bottom
+
+
+ 279, 270
+
+
+ 732, 281
+
+
+ 11
+
+
+ PropertiesTabControl
+
+
+ MetroFramework.Controls.MetroTabControl, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
+
+
+ $this
+
+
+ 7
+
+
+ True
+
+
+ True
+
+
+ 433, 71
+
+
+ 0, 0
+
+
+ 3
+
+
+ label11
+
+
+ MetroFramework.Controls.MetroLabel, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
+
+
+ $this
+
+
+ 8
+
+
+ 22, 20
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+ vAAADrwBlbxySQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xOdTWsmQAAABVSURBVDhPYxgc
+ 4P8Chv8YeKWUIFSaMPi/W+r//1MapOGTOixQ7UADsCkgAkO1jywDRIGxA8JQPlQ7PQyAaUTDUO30MACG
+ YZqhfKh24gGGzYMAMDAAAPvHncAZVkkSAAAAAElFTkSuQmCC
+
+
+
+ 172, 22
+
+
+ Folder
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+ vAAADrwBlbxySQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xOdTWsmQAAAIkSURBVDhPpdLf
+ T1JxGMfxc1n8qtzcyglCWhFS1PLGHAgisDmktZZtabRSEYhDZ8xpiSWVpaSxLpoXyWquLvzV+oGZq+iy
+ /6Stm7qsm+DT830YMJw3rbO9Djs7z/P+wob03xcAyWbUwqLXotWgha1pDzPr1axl/y52uEHFrAY1z4l5
+ sVsK0IK1UVMbaKQAOXhgN2tuKLHQTKtBh6M0XwmIxe1OtexjXZa9pA6dlnomlgXx7WoCo/1eTF3pwfRQ
+ gM3HLmD+Wh8yIwE8CgcwFznLJs67cLPPgeMmXW1gKRXCZjqGfCbBvi6kWH6OnoXMKFsd68fa2CW0Haqr
+ BpYnh5G7F8PGtIyV2yG2NhXHeuo6nioD5CI+pRMsG+nFYqSHVQKrt0LYKAcmhyCeX6Vklk0MsI9phQIK
+ Bfy07OfPSkAs/v7xDcViEd6OZ/C2LyOXHMb75Agtlk72nF6hdy/FEgrFP3yI2OVA7r6MXz+/04siPB3P
+ aXgJ75JhbFIgP5PAZwr42lcp8IJnioUCBcLVQHbQizfjQTr1Kj7cTbBIpw1R54mK/GwMXwjqaYWkzrVV
+ A4uDPry+QYGJIN7eUVjMcQyyvWrrQRxbM/GdA4+Dbjy57MJC0AmnUQ2XUYPZXjse+qvKi9vRHZLisUJx
+ WyB3m0sBkwZuvYr56A8j7LQs0B2S7LMg2n0EUY8ZdpMaDgo4mlSsq1lXo7w4fuZk6Sf861U5mS9J+gsp
+ e+98+xbVEAAAAABJRU5ErkJggg==
+
+
+
+ 172, 22
+
+
+ Skin
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+ vAAADrwBlbxySQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xMkMEa+wAAAI/SURBVDhPjZHt
+ b9JQFMbvv6IRCiYmU+cGpQXH5oACMkZvgQILG2Su7e2mE3l1cTMricaXEQtscVN0UYIaB8MZmW/ZFxP/
+ KrzNpCHxi0+eL/ec53fuSQ7IHLqyXW+uwwj7lLBvQweu9N6Y/M65/h3iOmpNLL2hxaYj1bAEnxhXPkyB
+ TNe9/H76YS96rzOz0Z3lSQI1banX1uTLMfVkYetnMt/2LTRGMq1rwlv7SssJHnyLcbRp77csvLLdaF1l
+ HabVg+mElVg9cq//gOpJ+tmvVNRmiKsXUi8sPGUGPEWIshihiShlvN1meNoQoQ1R2jDfuBimCfHjJOsg
+ SrNXWIcRJwuQBFXJneXoOvL0NiGkzDtLrgJnKUIySp6L0MYYeVYWhUKYrAq+MG3WgGJolCfP1BGzI0zc
+ gfYcpNrlNHZ/SE9Ff4Ejn4vOjjIHDu7HI7RpjRsvsiOPN+7iRmVxqpkLakEANPf7ypyjnJzEQzEDegon
+ eS/t3grs3gw+Ki5iIAfJCgoMA7i4hWZU6TpmwCdlHr+7SvpoM1YR/VpO1wDQhRlQkzzZ0OVsmKwhby5k
+ 1cqnuX+tA1WZ4e3mUtiK/X/AcgBv9bUcx9YAXYOcrlPAm+fIIhyvIh/e6lhJYHiNHdX6AwAHPpcTPSWm
+ AVnWCh2mbeQpQEtN9tclpip78nBot37/i5KoIUY7rhIDOdaiIl+es5U4MkIZ8S15O4E/0YCB8HNbcuOh
+ mAGqxOQ5S4Q6f1yOF6CVp0w6gxfQ/ZdBnj/Cc21Sm8M0egAAAABJRU5ErkJggg==
+
+
+
+ 172, 22
+
+
+ Animated Texture
+
+
+ 172, 22
+
+
+ Audio.pck
+
+
+ 172, 22
+
+
+ Colours.col
+
+
+ 172, 22
+
+
+ Skins.pck
+
+
+ 172, 22
+
+
+ Behaviours.bin
+
+
+ 172, 22
+
+
+ EntityMaterials.bin
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+ vAAADrwBlbxySQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xOdTWsmQAAAA3SURBVDhPY/j/
+ /z9FGKsgGIsCKWSMTQ0QYxUE45FmALpiYvFwMgAbxqIYG8YqCMajBhCJ/zMAAPGwpV/Xje8RAAAAAElF
+ TkSuQmCC
+
+
+
+ 157, 22
+
+
+ Create
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+ vAAADrwBlbxySQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xOdTWsmQAAAIkSURBVDhPpdLf
+ T1JxGMfxc1n8qtzcyglCWhFS1PLGHAgisDmktZZtabRSEYhDZ8xpiSWVpaSxLpoXyWquLvzV+oGZq+iy
+ /6Stm7qsm+DT830YMJw3rbO9Djs7z/P+wob03xcAyWbUwqLXotWgha1pDzPr1axl/y52uEHFrAY1z4l5
+ sVsK0IK1UVMbaKQAOXhgN2tuKLHQTKtBh6M0XwmIxe1OtexjXZa9pA6dlnomlgXx7WoCo/1eTF3pwfRQ
+ gM3HLmD+Wh8yIwE8CgcwFznLJs67cLPPgeMmXW1gKRXCZjqGfCbBvi6kWH6OnoXMKFsd68fa2CW0Haqr
+ BpYnh5G7F8PGtIyV2yG2NhXHeuo6nioD5CI+pRMsG+nFYqSHVQKrt0LYKAcmhyCeX6Vklk0MsI9phQIK
+ Bfy07OfPSkAs/v7xDcViEd6OZ/C2LyOXHMb75Agtlk72nF6hdy/FEgrFP3yI2OVA7r6MXz+/04siPB3P
+ aXgJ75JhbFIgP5PAZwr42lcp8IJnioUCBcLVQHbQizfjQTr1Kj7cTbBIpw1R54mK/GwMXwjqaYWkzrVV
+ A4uDPry+QYGJIN7eUVjMcQyyvWrrQRxbM/GdA4+Dbjy57MJC0AmnUQ2XUYPZXjse+qvKi9vRHZLisUJx
+ WyB3m0sBkwZuvYr56A8j7LQs0B2S7LMg2n0EUY8ZdpMaDgo4mlSsq1lXo7w4fuZk6Sf861U5mS9J+gsp
+ e+98+xbVEAAAAABJRU5ErkJggg==
+
+
+
+ 228, 22
+
+
+ Import Skin
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+ vAAADrwBlbxySQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xOdTWsmQAAAEnSURBVDhPYxgc
+ 4P8Chv8YeKWUIFSaMPi/W+r//1MapOGTOixQ7UADkCS05Xjh2FhFEIydtIT+22uJAsX4wBimFqod04Bt
+ nTn/9/YV/T82rQGM93YXAfkl/1eVRYPl8RqwuTnn/5aW3P8r69L+r67P+7+mIf//rIKo/7s7i/7PyfT9
+ PzvTC78BW6AGrKpN+7+2IReM5xTF/N/VWQA0wAdogA8BA4Ca//7799/VauH/TdUZ/7dVp//fA7Td3XLV
+ //+iwNgBYXwGbCiP+7+5Oun/9qai/5n2+v+zHAzAeG9HDnEGTIl3/D8tzuG/owLP/w5f2/9dPrYIjWgY
+ qh3VgAJnrf+5Lhr/HRV5/jvLcoExNs0gDNWOagBeDNMM5UO1Ew8wbB4EgIEBABiEccKRdcoAAAAAAElF
+ TkSuQmCC
+
+
+
+ 228, 22
+
+
+ Import Extracted Skins Folder
+
+
+ 228, 22
+
+
+ Add Texture
+
+
+ 228, 22
+
+
+ Add File
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+ vAAADrwBlbxySQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xOdTWsmQAAABzSURBVDhPpYzB
+ DQAhCARp4hr3Txu254WTjYRb9cEmk/BgRjBVHTv85Twmgt77PcJEYIFrhIkAgWOEiSAGthEmgtbaD9fW
+ mBgpB4xywCgFxiMf5YDdrq3l5wjEjKtzTARMNlydY2IGot2ureVnRjkQmZbICyCi7XU5cfqKAAAAAElF
+ TkSuQmCC
+
+
+
+ 157, 22
+
+
+ Import
+
+
+ 186, 22
+
+
+ Export as 3DS Texture
+
+
+ 157, 22
+
+
+ Export
+
+
+ 222, 22
+
+
+ Skin (.PNG)
+
+
+ 222, 22
+
+
+ Cape (.PNG)
+
+
+ 222, 22
+
+
+ Texture (.PNG)
+
+
+ 222, 22
+
+
+ Languages File (.LOC)
+
+
+ 222, 22
+
+
+ Game Rules File (.GRF)
+
+
+ 222, 22
+
+
+ Music Cues File (audio.PCK)
+
+
+ 222, 22
+
+
+ Colour Table File (.COL)
+
+
+ 222, 22
+
+
+ Game Rules Header (.GRH)
+
+
+ 222, 22
+
+
+ Skins PCK (.PCK)
+
+
+ 222, 22
+
+
+ Models File (.BIN)
+
+
+ 222, 22
+
+
+ Behaviours File (.BIN)
+
+
+ 222, 22
+
+
+ Entity Materials File (.BIN)
+
+
+ 157, 22
+
+
+ Set File Type
+
+
+ 154, 6
+
+
+ 223, 22
+
+
+ Generate MipMap Texture
+
+
+ 223, 22
+
+
+ View File Info
+
+
+ 223, 22
+
+
+ Correct Skin Decimals
+
+
+ 100, 22
+
+
+ Big
+
+
+ 100, 22
+
+
+ Little
+
+
+ 223, 22
+
+
+ Set Endianness
+
+
+ 80, 22
+
+
+ 1
+
+
+ 80, 22
+
+
+ 2
+
+
+ 80, 22
+
+
+ 3
+
+
+ 223, 22
+
+
+ Set Model Container version
+
+
+ 157, 22
+
+
+ Misc. Functions
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+ vAAADrwBlbxySQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xMkMEa+wAAACYSURBVDhPpZBZ
+ CsQwDEOd5QK5/2E9qCBGXtopzMcDxxKyY3P3izmnm9kt0OlVvsVVVgOAtvduQ4KJdYbaGKOEFFOHamut
+ ENKaMlk75zi2QX1rUqDpkbEF/cGktb47ygb5ODA8hVArgsK1cx+EAE7LaB8+hb3QzDx942eAXrqjBOgR
+ MRkBfHeUADbe8ncANw4NhLwF33R3+wA6sV5/E8GOLwAAAABJRU5ErkJggg==
+
+
+
+ 157, 22
+
+
+ Extract
+
+
+ 154, 6
+
+
+ 157, 22
+
+
+ Clone
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+ vAAADrwBlbxySQAAACVJREFUOE9jwAL+E8AkAbI0IYNRA0YNAIFRA8g0AKYJF0YCDAwAzhor1TRE/JoA
+ AAAASUVORK5CYII=
+
+
+
+ 157, 22
+
+
+ Rename
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+ vAAADrwBlbxySQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xMkMEa+wAAAC/SURBVDhPlVHB
+ DQMhDEOIfwfoOuzFoPxhAd5c6/SMAgq0tRQFmdgXfA5IKUkBMcbHPxyJCxVCkK7rm+EwaK1dQO9dClzO
+ WfpOTM7hy1oMGNvY4pucxNY2p6cAWzFw2oZuMmiJweGeHM634UdLg50YwD05vQ2fYoaoDTEMrJyIfw3R
+ 4qYQWUZgg6OwlDJyMH8LcwF2T8FZ5kYQb4Lde/9Et8S6Dy1z0LUGi7VpWGvl3Lw2V98ZrtwIUYktwwPn
+ 3AtE5NqX8pp0ZQAAAABJRU5ErkJggg==
+
+
+
+ 157, 22
+
+
+ Replace
+
+
+ 157, 22
+
+
+ Delete
+
+
+ 158, 236
+
+
+ contextMenuPCKEntries
+
+
+ System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Left
+
+
+ 0
+
+
+ 204, 20
+
+
+ 32, 32
+
+
+ 5, 50
+
+
+ 0
+
+
+ 274, 501
+
+
+ 20
+
+
+ treeViewMain
+
+
+ System.Windows.Forms.TreeView, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ $this
+
+
+ 9
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+ vAAADrwBlbxySQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xMkMEa+wAAABSSURBVDhP5c0x
+ DsAgDENRxt7/wmkNSpRGf0CCCZAegxNMM7MlGMp3dIU6dxhKf/QMNxRogeQC8ivw5Vn7C0heJlFA+kL5
+ jWAohxRkde4wnGftBS90axNmphIGAAAAAElFTkSuQmCC
+
+
+
+ 181, 22
+
+
+ Add Multiple Entries
+
+
+ Top, Right
+
+
+ True
+
+
+ 831, 0
+
+
+ 173, 15
+
+
+ 22
+
+
+ Save as Switch/Vita/PS4 PCK
+
+
+ LittleEndianCheckBox
+
+
+ MetroFramework.Controls.MetroCheckBox, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
+
+
+ $this
+
+
+ 3
+
+
+ Top, Bottom, Left, Right
+
+
+ None
+
+
+ NoControl
+
+
+ 285, 50
+
+
+ 218, 218
+
+
+ Zoom
+
+
+ 18
+
+
+ previewPictureBox
+
+
+ PckStudio.ToolboxItems.InterpolationPictureBox, PCK-Studio, Version=7.0.0.2, Culture=neutral, PublicKeyToken=null
+
+
+ $this
+
+
+ 2
+
+
+ True
+
+
+ None
+
+
+ 4, 38
+
+
+ 5, 50, 5, 7
+
+
+ 1016, 558
+
+
+ addEntryToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ addEntryToolStripMenuItem1
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ addBOXEntryToolStripMenuItem1
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ addANIMEntryToolStripMenuItem1
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ addMultipleEntriesToolStripMenuItem1
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ deleteEntryToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ editAllEntriesToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ createToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ folderToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ skinToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ createAnimatedTextureToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ audiopckToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ colourscolToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ CreateSkinsPCKToolStripMenuItem1
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ behavioursbinToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ entityMaterialsbinToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ importSkinsToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ importSkinToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ importExtractedSkinsFolderToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ addTextureToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ addFileToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ exportToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ as3DSTextureFileToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ setFileTypeToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ skinToolStripMenuItem1
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ capeToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ textureToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ languagesFileLOCToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ gameRulesFileGRFToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ audioPCKFileToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ coloursCOLFileToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ gameRulesHeaderGRHToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ skinsPCKToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ modelsFileBINToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ behavioursFileBINToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ entityMaterialsFileBINToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ toolStripSeparator5
+
+
+ System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ miscFunctionsToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ generateMipMapTextureToolStripMenuItem1
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ viewFileInfoToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ correctSkinDecimalsToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ setSubPCKEndiannessToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ bigEndianXbox360PS3WiiUToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ littleEndianPS4PSVitaSwitchToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ setModelContainerFormatToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ version1ToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ version2ToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ version3114ToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ extractToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ toolStripSeparator6
+
+
+ System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ cloneFileToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ renameFileToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ replaceToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ deleteFileToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ imageList
+
+
+ System.Windows.Forms.ImageList, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ addMultipleEntriesToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ PckEditor
+
+
+ PckStudio.Internal.EditorControl`1[[PckStudio.Internal.PackInfo, PCK-Studio, Version=7.0.0.2, Culture=neutral, PublicKeyToken=null]], PCK-Studio, Version=7.0.0.2, Culture=neutral, PublicKeyToken=null
+
+
\ No newline at end of file
diff --git a/PCK-Studio/Forms/Editor/ModelEditor.resx b/PCK-Studio/Forms/Editor/ModelEditor.resx
index a9f732b1..b61b7c65 100644
--- a/PCK-Studio/Forms/Editor/ModelEditor.resx
+++ b/PCK-Studio/Forms/Editor/ModelEditor.resx
@@ -117,6 +117,7 @@
System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+<<<<<<<< HEAD:PCK-Studio/Forms/Editor/ModelEditor.resx
17, 17
@@ -126,7 +127,128 @@
293, 17
+========
+
+
+ True
+
+>>>>>>>> main:PckStudio.Core/ItemSelectionPopUp.resx
+
+ 15, 41
+
+
+ 35, 13
+
+
+ 3
+
+
+ Items:
+
+
+ label2
+
+
+ System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ $this
+
+
+ 3
+
+
+
+ Flat
+
+
+ 54, 76
+
+
+ 75, 23
+
+
+ 4
+
+
+ Add
+
+
+ okBtn
+
+
+ System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ $this
+
+
+ 2
+
+
+ Flat
+
+
+ NoControl
+
+
+ 135, 76
+
+
+ 75, 23
+
+
+ 6
+
+
+ Cancel
+
+
+ cancelButton
+
+
+ System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ $this
+
+
+ 1
+
+
+ 23
+
+
+ 60, 34
+
+
+ 192, 29
+
+
+ 7
+
+
+ ComboBox
+
+
+ MetroFramework.Controls.MetroComboBox, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
+
+
+ $this
+
+
+ 0
+
+
+ True
+
+
+ 6, 13
+
+
+ 264, 105
+
AAABAA0AAAAAAAEAIAD7NAAA1gAAAICAAAABACAAKAgBANE1AACAgAAAAQAIAChMAAD5PQEAQEAAAAEA
@@ -2633,4 +2755,13 @@
AP//AAA=
+
+ CenterParent
+
+
+ ItemSelectionPopUp
+
+
+ MetroFramework.Forms.MetroForm, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
+
\ No newline at end of file
diff --git a/PckStudio.Core/Resources/additional_mapicons.png b/PckStudio.Core/Resources/additional_mapicons.png
new file mode 100644
index 00000000..11b7256a
Binary files /dev/null and b/PckStudio.Core/Resources/additional_mapicons.png differ
diff --git a/PckStudio.Core/Resources/bannerData.json b/PckStudio.Core/Resources/bannerData.json
new file mode 100644
index 00000000..f1de015f
--- /dev/null
+++ b/PckStudio.Core/Resources/bannerData.json
@@ -0,0 +1,1053 @@
+{
+ "COMMENT_1": "JSON by MattNL",
+ "entries": [
+ {
+ "internalName": "base",
+ "displayName": "Base",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "border",
+ "displayName": "Bordure",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "bricks",
+ "displayName": "Field Masoned",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "circle",
+ "displayName": "Roundel",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "creeper",
+ "displayName": "Creeper Charge",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "cross",
+ "displayName": "Saltire",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "curly_border",
+ "displayName": "Bordure Indented",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "diagonal_left",
+ "displayName": "Per Bend Sinister",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "diagonal_right",
+ "displayName": "Per Bend",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "diagonal_up_left",
+ "displayName": "Per Bend Inverted",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "diagonal_up_right",
+ "displayName": "Per Bend Sinister Inverted",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "flower",
+ "displayName": "Flower Charge",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "gradient",
+ "displayName": "Gradient",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "gradient_up",
+ "displayName": "Base Gradient",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "half_horizontal",
+ "displayName": "Per Fess",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "half_horizontal_bottom",
+ "displayName": "Per Fess Inverted",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "half_vertical",
+ "displayName": "Per Pale",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "half_vertical_right",
+ "displayName": "Per Pale Inverted",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "mojang",
+ "displayName": "Thing",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "rhombus",
+ "displayName": "Lozenge",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "skull",
+ "displayName": "Skull Charge",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "small_stripes",
+ "displayName": "Paly",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "square_bottom_left",
+ "displayName": "Base Dexter Canton",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "square_bottom_right",
+ "displayName": "Base Sinister Canton",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "square_top_left",
+ "displayName": "Chief Dexter Canton",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "square_top_right",
+ "displayName": "Chief Sinister Canton",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "straight_cross",
+ "displayName": "Cross",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "stripe_bottom",
+ "displayName": "Base Fess",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "stripe_center",
+ "displayName": "Pale",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "strip_downleft",
+ "displayName": "Bend Sinister",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "stripe_downright",
+ "displayName": "Bend",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "stripe_left",
+ "displayName": "Pale Dexter",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "stripe_middle",
+ "displayName": "Fess",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "stripe_right",
+ "displayName": "Pale Sinister",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "stripe_top",
+ "displayName": "Chief Fess",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "triangle_bottom",
+ "displayName": "Chevron",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "triangle_top",
+ "displayName": "Inverted Chevron",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "triangles_bottom",
+ "displayName": "Base Indented",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "triangles_top",
+ "displayName": "Chief Indented",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "mask",
+ "displayName": "Mask"
+ },
+ {
+ "internalName": "illager",
+ "displayName": "Ominous Banner [PS4 ONLY]"
+ },
+ {
+ "internalName": "globe",
+ "displayName": "Globe [PS4 ONLY]",
+
+ "colourEntry": {
+ "defaultName": "Banner_White",
+ "variants": [
+ "Banner_Black",
+ "Banner_Blue",
+ "Banner_Brown",
+ "Banner_Cyan",
+ "Banner_Gray",
+ "Banner_Green",
+ "Banner_Light_Blue",
+ "Banner_Lime",
+ "Banner_Magenta",
+ "Banner_Orange",
+ "Banner_Pink",
+ "Banner_Purple",
+ "Banner_Red",
+ "Banner_Silver",
+ "Banner_White",
+ "Banner_Yellow"
+ ]
+ }
+ }
+ ]
+}
diff --git a/PckStudio.Core/Resources/banners.png b/PckStudio.Core/Resources/banners.png
new file mode 100644
index 00000000..952a0eff
Binary files /dev/null and b/PckStudio.Core/Resources/banners.png differ
diff --git a/PckStudio.Core/Resources/blockData.json b/PckStudio.Core/Resources/blockData.json
new file mode 100644
index 00000000..d4622c10
--- /dev/null
+++ b/PckStudio.Core/Resources/blockData.json
@@ -0,0 +1,2922 @@
+{
+ "COMMENT_1": "Tile data research by MattNL",
+ "COMMENT_2": "JSON by PhoenixARC, MattNL, and NessieHax (Miku-666)",
+ "entries": [
+ {
+ "internalName": "grass_top",
+ "displayName": "Grass Block (Top)",
+
+ "colourEntry": {
+ "defaultName": "Grass_Common",
+ "variants": [
+ "Grass_Common",
+ "Grass_Mesa",
+ "Grass_Swamp1",
+ "Grass_Swamp2"
+ ]
+ }
+ },
+ {
+ "internalName": "stone",
+ "displayName": "Stone"
+ },
+ {
+ "internalName": "dirt",
+ "displayName": "Dirt"
+ },
+ {
+ "internalName": "grass_side",
+ "displayName": "Grass Block (Side)"
+ },
+ {
+ "internalName": "planks_oak",
+ "displayName": "Oak Planks"
+ },
+ {
+ "internalName": "stoneslab_side",
+ "displayName": "Stone Slab (Side)"
+ },
+ {
+ "internalName": "stoneslab_top",
+ "displayName": "Stone Slab (Top)"
+ },
+ {
+ "internalName": "brick",
+ "displayName": "Bricks"
+ },
+ {
+ "internalName": "tnt_side",
+ "displayName": "TNT (Side)"
+ },
+ {
+ "internalName": "tnt_top",
+ "displayName": "TNT (Top)"
+ },
+ {
+ "internalName": "tnt_bottom",
+ "displayName": "TNT (Bottom)"
+ },
+ {
+ "internalName": "web",
+ "displayName": "Cobweb"
+ },
+ {
+ "internalName": "flower_rose",
+ "displayName": "Poppy"
+ },
+ {
+ "internalName": "flower_dandelion",
+ "displayName": "Dandelion"
+ },
+ {
+ "internalName": "portal",
+ "displayName": "Nether Portal"
+ },
+ {
+ "internalName": "sapling",
+ "displayName": "Oak Sapling"
+ },
+ {
+ "internalName": "cobblestone",
+ "displayName": "Cobblestone"
+ },
+ {
+ "internalName": "bedrock",
+ "displayName": "Bedrock"
+ },
+ {
+ "internalName": "sand",
+ "displayName": "Sand"
+ },
+ {
+ "internalName": "gravel",
+ "displayName": "Gravel"
+ },
+ {
+ "internalName": "log_oak",
+ "displayName": "Oak Wood (Side)"
+ },
+ {
+ "internalName": "log_oak_top",
+ "displayName": "Oak Wood (Top)"
+ },
+ {
+ "internalName": "iron_block",
+ "displayName": "Block of Iron"
+ },
+ {
+ "internalName": "gold_block",
+ "displayName": "Block of Gold"
+ },
+ {
+ "internalName": "diamond_block",
+ "displayName": "Block of Diamond"
+ },
+ {
+ "internalName": "emerald_block",
+ "displayName": "Block of Emerald"
+ },
+ {
+ "internalName": "redstone_block",
+ "displayName": "Block of Redstone"
+ },
+ {
+ "internalName": "dropper_front_horizontal",
+ "displayName": "Dropper (Front)"
+ },
+ {
+ "internalName": "mushroom_red",
+ "displayName": "Mushroom (Red)"
+ },
+ {
+ "internalName": "mushroom_brown",
+ "displayName": "Mushroom (Brown)"
+ },
+ {
+ "internalName": "sapling_jungle",
+ "displayName": "Jungle Tree Sapling"
+ },
+ {
+ "internalName": "fire_0",
+ "displayName": "Fire (Layer 1)"
+ },
+ {
+ "internalName": "gold_ore",
+ "displayName": "Gold Ore"
+ },
+ {
+ "internalName": "iron_ore",
+ "displayName": "Iron Ore"
+ },
+ {
+ "internalName": "coal_ore",
+ "displayName": "Coal Ore"
+ },
+ {
+ "internalName": "bookshelf",
+ "displayName": "Bookshelf"
+ },
+ {
+ "internalName": "cobblestone_mossy",
+ "displayName": "Moss Stone"
+ },
+ {
+ "internalName": "obsidian",
+ "displayName": "Obsidian"
+ },
+ {
+ "internalName": "grass_side_overlay",
+ "displayName": "Grass Side (Overlay)",
+
+ "colourEntry": {
+ "defaultName": "Grass_Common",
+ "variants": [
+ "Grass_Common",
+ "Grass_Mesa",
+ "Grass_Swamp1",
+ "Grass_Swamp2"
+ ]
+ }
+ },
+ {
+ "internalName": "tallgrass",
+ "displayName": "Tall Grass",
+
+ "colourEntry": {
+ "defaultName": "Grass_Common",
+ "variants": [
+ "Grass_Common",
+ "Grass_Mesa",
+ "Grass_Swamp1",
+ "Grass_Swamp2"
+ ]
+ }
+ },
+ {
+ "internalName": "dispenser_front_vertical",
+ "displayName": "Dispenser (Vertical) (Front)"
+ },
+ {
+ "internalName": "beacon",
+ "displayName": "Beacon"
+ },
+ {
+ "internalName": "dropper_front_vertical",
+ "displayName": "Dropper (Vertical) (Front)"
+ },
+ {
+ "internalName": "workbench_top",
+ "displayName": "Crafting Table (Top)"
+ },
+ {
+ "internalName": "furnace_front",
+ "displayName": "Furnace (Front)"
+ },
+ {
+ "internalName": "furnace_side",
+ "displayName": "Furnace/Dispenser/Dropper (Side)"
+ },
+ {
+ "internalName": "dispenser_front",
+ "displayName": "Dispenser (Front)"
+ },
+ {
+ "internalName": "fire_1",
+ "displayName": "Fire (Layer 2)"
+ },
+ {
+ "internalName": "sponge",
+ "displayName": "Sponge"
+ },
+ {
+ "internalName": "glass",
+ "displayName": "Glass"
+ },
+ {
+ "internalName": "diamond_ore",
+ "displayName": "Diamond Ore"
+ },
+ {
+ "internalName": "redstone_ore",
+ "displayName": "Redstone Ore"
+ },
+ {
+ "internalName": "leaves",
+ "displayName": "Oak Leaves",
+
+ "colourEntry": {
+ "defaultName": "Foliage_Default",
+ "variants": [
+ "Foliage_Default",
+ "Foliage_Evergreen",
+ "Foliage_Birch",
+ "Foliage_Mesa",
+ "Foliage_Swampland"
+ ]
+ }
+ },
+ {
+ "internalName": "leaves_opaque",
+ "displayName": "Oak Leaves (Opaque)",
+
+ "colourEntry": {
+ "defaultName": "Foliage_Default",
+ "variants": [
+ "Foliage_Default",
+ "Foliage_Evergreen",
+ "Foliage_Birch",
+ "Foliage_Mesa",
+ "Foliage_Swampland"
+ ]
+ }
+ },
+ {
+ "internalName": "stonebrick",
+ "displayName": "Stone Bricks"
+ },
+ {
+ "internalName": "deadbush",
+ "displayName": "Dead Bush/Shrub"
+ },
+ {
+ "internalName": "fern",
+ "displayName": "Fern",
+
+ "colourEntry": {
+ "defaultName": "Grass_Common",
+ "variants": [
+ "Grass_Common",
+ "Grass_Mesa",
+ "Grass_Swamp1",
+ "Grass_Swamp2"
+ ]
+ }
+ },
+ {
+ "internalName": "daylight_detector_top",
+ "displayName": "Daylight Sensor (Top)"
+ },
+ {
+ "internalName": "daylight_detector_side",
+ "displayName": "Daylight Sensor (Side)"
+ },
+ {
+ "internalName": "workbench_side",
+ "displayName": "Crafting Table (Side)"
+ },
+ {
+ "internalName": "workbench_front",
+ "displayName": "Crafting Table (Front)"
+ },
+ {
+ "internalName": "furnace_front_lit",
+ "displayName": "Furnace (Lit) (Front)"
+ },
+ {
+ "internalName": "furnace_top",
+ "displayName": "Furnace/Dispenser/Dropper (Top)"
+ },
+ {
+ "internalName": "sapling_spruce",
+ "displayName": "Spruce Sapling"
+ },
+ {
+ "internalName": "wool_colored_white",
+ "displayName": "White Wool"
+ },
+ {
+ "internalName": "mob_spawner",
+ "displayName": "Monster Spawner"
+ },
+ {
+ "internalName": "snow",
+ "displayName": "Snow"
+ },
+ {
+ "internalName": "ice",
+ "displayName": "Ice"
+ },
+ {
+ "internalName": "snow_side",
+ "displayName": "Grass Block (Snowy) (Side)"
+ },
+ {
+ "internalName": "cactus_top",
+ "displayName": "Cactus (Top)"
+ },
+ {
+ "internalName": "cactus_side",
+ "displayName": "Cactus (Side)"
+ },
+ {
+ "internalName": "cactus_bottom",
+ "displayName": "Cactus (Bottom)"
+ },
+ {
+ "internalName": "clay",
+ "displayName": "Clay"
+ },
+ {
+ "internalName": "reeds",
+ "displayName": "Sugar Canes"
+ },
+ {
+ "internalName": "jukebox_side",
+ "displayName": "Jukebox (Side)"
+ },
+ {
+ "internalName": "jukebox_top",
+ "displayName": "Jukebox (Top)"
+ },
+ {
+ "internalName": "waterlily",
+ "displayName": "Lily Pad",
+
+ "colourEntry": {
+ "defaultName": "Tile_WaterLily",
+ "variants": [ "Tile_WaterLily" ]
+ }
+ },
+ {
+ "internalName": "mycel_side",
+ "displayName": "Mycelium (Side)"
+ },
+ {
+ "internalName": "mycel_top",
+ "displayName": "Mycelium (Top)"
+ },
+ {
+ "internalName": "sapling_birch",
+ "displayName": "Birch Sapling"
+ },
+ {
+ "internalName": "torch_on",
+ "displayName": "Torch"
+ },
+ {
+ "internalName": "door_wood_upper",
+ "displayName": "Oak Door (Top)"
+ },
+ {
+ "internalName": "door_iron_upper",
+ "displayName": "Iron Door (Top)"
+ },
+ {
+ "internalName": "ladder",
+ "displayName": "Ladder"
+ },
+ {
+ "internalName": "trapdoor",
+ "displayName": "Oak Trapdoor"
+ },
+ {
+ "internalName": "iron_bars",
+ "displayName": "Iron Bars"
+ },
+ {
+ "internalName": "farmland_wet",
+ "displayName": "Farmland (Wet)"
+ },
+ {
+ "internalName": "farmland_dry",
+ "displayName": "Farmland"
+ },
+ {
+ "internalName": "crops_0",
+ "displayName": "Wheat (Stage 1)"
+ },
+ {
+ "internalName": "crops_1",
+ "displayName": "Wheat (Stage 2)"
+ },
+ {
+ "internalName": "crops_2",
+ "displayName": "Wheat (Stage 3)"
+ },
+ {
+ "internalName": "crops_3",
+ "displayName": "Wheat (Stage 4)"
+ },
+ {
+ "internalName": "crops_4",
+ "displayName": "Wheat (Stage 5)"
+ },
+ {
+ "internalName": "crops_5",
+ "displayName": "Wheat (Stage 6)"
+ },
+ {
+ "internalName": "crops_6",
+ "displayName": "Wheat (Stage 7)"
+ },
+ {
+ "internalName": "crops_7",
+ "displayName": "Wheat (Stage 8)"
+ },
+ {
+ "internalName": "lever",
+ "displayName": "Lever"
+ },
+ {
+ "internalName": "door_wood_lower",
+ "displayName": "Oak Door (Bottom)"
+ },
+ {
+ "internalName": "door_iron_lower",
+ "displayName": "Iron Door (Bottom)"
+ },
+ {
+ "internalName": "redstone_torch_on",
+ "displayName": "Redstone Torch"
+ },
+ {
+ "internalName": "stonebrick_mossy",
+ "displayName": "Mossy Stone Bricks"
+ },
+ {
+ "internalName": "stonebrick_cracked",
+ "displayName": "Cracked Stone Bricks"
+ },
+ {
+ "internalName": "pumpkin_top",
+ "displayName": "Pumpkin (Top)"
+ },
+ {
+ "internalName": "netherrack",
+ "displayName": "Netherrack"
+ },
+ {
+ "internalName": "soul_sand",
+ "displayName": "Soul Sand"
+ },
+ {
+ "internalName": "glowstone",
+ "displayName": "Glowstone"
+ },
+ {
+ "internalName": "piston_top_sticky",
+ "displayName": "Sticky Piston (Top)"
+ },
+ {
+ "internalName": "piston_top",
+ "displayName": "Piston (Top)"
+ },
+ {
+ "internalName": "piston_side",
+ "displayName": "Piston (Side)"
+ },
+ {
+ "internalName": "piston_bottom",
+ "displayName": "Piston (Bottom)"
+ },
+ {
+ "internalName": "piston_inner_top",
+ "displayName": "Piston (Inside)"
+ },
+ {
+ "internalName": "stem_straight",
+ "displayName": "Stem",
+
+ "colourEntry": {
+ "defaultName": "Tile_StemMin",
+ "variants": [
+ "Tile_StemMin",
+ "Tile_StemMax"
+ ]
+ }
+ },
+ {
+ "internalName": "rail_normal_turned",
+ "displayName": "Rail (Turned)"
+ },
+ {
+ "internalName": "wool_colored_black",
+ "displayName": "Black Wool"
+ },
+ {
+ "internalName": "wool_colored_gray",
+ "displayName": "Gray Wool"
+ },
+ {
+ "internalName": "redstone_torch_off",
+ "displayName": "Redstone Torch (Off)"
+ },
+ {
+ "internalName": "log_spruce",
+ "displayName": "Spruce Wood (Side)"
+ },
+ {
+ "internalName": "log_birch",
+ "displayName": "Birch Wood (Side)"
+ },
+ {
+ "internalName": "pumpkin_side",
+ "displayName": "Pumpkin (Side)"
+ },
+ {
+ "internalName": "pumpkin_face_off",
+ "displayName": "Carved Pumpkin"
+ },
+ {
+ "internalName": "pumpkin_face_on",
+ "displayName": "Jack-O-Lantern"
+ },
+ {
+ "internalName": "cake_top",
+ "displayName": "Cake (Top)"
+ },
+ {
+ "internalName": "cake_side",
+ "displayName": "Cake (Side)"
+ },
+ {
+ "internalName": "cake_inner",
+ "displayName": "Cake (Inside)"
+ },
+ {
+ "internalName": "cake_bottom",
+ "displayName": "Cake (Bottom)"
+ },
+ {
+ "internalName": "mushroom_block_skin_red",
+ "displayName": "Mushroom (Red Block)"
+ },
+ {
+ "internalName": "mushroom_block_skin_brown",
+ "displayName": "Mushroom (Brown Block)"
+ },
+ {
+ "internalName": "stem_bent",
+ "displayName": "Stem (Attached)",
+
+ "colourEntry": {
+ "defaultName": "Tile_StemMin",
+ "variants": [
+ "Tile_StemMin",
+ "Tile_StemMax"
+ ]
+ }
+ },
+ {
+ "internalName": "rail_normal",
+ "displayName": "Rail"
+ },
+ {
+ "internalName": "wool_colored_red",
+ "displayName": "Red Wool"
+ },
+ {
+ "internalName": "wool_colored_pink",
+ "displayName": "Pink Wool"
+ },
+ {
+ "internalName": "repeater_off",
+ "displayName": "Repeater"
+ },
+ {
+ "internalName": "leaves_spruce",
+ "displayName": "Spruce Leaves",
+
+ "colourEntry": {
+ "defaultName": "Foliage_Evergreen",
+ "variants": [
+ "Foliage_Default",
+ "Foliage_Evergreen",
+ "Foliage_Birch",
+ "Foliage_Mesa",
+ "Foliage_Swampland"
+ ]
+ }
+ },
+ {
+ "internalName": "leaves_spruce_opaque",
+ "displayName": "Spruce Leaves (Opaque)",
+
+ "colourEntry": {
+ "defaultName": "Foliage_Evergreen",
+ "variants": [
+ "Foliage_Default",
+ "Foliage_Evergreen",
+ "Foliage_Birch",
+ "Foliage_Mesa",
+ "Foliage_Swampland"
+ ]
+ }
+ },
+ {
+ "internalName": "conduit_top",
+ "displayName": "Conduit (Break Particles)"
+ },
+ {
+ "internalName": "turtle_egg_hatch_0",
+ "displayName": "Sea Turtle Egg (Stage 1)"
+ },
+ {
+ "internalName": "melon_side",
+ "displayName": "Melon (Side)"
+ },
+ {
+ "internalName": "melon_top",
+ "displayName": "Melon (Top)"
+ },
+ {
+ "internalName": "cauldron_top",
+ "displayName": "Cauldron (Top)"
+ },
+ {
+ "internalName": "cauldron_inner",
+ "displayName": "Cauldron (Inside)"
+ },
+ {
+ "internalName": "sponge_wet",
+ "displayName": "Wet Sponge"
+ },
+ {
+ "internalName": "mushroom_block_skin_stem",
+ "displayName": "Mushroom (Stem Block)"
+ },
+ {
+ "internalName": "mushroom_block_inside",
+ "displayName": "Mushroom (Inside Block)"
+ },
+ {
+ "internalName": "vine",
+ "displayName": "Vines",
+
+ "colourEntry": {
+ "defaultName": "Foliage_Default",
+ "variants": [
+ "Foliage_Default",
+ "Foliage_Evergreen",
+ "Foliage_Birch",
+ "Foliage_Mesa",
+ "Foliage_Swampland"
+ ]
+ }
+ },
+ {
+ "internalName": "lapis_block",
+ "displayName": "Lapis Lazuli Block"
+ },
+ {
+ "internalName": "wool_colored_green",
+ "displayName": "Green Wool"
+ },
+ {
+ "internalName": "wool_colored_lime",
+ "displayName": "Lime Wool"
+ },
+ {
+ "internalName": "repeater_on",
+ "displayName": "Redstone Repeater (On)"
+ },
+ {
+ "internalName": "glass_pane_top",
+ "displayName": "Glass Pane (Top)"
+ },
+ {
+ "internalName": "chest_top",
+ "displayName": "Chest (Break Particles)"
+ },
+ {
+ "internalName": "ender_chest_top",
+ "displayName": "Ender Chest (Break Particles)"
+ },
+ {
+ "internalName": "turtle_egg_hatch_1",
+ "displayName": "Sea Turtle Egg (Stage 2)"
+ },
+ {
+ "internalName": "turtle_egg_hatch_2",
+ "displayName": "Sea Turtle Egg (Stage 3)"
+ },
+ {
+ "internalName": "log_jungle",
+ "displayName": "Jungle Wood (Side)"
+ },
+ {
+ "internalName": "cauldron_side",
+ "displayName": "Cauldron (Side)"
+ },
+ {
+ "internalName": "cauldron_bottom",
+ "displayName": "Cauldron (Bottom)"
+ },
+ {
+ "internalName": "brewing_stand_base",
+ "displayName": "Brewing Stand (Base)"
+ },
+ {
+ "internalName": "brewing_stand",
+ "displayName": "Brewing Stand"
+ },
+ {
+ "internalName": "endframe_top",
+ "displayName": "End Portal Frame (Top)"
+ },
+ {
+ "internalName": "endframe_side",
+ "displayName": "End Portal Frame (Side)"
+ },
+ {
+ "internalName": "lapis_ore",
+ "displayName": "Lapis Lazuli Ore"
+ },
+ {
+ "internalName": "wool_colored_brown",
+ "displayName": "Brown Wool"
+ },
+ {
+ "internalName": "wool_colored_yellow",
+ "displayName": "Yellow Wool"
+ },
+ {
+ "internalName": "rail_golden",
+ "displayName": "Powered Rail"
+ },
+ {
+ "internalName": "redstone_dust_cross",
+ "displayName": "Redstone Dust (Cross)",
+
+ "colourEntry": {
+ "defaultName": "Tile_RedstoneDust",
+ "variants": [
+ "Tile_RedstoneDust",
+ "Tile_RedstoneDustUnlit",
+ "Tile_RedstoneDustLitMin",
+ "Tile_RedstoneDustLitMax"
+ ]
+ }
+ },
+ {
+ "internalName": "redstone_dust_line",
+ "displayName": "Redstone Dust (Line)",
+
+ "colourEntry": {
+ "defaultName": "Tile_RedstoneDust",
+ "variants": [
+ "Tile_RedstoneDust",
+ "Tile_RedstoneDustUnlit",
+ "Tile_RedstoneDustLitMin",
+ "Tile_RedstoneDustLitMax"
+ ]
+ }
+ },
+ {
+ "internalName": "enchantment_top",
+ "displayName": "Enchantment Table (Top)"
+ },
+ {
+ "internalName": "dragon_egg",
+ "displayName": "Dragon Egg"
+ },
+ {
+ "internalName": "cocoa_2",
+ "displayName": "Cocoa (Stage 3)"
+ },
+ {
+ "internalName": "cocoa_1",
+ "displayName": "Cocoa (Stage 2)"
+ },
+ {
+ "internalName": "cocoa_0",
+ "displayName": "Cocoa (Stage 1)"
+ },
+ {
+ "internalName": "emerald_ore",
+ "displayName": "Emerald Ore"
+ },
+ {
+ "internalName": "trip_wire_source",
+ "displayName": "Tripwire Hook"
+ },
+ {
+ "internalName": "trip_wire",
+ "displayName": "Tripwire"
+ },
+ {
+ "internalName": "endframe_eye",
+ "displayName": "End Portal Frame (Eye)"
+ },
+ {
+ "internalName": "end_stone",
+ "displayName": "End Stone"
+ },
+ {
+ "internalName": "sandstone_top",
+ "displayName": "Sandstone (Top)"
+ },
+ {
+ "internalName": "wool_colored_blue",
+ "displayName": "Blue Wool"
+ },
+ {
+ "internalName": "wool_colored_light_blue",
+ "displayName": "Light Blue Wool"
+ },
+ {
+ "internalName": "rail_golden_powered",
+ "displayName": "Powered Rail (On)"
+ },
+ {
+ "internalName": "redstone_dust_cross_overlay",
+ "displayName": "Redstone Dust (Cross) (Overlay)"
+ },
+ {
+ "internalName": "redstone_dust_line_overlay",
+ "displayName": "Redstone Dust (Line) (Overlay)"
+ },
+ {
+ "internalName": "enchantment_side",
+ "displayName": "Enchantment Table (Side)"
+ },
+ {
+ "internalName": "enchantment_bottom",
+ "displayName": "Enchantment Table (Bottom)"
+ },
+ {
+ "internalName": "diamondRing",
+ "displayName": "Diamond Score Ring"
+ },
+ {
+ "internalName": "itemframe_back",
+ "displayName": "Item Frame"
+ },
+ {
+ "internalName": "flower_pot",
+ "displayName": "Flower Pot"
+ },
+ {
+ "internalName": "comparator_off",
+ "displayName": "Redstone Comparator"
+ },
+ {
+ "internalName": "comparator_on",
+ "displayName": "Redstone Comparator (On)"
+ },
+ {
+ "internalName": "rail_activator",
+ "displayName": "Activator Rail"
+ },
+ {
+ "internalName": "rail_activator_powered",
+ "displayName": "Activator Rail (On)"
+ },
+ {
+ "internalName": "quartz_ore",
+ "displayName": "Nether Quartz Ore"
+ },
+ {
+ "internalName": "sandstone_side",
+ "displayName": "Sandstone (Side)"
+ },
+ {
+ "internalName": "wool_colored_purple",
+ "displayName": "Purple Wool"
+ },
+ {
+ "internalName": "wool_colored_magenta",
+ "displayName": "Magenta Wool"
+ },
+ {
+ "internalName": "detectorRail",
+ "displayName": "Detector Rail"
+ },
+ {
+ "internalName": "leaves_jungle",
+ "displayName": "Jungle Leaves",
+
+ "colourEntry": {
+ "defaultName": "Foliage_Default",
+ "variants": [
+ "Foliage_Default",
+ "Foliage_Evergreen",
+ "Foliage_Birch",
+ "Foliage_Mesa",
+ "Foliage_Swampland"
+ ]
+ }
+ },
+ {
+ "internalName": "leaves_jungle_opaque",
+ "displayName": "Jungle Leaves (Opaque)",
+
+ "colourEntry": {
+ "defaultName": "Foliage_Default",
+ "variants": [
+ "Foliage_Default",
+ "Foliage_Evergreen",
+ "Foliage_Birch",
+ "Foliage_Mesa",
+ "Foliage_Swampland"
+ ]
+ }
+ },
+ {
+ "internalName": "planks_spruce",
+ "displayName": "Spruce Planks"
+ },
+ {
+ "internalName": "planks_jungle",
+ "displayName": "Jungle Planks"
+ },
+ {
+ "internalName": "carrots_stage_0",
+ "displayName": "Carrots (Stage 1)"
+ },
+ {
+ "internalName": "carrots_stage_1",
+ "displayName": "Carrots (Stage 2)"
+ },
+ {
+ "internalName": "carrots_stage_2",
+ "displayName": "Carrots (Stage 3)"
+ },
+ {
+ "internalName": "carrots_stage_3",
+ "displayName": "Carrots (Stage 4)"
+ },
+ {
+ "internalName": "slime",
+ "displayName": "Slime Block"
+ },
+ {
+ "internalName": "water",
+ "displayName": "Water",
+
+ "colourEntry": {
+ "isWaterColour": true,
+ "defaultName": "Water_Plains",
+ "variants": [
+ "Water_Ocean",
+ "Water_Plains",
+ "Water_Desert",
+ "Water_ExtremeHills",
+ "Water_Forest",
+ "Water_Taiga",
+ "Water_Swampland",
+ "Water_River",
+ "Water_Hell",
+ "Water_Sky",
+ "Water_FrozenOcean",
+ "Water_FrozenRiver",
+ "Water_IcePlains",
+ "Water_IceMountains",
+ "Water_MushroomIsland",
+ "Water_MushroomIslandShore",
+ "Water_Beach",
+ "Water_DesertHills",
+ "Water_ForestHills",
+ "Water_TaigaHills",
+ "Water_ExtremeHillsEdge",
+ "Water_Jungle",
+ "Water_JungleHills",
+ "Water_JungleEdge",
+ "Water_DeepOcean",
+ "Water_StoneBeach",
+ "Water_ColdBeach",
+ "Water_BirchForest",
+ "Water_BirchForestHills",
+ "Water_RoofedForest",
+ "Water_ColdTaiga",
+ "Water_ColdTaigaHills",
+ "Water_MegaTaiga",
+ "Water_MegaTaigaHills",
+ "Water_ExtremeHillsPlus",
+ "Water_Savanna",
+ "Water_SavannaPlateau",
+ "Water_Mesa",
+ "Water_MesaPlateauF",
+ "Water_MesaPlateau"
+ ]
+ }
+ },
+ {
+ "internalName": "water_flow",
+ "displayName": "Flowing Water",
+
+ "width": 2,
+ "height": 2,
+ "colourEntry": {
+ "isWaterColour": true,
+ "defaultName": "Water_Plains",
+ "variants": [
+ "Water_Ocean",
+ "Water_Plains",
+ "Water_Desert",
+ "Water_ExtremeHills",
+ "Water_Forest",
+ "Water_Taiga",
+ "Water_Swampland",
+ "Water_River",
+ "Water_Hell",
+ "Water_Sky",
+ "Water_FrozenOcean",
+ "Water_FrozenRiver",
+ "Water_IcePlains",
+ "Water_IceMountains",
+ "Water_MushroomIsland",
+ "Water_MushroomIslandShore",
+ "Water_Beach",
+ "Water_DesertHills",
+ "Water_ForestHills",
+ "Water_TaigaHills",
+ "Water_ExtremeHillsEdge",
+ "Water_Jungle",
+ "Water_JungleHills",
+ "Water_JungleEdge",
+ "Water_DeepOcean",
+ "Water_StoneBeach",
+ "Water_ColdBeach",
+ "Water_BirchForest",
+ "Water_BirchForestHills",
+ "Water_RoofedForest",
+ "Water_ColdTaiga",
+ "Water_ColdTaigaHills",
+ "Water_MegaTaiga",
+ "Water_MegaTaigaHills",
+ "Water_ExtremeHillsPlus",
+ "Water_Savanna",
+ "Water_SavannaPlateau",
+ "Water_Mesa",
+ "Water_MesaPlateauF",
+ "Water_MesaPlateau"
+ ]
+ }
+ },
+ {
+ "internalName": "water_flow",
+ "displayName": ""
+ },
+ {
+ "internalName": "sandstone_bottom",
+ "displayName": "Sandstone (Bottom)"
+ },
+ {
+ "internalName": "wool_colored_cyan",
+ "displayName": "Cyan Wool"
+ },
+ {
+ "internalName": "wool_colored_orange",
+ "displayName": "Orange Wool"
+ },
+ {
+ "internalName": "redstoneLight",
+ "displayName": "Redstone Lamp"
+ },
+ {
+ "internalName": "redstoneLight_lit",
+ "displayName": "Redstone Lamp (On)"
+ },
+ {
+ "internalName": "stonebrick_carved",
+ "displayName": "Chiseled Stone Bricks"
+ },
+ {
+ "internalName": "planks_birch",
+ "displayName": "Birch Planks"
+ },
+ {
+ "internalName": "anvil_base",
+ "displayName": "Anvil (Base)"
+ },
+ {
+ "internalName": "anvil_top_damaged_1",
+ "displayName": "Anvil (Slightly Damaged) (Top)"
+ },
+ {
+ "internalName": "quartz_block_chiseled_top",
+ "displayName": "Chiseled Quartz Block (Top)"
+ },
+ {
+ "internalName": "quartz_block_lines_top",
+ "displayName": "Pillar Quartz Block (Top)"
+ },
+ {
+ "internalName": "quartz_block_top",
+ "displayName": "Block of Quartz (Top)"
+ },
+ {
+ "internalName": "hopper_outside",
+ "displayName": "Hopper (Side)"
+ },
+ {
+ "internalName": "detectorRail_on",
+ "displayName": "Detector Rail (On)"
+ },
+ {
+ "internalName": "water_flow",
+ "displayName": ""
+ },
+ {
+ "internalName": "water_flow",
+ "displayName": ""
+ },
+ {
+ "internalName": "nether_brick",
+ "displayName": "Nether Brick"
+ },
+ {
+ "internalName": "wool_colored_silver",
+ "displayName": "Light Gray Wool"
+ },
+ {
+ "internalName": "nether_wart_stage_0",
+ "displayName": "Nether Wart (Stage 1)"
+ },
+ {
+ "internalName": "nether_wart_stage_1",
+ "displayName": "Nether Wart (Stage 2)"
+ },
+ {
+ "internalName": "nether_wart_stage_2",
+ "displayName": "Nether Wart (Stage 3)"
+ },
+ {
+ "internalName": "sandstone_carved",
+ "displayName": "Chiseled Sandstone"
+ },
+ {
+ "internalName": "sandstone_smooth",
+ "displayName": "Smooth Sandstone"
+ },
+ {
+ "internalName": "anvil_top",
+ "displayName": "Anvil (Top)"
+ },
+ {
+ "internalName": "anvil_top_damaged_2",
+ "displayName": "Anvil (Very Damaged) (Top)"
+ },
+ {
+ "internalName": "quartz_block_chiseled",
+ "displayName": "Chiseled Quartz Block (Side)"
+ },
+ {
+ "internalName": "quartz_block_lines",
+ "displayName": "Pillar Quartz Block (Side)"
+ },
+ {
+ "internalName": "quartz_block_side",
+ "displayName": "Block of Quartz (Side)"
+ },
+ {
+ "internalName": "hopper_inside",
+ "displayName": "Hopper (Inside)"
+ },
+ {
+ "internalName": "lava",
+ "displayName": "Lava"
+ },
+ {
+ "internalName": "lava_flow",
+ "displayName": "Flowing Lava",
+ "width": 2,
+ "height": 2
+ },
+ {
+ "internalName": "lava_flow",
+ "displayName": "",
+ },
+ {
+ "internalName": "destroy_0",
+ "displayName": "Destroy (Stage 1)"
+ },
+ {
+ "internalName": "destroy_1",
+ "displayName": "Destroy (Stage 2)"
+ },
+ {
+ "internalName": "destroy_2",
+ "displayName": "Destroy (Stage 3)"
+ },
+ {
+ "internalName": "destroy_3",
+ "displayName": "Destroy (Stage 4)"
+ },
+ {
+ "internalName": "destroy_4",
+ "displayName": "Destroy (Stage 5)"
+ },
+ {
+ "internalName": "destroy_5",
+ "displayName": "Destroy (Stage 6)"
+ },
+ {
+ "internalName": "destroy_6",
+ "displayName": "Destroy (Stage 7)"
+ },
+ {
+ "internalName": "destroy_7",
+ "displayName": "Destroy (Stage 8)"
+ },
+ {
+ "internalName": "destroy_8",
+ "displayName": "Destroy (Stage 9)"
+ },
+ {
+ "internalName": "destroy_9",
+ "displayName": "Destroy (Stage 10)"
+ },
+ {
+ "internalName": "hay_block_side",
+ "displayName": "Hay Bale (Side)"
+ },
+ {
+ "internalName": "quartz_block_bottom",
+ "displayName": "Quartz Block (Bottom)"
+ },
+ {
+ "internalName": "hopper_top",
+ "displayName": "Hopper (Top)"
+ },
+ {
+ "internalName": "hay_block_top",
+ "displayName": "Hay Bale (Top)"
+ },
+ {
+ "internalName": "lava_flow",
+ "displayName": "",
+ },
+ {
+ "internalName": "lava_flow",
+ "displayName": "",
+ },
+ {
+ "internalName": "coal_block",
+ "displayName": "Block of Coal"
+ },
+ {
+ "internalName": "hardened_clay",
+ "displayName": "Terracotta"
+ },
+ {
+ "internalName": "noteblock",
+ "displayName": "Note Block"
+ },
+ {
+ "internalName": "stone_andesite",
+ "displayName": "Andesite"
+ },
+ {
+ "internalName": "stone_andesite_smooth",
+ "displayName": "Polished Andesite"
+ },
+ {
+ "internalName": "stone_diorite",
+ "displayName": "Diorite"
+ },
+ {
+ "internalName": "stone_diorite_smooth",
+ "displayName": "Polished Diorite"
+ },
+ {
+ "internalName": "stone_granite",
+ "displayName": "Granite"
+ },
+ {
+ "internalName": "stone_granite_smooth",
+ "displayName": "Polished Granite"
+ },
+ {
+ "internalName": "potatoes_stage_0",
+ "displayName": "Potatoes (Stage 1)"
+ },
+ {
+ "internalName": "potatoes_stage_1",
+ "displayName": "Potatoes (Stage 2)"
+ },
+ {
+ "internalName": "potatoes_stage_2",
+ "displayName": "Potatoes (Stage 3)"
+ },
+ {
+ "internalName": "potatoes_stage_3",
+ "displayName": "Potatoes (Stage 4)"
+ },
+ {
+ "internalName": "log_spruce_top",
+ "displayName": "Spruce Wood (Top)"
+ },
+ {
+ "internalName": "log_jungle_top",
+ "displayName": "Jungle Wood (Top)"
+ },
+ {
+ "internalName": "log_birch_top",
+ "displayName": "Birch Wood (Top)"
+ },
+ {
+ "internalName": "hardened_clay_stained_black",
+ "displayName": "Black Terracotta"
+ },
+ {
+ "internalName": "hardened_clay_stained_blue",
+ "displayName": "Blue Terracotta"
+ },
+ {
+ "internalName": "hardened_clay_stained_brown",
+ "displayName": "Brown Terracotta"
+ },
+ {
+ "internalName": "hardened_clay_stained_cyan",
+ "displayName": "Cyan Terracotta"
+ },
+ {
+ "internalName": "hardened_clay_stained_gray",
+ "displayName": "Gray Terracotta"
+ },
+ {
+ "internalName": "hardened_clay_stained_green",
+ "displayName": "Green Terracotta"
+ },
+ {
+ "internalName": "hardened_clay_stained_light_blue",
+ "displayName": "Light Blue Terracotta"
+ },
+ {
+ "internalName": "hardened_clay_stained_lime",
+ "displayName": "Lime Terracotta"
+ },
+ {
+ "internalName": "hardened_clay_stained_magenta",
+ "displayName": "Magenta Terracotta"
+ },
+ {
+ "internalName": "hardened_clay_stained_orange",
+ "displayName": "Orange Terracotta"
+ },
+ {
+ "internalName": "hardened_clay_stained_pink",
+ "displayName": "Pink Terracotta"
+ },
+ {
+ "internalName": "hardened_clay_stained_purple",
+ "displayName": "Purple Terracotta"
+ },
+ {
+ "internalName": "hardened_clay_stained_red",
+ "displayName": "Red Terracotta"
+ },
+ {
+ "internalName": "hardened_clay_stained_silver",
+ "displayName": "Light Gray Terracotta"
+ },
+ {
+ "internalName": "hardened_clay_stained_white",
+ "displayName": "White Terracotta"
+ },
+ {
+ "internalName": "hardened_clay_stained_yellow",
+ "displayName": "Yellow Terracotta"
+ },
+ {
+ "internalName": "glass_black",
+ "displayName": "Black Stained Glass"
+ },
+ {
+ "internalName": "glass_blue",
+ "displayName": "Blue Stained Glass"
+ },
+ {
+ "internalName": "glass_brown",
+ "displayName": "Brown Stained Glass"
+ },
+ {
+ "internalName": "glass_cyan",
+ "displayName": "Cyan Stained Glass"
+ },
+ {
+ "internalName": "glass_gray",
+ "displayName": "Gray Stained Glass"
+ },
+ {
+ "internalName": "glass_green",
+ "displayName": "Green Stained Glass"
+ },
+ {
+ "internalName": "glass_light_blue",
+ "displayName": "Light Blue Stained Glass"
+ },
+ {
+ "internalName": "glass_lime",
+ "displayName": "Lime Stained Glass"
+ },
+ {
+ "internalName": "glass_magenta",
+ "displayName": "Magenta Stained Glass"
+ },
+ {
+ "internalName": "glass_orange",
+ "displayName": "Orange Stained Glass"
+ },
+ {
+ "internalName": "glass_pink",
+ "displayName": "Pink Stained Glass"
+ },
+ {
+ "internalName": "glass_purple",
+ "displayName": "Purple Stained Glass"
+ },
+ {
+ "internalName": "glass_red",
+ "displayName": "Red Stained Glass"
+ },
+ {
+ "internalName": "glass_silver",
+ "displayName": "Light Gray Stained Glass"
+ },
+ {
+ "internalName": "glass_white",
+ "displayName": "White Stained Glass"
+ },
+ {
+ "internalName": "glass_yellow",
+ "displayName": "Yellow Stained Glass"
+ },
+ {
+ "internalName": "glass_pane_top_black",
+ "displayName": "Black Stained Glass Pane (Top)"
+ },
+ {
+ "internalName": "glass_pane_top_blue",
+ "displayName": "Blue Stained Glass Pane (Top)"
+ },
+ {
+ "internalName": "glass_pane_top_brown",
+ "displayName": "Brown Stained Glass Pane (Top)"
+ },
+ {
+ "internalName": "glass_pane_top_cyan",
+ "displayName": "Cyan Stained Glass Pane (Top)"
+ },
+ {
+ "internalName": "glass_pane_top_gray",
+ "displayName": "Gray Stained Glass Pane (Top)"
+ },
+ {
+ "internalName": "glass_pane_top_green",
+ "displayName": "Green Stained Glass Pane (Top)"
+ },
+ {
+ "internalName": "glass_pane_top_light_blue",
+ "displayName": "Light Blue Stained Glass Pane (Top)"
+ },
+ {
+ "internalName": "glass_pane_top_lime",
+ "displayName": "Lime Stained Glass Pane (Top)"
+ },
+ {
+ "internalName": "glass_pane_top_magenta",
+ "displayName": "Magenta Stained Glass Pane (Top)"
+ },
+ {
+ "internalName": "glass_pane_top_orange",
+ "displayName": "Orange Stained Glass Pane (Top)"
+ },
+ {
+ "internalName": "glass_pane_top_pink",
+ "displayName": "Pink Stained Glass Pane (Top)"
+ },
+ {
+ "internalName": "glass_pane_top_purple",
+ "displayName": "Purple Stained Glass Pane (Top)"
+ },
+ {
+ "internalName": "glass_pane_top_red",
+ "displayName": "Red Stained Glass Pane (Top)"
+ },
+ {
+ "internalName": "glass_pane_top_silver",
+ "displayName": "Light Gray Stained Glass Pane (Top)"
+ },
+ {
+ "internalName": "glass_pane_top_white",
+ "displayName": "White Stained Glass Pane (Top)"
+ },
+ {
+ "internalName": "glass_pane_top_yellow",
+ "displayName": "Yellow Stained Glass Pane (Top)"
+ },
+ {
+ "internalName": "double_plant_fern_top",
+ "displayName": "Large Fern (Top)",
+
+ "colourEntry": {
+ "defaultName": "Grass_Common",
+ "variants": [
+ "Grass_Common",
+ "Grass_Mesa",
+ "Grass_Swamp1",
+ "Grass_Swamp2"
+ ]
+ }
+ },
+ {
+ "internalName": "double_plant_grass_top",
+ "displayName": "Double Tall Grass (Top)",
+
+ "colourEntry": {
+ "defaultName": "Grass_Common",
+ "variants": [
+ "Grass_Common",
+ "Grass_Mesa",
+ "Grass_Swamp1",
+ "Grass_Swamp2"
+ ]
+ }
+ },
+ {
+ "internalName": "double_plant_paeonia_top",
+ "displayName": "Peony (Top)"
+ },
+ {
+ "internalName": "double_plant_rose_top",
+ "displayName": "Rose Bush (Top)"
+ },
+ {
+ "internalName": "double_plant_syringa_top",
+ "displayName": "Lilac (Top)"
+ },
+ {
+ "internalName": "flower_tulip_orange",
+ "displayName": "Orange Tulip"
+ },
+ {
+ "internalName": "double_plant_sunflower_top",
+ "displayName": "Sunflower (Top)"
+ },
+ {
+ "internalName": "double_plant_sunflower_front",
+ "displayName": "Sunflower (Front)"
+ },
+ {
+ "internalName": "log_acacia",
+ "displayName": "Acacia Wood (Side)"
+ },
+ {
+ "internalName": "log_acacia_top",
+ "displayName": "Acacia Wood (Top)"
+ },
+ {
+ "internalName": "planks_acacia",
+ "displayName": "Acacia Planks"
+ },
+ {
+ "internalName": "leaves_acacia",
+ "displayName": "Acacia Leaves",
+
+ "colourEntry": {
+ "defaultName": "Foliage_Default",
+ "variants": [
+ "Foliage_Default",
+ "Foliage_Evergreen",
+ "Foliage_Birch",
+ "Foliage_Mesa",
+ "Foliage_Swampland"
+ ]
+ }
+ },
+ {
+ "internalName": "leaves_acacia_fast",
+ "displayName": "Acacia Leaves (Opaque)",
+
+ "colourEntry": {
+ "defaultName": "Foliage_Default",
+ "variants": [
+ "Foliage_Default",
+ "Foliage_Evergreen",
+ "Foliage_Birch",
+ "Foliage_Mesa",
+ "Foliage_Swampland"
+ ]
+ }
+ },
+ {
+ "internalName": "prismarine_bricks",
+ "displayName": "Prismarine Bricks"
+ },
+ {
+ "internalName": "red_sand",
+ "displayName": "Red Sand"
+ },
+ {
+ "internalName": "red_sandstone_top",
+ "displayName": "Red Sandstone (Top)"
+ },
+ {
+ "internalName": "double_plant_fern_bottom",
+ "displayName": "Large Fern (Bottom)",
+
+ "colourEntry": {
+ "defaultName": "Grass_Common",
+ "variants": [
+ "Grass_Common",
+ "Grass_Mesa",
+ "Grass_Swamp1",
+ "Grass_Swamp2"
+ ]
+ }
+ },
+ {
+ "internalName": "double_plant_grass_bottom",
+ "displayName": "Double Tall Grass (Bottom)",
+
+ "colourEntry": {
+ "defaultName": "Grass_Common",
+ "variants": [
+ "Grass_Common",
+ "Grass_Mesa",
+ "Grass_Swamp1",
+ "Grass_Swamp2"
+ ]
+ }
+ },
+ {
+ "internalName": "double_plant_paeonia_bottom",
+ "displayName": "Peony (Bottom)"
+ },
+ {
+ "internalName": "double_plant_rose_bottom",
+ "displayName": "Rose Bush (Bottom)"
+ },
+ {
+ "internalName": "double_plant_syringa_bottom",
+ "displayName": "Lilac (Bottom)"
+ },
+ {
+ "internalName": "flower_tulip_pink",
+ "displayName": "Pink Tulip"
+ },
+ {
+ "internalName": "double_plant_sunflower_bottom",
+ "displayName": "Sunflower (Bottom)"
+ },
+ {
+ "internalName": "double_plant_sunflower_back",
+ "displayName": "Sunflower (Back)"
+ },
+ {
+ "internalName": "log_big_oak",
+ "displayName": "Dark Oak Wood (Side)"
+ },
+ {
+ "internalName": "log_big_oak_top",
+ "displayName": "Dark Oak Wood (Top)"
+ },
+ {
+ "internalName": "planks_big_oak",
+ "displayName": "Dark Oak Planks"
+ },
+ {
+ "internalName": "leaves_big_oak",
+ "displayName": "Dark Oak Leaves",
+
+ "colourEntry": {
+ "defaultName": "Foliage_Default",
+ "variants": [
+ "Foliage_Default",
+ "Foliage_Evergreen",
+ "Foliage_Birch",
+ "Foliage_Mesa",
+ "Foliage_Swampland"
+ ]
+ }
+ },
+ {
+ "internalName": "leaves_big_oak_fast",
+ "displayName": "Dark Oak Leaves (Opaque)",
+
+ "colourEntry": {
+ "defaultName": "Foliage_Default",
+ "variants": [
+ "Foliage_Default",
+ "Foliage_Evergreen",
+ "Foliage_Birch",
+ "Foliage_Mesa",
+ "Foliage_Swampland"
+ ]
+ }
+ },
+ {
+ "internalName": "prismarine_dark",
+ "displayName": "Dark Prismarine"
+ },
+ {
+ "internalName": "red_sandstone_bottom",
+ "displayName": "Red Sandstone (Bottom)"
+ },
+ {
+ "internalName": "red_sandstone_normal",
+ "displayName": "Red Sandstone (Side)"
+ },
+ {
+ "internalName": "flower_alium",
+ "displayName": "Allium"
+ },
+ {
+ "internalName": "flower_blue_orchid",
+ "displayName": "Blue Orchid"
+ },
+ {
+ "internalName": "flower_houstonia",
+ "displayName": "Azure Bluet"
+ },
+ {
+ "internalName": "flower_oxeye_daisy",
+ "displayName": "Oxeye Daisy"
+ },
+ {
+ "internalName": "flower_tulip_red",
+ "displayName": "Red Tulip"
+ },
+ {
+ "internalName": "flower_tulip_white",
+ "displayName": "White Tulip"
+ },
+ {
+ "internalName": "sapling_acacia",
+ "displayName": "Acacia Sapling"
+ },
+ {
+ "internalName": "sapling_roofed_oak",
+ "displayName": "Dark Oak Sapling"
+ },
+ {
+ "internalName": "coarse_dirt",
+ "displayName": "Coarse Dirt"
+ },
+ {
+ "internalName": "dirt_podzol_side",
+ "displayName": "Podzol (Side)"
+ },
+ {
+ "internalName": "dirt_podzol_top",
+ "displayName": "Podzol (Top)"
+ },
+ {
+ "internalName": "leaves_birch",
+ "displayName": "Birch Leaves",
+
+ "colourEntry": {
+ "defaultName": "Foliage_Birch",
+ "variants": [
+ "Foliage_Default",
+ "Foliage_Evergreen",
+ "Foliage_Birch",
+ "Foliage_Mesa",
+ "Foliage_Swampland"
+ ]
+ }
+ },
+ {
+ "internalName": "leaves_birch_fast",
+ "displayName": "Birch Leaves (Opaque)",
+
+ "colourEntry": {
+ "defaultName": "Foliage_Birch",
+ "variants": [
+ "Foliage_Default",
+ "Foliage_Evergreen",
+ "Foliage_Birch",
+ "Foliage_Mesa",
+ "Foliage_Swampland"
+ ]
+ }
+ },
+ {
+ "internalName": "prismarine_rough",
+ "displayName": "Prismarine"
+ },
+ {
+ "internalName": "red_sandstone_carved",
+ "displayName": "Chiseled Red Sandstone"
+ },
+ {
+ "internalName": "red_sandstone_smooth",
+ "displayName": "Smooth Red Standstone"
+ },
+ {
+ "internalName": "door_acacia_upper",
+ "displayName": "Acacia Door (Top)"
+ },
+ {
+ "internalName": "door_birch_upper",
+ "displayName": "Birch Door (Top)"
+ },
+ {
+ "internalName": "door_dark_oak_upper",
+ "displayName": "Dark Oak Door (Top)"
+ },
+ {
+ "internalName": "door_jungle_upper",
+ "displayName": "Jungle Door (Top)"
+ },
+ {
+ "internalName": "door_spruce_upper",
+ "displayName": "Spruce Door (Top)"
+ },
+ {
+ "internalName": "chorus_flower",
+ "displayName": "Chorus Flower"
+ },
+ {
+ "internalName": "chorus_flower_dead",
+ "displayName": "Chorus Flower (Dead)"
+ },
+ {
+ "internalName": "chorus_flower_plant",
+ "displayName": "Chorus Plant"
+ },
+ {
+ "internalName": "end_bricks",
+ "displayName": "End Stone Bricks"
+ },
+ {
+ "internalName": "grass_path_side",
+ "displayName": "Grass Path (Side)"
+ },
+ {
+ "internalName": "grass_path_top",
+ "displayName": "Grass Path (Top)"
+ },
+ {
+ "internalName": "barrier",
+ "displayName": "Barrier"
+ },
+ {
+ "internalName": "ice_packed",
+ "displayName": "Packed Ice"
+ },
+ {
+ "internalName": "sea_lantern",
+ "displayName": "Sea Lantern"
+ },
+ {
+ "internalName": "daylight_detector_inverted_top",
+ "displayName": "Daylight Sensor (Inverted) (Top)"
+ },
+ {
+ "internalName": "iron_trapdoor",
+ "displayName": "Iron Trapdoor"
+ },
+ {
+ "internalName": "door_acacia_lower",
+ "displayName": "Acacia Door (Bottom)"
+ },
+ {
+ "internalName": "door_birch_lower",
+ "displayName": "Birch Door (Bottom)"
+ },
+ {
+ "internalName": "door_dark_oak_lower",
+ "displayName": "Dark Oak Door (Bottom)"
+ },
+ {
+ "internalName": "door_jungle_lower",
+ "displayName": "Jungle Door (Bottom)"
+ },
+ {
+ "internalName": "door_spruce_lower",
+ "displayName": "Spruce Door (Bottom)"
+ },
+ {
+ "internalName": "purpur_block",
+ "displayName": "Purpur Block"
+ },
+ {
+ "internalName": "purpur_pillar",
+ "displayName": "Purpur Pillar (Side)"
+ },
+ {
+ "internalName": "purpur_pillar_top",
+ "displayName": "Purpur Pillar (Top)"
+ },
+ {
+ "internalName": "end_rod",
+ "displayName": "End Rod"
+ },
+ {
+ "internalName": "magma",
+ "displayName": "Magma Block"
+ },
+ {
+ "internalName": "nether_wart_block",
+ "displayName": "Nether Wart Block"
+ },
+ {
+ "internalName": "red_nether_brick",
+ "displayName": "Red Nether Brick"
+ },
+ {
+ "internalName": "frosted_ice_0",
+ "displayName": "Frosted Ice (Stage 1)"
+ },
+ {
+ "internalName": "frosted_ice_1",
+ "displayName": "Frosted Ice (Stage 2)"
+ },
+ {
+ "internalName": "frosted_ice_2",
+ "displayName": "Frosted Ice (Stage 3)"
+ },
+ {
+ "internalName": "frosted_ice_3",
+ "displayName": "Frosted Ice (Stage 4)"
+ },
+ {
+ "internalName": "beetroots_stage_0",
+ "displayName": "Beetroots (Stage 1)"
+ },
+ {
+ "internalName": "beetroots_stage_1",
+ "displayName": "Beetroots (Stage 2)"
+ },
+ {
+ "internalName": "beetroots_stage_2",
+ "displayName": "Beetroots (Stage 3)"
+ },
+ {
+ "internalName": "beetroots_stage_3",
+ "displayName": "Beetroots (Stage 4)"
+ },
+ {
+ "internalName": "chain_command_block_back",
+ "displayName": "Chain Command Block (Back)"
+ },
+ {
+ "internalName": "chain_command_block_conditional",
+ "displayName": "Chain Command Block (Conditional) (Side)"
+ },
+ {
+ "internalName": "chain_command_block_front",
+ "displayName": "Chain Command Block (Front)"
+ },
+ {
+ "internalName": "chain_command_block_side",
+ "displayName": "Chain Command Block (Side)"
+ },
+ {
+ "internalName": "command_block_back",
+ "displayName": "Command Block (Back)"
+ },
+ {
+ "internalName": "command_block_conditional",
+ "displayName": "Command Block (Conditional) (Side)"
+ },
+ {
+ "internalName": "command_block_front",
+ "displayName": "Command Block (Front)"
+ },
+ {
+ "internalName": "command_block_side",
+ "displayName": "Command Block (Side)"
+ },
+ {
+ "internalName": "repeating_command_block_back",
+ "displayName": "Repeating Command Block (Back)"
+ },
+ {
+ "internalName": "repeating_command_block_conditional",
+ "displayName": "Repeating Command Block (Conditional) (Side)"
+ },
+ {
+ "internalName": "repeating_command_block_front",
+ "displayName": "Repeating Command Block (Front)"
+ },
+ {
+ "internalName": "repeating_command_block_side",
+ "displayName": "Repeating Command Block (Side)"
+ },
+ {
+ "internalName": "bone_block_side",
+ "displayName": "Bone Block (Side)"
+ },
+ {
+ "internalName": "bone_block_top",
+ "displayName": "Bone Block (Top)"
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "observer_front",
+ "displayName": "Observer (Front)"
+ },
+ {
+ "internalName": "observer_side",
+ "displayName": "Observer (Side)"
+ },
+ {
+ "internalName": "observer_back",
+ "displayName": "Observer (Back)"
+ },
+ {
+ "internalName": "observer_back_lit",
+ "displayName": "Observer (On) (Back)"
+ },
+ {
+ "internalName": "observer_top",
+ "displayName": "Observer (Top and Bottom)"
+ },
+ {
+ "internalName": "goldRing",
+ "displayName": "Gold Score Ring"
+ },
+ {
+ "internalName": "emeraldRing",
+ "displayName": "Emerald Score Ring"
+ },
+ {
+ "internalName": "structure_block",
+ "displayName": "Structure Block"
+ },
+ {
+ "internalName": "structure_block_corner",
+ "displayName": "Structure Block (Corner)"
+ },
+ {
+ "internalName": "structure_block_data",
+ "displayName": "Structure Block (Data)"
+ },
+ {
+ "internalName": "structure_block_load",
+ "displayName": "Structure Block (Load)"
+ },
+ {
+ "internalName": "structure_block_save",
+ "displayName": "Structure Block (Save)"
+ },
+ {
+ "internalName": "concrete_black",
+ "displayName": "Black Concrete"
+ },
+ {
+ "internalName": "concrete_blue",
+ "displayName": "Blue Concrete"
+ },
+ {
+ "internalName": "concrete_brown",
+ "displayName": "Brown Concrete"
+ },
+ {
+ "internalName": "concrete_cyan",
+ "displayName": "Cyan Concrete"
+ },
+ {
+ "internalName": "concrete_gray",
+ "displayName": "Gray Concrete"
+ },
+ {
+ "internalName": "concrete_green",
+ "displayName": "Green Concrete"
+ },
+ {
+ "internalName": "concrete_light_blue",
+ "displayName": "Light Blue Concrete"
+ },
+ {
+ "internalName": "concrete_lime",
+ "displayName": "Lime Concrete"
+ },
+ {
+ "internalName": "concrete_magenta",
+ "displayName": "Magenta Concrete"
+ },
+ {
+ "internalName": "concrete_orange",
+ "displayName": "Orange Concrete"
+ },
+ {
+ "internalName": "concrete_pink",
+ "displayName": "Pink Concrete"
+ },
+ {
+ "internalName": "concrete_purple",
+ "displayName": "Purple Concrete"
+ },
+ {
+ "internalName": "concrete_red",
+ "displayName": "Red Concrete"
+ },
+ {
+ "internalName": "concrete_silver",
+ "displayName": "Light Gray Concrete"
+ },
+ {
+ "internalName": "concrete_white",
+ "displayName": "White Concrete"
+ },
+ {
+ "internalName": "concrete_yellow",
+ "displayName": "Yellow Concrete"
+ },
+ {
+ "internalName": "concrete_powder_black",
+ "displayName": "Black Concrete Powder"
+ },
+ {
+ "internalName": "concrete_powder_blue",
+ "displayName": "Blue Concrete Powder"
+ },
+ {
+ "internalName": "concrete_powder_brown",
+ "displayName": "Brown Concrete Powder"
+ },
+ {
+ "internalName": "concrete_powder_cyan",
+ "displayName": "Cyan Concrete Powder"
+ },
+ {
+ "internalName": "concrete_powder_gray",
+ "displayName": "Gray Concrete Powder"
+ },
+ {
+ "internalName": "concrete_powder_green",
+ "displayName": "Green Concrete Powder"
+ },
+ {
+ "internalName": "concrete_powder_light_blue",
+ "displayName": "Light Blue Concrete Powder"
+ },
+ {
+ "internalName": "concrete_powder_lime",
+ "displayName": "Lime Concrete Powder"
+ },
+ {
+ "internalName": "concrete_powder_magenta",
+ "displayName": "Magenta Concrete Powder"
+ },
+ {
+ "internalName": "concrete_powder_orange",
+ "displayName": "Orange Concrete Powder"
+ },
+ {
+ "internalName": "concrete_powder_pink",
+ "displayName": "Pink Concrete Powder"
+ },
+ {
+ "internalName": "concrete_powder_purple",
+ "displayName": "Purple Concrete Powder"
+ },
+ {
+ "internalName": "concrete_powder_red",
+ "displayName": "Red Concrete Powder"
+ },
+ {
+ "internalName": "concrete_powder_silver",
+ "displayName": "Light Gray Concrete Powder"
+ },
+ {
+ "internalName": "concrete_powder_white",
+ "displayName": "White Concrete Powder"
+ },
+ {
+ "internalName": "concrete_powder_yellow",
+ "displayName": "Yellow Concrete Powder"
+ },
+ {
+ "internalName": "glazed_terracotta_black",
+ "displayName": "Black Glazed Terracotta"
+ },
+ {
+ "internalName": "glazed_terracotta_blue",
+ "displayName": "Blue Glazed Terracotta"
+ },
+ {
+ "internalName": "glazed_terracotta_brown",
+ "displayName": "Brown Glazed Terracotta"
+ },
+ {
+ "internalName": "glazed_terracotta_cyan",
+ "displayName": "Cyan Glazed Terracotta"
+ },
+ {
+ "internalName": "glazed_terracotta_gray",
+ "displayName": "Gray Glazed Terracotta"
+ },
+ {
+ "internalName": "glazed_terracotta_green",
+ "displayName": "Green Glazed Terracotta"
+ },
+ {
+ "internalName": "glazed_terracotta_light_blue",
+ "displayName": "Light Blue Glazed Terracotta"
+ },
+ {
+ "internalName": "glazed_terracotta_lime",
+ "displayName": "Lime Glazed Terracotta"
+ },
+ {
+ "internalName": "glazed_terracotta_magenta",
+ "displayName": "Magenta Glazed Terracotta"
+ },
+ {
+ "internalName": "glazed_terracotta_orange",
+ "displayName": "Orange Glazed Terracotta"
+ },
+ {
+ "internalName": "glazed_terracotta_pink",
+ "displayName": "Pink Glazed Terracotta"
+ },
+ {
+ "internalName": "glazed_terracotta_purple",
+ "displayName": "Purple Glazed Terracotta"
+ },
+ {
+ "internalName": "glazed_terracotta_red",
+ "displayName": "Red Glazed Terracotta"
+ },
+ {
+ "internalName": "glazed_terracotta_silver",
+ "displayName": "Light Gray Glazed Terracotta"
+ },
+ {
+ "internalName": "glazed_terracotta_white",
+ "displayName": "White Glazed Terracotta"
+ },
+ {
+ "internalName": "glazed_terracotta_yellow",
+ "displayName": "Yellow Glazed Terracotta"
+ },
+ {
+ "internalName": "shulker_top",
+ "displayName": "Shulker Box (Break Particles)",
+
+ "colourEntry": {
+ "defaultName": "Shulker_Box_Purple",
+ "variants": [
+ "Shulker_Box_Black",
+ "Shulker_Box_Blue",
+ "Shulker_Box_Brown",
+ "Shulker_Box_Cyan",
+ "Shulker_Box_Grey",
+ "Shulker_Box_Green",
+ "Shulker_Box_Light_Blue",
+ "Shulker_Box_Light_Green",
+ "Shulker_Box_Magenta",
+ "Shulker_Box_Orange",
+ "Shulker_Box_Pink",
+ "Shulker_Box_Purple",
+ "Shulker_Box_Red",
+ "Shulker_Box_Silver",
+ "Shulker_Box_White",
+ "Shulker_Box_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "shulker_top_overlay",
+ "displayName": "Shulker Box (Break Particles) (Overlay) (Unused)"
+ },
+ {
+ "internalName": "cauldron_water",
+ "displayName": "Cauldron Water",
+ "allowCustomColour": true,
+
+ "colourEntry": {
+ "defaultName": "Cauldron_Water",
+ "variants": [
+ "Cauldron_Water",
+ "Effect_MovementSpeed",
+ "Effect_MovementSlowDown",
+ "Effect_DigSpeed",
+ "Effect_DigSlowdown",
+ "Effect_DamageBoost",
+ "Effect_Heal",
+ "Effect_Harm",
+ "Effect_Jump",
+ "Effect_Confusion",
+ "Effect_Regeneration",
+ "Effect_DamageResistance",
+ "Effect_FireResistance",
+ "Effect_WaterBreathing",
+ "Effect_Invisibility",
+ "Effect_Blindness",
+ "Effect_NightVision",
+ "Effect_Hunger",
+ "Effect_Weakness",
+ "Effect_Poison",
+ "Effect_Wither",
+ "Effect_HealthBoost",
+ "Effect_Absorption",
+ "Effect_Saturation",
+ "Effect_Levitation",
+ "Effect_Luck",
+ "Effect_BadLuck",
+ "Effect_TurtleMaster",
+ "Effect_SlowFall"
+ ]
+ }
+ },
+ {
+ "internalName": "seagrass_doubletall_top",
+ "displayName": "Double Tall Seagrass (Top)"
+ },
+ {
+ "internalName": "coral_blue",
+ "displayName": "Tube Coral Block"
+ },
+ {
+ "internalName": "coral_purple",
+ "displayName": "Bubble Coral Block"
+ },
+ {
+ "internalName": "coral_pink",
+ "displayName": "Brain Coral Block"
+ },
+ {
+ "internalName": "coral_red",
+ "displayName": "Fire Coral Block"
+ },
+ {
+ "internalName": "coral_yellow",
+ "displayName": "Horn Coral Block"
+ },
+ {
+ "internalName": "coral_plant_blue",
+ "displayName": "Tube Coral"
+ },
+ {
+ "internalName": "coral_plant_purple",
+ "displayName": "Bubble Coral"
+ },
+ {
+ "internalName": "coral_plant_pink",
+ "displayName": "Brain Coral"
+ },
+ {
+ "internalName": "coral_plant_red",
+ "displayName": "Fire Coral"
+ },
+ {
+ "internalName": "coral_plant_yellow",
+ "displayName": "Horn Coral"
+ },
+ {
+ "internalName": "sea_pickle",
+ "displayName": "Sea Pickle"
+ },
+ {
+ "internalName": "blue_ice",
+ "displayName": "Blue Ice"
+ },
+ {
+ "internalName": "dried_kelp_top",
+ "displayName": "Dried Kelp Block (Top)"
+ },
+ {
+ "internalName": "dried_kelp_side",
+ "displayName": "Dried Kelp Block (Side)"
+ },
+ {
+ "internalName": "seagrass_carried",
+ "displayName": "Seagrass (Item)"
+ },
+ {
+ "internalName": "seagrass_doubletall_bottom",
+ "displayName": "Double Tall Seagrass (Bottom)"
+ },
+ {
+ "internalName": "coral_blue_dead",
+ "displayName": "Dead Tube Coral Block"
+ },
+ {
+ "internalName": "coral_purple_dead",
+ "displayName": "Dead Bubble Coral Block"
+ },
+ {
+ "internalName": "coral_pink_dead",
+ "displayName": "Dead Brain Coral Block"
+ },
+ {
+ "internalName": "coral_red_dead",
+ "displayName": "Dead Fire Coral Block"
+ },
+ {
+ "internalName": "coral_yellow_dead",
+ "displayName": "Dead Horn Coral Block"
+ },
+ {
+ "internalName": "coral_fan_blue",
+ "displayName": "Tube Coral Fan"
+ },
+ {
+ "internalName": "coral_fan_purple",
+ "displayName": "Bubble Coral Fan"
+ },
+ {
+ "internalName": "coral_fan_pink",
+ "displayName": "Brain Coral Fan"
+ },
+ {
+ "internalName": "coral_fan_red",
+ "displayName": "Fire Coral Fan"
+ },
+ {
+ "internalName": "coral_fan_yellow",
+ "displayName": "Horn Coral Fan"
+ },
+ {
+ "internalName": "bamboo_stem",
+ "displayName": "Bamboo (Stem) [PS4 ONLY]"
+ },
+ {
+ "internalName": "bamboo_leaf_small",
+ "displayName": "Bamboo (Small Leaves) [PS4 ONLY]"
+ },
+ {
+ "internalName": "kelp_a",
+ "displayName": "Kelp (Bottom)"
+ },
+ {
+ "internalName": "kelp_a",
+ "displayName": ""
+ },
+ {
+ "internalName": "kelp_a",
+ "displayName": ""
+ },
+ {
+ "internalName": "kelp_a",
+ "displayName": ""
+ },
+ {
+ "internalName": "kelp_top_a",
+ "displayName": "Kelp (Top)"
+ },
+ {
+ "internalName": "kelp_top_a",
+ "displayName": ""
+ },
+ {
+ "internalName": "kelp_top_a",
+ "displayName": ""
+ },
+ {
+ "internalName": "kelp_top_a",
+ "displayName": ""
+ },
+ {
+ "internalName": "seagrass",
+ "displayName": "Seagrass"
+ },
+ {
+ "internalName": "coral_fan_blue_dead",
+ "displayName": "Dead Tube Coral Fan"
+ },
+ {
+ "internalName": "coral_fan_purple_dead",
+ "displayName": "Dead Bubble Coral Fan"
+ },
+ {
+ "internalName": "coral_fan_pink_dead",
+ "displayName": "Dead Brain Coral Fan"
+ },
+ {
+ "internalName": "coral_fan_red_dead",
+ "displayName": "Dead Fire Coral Fan"
+ },
+ {
+ "internalName": "coral_fan_yellow_dead",
+ "displayName": "Dead Horn Coral Fan"
+ },
+ {
+ "internalName": "bamboo_leaf",
+ "displayName": "Bamboo (Leaves) [PS4 ONLY]"
+ },
+ {
+ "internalName": "spruce_trapdoor",
+ "displayName": "Spruce Trapdoor"
+ },
+ {
+ "internalName": "stripped_log_oak",
+ "displayName": "Stripped Oak Log (Side)"
+ },
+ {
+ "internalName": "stripped_log_oak_top",
+ "displayName": "Stripped Oak Log (Top)"
+ },
+ {
+ "internalName": "stripped_log_acacia",
+ "displayName": "Stripped Acacia Log (Side)"
+ },
+ {
+ "internalName": "stripped_log_acacia_top",
+ "displayName": "Stripped Acacia Log (Top)"
+ },
+ {
+ "internalName": "stripped_log_birch",
+ "displayName": "Stripped Birch Log (Side)"
+ },
+ {
+ "internalName": "stripped_log_birch_top",
+ "displayName": "Stripped Birch Log (Top)"
+ },
+ {
+ "internalName": "stripped_log_dark_oak",
+ "displayName": "Stripped Dark Oak Log (Side)"
+ },
+ {
+ "internalName": "stripped_log_dark_oak_top",
+ "displayName": "Stripped Dark Oak Log (Top)"
+ },
+ {
+ "internalName": "stripped_log_jungle",
+ "displayName": "Stripped Jungle Log (Side)"
+ },
+ {
+ "internalName": "stripped_log_jungle_top",
+ "displayName": "Stripped Birch Log (Top)"
+ },
+ {
+ "internalName": "stripped_log_spruce",
+ "displayName": "Stripped Spruce Log (Side)"
+ },
+ {
+ "internalName": "stripped_log_spruce_top",
+ "displayName": "Stripped Spruce Log (Top)"
+ },
+ {
+ "internalName": "acacia_trapdoor",
+ "displayName": "Acacia Trapdoor"
+ },
+ {
+ "internalName": "birch_trapdoor",
+ "displayName": "Birch Trapdoor"
+ },
+ {
+ "internalName": "dark_oak_trapdoor",
+ "displayName": "Dark Oak Trapdoor"
+ },
+ {
+ "internalName": "jungle_trapdoor",
+ "displayName": "Jungle Trapdoor"
+ },
+ {
+ "internalName": "bamboo_sapling",
+ "displayName": "Bamboo Sapling [PS4 ONLY]"
+ },
+ {
+ "internalName": "bamboo_singleleaf",
+ "displayName": "Bamboo (Single Leaf) [PS4 ONLY]"
+ },
+ {
+ "internalName": "flower_lily_of_the_valley",
+ "displayName": "Lily of the Valley [PS4 ONLY]"
+ },
+ {
+ "internalName": "flower_cornflower",
+ "displayName": "Cornflower [PS4 ONLY]"
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "berry_bush_sapling",
+ "displayName": "Sweet Berry Bush (Stage 1) [PS4 ONLY]"
+ },
+ {
+ "internalName": "berry_bush_no_berries",
+ "displayName": "Sweet Berry Bush (Stage 2) [PS4 ONLY]"
+ },
+ {
+ "internalName": "berry_bush_some_berries",
+ "displayName": "Sweet Berry Bush (Stage 3) [PS4 ONLY]"
+ },
+ {
+ "internalName": "berry_bush_full_berries",
+ "displayName": "Sweet Berry Bush (Stage 4) [PS4 ONLY]"
+ },
+ {
+ "internalName": "campfire_log",
+ "displayName": "Campfire (Log) [PS4 ONLY]"
+ },
+ {
+ "internalName": "campfire_log_lit",
+ "displayName": "Campfire (Log) (Lit) [PS4 ONLY]"
+ },
+ {
+ "internalName": "campfire_smoke",
+ "displayName": "Campfire (Smoke) [PS4 ONLY]"
+ },
+ {
+ "internalName": "campfire",
+ "displayName": "Campfire (Flame) [PS4 ONLY]"
+ },
+ {
+ "internalName": "scaffolding_side",
+ "displayName": "Scaffolding (Side) [PS4 ONLY]"
+ },
+ {
+ "internalName": "scaffolding_bottom",
+ "displayName": "Scaffolding (Bottom) [PS4 ONLY]"
+ },
+ {
+ "internalName": "scaffolding_top",
+ "displayName": "Scaffolding (Top) [PS4 ONLY]"
+ },
+ {
+ "internalName": "barrel_side",
+ "displayName": "Barrel (Side) [PS4 ONLY]"
+ },
+ {
+ "internalName": "barrel_top",
+ "displayName": "Barrel (Top) [PS4 ONLY]"
+ },
+ {
+ "internalName": "barrel_bottom",
+ "displayName": "Barrel (Bottom) [PS4 ONLY]"
+ },
+ {
+ "internalName": "bell_side",
+ "displayName": "Bell (Side) [PS4 ONLY]"
+ },
+ {
+ "internalName": "bell_top",
+ "displayName": "Bell (Top) [PS4 ONLY]"
+ },
+ {
+ "internalName": "bell_bottom",
+ "displayName": "Bell (Bottom) [PS4 ONLY]"
+ },
+ {
+ "internalName": "lantern",
+ "displayName": "Lantern [PS4 ONLY]"
+ },
+ {
+ "internalName": "jigsaw_side",
+ "displayName": "Jigsaw (Side) [PS4 ONLY]"
+ },
+ {
+ "internalName": "jigsaw_top",
+ "displayName": "Jigsaw (Top) [PS4 ONLY]"
+ },
+ {
+ "internalName": "blast_furnace_front",
+ "displayName": "Blast Furnace (Front) [PS4 ONLY]"
+ },
+ {
+ "internalName": "blast_furnace_front_on",
+ "displayName": "Blast Furnace (Front) (Lit) [PS4 ONLY]"
+ },
+ {
+ "internalName": "blast_furnace_side",
+ "displayName": "Blast Furnace (Side) [PS4 ONLY]"
+ },
+ {
+ "internalName": "blast_furnace_top",
+ "displayName": "Blast Furnace (Top) [PS4 ONLY]"
+ },
+ {
+ "internalName": "grindstone_side",
+ "displayName": "Grindstone (Side) [PS4 ONLY]"
+ },
+ {
+ "internalName": "grindstone_round",
+ "displayName": "Grindstone (Round) [PS4 ONLY]"
+ },
+ {
+ "internalName": "grindstone_pivot",
+ "displayName": "Grindstone (Pivot) [PS4 ONLY]"
+ },
+ {
+ "internalName": "cartography_table_side1",
+ "displayName": "Cartography Table (Back) [PS4 ONLY]"
+ },
+ {
+ "internalName": "cartography_table_side2",
+ "displayName": "Cartography Table (Right Side) [PS4 ONLY]"
+ },
+ {
+ "internalName": "cartography_table_side3",
+ "displayName": "Cartography Table (Front and Left Side) [PS4 ONLY]"
+ },
+ {
+ "internalName": "cartography_table_top",
+ "displayName": "Cartography Table (Top) [PS4 ONLY]"
+ },
+ {
+ "internalName": "lectern_sides",
+ "displayName": "Lectern (Side) [PS4 ONLY]"
+ },
+ {
+ "internalName": "lectern_front",
+ "displayName": "Lectern (Front) [PS4 ONLY]"
+ },
+ {
+ "internalName": "lectern_base",
+ "displayName": "Lectern (Base) [PS4 ONLY]"
+ },
+ {
+ "internalName": "lectern_top",
+ "displayName": "Lectern (Top) [PS4 ONLY]"
+ },
+ {
+ "internalName": "loom_side",
+ "displayName": "Loom (Side) [PS4 ONLY]"
+ },
+ {
+ "internalName": "loom_front",
+ "displayName": "Loom (Front) [PS4 ONLY]"
+ },
+ {
+ "internalName": "loom_top",
+ "displayName": "Loom (Top) [PS4 ONLY]"
+ },
+ {
+ "internalName": "loom_bottom",
+ "displayName": "Loom (Bottom) [PS4 ONLY]"
+ },
+ {
+ "internalName": "smithing_table_side",
+ "displayName": "Smithing Table (Side) [PS4 ONLY]"
+ },
+ {
+ "internalName": "smithing_table_front",
+ "displayName": "Smithing Table (Front) [PS4 ONLY]"
+ },
+ {
+ "internalName": "smithing_table_top",
+ "displayName": "Smithing Table (Top) [PS4 ONLY]"
+ },
+ {
+ "internalName": "composter_top",
+ "displayName": "Composter (Top) [PS4 ONLY]"
+ },
+ {
+ "internalName": "fletcher_table_side2",
+ "displayName": "Fletching Table (Front and Back) [PS4 ONLY]"
+ },
+ {
+ "internalName": "fletcher_table_side1",
+ "displayName": "Fletching Table (Side) [PS4 ONLY]"
+ },
+ {
+ "internalName": "fletcher_table_top",
+ "displayName": "Fletching Table (Top) [PS4 ONLY]"
+ },
+ {
+ "internalName": "stonecutter2_saw",
+ "displayName": "Stonecutter (Saw) [PS4 ONLY]"
+ },
+ {
+ "internalName": "stonecutter2_side",
+ "displayName": "Stonecutter (Side) [PS4 ONLY]"
+ },
+ {
+ "internalName": "stonecutter2_top",
+ "displayName": "Stonecutter (Top) [PS4 ONLY]"
+ },
+ {
+ "internalName": "stonecutter2_bottom",
+ "displayName": "Stonecutter (Bottom) [PS4 ONLY]"
+ },
+ {
+ "internalName": "smoker_side",
+ "displayName": "Smoker (Side) [PS4 ONLY]"
+ },
+ {
+ "internalName": "smoker_front",
+ "displayName": "Smoker (Front) [PS4 ONLY]"
+ },
+ {
+ "internalName": "smoker_front_on",
+ "displayName": "Smoker (Front) (Lit) [PS4 ONLY]"
+ },
+ {
+ "internalName": "smoker_top",
+ "displayName": "Smoker (Top) [PS4 ONLY]"
+ },
+ {
+ "internalName": "smoker_bottom",
+ "displayName": "Smoker (Bottom) [PS4 ONLY]"
+ },
+ {
+ "internalName": "compost",
+ "displayName": "Compost [PS4 ONLY]"
+ },
+ {
+ "internalName": "compost_ready",
+ "displayName": "Compost (Ready) [PS4 ONLY]"
+ },
+ {
+ "internalName": "composter_bottom",
+ "displayName": "Composter (Bottom) [PS4 ONLY]"
+ },
+ {
+ "internalName": "composter_side",
+ "displayName": "Composter (Side) [PS4 ONLY]"
+ },
+ {
+ "internalName": "barrel_top_open",
+ "displayName": "Barrel (Top) (Open) [PS4 ONLY]"
+ },
+ {
+ "internalName": "smithing_table_bottom",
+ "displayName": "Smithing Table (Bottom) [PS4 ONLY]"
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ }
+ ]
+}
diff --git a/PckStudio.Core/Resources/experienceOrbData.json b/PckStudio.Core/Resources/experienceOrbData.json
new file mode 100644
index 00000000..f83a7ab3
--- /dev/null
+++ b/PckStudio.Core/Resources/experienceOrbData.json
@@ -0,0 +1,124 @@
+{
+ "COMMENT_1": "JSON by MattNL",
+ "entries": [
+ {
+ "internalName": "experience_orb_0",
+ "displayName": "Experience Orb (Size 1)",
+ "hasColourEntry": true,
+ "colourEntry": {
+ "defaultName": "experience_orb",
+ "variants": ["experience_orb"]
+ }
+ },
+ {
+ "internalName": "experience_orb_1",
+ "displayName": "Experience Orb (Size 2)",
+ "hasColourEntry": true,
+ "colourEntry": {
+ "defaultName": "experience_orb",
+ "variants": ["experience_orb"]
+ }
+ },
+ {
+ "internalName": "experience_orb_2",
+ "displayName": "Experience Orb (Size 3)",
+ "hasColourEntry": true,
+ "colourEntry": {
+ "defaultName": "experience_orb",
+ "variants": ["experience_orb"]
+ }
+ },
+ {
+ "internalName": "experience_orb_3",
+ "displayName": "Experience Orb (Size 4)",
+ "hasColourEntry": true,
+ "colourEntry": {
+ "defaultName": "experience_orb",
+ "variants": ["experience_orb"]
+ }
+ },
+ {
+ "internalName": "experience_orb_4",
+ "displayName": "Experience Orb (Size 5)",
+ "hasColourEntry": true,
+ "colourEntry": {
+ "defaultName": "experience_orb",
+ "variants": ["experience_orb"]
+ }
+ },
+ {
+ "internalName": "experience_orb_5",
+ "displayName": "Experience Orb (Size 6)",
+ "hasColourEntry": true,
+ "colourEntry": {
+ "defaultName": "experience_orb",
+ "variants": ["experience_orb"]
+ }
+ },
+ {
+ "internalName": "experience_orb_6",
+ "displayName": "Experience Orb (Size 7)",
+ "hasColourEntry": true,
+ "colourEntry": {
+ "defaultName": "experience_orb",
+ "variants": ["experience_orb"]
+ }
+ },
+ {
+ "internalName": "experience_orb_7",
+ "displayName": "Experience Orb (Size 8)",
+ "hasColourEntry": true,
+ "colourEntry": {
+ "defaultName": "experience_orb",
+ "variants": ["experience_orb"]
+ }
+ },
+ {
+ "internalName": "experience_orb_8",
+ "displayName": "Experience Orb (Size 9)",
+ "hasColourEntry": true,
+ "colourEntry": {
+ "defaultName": "experience_orb",
+ "variants": ["experience_orb"]
+ }
+ },
+ {
+ "internalName": "experience_orb_9",
+ "displayName": "Experience Orb (Size 10)",
+ "hasColourEntry": true,
+ "colourEntry": {
+ "defaultName": "experience_orb",
+ "variants": ["experience_orb"]
+ }
+ },
+ {
+ "internalName": "experience_orb_10",
+ "displayName": "Experience Orb (Size 11)",
+ "hasColourEntry": true,
+ "colourEntry": {
+ "defaultName": "experience_orb",
+ "variants": ["experience_orb"]
+ }
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ }
+ ]
+}
\ No newline at end of file
diff --git a/PckStudio.Core/Resources/experience_orbs.png b/PckStudio.Core/Resources/experience_orbs.png
new file mode 100644
index 00000000..1a2d58a3
Binary files /dev/null and b/PckStudio.Core/Resources/experience_orbs.png differ
diff --git a/PckStudio.Core/Resources/explosion.png b/PckStudio.Core/Resources/explosion.png
new file mode 100644
index 00000000..242d9115
Binary files /dev/null and b/PckStudio.Core/Resources/explosion.png differ
diff --git a/PckStudio.Core/Resources/explosionData.json b/PckStudio.Core/Resources/explosionData.json
new file mode 100644
index 00000000..f9845f7e
--- /dev/null
+++ b/PckStudio.Core/Resources/explosionData.json
@@ -0,0 +1,197 @@
+{
+ "COMMENT_1": "JSON by MattNL",
+ "entries": [
+ {
+ "internalName": "explosion_0",
+ "displayName": "Explosion (Stage 1)",
+ "hasColourEntry": true,
+ "colourEntry": {
+ "defaultName": "Particle_Explode",
+ "variants": [
+ "Particle_Explode",
+ "Particle_HugeExplosion"
+ ]
+ }
+ },
+ {
+ "internalName": "explosion_1",
+ "displayName": "Explosion (Stage 2)",
+ "hasColourEntry": true,
+ "colourEntry": {
+ "defaultName": "Particle_Explode",
+ "variants": [
+ "Particle_Explode",
+ "Particle_HugeExplosion"
+ ]
+ }
+ },
+ {
+ "internalName": "explosion_2",
+ "displayName": "Explosion (Stage 3)",
+ "hasColourEntry": true,
+ "colourEntry": {
+ "defaultName": "Particle_Explode",
+ "variants": [
+ "Particle_Explode",
+ "Particle_HugeExplosion"
+ ]
+ }
+ },
+ {
+ "internalName": "explosion_3",
+ "displayName": "Explosion (Stage 4)",
+ "hasColourEntry": true,
+ "colourEntry": {
+ "defaultName": "Particle_Explode",
+ "variants": [
+ "Particle_Explode",
+ "Particle_HugeExplosion"
+ ]
+ }
+ },
+ {
+ "internalName": "explosion_4",
+ "displayName": "Explosion (Stage 5)",
+ "hasColourEntry": true,
+ "colourEntry": {
+ "defaultName": "Particle_Explode",
+ "variants": [
+ "Particle_Explode",
+ "Particle_HugeExplosion"
+ ]
+ }
+ },
+ {
+ "internalName": "explosion_5",
+ "displayName": "Explosion (Stage 6)",
+ "hasColourEntry": true,
+ "colourEntry": {
+ "defaultName": "Particle_Explode",
+ "variants": [
+ "Particle_Explode",
+ "Particle_HugeExplosion"
+ ]
+ }
+ },
+ {
+ "internalName": "explosion_6",
+ "displayName": "Explosion (Stage 7)",
+ "hasColourEntry": true,
+ "colourEntry": {
+ "defaultName": "Particle_Explode",
+ "variants": [
+ "Particle_Explode",
+ "Particle_HugeExplosion"
+ ]
+ }
+ },
+ {
+ "internalName": "explosion_7",
+ "displayName": "Explosion (Stage 8)",
+ "hasColourEntry": true,
+ "colourEntry": {
+ "defaultName": "Particle_Explode",
+ "variants": [
+ "Particle_Explode",
+ "Particle_HugeExplosion"
+ ]
+ }
+ },
+ {
+ "internalName": "explosion_8",
+ "displayName": "Explosion (Stage 9)",
+ "hasColourEntry": true,
+ "colourEntry": {
+ "defaultName": "Particle_Explode",
+ "variants": [
+ "Particle_Explode",
+ "Particle_HugeExplosion"
+ ]
+ }
+ },
+ {
+ "internalName": "explosion_9",
+ "displayName": "Explosion (Stage 10)",
+ "hasColourEntry": true,
+ "colourEntry": {
+ "defaultName": "Particle_Explode",
+ "variants": [
+ "Particle_Explode",
+ "Particle_HugeExplosion"
+ ]
+ }
+ },
+ {
+ "internalName": "explosion_10",
+ "displayName": "Explosion (Stage 11)",
+ "hasColourEntry": true,
+ "colourEntry": {
+ "defaultName": "Particle_Explode",
+ "variants": [
+ "Particle_Explode",
+ "Particle_HugeExplosion"
+ ]
+ }
+ },
+ {
+ "internalName": "explosion_11",
+ "displayName": "Explosion (Stage 12)",
+ "hasColourEntry": true,
+ "colourEntry": {
+ "defaultName": "Particle_Explode",
+ "variants": [
+ "Particle_Explode",
+ "Particle_HugeExplosion"
+ ]
+ }
+ },
+ {
+ "internalName": "explosion_12",
+ "displayName": "Explosion (Stage 13)",
+ "hasColourEntry": true,
+ "colourEntry": {
+ "defaultName": "Particle_Explode",
+ "variants": [
+ "Particle_Explode",
+ "Particle_HugeExplosion"
+ ]
+ }
+ },
+ {
+ "internalName": "explosion_13",
+ "displayName": "Explosion (Stage 14)",
+ "hasColourEntry": true,
+ "colourEntry": {
+ "defaultName": "Particle_Explode",
+ "variants": [
+ "Particle_Explode",
+ "Particle_HugeExplosion"
+ ]
+ }
+ },
+ {
+ "internalName": "explosion_14",
+ "displayName": "Explosion (Stage 15)",
+ "hasColourEntry": true,
+ "colourEntry": {
+ "defaultName": "Particle_Explode",
+ "variants": [
+ "Particle_Explode",
+ "Particle_HugeExplosion"
+ ]
+ }
+ },
+ {
+ "internalName": "explosion_15",
+ "displayName": "Explosion (Stage 16)",
+ "hasColourEntry": true,
+ "colourEntry": {
+ "defaultName": "Particle_Explode",
+ "variants": [
+ "Particle_Explode",
+ "Particle_HugeExplosion"
+ ]
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/PckStudio.Core/Resources/itemData.json b/PckStudio.Core/Resources/itemData.json
new file mode 100644
index 00000000..51c380b7
--- /dev/null
+++ b/PckStudio.Core/Resources/itemData.json
@@ -0,0 +1,1361 @@
+{
+ "COMMENT_1": "Tile data research by MattNL",
+ "COMMENT_2": "JSON by PhoenixARC, MattNL, and NessieHax (Miku-666)",
+ "entries": [
+ {
+ "internalName": "helmetCloth",
+ "displayName": "Leather Cap",
+ "allowCustomColour": true,
+ "hasColourEntry": true,
+ "colourEntry": {
+ "defaultName": "Armour_Default_Leather_Colour",
+ "variants": [ "Armour_Default_Leather_Colour" ]
+ }
+ },
+ {
+ "internalName": "helmetChain",
+ "displayName": "Chain Helmet"
+ },
+ {
+ "internalName": "helmetIron",
+ "displayName": "Iron Helmet"
+ },
+ {
+ "internalName": "helmetDiamond",
+ "displayName": "Diamond Helmet"
+ },
+ {
+ "internalName": "helmetGold",
+ "displayName": "Golden Helmet"
+ },
+ {
+ "internalName": "flintAndSteel",
+ "displayName": "Flint and Steel"
+ },
+ {
+ "internalName": "flint",
+ "displayName": "Flint"
+ },
+ {
+ "internalName": "coal",
+ "displayName": "Coal"
+ },
+ {
+ "internalName": "string",
+ "displayName": "String"
+ },
+ {
+ "internalName": "seeds",
+ "displayName": "Seeds"
+ },
+ {
+ "internalName": "apple",
+ "displayName": "Apple"
+ },
+ {
+ "internalName": "appleGold",
+ "displayName": "Golden Apple"
+ },
+ {
+ "internalName": "egg",
+ "displayName": "Egg"
+ },
+ {
+ "internalName": "sugar",
+ "displayName": "Sugar"
+ },
+ {
+ "internalName": "snowball",
+ "displayName": "Snowball"
+ },
+ {
+ "internalName": "elytra",
+ "displayName": "Elytra"
+ },
+ {
+ "internalName": "chestplateCloth",
+ "displayName": "Leather Tunic",
+ "allowCustomColour": true,
+ "hasColourEntry": true,
+ "colourEntry": {
+ "defaultName": "Armour_Default_Leather_Colour",
+ "variants": [ "Armour_Default_Leather_Colour" ]
+ }
+ },
+ {
+ "internalName": "chestplateChain",
+ "displayName": "Chain Chestplate"
+ },
+ {
+ "internalName": "chestplateIron",
+ "displayName": "Iron Chestplate"
+ },
+ {
+ "internalName": "chestplateDiamond",
+ "displayName": "Diamond Chestplate"
+ },
+ {
+ "internalName": "chestplateGold",
+ "displayName": "Golden Chestplate"
+ },
+ {
+ "internalName": "bow",
+ "displayName": "Bow"
+ },
+ {
+ "internalName": "brick",
+ "displayName": "Brick"
+ },
+ {
+ "internalName": "ingotIron",
+ "displayName": "Iron Ingot"
+ },
+ {
+ "internalName": "feather",
+ "displayName": "Feather"
+ },
+ {
+ "internalName": "wheat",
+ "displayName": "Wheat"
+ },
+ {
+ "internalName": "painting",
+ "displayName": "Painting"
+ },
+ {
+ "internalName": "reeds",
+ "displayName": "Sugar Canes"
+ },
+ {
+ "internalName": "bone",
+ "displayName": "Bone"
+ },
+ {
+ "internalName": "cake",
+ "displayName": "Cake"
+ },
+ {
+ "internalName": "slimeball",
+ "displayName": "Slimeball"
+ },
+ {
+ "internalName": "broken_elytra",
+ "displayName": "Elytra (Broken)"
+ },
+ {
+ "internalName": "leggingsCloth",
+ "displayName": "Leather Pants",
+ "allowCustomColour": true,
+ "hasColourEntry": true,
+ "colourEntry": {
+ "defaultName": "Armour_Default_Leather_Colour",
+ "variants": [ "Armour_Default_Leather_Colour" ]
+ }
+ },
+ {
+ "internalName": "leggingsChain",
+ "displayName": "Chain Leggings"
+ },
+ {
+ "internalName": "leggingsIron",
+ "displayName": "Iron Leggings"
+ },
+ {
+ "internalName": "leggingsDiamond",
+ "displayName": "Diamond Leggings"
+ },
+ {
+ "internalName": "leggingsGold",
+ "displayName": "Golden Leggings"
+ },
+ {
+ "internalName": "arrow",
+ "displayName": "Arrow"
+ },
+ {
+ "internalName": "end_crystal",
+ "displayName": "End Crystal"
+ },
+ {
+ "internalName": "ingotGold",
+ "displayName": "Gold Ingot"
+ },
+ {
+ "internalName": "sulphur",
+ "displayName": "Gunpowder"
+ },
+ {
+ "internalName": "bread",
+ "displayName": "Bread"
+ },
+ {
+ "internalName": "sign",
+ "displayName": "Oak Sign"
+ },
+ {
+ "internalName": "doorWood",
+ "displayName": "Oak Door"
+ },
+ {
+ "internalName": "doorIron",
+ "displayName": "Iron Door"
+ },
+ {
+ "internalName": "bed",
+ "displayName": "Bed"
+ },
+ {
+ "internalName": "fireball",
+ "displayName": "Fire Charge"
+ },
+ {
+ "internalName": "chorus_fruit",
+ "displayName": "Chorus Fruit"
+ },
+ {
+ "internalName": "bootsCloth",
+ "displayName": "Leather Boots",
+ "allowCustomColour": true,
+ "hasColourEntry": true,
+ "colourEntry": {
+ "defaultName": "Armour_Default_Leather_Colour",
+ "variants": [ "Armour_Default_Leather_Colour" ]
+ }
+ },
+ {
+ "internalName": "bootsChain",
+ "displayName": "Chain Boots"
+ },
+ {
+ "internalName": "bootsIron",
+ "displayName": "Iron Boots"
+ },
+ {
+ "internalName": "bootsDiamond",
+ "displayName": "Diamond Boots"
+ },
+ {
+ "internalName": "bootsGold",
+ "displayName": "Golden Boots"
+ },
+ {
+ "internalName": "stick",
+ "displayName": "Stick"
+ },
+ {
+ "internalName": "compass",
+ "displayName": "Compass"
+ },
+ {
+ "internalName": "diamond",
+ "displayName": "Diamond"
+ },
+ {
+ "internalName": "redstone",
+ "displayName": "Redstone"
+ },
+ {
+ "internalName": "clay",
+ "displayName": "Clay"
+ },
+ {
+ "internalName": "paper",
+ "displayName": "Paper"
+ },
+ {
+ "internalName": "book",
+ "displayName": "Book"
+ },
+ {
+ "internalName": "map",
+ "displayName": "Map"
+ },
+ {
+ "internalName": "seeds_pumpkin",
+ "displayName": "Pumpkin Seeds"
+ },
+ {
+ "internalName": "seeds_melon",
+ "displayName": "Melon Seeds"
+ },
+ {
+ "internalName": "chorus_fruit_popped",
+ "displayName": "Popped Chorus Fruit"
+ },
+ {
+ "internalName": "swordWood",
+ "displayName": "Wooden Sword"
+ },
+ {
+ "internalName": "swordStone",
+ "displayName": "Stone Sword"
+ },
+ {
+ "internalName": "swordIron",
+ "displayName": "Iron Sword"
+ },
+ {
+ "internalName": "swordDiamond",
+ "displayName": "Diamond Sword"
+ },
+ {
+ "internalName": "swordGold",
+ "displayName": "Golden Sword"
+ },
+ {
+ "internalName": "fishingRod_uncast",
+ "displayName": "Fishing Rod"
+ },
+ {
+ "internalName": "clock",
+ "displayName": "Clock"
+ },
+ {
+ "internalName": "bowl",
+ "displayName": "Bowl"
+ },
+ {
+ "internalName": "mushroomStew",
+ "displayName": "Mushroom Stew"
+ },
+ {
+ "internalName": "yellowDust",
+ "displayName": "Glowstone Dust"
+ },
+ {
+ "internalName": "bucket",
+ "displayName": "Bucket"
+ },
+ {
+ "internalName": "bucketWater",
+ "displayName": "Water Bucket"
+ },
+ {
+ "internalName": "bucketLava",
+ "displayName": "Lava Bucket"
+ },
+ {
+ "internalName": "milk",
+ "displayName": "Milk Bucket"
+ },
+ {
+ "internalName": "dyePowder_black",
+ "displayName": "Ink Sac"
+ },
+ {
+ "internalName": "dyePowder_gray",
+ "displayName": "Gray Dye"
+ },
+ {
+ "internalName": "shovelWood",
+ "displayName": "Wooden Shovel"
+ },
+ {
+ "internalName": "shovelStone",
+ "displayName": "Stone Shovel"
+ },
+ {
+ "internalName": "shovelIron",
+ "displayName": "Iron Shovel"
+ },
+ {
+ "internalName": "shovelDiamond",
+ "displayName": "Diamond Shovel"
+ },
+ {
+ "internalName": "shovelGold",
+ "displayName": "Golden Shovel"
+ },
+ {
+ "internalName": "fishingRod_cast",
+ "displayName": "Fishing Rod (Cast)"
+ },
+ {
+ "internalName": "diode",
+ "displayName": "Redstone Repeater"
+ },
+ {
+ "internalName": "porkchopRaw",
+ "displayName": "Raw Porkchop"
+ },
+ {
+ "internalName": "porkchopCooked",
+ "displayName": "Cooked Porkchop"
+ },
+ {
+ "internalName": "fishRaw",
+ "displayName": "Raw Cod"
+ },
+ {
+ "internalName": "fishCooked",
+ "displayName": "Cooked Cod"
+ },
+ {
+ "internalName": "rottenFlesh",
+ "displayName": "Rotten Flesh"
+ },
+ {
+ "internalName": "cookie",
+ "displayName": "Cookie"
+ },
+ {
+ "internalName": "shears",
+ "displayName": "Shears"
+ },
+ {
+ "internalName": "dyePowder_red",
+ "displayName": "Rose Red"
+ },
+ {
+ "internalName": "dyePowder_pink",
+ "displayName": "Pink Dye"
+ },
+ {
+ "internalName": "pickaxeWood",
+ "displayName": "Wooden Pickaxe"
+ },
+ {
+ "internalName": "pickaxeStone",
+ "displayName": "Stone Pickaxe"
+ },
+ {
+ "internalName": "pickaxeIron",
+ "displayName": "Iron Pickaxe"
+ },
+ {
+ "internalName": "pickaxeDiamond",
+ "displayName": "Diamond Pickaxe"
+ },
+ {
+ "internalName": "pickaxeGold",
+ "displayName": "Golden Pickaxe"
+ },
+ {
+ "internalName": "bow_pull_0",
+ "displayName": "Bow (Pulling Stage 1)"
+ },
+ {
+ "internalName": "carrotOnAStick",
+ "displayName": "Carrot on a Stick"
+ },
+ {
+ "internalName": "leather",
+ "displayName": "Leather"
+ },
+ {
+ "internalName": "saddle",
+ "displayName": "Saddle"
+ },
+ {
+ "internalName": "beefRaw",
+ "displayName": "Raw Beef"
+ },
+ {
+ "internalName": "beefCooked",
+ "displayName": "Steak"
+ },
+ {
+ "internalName": "enderPearl",
+ "displayName": "Ender Pearl"
+ },
+ {
+ "internalName": "blazeRod",
+ "displayName": "Blaze Rod"
+ },
+ {
+ "internalName": "melon",
+ "displayName": "Melon Slice"
+ },
+ {
+ "internalName": "dyePowder_green",
+ "displayName": "Cactus Green"
+ },
+ {
+ "internalName": "dyePowder_lime",
+ "displayName": "Lime Dye"
+ },
+ {
+ "internalName": "hatchetWood",
+ "displayName": "Wooden Axe"
+ },
+ {
+ "internalName": "hatchetStone",
+ "displayName": "Stone Axe"
+ },
+ {
+ "internalName": "hatchetIron",
+ "displayName": "Iron Axe"
+ },
+ {
+ "internalName": "hatchetDiamond",
+ "displayName": "Diamond Axe"
+ },
+ {
+ "internalName": "hatchetGold",
+ "displayName": "Golden Axe"
+ },
+ {
+ "internalName": "bow_pull_1",
+ "displayName": "Bow (Pulling Stage 2)"
+ },
+ {
+ "internalName": "potatoBaked",
+ "displayName": "Baked Potato"
+ },
+ {
+ "internalName": "potato",
+ "displayName": "Potato"
+ },
+ {
+ "internalName": "carrots",
+ "displayName": "Carrot"
+ },
+ {
+ "internalName": "chickenRaw",
+ "displayName": "Raw Chicken"
+ },
+ {
+ "internalName": "chickenCooked",
+ "displayName": "Cooked Chicken"
+ },
+ {
+ "internalName": "ghastTear",
+ "displayName": "Ghast Tear"
+ },
+ {
+ "internalName": "goldNugget",
+ "displayName": "Gold Nugget"
+ },
+ {
+ "internalName": "netherStalkSeeds",
+ "displayName": "Nether Wart"
+ },
+ {
+ "internalName": "dyePowder_brown",
+ "displayName": "Cocoa Beans"
+ },
+ {
+ "internalName": "dyePowder_yellow",
+ "displayName": "Dandelion Yellow"
+ },
+ {
+ "internalName": "hoeWood",
+ "displayName": "Wooden Hoe"
+ },
+ {
+ "internalName": "hoeStone",
+ "displayName": "Stone Hoe"
+ },
+ {
+ "internalName": "hoeIron",
+ "displayName": "Iron Hoe"
+ },
+ {
+ "internalName": "hoeDiamond",
+ "displayName": "Diamond Hoe"
+ },
+ {
+ "internalName": "hoeGold",
+ "displayName": "Golden Hoe"
+ },
+ {
+ "internalName": "bow_pull_2",
+ "displayName": "Bow (Pulling Stage 3)"
+ },
+ {
+ "internalName": "potatoPoisonous",
+ "displayName": "Poisonous Potato"
+ },
+ {
+ "internalName": "minecart",
+ "displayName": "Minecart"
+ },
+ {
+ "internalName": "boat",
+ "displayName": "Oak Boat"
+ },
+ {
+ "internalName": "speckledMelon",
+ "displayName": "Glistering Melon"
+ },
+ {
+ "internalName": "fermentedSpiderEye",
+ "displayName": "Fermented Spider Eye"
+ },
+ {
+ "internalName": "spiderEye",
+ "displayName": "Spider Eye"
+ },
+ {
+ "internalName": "glassBottle",
+ "displayName": "Glass Bottle"
+ },
+ {
+ "internalName": "potion_contents",
+ "displayName": "Potion (Overlay)",
+ "allowCustomColour": true,
+ "hasColourEntry": true,
+ "colourEntry": {
+ "defaultName": "Potion_BaseColour",
+ "variants": [
+ "Potion_BaseColour",
+ "Effect_MovementSpeed",
+ "Effect_MovementSlowDown",
+ "Effect_DigSpeed",
+ "Effect_DigSlowdown",
+ "Effect_DamageBoost",
+ "Effect_Heal",
+ "Effect_Harm",
+ "Effect_Jump",
+ "Effect_Confusion",
+ "Effect_Regeneration",
+ "Effect_DamageResistance",
+ "Effect_FireResistance",
+ "Effect_WaterBreathing",
+ "Effect_Invisibility",
+ "Effect_Blindness",
+ "Effect_NightVision",
+ "Effect_Hunger",
+ "Effect_Weakness",
+ "Effect_Poison",
+ "Effect_Wither",
+ "Effect_HealthBoost",
+ "Effect_Absorption",
+ "Effect_Saturation",
+ "Effect_Levitation",
+ "Effect_Luck",
+ "Effect_BadLuck",
+ "Effect_TurtleMaster",
+ "Effect_SlowFall"
+ ]
+ }
+ },
+ {
+ "internalName": "dyePowder_blue",
+ "displayName": "Lapis Lazuli"
+ },
+ {
+ "internalName": "dyePowder_light_blue",
+ "displayName": "Light Blue Dye"
+ },
+ {
+ "internalName": "helmetCloth_overlay",
+ "displayName": "Leather Cap (Overlay)"
+ },
+ {
+ "internalName": "spectral_arrow",
+ "displayName": "Spectral Arrow"
+ },
+ {
+ "internalName": "iron_horse_armor",
+ "displayName": "Iron Horse Armor"
+ },
+ {
+ "internalName": "diamond_horse_armor",
+ "displayName": "Diamond Horse Armor"
+ },
+ {
+ "internalName": "gold_horse_armor",
+ "displayName": "Gold Horse Armor"
+ },
+ {
+ "internalName": "comparator",
+ "displayName": "Redstone Comparator"
+ },
+ {
+ "internalName": "carrotGolden",
+ "displayName": "Golden Carrot"
+ },
+ {
+ "internalName": "minecart_chest",
+ "displayName": "Minecart with Chest"
+ },
+ {
+ "internalName": "pumpkinPie",
+ "displayName": "Pumpkin Pie"
+ },
+ {
+ "internalName": "monsterPlacer",
+ "displayName": "Spawn Egg",
+ "hasColourEntry": true,
+ "colourEntry": {
+ "defaultName": "Mob_Creeper_Colour1",
+ "variants": [
+ "Mob_Creeper_Colour1",
+ "Mob_Skeleton_Colour1",
+ "Mob_Spider_Colour1",
+ "Mob_Zombie_Colour1",
+ "Mob_Slime_Colour1",
+ "Mob_Ghast_Colour1",
+ "Mob_PigZombie_Colour1",
+ "Mob_Enderman_Colour1",
+ "Mob_CaveSpider_Colour1",
+ "Mob_Silverfish_Colour1",
+ "Mob_Blaze_Colour1",
+ "Mob_LavaSlime_Colour1",
+ "Mob_Pig_Colour1",
+ "Mob_Sheep_Colour1",
+ "Mob_Cow_Colour1",
+ "Mob_Chicken_Colour1",
+ "Mob_Squid_Colour1",
+ "Mob_Wolf_Colour1",
+ "Mob_MushroomCow_Colour1",
+ "Mob_Ocelot_Colour1",
+ "Mob_Villager_Colour1",
+ "Mob_Bat_Colour1",
+ "Mob_Witch_Colour1",
+ "Mob_Horse_Colour1",
+ "Mob_Endermite_Color1",
+ "Mob_Guardian_Color1",
+ "Mob_Rabbit_Colour1",
+ "Mob_PolarBear_Colour1",
+ "Mob_Shulker_Colour1",
+ "Mob_Elder_Guardian_Colour1",
+ "Mob_Evocation_Illager_Colour1",
+ "Mob_Llama_Colour1",
+ "Mob_Donkey_Colour1",
+ "Mob_Skeleton_Horse_Colour1",
+ "Mob_Zombie_Horse_Colour1",
+ "Mob_Mule_Colour1",
+ "Mob_Stray_Colour1",
+ "Mob_Husk_Colour1",
+ "Mob_Vex_Colour1",
+ "Mob_Vindication_Illager_Colour1",
+ "Mob_Zombie_Villager_Colour1",
+ "Mob_Parrot_Colour1",
+ "Mob_Wither_Skeleton_Colour1",
+ "Mob_Turtle_Colour1",
+ "Mob_Tropical_Colour1",
+ "Mob_Cod_Colour1",
+ "Mob_Pufferfish_Colour1",
+ "Mob_Salmon_Colour1",
+ "Mob_Drowned_Colour1",
+ "Mob_Dolphin_Colour1",
+ "Mob_Phantom_Colour1"
+ ]
+ }
+ },
+ {
+ "internalName": "potion_splash",
+ "displayName": "Splash Potion"
+ },
+ {
+ "internalName": "eyeOfEnder",
+ "displayName": "Eye of Ender"
+ },
+ {
+ "internalName": "cauldron",
+ "displayName": "Cauldron"
+ },
+ {
+ "internalName": "blazePowder",
+ "displayName": "Blaze Powder"
+ },
+ {
+ "internalName": "dyePowder_purple",
+ "displayName": "Purple Dye"
+ },
+ {
+ "internalName": "dyePowder_magenta",
+ "displayName": "Magenta Dye"
+ },
+ {
+ "internalName": "chestplateCloth_overlay",
+ "displayName": "Leather Tunic (Overlay)"
+ },
+ {
+ "internalName": "tipped_arrow_base",
+ "displayName": "Tipped Arrow"
+ },
+ {
+ "internalName": "dragon_breath",
+ "displayName": "Dragon's Breath"
+ },
+ {
+ "internalName": "name_tag",
+ "displayName": "Name Tag"
+ },
+ {
+ "internalName": "lead",
+ "displayName": "Lead"
+ },
+ {
+ "internalName": "netherbrick",
+ "displayName": "Nether Brick"
+ },
+ {
+ "internalName": "fish_clownfish_raw",
+ "displayName": "Tropical Fish"
+ },
+ {
+ "internalName": "minecart_furnace",
+ "displayName": "Minecart with Furnace"
+ },
+ {
+ "internalName": "charcoal",
+ "displayName": "Charcoal"
+ },
+ {
+ "internalName": "monsterPlacer_overlay",
+ "displayName": "Spawn Egg (Overlay)",
+ "hasColourEntry": true,
+ "colourEntry": {
+ "defaultName": "Mob_Creeper_Colour2",
+ "variants": [
+ "Mob_Creeper_Colour2",
+ "Mob_Skeleton_Colour2",
+ "Mob_Spider_Colour2",
+ "Mob_Zombie_Colour2",
+ "Mob_Slime_Colour2",
+ "Mob_Ghast_Colour2",
+ "Mob_PigZombie_Colour2",
+ "Mob_Enderman_Colour2",
+ "Mob_CaveSpider_Colour2",
+ "Mob_Silverfish_Colour2",
+ "Mob_Blaze_Colour2",
+ "Mob_LavaSlime_Colour2",
+ "Mob_Pig_Colour2",
+ "Mob_Sheep_Colour2",
+ "Mob_Cow_Colour2",
+ "Mob_Chicken_Colour2",
+ "Mob_Squid_Colour2",
+ "Mob_Wolf_Colour2",
+ "Mob_MushroomCow_Colour2",
+ "Mob_Ocelot_Colour2",
+ "Mob_Villager_Colour2",
+ "Mob_Bat_Colour2",
+ "Mob_Witch_Colour2",
+ "Mob_Horse_Colour2",
+ "Mob_Endermite_Color2",
+ "Mob_Guardian_Color2",
+ "Mob_Rabbit_Colour2",
+ "Mob_PolarBear_Colour2",
+ "Mob_Shulker_Colour2",
+ "Mob_Elder_Guardian_Colour2",
+ "Mob_Evocation_Illager_Colour2",
+ "Mob_Llama_Colour2",
+ "Mob_Donkey_Colour2",
+ "Mob_Skeleton_Horse_Colour2",
+ "Mob_Zombie_Horse_Colour2",
+ "Mob_Mule_Colour2",
+ "Mob_Stray_Colour2",
+ "Mob_Husk_Colour2",
+ "Mob_Vex_Colour2",
+ "Mob_Vindication_Illager_Colour2",
+ "Mob_Zombie_Villager_Colour2",
+ "Mob_Parrot_Colour2",
+ "Mob_Wither_Skeleton_Colour2",
+ "Mob_Turtle_Colour2",
+ "Mob_Tropical_Colour2",
+ "Mob_Cod_Colour2",
+ "Mob_Pufferfish_Colour2",
+ "Mob_Salmon_Colour2",
+ "Mob_Drowned_Colour2",
+ "Mob_Dolphin_Colour2",
+ "Mob_Phantom_Colour2"
+ ]
+ }
+ },
+ {
+ "internalName": "bed_overlay",
+ "displayName": "Bed (Overlay)",
+ "hasColourEntry": true,
+ "colourEntry": {
+ "defaultName": "Bed_White",
+ "variants": [
+ "Bed_Black",
+ "Bed_Blue",
+ "Bed_Brown",
+ "Bed_Cyan",
+ "Bed_Grey",
+ "Bed_Green",
+ "Bed_Light_Blue",
+ "Bed_Lime",
+ "Bed_Magenta",
+ "Bed_Orange",
+ "Bed_Pink",
+ "Bed_Purple",
+ "Bed_Red",
+ "Bed_Silver",
+ "Bed_White",
+ "Bed_Yellow"
+ ]
+ }
+ },
+ {
+ "internalName": "expBottle",
+ "displayName": "Bottle o'Enchanting"
+ },
+ {
+ "internalName": "brewingStand",
+ "displayName": "Brewing Stand"
+ },
+ {
+ "internalName": "magmaCream",
+ "displayName": "Magma Cream"
+ },
+ {
+ "internalName": "dyePowder_cyan",
+ "displayName": "Cyan Dye"
+ },
+ {
+ "internalName": "dyePowder_orange",
+ "displayName": "Orange Dye"
+ },
+ {
+ "internalName": "leggingsCloth_overlay",
+ "displayName": "Leather Pants (Overlay)"
+ },
+ {
+ "internalName": "tipped_arrow_head",
+ "displayName": "Tipped Arrow (Overlay)"
+ },
+ {
+ "internalName": "potion_bottle_lingering",
+ "displayName": "Lingering Potion"
+ },
+ {
+ "internalName": "barrier",
+ "displayName": "debug_fourj_item"
+ },
+ {
+ "internalName": "mutton_raw",
+ "displayName": "Raw Mutton"
+ },
+ {
+ "internalName": "rabbit_raw",
+ "displayName": "Raw Rabbit"
+ },
+ {
+ "internalName": "fish_pufferfish_raw",
+ "displayName": "Pufferfish"
+ },
+ {
+ "internalName": "minecart_hopper",
+ "displayName": "Minecart with Hopper"
+ },
+ {
+ "internalName": "hopper",
+ "displayName": "Hopper"
+ },
+ {
+ "internalName": "nether_star",
+ "displayName": "Nether Star"
+ },
+ {
+ "internalName": "emerald",
+ "displayName": "Emerald"
+ },
+ {
+ "internalName": "writingBook",
+ "displayName": "Book and Quill"
+ },
+ {
+ "internalName": "writtenBook",
+ "displayName": "Written Book"
+ },
+ {
+ "internalName": "flowerPot",
+ "displayName": "Flower Pot"
+ },
+ {
+ "internalName": "dyePowder_silver",
+ "displayName": "Light Gray Dye"
+ },
+ {
+ "internalName": "dyePowder_white",
+ "displayName": "Bone Meal"
+ },
+ {
+ "internalName": "bootsCloth_overlay",
+ "displayName": "Leather Boots (Overlay)"
+ },
+ {
+ "internalName": "beetroot",
+ "displayName": "Beetroot"
+ },
+ {
+ "internalName": "beetroot_seeds",
+ "displayName": "Beetroot Seeds"
+ },
+ {
+ "internalName": "beetroot_soup",
+ "displayName": "Beetroot Soup"
+ },
+ {
+ "internalName": "mutton_cooked",
+ "displayName": "Cooked Mutton"
+ },
+ {
+ "internalName": "rabbit_cooked",
+ "displayName": "Cooked Rabbit"
+ },
+ {
+ "internalName": "fish_salmon_raw",
+ "displayName": "Raw Salmon"
+ },
+ {
+ "internalName": "minecart_tnt",
+ "displayName": "Minecart with TNT"
+ },
+ {
+ "internalName": "wooden_armorstand",
+ "displayName": "Armor Stand"
+ },
+ {
+ "internalName": "fireworks",
+ "displayName": "Firework Rocket"
+ },
+ {
+ "internalName": "fireworks_charge",
+ "displayName": "Firework Star"
+ },
+ {
+ "internalName": "fireworks_charge_overlay",
+ "displayName": "Firework Star (Overlay)",
+ "allowCustomColour": true
+ },
+ {
+ "internalName": "netherquartz",
+ "displayName": "Nether Quartz"
+ },
+ {
+ "internalName": "map_empty",
+ "displayName": "Empty Map"
+ },
+ {
+ "internalName": "frame",
+ "displayName": "Item Frame"
+ },
+ {
+ "internalName": "enchantedBook",
+ "displayName": "Enchanted Book"
+ },
+ {
+ "internalName": "door_acacia",
+ "displayName": "Acacia Door"
+ },
+ {
+ "internalName": "door_birch",
+ "displayName": "Birch Door"
+ },
+ {
+ "internalName": "door_dark_oak",
+ "displayName": "Dark Oak Door"
+ },
+ {
+ "internalName": "door_jungle",
+ "displayName": "Jungle Door"
+ },
+ {
+ "internalName": "door_spruce",
+ "displayName": "Spruce Door"
+ },
+ {
+ "internalName": "rabbit_stew",
+ "displayName": "Rabbit Stew"
+ },
+ {
+ "internalName": "fish_salmon_cooked",
+ "displayName": "Cooked Salmon"
+ },
+ {
+ "internalName": "minecart_command_block",
+ "displayName": "Minecart with Command Block"
+ },
+ {
+ "internalName": "acacia_boat",
+ "displayName": "Acacia Boat"
+ },
+ {
+ "internalName": "birch_boat",
+ "displayName": "Birch Boat"
+ },
+ {
+ "internalName": "dark_oak_boat",
+ "displayName": "Dark Oak Boat"
+ },
+ {
+ "internalName": "jungle_boat",
+ "displayName": "Jungle Boat"
+ },
+ {
+ "internalName": "spruce_boat",
+ "displayName": "Spruce Boat"
+ },
+ {
+ "internalName": "prismarine_shard",
+ "displayName": "Prismarine Shard"
+ },
+ {
+ "internalName": "prismarine_crystals",
+ "displayName": "Prismarine Crystals"
+ },
+ {
+ "internalName": "leather_horse_armor_base",
+ "displayName": "Leather Horse Armor",
+ "allowCustomColour": true,
+ "hasColourEntry": true,
+ "colourEntry": {
+ "defaultName": "Armour_Default_Leather_Colour",
+ "variants": [ "Armour_Default_Leather_Colour" ]
+ }
+ },
+ {
+ "internalName": "structure_void",
+ "displayName": "Structure Void"
+ },
+ {
+ "internalName": "map_filled_markings",
+ "displayName": "Filled Map (Overlay)"
+ },
+ {
+ "internalName": "totem",
+ "displayName": "Totem of Undying"
+ },
+ {
+ "internalName": "shulker_shell",
+ "displayName": "Shulker Shell"
+ },
+ {
+ "internalName": "iron_nugget",
+ "displayName": "Iron Nugget"
+ },
+ {
+ "internalName": "rabbit_foot",
+ "displayName": "Rabbit's Foot"
+ },
+ {
+ "internalName": "rabbit_hide",
+ "displayName": "Rabbit Hide"
+ },
+ {
+ "internalName": "compass",
+ "displayName": ""
+ },
+ {
+ "internalName": "compass",
+ "displayName": ""
+ },
+ {
+ "internalName": "compass",
+ "displayName": ""
+ },
+ {
+ "internalName": "compass",
+ "displayName": ""
+ },
+ {
+ "internalName": "clock",
+ "displayName": ""
+ },
+ {
+ "internalName": "clock",
+ "displayName": ""
+ },
+ {
+ "internalName": "clock",
+ "displayName": ""
+ },
+ {
+ "internalName": "clock",
+ "displayName": ""
+ },
+ {
+ "internalName": "dragonFireball",
+ "displayName": "Dragon Fireball"
+ },
+ {
+ "internalName": "record_13",
+ "displayName": "Music Disc (C418 - 13)"
+ },
+ {
+ "internalName": "record_cat",
+ "displayName": "Music Disc (C418 - cat)"
+ },
+ {
+ "internalName": "record_blocks",
+ "displayName": "Music Disc (C418 - blocks)"
+ },
+ {
+ "internalName": "record_chirp",
+ "displayName": "Music Disc (C418 - chirp)"
+ },
+ {
+ "internalName": "record_far",
+ "displayName": "Music Disc (C418 - far)"
+ },
+ {
+ "internalName": "record_mall",
+ "displayName": "Music Disc (C418 - mall)"
+ },
+ {
+ "internalName": "record_mellohi",
+ "displayName": "Music Disc (C418 - mellohi)"
+ },
+ {
+ "internalName": "record_stal",
+ "displayName": "Music Disc (C418 - stal)"
+ },
+ {
+ "internalName": "record_strad",
+ "displayName": "Music Disc (C418 - strad)"
+ },
+ {
+ "internalName": "record_ward",
+ "displayName": "Music Disc (C418 - ward)"
+ },
+ {
+ "internalName": "record_11",
+ "displayName": "Music Disc (C418 - 11)"
+ },
+ {
+ "internalName": "record_where are we now",
+ "displayName": "Music Disc (C418 - wait)"
+ },
+ {
+ "internalName": "bucketFish",
+ "displayName": "Bucket of Cod"
+ },
+ {
+ "internalName": "bucketSalmon",
+ "displayName": "Bucket of Salmon"
+ },
+ {
+ "internalName": "bucketPuffer",
+ "displayName": "Bucket of Pufferfish"
+ },
+ {
+ "internalName": "bucketTropical",
+ "displayName": "Bucket of Tropical Fish"
+ },
+ {
+ "internalName": "leather_horse_armor_detail",
+ "displayName": "Leather Horse Armor (Overlay)"
+ },
+ {
+ "internalName": "dyePowder_black1",
+ "displayName": "Black Dye [PS4 ONLY]"
+ },
+ {
+ "internalName": "dyePowder_blue1",
+ "displayName": "Blue Dye [PS4 ONLY]"
+ },
+ {
+ "internalName": "dyePowder_brown1",
+ "displayName": "Brown Dye [PS4 ONLY]"
+ },
+ {
+ "internalName": "dyePowder_white1",
+ "displayName": "White Dye [PS4 ONLY]"
+ },
+ {
+ "internalName": "bamboo",
+ "displayName": "Bamboo [PS4 ONLY]"
+ },
+ {
+ "internalName": "lantern_carried",
+ "displayName": "Lantern [PS4 ONLY]"
+ },
+ {
+ "internalName": "kelp",
+ "displayName": "Kelp"
+ },
+ {
+ "internalName": "dried_kelp",
+ "displayName": "Dried Kelp"
+ },
+ {
+ "internalName": "sea_pickle",
+ "displayName": "Sea Pickle"
+ },
+ {
+ "internalName": "nautilus",
+ "displayName": "Nautilus Shell"
+ },
+ {
+ "internalName": "nautilus_core",
+ "displayName": "Heart of the Sea"
+ },
+ {
+ "internalName": "turtle_helmet",
+ "displayName": "Turtle Shell"
+ },
+ {
+ "internalName": "turtle_shell_piece",
+ "displayName": "Scute"
+ },
+ {
+ "internalName": "trident",
+ "displayName": "Trident"
+ },
+ {
+ "internalName": "phantom_membrane",
+ "displayName": "Phantom Membrane"
+ },
+ {
+ "internalName": "acacia_sign",
+ "displayName": "Acacia Sign [PS4 ONLY]"
+ },
+ {
+ "internalName": "birch_sign",
+ "displayName": "Birch Sign [PS4 ONLY]"
+ },
+ {
+ "internalName": "dark_oak_sign",
+ "displayName": "Dark Oak Sign [PS4 ONLY]"
+ },
+ {
+ "internalName": "jungle_sign",
+ "displayName": "Jungle Sign [PS4 ONLY]"
+ },
+ {
+ "internalName": "spruce_sign",
+ "displayName": "Spruce Sign [PS4 ONLY]"
+ },
+ {
+ "internalName": "crossbow",
+ "displayName": "Crossbow [PS4 ONLY]"
+ },
+ {
+ "internalName": "crossbow_pull_0",
+ "displayName": "Crossbow (Pulling Stage 1) [PS4 ONLY]"
+ },
+ {
+ "internalName": "crossbow_pull_1",
+ "displayName": "Crossbow (Pulling Stage 2) [PS4 ONLY]"
+ },
+ {
+ "internalName": "crossbow_pull_2",
+ "displayName": "Crossbow (Pulling Stage 3) [PS4 ONLY]"
+ },
+ {
+ "internalName": "crossbow_arrow",
+ "displayName": "Crossbow (Loaded) [PS4 ONLY]"
+ },
+ {
+ "internalName": "crossbow_firework",
+ "displayName": "Crossbow (Loaded) (Firework) [PS4 ONLY]"
+ },
+ {
+ "internalName": "sweet_berries",
+ "displayName": "Sweet Berries [PS4 ONLY]"
+ },
+ {
+ "internalName": "banner_pattern",
+ "displayName": "Banner Pattern [PS4 ONLY]"
+ },
+ {
+ "internalName": "bell",
+ "displayName": "Bell [PS4 ONLY]"
+ },
+ {
+ "internalName": "campfire_carried",
+ "displayName": "Campfire [PS4 ONLY]"
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ }
+ ]
+}
diff --git a/PckStudio.Core/Resources/items.png b/PckStudio.Core/Resources/items.png
new file mode 100644
index 00000000..6d316ad9
Binary files /dev/null and b/PckStudio.Core/Resources/items.png differ
diff --git a/PckStudio.Core/Resources/mapIconData.json b/PckStudio.Core/Resources/mapIconData.json
new file mode 100644
index 00000000..8e1273f2
--- /dev/null
+++ b/PckStudio.Core/Resources/mapIconData.json
@@ -0,0 +1,135 @@
+{
+ "COMMENT_1": "JSON by MattNL",
+ "entries": [
+ {
+ "internalName": "player_1",
+ "displayName": "Player 1"
+ },
+ {
+ "internalName": "player_2",
+ "displayName": "Player 2"
+ },
+ {
+ "internalName": "player_3",
+ "displayName": "Player 3"
+ },
+ {
+ "internalName": "player_4",
+ "displayName": "Player 4"
+ },
+ {
+ "internalName": "target_x",
+ "displayName": "Unused"
+ },
+ {
+ "internalName": "target_point",
+ "displayName": "Target Point (Unused)"
+ },
+ {
+ "internalName": "player_off_map",
+ "displayName": "Player (Off Map) (Unused)"
+ },
+ {
+ "internalName": "frame",
+ "displayName": "Item Frame"
+ },
+ {
+ "internalName": "player_5",
+ "displayName": "Player 5"
+ },
+ {
+ "internalName": "player_6",
+ "displayName": "Player 6"
+ },
+ {
+ "internalName": "player_7",
+ "displayName": "Player 7"
+ },
+ {
+ "internalName": "player_8",
+ "displayName": "Player 8"
+ },
+ {
+ "internalName": "structure",
+ "displayName": "Structure (Explorer Map)"
+ },
+ {
+ "internalName": "player_off_limits",
+ "displayName": "Player (Off Limits) (Unused)"
+ },
+ {
+ "internalName": "mansion",
+ "displayName": "Woodland Mansion (Explorer Map)"
+ },
+ {
+ "internalName": "monument",
+ "displayName": "Ocean Monument (Explorer Map)"
+ }
+ ],
+ "additional_entries": [
+ {
+ "internalName": "player_1_off_map",
+ "displayName": "Player 1 (Off Map)"
+ },
+ {
+ "internalName": "player_2_off_map",
+ "displayName": "Player 2 (Off Map)"
+ },
+ {
+ "internalName": "player_3_off_map",
+ "displayName": "Player 3 (Off Map)"
+ },
+ {
+ "internalName": "player_4_off_map",
+ "displayName": "Player 4 (Off Map)"
+ },
+ {
+ "internalName": "treasure",
+ "displayName": "Buried Treasure"
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "player_5_off_map",
+ "displayName": "Player 5 (Off Map)"
+ },
+ {
+ "internalName": "player_6_off_map",
+ "displayName": "Player 6 (Off Map)"
+ },
+ {
+ "internalName": "player_7_off_map",
+ "displayName": "Player 7 (Off Map)"
+ },
+ {
+ "internalName": "player_8_off_map",
+ "displayName": "Player 8 (Off Map)"
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ }
+ ]
+}
diff --git a/PckStudio.Core/Resources/map_icons.png b/PckStudio.Core/Resources/map_icons.png
new file mode 100644
index 00000000..7b6ecd13
Binary files /dev/null and b/PckStudio.Core/Resources/map_icons.png differ
diff --git a/PckStudio.Core/Resources/moonPhaseData.json b/PckStudio.Core/Resources/moonPhaseData.json
new file mode 100644
index 00000000..506e7f6f
--- /dev/null
+++ b/PckStudio.Core/Resources/moonPhaseData.json
@@ -0,0 +1,37 @@
+{
+ "COMMENT_1": "JSON by MattNL",
+ "entries": [
+ {
+ "internalName": "moon_phase_0",
+ "displayName": "Full Moon"
+ },
+ {
+ "internalName": "moon_phase_1",
+ "displayName": "Waning Gibbous"
+ },
+ {
+ "internalName": "moon_phase_2",
+ "displayName": "Last Quarter"
+ },
+ {
+ "internalName": "moon_phase_3",
+ "displayName": "Waning Crescent"
+ },
+ {
+ "internalName": "moon_phase_4",
+ "displayName": "New Moon"
+ },
+ {
+ "internalName": "moon_phase_5",
+ "displayName": "Waxing Crescent"
+ },
+ {
+ "internalName": "moon_phase_6",
+ "displayName": "First Quarter"
+ },
+ {
+ "internalName": "moon_phase_7",
+ "displayName": "Waxing Gibbous"
+ }
+ ]
+}
diff --git a/PckStudio.Core/Resources/moon_phases.png b/PckStudio.Core/Resources/moon_phases.png
new file mode 100644
index 00000000..ce239ea7
Binary files /dev/null and b/PckStudio.Core/Resources/moon_phases.png differ
diff --git a/PckStudio.Core/Resources/paintingData.json b/PckStudio.Core/Resources/paintingData.json
new file mode 100644
index 00000000..5b5b0ef9
--- /dev/null
+++ b/PckStudio.Core/Resources/paintingData.json
@@ -0,0 +1,1062 @@
+{
+ "COMMENT_1": "JSON by MattNL",
+ "entries": [
+ {
+ "internalName": "Kebab",
+ "displayName": "\"Kebab med tre pepperoni\" by Kristoffer Zetterstrand"
+ },
+ {
+ "internalName": "Aztec",
+ "displayName": "\"de_aztec\" by Kristoffer Zetterstrand"
+ },
+ {
+ "internalName": "Alban",
+ "displayName": "\"Albanian\" by Kristoffer Zetterstrand"
+ },
+ {
+ "internalName": "Aztec2",
+ "displayName": "\"de_aztec\" by Kristoffer Zetterstrand"
+ },
+ {
+ "internalName": "Bomb",
+ "displayName": "\"Target Successfully Bombed\" by Kristoffer Zetterstrand"
+ },
+ {
+ "internalName": "Plant",
+ "displayName": "\"Paradisträd\" by Kristoffer Zetterstrand"
+ },
+ {
+ "internalName": "Wasteland",
+ "displayName": "\"Wasteland\" by Kristoffer Zetterstrand"
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "Back",
+ "displayName": "Back Texture",
+ "width": 4,
+ "height": 4
+ },
+ {
+ "internalName": "Back",
+ "displayName": "",
+ },
+ {
+ "internalName": "Back",
+ "displayName": "",
+ },
+ {
+ "internalName": "Back",
+ "displayName": "",
+ },
+ {
+ "internalName": "1x1E1",
+ "displayName": "Extra Painting 1"
+ },
+ {
+ "internalName": "1x1E2",
+ "displayName": "Extra Painting 2"
+ },
+ {
+ "internalName": "1x1E3",
+ "displayName": "Extra Painting 3"
+ },
+ {
+ "internalName": "1x1E4",
+ "displayName": "Extra Painting 4"
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "Back",
+ "displayName": ""
+ },
+ {
+ "internalName": "Back",
+ "displayName": "",
+ },
+ {
+ "internalName": "Back",
+ "displayName": "",
+ },
+ {
+ "internalName": "Back",
+ "displayName": "",
+ },
+ {
+ "internalName": "Pool",
+ "displayName": "\"The Pool\" by Kristoffer Zetterstrand",
+ "width": 2
+ },
+ {
+ "internalName": "Pool",
+ "displayName": ""
+ },
+ {
+ "internalName": "Courbet",
+ "displayName": "\"Bonjour Monsieur Courbet\" by Kristoffer Zetterstrand",
+ "width": 2
+ },
+ {
+ "internalName": "Courbet",
+ "displayName": ""
+ },
+ {
+ "internalName": "Sea",
+ "displayName": "\"Seaside\" by Kristoffer Zetterstrand",
+ "width": 2
+ },
+ {
+ "internalName": "Sea",
+ "displayName": ""
+ },
+ {
+ "internalName": "Sunset",
+ "displayName": "\"sunset_dense\" by Kristoffer Zetterstrand",
+ "width": 2
+ },
+ {
+ "internalName": "Sunset",
+ "displayName": ""
+ },
+ {
+ "internalName": "Creebet",
+ "displayName": "\"Creebet\" by Kristoffer Zetterstrand",
+ "width": 2
+ },
+ {
+ "internalName": "Creebet",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "Back",
+ "displayName": ""
+ },
+ {
+ "internalName": "Back",
+ "displayName": "",
+ },
+ {
+ "internalName": "Back",
+ "displayName": "",
+ },
+ {
+ "internalName": "Back",
+ "displayName": "",
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "Back",
+ "displayName": ""
+ },
+ {
+ "internalName": "Back",
+ "displayName": "",
+ },
+ {
+ "internalName": "Back",
+ "displayName": "",
+ },
+ {
+ "internalName": "Back",
+ "displayName": "",
+ },
+ {
+ "internalName": "Wanderer",
+ "displayName": "\"Wanderer\" by Kristoffer Zetterstrand",
+ "height": 2
+ },
+ {
+ "internalName": "Graham",
+ "displayName": "\"Graham\" by Kristoffer Zetterstrand",
+ "height": 2
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "Skeleton",
+ "displayName": "\"Mortal Coil\" by Kristoffer Zetterstrand",
+ "width": 4,
+ "height": 3
+ },
+ {
+ "internalName": "Skeleton",
+ "displayName": "",
+ },
+ {
+ "internalName": "Skeleton",
+ "displayName": "",
+ },
+ {
+ "internalName": "Skeleton",
+ "displayName": "",
+ },
+ {
+ "internalName": "Wanderer",
+ "displayName": ""
+ },
+ {
+ "internalName": "Graham",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "Skeleton",
+ "displayName": "",
+ },
+ {
+ "internalName": "Skeleton",
+ "displayName": "",
+ },
+ {
+ "internalName": "Skeleton",
+ "displayName": "",
+ },
+ {
+ "internalName": "Skeleton",
+ "displayName": "",
+ },
+ {
+ "internalName": "Fighters",
+ "displayName": "\"Fighters\" by Kristoffer Zetterstrand",
+ "width": 4,
+ "height": 2
+ },
+ {
+ "internalName": "Fighters",
+ "displayName": ""
+ },
+ {
+ "internalName": "Fighters",
+ "displayName": ""
+ },
+ {
+ "internalName": "Fighters",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "Skeleton",
+ "displayName": ""
+ },
+ {
+ "internalName": "Skeleton",
+ "displayName": ""
+ },
+ {
+ "internalName": "Skeleton",
+ "displayName": ""
+ },
+ {
+ "internalName": "Skeleton",
+ "displayName": ""
+ },
+ {
+ "internalName": "Fighters",
+ "displayName": ""
+ },
+ {
+ "internalName": "Fighters",
+ "displayName": ""
+ },
+ {
+ "internalName": "Fighters",
+ "displayName": ""
+ },
+ {
+ "internalName": "Fighters",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "DonkeyKong",
+ "displayName": "\"Kong\" by Kristoffer Zetterstrand",
+ "width": 4,
+ "height": 3
+ },
+ {
+ "internalName": "DonkeyKong",
+ "displayName": ""
+ },
+ {
+ "internalName": "DonkeyKong",
+ "displayName": ""
+ },
+ {
+ "internalName": "DonkeyKong",
+ "displayName": ""
+ },
+ {
+ "internalName": "Match",
+ "displayName": "\"Match\" by Kristoffer Zetterstrand",
+ "width": 2,
+ "height": 2
+ },
+ {
+ "internalName": "Match",
+ "displayName": ""
+ },
+ {
+ "internalName": "Bust",
+ "displayName": "\"Bust\" by Kristoffer Zetterstrand",
+ "width": 2,
+ "height": 2
+ },
+ {
+ "internalName": "Bust",
+ "displayName": ""
+ },
+ {
+ "internalName": "Stage",
+ "displayName": "\"The stage is set\" by Kristoffer Zetterstrand",
+ "width": 2,
+ "height": 2
+ },
+ {
+ "internalName": "Stage",
+ "displayName": ""
+ },
+ {
+ "internalName": "Void",
+ "displayName": "\"The Void\" by Kristoffer Zetterstrand",
+ "width": 2,
+ "height": 2
+ },
+ {
+ "internalName": "Void",
+ "displayName": ""
+ },
+ {
+ "internalName": "SkullAndRoses",
+ "displayName": "\"Skull and Roses\" by Kristoffer Zetterstrand",
+ "width": 2,
+ "height": 2
+ },
+ {
+ "internalName": "SkullAndRoses",
+ "displayName": ""
+ },
+ {
+ "internalName": "Wither",
+ "displayName": "\"Wither\" by Jens Bergensten",
+ "width": 2,
+ "height": 2
+ },
+ {
+ "internalName": "Wither",
+ "displayName": ""
+ },
+ {
+ "internalName": "DonkeyKong",
+ "displayName": ""
+ },
+ {
+ "internalName": "DonkeyKong",
+ "displayName": ""
+ },
+ {
+ "internalName": "DonkeyKong",
+ "displayName": ""
+ },
+ {
+ "internalName": "DonkeyKong",
+ "displayName": ""
+ },
+ {
+ "internalName": "Match",
+ "displayName": ""
+ },
+ {
+ "internalName": "Match",
+ "displayName": ""
+ },
+ {
+ "internalName": "Bust",
+ "displayName": ""
+ },
+ {
+ "internalName": "Bust",
+ "displayName": ""
+ },
+ {
+ "internalName": "Stage",
+ "displayName": ""
+ },
+ {
+ "internalName": "Stage",
+ "displayName": ""
+ },
+ {
+ "internalName": "Void",
+ "displayName": ""
+ },
+ {
+ "internalName": "Void",
+ "displayName": ""
+ },
+ {
+ "internalName": "SkullAndRoses",
+ "displayName": ""
+ },
+ {
+ "internalName": "SkullAndRoses",
+ "displayName": ""
+ },
+ {
+ "internalName": "Wither",
+ "displayName": ""
+ },
+ {
+ "internalName": "Wither",
+ "displayName": ""
+ },
+ {
+ "internalName": "DonkeyKong",
+ "displayName": "",
+ },
+ {
+ "internalName": "DonkeyKong",
+ "displayName": "",
+ },
+ {
+ "internalName": "DonkeyKong",
+ "displayName": "",
+ },
+ {
+ "internalName": "DonkeyKong",
+ "displayName": "",
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "Pointer",
+ "displayName": "\"Pointer\" by Kristoffer Zetterstrand",
+ "width": 4,
+ "height": 4
+ },
+ {
+ "internalName": "Pointer",
+ "displayName": ""
+ },
+ {
+ "internalName": "Pointer",
+ "displayName": ""
+ },
+ {
+ "internalName": "Pointer",
+ "displayName": ""
+ },
+ {
+ "internalName": "Pigscene",
+ "displayName": "\"Pigscene\" by Kristoffer Zetterstrand",
+ "width": 4,
+ "height": 4
+ },
+ {
+ "internalName": "Pigscene",
+ "displayName": ""
+ },
+ {
+ "internalName": "Pigscene",
+ "displayName": ""
+ },
+ {
+ "internalName": "Pigscene",
+ "displayName": ""
+ },
+ {
+ "internalName": "BurningSkull",
+ "displayName": "\"Skull On Fire\" by Kristoffer Zetterstrand",
+ "width": 4,
+ "height": 4
+ },
+ {
+ "internalName": "BurningSkull",
+ "displayName": ""
+ },
+ {
+ "internalName": "BurningSkull",
+ "displayName": ""
+ },
+ {
+ "internalName": "BurningSkull",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": "",
+ },
+ {
+ "internalName": "",
+ "displayName": "",
+ },
+ {
+ "internalName": "",
+ "displayName": "",
+ },
+ {
+ "internalName": "",
+ "displayName": "",
+ },
+ {
+ "internalName": "Pointer",
+ "displayName": "",
+ },
+ {
+ "internalName": "Pointer",
+ "displayName": ""
+ },
+ {
+ "internalName": "Pointer",
+ "displayName": ""
+ },
+ {
+ "internalName": "Pointer",
+ "displayName": ""
+ },
+ {
+ "internalName": "Pigscene",
+ "displayName": ""
+ },
+ {
+ "internalName": "Pigscene",
+ "displayName": ""
+ },
+ {
+ "internalName": "Pigscene",
+ "displayName": ""
+ },
+ {
+ "internalName": "Pigscene",
+ "displayName": ""
+ },
+ {
+ "internalName": "BurningSkull",
+ "displayName": ""
+ },
+ {
+ "internalName": "BurningSkull",
+ "displayName": ""
+ },
+ {
+ "internalName": "BurningSkull",
+ "displayName": ""
+ },
+ {
+ "internalName": "BurningSkull",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": "",
+ },
+ {
+ "internalName": "",
+ "displayName": "",
+ },
+ {
+ "internalName": "",
+ "displayName": "",
+ },
+ {
+ "internalName": "",
+ "displayName": "",
+ },
+ {
+ "internalName": "Pointer",
+ "displayName": ""
+ },
+ {
+ "internalName": "Pointer",
+ "displayName": ""
+ },
+ {
+ "internalName": "Pointer",
+ "displayName": ""
+ },
+ {
+ "internalName": "Pointer",
+ "displayName": ""
+ },
+ {
+ "internalName": "Pigscene",
+ "displayName": "",
+ },
+ {
+ "internalName": "Pigscene",
+ "displayName": ""
+ },
+ {
+ "internalName": "Pigscene",
+ "displayName": ""
+ },
+ {
+ "internalName": "Pigscene",
+ "displayName": ""
+ },
+ {
+ "internalName": "BurningSkull",
+ "displayName": "",
+ },
+ {
+ "internalName": "BurningSkull",
+ "displayName": ""
+ },
+ {
+ "internalName": "BurningSkull",
+ "displayName": ""
+ },
+ {
+ "internalName": "BurningSkull",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": "",
+ },
+ {
+ "internalName": "",
+ "displayName": "",
+ },
+ {
+ "internalName": "",
+ "displayName": "",
+ },
+ {
+ "internalName": "",
+ "displayName": "",
+ },
+ {
+ "internalName": "Pointer",
+ "displayName": "",
+ },
+ {
+ "internalName": "Pointer",
+ "displayName": ""
+ },
+ {
+ "internalName": "Pointer",
+ "displayName": ""
+ },
+ {
+ "internalName": "Pointer",
+ "displayName": ""
+ },
+ {
+ "internalName": "Pigscene",
+ "displayName": "",
+ },
+ {
+ "internalName": "Pigscene",
+ "displayName": ""
+ },
+ {
+ "internalName": "Pigscene",
+ "displayName": ""
+ },
+ {
+ "internalName": "Pigscene",
+ "displayName": ""
+ },
+ {
+ "internalName": "BurningSkull",
+ "displayName": "",
+ },
+ {
+ "internalName": "BurningSkull",
+ "displayName": ""
+ },
+ {
+ "internalName": "BurningSkull",
+ "displayName": ""
+ },
+ {
+ "internalName": "BurningSkull",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": "",
+ },
+ {
+ "internalName": "",
+ "displayName": "",
+ },
+ {
+ "internalName": "",
+ "displayName": "",
+ },
+ {
+ "internalName": "",
+ "displayName": "",
+ }
+ ]
+}
diff --git a/PckStudio.Core/Resources/paintings.png b/PckStudio.Core/Resources/paintings.png
new file mode 100644
index 00000000..b8bc84fe
Binary files /dev/null and b/PckStudio.Core/Resources/paintings.png differ
diff --git a/PckStudio.Core/Resources/particleData.json b/PckStudio.Core/Resources/particleData.json
new file mode 100644
index 00000000..924ab98a
--- /dev/null
+++ b/PckStudio.Core/Resources/particleData.json
@@ -0,0 +1,2097 @@
+{
+ "COMMENT_1": "JSON by MattNL",
+ "entries": [
+ {
+ "internalName": "generic_0",
+ "displayName": "Generic (Stage 1)",
+ "colourEntry": {
+ "defaultName": "None",
+ "variants": [
+ "None",
+ "Particle_Smoke",
+ "Particle_NetherPortal",
+ "Particle_EnderPortal",
+ "Particle_Ender",
+ "Particle_DragonBreathMin",
+ "Particle_DragonBreathMax"
+ ]
+ }
+ },
+ {
+ "internalName": "generic_1",
+ "displayName": "Generic (Stage 2)",
+ "colourEntry": {
+ "defaultName": "None",
+ "variants": [
+ "None",
+ "Particle_Smoke",
+ "Particle_NetherPortal",
+ "Particle_EnderPortal",
+ "Particle_Ender",
+ "Particle_DragonBreathMin",
+ "Particle_DragonBreathMax"
+ ]
+ }
+ },
+ {
+ "internalName": "generic_2",
+ "displayName": "Generic (Stage 3)",
+ "colourEntry": {
+ "defaultName": "None",
+ "variants": [
+ "None",
+ "Particle_Smoke",
+ "Particle_NetherPortal",
+ "Particle_EnderPortal",
+ "Particle_Ender",
+ "Particle_DragonBreathMin",
+ "Particle_DragonBreathMax"
+ ]
+ }
+ },
+ {
+ "internalName": "generic_3",
+ "displayName": "Generic (Stage 4)",
+ "colourEntry": {
+ "defaultName": "None",
+ "variants": [
+ "None",
+ "Particle_Smoke",
+ "Particle_NetherPortal",
+ "Particle_EnderPortal",
+ "Particle_Ender",
+ "Particle_DragonBreathMin",
+ "Particle_DragonBreathMax"
+ ]
+ }
+ },
+ {
+ "internalName": "generic_4",
+ "displayName": "Generic (Stage 5)",
+ "colourEntry": {
+ "defaultName": "None",
+ "variants": [
+ "None",
+ "Particle_Smoke",
+ "Particle_NetherPortal",
+ "Particle_EnderPortal",
+ "Particle_Ender",
+ "Particle_DragonBreathMin",
+ "Particle_DragonBreathMax"
+ ]
+ }
+ },
+ {
+ "internalName": "generic_5",
+ "displayName": "Generic (Stage 6)",
+ "colourEntry": {
+ "defaultName": "None",
+ "variants": [
+ "None",
+ "Particle_Smoke",
+ "Particle_NetherPortal",
+ "Particle_EnderPortal",
+ "Particle_Ender",
+ "Particle_DragonBreathMin",
+ "Particle_DragonBreathMax"
+ ]
+ }
+ },
+ {
+ "internalName": "generic_6",
+ "displayName": "Generic (Stage 7)",
+ "colourEntry": {
+ "defaultName": "None",
+ "variants": [
+ "None",
+ "Particle_Smoke",
+ "Particle_NetherPortal",
+ "Particle_EnderPortal",
+ "Particle_Ender",
+ "Particle_DragonBreathMin",
+ "Particle_DragonBreathMax"
+ ]
+ }
+ },
+ {
+ "internalName": "generic_7",
+ "displayName": "Generic (Stage 8)",
+ "colourEntry": {
+ "defaultName": "None",
+ "variants": [
+ "None",
+ "Particle_Smoke",
+ "Particle_NetherPortal",
+ "Particle_EnderPortal",
+ "Particle_Ender",
+ "Particle_DragonBreathMin",
+ "Particle_DragonBreathMax"
+ ]
+ }
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "unused_splash_0",
+ "displayName": "Splash (Stage 1) (Unused)"
+ },
+ {
+ "internalName": "unused_splash_1",
+ "displayName": "Splash (Stage 2) (Unused)"
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "splash_0",
+ "displayName": "Splash (Stage 1)"
+ },
+ {
+ "internalName": "splash_1",
+ "displayName": "Splash (Stage 2)"
+ },
+ {
+ "internalName": "splash_2",
+ "displayName": "Splash (Stage 3)"
+ },
+ {
+ "internalName": "splash_3",
+ "displayName": "Splash (Stage 4)"
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "classic_bubble",
+ "displayName": "Bubble (Unused)"
+ },
+ {
+ "internalName": "bobber",
+ "displayName": "Fishing Bobber"
+ },
+ {
+ "internalName": "bubble",
+ "displayName": "Bubble",
+ "colourEntry": {
+ "isWaterColour": true,
+ "defaultName": "Water_Plains",
+ "variants": [
+ "Water_Ocean",
+ "Water_Plains",
+ "Water_Desert",
+ "Water_ExtremeHills",
+ "Water_Forest",
+ "Water_Taiga",
+ "Water_Swampland",
+ "Water_River",
+ "Water_Hell",
+ "Water_Sky",
+ "Water_FrozenOcean",
+ "Water_FrozenRiver",
+ "Water_IcePlains",
+ "Water_IceMountains",
+ "Water_MushroomIsland",
+ "Water_MushroomIslandShore",
+ "Water_Beach",
+ "Water_DesertHills",
+ "Water_ForestHills",
+ "Water_TaigaHills",
+ "Water_ExtremeHillsEdge",
+ "Water_Jungle",
+ "Water_JungleHills",
+ "Water_JungleEdge",
+ "Water_DeepOcean",
+ "Water_StoneBeach",
+ "Water_ColdBeach",
+ "Water_BirchForest",
+ "Water_BirchForestHills",
+ "Water_RoofedForest",
+ "Water_ColdTaiga",
+ "Water_ColdTaigaHills",
+ "Water_MegaTaiga",
+ "Water_MegaTaigaHills",
+ "Water_ExtremeHillsPlus",
+ "Water_Savanna",
+ "Water_SavannaPlateau",
+ "Water_Mesa",
+ "Water_MesaPlateauF",
+ "Water_MesaPlateau"
+ ]
+ }
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "flash",
+ "displayName": "Firework Flash",
+ "width": 4,
+ "height": 4,
+ "allowCustomColour": true
+ },
+ {
+ "internalName": "flash",
+ "displayName": ""
+ },
+ {
+ "internalName": "flash",
+ "displayName": ""
+ },
+ {
+ "internalName": "flash",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "flame",
+ "displayName": "Flame"
+ },
+ {
+ "internalName": "lava",
+ "displayName": "Lava"
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "flash",
+ "displayName": ""
+ },
+ {
+ "internalName": "flash",
+ "displayName": ""
+ },
+ {
+ "internalName": "flash",
+ "displayName": ""
+ },
+ {
+ "internalName": "flash",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "note",
+ "displayName": "Noteblock Note",
+ "colourEntry": {
+ "defaultName": "Particle_Note_00",
+ "variants": [
+ "Particle_Note_00",
+ "Particle_Note_01",
+ "Particle_Note_02",
+ "Particle_Note_03",
+ "Particle_Note_04",
+ "Particle_Note_05",
+ "Particle_Note_06",
+ "Particle_Note_07",
+ "Particle_Note_08",
+ "Particle_Note_09",
+ "Particle_Note_10",
+ "Particle_Note_11",
+ "Particle_Note_12",
+ "Particle_Note_13",
+ "Particle_Note_14",
+ "Particle_Note_15",
+ "Particle_Note_16",
+ "Particle_Note_17",
+ "Particle_Note_18",
+ "Particle_Note_19",
+ "Particle_Note_20",
+ "Particle_Note_21",
+ "Particle_Note_22",
+ "Particle_Note_23",
+ "Particle_Note_24",
+ ]
+ }
+ },
+ {
+ "internalName": "critical_hit",
+ "displayName": "Critical Hit",
+ "colourEntry": {
+ "defaultName": "critical_hit",
+ "variants": [
+ "critical_hit"
+ ]
+ }
+ },
+ {
+ "internalName": "enchanted_hit",
+ "displayName": "Enchanted Hit",
+ "colourEntry": {
+ "defaultName": "critical_hit",
+ "variants": [
+ "critical_hit"
+ ]
+ }
+ },
+ {
+ "internalName": "damage",
+ "displayName": "Damage Indicator"
+ },
+ {
+ "internalName": "flash",
+ "displayName": ""
+ },
+ {
+ "internalName": "flash",
+ "displayName": ""
+ },
+ {
+ "internalName": "flash",
+ "displayName": ""
+ },
+ {
+ "internalName": "flash",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "heart",
+ "displayName": "Heart"
+ },
+ {
+ "internalName": "angry",
+ "displayName": "Angry"
+ },
+ {
+ "internalName": "glint",
+ "displayName": "Glint"
+ },
+ {
+ "internalName": "angry_villager",
+ "displayName": "Angry Villager (Unused)"
+ },
+ {
+ "internalName": "flash",
+ "displayName": ""
+ },
+ {
+ "internalName": "flash",
+ "displayName": ""
+ },
+ {
+ "internalName": "flash",
+ "displayName": ""
+ },
+ {
+ "internalName": "flash",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "water_0",
+ "displayName": "Water (Stage 1) (Unused)"
+ },
+ {
+ "internalName": "water_1",
+ "displayName": "Water (Stage 2) (Unused)"
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "bubble_pop_0",
+ "displayName": "Bubble Pop (Stage 1) (Unused)",
+ "width": 2,
+ "height": 2
+ },
+ {
+ "internalName": "bubble_pop_0",
+ "displayName": ""
+ },
+ {
+ "internalName": "bubble_pop_1",
+ "displayName": "Bubble Pop (Stage 2) (Unused)",
+ "width": 2,
+ "height": 2
+ },
+ {
+ "internalName": "bubble_pop_1",
+ "displayName": ""
+ },
+ {
+ "internalName": "bubble_pop_2",
+ "displayName": "Bubble Pop (Stage 3) (Unused)",
+ "width": 2,
+ "height": 2
+ },
+ {
+ "internalName": "bubble_pop_2",
+ "displayName": ""
+ },
+ {
+ "internalName": "bubble_pop_3",
+ "displayName": "Bubble Pop (Stage 4) (Unused)",
+ "width": 2,
+ "height": 2
+ },
+ {
+ "internalName": "bubble_pop_3",
+ "displayName": ""
+ },
+ {
+ "internalName": "bubble_pop_4",
+ "displayName": "Bubble Pop (Stage 5) (Unused)",
+ "width": 2,
+ "height": 2
+ },
+ {
+ "internalName": "bubble_pop_4",
+ "displayName": ""
+ },
+ {
+ "internalName": "drip_hang",
+ "displayName": "Drip (Hang)",
+
+ "colourEntry": {
+ "defaultName": "Particle_DripWater",
+ "variants": [
+ "Particle_DripWater",
+ "Particle_DripLavaStart",
+ "Particle_DripLavaEnd"
+ ]
+ }
+ },
+ {
+ "internalName": "drip_fall",
+ "displayName": "Drip (Fall)",
+ "colourEntry": {
+ "defaultName": "Particle_DripWater",
+ "variants": [
+ "Particle_DripWater",
+ "Particle_DripLavaStart",
+ "Particle_DripLavaEnd"
+ ]
+ }
+ },
+ {
+ "internalName": "drip_land",
+ "displayName": "Drip (Land)",
+ "colourEntry": {
+ "defaultName": "Particle_DripWater",
+ "variants": [
+ "Particle_DripWater",
+ "Particle_DripLavaStart",
+ "Particle_DripLavaEnd"
+ ]
+ }
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "bubble_pop_0",
+ "displayName": ""
+ },
+ {
+ "internalName": "bubble_pop_0",
+ "displayName": ""
+ },
+ {
+ "internalName": "bubble_pop_1",
+ "displayName": ""
+ },
+ {
+ "internalName": "bubble_pop_1",
+ "displayName": ""
+ },
+ {
+ "internalName": "bubble_pop_2",
+ "displayName": ""
+ },
+ {
+ "internalName": "bubble_pop_2",
+ "displayName": ""
+ },
+ {
+ "internalName": "bubble_pop_3",
+ "displayName": ""
+ },
+ {
+ "internalName": "bubble_pop_3",
+ "displayName": ""
+ },
+ {
+ "internalName": "bubble_pop_4",
+ "displayName": ""
+ },
+ {
+ "internalName": "bubble_pop_4",
+ "displayName": ""
+ },
+ {
+ "internalName": "effect_0",
+ "displayName": "Effect (Stage 1)",
+
+ "allowCustomColour": true,
+ "colourEntry": {
+ "defaultName": "Potion_BaseColour",
+ "variants": [
+ "Potion_BaseColour",
+ "Effect_MovementSpeed",
+ "Effect_MovementSlowDown",
+ "Effect_DigSpeed",
+ "Effect_DigSlowdown",
+ "Effect_DamageBoost",
+ "Effect_Heal",
+ "Effect_Harm",
+ "Effect_Jump",
+ "Effect_Confusion",
+ "Effect_Regeneration",
+ "Effect_DamageResistance",
+ "Effect_FireResistance",
+ "Effect_WaterBreathing",
+ "Effect_Invisibility",
+ "Effect_Blindness",
+ "Effect_NightVision",
+ "Effect_Hunger",
+ "Effect_Weakness",
+ "Effect_Poison",
+ "Effect_Wither",
+ "Effect_HealthBoost",
+ "Effect_Absorption",
+ "Effect_Saturation",
+ "Effect_Levitation",
+ "Effect_Luck",
+ "Effect_BadLuck",
+ "Effect_TurtleMaster",
+ "Effect_SlowFall"
+ ]
+ }
+ },
+ {
+ "internalName": "effect_1",
+ "displayName": "Effect (Stage 2)",
+
+ "allowCustomColour": true,
+ "colourEntry": {
+ "defaultName": "Potion_BaseColour",
+ "variants": [
+ "Potion_BaseColour",
+ "Effect_MovementSpeed",
+ "Effect_MovementSlowDown",
+ "Effect_DigSpeed",
+ "Effect_DigSlowdown",
+ "Effect_DamageBoost",
+ "Effect_Heal",
+ "Effect_Harm",
+ "Effect_Jump",
+ "Effect_Confusion",
+ "Effect_Regeneration",
+ "Effect_DamageResistance",
+ "Effect_FireResistance",
+ "Effect_WaterBreathing",
+ "Effect_Invisibility",
+ "Effect_Blindness",
+ "Effect_NightVision",
+ "Effect_Hunger",
+ "Effect_Weakness",
+ "Effect_Poison",
+ "Effect_Wither",
+ "Effect_HealthBoost",
+ "Effect_Absorption",
+ "Effect_Saturation",
+ "Effect_Levitation",
+ "Effect_Luck",
+ "Effect_BadLuck",
+ "Effect_TurtleMaster",
+ "Effect_SlowFall"
+ ]
+ }
+ },
+ {
+ "internalName": "effect_2",
+ "displayName": "Effect (Stage 3)",
+ "allowCustomColour": true,
+
+ "colourEntry": {
+ "defaultName": "Potion_BaseColour",
+ "variants": [
+ "Potion_BaseColour",
+ "Effect_MovementSpeed",
+ "Effect_MovementSlowDown",
+ "Effect_DigSpeed",
+ "Effect_DigSlowdown",
+ "Effect_DamageBoost",
+ "Effect_Heal",
+ "Effect_Harm",
+ "Effect_Jump",
+ "Effect_Confusion",
+ "Effect_Regeneration",
+ "Effect_DamageResistance",
+ "Effect_FireResistance",
+ "Effect_WaterBreathing",
+ "Effect_Invisibility",
+ "Effect_Blindness",
+ "Effect_NightVision",
+ "Effect_Hunger",
+ "Effect_Weakness",
+ "Effect_Poison",
+ "Effect_Wither",
+ "Effect_HealthBoost",
+ "Effect_Absorption",
+ "Effect_Saturation",
+ "Effect_Levitation",
+ "Effect_Luck",
+ "Effect_BadLuck",
+ "Effect_TurtleMaster",
+ "Effect_SlowFall"
+ ]
+ }
+ },
+ {
+ "internalName": "effect_3",
+ "displayName": "Effect (Stage 4)",
+ "allowCustomColour": true,
+
+ "colourEntry": {
+ "defaultName": "Potion_BaseColour",
+ "variants": [
+ "Potion_BaseColour",
+ "Effect_MovementSpeed",
+ "Effect_MovementSlowDown",
+ "Effect_DigSpeed",
+ "Effect_DigSlowdown",
+ "Effect_DamageBoost",
+ "Effect_Heal",
+ "Effect_Harm",
+ "Effect_Jump",
+ "Effect_Confusion",
+ "Effect_Regeneration",
+ "Effect_DamageResistance",
+ "Effect_FireResistance",
+ "Effect_WaterBreathing",
+ "Effect_Invisibility",
+ "Effect_Blindness",
+ "Effect_NightVision",
+ "Effect_Hunger",
+ "Effect_Weakness",
+ "Effect_Poison",
+ "Effect_Wither",
+ "Effect_HealthBoost",
+ "Effect_Absorption",
+ "Effect_Saturation",
+ "Effect_Levitation",
+ "Effect_Luck",
+ "Effect_BadLuck",
+ "Effect_TurtleMaster",
+ "Effect_SlowFall"
+ ]
+ }
+ },
+ {
+ "internalName": "effect_4",
+ "displayName": "Effect (Stage 5)",
+ "allowCustomColour": true,
+
+ "colourEntry": {
+ "defaultName": "Potion_BaseColour",
+ "variants": [
+ "Potion_BaseColour",
+ "Effect_MovementSpeed",
+ "Effect_MovementSlowDown",
+ "Effect_DigSpeed",
+ "Effect_DigSlowdown",
+ "Effect_DamageBoost",
+ "Effect_Heal",
+ "Effect_Harm",
+ "Effect_Jump",
+ "Effect_Confusion",
+ "Effect_Regeneration",
+ "Effect_DamageResistance",
+ "Effect_FireResistance",
+ "Effect_WaterBreathing",
+ "Effect_Invisibility",
+ "Effect_Blindness",
+ "Effect_NightVision",
+ "Effect_Hunger",
+ "Effect_Weakness",
+ "Effect_Poison",
+ "Effect_Wither",
+ "Effect_HealthBoost",
+ "Effect_Absorption",
+ "Effect_Saturation",
+ "Effect_Levitation",
+ "Effect_Luck",
+ "Effect_BadLuck",
+ "Effect_TurtleMaster",
+ "Effect_SlowFall"
+ ]
+ }
+ },
+ {
+ "internalName": "effect_5",
+ "displayName": "Effect (Stage 6)",
+ "allowCustomColour": true,
+
+ "colourEntry": {
+ "defaultName": "Potion_BaseColour",
+ "variants": [
+ "Potion_BaseColour",
+ "Effect_MovementSpeed",
+ "Effect_MovementSlowDown",
+ "Effect_DigSpeed",
+ "Effect_DigSlowdown",
+ "Effect_DamageBoost",
+ "Effect_Heal",
+ "Effect_Harm",
+ "Effect_Jump",
+ "Effect_Confusion",
+ "Effect_Regeneration",
+ "Effect_DamageResistance",
+ "Effect_FireResistance",
+ "Effect_WaterBreathing",
+ "Effect_Invisibility",
+ "Effect_Blindness",
+ "Effect_NightVision",
+ "Effect_Hunger",
+ "Effect_Weakness",
+ "Effect_Poison",
+ "Effect_Wither",
+ "Effect_HealthBoost",
+ "Effect_Absorption",
+ "Effect_Saturation",
+ "Effect_Levitation",
+ "Effect_Luck",
+ "Effect_BadLuck",
+ "Effect_TurtleMaster",
+ "Effect_SlowFall"
+ ]
+ }
+ },
+ {
+ "internalName": "effect_6",
+ "displayName": "Effect (Stage 7)",
+ "allowCustomColour": true,
+
+ "colourEntry": {
+ "defaultName": "Potion_BaseColour",
+ "variants": [
+ "Potion_BaseColour",
+ "Effect_MovementSpeed",
+ "Effect_MovementSlowDown",
+ "Effect_DigSpeed",
+ "Effect_DigSlowdown",
+ "Effect_DamageBoost",
+ "Effect_Heal",
+ "Effect_Harm",
+ "Effect_Jump",
+ "Effect_Confusion",
+ "Effect_Regeneration",
+ "Effect_DamageResistance",
+ "Effect_FireResistance",
+ "Effect_WaterBreathing",
+ "Effect_Invisibility",
+ "Effect_Blindness",
+ "Effect_NightVision",
+ "Effect_Hunger",
+ "Effect_Weakness",
+ "Effect_Poison",
+ "Effect_Wither",
+ "Effect_HealthBoost",
+ "Effect_Absorption",
+ "Effect_Saturation",
+ "Effect_Levitation",
+ "Effect_Luck",
+ "Effect_BadLuck",
+ "Effect_TurtleMaster",
+ "Effect_SlowFall"
+ ]
+ }
+ },
+ {
+ "internalName": "effect_7",
+ "displayName": "Effect (Stage 8)",
+ "allowCustomColour": true,
+
+ "colourEntry": {
+ "defaultName": "Potion_BaseColour",
+ "variants": [
+ "Potion_BaseColour",
+ "Effect_MovementSpeed",
+ "Effect_MovementSlowDown",
+ "Effect_DigSpeed",
+ "Effect_DigSlowdown",
+ "Effect_DamageBoost",
+ "Effect_Heal",
+ "Effect_Harm",
+ "Effect_Jump",
+ "Effect_Confusion",
+ "Effect_Regeneration",
+ "Effect_DamageResistance",
+ "Effect_FireResistance",
+ "Effect_WaterBreathing",
+ "Effect_Invisibility",
+ "Effect_Blindness",
+ "Effect_NightVision",
+ "Effect_Hunger",
+ "Effect_Weakness",
+ "Effect_Poison",
+ "Effect_Wither",
+ "Effect_HealthBoost",
+ "Effect_Absorption",
+ "Effect_Saturation",
+ "Effect_Levitation",
+ "Effect_Luck",
+ "Effect_BadLuck",
+ "Effect_TurtleMaster",
+ "Effect_SlowFall"
+ ]
+ }
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "spell_0",
+ "displayName": "Splash Effect (Stage 1)",
+ "allowCustomColour": true,
+
+ "colourEntry": {
+ "defaultName": "Potion_BaseColour",
+ "variants": [
+ "Potion_BaseColour",
+ "Effect_MovementSpeed",
+ "Effect_MovementSlowDown",
+ "Effect_DigSpeed",
+ "Effect_DigSlowdown",
+ "Effect_DamageBoost",
+ "Effect_Heal",
+ "Effect_Harm",
+ "Effect_Jump",
+ "Effect_Confusion",
+ "Effect_Regeneration",
+ "Effect_DamageResistance",
+ "Effect_FireResistance",
+ "Effect_WaterBreathing",
+ "Effect_Invisibility",
+ "Effect_Blindness",
+ "Effect_NightVision",
+ "Effect_Hunger",
+ "Effect_Weakness",
+ "Effect_Poison",
+ "Effect_Wither",
+ "Effect_HealthBoost",
+ "Effect_Absorption",
+ "Effect_Saturation",
+ "Effect_Levitation",
+ "Effect_Luck",
+ "Effect_BadLuck",
+ "Effect_TurtleMaster",
+ "Effect_SlowFall"
+ ]
+ }
+ },
+ {
+ "internalName": "spell_1",
+ "displayName": "Splash Effect (Stage 2)",
+ "allowCustomColour": true,
+
+ "colourEntry": {
+ "defaultName": "Potion_BaseColour",
+ "variants": [
+ "Potion_BaseColour",
+ "Effect_MovementSpeed",
+ "Effect_MovementSlowDown",
+ "Effect_DigSpeed",
+ "Effect_DigSlowdown",
+ "Effect_DamageBoost",
+ "Effect_Heal",
+ "Effect_Harm",
+ "Effect_Jump",
+ "Effect_Confusion",
+ "Effect_Regeneration",
+ "Effect_DamageResistance",
+ "Effect_FireResistance",
+ "Effect_WaterBreathing",
+ "Effect_Invisibility",
+ "Effect_Blindness",
+ "Effect_NightVision",
+ "Effect_Hunger",
+ "Effect_Weakness",
+ "Effect_Poison",
+ "Effect_Wither",
+ "Effect_HealthBoost",
+ "Effect_Absorption",
+ "Effect_Saturation",
+ "Effect_Levitation",
+ "Effect_Luck",
+ "Effect_BadLuck",
+ "Effect_TurtleMaster",
+ "Effect_SlowFall"
+ ]
+ }
+ },
+ {
+ "internalName": "spell_2",
+ "displayName": "Splash Effect (Stage 3)",
+ "allowCustomColour": true,
+
+ "colourEntry": {
+ "defaultName": "Potion_BaseColour",
+ "variants": [
+ "Potion_BaseColour",
+ "Effect_MovementSpeed",
+ "Effect_MovementSlowDown",
+ "Effect_DigSpeed",
+ "Effect_DigSlowdown",
+ "Effect_DamageBoost",
+ "Effect_Heal",
+ "Effect_Harm",
+ "Effect_Jump",
+ "Effect_Confusion",
+ "Effect_Regeneration",
+ "Effect_DamageResistance",
+ "Effect_FireResistance",
+ "Effect_WaterBreathing",
+ "Effect_Invisibility",
+ "Effect_Blindness",
+ "Effect_NightVision",
+ "Effect_Hunger",
+ "Effect_Weakness",
+ "Effect_Poison",
+ "Effect_Wither",
+ "Effect_HealthBoost",
+ "Effect_Absorption",
+ "Effect_Saturation",
+ "Effect_Levitation",
+ "Effect_Luck",
+ "Effect_BadLuck",
+ "Effect_TurtleMaster",
+ "Effect_SlowFall"
+ ]
+ }
+ },
+ {
+ "internalName": "spell_3",
+ "displayName": "Splash Effect (Stage 4)",
+ "allowCustomColour": true,
+
+ "colourEntry": {
+ "defaultName": "Potion_BaseColour",
+ "variants": [
+ "Potion_BaseColour",
+ "Effect_MovementSpeed",
+ "Effect_MovementSlowDown",
+ "Effect_DigSpeed",
+ "Effect_DigSlowdown",
+ "Effect_DamageBoost",
+ "Effect_Heal",
+ "Effect_Harm",
+ "Effect_Jump",
+ "Effect_Confusion",
+ "Effect_Regeneration",
+ "Effect_DamageResistance",
+ "Effect_FireResistance",
+ "Effect_WaterBreathing",
+ "Effect_Invisibility",
+ "Effect_Blindness",
+ "Effect_NightVision",
+ "Effect_Hunger",
+ "Effect_Weakness",
+ "Effect_Poison",
+ "Effect_Wither",
+ "Effect_HealthBoost",
+ "Effect_Absorption",
+ "Effect_Saturation",
+ "Effect_Levitation",
+ "Effect_Luck",
+ "Effect_BadLuck",
+ "Effect_TurtleMaster",
+ "Effect_SlowFall"
+ ]
+ }
+ },
+ {
+ "internalName": "spell_4",
+ "displayName": "Splash Effect (Stage 5)",
+ "allowCustomColour": true,
+
+ "colourEntry": {
+ "defaultName": "Potion_BaseColour",
+ "variants": [
+ "Potion_BaseColour",
+ "Effect_MovementSpeed",
+ "Effect_MovementSlowDown",
+ "Effect_DigSpeed",
+ "Effect_DigSlowdown",
+ "Effect_DamageBoost",
+ "Effect_Heal",
+ "Effect_Harm",
+ "Effect_Jump",
+ "Effect_Confusion",
+ "Effect_Regeneration",
+ "Effect_DamageResistance",
+ "Effect_FireResistance",
+ "Effect_WaterBreathing",
+ "Effect_Invisibility",
+ "Effect_Blindness",
+ "Effect_NightVision",
+ "Effect_Hunger",
+ "Effect_Weakness",
+ "Effect_Poison",
+ "Effect_Wither",
+ "Effect_HealthBoost",
+ "Effect_Absorption",
+ "Effect_Saturation",
+ "Effect_Levitation",
+ "Effect_Luck",
+ "Effect_BadLuck",
+ "Effect_TurtleMaster",
+ "Effect_SlowFall"
+ ]
+ }
+ },
+ {
+ "internalName": "spell_5",
+ "displayName": "Splash Effect (Stage 6)",
+ "allowCustomColour": true,
+
+ "colourEntry": {
+ "defaultName": "Potion_BaseColour",
+ "variants": [
+ "Potion_BaseColour",
+ "Effect_MovementSpeed",
+ "Effect_MovementSlowDown",
+ "Effect_DigSpeed",
+ "Effect_DigSlowdown",
+ "Effect_DamageBoost",
+ "Effect_Heal",
+ "Effect_Harm",
+ "Effect_Jump",
+ "Effect_Confusion",
+ "Effect_Regeneration",
+ "Effect_DamageResistance",
+ "Effect_FireResistance",
+ "Effect_WaterBreathing",
+ "Effect_Invisibility",
+ "Effect_Blindness",
+ "Effect_NightVision",
+ "Effect_Hunger",
+ "Effect_Weakness",
+ "Effect_Poison",
+ "Effect_Wither",
+ "Effect_HealthBoost",
+ "Effect_Absorption",
+ "Effect_Saturation",
+ "Effect_Levitation",
+ "Effect_Luck",
+ "Effect_BadLuck",
+ "Effect_TurtleMaster",
+ "Effect_SlowFall"
+ ]
+ }
+ },
+ {
+ "internalName": "spell_6",
+ "displayName": "Splash Effect (Stage 7)",
+ "allowCustomColour": true,
+
+ "colourEntry": {
+ "defaultName": "Potion_BaseColour",
+ "variants": [
+ "Potion_BaseColour",
+ "Effect_MovementSpeed",
+ "Effect_MovementSlowDown",
+ "Effect_DigSpeed",
+ "Effect_DigSlowdown",
+ "Effect_DamageBoost",
+ "Effect_Heal",
+ "Effect_Harm",
+ "Effect_Jump",
+ "Effect_Confusion",
+ "Effect_Regeneration",
+ "Effect_DamageResistance",
+ "Effect_FireResistance",
+ "Effect_WaterBreathing",
+ "Effect_Invisibility",
+ "Effect_Blindness",
+ "Effect_NightVision",
+ "Effect_Hunger",
+ "Effect_Weakness",
+ "Effect_Poison",
+ "Effect_Wither",
+ "Effect_HealthBoost",
+ "Effect_Absorption",
+ "Effect_Saturation",
+ "Effect_Levitation",
+ "Effect_Luck",
+ "Effect_BadLuck",
+ "Effect_TurtleMaster",
+ "Effect_SlowFall"
+ ]
+ }
+ },
+ {
+ "internalName": "spell_7",
+ "displayName": "Splash Effect (Stage 8)",
+ "allowCustomColour": true,
+
+ "colourEntry": {
+ "defaultName": "Potion_BaseColour",
+ "variants": [
+ "Potion_BaseColour",
+ "Effect_MovementSpeed",
+ "Effect_MovementSlowDown",
+ "Effect_DigSpeed",
+ "Effect_DigSlowdown",
+ "Effect_DamageBoost",
+ "Effect_Heal",
+ "Effect_Harm",
+ "Effect_Jump",
+ "Effect_Confusion",
+ "Effect_Regeneration",
+ "Effect_DamageResistance",
+ "Effect_FireResistance",
+ "Effect_WaterBreathing",
+ "Effect_Invisibility",
+ "Effect_Blindness",
+ "Effect_NightVision",
+ "Effect_Hunger",
+ "Effect_Weakness",
+ "Effect_Poison",
+ "Effect_Wither",
+ "Effect_HealthBoost",
+ "Effect_Absorption",
+ "Effect_Saturation",
+ "Effect_Levitation",
+ "Effect_Luck",
+ "Effect_BadLuck",
+ "Effect_TurtleMaster",
+ "Effect_SlowFall"
+ ]
+ }
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "spark_0",
+ "displayName": "Firework Spark (Stage 1)",
+ "allowCustomColour": true,
+
+ "colourEntry": {
+ "defaultName": "None",
+ "variants": [
+ "None",
+ "Particle_ScoreRing_Small",
+ "Particle_ScoreRing_Medium",
+ "Particle_ScoreRing_Large"
+ ]
+ }
+ },
+ {
+ "internalName": "spark_1",
+ "displayName": "Firework Spark (Stage 2)",
+ "allowCustomColour": true,
+
+ "colourEntry": {
+ "defaultName": "None",
+ "variants": [
+ "None",
+ "Particle_ScoreRing_Small",
+ "Particle_ScoreRing_Medium",
+ "Particle_ScoreRing_Large"
+ ]
+ }
+ },
+ {
+ "internalName": "spark_2",
+ "displayName": "Firework Spark (Stage 3)",
+ "allowCustomColour": true,
+
+ "colourEntry": {
+ "defaultName": "None",
+ "variants": [
+ "None",
+ "Particle_ScoreRing_Small",
+ "Particle_ScoreRing_Medium",
+ "Particle_ScoreRing_Large"
+ ]
+ }
+ },
+ {
+ "internalName": "spark_3",
+ "displayName": "Firework Spark (Stage 4)",
+ "allowCustomColour": true,
+
+ "colourEntry": {
+ "defaultName": "None",
+ "variants": [
+ "None",
+ "Particle_ScoreRing_Small",
+ "Particle_ScoreRing_Medium",
+ "Particle_ScoreRing_Large"
+ ]
+ }
+ },
+ {
+ "internalName": "spark_4",
+ "displayName": "Firework Spark (Stage 5)",
+ "allowCustomColour": true,
+
+ "colourEntry": {
+ "defaultName": "None",
+ "variants": [
+ "None",
+ "Particle_ScoreRing_Small",
+ "Particle_ScoreRing_Medium",
+ "Particle_ScoreRing_Large"
+ ]
+ }
+ },
+ {
+ "internalName": "spark_5",
+ "displayName": "Firework Spark (Stage 6)",
+ "allowCustomColour": true,
+
+ "colourEntry": {
+ "defaultName": "None",
+ "variants": [
+ "None",
+ "Particle_ScoreRing_Small",
+ "Particle_ScoreRing_Medium",
+ "Particle_ScoreRing_Large"
+ ]
+ }
+ },
+ {
+ "internalName": "spark_6",
+ "displayName": "Firework Spark (Stage 7)",
+ "allowCustomColour": true,
+
+ "colourEntry": {
+ "defaultName": "None",
+ "variants": [
+ "None",
+ "Particle_ScoreRing_Small",
+ "Particle_ScoreRing_Medium",
+ "Particle_ScoreRing_Large"
+ ]
+ }
+ },
+ {
+ "internalName": "spark_7",
+ "displayName": "Firework Spark (Stage 8)",
+ "allowCustomColour": true,
+
+ "colourEntry": {
+ "defaultName": "None",
+ "variants": [
+ "None",
+ "Particle_ScoreRing_Small",
+ "Particle_ScoreRing_Medium",
+ "Particle_ScoreRing_Large"
+ ]
+ }
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "glitter_0",
+ "displayName": "Shulker/End Rod Glitter (Stage 1)"
+ },
+ {
+ "internalName": "glitter_1",
+ "displayName": "Shulker/End Rod Glitter (Stage 2)"
+ },
+ {
+ "internalName": "glitter_2",
+ "displayName": "Shulker/End Rod Glitter (Stage 3)"
+ },
+ {
+ "internalName": "glitter_3",
+ "displayName": "Shulker/End Rod Glitter (Stage 4)"
+ },
+ {
+ "internalName": "glitter_4",
+ "displayName": "Shulker/End Rod Glitter (Stage 5)"
+ },
+ {
+ "internalName": "glitter_5",
+ "displayName": "Shulker/End Rod Glitter (Stage 6)"
+ },
+ {
+ "internalName": "glitter_6",
+ "displayName": "Shulker/End Rod Glitter (Stage 7)"
+ },
+ {
+ "internalName": "glitter_7",
+ "displayName": "Shulker/End Rod Glitter (Stage 8)"
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "camera_shoot_explosion_0",
+ "displayName": "Bedrock Edition Explosion (Unused) (Stage 1)"
+ },
+ {
+ "internalName": "camera_shoot_explosion_1",
+ "displayName": "Bedrock Edition Explosion (Unused) (Stage 2)"
+ },
+ {
+ "internalName": "camera_shoot_explosion_2",
+ "displayName": "Bedrock Edition Explosion (Unused) (Stage 3)"
+ },
+ {
+ "internalName": "camera_shoot_explosion_3",
+ "displayName": "Bedrock Edition Explosion (Unused) (Stage 4)"
+ },
+ {
+ "internalName": "camera_shoot_explosion_4",
+ "displayName": "Bedrock Edition Explosion (Unused) (Stage 5)"
+ },
+ {
+ "internalName": "camera_shoot_explosion_5",
+ "displayName": "Bedrock Edition Explosion (Unused) (Stage 6)"
+ },
+ {
+ "internalName": "camera_shoot_explosion_6",
+ "displayName": "Bedrock Edition Explosion (Unused) (Stage 7)"
+ },
+ {
+ "internalName": "camera_shoot_explosion_7",
+ "displayName": "Bedrock Edition Explosion (Unused) (Stage 8)"
+ },
+ {
+ "internalName": "camera_shoot_explosion_8",
+ "displayName": "Bedrock Edition Explosion (Unused) (Stage 9)"
+ },
+ {
+ "internalName": "camera_shoot_explosion_9",
+ "displayName": "Bedrock Edition Explosion (Unused) (Stage 10)"
+ },
+ {
+ "internalName": "camera_shoot_explosion_10",
+ "displayName": "Bedrock Edition Explosion (Unused) (Stage 11)"
+ },
+ {
+ "internalName": "camera_shoot_explosion_11",
+ "displayName": "Bedrock Edition Explosion (Unused) (Stage 12)"
+ },
+ {
+ "internalName": "camera_shoot_explosion_12",
+ "displayName": "Bedrock Edition Explosion (Unused) (Stage 13)"
+ },
+ {
+ "internalName": "camera_shoot_explosion_13",
+ "displayName": "Bedrock Edition Explosion (Unused) (Stage 14)"
+ },
+ {
+ "internalName": "camera_shoot_explosion_14",
+ "displayName": "Bedrock Edition Explosion (Unused) (Stage 15)"
+ },
+ {
+ "internalName": "camera_shoot_explosion_15",
+ "displayName": "Bedrock Edition Explosion (Unused) (Stage 16)"
+ },
+ {
+ "internalName": "conduit_0",
+ "displayName": "Conduit (Stage 1)"
+ },
+ {
+ "internalName": "conduit_1",
+ "displayName": "Conduit (Stage 2)"
+ },
+ {
+ "internalName": "conduit_2",
+ "displayName": "Conduit (Stage 3)"
+ },
+ {
+ "internalName": "conduit_3",
+ "displayName": "Conduit (Stage 4)"
+ },
+ {
+ "internalName": "conduit_4",
+ "displayName": "Conduit (Stage 5)"
+ },
+ {
+ "internalName": "conduit_5",
+ "displayName": "Conduit (Stage 6)"
+ },
+ {
+ "internalName": "conduit_6",
+ "displayName": "Conduit (Stage 7)"
+ },
+ {
+ "internalName": "conduit_7",
+ "displayName": "Conduit (Stage 8)"
+ },
+ {
+ "internalName": "conduit_8",
+ "displayName": "Conduit (Stage 9)"
+ },
+ {
+ "internalName": "conduit_9",
+ "displayName": "Conduit (Stage 10)"
+ },
+ {
+ "internalName": "conduit_10",
+ "displayName": "Conduit (Stage 11)"
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "sga_a",
+ "displayName": "Standard Galactic Language (A)",
+
+ "colourEntry": {
+ "defaultName": "Particle_EnchantmentTable",
+ "variants": [
+ "Particle_EnchantmentTable"
+ ]
+ }
+ },
+ {
+ "internalName": "sga_b",
+ "displayName": "Standard Galactic Language (B)",
+
+ "colourEntry": {
+ "defaultName": "Particle_EnchantmentTable",
+ "variants": [
+ "Particle_EnchantmentTable"
+ ]
+ }
+ },
+ {
+ "internalName": "sga_c",
+ "displayName": "Standard Galactic Language (C)",
+
+ "colourEntry": {
+ "defaultName": "Particle_EnchantmentTable",
+ "variants": [
+ "Particle_EnchantmentTable"
+ ]
+ }
+ },
+ {
+ "internalName": "sga_d",
+ "displayName": "Standard Galactic Language (D)",
+
+ "colourEntry": {
+ "defaultName": "Particle_EnchantmentTable",
+ "variants": [
+ "Particle_EnchantmentTable"
+ ]
+ }
+ },
+ {
+ "internalName": "sga_e",
+ "displayName": "Standard Galactic Language (E)",
+
+ "colourEntry": {
+ "defaultName": "Particle_EnchantmentTable",
+ "variants": [
+ "Particle_EnchantmentTable"
+ ]
+ }
+ },
+ {
+ "internalName": "sga_f",
+ "displayName": "Standard Galactic Language (F)",
+
+ "colourEntry": {
+ "defaultName": "Particle_EnchantmentTable",
+ "variants": [
+ "Particle_EnchantmentTable"
+ ]
+ }
+ },
+ {
+ "internalName": "sga_g",
+ "displayName": "Standard Galactic Language (G)",
+
+ "colourEntry": {
+ "defaultName": "Particle_EnchantmentTable",
+ "variants": [
+ "Particle_EnchantmentTable"
+ ]
+ }
+ },
+ {
+ "internalName": "sga_h",
+ "displayName": "Standard Galactic Language (H)",
+
+ "colourEntry": {
+ "defaultName": "Particle_EnchantmentTable",
+ "variants": [
+ "Particle_EnchantmentTable"
+ ]
+ }
+ },
+ {
+ "internalName": "sga_i",
+ "displayName": "Standard Galactic Language (I)",
+
+ "colourEntry": {
+ "defaultName": "Particle_EnchantmentTable",
+ "variants": [
+ "Particle_EnchantmentTable"
+ ]
+ }
+ },
+ {
+ "internalName": "sga_j",
+ "displayName": "Standard Galactic Language (J)",
+
+ "colourEntry": {
+ "defaultName": "Particle_EnchantmentTable",
+ "variants": [
+ "Particle_EnchantmentTable"
+ ]
+ }
+ },
+ {
+ "internalName": "sga_k",
+ "displayName": "Standard Galactic Language (K)",
+
+ "colourEntry": {
+ "defaultName": "Particle_EnchantmentTable",
+ "variants": [
+ "Particle_EnchantmentTable"
+ ]
+ }
+ },
+ {
+ "internalName": "sga_l",
+ "displayName": "Standard Galactic Language (L)",
+
+ "colourEntry": {
+ "defaultName": "Particle_EnchantmentTable",
+ "variants": [
+ "Particle_EnchantmentTable"
+ ]
+ }
+ },
+ {
+ "internalName": "sga_m",
+ "displayName": "Standard Galactic Language (M)",
+
+ "colourEntry": {
+ "defaultName": "Particle_EnchantmentTable",
+ "variants": [
+ "Particle_EnchantmentTable"
+ ]
+ }
+ },
+ {
+ "internalName": "sga_n",
+ "displayName": "Standard Galactic Language (N)",
+
+ "colourEntry": {
+ "defaultName": "Particle_EnchantmentTable",
+ "variants": [
+ "Particle_EnchantmentTable"
+ ]
+ }
+ },
+ {
+ "internalName": "sga_o",
+ "displayName": "Standard Galactic Language (O)",
+
+ "colourEntry": {
+ "defaultName": "Particle_EnchantmentTable",
+ "variants": [
+ "Particle_EnchantmentTable"
+ ]
+ }
+ },
+ {
+ "internalName": "sga_p",
+ "displayName": "Standard Galactic Language (P)",
+
+ "colourEntry": {
+ "defaultName": "Particle_EnchantmentTable",
+ "variants": [
+ "Particle_EnchantmentTable"
+ ]
+ }
+ },
+ {
+ "internalName": "sga_q",
+ "displayName": "Standard Galactic Language (Q)",
+
+ "colourEntry": {
+ "defaultName": "Particle_EnchantmentTable",
+ "variants": [
+ "Particle_EnchantmentTable"
+ ]
+ }
+ },
+ {
+ "internalName": "sga_r",
+ "displayName": "Standard Galactic Language (R)",
+
+ "colourEntry": {
+ "defaultName": "Particle_EnchantmentTable",
+ "variants": [
+ "Particle_EnchantmentTable"
+ ]
+ }
+ },
+ {
+ "internalName": "sga_s",
+ "displayName": "Standard Galactic Language (S)",
+
+ "colourEntry": {
+ "defaultName": "Particle_EnchantmentTable",
+ "variants": [
+ "Particle_EnchantmentTable"
+ ]
+ }
+ },
+ {
+ "internalName": "sga_t",
+ "displayName": "Standard Galactic Language (T)",
+
+ "colourEntry": {
+ "defaultName": "Particle_EnchantmentTable",
+ "variants": [
+ "Particle_EnchantmentTable"
+ ]
+ }
+ },
+ {
+ "internalName": "sga_u",
+ "displayName": "Standard Galactic Language (U)",
+
+ "colourEntry": {
+ "defaultName": "Particle_EnchantmentTable",
+ "variants": [
+ "Particle_EnchantmentTable"
+ ]
+ }
+ },
+ {
+ "internalName": "sga_v",
+ "displayName": "Standard Galactic Language (V)",
+
+ "colourEntry": {
+ "defaultName": "Particle_EnchantmentTable",
+ "variants": [
+ "Particle_EnchantmentTable"
+ ]
+ }
+ },
+ {
+ "internalName": "sga_w",
+ "displayName": "Standard Galactic Language (W)",
+
+ "colourEntry": {
+ "defaultName": "Particle_EnchantmentTable",
+ "variants": [
+ "Particle_EnchantmentTable"
+ ]
+ }
+ },
+ {
+ "internalName": "sga_x",
+ "displayName": "Standard Galactic Language (X)",
+
+ "colourEntry": {
+ "defaultName": "Particle_EnchantmentTable",
+ "variants": [
+ "Particle_EnchantmentTable"
+ ]
+ }
+ },
+ {
+ "internalName": "sga_y",
+ "displayName": "Standard Galactic Language (Y)",
+
+ "colourEntry": {
+ "defaultName": "Particle_EnchantmentTable",
+ "variants": [
+ "Particle_EnchantmentTable"
+ ]
+ }
+ },
+ {
+ "internalName": "sga_z",
+ "displayName": "Standard Galactic Language (Z)",
+
+ "colourEntry": {
+ "defaultName": "Particle_EnchantmentTable",
+ "variants": [
+ "Particle_EnchantmentTable"
+ ]
+ }
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ {
+ "internalName": "",
+ "displayName": ""
+ },
+ ]
+}
\ No newline at end of file
diff --git a/PckStudio.Core/Resources/particles.png b/PckStudio.Core/Resources/particles.png
new file mode 100644
index 00000000..b4f1e1f6
Binary files /dev/null and b/PckStudio.Core/Resources/particles.png differ
diff --git a/PckStudio.Core/Resources/terrain.png b/PckStudio.Core/Resources/terrain.png
new file mode 100644
index 00000000..9b6d1791
Binary files /dev/null and b/PckStudio.Core/Resources/terrain.png differ
diff --git a/PckStudio.Rendering/TextureChangingEventArgs.cs b/PckStudio.Rendering/TextureChangingEventArgs.cs
index 6174e509..af9cbe7f 100644
--- a/PckStudio.Rendering/TextureChangingEventArgs.cs
+++ b/PckStudio.Rendering/TextureChangingEventArgs.cs
@@ -18,6 +18,7 @@
using System.ComponentModel;
using System.Drawing;
+<<<<<<<< HEAD:PckStudio.Rendering/TextureChangingEventArgs.cs
namespace PckStudio.Rendering
{
public class TextureChangingEventArgs : CancelEventArgs
@@ -28,5 +29,26 @@ namespace PckStudio.Rendering
{
NewTexture = newTexture;
}
+========
+namespace PckStudio.Core
+{
+ public enum ResourceCategory
+ {
+ Unknown = -1,
+ ItemAnimation,
+ BlockAnimation,
+ MobEntityTextures,
+ ItemEntityTextures,
+ ItemAtlas,
+ BlockAtlas,
+ ParticleAtlas,
+ BannerAtlas,
+ PaintingAtlas,
+ ExplosionAtlas,
+ ExperienceOrbAtlas,
+ MoonPhaseAtlas,
+ MapIconAtlas,
+ AdditionalMapIconsAtlas,
+>>>>>>>> main:PckStudio.Core/ResourceCategory.cs
}
}
\ No newline at end of file
diff --git a/PckStuido.ModelSupport/Extension/SkinExtension.cs b/PckStuido.ModelSupport/Extension/SkinExtension.cs
new file mode 100644
index 00000000..3dcf6492
--- /dev/null
+++ b/PckStuido.ModelSupport/Extension/SkinExtension.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using OMI.Formats.Model;
+using PckStudio.Core.Skin;
+using PckStudio.ModelSupport;
+
+namespace PckStuido.ModelSupport.Extension
+{
+ public static class SkinExtension
+ {
+ public static SkinModelInfo GetModelInfo(this Skin skin) => new SkinModelInfo(skin.Texture, skin.Anim, skin.Model);
+
+ public static void SetModelInfo(this Skin skin, SkinModelInfo modelInfo)
+ {
+ skin.Texture = modelInfo.Texture;
+ skin.Anim = modelInfo.Anim;
+ skin.Model = modelInfo.Model;
+ }
+ }
+}
diff --git a/PckStuido.ModelSupport/Format/External/BedrockLegacyModel.cs b/PckStuido.ModelSupport/Format/External/BedrockLegacyModel.cs
new file mode 100644
index 00000000..1f96f7d4
--- /dev/null
+++ b/PckStuido.ModelSupport/Format/External/BedrockLegacyModel.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Newtonsoft.Json;
+
+namespace PckStudio.ModelSupport.Format.External
+{
+ internal class BedrockLegacyModel : Dictionary
+ {
+ }
+}
diff --git a/PckStuido.ModelSupport/Format/External/BedrockModel.cs b/PckStuido.ModelSupport/Format/External/BedrockModel.cs
new file mode 100644
index 00000000..7f8f4766
--- /dev/null
+++ b/PckStuido.ModelSupport/Format/External/BedrockModel.cs
@@ -0,0 +1,158 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Numerics;
+using System.Text;
+using System.Threading.Tasks;
+using Newtonsoft.Json;
+
+namespace PckStudio.ModelSupport.Format.External
+{
+ internal class BedrockModel
+ {
+ [JsonProperty("format_version")]
+ public string FormatVersion { get; set; }
+
+ [JsonProperty("minecraft:geometry")]
+ public List Models { get; } = new List();
+ }
+
+ internal class Geometry
+ {
+ [JsonProperty("description", NullValueHandling = NullValueHandling.Ignore)]
+ public GeometryDescription Description { get; set; }
+
+ [JsonProperty("bones")]
+ public List Bones { get; } = new List();
+ }
+
+ internal class GeometryDescription
+ {
+ [JsonProperty("identifier")]
+ public string Identifier { get; set; }
+
+ [JsonProperty("texture_width")]
+ private int TextureWidth;
+
+ [JsonProperty("texture_height")]
+ private int TextureHeight;
+
+ [JsonIgnore]
+ public Size TextureSize
+ {
+ get => new Size(TextureWidth, TextureHeight);
+ set
+ {
+ TextureWidth = value.Width;
+ TextureHeight = value.Height;
+ }
+ }
+ }
+
+ internal class Bone
+ {
+ [JsonProperty("name")]
+ public string Name { get; set; }
+
+ public Bone(string name)
+ {
+ Name = name;
+ Cubes = new List();
+ }
+
+
+ [JsonProperty("parent", NullValueHandling = NullValueHandling.Ignore)]
+ public string Parent { get; set; } = "";
+
+ [JsonIgnore]
+ public Vector3 Pivot
+ {
+ get => pivot.Length < 3 ? Vector3.Zero : new Vector3(pivot[0], pivot[1], pivot[2]);
+ set
+ {
+ if (pivot.Length < 3)
+ pivot = new float[3];
+ pivot[0] = value.X;
+ pivot[1] = value.Y;
+ pivot[2] = value.Z;
+ }
+ }
+
+ [JsonProperty("cubes")]
+ public List Cubes;
+
+ [JsonProperty("pivot")]
+ private float[] pivot { get; set; } = new float[3];
+ }
+
+ internal class Cube
+ {
+ [JsonProperty("origin")]
+ private float[] origin { get; set; } = new float[3];
+ [JsonIgnore]
+ public Vector3 Origin
+ {
+ get => origin.Length < 3 ? Vector3.Zero : new Vector3(origin[0], origin[1], origin[2]);
+ set
+ {
+ if (origin.Length < 3)
+ origin = new float[3];
+ origin[0] = value.X;
+ origin[1] = value.Y;
+ origin[2] = value.Z;
+ }
+ }
+
+ [JsonProperty("rotation")]
+ private float[] rotation { get; set; } = new float[3];
+ [JsonIgnore]
+ public Vector3 Rotation
+ {
+ get => rotation.Length < 3 ? Vector3.Zero : new Vector3(rotation[0], rotation[1], rotation[2]);
+ set
+ {
+ rotation[0] = value.X;
+ rotation[1] = value.Y;
+ rotation[2] = value.Z;
+ }
+ }
+
+ [JsonProperty("size")]
+ private float[] size { get; set; } = new float[3];
+ [JsonIgnore]
+ public Vector3 Size
+ {
+ get => size.Length < 3 ? Vector3.Zero : new Vector3(size[0], size[1], size[2]);
+ set
+ {
+ if (size.Length < 3)
+ size = new float[3];
+ size[0] = value.X;
+ size[1] = value.Y;
+ size[2] = value.Z;
+ }
+ }
+
+ [JsonProperty("uv")]
+ private float[] uv { get; set; } = new float[2];
+ [JsonIgnore]
+ public Vector2 Uv
+ {
+ get => uv.Length < 2 ? Vector2.Zero : new Vector2(uv[0], uv[1]);
+ set
+ {
+ if (uv.Length < 2)
+ uv = new float[2];
+ uv[0] = value.X;
+ uv[1] = value.Y;
+ }
+ }
+
+ [JsonProperty("inflate")]
+ public float Inflate { get; set; } = 0f;
+
+ [JsonProperty("mirror", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)]
+ public bool Mirror { get; set; } = false;
+ }
+}
diff --git a/PckStuido.ModelSupport/Format/External/BlockBenchModel.cs b/PckStuido.ModelSupport/Format/External/BlockBenchModel.cs
new file mode 100644
index 00000000..1c3f5e3e
--- /dev/null
+++ b/PckStuido.ModelSupport/Format/External/BlockBenchModel.cs
@@ -0,0 +1,362 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.IO;
+using System.Linq;
+using System.Numerics;
+using System.Text;
+using System.Threading.Tasks;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using NamedTexture = PckStudio.Core.NamedData;
+
+namespace PckStudio.ModelSupport.Format.External
+{
+ internal static class BlockBenchFormatInfos
+ {
+ internal static readonly string FormatVersion = "4.5";
+
+ internal static BlockBenchFormatInfo Free { get; } = new BlockBenchFormatInfo(FormatVersion, "free", true);
+ internal static BlockBenchFormatInfo BedrockEntity { get; } = new BlockBenchFormatInfo(FormatVersion, "bedrock", true);
+ }
+
+ internal sealed class BlockBenchFormatInfo
+ {
+ [JsonProperty("format_version")]
+ internal string FormatVersion { get; }
+
+ [JsonProperty("model_format")]
+ internal string ModelFormat { get; }
+
+ [JsonProperty("box_uv")]
+ internal bool UseBoxUv { get; set; }
+
+ [JsonConstructor]
+ private BlockBenchFormatInfo() { }
+
+ internal BlockBenchFormatInfo(string formatVersion, string modelFormat, bool useBoxUv)
+ {
+ FormatVersion = formatVersion;
+ ModelFormat = modelFormat;
+ UseBoxUv = useBoxUv;
+ }
+ }
+
+ internal class Element
+ {
+ [JsonProperty("name")]
+ internal string Name;
+
+ [JsonProperty("box_uv")]
+ internal bool UseBoxUv;
+
+ [JsonProperty("visibility", DefaultValueHandling = DefaultValueHandling.Ignore)]
+ internal bool IsVisibile { get; set; } = true;
+
+ [JsonProperty("rescale")]
+ internal bool Rescale;
+
+ [JsonProperty("mirror_uv")]
+ internal bool MirrorUv;
+
+ [JsonProperty("locked")]
+ internal bool Locked;
+
+ [DefaultValue(true)]
+ [JsonProperty("export", DefaultValueHandling = DefaultValueHandling.Ignore)]
+ internal bool Export { get; } = true;
+
+ [JsonProperty("inflate")]
+ internal float Inflate;
+
+ [JsonProperty("origin", NullValueHandling = NullValueHandling.Ignore)]
+ private float[] origin;
+
+ [JsonProperty("from")]
+ private float[] from;
+
+ [JsonProperty("to")]
+ private float[] to;
+
+ [JsonProperty("uv_offset")]
+ private int[] uv_offset;
+
+ [JsonProperty("rotation", NullValueHandling = NullValueHandling.Ignore)]
+ private float[] rotation;
+
+ [JsonIgnore()]
+ internal Vector3 Origin
+ {
+ get
+ {
+ return new Vector3(origin?[0] ?? 0, origin?[1] ?? 0, origin?[2] ?? 0);
+ }
+ set
+ {
+ if (origin is null || origin.Length < 3)
+ origin = new float[3];
+ origin[0] = value.X;
+ origin[1] = value.Y;
+ origin[2] = value.Z;
+ }
+ }
+
+ [JsonIgnore()]
+ internal Vector3 From
+ {
+ get
+ {
+ return new Vector3(from?[0] ?? 0, from?[1] ?? 0, from?[2] ?? 0);
+ }
+ set
+ {
+ if (from is null || from.Length < 3)
+ from = new float[3];
+ from[0] = value.X;
+ from[1] = value.Y;
+ from[2] = value.Z;
+ }
+ }
+
+ [JsonIgnore()]
+ internal Vector3 To
+ {
+ get
+ {
+ return new Vector3(to?[0] ?? 0, to?[1] ?? 0, to?[2] ?? 0);
+ }
+ set
+ {
+ if (to is null || to.Length < 3)
+ to = new float[3];
+ to[0] = value.X;
+ to[1] = value.Y;
+ to[2] = value.Z;
+ }
+ }
+
+ [JsonIgnore()]
+ internal Vector2 UvOffset
+ {
+ get
+ {
+ return new Vector2(uv_offset?[0] ?? 0, uv_offset?[1] ?? 0);
+ }
+ set
+ {
+ if (uv_offset is null || uv_offset.Length < 2)
+ uv_offset = new int[2];
+ uv_offset[0] = (int)value.X;
+ uv_offset[1] = (int)value.Y;
+ }
+ }
+
+ [JsonIgnore()]
+ internal Vector3 Rotation
+ {
+ get
+ {
+ return new Vector3(rotation?[0] ?? 0, rotation?[1] ?? 0, rotation?[2] ?? 0);
+ }
+ set
+ {
+ if (rotation is null || rotation.Length < 3)
+ rotation = new float[3];
+ rotation[0] = value.X;
+ rotation[1] = value.Y;
+ rotation[2] = value.Z;
+ }
+ }
+
+ [JsonProperty("type")]
+ internal string Type;
+
+ [JsonProperty("uuid")]
+ internal Guid Uuid;
+
+ internal static Element CreateCube(string name, Vector2 uvOffset, Vector3 pos, Vector3 size, float inflate, bool mirror)
+ {
+ return new Element
+ {
+ Name = name,
+ UseBoxUv = true,
+ Locked = false,
+ Rescale = false,
+ Type = "cube",
+ Uuid = Guid.NewGuid(),
+ UvOffset = uvOffset,
+ MirrorUv = mirror,
+ Inflate = inflate,
+ From = pos,
+ To = pos + size
+ };
+ }
+
+ }
+
+ internal class Texture
+ {
+ public static implicit operator Image(Texture texture) => texture.GetImage();
+ public static implicit operator Texture(Image image) => new Texture(image);
+ public static implicit operator Texture(NamedTexture namedTexture) => new Texture(namedTexture.Name, namedTexture.Value);
+
+ private const string _TEXTUREDATAHEAD = "data:image/png;base64,";
+
+ [JsonConstructor]
+ private Texture()
+ {
+ }
+
+ internal Texture(string name, Image image)
+ : this(image)
+ {
+ Name = name;
+ }
+
+ internal Texture(Image image)
+ {
+ if (image is not null)
+ {
+ SetImage(image);
+ return;
+ }
+ Debug.WriteLine($"param: {nameof(image)} is null");
+ }
+
+ [JsonProperty("name")]
+ internal string Name { get; set; }
+
+ [JsonProperty("source")]
+ internal string TextureSource { get; private set; }
+
+ private Image GetImage()
+ {
+ string data = TextureSource;
+ if (data.StartsWith(_TEXTUREDATAHEAD))
+ {
+ byte[] encodedData = Convert.FromBase64String(data.Substring(_TEXTUREDATAHEAD.Length));
+ using var ms = new MemoryStream(encodedData);
+ return Image.FromStream(ms);
+ }
+ return null;
+ }
+
+ private void SetImage(Image image)
+ {
+ var ms = new MemoryStream();
+ image.Save(ms, ImageFormat.Png);
+ TextureSource = _TEXTUREDATAHEAD + Convert.ToBase64String(ms.ToArray());
+ }
+ }
+
+ internal class Outline
+ {
+ [JsonProperty("name")]
+ internal string Name;
+
+ [JsonProperty("origin")]
+ private float[] origin;
+
+ [JsonIgnore]
+ public Vector3 Origin
+ {
+ get => new Vector3(origin?[0] ?? 0, origin?[1] ?? 0, origin?[2] ?? 0);
+ set
+ {
+ if (origin is null || origin.Length < 3)
+ origin = new float[3];
+ origin[0] = value.X;
+ origin[1] = value.Y;
+ origin[2] = value.Z;
+ }
+ }
+
+ [JsonProperty("rotation")]
+ private float[] rotation;
+
+ [JsonIgnore]
+ public Vector3 Rotation
+ {
+ get => new Vector3(rotation?[0] ?? 0, rotation?[1] ?? 0, rotation?[2] ?? 0);
+ set
+ {
+ if (rotation is null || rotation.Length < 3)
+ rotation = new float[3];
+ rotation[0] = value.X;
+ rotation[1] = value.Y;
+ rotation[2] = value.Z;
+ }
+ }
+
+ [JsonProperty("uuid")]
+ internal Guid Uuid;
+
+ [JsonProperty("children")]
+ internal JArray Children;
+
+ public Outline(string name)
+ {
+ Name = name;
+ origin = new float[3];
+ Uuid = Guid.NewGuid();
+ Children = new JArray();
+ }
+ }
+
+ internal class TextureRes
+ {
+ [JsonProperty("width")]
+ internal int Width { get; set; }
+
+ [JsonProperty("height")]
+ internal int Height { get; set; }
+
+ public TextureRes(int width, int height)
+ {
+ Width = width;
+ Height = height;
+ }
+
+ public static implicit operator Size(TextureRes res) => new Size(res.Width, res.Height);
+ public static implicit operator TextureRes(Size size) => new TextureRes(size.Width, size.Height);
+ }
+
+ internal class BlockBenchModel
+ {
+ [JsonProperty("name")]
+ internal string Name;
+
+ [JsonProperty("meta")]
+ internal BlockBenchFormatInfo Format;
+
+ [JsonProperty("model_identifier")]
+ internal string ModelIdentifier { get; set; } = "";
+
+ [JsonProperty("resolution")]
+ internal TextureRes TextureResolution;
+
+ [JsonProperty("elements")]
+ internal Element[] Elements;
+
+ [JsonProperty("outliner")]
+ internal JArray Outliner;
+
+ [JsonProperty("textures")]
+ internal Texture[] Textures;
+
+ internal static BlockBenchModel Create(BlockBenchFormatInfo formatInfo, string name, Size textureResolution, IEnumerable textures)
+ {
+ return new BlockBenchModel()
+ {
+ Name = name,
+ Textures = textures.ToArray(),
+ TextureResolution = textureResolution,
+ ModelIdentifier = "",
+ Format = formatInfo,
+ };
+ }
+ }
+}
diff --git a/PckStuido.ModelSupport/Format/Internal/PSM/PSMFile.cs b/PckStuido.ModelSupport/Format/Internal/PSM/PSMFile.cs
new file mode 100644
index 00000000..1aebcecc
--- /dev/null
+++ b/PckStuido.ModelSupport/Format/Internal/PSM/PSMFile.cs
@@ -0,0 +1,86 @@
+using System;
+using System.Collections.Generic;
+using PckStudio.Core.Skin;
+
+namespace PckStudio.ModelSupport.Internal.Format
+{
+/*
+ Magic - 3 bytes("psm")
+ Version - 1 byte [u8]
+ Anim - 4 bytes[int32]
+ NumberOfParts - 4 bytes[int32]
+ {
+ part parent - 1 byte (HEAD=0, BODY=1, LEG0=2, LEG1=3, ARM0=4, ARM1=5)
+ Position-X - 4 bytes (float32)
+ Position-Y - 4 bytes (float32)
+ Position-Z - 4 bytes (float32)
+ Size-X - 4 bytes (float32)
+ Size-Y - 4 bytes (float32)
+ Size-Z - 4 bytes (float32)
+ MirrorAndUvX - 1 bit flag 7 bits uv.x value(0-64) (s8)
+ HideWithArmorAndUvY - 1 bit flag 7 bits uv.y value(0-64) (s8)
+ inflation/scale value - 4 bytes (float32)
+ }
+ NumberOfOffsets - 4 bytes[int32]
+ {
+ offset part - 1 byte
+ vertical offset - 4 bytes[float]
+ }
+*/
+ public sealed class PSMFile
+ {
+ internal static readonly string HEADER_MAGIC = "psm";
+ internal const byte CurrentVersion = 1;
+
+ public readonly byte Version;
+
+ internal PSMFile(byte version)
+ {
+ Version = version;
+ }
+
+ internal PSMFile(byte version, SkinANIM skinANIM)
+ : this(version)
+ {
+ SkinANIM = skinANIM;
+ }
+
+ public SkinANIM SkinANIM { get; private set; }
+
+ public readonly List Parts = new List();
+ public readonly List Offsets = new List();
+ }
+
+ public enum PSMOffsetType : byte
+ {
+ HEAD = 0,
+ BODY = 1,
+ ARM0 = 2,
+ ARM1 = 3,
+ LEG0 = 4,
+ LEG1 = 5,
+
+ TOOL0 = 6,
+ TOOL1 = 7,
+
+ HELMET = 8,
+ SHOULDER0 = 9,
+ SHOULDER1 = 10,
+ CHEST = 11,
+ WAIST = 12,
+ PANTS0 = 13,
+ PANTS1 = 14,
+ BOOT0 = 15,
+ BOOT1 = 16,
+ }
+
+ public enum PSMParentType : byte
+ {
+ HEAD = 0,
+ BODY = 1,
+ ARM0 = 2,
+ ARM1 = 3,
+ LEG0 = 4,
+ LEG1 = 5,
+ }
+}
diff --git a/PckStuido.ModelSupport/Format/Internal/PSM/PSMFileReader.cs b/PckStuido.ModelSupport/Format/Internal/PSM/PSMFileReader.cs
new file mode 100644
index 00000000..40579ea3
--- /dev/null
+++ b/PckStuido.ModelSupport/Format/Internal/PSM/PSMFileReader.cs
@@ -0,0 +1,156 @@
+using System.Diagnostics;
+using System.IO;
+using System.Text;
+using OMI;
+using OMI.Workers;
+using PckStudio.Core.FileFormats;
+using PckStudio.Core;
+using PckStudio.Core.Skin;
+
+namespace PckStudio.ModelSupport.Internal.Format
+{
+ internal class PSMFileReader : IDataFormatReader, IDataFormatReader
+ {
+ public PSMFile FromFile(string filename)
+ {
+ if (File.Exists(filename))
+ {
+ using (var fs = File.OpenRead(filename))
+ {
+ return FromStream(fs);
+ }
+ }
+ throw new FileNotFoundException(filename);
+ }
+
+ public PSMFile FromStream(Stream stream)
+ {
+ using var reader = new EndiannessAwareBinaryReader(stream, Encoding.ASCII, leaveOpen: true, ByteOrder.LittleEndian);
+
+ var magic = reader.ReadString(3);
+ if (magic != PSMFile.HEADER_MAGIC)
+ {
+ Trace.TraceError("PSMFileReader.FromStream - Failed to load csmb.\n\tReason: Header magic mismatch.");
+ return new PSMFile(byte.MaxValue);
+ }
+
+ byte version = reader.ReadByte();
+ if (version < 1 || version > 1)
+ {
+ Trace.TraceError("PSMFileReader.FromStream - Failed to load csmb.\n\tReason: Unsupported version.");
+ return new PSMFile(byte.MaxValue);
+ }
+
+ var skinANIM = SkinANIM.FromValue(reader.ReadInt32());
+ PSMFile csmbFile = new PSMFile(version, skinANIM);
+ int numOfParts = reader.ReadInt32();
+ for (int i = 0; i < numOfParts; i++)
+ {
+ SkinBOX part = ReadPart(reader);
+ csmbFile.Parts.Add(part);
+ }
+ int numOfOffsets = reader.ReadInt32();
+ for (int i = 0; i < numOfOffsets; i++)
+ {
+ SkinPartOffset offset = ReadOffset(reader);
+ csmbFile.Offsets.Add(offset);
+ }
+
+ return csmbFile;
+ }
+
+ private SkinBOX ReadPart(EndiannessAwareBinaryReader reader)
+ {
+ string type = GetParentType((PSMParentType)reader.ReadByte());
+ float posX = reader.ReadSingle();
+ float posY = reader.ReadSingle();
+ float posZ = reader.ReadSingle();
+ float sizeX = reader.ReadSingle();
+ float sizeY = reader.ReadSingle();
+ float sizeZ = reader.ReadSingle();
+ byte mirrorAndUvX = reader.ReadByte();
+ byte hideWithArmorAndUvY = reader.ReadByte();
+ int uvX = mirrorAndUvX & 0x7f;
+ int uvY = hideWithArmorAndUvY & 0x7f;
+ bool mirror = (mirrorAndUvX & 0x80) != 0;
+ bool hideWithArmor = (hideWithArmorAndUvY & 0x80) != 0;
+ float scale = reader.ReadSingle();
+ return new SkinBOX(type, new System.Numerics.Vector3(posX, posY, posZ), new System.Numerics.Vector3(sizeX, sizeY, sizeZ), new System.Numerics.Vector2(uvX, uvY), hideWithArmor, mirror, scale);
+ }
+
+ private SkinPartOffset ReadOffset(EndiannessAwareBinaryReader reader)
+ {
+ PSMOffsetType type = (PSMOffsetType)reader.ReadByte();
+ float value = reader.ReadSingle();
+ return new SkinPartOffset(GetOffsetType(type), value);
+ }
+
+ private static string GetParentType(PSMParentType type)
+ {
+ switch (type)
+ {
+ case PSMParentType.HEAD:
+ return "HEAD";
+ case PSMParentType.BODY:
+ return "BODY";
+ case PSMParentType.ARM0:
+ return "ARM0";
+ case PSMParentType.ARM1:
+ return "ARM1";
+ case PSMParentType.LEG0:
+ return "LEG0";
+ case PSMParentType.LEG1:
+ return "LEG1";
+ default:
+ throw new InvalidDataException(type.ToString());
+ }
+ }
+
+ private static string GetOffsetType(PSMOffsetType type)
+ {
+ switch (type)
+ {
+ case PSMOffsetType.HEAD:
+ return "HEAD";
+ case PSMOffsetType.BODY:
+ return "BODY";
+ case PSMOffsetType.ARM0:
+ return "ARM0";
+ case PSMOffsetType.ARM1:
+ return "ARM1";
+ case PSMOffsetType.LEG0:
+ return "LEG0";
+ case PSMOffsetType.LEG1:
+ return "LEG1";
+ case PSMOffsetType.TOOL0:
+ return "TOOL0";
+ case PSMOffsetType.TOOL1:
+ return "TOOL1";
+ case PSMOffsetType.HELMET:
+ return "HELMET";
+ case PSMOffsetType.SHOULDER0:
+ return "SHOULDER0";
+ case PSMOffsetType.SHOULDER1:
+ return "SHOULDER1";
+ case PSMOffsetType.CHEST:
+ return "CHEST";
+ case PSMOffsetType.WAIST:
+ return "WAIST";
+ case PSMOffsetType.PANTS0:
+ return "PANTS0";
+ case PSMOffsetType.PANTS1:
+ return "PANTS1";
+ case PSMOffsetType.BOOT0:
+ return "BOOT0";
+ case PSMOffsetType.BOOT1:
+ return "BOOT1";
+ default:
+ throw new InvalidDataException(type.ToString());
+ }
+ }
+
+ object IDataFormatReader.FromStream(Stream stream) => FromStream(stream);
+
+ object IDataFormatReader.FromFile(string filename) => FromFile(filename);
+ }
+}
diff --git a/PckStuido.ModelSupport/Format/Internal/PSM/PSMFileWriter.cs b/PckStuido.ModelSupport/Format/Internal/PSM/PSMFileWriter.cs
new file mode 100644
index 00000000..aebb3144
--- /dev/null
+++ b/PckStuido.ModelSupport/Format/Internal/PSM/PSMFileWriter.cs
@@ -0,0 +1,134 @@
+using System.IO;
+using System.Text;
+using PckStudio.Core.FileFormats;
+using OMI.Workers;
+using OMI;
+using System;
+using OpenTK;
+using PckStudio.Core.Skin;
+
+namespace PckStudio.ModelSupport.Internal.Format
+{
+ internal class PSMFileWriter : IDataFormatWriter
+ {
+ PSMFile _PSM;
+
+ public PSMFileWriter(PSMFile csmb)
+ {
+ _PSM = csmb;
+ }
+
+ public void WriteToFile(string filename)
+ {
+ using(var fs = File.OpenWrite(filename))
+ {
+ WriteToStream(fs);
+ }
+ }
+
+ public void WriteToStream(Stream stream)
+ {
+ using (var writer = new EndiannessAwareBinaryWriter(stream, Encoding.ASCII, leaveOpen: true, ByteOrder.LittleEndian))
+ {
+ writer.WriteString(PSMFile.HEADER_MAGIC);
+ writer.Write(_PSM.Version);
+ writer.Write(_PSM.SkinANIM.ToValue());
+ writer.Write(_PSM.Parts.Count);
+ foreach (SkinBOX part in _PSM.Parts)
+ {
+ WritePart(writer, part);
+ }
+ writer.Write(_PSM.Offsets.Count);
+ foreach (SkinPartOffset offset in _PSM.Offsets)
+ {
+ writer.Write((byte)GetOffsetPart(offset.Type));
+ writer.Write(offset.Value);
+ }
+ }
+ }
+
+ private void WritePart(EndiannessAwareBinaryWriter writer, SkinBOX part)
+ {
+ writer.Write((byte)GetParentPart(part.Type));
+ writer.Write(part.Pos.X);
+ writer.Write(part.Pos.Y);
+ writer.Write(part.Pos.Z);
+ writer.Write(part.Size.X);
+ writer.Write(part.Size.Y);
+ writer.Write(part.Size.Z);
+
+ byte uvX = (byte)MathHelper.Clamp((int)part.UV.X, 0, 64);
+ byte uvY = (byte)MathHelper.Clamp((int)part.UV.Y, 0, 64);
+ byte mirrorAndUvX = (byte)(Convert.ToByte(part.Mirror) << 7 | uvX);
+ byte hideWithArmorAndUvY = (byte)(Convert.ToByte(part.HideWithArmor) << 7 | uvY);
+
+ writer.Write(mirrorAndUvX);
+ writer.Write(hideWithArmorAndUvY);
+ writer.Write(part.Scale);
+ }
+
+ private static PSMParentType GetParentPart(string type)
+ {
+ switch (type)
+ {
+ case "HEAD":
+ return PSMParentType.HEAD;
+ case "BODY":
+ return PSMParentType.BODY;
+ case "ARM0":
+ return PSMParentType.ARM0;
+ case "ARM1":
+ return PSMParentType.ARM1;
+ case "LEG0":
+ return PSMParentType.LEG0;
+ case "LEG1":
+ return PSMParentType.LEG1;
+ default:
+ throw new InvalidDataException(type);
+ }
+ }
+
+ private static PSMOffsetType GetOffsetPart(string type)
+ {
+ switch (type)
+ {
+ case "HEAD":
+ return PSMOffsetType.HEAD;
+ case "BODY":
+ return PSMOffsetType.BODY;
+ case "ARM0":
+ return PSMOffsetType.ARM0;
+ case "ARM1":
+ return PSMOffsetType.ARM1;
+ case "LEG0":
+ return PSMOffsetType.LEG0;
+ case "LEG1":
+ return PSMOffsetType.LEG1;
+ case "TOOL0":
+ return PSMOffsetType.TOOL0;
+ case "TOOL1":
+ return PSMOffsetType.TOOL1;
+ case "HELMET":
+ return PSMOffsetType.HELMET;
+ case "SHOULDER0":
+ return PSMOffsetType.SHOULDER0;
+ case "SHOULDER1":
+ return PSMOffsetType.SHOULDER1;
+ case "CHEST":
+ return PSMOffsetType.CHEST;
+ case "WAIST":
+ return PSMOffsetType.WAIST;
+ case "PANTS0":
+ return PSMOffsetType.PANTS0;
+ case "PANTS1":
+ return PSMOffsetType.PANTS1;
+ case "BOOT0":
+ return PSMOffsetType.BOOT0;
+ case "BOOT1":
+ return PSMOffsetType.BOOT1;
+ default:
+ throw new InvalidDataException(type);
+ }
+ }
+ }
+}
diff --git a/PckStuido.ModelSupport/GameModelImporter.cs b/PckStuido.ModelSupport/GameModelImporter.cs
new file mode 100644
index 00000000..5730d551
--- /dev/null
+++ b/PckStuido.ModelSupport/GameModelImporter.cs
@@ -0,0 +1,239 @@
+/* Copyright (c) 2024-present miku-666
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1.The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+**/
+using System;
+using System.IO;
+using System.Linq;
+using System.Drawing;
+using System.Numerics;
+using System.Diagnostics;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+
+using OMI.Formats.Model;
+
+using PckStudio.Core.Json;
+using PckStudio.Core.Extensions;
+using PckStudio.Core;
+using PckStudio.ModelSupport.Format.External;
+using PckStuido.ModelSupport.Properties;
+using NamedTexture = PckStudio.Core.NamedData;
+
+namespace PckStudio.ModelSupport
+{
+ public sealed class GameModelImporter : ModelImporter
+ {
+ public static GameModelImporter Default { get; } = new GameModelImporter();
+
+ public sealed class ModelExportSettings
+ {
+ public bool CreateModelOutline { get; set; } = true;
+ }
+
+ public ModelExportSettings ExportSettings { get; } = new ModelExportSettings();
+
+ public sealed class ModelImportSettings
+ {
+ public int ModelVersion { get; set; } = 1;
+ }
+
+ public ModelImportSettings ImportSettings { get; } = new ModelImportSettings();
+
+ public static ReadOnlyDictionary ModelMetaData { get; } = JsonConvert.DeserializeObject>(Resources.modelMetaData);
+ public static ReadOnlyDictionary DefaultModels { get; } = JsonConvert.DeserializeObject>(Resources.defaultModels);
+
+ private GameModelImporter()
+ {
+ // TODO: add import functionality -miku
+ InternalAddProvider(new FileDialogFilter("Block bench model(*.bbmodel)", "*.bbmodel"), ImportBlockBenchModel, ExportBlockBenchModel);
+ }
+
+ private readonly Vector3 bbModelTransformAxis = new Vector3(1, 1, 0);
+ // maybe get this value from the json. -miku
+ private readonly Vector3 _heightOffset = Vector3.UnitY * 24f;
+
+ private void ExportBlockBenchModel(string filepath, GameModelInfo modelInfo)
+ {
+ BlockBenchModel blockBenchModel = BlockBenchModel.Create(BlockBenchFormatInfos.BedrockEntity, modelInfo.Model.Name, modelInfo.Model.TextureSize, modelInfo.Textures.Select(nt => (Texture)nt));
+ blockBenchModel.ModelIdentifier = modelInfo.Model.Name;
+
+ List elements = new List(modelInfo.Model.PartCount);
+
+ if (!ModelMetaData.TryGetValue(modelInfo.Model.Name, out JsonModelMetaData modelMetaData))
+ {
+ Trace.TraceError($"[{nameof(GameModelImporter)}:{nameof(ExportBlockBenchModel)}] Failed to get model meta data for '{modelInfo.Model.Name}'.");
+ return;
+ }
+
+ IEnumerable outlines = ConvertToOutlines(modelInfo.Model, Vector3.Zero, modelMetaData.RootParts, elements.AddRange);
+
+ blockBenchModel.Elements = elements.ToArray();
+ if (ExportSettings.CreateModelOutline)
+ outlines = new Outline[1]
+ {
+ new Outline(modelInfo.Model.Name) { Children = JArray.FromObject(outlines) }
+ };
+
+ blockBenchModel.Outliner = JArray.FromObject(outlines);
+
+ string content = JsonConvert.SerializeObject(blockBenchModel, Formatting.Indented);
+ File.WriteAllText(filepath, content);
+ }
+
+ private Element ToElement(string partName, ModelBox modelBox, Vector3 partTranslation)
+ {
+ Element element = CreateElement(partName, modelBox, partTranslation, bbModelTransformAxis, _heightOffset);
+ //element.Rotation = rotation * TransformSpace(Vector3.One, Vector3.Zero, bbModelTransformAxis);
+ //element.Origin = outline.Origin;
+ return element;
+ }
+
+ private Outline[] ConvertToOutlines(Model model, Vector3 parentRotation, IReadOnlyCollection keyValues, Action addElements, int depth = 0)
+ {
+ Outline CreateOutline(ModelPart modelPart)
+ {
+ Outline outline = new Outline(modelPart.Name);
+
+ Vector3 partTranslation = modelPart.Translation;
+ outline.Origin = TransformSpace(partTranslation, Vector3.Zero, bbModelTransformAxis);
+ outline.Origin += _heightOffset;
+
+ Vector3 rotation = modelPart.Rotation;
+ outline.Rotation = rotation * TransformSpace(Vector3.One, Vector3.Zero, bbModelTransformAxis);
+ outline.Rotation += parentRotation;
+
+ Element[] elements1 = modelPart.GetBoxes().Select(box => ToElement(modelPart.Name, box, partTranslation)).ToArray();
+ addElements(elements1);
+
+ outline.Children.Add(elements1.Select(element => element.Uuid).ToArray());
+ return outline;
+ }
+
+ if (depth == 0 && keyValues.Count == 0)
+ {
+ return model.GetParts().Select(CreateOutline).ToArray();
+ }
+
+ List outlines = new List();
+ foreach (ModelMetaDataPart item in keyValues)
+ {
+ if (!model.TryGetPart(item.Name, out ModelPart modelPart))
+ {
+ Debug.WriteLine($"{nameof(item.Name)}: '{item.Name}' not in {nameof(model)}.");
+ continue;
+ }
+ Outline partentOutline = CreateOutline(modelPart);
+ JToken[] s = ConvertToOutlines(model, modelPart.Rotation, item.Children, addElements, depth + 1).Select(JToken.FromObject).ToArray();
+ partentOutline.Children.Add(s);
+ outlines.Add(partentOutline);
+ }
+ return outlines.ToArray();
+ }
+
+
+ private static Element CreateElement(string name, ModelBox box, Vector3 origin, Vector3 translationUnit, Vector3 offset)
+ {
+ Vector3 pos = box.Position;
+ Vector3 size = box.Size;
+ Vector3 transformPos = TransformSpace(pos + origin, size, translationUnit) + offset;
+ return Element.CreateCube(name, box.Uv, transformPos, size, box.Inflate, box.Mirror);
+ }
+
+ private GameModelInfo ImportBlockBenchModel(string filepath)
+ {
+ BlockBenchModel blockBenchModel = JsonConvert.DeserializeObject(File.ReadAllText(filepath));
+ if (!blockBenchModel.Format.UseBoxUv)
+ {
+ Trace.TraceError($"[{nameof(GameModelImporter)}:{nameof(ImportBlockBenchModel)}] Failed to import model '{blockBenchModel.ModelIdentifier}': Model does not use box uv.");
+ return null;
+ }
+
+ if (!ModelMetaData.TryGetValue(blockBenchModel.ModelIdentifier, out JsonModelMetaData modelMetaData))
+ {
+ Trace.TraceError($"[{nameof(GameModelImporter)}:{nameof(ImportBlockBenchModel)}] Failed to import model '{blockBenchModel.ModelIdentifier}': No model meta data found.");
+ return null;
+ }
+
+ IEnumerable textures = blockBenchModel.Textures
+ .Where(t => modelMetaData.TextureLocations.Any(texName => !string.IsNullOrEmpty(t.Name) && texName.EndsWith(Path.GetFileNameWithoutExtension(t.Name))))
+ .Select(t => new NamedTexture(modelMetaData.TextureLocations.First(texName => texName.EndsWith(Path.GetFileNameWithoutExtension(t.Name))), (Image)t));
+
+ Model model = new Model(blockBenchModel.ModelIdentifier, blockBenchModel.TextureResolution);
+
+ JArray rootOutline = blockBenchModel.Outliner
+ .FirstOrDefault(token => token.Type == JTokenType.Object && token.ToObject().Name == blockBenchModel.ModelIdentifier)
+ ?.ToObject().Children ?? blockBenchModel.Outliner;
+
+ foreach (Outline outline in rootOutline.Where(token => token.Type == JTokenType.Object).Select(token => token.ToObject()))
+ {
+ foreach (ModelPart part in ConvertOutlineToModelPart(outline, blockBenchModel.Elements))
+ {
+ model.AddPart(part);
+ }
+ }
+
+ return new GameModelInfo(model, textures);
+ }
+
+ private IEnumerable ConvertOutlineToModelPart(Outline root, IReadOnlyCollection elements)
+ {
+ List parts = new List(
+ root.Children
+ .Where(token => token.Type == JTokenType.Object)
+ .SelectMany(token => ConvertOutlineToModelPart(token.ToObject(), elements))
+ );
+
+ IEnumerable modelBoxElements = root.Children
+ .Where(token => token.Type == JTokenType.String && Guid.TryParse(token.ToString(), out Guid _))
+ .Select(token => elements.First(e => e.Uuid == Guid.Parse(token.ToString())))
+ .Where(element => element.Type == "cube" && element.UseBoxUv && element.Export);
+
+ Vector3 additionalRotation = new Vector3();
+ Element first = modelBoxElements.FirstOrDefault() ?? new Element() { Rotation = Vector3.Zero };
+ if (first.Rotation != Vector3.Zero)
+ {
+ if (!modelBoxElements.All(e => e.Rotation == first.Rotation))
+ {
+ Trace.TraceError($"[{nameof(GameModelImporter)}:{nameof(ImportBlockBenchModel)}] Rotation can't be applied for single elements.");
+ return Enumerable.Empty();
+ }
+ additionalRotation = first.Rotation;
+ }
+ Vector3 translation = TransformSpace(root.Origin - _heightOffset, Vector3.Zero, bbModelTransformAxis);
+ Vector3 rotation = TransformSpace(root.Rotation, Vector3.Zero, bbModelTransformAxis);
+ ModelPart part = new ModelPart(root.Name, string.Empty, translation, rotation, additionalRotation);
+ part.AddBoxes(modelBoxElements.Select(box => ConvertElementToModelBox(box, part.Translation)));
+ parts.Add(part);
+ return parts;
+ }
+
+ private ModelBox ConvertElementToModelBox(Element element, Vector3 translation)
+ {
+ BoundingBox boundingBox = new BoundingBox(element.From, element.To);
+
+ Vector3 pos = boundingBox.Start.ToNumericsVector();
+ Vector3 size = boundingBox.Volume.ToNumericsVector();
+
+ Vector3 transformedPos = TransformSpace(pos, size, bbModelTransformAxis) - translation + _heightOffset;
+
+ return new ModelBox(transformedPos, size, element.UvOffset, element.Inflate, element.MirrorUv);
+ }
+ }
+}
diff --git a/PckStuido.ModelSupport/GameModelInfo.cs b/PckStuido.ModelSupport/GameModelInfo.cs
new file mode 100644
index 00000000..dd53eb5a
--- /dev/null
+++ b/PckStuido.ModelSupport/GameModelInfo.cs
@@ -0,0 +1,20 @@
+using System.Collections.Generic;
+using OMI.Formats.Model;
+using NamedTexture = PckStudio.Core.NamedData;
+
+namespace PckStudio.ModelSupport
+{
+ public sealed class GameModelInfo
+ {
+ public Model Model { get; }
+
+ public IEnumerable Textures { get; }
+
+ public GameModelInfo(Model model, IEnumerable textures)
+ {
+ Model = model;
+ Textures = textures;
+ }
+
+ }
+}
diff --git a/PckStuido.ModelSupport/Json/JsonDefaultModel.cs b/PckStuido.ModelSupport/Json/JsonDefaultModel.cs
new file mode 100644
index 00000000..2fb3aadc
--- /dev/null
+++ b/PckStuido.ModelSupport/Json/JsonDefaultModel.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Numerics;
+using Newtonsoft.Json;
+
+namespace PckStudio.Core.Json
+{
+ public class DefaultModel
+ {
+ [JsonProperty("textureSize", Required = Required.Always)]
+ public Vector2 TextureSize { get; set; }
+
+ [JsonProperty("parts", Required = Required.Always)]
+ public DefaultPart[] Parts { get; set; } = Array.Empty();
+ }
+
+ public class DefaultPart
+ {
+ [JsonProperty("name", Required = Required.Always)]
+ public string Name { get; set; }
+
+ [JsonProperty("translation")]
+ public Vector3 Translation { get; set; } = Vector3.Zero;
+
+ [JsonProperty("rotation")]
+ public Vector3 Rotation { get; set; } = Vector3.Zero;
+
+ [JsonProperty("boxes")]
+ public ModelDefaultBox[] Boxes { get; set; }
+ }
+
+ public class ModelDefaultBox
+ {
+ [JsonProperty("pos")]
+ public Vector3 Position { get; set; }
+
+ [JsonProperty("size")]
+ public Vector3 Size { get; set; }
+
+ [JsonProperty("uv")]
+ public Vector2 Uv { get; set; }
+
+ [JsonProperty("mirror")]
+ public bool Mirror { get; set; } = false;
+
+ [JsonProperty("inflate")]
+ public float Inflate { get; set; } = 0f;
+ }
+}
diff --git a/PckStuido.ModelSupport/Json/JsonModelMetaData.cs b/PckStuido.ModelSupport/Json/JsonModelMetaData.cs
new file mode 100644
index 00000000..d274cfb3
--- /dev/null
+++ b/PckStuido.ModelSupport/Json/JsonModelMetaData.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Numerics;
+using Newtonsoft.Json;
+
+namespace PckStudio.Core.Json
+{
+ public class ModelMetaDataPart
+ {
+ [JsonProperty("name", Required = Required.Always)]
+ public string Name { get; set; }
+
+ [JsonProperty("children", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)]
+ public ModelMetaDataPart[] Children { get; set; } = Array.Empty();
+
+ [JsonConstructor]
+ public ModelMetaDataPart()
+ {
+ }
+
+ public ModelMetaDataPart(string name)
+ : this(name, Array.Empty())
+ {
+ }
+
+ public ModelMetaDataPart(string name, params ModelMetaDataPart[] children)
+ {
+ Name = name;
+ Children = children;
+ }
+ }
+
+ public class JsonModelMetaData
+ {
+ [JsonProperty("textureLocations", Required = Required.Always)]
+ public string[] TextureLocations { get; set; }
+
+ [JsonProperty("materialName", NullValueHandling = NullValueHandling.Ignore)]
+ public string MaterialName { get; set; } = string.Empty;
+
+ [JsonProperty("uv_offsets", NullValueHandling = NullValueHandling.Ignore)]
+ public Vector2[] UvOffsets { get; set; } = Array.Empty();
+
+ [JsonProperty("parts", NullValueHandling = NullValueHandling.Ignore)]
+ public ModelMetaDataPart[] RootParts { get; set; } = Array.Empty();
+ }
+}
diff --git a/PckStuido.ModelSupport/ModelImporter.cs b/PckStuido.ModelSupport/ModelImporter.cs
new file mode 100644
index 00000000..ee32a94a
--- /dev/null
+++ b/PckStuido.ModelSupport/ModelImporter.cs
@@ -0,0 +1,178 @@
+/* Copyright (c) 2024-present miku-666
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1.The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+**/
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Numerics;
+using PckStudio.Core;
+using PckStudio.Interfaces;
+
+namespace PckStudio.ModelSupport
+{
+ public abstract class ModelImporter where T : class
+ {
+ private Dictionary> _importProviders = new Dictionary>();
+
+ private sealed class InternalImportProvider : IModelImportProvider
+ {
+ public string Name => nameof(InternalImportProvider);
+
+ public FileDialogFilter DialogFilter => _dialogFilter;
+
+ public bool SupportImport => _import != null;
+
+ public bool SupportExport => _export != null;
+
+ private FileDialogFilter _dialogFilter;
+ private Func _import;
+ private Action _export;
+
+ public InternalImportProvider(FileDialogFilter dialogFilter, Func import, Action export)
+ {
+ _dialogFilter = dialogFilter;
+ _import = import;
+ _export = export;
+ }
+
+ public void Export(string filename, T model)
+ {
+ _ = _export ?? throw new NotImplementedException();
+ _export(filename, model);
+ }
+
+ public T Import(string filename)
+ {
+ _ = _import ?? throw new NotImplementedException();
+ return _import(filename);
+ }
+
+ public void Export(ref Stream stream, T model)
+ {
+ throw new NotImplementedException();
+ }
+
+ public T Import(Stream stream)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ ///
+ /// Filter that can be used for or
+ ///
+ public string SupportedModelFileFormatsFilter => string.Join("|", _importProviders.Values.Select(p => p.DialogFilter));
+
+ public T Import(string filename)
+ {
+ if (!File.Exists(filename))
+ {
+ Trace.TraceWarning($"[{nameof(ModelImporter)}:Import] Failed to import '{filename}'. File does not exist.");
+ return default;
+ }
+
+ if (!HasProvider(filename))
+ {
+ Trace.TraceWarning($"[{nameof(ModelImporter)}:Import] No provider found for '{Path.GetExtension(filename)}'.");
+ return default;
+ }
+
+ IModelImportProvider provider = GetProvider(filename);
+ if (!provider.SupportImport)
+ {
+ throw new NotSupportedException($"Provider '{provider.Name}' does not support importing.");
+ }
+
+ return provider.Import(filename);
+ }
+
+ public void Export(string filename, T model)
+ {
+ if (model is null)
+ {
+ Trace.TraceError($"[{nameof(ModelImporter)}:Export] Model is null.");
+ return;
+ }
+
+ if (!HasProvider(filename))
+ {
+ Trace.TraceWarning($"[{nameof(ModelImporter)}:Export] No provider found for '{Path.GetExtension(filename)}'.");
+ return;
+ }
+
+ IModelImportProvider provider = GetProvider(filename);
+ if (!provider.SupportExport)
+ {
+ throw new NotSupportedException($"Provider '{provider.Name}' does not support exporting.");
+ }
+ provider.Export(filename, model);
+ }
+
+ internal bool AddProvider(IModelImportProvider provider)
+ {
+ if (_importProviders.ContainsKey(provider.DialogFilter.Extension))
+ return false;
+
+ _importProviders.Add(provider.DialogFilter.Extension, provider);
+ return true;
+ }
+
+ protected bool InternalAddProvider(FileDialogFilter dialogFilter, Func import, Action export)
+ {
+ return AddProvider(new InternalImportProvider(dialogFilter, import, export));
+ }
+
+ ///
+ /// Translates coordinate unit system into our coordinate system
+ ///
+ /// Position/Origin of the Object(Cube).
+ /// The Size of the Object(Cube).
+ /// Describes what axises need translation.
+ /// The translated position
+ protected static Vector3 TransformSpace(Vector3 origin, Vector3 size, Vector3 translationUnit)
+ {
+ // The translation unit describes what axises need to be swapped
+ // Example:
+ // translation unit = (1, 0, 0) => This translation unit will ONLY swap the X axis
+ translationUnit = Vector3.Clamp(translationUnit, Vector3.Zero, Vector3.One);
+ // To better understand see:
+ // https://sharplab.io/#v2:C4LgTgrgdgNAJiA1AHwAICYCMBYAUKgBgAJVMA6AOQgFsBTMASwGMBnAbj1QGYT0iBhIgG88RMb3SjxI3OLlEAbgEMwRBlAAOEYEQC8RKLQDuRAGq0mwAPZguACkwwijogQCUHWfLHLVtAB4aFsC0cHoGxmbBNvYAtC7xTpgeUt6+RGC0LOEAKmBKUCwAYjbU/FY2cOpKISx26lrAKV7epACcdpkszd5i7Z1ZevoBQZahPeIAvqlEM9wkmABsUZYxRHkFxaXlldW1duartmqa2m4zMr2KKhmD+ofWtmT8ADZK1Br1p8BODzFkAC16FZftEngB5QwTbxdIgAKn06E8V1hsXuYK4ZEhtGRvVQAHYiLEurixNNcJMgA
+ Vector3 transformUnit = -((translationUnit * 2) - Vector3.One);
+
+ Vector3 pos = origin;
+ // The next line essentialy does uses the fomular below just on all axis.
+ // x = -(pos.x + size.x)
+ pos *= transformUnit;
+ pos -= size * translationUnit;
+ return pos;
+ }
+
+ private bool HasProvider(string filename)
+ {
+ string fileExtension = Path.GetExtension(filename);
+ return _importProviders.ContainsKey(fileExtension) && _importProviders[fileExtension] is not null;
+ }
+
+ private IModelImportProvider GetProvider(string filename)
+ {
+ string fileExtension = Path.GetExtension(filename);
+ return _importProviders.ContainsKey(fileExtension) ? _importProviders[fileExtension] : null;
+ }
+ }
+}
diff --git a/PckStuido.ModelSupport/PckStuido.ModelSupport.csproj b/PckStuido.ModelSupport/PckStuido.ModelSupport.csproj
new file mode 100644
index 00000000..d7697c87
--- /dev/null
+++ b/PckStuido.ModelSupport/PckStuido.ModelSupport.csproj
@@ -0,0 +1,96 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {43BCACD7-5405-4499-9B45-E1435AC03C26}
+ Library
+ NDEBUG
+ Properties
+ PckStuido.ModelSupport
+ PckStuido.ModelSupport
+ v4.8
+ 12
+ 512
+ true
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ Resources.resx
+
+
+
+
+
+
+ 13.0.3
+
+
+
+
+ {345eabed-f0d1-4d04-b409-babdef747352}
+ PckStudio.Core
+
+
+ {693aebc1-293d-4df0-bcae-26a1099fe7bb}
+ OMI Filetype Library
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/PckStuido.ModelSupport/Properties/AssemblyInfo.cs b/PckStuido.ModelSupport/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..4e98a15b
--- /dev/null
+++ b/PckStuido.ModelSupport/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("PckStuido.ModelSupport")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("PckStuido.ModelSupport")]
+[assembly: AssemblyCopyright("Copyright © 2025")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("43bcacd7-5405-4499-9b45-e1435ac03c26")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/PckStuido.ModelSupport/Properties/Resources.Designer.cs b/PckStuido.ModelSupport/Properties/Resources.Designer.cs
new file mode 100644
index 00000000..b98cf665
--- /dev/null
+++ b/PckStuido.ModelSupport/Properties/Resources.Designer.cs
@@ -0,0 +1,120 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace PckStuido.ModelSupport.Properties {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PckStuido.ModelSupport.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to {
+ /// "bat": {
+ /// "textureSize": { "X": 64, "Y": 64 },
+ /// "parts": [
+ /// {
+ /// "name": "head",
+ /// "boxes": [
+ /// { "pos": { "X": -3, "Y": -3, "Z": -3 }, "size": { "X": 6, "Y": 6, "Z": 6 }, "uv": { "X": 0, "Y": 0 } }
+ /// ]
+ /// },
+ /// {
+ /// "name": "body",
+ /// "boxes": [
+ /// { "pos": { "X": -3, "Y": 4, "Z": -3 }, "size": { "X": 6, "Y": 12, "Z": 6 }, "uv": { "X": 0, "Y": 16 } },
+ /// { "pos": { "X": -5, "Y": 16, "Z": 0 }, "size": { "X": 10, "Y": 6, "Z": [rest of string was truncated]";.
+ ///
+ internal static string defaultModels {
+ get {
+ return ResourceManager.GetString("defaultModels", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to {
+ /// "bat": {
+ /// "textureLocations": [
+ /// "res/mob/bat"
+ /// ],
+ /// "materialName": "bat",
+ /// "parts": [
+ /// {
+ /// "name": "head",
+ /// "children": [
+ /// { "name": "rightEar" },
+ /// { "name": "leftEar" }
+ /// ]
+ /// },
+ /// {
+ /// "name": "body",
+ /// "children": [
+ /// {
+ /// "name": "rightWing",
+ /// "children": [
+ /// { "name": "rightWingTip" }
+ /// ]
+ /// },
+ /// {
+ /// "name": "leftWing",
+ /// [rest of string was truncated]";.
+ ///
+ internal static string modelMetaData {
+ get {
+ return ResourceManager.GetString("modelMetaData", resourceCulture);
+ }
+ }
+ }
+}
diff --git a/PckStuido.ModelSupport/Properties/Resources.resx b/PckStuido.ModelSupport/Properties/Resources.resx
new file mode 100644
index 00000000..b1909c61
--- /dev/null
+++ b/PckStuido.ModelSupport/Properties/Resources.resx
@@ -0,0 +1,127 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+ ..\Resources\defaultModels.json;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252
+
+
+ ..\Resources\modelMetaData.json;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;iso-8859-1
+
+
\ No newline at end of file
diff --git a/PckStuido.ModelSupport/Resources/defaultModels.json b/PckStuido.ModelSupport/Resources/defaultModels.json
new file mode 100644
index 00000000..c77963e9
--- /dev/null
+++ b/PckStuido.ModelSupport/Resources/defaultModels.json
@@ -0,0 +1,619 @@
+{
+ "bat": {
+ "textureSize": { "X": 64, "Y": 64 },
+ "parts": [
+ {
+ "name": "head",
+ "boxes": [
+ { "pos": { "X": -3, "Y": -3, "Z": -3 }, "size": { "X": 6, "Y": 6, "Z": 6 }, "uv": { "X": 0, "Y": 0 } }
+ ]
+ },
+ {
+ "name": "body",
+ "boxes": [
+ { "pos": { "X": -3, "Y": 4, "Z": -3 }, "size": { "X": 6, "Y": 12, "Z": 6 }, "uv": { "X": 0, "Y": 16 } },
+ { "pos": { "X": -5, "Y": 16, "Z": 0 }, "size": { "X": 10, "Y": 6, "Z": 1 }, "uv": { "X": 0, "Y": 34 } }
+ ]
+ },
+ {
+ "name": "rightEar",
+ "boxes": [
+ { "pos": { "X": -4, "Y": -6, "Z": -2 }, "size": { "X": 3, "Y": 4, "Z": 1 }, "uv": { "X": 24, "Y": 0 } }
+ ]
+ },
+ {
+ "name": "leftEar",
+ "boxes": [
+ { "pos": { "X": 1, "Y": -6, "Z": -2 }, "size": { "X": 3, "Y": 4, "Z": 1 }, "uv": { "X": 24, "Y": 0 }, "mirror": true }
+ ]
+ },
+ {
+ "name": "rightWing",
+ "boxes": [
+ { "pos": { "X": -12, "Y": 1, "Z": 1.5 }, "size": { "X": 10, "Y": 16, "Z": 1 }, "uv": { "X": 42, "Y": 0 } }
+ ]
+ },
+ {
+ "name": "rightWingTip",
+ "translation": { "X": -12, "Y": 1, "Z": 1.5 },
+ "boxes": [
+ { "pos": { "X": -8, "Y": 1, "Z": 0 }, "size": { "X": 8, "Y": 12, "Z": 1 }, "uv": { "X": 24, "Y": 16 } }
+ ]
+ },
+ {
+ "name": "leftWing",
+ "boxes": [
+ { "pos": { "X": 2, "Y": 1, "Z": 1.5 }, "size": { "X": 10, "Y": 16, "Z": 1 }, "uv": { "X": 42, "Y": 0 }, "mirror": true }
+ ]
+ },
+ {
+ "name": "leftWingTip",
+ "translation": { "X": 12, "Y": 1, "Z": 1.5 },
+ "boxes": [
+ { "pos": { "X": 0, "Y": 1, "Z": 0 }, "size": { "X": 8, "Y": 12, "Z": 1 }, "uv": { "X": 24, "Y": 16 }, "mirror": true }
+ ]
+ }
+ ]
+ },
+ "trident": {
+ "textureSize": { "X": 32, "Y": 32 },
+ "parts": [
+ {
+ "name": "pole",
+ "boxes": [
+ { "pos": { "X": -0.5, "Y": -4, "Z": -0.5 }, "size": { "X": 1, "Y": 31, "Z": 1 }, "uv": { "X": 0, "Y": 0 } },
+ { "pos": { "X": -1.5, "Y": 0, "Z": -0.5 }, "size": { "X": 3, "Y": 2, "Z": 1 }, "uv": { "X": 4, "Y": 0 } },
+ { "pos": { "X": -2.5, "Y": -3, "Z": -0.5 }, "size": { "X": 1, "Y": 4, "Z": 1 }, "uv": { "X": 4, "Y": 3 } },
+ { "pos": { "X": 1.5, "Y": -3, "Z": -0.5 }, "size": { "X": 1, "Y": 4, "Z": 1 }, "uv": { "X": 4, "Y": 3 }, "mirror": true }
+ ]
+ }
+ ]
+ },
+ "irongolem": {
+ "textureSize": { "X": 128, "Y": 128 },
+ "parts": [
+ {
+ "name": "head",
+ "translation": { "X": 0, "Y": 0, "Z": -2 },
+ "boxes": [
+ { "pos": { "X": -4, "Y": -12, "Z": -5.5 }, "size": { "X": 8, "Y": 10, "Z": 8 }, "uv": { "X": 0, "Y": 0 } },
+ { "pos": { "X": -1, "Y": -5, "Z": -7.5 }, "size": { "X": 2, "Y": 4, "Z": 2 }, "uv": { "X": 24, "Y": 0 } }
+ ]
+ },
+ {
+ "name": "body",
+ "boxes": [
+ { "pos": { "X": -9, "Y": -2, "Z": -6 }, "size": { "X": 18, "Y": 12, "Z": 11 }, "uv": { "X": 0, "Y": 40 } },
+ { "pos": { "X": -4.5, "Y": 10, "Z": -3 }, "size": { "X": 9, "Y": 5, "Z": 6 }, "uv": { "X": 0, "Y": 70 }, "inflate": 0.5 }
+ ]
+ },
+ {
+ "name": "arm0",
+ "translation": { "X": 0, "Y": 0, "Z": 0 },
+ "boxes": [
+ { "pos": { "X": -13, "Y": -2.5, "Z": -3 }, "size": { "X": 4, "Y": 30, "Z": 6 }, "uv": { "X": 60, "Y": 58 } }
+ ]
+ },
+ {
+ "name": "arm1",
+ "translation": { "X": 0, "Y": 0, "Z": 0 },
+ "boxes": [
+ { "pos": { "X": 9, "Y": -2.5, "Z": -3 }, "size": { "X": 4, "Y": 30, "Z": 6 }, "uv": { "X": 60, "Y": 21 } }
+ ]
+ },
+ {
+ "name": "leg0",
+ "translation": { "X": -4, "Y": 18, "Z": 0 },
+ "boxes": [
+ { "pos": { "X": -3.5, "Y": -3, "Z": -3 }, "size": { "X": 6, "Y": 16, "Z": 5 }, "uv": { "X": 37, "Y": 0 } }
+ ]
+ },
+ {
+ "name": "leg1",
+ "translation": { "X": 5, "Y": 18, "Z": 0 },
+ "boxes": [
+ { "pos": { "X": -3.5, "Y": -3, "Z": -3 }, "size": { "X": 6, "Y": 16, "Z": 5 }, "uv": { "X": 60, "Y": 0 }, "mirror": true }
+ ]
+ }
+ ]
+ },
+ "dolphin": {
+ "textureSize": { "X": 64, "Y": 64 },
+ "parts": [
+ {
+ "name": "head",
+ "boxes": [
+ { "pos": { "X": -4, "Y": -7, "Z": -6 }, "size": { "X": 8, "Y": 7, "Z": 6 }, "uv": { "X": 0, "Y": 0 } }
+ ]
+ },
+ {
+ "name": "nose",
+ "translation": { "X": 0, "Y": 0, "Z": -10 },
+ "boxes": [
+ { "pos": { "X": -1, "Y": -2, "Z": 0 }, "size": { "X": 2, "Y": 2, "Z": 4 }, "uv": { "X": 0, "Y": 13 } }
+ ]
+ },
+ {
+ "name": "body",
+ "translation": { "X": 0, "Y": 0, "Z": 0 },
+ "rotation": { "X": 0, "Y": 0, "Z": 0 },
+ "boxes": [
+ { "pos": { "X": -4, "Y": -7, "Z": 0 }, "size": { "X": 8, "Y": 7, "Z": 13 }, "uv": { "X": 0, "Y": 13 } }
+ ]
+ },
+ {
+ "name": "back_fin",
+ "translation": { "X": 0, "Y": -7, "Z": 7 },
+ "boxes": [
+ { "pos": { "X": -0.5, "Y": -5, "Z": -1 }, "size": { "X": 1, "Y": 5, "Z": 4 }, "uv": { "X": 29, "Y": 0 } }
+ ]
+ },
+ {
+ "name": "left_fin",
+ "translation": { "X": 3, "Y": -1, "Z": 2 },
+ "boxes": [
+ { "pos": { "X": 0, "Y": -1, "Z": -1 }, "size": { "X": 8, "Y": 1, "Z": 4 }, "uv": { "X": 40, "Y": 0 } }
+ ]
+ },
+ {
+ "name": "right_fin",
+ "translation": { "X": -3, "Y": -1, "Z": 2 },
+ "boxes": [
+ { "pos": { "X": -8, "Y": -1, "Z": -1 }, "size": { "X": 8, "Y": 1, "Z": 4 }, "uv": { "X": 40, "Y": 6 } }
+ ]
+ },
+ {
+ "name": "tail",
+ "translation": { "X": 0, "Y": -2.5, "Z": 14 },
+ "boxes": [
+ { "pos": { "X": -2, "Y": -2.5, "Z": -1 }, "size": { "X": 4, "Y": 5, "Z": 11 }, "uv": { "X": 0, "Y": 33 } }
+ ]
+ },
+ {
+ "name": "tail_fin",
+ "translation": { "X": 0, "Y": 0, "Z": 24 },
+ "boxes": [
+ { "pos": { "X": -5, "Y": -2.5, "Z": -1 }, "size": { "X": 10, "Y": 1, "Z": 6 }, "uv": { "X": 0, "Y": 49 } }
+ ]
+ }
+ ]
+ },
+ "creeper_head": {
+ "textureSize": { "X": 64, "Y": 32 },
+ "parts": [
+ {
+ "name": "head",
+ "boxes": [
+ { "pos": { "X": -4, "Y": -8, "Z": -4 }, "size": { "X": 8, "Y": 8, "Z": 8 }, "uv": { "X": 0, "Y": 0 } }
+ ]
+ }
+ ]
+ },
+ "creeper": {
+ "textureSize": { "X": 64, "Y": 32 },
+ "parts": [
+ {
+ "name": "head",
+ "translation": { "X": 0, "Y": 6, "Z": 0 },
+ "boxes": [
+ { "pos": { "X": -4, "Y": -8, "Z": -4 }, "size": { "X": 8, "Y": 8, "Z": 8 }, "uv": { "X": 0, "Y": 0 } }
+ ]
+ },
+ {
+ "name": "body",
+ "translation": { "X": 0, "Y": 6, "Z": 0 },
+ "boxes": [
+ { "pos": { "X": -4, "Y": 0, "Z": -2 }, "size": { "X": 8, "Y": 12, "Z": 4 }, "uv": { "X": 16, "Y": 16 } }
+ ]
+ },
+ {
+ "name": "leg0",
+ "translation": { "X": -2, "Y": 18, "Z": 4 },
+ "boxes": [
+ { "pos": { "X": -2, "Y": 0, "Z": -2 }, "size": { "X": 4, "Y": 6, "Z": 4 }, "uv": { "X": 0, "Y": 16 } }
+ ]
+ },
+ {
+ "name": "leg1",
+ "translation": { "X": 2, "Y": 18, "Z": 4 },
+ "boxes": [
+ { "pos": { "X": -2, "Y": 0, "Z": -2 }, "size": { "X": 4, "Y": 6, "Z": 4 }, "uv": { "X": 0, "Y": 16 } }
+ ]
+ },
+ {
+ "name": "leg2",
+ "translation": { "X": -2, "Y": 18, "Z": -4 },
+ "boxes": [
+ { "pos": { "X": -2, "Y": 0, "Z": -2 }, "size": { "X": 4, "Y": 6, "Z": 4 }, "uv": { "X": 0, "Y": 16 } }
+ ]
+ },
+ {
+ "name": "leg3",
+ "translation": { "X": 2, "Y": 18, "Z": -4 },
+ "boxes": [
+ { "pos": { "X": -2, "Y": 0, "Z": -2 }, "size": { "X": 4, "Y": 6, "Z": 4 }, "uv": { "X": 0, "Y": 16 } }
+ ]
+ }
+ ]
+ },
+ "boat": {
+ "textureSize": { "X": 128, "Y": 64 },
+ "parts": [
+ {
+ "name": "bottom",
+ "translation": { "X": 0, "Y": 3, "Z": 1 },
+ "rotation": { "X": 90, "Y": 0, "Z": 0 },
+ "boxes": [
+ { "pos": { "X": -14, "Y": -9, "Z": -3 }, "size": { "X": 28, "Y": 16, "Z": 3 }, "uv": { "X": 0, "Y": 0 } }
+ ]
+ },
+ {
+ "name": "front",
+ "translation": { "X": 15, "Y": 4, "Z": 0 },
+ "rotation": { "X": 0, "Y": 90, "Z": 0 },
+ "boxes": [
+ { "pos": { "X": -8, "Y": -7, "Z": -1 }, "size": { "X": 16, "Y": 6, "Z": 2 }, "uv": { "X": 0, "Y": 27 } }
+ ]
+ },
+ {
+ "name": "back",
+ "translation": { "X": -15, "Y": 4, "Z": 4 },
+ "rotation": { "X": 0, "Y": 270, "Z": 0 },
+ "boxes": [
+ { "pos": { "X": -13, "Y": -7, "Z": -1 }, "size": { "X": 18, "Y": 6, "Z": 2 }, "uv": { "X": 0, "Y": 19 } }
+ ]
+ },
+ {
+ "name": "left",
+ "translation": { "X": 0, "Y": 4, "Z": 9 },
+ "boxes": [
+ { "pos": { "X": -14, "Y": -7, "Z": -1 }, "size": { "X": 28, "Y": 6, "Z": 2 }, "uv": { "X": 0, "Y": 43 } }
+ ]
+ },
+ {
+ "name": "right",
+ "translation": { "X": 0, "Y": 4, "Z": -9 },
+ "rotation": { "X": 0, "Y": 180, "Z": 0 },
+ "boxes": [
+ { "pos": { "X": -14, "Y": -7, "Z": -1 }, "size": { "X": 28, "Y": 6, "Z": 2 }, "uv": { "X": 0, "Y": 35 } }
+ ]
+ },
+ {
+ "name": "paddle_left",
+ "translation": { "X": 3, "Y": -5, "Z": 9 },
+ "rotation": { "X": 0, "Y": 0, "Z": 11.25 },
+ "boxes": [
+ { "pos": { "X": -1, "Y": 0, "Z": -5 }, "size": { "X": 2, "Y": 2, "Z": 18 }, "uv": { "X": 62, "Y": 0 } },
+ { "pos": { "X": -1.001, "Y": -3, "Z": 8 }, "size": { "X": 1, "Y": 6, "Z": 7 }, "uv": { "X": 62, "Y": 0 } }
+ ]
+ },
+ {
+ "name": "paddle_right",
+ "translation": { "X": 3, "Y": -5, "Z": -9 },
+ "rotation": { "X": 0, "Y": 180, "Z": 11.25 },
+ "boxes": [
+ { "pos": { "X": -1, "Y": 0, "Z": -5 }, "size": { "X": 2, "Y": 2, "Z": 18 }, "uv": { "X": 62, "Y": 20 } },
+ { "pos": { "X": 0.001, "Y": -3, "Z": 8 }, "size": { "X": 1, "Y": 6, "Z": 7 }, "uv": { "X": 62, "Y": 20 } }
+ ]
+ }
+ ]
+ },
+ "bed":{
+ "textureSize": { "X": 64, "Y": 128 },
+ "parts": [
+ {
+ "name": "bed",
+ "boxes": [
+ { "pos": { "X": 0, "Y": 0, "Z": 0 }, "size": { "X": 16, "Y": 32, "Z": 6 }, "uv": { "X": 0, "Y": 0 } },
+ { "pos": { "X": 3, "Y": 31, "Z": 6 }, "size": { "X": 10, "Y": 1, "Z": 3 }, "uv": { "X": 38, "Y": 2 } },
+ { "pos": { "X": 3, "Y": 0, "Z": 6 }, "size": { "X": 10, "Y": 1, "Z": 3 }, "uv": { "X": 38, "Y": 38 } },
+ { "pos": { "X": 15, "Y": 3, "Z": 6 }, "size": { "X": 1, "Y": 26, "Z": 3 }, "uv": { "X": 52, "Y": 6 } },
+ { "pos": { "X": 0, "Y": 3, "Z": 6 }, "size": { "X": 1, "Y": 26, "Z": 3 }, "uv": { "X": 44, "Y": 6 } }
+ ]
+ },
+ {
+ "name": "leg0",
+ "boxes": [
+ { "pos": { "X": 0, "Y": 29, "Z": 6 }, "size": { "X": 3, "Y": 3, "Z": 3 }, "uv": { "X": 0, "Y": 44 } }
+ ]
+ },
+ {
+ "name": "leg1",
+ "boxes": [
+ { "pos": { "X": 13, "Y": 29, "Z": 6 }, "size": { "X": 3, "Y": 3, "Z": 3 }, "uv": { "X": 12, "Y": 44 } }
+ ]
+ },
+ {
+ "name": "leg2",
+ "boxes": [
+ { "pos": { "X": 0, "Y": 0, "Z": 6 }, "size": { "X": 3, "Y": 3, "Z": 3 }, "uv": { "X": 0, "Y": 38 } }
+ ]
+ },
+ {
+ "name": "leg3",
+ "boxes": [
+ { "pos": { "X": 13, "Y": 0, "Z": 6 }, "size": { "X": 3, "Y": 3, "Z": 3 }, "uv": { "X": 12, "Y": 38 } }
+ ]
+ }
+ ]
+ },
+ "chicken": {
+ "textureSize": { "X": 64, "Y": 32 },
+ "parts": [
+ {
+ "name": "head",
+ "translation": { "X": 0, "Y": 15, "Z": -4 },
+ "boxes": [
+ { "pos": { "X": -2, "Y": -6, "Z": -2 }, "size": { "X": 4, "Y": 6, "Z": 3 }, "uv": { "X": 0, "Y": 0 } }
+ ]
+ },
+ {
+ "name": "beak",
+ "translation": { "X": 0, "Y": 15, "Z": -4 },
+ "boxes": [
+ { "pos": { "X": -2, "Y": -4, "Z": -4 }, "size": { "X": 4, "Y": 2, "Z": 2 }, "uv": { "X": 14, "Y": 0 } }
+ ]
+ },
+ {
+ "name": "comb",
+ "translation": { "X": 0, "Y": 15, "Z": -4 },
+ "boxes": [
+ { "pos": { "X": -1, "Y": -2, "Z": -3 }, "size": { "X": 2, "Y": 2, "Z": 2 }, "uv": { "X": 14, "Y": 4 } }
+ ]
+ },
+ {
+ "name": "body",
+ "translation": { "X": 0, "Y": 16, "Z": 0 },
+ "boxes": [
+ { "pos": { "X": -3, "Y": -4, "Z": -3 }, "size": { "X": 6, "Y": 8, "Z": 6 }, "uv": { "X": 0, "Y": 9 } }
+ ]
+ },
+ {
+ "name": "leg0",
+ "translation": { "X": -2, "Y": 19, "Z": 1 },
+ "boxes": [
+ { "pos": { "X": -1, "Y": 0, "Z": -3 }, "size": { "X": 3, "Y": 5, "Z": 3 }, "uv": { "X": 26, "Y": 0 } }
+ ]
+ },
+ {
+ "name": "leg1",
+ "translation": { "X": 1, "Y": 19, "Z": 1 },
+ "boxes": [
+ { "pos": { "X": -1, "Y": 0, "Z": -3 }, "size": { "X": 3, "Y": 5, "Z": 3 }, "uv": { "X": 26, "Y": 0 } }
+ ]
+ },
+ {
+ "name": "wing0",
+ "translation": { "X": -4, "Y": 13, "Z": 0 },
+ "boxes": [
+ { "pos": { "X": 0, "Y": 0, "Z": -3 }, "size": { "X": 1, "Y": 4, "Z": 6 }, "uv": { "X": 24, "Y": 13 } }
+ ]
+ },
+ {
+ "name": "wing1",
+ "translation": { "X": 4, "Y": 13, "Z": 0 },
+ "boxes": [
+ { "pos": { "X": -1, "Y": 0, "Z": -3 }, "size": { "X": 1, "Y": 4, "Z": 6 }, "uv": { "X": 24, "Y": 13 } }
+ ]
+ }
+ ]
+ },
+ "cow": {
+ "textureSize": { "X": 64, "Y": 32 },
+ "parts": [
+ {
+ "name": "head",
+ "translation": { "X": 0, "Y": 4, "Z": -8 },
+ "boxes": [
+ { "pos": { "X": -4, "Y": -4, "Z": -6 }, "size": { "X": 8, "Y": 8, "Z": 6 }, "uv": { "X": 0, "Y": 0 } },
+ { "pos": { "X": -5, "Y": -5, "Z": -4 }, "size": { "X": 1, "Y": 3, "Z": 1 }, "uv": { "X": 22, "Y": 0 } },
+ { "pos": { "X": 4, "Y": -5, "Z": -4 }, "size": { "X": 1, "Y": 3, "Z": 1 }, "uv": { "X": 22, "Y": 0 } }
+ ]
+ },
+ {
+ "name": "body",
+ "translation": { "X": 0, "Y": 5, "Z": 2 },
+ "rotation": { "X": 90, "Y": 0, "Z": 0 },
+ "boxes": [
+ { "pos": { "X": -6, "Y": -10, "Z": -7 }, "size": { "X": 12, "Y": 18, "Z": 10 }, "uv": { "X": 18, "Y": 4 } },
+ { "pos": { "X": -2, "Y": 2, "Z": -8 }, "size": { "X": 4, "Y": 6, "Z": 1 }, "uv": { "X": 52, "Y": 0 } }
+ ]
+ },
+ {
+ "name": "leg0",
+ "translation": { "X": -4, "Y": 12, "Z": 7 },
+ "boxes": [
+ { "pos": { "X": -2, "Y": 0, "Z": -2 }, "size": { "X": 4, "Y": 12, "Z": 4 }, "uv": { "X": 0, "Y": 16 } }
+ ]
+ },
+ {
+ "name": "leg1",
+ "translation": { "X": 4, "Y": 12, "Z": 7 },
+ "boxes": [
+ { "pos": { "X": -2, "Y": 0, "Z": -2 }, "size": { "X": 4, "Y": 12, "Z": 4 }, "uv": { "X": 0, "Y": 16 } }
+ ]
+ },
+ {
+ "name": "leg2",
+ "translation": { "X": -4, "Y": 12, "Z": -6 },
+ "boxes": [
+ { "pos": { "X": -2, "Y": 0, "Z": -2 }, "size": { "X": 4, "Y": 12, "Z": 4 }, "uv": { "X": 0, "Y": 16 } }
+ ]
+ },
+ {
+ "name": "leg3",
+ "translation": { "X": 4, "Y": 12, "Z": -6 },
+ "boxes": [
+ { "pos": { "X": -2, "Y": 0, "Z": -2 }, "size": { "X": 4, "Y": 12, "Z": 4 }, "uv": { "X": 0, "Y": 16 } }
+ ]
+ }
+ ]
+ },
+ "mooshroom": {
+ "textureSize": { "X": 64, "Y": 32 },
+ "parts": [
+ {
+ "name": "head",
+ "translation": { "X": 0, "Y": 4, "Z": -8 },
+ "boxes": [
+ { "pos": { "X": -4, "Y": -4, "Z": -6 }, "size": { "X": 8, "Y": 8, "Z": 6 }, "uv": { "X": 0, "Y": 0 } },
+ { "pos": { "X": -5, "Y": -5, "Z": -4 }, "size": { "X": 1, "Y": 3, "Z": 1 }, "uv": { "X": 22, "Y": 0 } },
+ { "pos": { "X": 4, "Y": -5, "Z": -4 }, "size": { "X": 1, "Y": 3, "Z": 1 }, "uv": { "X": 22, "Y": 0 } }
+ ]
+ },
+ {
+ "name": "body",
+ "translation": { "X": 0, "Y": 5, "Z": 2 },
+ "rotation": { "X": 90, "Y": 0, "Z": 0 },
+ "boxes": [
+ { "pos": { "X": -6, "Y": -10, "Z": -7 }, "size": { "X": 12, "Y": 18, "Z": 10 }, "uv": { "X": 18, "Y": 4 } },
+ { "pos": { "X": -2, "Y": 2, "Z": -8 }, "size": { "X": 4, "Y": 6, "Z": 1 }, "uv": { "X": 52, "Y": 0 } }
+ ]
+ },
+ {
+ "name": "leg0",
+ "translation": { "X": -4, "Y": 12, "Z": 7 },
+ "boxes": [
+ { "pos": { "X": -2, "Y": 0, "Z": -2 }, "size": { "X": 4, "Y": 12, "Z": 4 }, "uv": { "X": 0, "Y": 16 } }
+ ]
+ },
+ {
+ "name": "leg1",
+ "translation": { "X": 4, "Y": 12, "Z": 7 },
+ "boxes": [
+ { "pos": { "X": -2, "Y": 0, "Z": -2 }, "size": { "X": 4, "Y": 12, "Z": 4 }, "uv": { "X": 0, "Y": 16 } }
+ ]
+ },
+ {
+ "name": "leg2",
+ "translation": { "X": -4, "Y": 12, "Z": -6 },
+ "boxes": [
+ { "pos": { "X": -2, "Y": 0, "Z": -2 }, "size": { "X": 4, "Y": 12, "Z": 4 }, "uv": { "X": 0, "Y": 16 } }
+ ]
+ },
+ {
+ "name": "leg3",
+ "translation": { "X": 4, "Y": 12, "Z": -6 },
+ "boxes": [
+ { "pos": { "X": -2, "Y": 0, "Z": -2 }, "size": { "X": 4, "Y": 12, "Z": 4 }, "uv": { "X": 0, "Y": 16 } }
+ ]
+ }
+ ]
+ },
+ "dragon_head": {
+ "textureSize": { "X": 256, "Y": 256 },
+ "parts": [
+ {
+ "name": "head",
+ "boxes": [
+ // upperlip
+ { "pos": { "X": -6, "Y": -1, "Z": -24 }, "size": { "X": 12, "Y": 5, "Z": 16 }, "uv": { "X": 176, "Y": 44 } },
+ // upperhead
+ { "pos": { "X": -8, "Y": -8, "Z": -10 }, "size": { "X": 16, "Y": 16, "Z": 16 }, "uv": { "X": 112, "Y": 30 } },
+ // scale
+ { "pos": { "X": 3, "Y": -12, "Z": -4 }, "size": { "X": 2, "Y": 4, "Z": 6 }, "uv": { "X": 0, "Y": 0 } },
+ { "pos": { "X": -5, "Y": -12, "Z": -4 }, "size": { "X": 2, "Y": 4, "Z": 6 }, "uv": { "X": 0, "Y": 0 }, "mirror": true },
+ // nostril
+ { "pos": { "X": 3, "Y": -3, "Z": -22 }, "size": { "X": 2, "Y": 2, "Z": 4 }, "uv": { "X": 112, "Y": 0 } },
+ { "pos": { "X": -5, "Y": -3, "Z": -22 }, "size": { "X": 2, "Y": 2, "Z": 4 }, "uv": { "X": 112, "Y": 0 }, "mirror": true },
+ ]
+ },
+ {
+ "name": "jaw",
+ "translation": { "X": 0, "Y": 4, "Z": -8 },
+ "boxes": [
+ { "pos": { "X": -6, "Y": 0, "Z": -16 }, "size": { "X": 12, "Y": 4, "Z": 16 }, "uv": { "X": 176, "Y": 65 } }
+ ]
+ }
+ ]
+ },
+ "pig": {
+ "textureSize": { "X": 64, "Y": 32 },
+ "parts": [
+ {
+ "name": "head",
+ "translation": { "X": 0, "Y": 12, "Z": -6 },
+ "boxes": [
+ { "pos": { "X": -4, "Y": -4, "Z": -8 }, "size": { "X": 8, "Y": 8, "Z": 8 }, "uv": { "X": 0, "Y": 0 } },
+ { "pos": { "X": -2, "Y": 0, "Z": -9 }, "size": { "X": 4, "Y": 3, "Z": 1 }, "uv": { "X": 16, "Y": 16 } }
+ ]
+ },
+ {
+ "name": "body",
+ "translation": { "X": 0, "Y": 11, "Z": 2 },
+ "rotation": { "X": 90, "Y": 0, "Z": 0 },
+ "boxes": [
+ { "pos": { "X": -5, "Y": -10, "Z": -7 }, "size": { "X": 10, "Y": 16, "Z": 8 }, "uv": { "X": 28, "Y": 8 } }
+ ]
+ },
+ {
+ "name": "leg0",
+ "translation": { "X": -3, "Y": 18, "Z": 7 },
+ "boxes": [
+ { "pos": { "X": -2, "Y": 0, "Z": -2 }, "size": { "X": 4, "Y": 6, "Z": 4 }, "uv": { "X": 0, "Y": 16 } }
+ ]
+ },
+ {
+ "name": "leg1",
+ "translation": { "X": 3, "Y": 18, "Z": 7 },
+ "boxes": [
+ { "pos": { "X": -2, "Y": 0, "Z": -2 }, "size": { "X": 4, "Y": 6, "Z": 4 }, "uv": { "X": 0, "Y": 16 } }
+ ]
+ },
+ {
+ "name": "leg2",
+ "translation": { "X": -3, "Y": 18, "Z": -5 },
+ "boxes": [
+ { "pos": { "X": -2, "Y": 0, "Z": -2 }, "size": { "X": 4, "Y": 6, "Z": 4 }, "uv": { "X": 0, "Y": 16 } }
+ ]
+ },
+ {
+ "name": "leg3",
+ "translation": { "X": 3, "Y": 18, "Z": -5 },
+ "boxes": [
+ { "pos": { "X": -2, "Y": 0, "Z": -2 }, "size": { "X": 4, "Y": 6, "Z": 4 }, "uv": { "X": 0, "Y": 16 } }
+ ]
+ }
+ ]
+ },
+ "snowgolem": {
+ "textureSize": { "X": 64, "Y": 64 },
+ "parts": [
+ {
+ "name": "head",
+ "translation": { "X": 0, "Y": 4, "Z": 0 },
+ "boxes": [
+ { "pos": { "X": -4, "Y": -8, "Z": -4 }, "size": { "X": 8, "Y": 8, "Z": 8 }, "uv": { "X": 0, "Y": 0 }, "inflate": -0.5 }
+ ]
+ },
+ {
+ "name": "arm1",
+ "translation": { "X": 0, "Y": 6, "Z": 0 },
+ "boxes": [
+ { "pos": { "X": -1, "Y": 0, "Z": -1 }, "size": { "X": 12, "Y": 2, "Z": 2 }, "uv": { "X": 32, "Y": 0 }, "inflate": -0.5 }
+ ]
+ },
+ {
+ "name": "arm2",
+ "translation": { "X": 0, "Y": 6, "Z": 0 },
+ "boxes": [
+ { "pos": { "X": -1, "Y": 0, "Z": -1 }, "size": { "X": 12, "Y": 2, "Z": 2 }, "uv": { "X": 32, "Y": 0 }, "inflate": -0.5 }
+ ]
+ },
+ {
+ "name": "piece1",
+ "translation": { "X": 0, "Y": 13, "Z": 0 },
+ "boxes": [
+ { "pos": { "X": -5, "Y": -10, "Z": -5 }, "size": { "X": 10, "Y": 10, "Z": 10 }, "uv": { "X": 0, "Y": 16 }, "inflate": -0.5 }
+ ]
+ },
+ {
+ "name": "piece2",
+ "translation": { "X": 0, "Y": 24, "Z": 0 },
+ "boxes": [
+ { "pos": { "X": -6, "Y": -12, "Z": -6 }, "size": { "X": 12, "Y": 12, "Z": 12 }, "uv": { "X": 0, "Y": 36 }, "inflate": -0.5 }
+ ]
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/PckStuido.ModelSupport/Resources/modelMetaData.json b/PckStuido.ModelSupport/Resources/modelMetaData.json
new file mode 100644
index 00000000..9be05f36
--- /dev/null
+++ b/PckStuido.ModelSupport/Resources/modelMetaData.json
@@ -0,0 +1,739 @@
+{
+ "bat": {
+ "textureLocations": [
+ "res/mob/bat"
+ ],
+ "materialName": "bat",
+ "parts": [
+ {
+ "name": "head",
+ "children": [
+ { "name": "rightEar" },
+ { "name": "leftEar" }
+ ]
+ },
+ {
+ "name": "body",
+ "children": [
+ {
+ "name": "rightWing",
+ "children": [
+ { "name": "rightWingTip" }
+ ]
+ },
+ {
+ "name": "leftWing",
+ "children": [
+ { "name": "leftWingTip" }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "bed": {
+ "textureLocations": [
+ "res/item/bed"
+ ],
+ "uv_offsets": [ {"X": 0, "Y": 64} ]
+ },
+ "blaze": {
+ "textureLocations": [
+ "res/mob/fire"
+ ],
+ "materialName": "blaze_head"
+ },
+ "boat": {
+ "textureLocations": [
+ "res/item/boat/boat_acacia",
+ "res/item/boat/boat_birch",
+ "res/item/boat/boat_darkoak",
+ "res/item/boat/boat_jungle",
+ "res/item/boat/boat_oak",
+ "res/item/boat/boat_spruce"
+ ]
+ },
+ "chicken": {
+ "textureLocations": [
+ "res/mob/chicken"
+ ]
+ },
+ "cow": {
+ "textureLocations": [
+ "res/mob/cow"
+ ]
+ },
+ "creeper": {
+ "textureLocations": [
+ "res/mob/creeper"
+ ]
+ },
+ "creeper_head": {
+ "textureLocations": [
+ "res/mob/creeper"
+ ]
+ },
+ "dolphin": {
+ "textureLocations": [
+ "res/mob/dolphin"
+ ],
+ "parts": [
+ {
+ "name": "body",
+ "children": [
+ {
+ "name": "head",
+ "children": [ { "name": "nose" } ]
+ },
+ {
+ "name": "tail",
+ "children": [ { "name": "tail_fin" } ]
+ },
+ { "name": "right_fin" },
+ { "name": "left_fin" },
+ { "name": "back_fin" }
+ ]
+ }
+ ]
+ },
+ "dragon": {
+ "textureLocations": [
+ "res/mob/enderdragon/ender"
+ ],
+ "materialName": "ender_dragon",
+ "parts": [
+ { "name": "body" },
+ // only needs to be inside when neck 1-5 aren't present
+ { "name": "neck" },
+
+ // neck 1-5 & tail 1-12 are not required to be inside the model
+ { "name": "neck1" },
+ { "name": "neck2" },
+ { "name": "neck3" },
+ { "name": "neck4" },
+ { "name": "neck5" },
+
+ { "name": "tail1" },
+ { "name": "tail2" },
+ { "name": "tail3" },
+ { "name": "tail4" },
+ { "name": "tail5" },
+ { "name": "tail6" },
+ { "name": "tail7" },
+ { "name": "tail8" },
+ { "name": "tail9" },
+ { "name": "tail10" },
+ { "name": "tail11" },
+ { "name": "tail12" },
+
+ {
+ "name": "head",
+ "children": [ { "name": "jaw" } ]
+ },
+ {
+ "name": "wing",
+ "children": [ { "name": "wingtip" } ]
+ },
+ {
+ "name": "wing1",
+ "children": [ { "name": "wingtip1" } ]
+ },
+ {
+ "name": "rearleg",
+ "children": [
+ {
+ "name": "rearlegtip",
+ "children": [ { "name": "rearfoot" } ]
+ }
+ ]
+ },
+ {
+ "name": "rearleg1",
+ "children": [
+ {
+ "name": "rearlegtip1",
+ "children": [ { "name": "rearfoot1" } ]
+ }
+ ]
+ },
+ {
+ "name": "frontleg",
+ "children": [
+ {
+ "name": "frontlegtip",
+ "children": [ { "name": "frontfoot" } ]
+ }
+ ]
+ },
+ {
+ "name": "frontleg1",
+ "children": [
+ {
+ "name": "frontlegtip1",
+ "children": [ { "name": "frontfoot1" } ]
+ }
+ ]
+ }
+ ]
+ },
+ "dragon_head": {
+ "textureLocations": [
+ "res/mob/enderdragon/ender"
+ ],
+ "parts": [
+ {
+ "name": "head",
+ "children": [ { "name": "jaw" } ]
+ }
+ ]
+ },
+ "enderman": {
+ "textureLocations": [
+ "res/mob/enderman"
+ ],
+ "materialName": "enderman" // "enderman_invisible" also valid
+ },
+ "ghast": {
+ "textureLocations": [
+ "res/mob/ghast",
+ "res/mob/ghast_fire"
+ ],
+ "materialName": "ghast"
+ },
+ "guardian": {
+ "textureLocations": [
+ "res/mob/guardian",
+ "res/mob/guardian_elder"
+ ],
+ "materialName": "guardian",
+ "parts": [
+ {
+ "name": "head",
+ "children": [
+ { "name": "eye" },
+ {
+ "name": "tailpart0",
+ "children": [
+ {
+ "name": "tailpart1",
+ "children": [ { "name": "tailpart2" } ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "irongolem": {
+ "textureLocations": [
+ "res/mob/villager_golem"
+ ],
+ "materialName": "iron_golem"
+ },
+ "lavaslime": {
+ "textureLocations": [
+ "res/mob/lava"
+ ],
+ "materialName": "magma_cube"
+ },
+ "llama": {
+ "textureLocations": [
+ "res/mob/llama/llama",
+ "res/mob/llama/llama_brown",
+ "res/mob/llama/llama_creamy",
+ "res/mob/llama/llama_gray",
+ "res/mob/llama/llama_white"
+ ]
+ },
+ "llamaspit": {
+ "textureLocations": [
+ "res/mob/llama/spit"
+ ]
+ },
+ "minecart": {
+ "textureLocations": [
+ "res/item/cart"
+ ]
+ },
+ // the ocelot model is weird.. -miku
+ "ocelot": {
+ "textureLocations": [
+ "res/mob/ozelot"
+ ]
+ },
+ "parrot": {
+ "textureLocations": [
+ "res/mob/parrot/parrot_blue",
+ "res/mob/parrot/parrot_green",
+ "res/mob/parrot/parrot_grey",
+ "res/mob/parrot/parrot_red_blue",
+ "res/mob/parrot/parrot_yellow_blue"
+ ],
+ "parts": [
+ {
+ "name": "head",
+ "children": [
+ { "name": "head2" },
+ { "name": "beak1" },
+ { "name": "beak2" },
+ { "name": "feather" }
+ ]
+ },
+ { "name": "body" },
+ { "name": "tail" },
+ { "name": "wing0" },
+ { "name": "wing1" },
+ { "name": "leg0" },
+ { "name": "leg1" }
+ ]
+ },
+ "phantom": {
+ "textureLocations": [
+ "res/mob/phantom"
+ ],
+ "materialName": "phantom", // phantom_invisible is also valid
+ "parts": [
+ {
+ "name": "body",
+ "children": [
+ { "name": "head" },
+ {
+ "name": "wing0",
+ "children": [ { "name": "wingtip0" } ]
+ },
+ {
+ "name": "wing1",
+ "children": [ { "name": "wingtip1" } ]
+ },
+ {
+ "name": "tail",
+ "children": [ { "name": "tailtip" } ]
+ }
+ ]
+ }
+ ]
+ },
+ "pig": {
+ "textureLocations": [
+ "res/mob/pig",
+ "res/mob/saddle"
+ ]
+ },
+ "pigzombie": {
+ "textureLocations": [
+ "res/mob/pigzombie"
+ ],
+ "materialName": "zombie_pigman"
+ },
+ "polarbear": {
+ "textureLocations": [
+ "res/mob/bear/polarbear"
+ ]
+ },
+ "rabbit": {
+ "textureLocations": [
+ "res/mob/rabbit/black",
+ "res/mob/rabbit/brown",
+ "res/mob/rabbit/caerbannog",
+ "res/mob/rabbit/gold",
+ "res/mob/rabbit/salt",
+ "res/mob/rabbit/toast",
+ "res/mob/rabbit/white",
+ "res/mob/rabbit/white_splotched"
+ ]
+ },
+ "sheep": {
+ "textureLocations": [
+ "res/mob/sheep",
+ "res/mob/sheep_fur"
+ ],
+ "materialName": "sheep"
+ },
+ "sheep.sheared": {
+ "textureLocations": [
+ "res/mob/sheep"
+ ],
+ "materialName": "sheep"
+ },
+ "shulker": {
+ "textureLocations": [
+ "res/mob/shulker/endergolem",
+ "res/mob/shulker/spark"
+ ],
+ "materialName": "shulker"
+ },
+ "silverfish": {
+ "textureLocations": [
+ "res/mob/silverfish"
+ ]
+ },
+ "skeleton": {
+ "textureLocations": [
+ "res/mob/skeleton"
+ ],
+ "materialName": "skeleton"
+ },
+ "skeleton.stray": {
+ "textureLocations": [
+ "res/mob/skeleton/stray"
+ ],
+ "materialName": "stray"
+ },
+ "skeleton.wither": {
+ "textureLocations": [
+ "res/mob/skeleton_wither"
+ ],
+ "materialName": "wither_skeleton"
+ },
+ "slime": {
+ "textureLocations": [
+ "res/mob/slime"
+ ]
+ },
+ "slime.armor": {
+ "textureLocations": [
+ "res/mob/slime"
+ ]
+ },
+ "snowgolem": {
+ "textureLocations": [
+ "res/mob/snowman"
+ ]
+ },
+ "spider": {
+ "textureLocations": [
+ "res/mob/spider",
+ "res/mob/cavespider"
+ ],
+ "materialName": "spider" // "spider_invisible" also valid
+ },
+ "squid": {
+ "textureLocations": [
+ "res/mob/squid"
+ ]
+ },
+ "trident": {
+ "textureLocations": [
+ "res/item/trident"
+ ]
+ },
+ "turtle": {
+ "textureLocations": [
+ "res/mob/sea_turtle"
+ ]
+ },
+ "villager": {
+ "textureLocations": [
+ "res/mob/villager/villager",
+ "res/mob/villager/butcher",
+ "res/mob/villager/farmer",
+ "res/mob/villager/librarian",
+ "res/mob/villager/priest",
+ "res/mob/villager/smith"
+ ]
+ },
+ "villager.witch": {
+ "textureLocations": [
+ "res/mob/witch"
+ ]
+ },
+ "vex": {
+ "textureLocations": [
+ "res/mob/illager/vex",
+ "res/mob/illager/vex_charging"
+ ]
+ },
+ "evoker": {
+ "textureLocations": [
+ "res/mob/illager/evoker"
+ ]
+ },
+ "vindicator": {
+ "textureLocations": [
+ "res/mob/illager/vindicator"
+ ]
+ },
+ "witherBoss": {
+ "textureLocations": [
+ "res/mob/wither/wither",
+ "res/mob/wither/wither_invulnerable"
+ ],
+ "materialName": "wither_boss"
+ },
+ "wolf": {
+ "textureLocations": [
+ "res/mob/wolf",
+ "res/mob/wolf_angry",
+ "res/mob/wolf_tame"
+ ],
+ "materialName": "wolf"
+ },
+ "zombie": {
+ "textureLocations": [
+ "res/mob/zombie"
+ ]
+ },
+ "zombie.husk": {
+ "textureLocations": [
+ "res/mob/zombie/husk"
+ ]
+ },
+ "zombie.villager": {
+ "textureLocations": [
+ "res/mob/zombie_villager/zombie_villager",
+ "res/mob/zombie_villager/zombie_butcher",
+ "res/mob/zombie_villager/zombie_farmer",
+ "res/mob/zombie_villager/zombie_librarian",
+ "res/mob/zombie_villager/zombie_priest",
+ "res/mob/zombie_villager/zombie_smith"
+ ]
+ },
+ "horse.v2": {
+ // markings and armor not included
+ "textureLocations": [
+ "res/mob/horse/donkey",
+ "res/mob/horse/horse_black",
+ "res/mob/horse/horse_brown",
+ "res/mob/horse/horse_chestnut",
+ "res/mob/horse/horse_creamy",
+ "res/mob/horse/horse_darkbrown",
+ "res/mob/horse/horse_gray",
+ "res/mob/horse/horse_skeleton",
+ "res/mob/horse/horse_white",
+ "res/mob/horse/horse_zombie",
+ "res/mob/horse/mule"
+ ],
+ "parts": [
+ {
+ "name": "Neck",
+ "children": [
+ {
+ "name": "Head",
+ "children": [
+ { "name": "HeadSaddle" },
+ { "name": "UMouth" },
+ { "name": "Ear1" },
+ { "name": "Ear2" },
+ { "name": "MuleEarL" },
+ { "name": "MuleEarR" },
+ { "name": "SaddleMouthL" },
+ { "name": "SaddleMouthR" }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "Body",
+ "children": [
+ { "name": "TailA" },
+ { "name": "Saddle" }
+ ]
+ },
+ { "name": "Mane" },
+ { "name": "Leg1A" },
+ { "name": "Leg2A" },
+ { "name": "Leg3A" },
+ { "name": "Leg4A" },
+ { "name": "Bag1" },
+ { "name": "Bag2" },
+ { "name": "SaddleMouthLine" },
+ { "name": "SaddleMouthLineR" }
+ ]
+ },
+ "cat": {
+ "textureLocations": [
+ "res/mob/cat_black",
+ "res/mob/cat_red",
+ "res/mob/cat_siamese"
+ ]
+ },
+ "zombie.drowned": {
+ "textureLocations": [
+ "res/mob/zombie/drowned"
+ ],
+ "materialName": "drowned"
+ },
+ "endermite": {
+ "textureLocations": [
+ "res/mob/endermite"
+ ]
+ },
+ "cod": {
+ "textureLocations": [
+ "res/mob/fish/cod"
+ ]
+ },
+ "pufferfish.small": {
+ "textureLocations": [
+ "res/mob/fish/pufferfish"
+ ]
+ },
+ "pufferfish.mid": {
+ "textureLocations": [
+ "res/mob/fish/pufferfish"
+ ]
+ },
+ "pufferfish.large": {
+ "textureLocations": [
+ "res/mob/fish/pufferfish"
+ ]
+ },
+ "salmon": {
+ "textureLocations": [
+ "res/mob/fish/salmon"
+ ]
+ },
+ "skeleton_head": {
+ "textureLocations": [
+ "res/mob/skeleton"
+ ]
+ },
+ "skeleton_wither_head": {
+ "textureLocations": [
+ "res/mob/skeleton_wither"
+ ]
+ },
+ "stray.armor": {
+ "textureLocations": [
+ "res/mob/skeleton/stray_overlay"
+ ]
+ },
+ "stray_armor": {
+ "textureLocations": [
+ "res/mob/skeleton/stray_overlay"
+ ]
+ },
+ "tropicalfish_a": {
+ "textureLocations": [
+ "res/mob/fish/tropical_a",
+ "res/mob/fish/tropical_a_pattern_1",
+ "res/mob/fish/tropical_a_pattern_2",
+ "res/mob/fish/tropical_a_pattern_3",
+ "res/mob/fish/tropical_a_pattern_4",
+ "res/mob/fish/tropical_a_pattern_5",
+ "res/mob/fish/tropical_a_pattern_6"
+ ]
+ },
+ "tropicalfish_b": {
+ "textureLocations": [
+ "res/mob/fish/tropical_b",
+ "res/mob/fish/tropical_b_pattern_1",
+ "res/mob/fish/tropical_b_pattern_2",
+ "res/mob/fish/tropical_b_pattern_3",
+ "res/mob/fish/tropical_b_pattern_4",
+ "res/mob/fish/tropical_b_pattern_5",
+ "res/mob/fish/tropical_b_pattern_6"
+ ]
+ },
+ "zombie_head": {
+ "textureLocations": [
+ "res/mob/zombie"
+ ]
+ },
+ "mooshroom": {
+ "textureLocations": [
+ "res/mob/redcow"
+ ]
+ },
+ "witherBoss.armor": {
+ "textureLocations": [
+ "res/mob/wither/wither_armor"
+ ]
+ },
+
+ "villager_v2": {
+ "textureLocations": [
+ "res/mob/villager/villagerBase1",
+ "res/mob/villager/villagerBase2",
+ "res/mob/villager/villagerBase3",
+ "res/mob/villager/villagerBase4",
+ "res/mob/villager/villagerBase5",
+ "res/mob/villager/villagerBase6",
+
+ "res/mob/wandering_trader",
+
+ "res/mob/villager/professions/armorer",
+ "res/mob/villager/professions/butcher",
+ "res/mob/villager/professions/cartographer",
+ "res/mob/villager/professions/cleric",
+ "res/mob/villager/professions/farmer",
+ "res/mob/villager/professions/fisherman",
+ "res/mob/villager/professions/fletcher",
+ "res/mob/villager/professions/leatherworker",
+ "res/mob/villager/professions/librarian",
+ "res/mob/villager/professions/nitwit",
+ "res/mob/villager/professions/shepherd",
+ "res/mob/villager/professions/stonemason",
+ "res/mob/villager/professions/toolsmith",
+ "res/mob/villager/professions/unskilled",
+ "res/mob/villager/professions/weaponsmith",
+
+ "res/mob/villager/biomes/biome_desert",
+ "res/mob/villager/biomes/biome_jungle",
+ "res/mob/villager/biomes/biome_plains",
+ "res/mob/villager/biomes/biome_savanna",
+ "res/mob/villager/biomes/biome_snow",
+ "res/mob/villager/biomes/biome_swamp",
+ "res/mob/villager/biomes/biome_taiga",
+
+ "res/mob/villager/levels/level_diamond",
+ "res/mob/villager/levels/level_gold",
+ "res/mob/villager/levels/level_iron"
+ ]
+ },
+ "zombie.villager_v2": {
+ "textureLocations": [
+ "res/mob/zombie_villager/zombie_villager",
+ "res/mob/zombie_villager/zombie_butcher",
+ "res/mob/zombie_villager/zombie_farmer",
+ "res/mob/zombie_villager/zombie_librarian",
+ "res/mob/zombie_villager/zombie_priest",
+ "res/mob/zombie_villager/zombie_smith",
+
+ "res/mob/zombie_villager/biomes/biome-desert-zombie",
+ "res/mob/zombie_villager/biomes/biome-jungle-zombie",
+ "res/mob/zombie_villager/biomes/biome-plains-zombie",
+ "res/mob/zombie_villager/biomes/biome-savanna-zombie",
+ "res/mob/zombie_villager/biomes/biome-snow-zombie",
+ "res/mob/zombie_villager/biomes/biome-swamp-zombie",
+ "res/mob/zombie_villager/biomes/biome-taiga-zombie",
+
+ "res/mob/zombie_villager/professions/armorer",
+ "res/mob/zombie_villager/professions/butcher",
+ "res/mob/zombie_villager/professions/cartographer",
+ "res/mob/zombie_villager/professions/cleric",
+ "res/mob/zombie_villager/professions/farmer",
+ "res/mob/zombie_villager/professions/fisherman",
+ "res/mob/zombie_villager/professions/fletcher",
+ "res/mob/zombie_villager/professions/leatherworker",
+ "res/mob/zombie_villager/professions/librarian",
+ "res/mob/zombie_villager/professions/nitwit",
+ "res/mob/zombie_villager/professions/shepherd",
+ "res/mob/zombie_villager/professions/stonemason",
+ "res/mob/zombie_villager/professions/toolsmith",
+ "res/mob/zombie_villager/professions/weaponsmith"
+ ]
+ },
+ "pillager": {
+ "textureLocations": [
+ "res/mob/pillager"
+ ]
+ },
+ "ravager": {
+ "textureLocations": [
+ "res/mob/illager/ravager"
+ ]
+ },
+
+ "panda": {
+ "textureLocations": [
+ "res/mob/panda/panda",
+ "res/mob/panda/panda_aggressive",
+ "res/mob/panda/panda_brown",
+ "res/mob/panda/panda_lazy",
+ "res/mob/panda/panda_playful",
+ "res/mob/panda/panda_sneezy",
+ "res/mob/panda/panda_worried"
+ ]
+ }
+}
diff --git a/PckStuido.ModelSupport/SkinModelImporter.cs b/PckStuido.ModelSupport/SkinModelImporter.cs
new file mode 100644
index 00000000..2cc7c2a8
--- /dev/null
+++ b/PckStuido.ModelSupport/SkinModelImporter.cs
@@ -0,0 +1,557 @@
+/* Copyright (c) 2024-present miku-666
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1.The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+**/
+using System;
+using System.IO;
+using System.Linq;
+using System.Drawing;
+using System.Numerics;
+using System.Diagnostics;
+using System.Windows.Forms;
+using System.Drawing.Imaging;
+using System.Collections.Generic;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+
+using PckStudio.Core;
+using PckStudio.Core.Skin;
+using PckStudio.Core.Extensions;
+using PckStudio.Core.FileFormats;
+using PckStudio.ModelSupport.Format.External;
+using PckStudio.Core.Additional_Popups;
+using PckStudio.ModelSupport.Internal.Format;
+
+namespace PckStudio.ModelSupport
+{
+ public sealed class SkinModelImporter : ModelImporter
+ {
+ public static SkinModelImporter Default { get; } = new SkinModelImporter();
+
+ private SkinModelImporter()
+ {
+ InternalAddProvider(new("Pck skin model(*.psm)", "*.psm"), ImportPsm, ExportPsm);
+ InternalAddProvider(new("Block bench model(*.bbmodel)", "*.bbmodel"), ImportBlockBenchModel, ExportBlockBenchModel);
+ InternalAddProvider(new("Bedrock (Legacy) Model(*.geo.json;*.json)", "*.geo.json;*.json"), ImportBedrockJson, ExportBedrockJson);
+ }
+
+ internal static SkinModelInfo ImportPsm(string filepath)
+ {
+ var reader = new PSMFileReader();
+ PSMFile csmbFile = reader.FromFile(filepath);
+ return new SkinModelInfo(null, csmbFile.SkinANIM, new(csmbFile.Parts, csmbFile.Offsets));
+ }
+
+ internal static void ExportPsm(string filepath, SkinModelInfo modelInfo)
+ {
+ PSMFile psmFile = new PSMFile(PSMFile.CurrentVersion, modelInfo.Anim);
+ psmFile.Parts.AddRange(modelInfo.Model.AdditionalBoxes);
+ psmFile.Offsets.AddRange(modelInfo.Model.PartOffsets);
+ var writer = new PSMFileWriter(psmFile);
+ writer.WriteToFile(filepath);
+ }
+
+ internal static SkinModelInfo ImportBlockBenchModel(string filepath)
+ {
+ BlockBenchModel blockBenchModel = JsonConvert.DeserializeObject(File.ReadAllText(filepath));
+ if (!blockBenchModel.Format.UseBoxUv)
+ {
+ Trace.TraceError($"[{nameof(SkinModelImporter)}:{nameof(ImportBlockBenchModel)}] Failed to import skin '{blockBenchModel.Name}': Skin does not use box uv.");
+ return null;
+ }
+
+ IEnumerable partOffsets = blockBenchModel.Outliner
+ .Where(token => token.Type == JTokenType.Object && SkinBOX.IsValidType(TryConvertToSkinBoxType(token.ToObject().Name)))
+ .Select(token => token.ToObject())
+ .Select(outline => new SkinPartOffset(TryConvertToSkinBoxType(outline.Name), -GetOffsetFromOrigin(TryConvertToSkinBoxType(outline.Name), outline.Origin).Y))
+ .Where(offset => offset.Value != 0f);
+
+ IEnumerable boxes = ReadOutliner(null, blockBenchModel.Outliner, blockBenchModel.Elements);
+
+ Image texture = null;
+ if (blockBenchModel.Textures.IndexInRange(0))
+ {
+ texture = blockBenchModel.Textures[0];
+ texture = SwapBoxBottomTexture(texture, boxes);
+ }
+
+ return CreateSkinModelInfo(texture, boxes, partOffsets);
+ }
+
+ private static SkinModelInfo CreateSkinModelInfo(Image texture, IEnumerable boxes, IEnumerable partOffsets)
+ {
+ SkinANIM skinANIM = (
+ SkinAnimMask.HEAD_DISABLED |
+ SkinAnimMask.HEAD_OVERLAY_DISABLED |
+ SkinAnimMask.BODY_DISABLED |
+ SkinAnimMask.BODY_OVERLAY_DISABLED |
+ SkinAnimMask.RIGHT_ARM_DISABLED |
+ SkinAnimMask.RIGHT_ARM_OVERLAY_DISABLED |
+ SkinAnimMask.LEFT_ARM_DISABLED |
+ SkinAnimMask.LEFT_ARM_OVERLAY_DISABLED |
+ SkinAnimMask.RIGHT_LEG_DISABLED |
+ SkinAnimMask.RIGHT_LEG_OVERLAY_DISABLED |
+ SkinAnimMask.LEFT_LEG_DISABLED |
+ SkinAnimMask.LEFT_LEG_OVERLAY_DISABLED);
+
+ skinANIM = skinANIM.SetFlag(SkinAnimFlag.RESOLUTION_64x64, texture.Size.Width == texture.Size.Height);
+
+ SkinModel skinModel = new SkinModel();
+
+ skinModel.PartOffsets.AddRange(partOffsets);
+
+ SkinBOX ApplyOffset(SkinBOX box)
+ {
+ SkinPartOffset offset = skinModel.PartOffsets.FirstOrDefault(offset => offset.Type == (box.IsOverlayPart() ? box.GetBaseType() : box.Type));
+ return string.IsNullOrEmpty(offset.Type) ? box : new SkinBOX(box.Type, box.Pos - (Vector3.UnitY * offset.Value), box.Size, box.UV, box.HideWithArmor, box.Mirror, box.Scale);
+ }
+
+ IEnumerable convertedBoxes = boxes.Select(ApplyOffset);
+
+ IEnumerable customBoxes = convertedBoxes.Where(box => !SkinBOX.KnownHashes.ContainsKey(box.GetHashCode()));
+
+ skinModel.AdditionalBoxes.AddRange(customBoxes);
+
+ // check for know boxes and filter them out
+ SkinAnimMask mask = (SkinAnimMask)convertedBoxes
+ .Where(box => SkinBOX.KnownHashes.ContainsKey(box.GetHashCode()) && Enum.IsDefined(typeof(SkinAnimMask), (1 >> (int)SkinBOX.KnownHashes[box.GetHashCode()])))
+ .Select(box => SkinBOX.KnownHashes[box.GetHashCode()])
+ .Select(i => 1 << (int)i)
+ .DefaultIfEmpty()
+ .Aggregate((a, b) => a | b);
+
+ if (mask != SkinAnimMask.NONE)
+ skinANIM &= ~mask;
+
+ return new SkinModelInfo(texture, skinANIM, skinModel);
+ }
+
+ private static IEnumerable ReadOutliner(string parentName, JArray oulineChildren, IReadOnlyCollection elements)
+ {
+ IEnumerable boxes = oulineChildren
+ .Where(token => token.Type == JTokenType.String && Guid.TryParse(token.ToString(), out Guid elementUuid) && elements.Any(e => e.Uuid == elementUuid))
+ .Select(token => elements.First(e => Guid.Parse(token.ToString()) == e.Uuid))
+ .Where(element => element.Type == "cube" && element.UseBoxUv && element.Export && SkinBOX.IsValidType(TryConvertToSkinBoxType(parentName ?? element.Name)))
+ .Select(element => LoadElement(element, TryConvertToSkinBoxType(parentName ?? element.Name)));
+
+ IEnumerable childOutlines = oulineChildren
+ .Where(token => token.Type == JTokenType.Object)
+ .Select(token => token.ToObject());
+
+ foreach (Outline childOutline in childOutlines)
+ {
+ boxes = boxes.Concat(ReadOutliner(parentName ?? childOutline.Name, childOutline.Children, elements));
+ }
+ return boxes;
+ }
+
+ private static SkinBOX LoadElement(Element element, string outlineName)
+ {
+ var boundingBox = new BoundingBox(element.From, element.To);
+ Vector3 pos = boundingBox.Start.ToNumericsVector();
+ Vector3 size = boundingBox.Volume.ToNumericsVector();
+ Vector2 uv = element.UvOffset;
+
+ pos = TranslateToInternalPosition(outlineName, pos, size, new Vector3(1, 1, 0));
+
+ var box = new SkinBOX(outlineName, pos, size, uv, mirror: element.MirrorUv);
+ if (SkinBOX.IsBasePart(outlineName) && ((outlineName == "HEAD" && element.Inflate == 0.5f) || (element.Inflate >= 0.25f && element.Inflate <= 0.5f)))
+ box = new SkinBOX(SkinBOXExtensions.GetOverlayType(outlineName), pos, size, uv, mirror: element.MirrorUv);
+ return box;
+ }
+
+ internal static void ExportBlockBenchModel(string filepath, SkinModelInfo modelInfo)
+ {
+ Image exportTexture = SwapBoxBottomTexture(modelInfo);
+ BlockBenchModel blockBenchModel = BlockBenchModel.Create(BlockBenchFormatInfos.BedrockEntity, Path.GetFileNameWithoutExtension(filepath), new Size(64, exportTexture.Width == exportTexture.Height ? 64 : 32), [exportTexture]);
+
+ Dictionary outliners = new Dictionary(5);
+ List elements = new List(modelInfo.Model.AdditionalBoxes.Count);
+
+ Dictionary offsetLookUp = new Dictionary(5);
+
+ void AddElement(SkinBOX box)
+ {
+ string offsetType = box.IsOverlayPart() ? box.GetBaseType() : box.Type;
+
+ Vector3 offset = GetOffsetForPart(offsetType, ref offsetLookUp, modelInfo.Model.PartOffsets);
+ if (!outliners.ContainsKey(offsetType))
+ {
+ outliners.Add(offsetType, new Outline(offsetType)
+ {
+ Origin = GetSkinPartPivot(offsetType, new Vector3(1, 1, 0)) + offset
+ });
+ }
+
+ Element element = CreateElement(box);
+
+ element.From += offset;
+ element.To += offset;
+
+ elements.Add(element);
+ outliners[offsetType].Children.Add(element.Uuid);
+ }
+
+ ANIM2BOX(modelInfo.Anim, AddElement);
+
+ foreach (SkinBOX box in modelInfo.Model.AdditionalBoxes)
+ {
+ AddElement(box);
+ }
+ blockBenchModel.Elements = elements.ToArray();
+ blockBenchModel.Outliner = JArray.FromObject(outliners.Values);
+
+ string content = JsonConvert.SerializeObject(blockBenchModel);
+ File.WriteAllText(filepath, content);
+ }
+
+ private static Element CreateElement(SkinBOX box)
+ {
+ Vector3 transformPos = TranslateFromInternalPosistion(box, new Vector3(1, 1, 0));
+ Element element = CreateElement(box.UV, transformPos, box.Size, box.Scale, box.Mirror);
+ if (box.IsOverlayPart())
+ element.Inflate = box.Type == "HEADWEAR" ? 0.5f : 0.25f;
+ return element;
+ }
+
+ private static Element CreateElement(Vector2 uvOffset, Vector3 pos, Vector3 size, float inflate, bool mirror)
+ {
+ return Element.CreateCube("cube", uvOffset, pos, size, inflate, mirror);
+ }
+
+ private static Geometry GetGeometry(string filepath)
+ {
+ // Bedrock Entity (Model)
+ if (filepath.EndsWith(".geo.json"))
+ {
+ BedrockModel bedrockModel = JsonConvert.DeserializeObject(File.ReadAllText(filepath));
+ var availableModels = bedrockModel.Models.Select(m => m.Description.Identifier).ToArray();
+ if (availableModels.Length < 2)
+ return availableModels.Length == 1 ? bedrockModel.Models[0] : null;
+
+ using ItemSelectionPopUp itemSelectionPopUp = new ItemSelectionPopUp(availableModels);
+ if (itemSelectionPopUp.ShowDialog() == DialogResult.OK && bedrockModel.Models.IndexInRange(itemSelectionPopUp.SelectedIndex))
+ {
+ return bedrockModel.Models[itemSelectionPopUp.SelectedIndex];
+ }
+ }
+
+ // Bedrock Legacy Model
+ else if (filepath.EndsWith(".json"))
+ {
+ BedrockLegacyModel bedrockModel = JsonConvert.DeserializeObject(File.ReadAllText(filepath));
+ var availableModels = bedrockModel.Select(m => m.Key).ToArray();
+ if (availableModels.Length < 2)
+ return availableModels.Length == 1 ? bedrockModel[availableModels[0]] : null;
+ using ItemSelectionPopUp itemSelectionPopUp = new ItemSelectionPopUp(availableModels);
+ if (itemSelectionPopUp.ShowDialog() == DialogResult.OK && bedrockModel.ContainsKey(itemSelectionPopUp.SelectedItem))
+ {
+ return bedrockModel[itemSelectionPopUp.SelectedItem];
+ }
+ }
+
+ return null;
+ }
+
+ private static SkinModelInfo ImportBedrockJson(string filepath)
+ {
+ Geometry geometry = GetGeometry(filepath);
+ if (geometry is null)
+ return null;
+
+ (IEnumerable boxes, IEnumerable partOffsets) = LoadGeometry(geometry);
+
+ Image texture = null;
+ string texturePath = Path.Combine(Path.GetDirectoryName(filepath), Path.GetFileNameWithoutExtension(filepath)) + ".png";
+ if (File.Exists(texturePath))
+ {
+ texture = Image.FromFile(texturePath).ReleaseFromFile();
+ texture = SwapBoxBottomTexture(texture, boxes);
+ }
+
+ return CreateSkinModelInfo(texture, boxes, partOffsets);
+ }
+
+ private static (IEnumerable boxes, IEnumerable partOffsets) LoadGeometry(Geometry geometry)
+ {
+ List skinPartOffsets = new List();
+ List boxes = new List();
+
+ foreach (Bone bone in geometry.Bones)
+ {
+ string boxType = TryConvertToSkinBoxType(bone.Name);
+ if (!SkinBOX.IsValidType(boxType))
+ continue;
+
+ string offsetType = SkinBOX.IsOverlayPart(boxType) ? SkinBOXExtensions.GetBaseType(boxType) : boxType;
+ Vector3 offset = GetOffsetFromOrigin(offsetType, bone.Pivot * new Vector3(-1, 1, 1));
+ if (offset.Y != 0f)
+ skinPartOffsets.Add(new SkinPartOffset(offsetType, -offset.Y));
+
+ foreach (Cube cube in bone.Cubes)
+ {
+ Vector3 pos = TranslateToInternalPosition(boxType, cube.Origin, cube.Size, Vector3.UnitY);
+ var skinBox = new SkinBOX(boxType, pos, cube.Size, cube.Uv, hideWithArmor: bone.Name == "helmet", mirror: cube.Mirror);
+ if (SkinBOX.IsBasePart(boxType) && ((boxType == "HEAD" && cube.Inflate == 0.5f) || (cube.Inflate >= 0.25f && cube.Inflate <= 0.5f)))
+ skinBox = new SkinBOX(SkinBOXExtensions.GetOverlayType(boxType), pos, cube.Size, cube.Uv, hideWithArmor: bone.Name == "helmet", mirror: cube.Mirror);
+ boxes.Add(skinBox);
+ }
+ }
+ return (boxes, skinPartOffsets);
+ }
+
+ internal static void ExportBedrockJson(string filepath, SkinModelInfo modelInfo)
+ {
+ if (string.IsNullOrEmpty(filepath) || !filepath.EndsWith(".json"))
+ return;
+
+ Dictionary bones = new Dictionary(5);
+ Dictionary offsetLookUp = new Dictionary(5);
+
+ void AddBone(SkinBOX box)
+ {
+ string offsetType = box.IsOverlayPart() ? box.GetBaseType() : box.Type;
+
+ Vector3 offset = GetOffsetForPart(offsetType, ref offsetLookUp, modelInfo.Model.PartOffsets);
+
+ if (!bones.ContainsKey(offsetType))
+ {
+ Bone bone = new Bone(offsetType)
+ {
+ Pivot = GetSkinPartPivot(offsetType, new Vector3(0, 1, 0)) + offset
+ };
+ bones.Add(offsetType, bone);
+ }
+ Vector3 pivot = bones.ContainsKey(offsetType) ? bones[offsetType].Pivot : Vector3.Zero;
+ Vector3 pos = TranslateFromInternalPosistion(box, new Vector3(1, 1, 0));
+ pos = TransformSpace(pos, box.Size, new Vector3(1, 0, 0));
+
+ bones[offsetType].Cubes.Add(new Cube()
+ {
+ Origin = pos + offset,
+ Size = box.Size,
+ Uv = box.UV,
+ Inflate = box.Scale + (box.IsOverlayPart() ? box.Type == "HEAD" ? 0.5f : 0.25f : 0f),
+ Mirror = box.Mirror,
+ });
+ }
+
+ ANIM2BOX(modelInfo.Anim, AddBone);
+
+ foreach (SkinBOX box in modelInfo.Model.AdditionalBoxes)
+ {
+ AddBone(box);
+ }
+
+ Geometry selectedGeometry = new Geometry();
+ selectedGeometry.Bones.AddRange(bones.Values);
+ object bedrockModel = null;
+ // Bedrock Entity (Model)
+ if (filepath.EndsWith(".geo.json"))
+ {
+ selectedGeometry.Description = new GeometryDescription()
+ {
+ Identifier = $"geometry.{Application.ProductName}.{Path.GetFileNameWithoutExtension(filepath)}",
+ TextureSize = modelInfo.Texture.Size,
+ };
+ bedrockModel = new BedrockModel
+ {
+ FormatVersion = "1.12.0",
+ Models = { selectedGeometry }
+ };
+ }
+ // Bedrock Legacy Model
+ else if (filepath.EndsWith(".json") && modelInfo.Texture.Height == modelInfo.Texture.Width)
+ {
+ bedrockModel = new BedrockLegacyModel
+ {
+ { $"geometry.{Application.ProductName}.{Path.GetFileNameWithoutExtension(filepath)}", selectedGeometry }
+ };
+ }
+ else
+ {
+ MessageBox.Show("Can't export to Bedrock Legacy Model.", "Invalid Texture Dimensions", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ return;
+ }
+
+ if (bedrockModel is not null)
+ {
+ string content = JsonConvert.SerializeObject(bedrockModel);
+ File.WriteAllText(filepath, content);
+ string texturePath = Path.Combine(Path.GetDirectoryName(filepath), Path.GetFileNameWithoutExtension(filepath)) + ".png";
+ SwapBoxBottomTexture(modelInfo).Save(texturePath, ImageFormat.Png);
+ }
+ }
+
+ private static void ANIM2BOX(SkinANIM anim, Action converter)
+ {
+ bool isSlim = anim.GetFlag(SkinAnimFlag.SLIM_MODEL);
+ bool is32x64 = !(anim.GetFlag(SkinAnimFlag.RESOLUTION_64x64) || isSlim);
+ if (!anim.GetFlag(SkinAnimFlag.HEAD_DISABLED))
+ converter(new SkinBOX("HEAD", new Vector3(-4, -8, -4), new Vector3(8), Vector2.Zero));
+
+ if (!is32x64 && !anim.GetFlag(SkinAnimFlag.HEAD_OVERLAY_DISABLED))
+ converter(new SkinBOX("HEADWEAR", new Vector3(-4, -8, -4), new Vector3(8), new Vector2(32, 0)));
+
+ if (!anim.GetFlag(SkinAnimFlag.BODY_DISABLED))
+ converter(new SkinBOX("BODY", new(-4, 0, -2), new(8, 12, 4), new(16, 16)));
+
+ if (!is32x64 && !anim.GetFlag(SkinAnimFlag.BODY_OVERLAY_DISABLED))
+ converter(new SkinBOX("JACKET", new(-4, 0, -2), new(8, 12, 4), new(16, 32)));
+
+ if (!anim.GetFlag(SkinAnimFlag.RIGHT_ARM_DISABLED))
+ converter(new SkinBOX("ARM0", new(isSlim ? -2 : - 3, -2, -2), new(isSlim ? 3 : 4, 12, 4), new(40, 16)));
+
+ if (!is32x64 && !anim.GetFlag(SkinAnimFlag.RIGHT_ARM_OVERLAY_DISABLED))
+ converter(new SkinBOX("SLEEVE0", new(isSlim ? -2 : - 3, -2, -2), new(isSlim ? 3 : 4, 12, 4), new(40, 32)));
+
+ if (!anim.GetFlag(SkinAnimFlag.LEFT_ARM_DISABLED))
+ converter(new SkinBOX("ARM1", new(-1, -2, -2), new(isSlim ? 3 : 4, 12, 4), is32x64 ? new(40, 16) : new(32, 48), mirror: is32x64));
+
+ if (!is32x64 && !anim.GetFlag(SkinAnimFlag.LEFT_ARM_OVERLAY_DISABLED))
+ converter(new SkinBOX("SLEEVE1", new(-1, -2, -2), new(isSlim ? 3 : 4, 12, 4), new(48, 48)));
+
+ if (!anim.GetFlag(SkinAnimFlag.RIGHT_LEG_DISABLED))
+ converter(new SkinBOX("LEG0", new(-2, 0, -2), new(4, 12, 4), new(0, 16)));
+
+ if (!is32x64 && !anim.GetFlag(SkinAnimFlag.RIGHT_LEG_OVERLAY_DISABLED))
+ converter(new SkinBOX("PANTS0", new(-2, 0, -2), new(4, 12, 4), new(0, 32)));
+
+ if (!anim.GetFlag(SkinAnimFlag.LEFT_LEG_DISABLED))
+ {
+ converter(new SkinBOX("LEG1", new(-2, 0, -2), new(4, 12, 4), is32x64 ? new(0, 16) : new(16, 48), mirror: is32x64));
+ }
+
+ if (!is32x64 && !anim.GetFlag(SkinAnimFlag.LEFT_LEG_OVERLAY_DISABLED))
+ {
+ converter(new SkinBOX("PANTS1", new(-2, 0, -2), new(4, 12, 4), new(0, 48)));
+ }
+ }
+
+ private static string TryConvertToSkinBoxType(string name)
+ {
+ if (!SkinBOX.IsValidType(name) && SkinBOX.IsValidType(name.ToUpper()))
+ {
+ return name.ToUpper();
+ }
+ return name.ToLower() switch
+ {
+ "helmet" => "HEAD",
+ "rightarm" => "ARM0",
+ "leftarm" => "ARM1",
+ "rightleg" => "LEG0",
+ "leftleg" => "LEG1",
+ "hat" => "HEADWEAR",
+ "bodyarmor" => "BODY",
+ "rightsleeve" => "SLEEVE0",
+ "leftsleeve" => "SLEEVE1",
+ "rightpants" => "PANTS0",
+ "leftpants" => "PANTS1",
+ _ => name,
+ };
+ }
+
+ private static Vector3 GetOffsetFromOrigin(string boxType, Vector3 origin)
+ {
+ Vector3 partTranslation = GameConstants.GetSkinPartPivot(boxType);
+ Vector3 offset = partTranslation - ((Vector3.UnitY * 24f) - origin);
+ if (offset.X != 0f || offset.Z != 0f)
+ Trace.TraceWarning($"[{nameof(SkinModelImporter)}:{nameof(GetOffsetFromOrigin)}] Warning: skin part({boxType}) offsets only support horizontal offsets.");
+ return offset * Vector3.UnitY;
+ }
+
+ private static Vector3 GetSkinPartPivot(string partName, Vector3 translationUnit)
+ {
+ return TransformSpace(GameConstants.GetSkinPartPivot(partName), Vector3.Zero, translationUnit) + (24f * Vector3.UnitY);
+ }
+
+ private static Vector3 GetOffsetForPart(string offsetType, ref Dictionary offsetLookUp, IEnumerable partOffsets)
+ {
+ if (offsetLookUp.ContainsKey(offsetType))
+ {
+ return -offsetLookUp[offsetType].Value * Vector3.UnitY;
+ }
+ if (partOffsets.Any(o => o.Type == offsetType))
+ {
+ SkinPartOffset partOffset = partOffsets.First(o => o.Type == offsetType);
+ offsetLookUp.Add(offsetType, partOffset);
+ return -partOffset.Value * Vector3.UnitY;
+ }
+ return Vector3.Zero;
+ }
+
+ private static Image SwapBoxBottomTexture(SkinModelInfo modelInfo)
+ {
+ return SwapBoxBottomTexture(modelInfo.Texture, modelInfo.Model.AdditionalBoxes);
+ }
+
+ private static Image SwapBoxBottomTexture(Image texture, IEnumerable boxes)
+ {
+ return SwapTextureAreas(texture, boxes.Where(box => !(box.Size == Vector3.One || box.Size == Vector3.Zero)).Select(box =>
+ {
+ var imgPos = Point.Truncate(new PointF(box.UV.X + box.Size.X + box.Size.Z, box.UV.Y));
+ var area = new RectangleF(imgPos, Size.Truncate(new SizeF(box.Size.X, box.Size.Z)));
+ return Rectangle.Truncate(area);
+ }), RotateFlipType.RotateNoneFlipY);
+ }
+
+ private static Image SwapTextureAreas(Image texture, IEnumerable areasToFix, RotateFlipType type)
+ {
+ if (texture == null)
+ {
+ Trace.TraceError($"[{nameof(SkinModelImporter)}:{nameof(SwapBoxBottomTexture)}] Failed to fix texture: texture is null.");
+ return null;
+ }
+ areasToFix = areasToFix.Where(rect => rect.Size.Width > 0 && rect.Size.Height > 0);
+ Image result = new Bitmap(texture);
+ using var g = Graphics.FromImage(result);
+ g.ApplyConfig(new GraphicsConfig()
+ {
+ InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor,
+ PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality
+ });
+ foreach (Rectangle area in areasToFix)
+ {
+ Image targetAreaImage = texture.GetArea(area);
+ targetAreaImage.RotateFlip(type);
+ Region clip = g.Clip;
+ g.SetClip(area);
+ g.Clear(Color.Transparent);
+ g.DrawImage(targetAreaImage, area.Location);
+ g.Clip = clip;
+ }
+ return result;
+ }
+
+ private static Vector3 TranslateToInternalPosition(string boxType, Vector3 origin, Vector3 size, Vector3 translationUnit)
+ {
+ Vector3 pos = TransformSpace(origin, size, translationUnit);
+ // Skin Renderer (and Game) specific offset value.
+ pos.Y += 24f;
+
+ // This will cancel out the part specific translation.
+ Vector3 translation = GameConstants.GetSkinPartTranslation(boxType);
+ pos -= translation;
+
+ return pos;
+ }
+
+ private static Vector3 TranslateFromInternalPosistion(SkinBOX skinBox, Vector3 translationUnit)
+ {
+ return TranslateToInternalPosition(skinBox.Type, skinBox.Pos, skinBox.Size, translationUnit);
+ }
+ }
+}
diff --git a/PckStuido.ModelSupport/SkinModelInfo.cs b/PckStuido.ModelSupport/SkinModelInfo.cs
new file mode 100644
index 00000000..a7a1b2f9
--- /dev/null
+++ b/PckStuido.ModelSupport/SkinModelInfo.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using PckStudio.Core.Skin;
+
+namespace PckStudio.ModelSupport
+{
+ public sealed class SkinModelInfo
+ {
+ public SkinModel Model { get; }
+ public SkinANIM Anim { get; }
+ public Image Texture { get; }
+
+ public SkinModelInfo(Image texture, SkinANIM anim, SkinModel model)
+ {
+ Texture = texture;
+ Anim = anim;
+ Model = model;
+ }
+ }
+}
diff --git a/Version.json b/Version.json
index 88ef4e47..0711d4f6 100644
--- a/Version.json
+++ b/Version.json
@@ -1,6 +1,6 @@
{
- "version": "7.0.0.2",
- "url": "https://github.com/PhoenixARC/-PCK-Studio/releases/download/v7.0.0.2/PCK-Studio.zip",
+ "version": "7.0.1.0",
+ "url": "https://github.com/PhoenixARC/-PCK-Studio/releases/download/v7.0.1.0/PCK-Studio.zip",
"changelog": "https://raw.githubusercontent.com/PhoenixARC/-PCK-Studio/main/CHANGELOG.md",
"mandatory": false
}
\ No newline at end of file