<commit_before>﻿// Original Work Copyright (c) <NAME> 2014-2016
// This file is subject to the GPL v2 License
// For additional details, see the LICENSE file

//****************************************************************************************************
//* This is a derivative of a work licensed under the GPL v3.0
//* Original unmodifeid source is available at:
//*      https://www.assembla.com/code/eo-dev-sharp/subversion/nodes
//*      (see Data/EMF.cs)
//* For additional details on GPL v3.0 see the file GPL3License.txt
//****************************************************************************************************

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using EOLib.Net;

namespace EOLib.IO.Map
{
	public class MapFile : IMapFile
	{
		#region Helper Classes

		private class MapEntityRow<T> : IMapEntityRow<T>
		{
			public int Y { get; set; }
			public List<IMapEntityItem<T>> EntityItems { get; set; }

			public MapEntityRow()
			{
				EntityItems = new List<IMapEntityItem<T>>();
			}
		}

		private class MapEntityItem<T> : IMapEntityItem<T>
		{
			public int X { get; set; }
			public T Value { get; set; }
		}

		#endregion

		public MapFileProperties Properties { get; private set; }

		public IReadOnly2DArray<TileSpec> Tiles { get { return _tiles; } }
		public IReadOnly2DArray<Warp> Warps { get { return _warps; } }
		public IReadOnlyDictionary<MapLayer, IReadOnly2DArray<int>> GFX
		{
			get
			{
				return _gfx.ToDictionary(k => k.Key, v => (IReadOnly2DArray<int>) v.Value);
			}
		}

		public IReadOnlyList<IMapEntityRow<TileSpec>> TileRows { get { return _tileRows; } }
		public IReadOnlyList<IMapEntityRow<Warp>> WarpRows { get { return _warpRows; } }
		public IReadOnlyDictionary<MapLayer, IReadOnlyList<IMapEntityRow<int>>> GFXRows
		{
			get
			{
				return _gfxRows.ToDictionary(k => k.Key, v => (IReadOnlyList<IMapEntityRow<int>>)v.Value);
			}
		}

		public List<NPCSpawn> NPCSpawns { get; private set; }
		public List<byte[]> Unknowns { get; private set; }
		public List<MapChest> Chests { get; private set; }
		public List<MapSign> Signs { get; private set; }

		#region Backing Collections
		//note: the collections must be kept in sync with any set accessors added to the MapFile class

		//backing fields for lookup tables (for rendering)
		private Array2D<TileSpec> _tiles;
		private Array2D<Warp> _warps;
		private Dictionary<MapLayer, Array2D<int>> _gfx;

		//backing fields for Save() function
		private readonly List<MapEntityRow<TileSpec>> _tileRows;
		private readonly List<MapEntityRow<Warp>> _warpRows;
		private readonly Dictionary<MapLayer, List<MapEntityRow<int>>> _gfxRows;

		#endregion

		private readonly IMapStringEncoderService _encoderService;

		public MapFile()
		{
			NPCSpawns = new List<NPCSpawn>();
			Unknowns = new List<byte[]>();
			Chests = new List<MapChest>();
			Signs = new List<MapSign>();

			_tileRows = new List<MapEntityRow<TileSpec>>();
			_warpRows = new List<MapEntityRow<Warp>>();
			_gfxRows = new Dictionary<MapLayer, List<MapEntityRow<int>>>();

			_encoderService = new MapStringEncoderService();
		}

