internal SmartTile(bool maxTiles4096, J2TFile tileset) { for (int i = 0; i < Assignments.Length; ++i) { Assignments[i] = new Assignment(); } ushortComparer comparer = maxTiles4096 ? ushortComparer.compare124 : ushortComparer.compare123; TilesICanPlace = new HashSet <ushort>(comparer); TilesIGoNextTo = new HashSet <ushort>(comparer); Tileset = tileset; }
internal SmartTile(SmartTile other) { Assignments = other.Assignments.Select(ass => new Assignment(ass)).ToArray(); PreviewTileIDs = other.PreviewTileIDs.Clone() as ushort[]; Name = other.Name; Friends = new List <int>(other.Friends); TilesICanPlace = new HashSet <ushort>(other.TilesICanPlace.Comparer); TilesICanPlace.UnionWith(other.TilesICanPlace); TilesIGoNextTo = new HashSet <ushort>(other.TilesIGoNextTo.Comparer); TilesIGoNextTo.UnionWith(other.TilesIGoNextTo); Tileset = other.Tileset; }
internal DialogResult ShowForm(SmartTile workingSmartTile, J2TFile tileset, int workingSmartTileIndex = -1) { Tileset = tileset; WorkingSmartTile = workingSmartTile; List <SmartTile> smartTiles = tileset.SmartTiles; if (smartTiles.Count >= 1) { AllSmartTileNames = smartTiles.Select(smartTile => smartTile.Name).ToList(); } else { AllSmartTileNames = new List <string>(); } if (workingSmartTileIndex == -1) { AllSmartTileNames.Add("[this]"); button1.Hide(); } if (smartTiles.Count > 1) { for (int otherSmartTileID = 0; otherSmartTileID < smartTiles.Count; ++otherSmartTileID) { checkedComboBox1.Items.Add( otherSmartTileID != workingSmartTileIndex ? AllSmartTileNames[otherSmartTileID] : "[this]", otherSmartTileID == workingSmartTileIndex ? CheckState.Indeterminate : workingSmartTile.Friends.Contains(otherSmartTileID) ? CheckState.Checked : CheckState.Unchecked ); } checkedComboBox1.SetItemCheckState(0, checkedComboBox1.GetItemCheckState(0)); //fixes issue of control not updating text preview in response to Items.Add checkedComboBox1.ItemCheck += (s, e) => { if (e.CurrentValue == CheckState.Indeterminate) { e.NewValue = CheckState.Indeterminate; } }; //don't let the indeterminate item (this smarttile itself) be altered } else { checkedComboBox1.Hide(); } AndValue = ((SmartTile.ushortComparer)WorkingSmartTile.TilesICanPlace.Comparer).AndValue; textBox1.Text = WorkingSmartTile.Name; CreateImageFromTileset(); using (new System.Threading.Timer(RedrawTiles, null, TimeSpan.FromSeconds(0), TimeSpan.FromSeconds(0.5))) ShowDialog(); return(Result); }
public uint getTileInTilesetID(uint tileInLevelID, out J2TFile J2T) { uint tileInTilesetID = tileInLevelID; int tilesetID = 0; while (true) { J2T = Tilesets[tilesetID++]; if (tileInTilesetID >= J2T.TileCount) { tileInTilesetID -= J2T.TileCount; } else { break; } } return(tileInTilesetID + J2T.FirstTile); }
internal bool ShowForm(J2TFile tileset, J2LFile level, int max, uint number) { Tileset = tileset; Level = level; Tilesets = level.Tilesets; LevelPalette = level.Palette; MaxTilesSupportedByLevel = (uint)max; NumberOfTilesInThisLevelBesidesThisTileset = number; inputLast.Maximum = Tileset.TotalNumberOfTiles; inputLast.Value = (InitialFirstTile = (int)Tileset.FirstTile) + (InitialTileCount = (int)Tileset.TileCount); inputFirst.Maximum = inputLast.Value - 1; inputFirst.Value = Tileset.FirstTile; inputLast.Minimum = inputFirst.Value + 1; ButtonDelete.Visible = Tilesets.Contains(Tileset); CreateImageFromTileset(); UpdatePreviewControls(); ShowDialog(); return(Result); }
private void Build_Click(object sender, EventArgs e) { if (listView1.SelectedItems.Count == 1) { var record = listView1.SelectedItems[0]; var J2T = new J2TFile(); J2T.VersionType = VersionType; Bitmap image = new Bitmap(1, 1), mask = new Bitmap(1, 1); string sourceFilepath = Path.Combine(TileDirectory, record.SubItems[2].Text); try { image = new Bitmap(sourceFilepath); sourceFilepath = Path.Combine(TileDirectory, record.SubItems[3].Text); mask = new Bitmap(sourceFilepath); switch (J2T.Build(image, mask, record.Text)) { case BuildResults.DifferentDimensions: MessageBox.Show(String.Format("The image and the mask must be the same dimensions. Your image is {0} by {1}, and your mask is {2} by {3}.", image.Width, image.Height, mask.Width, mask.Height), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); break; case BuildResults.BadDimensions: MessageBox.Show(String.Format("A tileset image must be 320 pixels wide and a multiple of 32 pixels high. Your image is {0} by {1}.", image.Width, image.Height), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); break; case BuildResults.ImageWrongFormat: MessageBox.Show("Your image file is saved in an incorrect color mode. A tileset image must use 8-bit color with no transparency (color 0 is used for transparency instead).", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); break; case BuildResults.MaskWrongFormat: MessageBox.Show("Your mask file is saved in an incorrect color mode. A tileset mask must use 8-bit color with no transparency (color 0 is used for transparency instead).", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); break; case BuildResults.TooBigForVersion: MessageBox.Show(String.Format("Your tileset images are too big. The tile limit for a {0} tileset is {1} tiles, but your tileset contains {2}.", J2File.FullVersionNames[J2T.VersionType], J2T.MaxTiles, (image.Height / 32 * 10)), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); break; case BuildResults.Success: string fullFilePath = Path.Combine(Directory.GetParent(TileDirectory).ToString(), record.SubItems[1].Text); if (J2T.Save(fullFilePath) != SavingResults.Success) { MessageBox.Show("Something went wrong.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } else { MessageBox.Show(String.Format("OK: Your tileset '{0}' has been built at {1} with {2} tiles ({3} Kb).", record.Text, fullFilePath, (image.Height / 32 * 10), new System.IO.FileInfo(fullFilePath).Length / 1024), "Successful Build", MessageBoxButtons.OK, MessageBoxIcon.Information); } break; } } catch (FileNotFoundException) { MessageBox.Show(sourceFilepath + " not found!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } catch { MessageBox.Show(sourceFilepath + " does not use an image format supported by this program. (Try PNG, GIF, TIFF, or BMP.)", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } finally { image.Dispose(); mask.Dispose(); } } }
internal bool LevelIsReadable(byte[] Data5, List <J2TFile> Tilesets, List <Layer> Layers, string Filepath) { if (Data5 == null || Data5.Length < 20) //level stops at the end of data4, as is good and proper { this = new PlusPropertyList(null); return(true); } using (BinaryReader data5reader = new BinaryReader(new MemoryStream(Data5), J2LFile.FileEncoding)) { if (new string(data5reader.ReadChars(4)) != MLLEData5MagicString) { return(false); } uint data5Version = data5reader.ReadUInt32(); if (data5Version > CurrentMLLEData5Version) { return(false); } //should be okay to read at this point this = new PlusPropertyList(null); uint csize = data5reader.ReadUInt32(); uint usize = data5reader.ReadUInt32(); using (BinaryReader data5bodyreader = new BinaryReader(new MemoryStream(ZlibStream.UncompressBuffer(data5reader.ReadBytes((int)csize))))) { IsSnowing = data5bodyreader.ReadBoolean(); IsSnowingOutdoorsOnly = data5bodyreader.ReadBoolean(); SnowingIntensity = data5bodyreader.ReadByte(); SnowingType = (SnowTypeEnum)data5bodyreader.ReadByte(); WarpsTransmuteCoins = data5bodyreader.ReadBoolean(); DelayGeneratedCrateOrigins = data5bodyreader.ReadBoolean(); Echo = data5bodyreader.ReadInt32(); DarknessColor = Color.FromArgb(data5bodyreader.ReadInt32()); WaterChangeSpeed = data5bodyreader.ReadSingle(); WaterInteraction = (WaterInteractionEnum)data5bodyreader.ReadByte(); WaterLayer = data5bodyreader.ReadInt32(); WaterLighting = (WaterLightingEnum)data5bodyreader.ReadByte(); WaterLevel = data5bodyreader.ReadSingle(); WaterGradientStart = Color.FromArgb(data5bodyreader.ReadInt32()); WaterGradientStop = Color.FromArgb(data5bodyreader.ReadInt32()); if (data5bodyreader.ReadBoolean()) { Palette = new Palette(data5bodyreader, true); } for (int i = 0; i < Mainframe.RecolorableSpriteNames.Length; ++i) { if ((i < 11 || data5Version >= 0x105) && data5bodyreader.ReadBoolean()) //the recolorable sprite list was expanded in MLLE-Include-1.5 { ColorRemappings[i] = new byte[Palette.PaletteSize]; for (uint j = 0; j < Palette.PaletteSize; ++j) { ColorRemappings[i][j] = data5bodyreader.ReadByte(); } } else { ColorRemappings[i] = null; } } var extraTilesetCount = data5bodyreader.ReadByte(); for (uint tilesetID = 0; tilesetID < extraTilesetCount; ++tilesetID) { var tilesetFilepath = Path.Combine(Path.GetDirectoryName(Filepath), data5bodyreader.ReadString()); if (File.Exists(tilesetFilepath)) { var tileset = new J2TFile(tilesetFilepath); tileset.FirstTile = data5bodyreader.ReadUInt16(); tileset.TileCount = data5bodyreader.ReadUInt16(); if (data5bodyreader.ReadBoolean()) { tileset.ColorRemapping = new byte[Palette.PaletteSize]; for (uint i = 0; i < Palette.PaletteSize; ++i) { tileset.ColorRemapping[i] = data5bodyreader.ReadByte(); } } Tilesets.Add(tileset); } else { this = new PlusPropertyList(null); MessageBox.Show("Additional tileset \"" + tilesetFilepath + "\" not found; MLLE will stop trying to read this Data5 section.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand); return(false); } } if (data5Version >= 0x102) //layers were added in MLLE-Include-1.2 { var defaultLayers = Layers.ToArray(); Layers.Clear(); int layerCount = (int)data5bodyreader.ReadUInt32(); List <Layer> nonDefaultLayers = new List <Layer>(); for (int i = 8; i < layerCount; i += 8) { J2LFile extraLevel = new J2LFile(); string levelFilePath = GetExtraDataLevelFilepath(Filepath, i / 8 - 1); if (File.Exists(levelFilePath)) { extraLevel.OpenLevel(levelFilePath, ref Data5, SecurityStringOverride: J2LFile.SecurityStringExtraDataNotForDirectEditing); nonDefaultLayers.AddRange(extraLevel.DefaultLayers); } else { this = new PlusPropertyList(null); MessageBox.Show("Additional file \"" + levelFilePath + "\" not found; MLLE will stop trying to read this Data5 section.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand); return(false); } } int nextNonDefaultLayerID = 0; for (uint i = 0; i < layerCount; ++i) { sbyte layerID = data5bodyreader.ReadSByte(); Layer layer; if (layerID >= 0) { layer = defaultLayers[layerID]; } else { layer = nonDefaultLayers[nextNonDefaultLayerID++]; layer.id = -1; } layer.Name = data5bodyreader.ReadString(); layer.Hidden = data5bodyreader.ReadBoolean(); layer.SpriteMode = data5bodyreader.ReadByte(); layer.SpriteParam = data5bodyreader.ReadByte(); layer.RotationAngle = data5bodyreader.ReadInt32(); layer.RotationRadiusMultiplier = data5bodyreader.ReadInt32(); Layers.Add(layer); } if (data5Version >= 0x103) //edited tiles were added in MLLE-Include-1.3 { int levelTileCount = Tilesets.Sum(ts => (int)ts.TileCount); foreach (byte[][] images in new byte[][][] { TileImages, TileMasks }) { int numberOfImages = data5bodyreader.ReadUInt16(); for (int i = 0; i < numberOfImages; ++i) { int tileID = data5bodyreader.ReadUInt16(); images[tileID] = data5bodyreader.ReadBytes(32 * 32); } } if (data5Version >= 0x105) //weapons were added in MLLE-Include-1.5(w) { for (int weaponID = 0; weaponID < 9; ++weaponID) { bool customWeapon = data5bodyreader.ReadBoolean(); Weapon weapon = Weapons[weaponID]; weapon.Options[0] = data5bodyreader.ReadInt32(); //maximum for (int optionID = 1; optionID < Weapon.NumberOfCommonOptions; ++optionID) { weapon.Options[optionID] = data5bodyreader.ReadByte(); //birds and crates and gems and replenishment } if (weaponID == 6) { Gun7Crate = data5bodyreader.ReadByte(); } else if (weaponID == 7) { Gun8Crate = data5bodyreader.ReadByte(); } else if (weaponID == 8) { Gun9Crate = data5bodyreader.ReadByte(); } if (customWeapon) { string name = data5bodyreader.ReadString(); var extendedWeapon = WeaponsForm.GetAllAvailableWeapons().Find(w => w.Name == name); if (extendedWeapon == null) { MessageBox.Show(String.Format("Sorry, the MLLE \"Weapons\" folder did not include any .ini file defining a weapon with the name \"{0}.\"", name), "Weapon not found", MessageBoxButtons.OK, MessageBoxIcon.Error); return(false); } Weapons[weaponID].Name = name; Array.Resize(ref Weapons[weaponID].Options, extendedWeapon.Options.Length); data5bodyreader.ReadInt32(); //length of jjSTREAM for (int optionID = Weapon.NumberOfCommonOptions; optionID < weapon.Options.Length; ++optionID) { switch (extendedWeapon.OptionTypes[optionID]) { case WeaponsForm.ExtendedWeapon.oTypes.Bool: case WeaponsForm.ExtendedWeapon.oTypes.Dropdown: weapon.Options[optionID] = data5bodyreader.ReadByte(); break; case WeaponsForm.ExtendedWeapon.oTypes.Int: weapon.Options[optionID] = data5bodyreader.ReadInt32(); break; } } } else if (weaponID == 7) { weapon.Options[Weapon.NumberOfCommonOptions] = data5bodyreader.ReadByte(); //Gun8 style } } } } } } } return(true); }
internal SmartTile(bool maxTiles4096, J2TFile tileset, ushort fileVersion, BinaryReader reader, uint tileOffset) : this(maxTiles4096, tileset) { Name = reader.ReadString(); Action <List <ushort> > conditionallyAddTileIDToList = (list) => { ushort tileID = reader.ReadUInt16(); int offsetTileID = (int)((tileID & 0xFFF) - tileset.FirstTile); if (offsetTileID >= 0 && offsetTileID < tileset.TileCount) { if (!maxTiles4096 && (tileID & 0x1000) != 0) //hflip { tileID ^= 0x1400; } list.Add((ushort)(tileID + tileOffset)); } }; for (int i = 0; i < Assignments.Length; ++i) { Assignment assignment = Assignments[i]; for (int numberOfTileIDs = reader.ReadByte(); numberOfTileIDs > 0; --numberOfTileIDs) { conditionallyAddTileIDToList(assignment.Tiles); } if (fileVersion >= 2) { for (int numberOfRules = reader.ReadByte(); numberOfRules > 0; --numberOfRules) { Rule newRule = new Rule(); newRule.X = reader.ReadSByte(); newRule.Y = reader.ReadSByte(); newRule.Not = reader.ReadBoolean(); newRule.OtherSmartTileID = reader.ReadSByte(); if (newRule.OtherSmartTileID == -1) { for (int numberOfSpecificTiles = reader.ReadByte(); numberOfSpecificTiles > 0; --numberOfSpecificTiles) { conditionallyAddTileIDToList(newRule.SpecificTiles); } } int intendedNumberOfResults = reader.ReadByte(); for (int numberOfResults = intendedNumberOfResults; numberOfResults > 0; --numberOfResults) { conditionallyAddTileIDToList(newRule.Result); } var rules = assignment.Rules; if (intendedNumberOfResults != 0 && newRule.Result.Count == 0) //none of the tiles can be found in this subset { Rule condition; while (rules.Count != 0 && (condition = rules.Last()).Result.Count == 0) //remove all "and" rules leading up to this one, to avoid confusing any other logic. { rules.Remove(condition); } } else { rules.Add(newRule); } } } } if (fileVersion >= 1) { for (int friendCount = reader.ReadByte(); friendCount > 0; --friendCount) { Friends.Add(reader.ReadByte()); } } }