		public void Load(string fileName)
		{
			var strID = fileName.Substring(fileName.LastIndexOf('\\') + 1, 5);
			var intID = int.Parse(strID);

			var filePacket = CreateFilePacketForLoad(fileName);

			SetMapProperties(intID, filePacket);
			ResetCollections();
			ReadNPCSpawns(filePacket);
			ReadUnknowns(filePacket);
			ReadMapChests(filePacket);
			ReadTileSpecs(filePacket);
			ReadWarpTiles(filePacket);
			ReadGFXLayers(filePacket);

			if (filePacket.ReadPosition == filePacket.Length)
				return;

			ReadMapSigns(filePacket);<commit_msg>Fix crash in MapFile loading, accept input with forward slash and backslash<commit_after>﻿// Original Work Copyright (c) <NAME> 2014-2016
// This file is subject to the GPL v2 License
// For additional details, see the LICENSE file

//****************************************************************************************************
//* This is a derivative of a work licensed under the GPL v3.0
//* Original unmodifeid source is available at:
//*      https://www.assembla.com/code/eo-dev-sharp/subversion/nodes
//*      (see Data/EMF.cs)
//* For additional details on GPL v3.0 see the file GPL3License.txt
//****************************************************************************************************

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using EOLib.Net;

namespace EOLib.IO.Map
{
	public class MapFile : IMapFile
	{
		#region Helper Classes

		private class MapEntityRow<T> : IMapEntityRow<T>
		{
			public int Y { get; set; }
			public List<IMapEntityItem<T>> EntityItems { get; set; }

			public MapEntityRow()
			{
				EntityItems = new List<IMapEntityItem<T>>();
			}
		}

		private class MapEntityItem<T> : IMapEntityItem<T>
		{
			public int X { get; set; }
			public T Value { get; set; }
		}

		#endregion

		public MapFileProperties Properties { get; private set; }

		public IReadOnly2DArray<TileSpec> Tiles { get { return _tiles; } }
		public IReadOnly2DArray<Warp> Warps { get { return _warps; } }
		public IReadOnlyDictionary<MapLayer, IReadOnly2DArray<int>> GFX
		{
			get
			{
				return _gfx.ToDictionary(k => k.Key, v => (IReadOnly2DArray<int>) v.Value);
			}
		}

		public IReadOnlyList<IMapEntityRow<TileSpec>> TileRows { get { return _tileRows; } }
		public IReadOnlyList<IMapEntityRow<Warp>> WarpRows { get { return _warpRows; } }
		public IReadOnlyDictionary<MapLayer, IReadOnlyList<IMapEntityRow<int>>> GFXRows
		{
			get
			{
				return _gfxRows.ToDictionary(k => k.Key, v => (IReadOnlyList<IMapEntityRow<int>>)v.Value);
			}
		}

		public List<NPCSpawn> NPCSpawns { get; private set; }
		public List<byte[]> Unknowns { get; private set; }
		public List<MapChest> Chests { get; private set; }
		public List<MapSign> Signs { get; private set; }

		#region Backing Collections
		//note: the collections must be kept in sync with any set accessors added to the MapFile class

		//backing fields for lookup tables (for rendering)
		private Array2D<TileSpec> _tiles;
		private Array2D<Warp> _warps;
		private Dictionary<MapLayer, Array2D<int>> _gfx;

		//backing fields for Save() function
		private readonly List<MapEntityRow<TileSpec>> _tileRows;
		private readonly List<MapEntityRow<Warp>> _warpRows;
		private readonly Dictionary<MapLayer, List<MapEntityRow<int>>> _gfxRows;

		#endregion

		private readonly IMapStringEncoderService _encoderService;

		public MapFile()
		{
			NPCSpawns = new List<NPCSpawn>();
			Unknowns = new List<byte[]>();
			Chests = new List<MapChest>();
			Signs = new List<MapSign>();

			_tileRows = new List<MapEntityRow<TileSpec>>();
			_warpRows = new List<MapEntityRow<Warp>>();
			_gfxRows = new Dictionary<MapLayer, List<MapEntityRow<int>>>();

			_encoderService = new MapStringEncoderService();
		}

		public void Load(string fileName)
		{
			var lastSlash = fileName.LastIndexOf('\\') < 0 ? fileName.LastIndexOf('/') : -1;
			if (lastSlash < 0)
				throw new IOException();

			var strID = fileName.Substring(lastSlash + 1, 5);
			var intID = int.Parse(strID);

			var filePacket = CreateFilePacketForLoad(fileName);

			SetMapProperties(intID, filePacket);
			ResetCollections();
			ReadNPCSpawns(filePacket);
			ReadUnknowns(filePacket);
			ReadMapChests(filePacket);
			ReadTileSpecs(filePacket);
			ReadWarpTiles(filePacket);
			ReadGFXLayers(filePacket);

			if (filePacket.ReadPosition == filePacket.Length)
				return;

			ReadMapSigns(filePacket);
{'fraction_non_alphanumeric': 0.1601743034464545, 'fraction_numerical': 0.006470355209296184, 'mean_word_length': 4.429390681003584, 'pattern_counts': {'":': 0, '<': 103, '<?xml version=': 0, '>': 109, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1644341', 'n_tokens_mistral': 2702, 'n_tokens_neox': 2409, 'n_words': 618}