using System; using System.Collections.Generic; using System.Diagnostics; using SUISS.Core; using SUISS.Storage; using UnityEngine; namespace SUISSEngine { [RequireComponent(typeof(Serializing))] public class IsometricGrid : MonoBehaviour { //[DebuggerBrowsable(DebuggerBrowsableState.Never)] public event IsometricGrid.GridDeserializedEventHandler GridDeserializedEvent; protected virtual void FireGridDeserializedEvent(UnityEngine.Object sender) { if (this.GridDeserializedEvent != null) { this.GridDeserializedEvent(sender); } } private void Awake() { if (this.sizeU <= 0 || this.sizeV <= 0) { throw new ArgumentException("Grid size must be positive integers", (this.Size.u > 0) ? "sizeU" : "sizeU"); } if (this.readOnlyGrid && this.readOnlyWapper == null) { UnityEngine.Debug.LogError("The grid " + base.gameObject.name + " is marked read only but does not have a readonly building wapper!"); } this.size = new GridSize(this.sizeU, this.sizeV); this.elements = new GridElement[this.size.u, this.size.v]; this.tiles = new Dictionary(); this.deserializing = false; List list = new List(); string[] array = new string[0]; if (this.elementTypes != null) { array = this.elementTypes.text.Split(new char[] { '\n' }); } else { UnityEngine.Debug.LogWarning("elementTypes is null!"); } GridIndex index; index.v = 0; while (index.v < this.size.v) { string[] array2 = new string[0]; if (index.v < array.Length) { array2 = array[index.v].Split(new char[] { '\t' }); } else { UnityEngine.Debug.LogWarning(string.Format("index.v ({0}) >= typeLines.Length ({1})", index.v, array.Length)); } index.u = 0; while (index.u < this.size.u) { int num = 0; if (index.u < array2.Length) { try { num = int.Parse(array2[index.u].Trim()); } catch (Exception ex) { UnityEngine.Debug.LogError(string.Format("Unable to parse '{0}' at {1},{2} on {3}: {4}", new object[] { array2[index.u], index.u, index.v, this.island.name, ex.StackTrace })); } } else { UnityEngine.Debug.LogWarning(string.Format("[index.v ({0})] index.u ({1}) >= types.Length ({2})", index.v, index.u, array2.Length)); } GridElement gridElement = new GridElement(this, index, num); this.elements[index.u, index.v] = gridElement; while (list.Count <= num) { list.Add(false); } list[num] = true; index.u++; } index.v++; } this._availableSurfaceTypes = list.ToArray(); } private void OnSerialize(Dictionary values) { if (!this.readOnlyGrid) { GameObjectManager instance = SingletonMonobehaviour.Instance; if (instance == null) { UnityEngine.Debug.LogError("Cannot serialize grid without GameObjectManager."); return; } values.Clear(); foreach (GridTile gridTile in this.tiles.Values) { if (instance.HavePrefabWithName(gridTile.name)) { string key = string.Format("{0},{1}", gridTile.index.u, gridTile.index.v); string text = gridTile.name; if (gridTile.mirrored) { text = "!" + text; } values[key] = text; } } } } private GameObject createReadOnlyPrefab(GameObject buildingPrefab) { if (buildingPrefab.GetComponent() != null) { return buildingPrefab; } this.readOnlyWapper.WrapAround(buildingPrefab); return this.readOnlyWapper.gameObject; } private void OnDeserialize(Dictionary values) { GameObjectManager instance = SingletonMonobehaviour.Instance; if (instance == null) { UnityEngine.Debug.LogError("Cannot deserialize grid without GameObjectManager."); return; } this.deserializing = true; Builder builder = this.island.builder; foreach (KeyValuePair keyValuePair in values) { bool mirrored = false; string text = (string)keyValuePair.Value; if (text.StartsWith("!")) { mirrored = true; text = text.Substring(1); } if (instance.HavePrefabWithName(text)) { string[] array = keyValuePair.Key.Split(new char[] { ',' }); GridIndex gridIndex = new GridIndex(int.Parse(array[0]), int.Parse(array[1])); if (gridIndex.isInvalid) { UnityEngine.Debug.LogWarning(string.Format("Grid entry {0} => {1} has invalid index.", keyValuePair.Key, keyValuePair.Value)); } else { GameObject gameObject = instance.GetPrefabWithName(text); if (this.readOnlyGrid) { gameObject = this.createReadOnlyPrefab(gameObject); } if (builder.BuildAt(gameObject, gridIndex, mirrored, true)) { GridTile gridTile = this.tiles[gridIndex]; Serializing component = gridTile.GetComponent(); if (component != null) { component.Deserialize(); } } } } else if (text != "surfingSchool" && text != "jungle" && text != "swamp") { UnityEngine.Debug.LogWarning(string.Format("GameObjectManager does not have prefab with name {0}.", text)); } } this.deserializing = false; this.HasGridDeserialized = true; this.FireGridDeserializedEvent(this); } protected void OnDeserialized() { this.island.BroadcastMessage("OnGridDeserialized", SendMessageOptions.DontRequireReceiver); } protected string GetKeyForIndex(GridIndex index) { return string.Format(this.serializing.StorageKey + "_Tile{0}", index.ToString()); } public bool[] AvailableSurfaceTypes { get { return this._availableSurfaceTypes; } } public GridSize Size { get { return new GridSize(this.sizeU, this.sizeV); } } public GridElement this[int u, int v] { get { return this.elements[u, v]; } } public GridElement this[GridIndex index] { get { return this.elements[index.u, index.v]; } } public GridOverlay Overlay { get { return this.overlay; } } public ICollection Tiles { get { return this.tiles.Values; } } public bool HasGridDeserialized { get; private set; } public void StartImport() { this.deserializing = true; } public GridIndex ConvertIslandCoordinateToGridIndex(Vector2 islandCoordinate) { Vector3 position = base.transform.position; float num = position.y - islandCoordinate.y + 0.5f * (islandCoordinate.x - position.x); GridIndex result; result.u = Mathf.FloorToInt(num / this.elementSize.y); if (result.u < 0 || result.u >= this.size.u) { return GridIndex.invalid; } num = position.y - islandCoordinate.y - 0.5f * (islandCoordinate.x - position.x); result.v = Mathf.FloorToInt(num / this.elementSize.y); if (result.v < 0 || result.v >= this.size.v) { return GridIndex.invalid; } return result; } public void FinishImport() { this.deserializing = false; this.serializing.Serialize(); } public Vector2 GetPositionForGridPoint(GridPoint point) { return new Vector2((point.u - point.v) * this.elementSize.x * 0.5f, (point.u + point.v) * this.elementSize.y * -0.5f); } public float GetZForGridIndex(GridIndex index) { return this.GetZForGridPoint(new GridPoint(index)); } public float GetZForGridPoint(GridPoint point) { float num = (point.u + point.v) / (float)(this.size.u + this.size.v); return this.zFar + (this.zNear - this.zFar) * num; } public bool CanSerialize(GridTile tile) { GameObjectManager instance = SingletonMonobehaviour.Instance; return instance.HavePrefabWithName(tile.name); } public void AddTileAt(GridTile tile, GridIndex index, bool serialize) { for (int i = index.v; i > index.v - tile.currentSize.v; i--) { for (int j = index.u; j > index.u - tile.currentSize.u; j--) { GridElement gridElement = this.elements[j, i]; gridElement.Tile = tile; } } if (serialize) { Serializing component = tile.GetComponent(); if (component != null) { component.StorageLifecycle = StorageLifecycle.Game; component.StorageKey = this.GetKeyForIndex(index); } } this.tiles[index] = tile; if (serialize && !this.deserializing && this.serializing != null && this.CanSerialize(tile)) { this.serializing.Serialize(); } } public void RemoveAtIndex(GridIndex index, GridSize size, bool serialize) { if (!this.tiles.ContainsKey(index)) { UnityEngine.Debug.LogWarning(string.Format("Tile does not exist at {0}.", index)); return; } for (int i = index.v; i > index.v - size.v; i--) { for (int j = index.u; j > index.u - size.u; j--) { GridElement gridElement = this.elements[j, i]; gridElement.Tile = null; } } GridTile gridTile = this.tiles[index]; if (serialize) { Serializing component = gridTile.GetComponent(); if (component != null) { component.Delete(); } } this.tiles.Remove(index); if (serialize && this.serializing != null && this.CanSerialize(gridTile)) { this.serializing.Serialize(); } } public void MoveTileFrom(GridTile tile, GridIndex oldIndex, bool serialize) { int num = 0; if (this.tiles.ContainsKey(oldIndex)) { for (int i = oldIndex.v; i > oldIndex.v - tile.size.v; i--) { for (int j = oldIndex.u; j > oldIndex.u - tile.size.u; j--) { GridElement gridElement = this.elements[j, i]; if (!object.ReferenceEquals(gridElement.Tile, tile)) { num++; } gridElement.Tile = null; } } this.tiles.Remove(oldIndex); } if (num > 0) { UnityEngine.Debug.LogWarning(string.Format("While moving {0} from {1} to {2}, notMatchCount is {3}.", new object[] { tile.name, oldIndex, tile.index, num })); } for (int k = tile.index.v; k > tile.index.v - tile.size.v; k--) { for (int l = tile.index.u; l > tile.index.u - tile.size.u; l--) { if (l < 0 || l >= this.size.u || k < 0 || k >= this.size.v) { UnityEngine.Debug.LogWarning(string.Format("While moving {0} from {1} to {2}, ({3},{4}) is oob.", new object[] { tile.name, oldIndex, tile.index, l, k })); } GridElement gridElement2 = this.elements[l, k]; gridElement2.Tile = tile; } } if (serialize) { Serializing component = tile.GetComponent(); if (component != null) { component.Rename(this.GetKeyForIndex(tile.index)); } } if (this.tiles.ContainsKey(tile.index)) { UnityEngine.Debug.LogWarning(string.Format("While moving {0} from {1} to {2}, tile.index already exists in this.tiles.", tile.name, oldIndex, tile.index)); } this.tiles[tile.index] = tile; if (serialize && !this.deserializing && this.serializing != null && this.CanSerialize(tile)) { this.serializing.Serialize(); } } public GridTile FindTileAt(GridIndex index, GridSize size) { for (int i = index.v; i > index.v - size.v; i--) { for (int j = index.u; j > index.u - size.u; j--) { GridElement gridElement = this.elements[j, i]; if (gridElement.Tile != null) { return gridElement.Tile; } } } return null; } public IEnumerator GetTileEnumerator() { return this.tiles.Values.GetEnumerator(); } public List GetNeighbourTiles(GridTile tile) { GridIndex index = tile.index; GridSize gridSize = tile.size; List list = new List(); for (int i = index.v; i > index.v - gridSize.v; i--) { foreach (int num in new int[] { index.u + 1, index.u - gridSize.u }) { GridIndex index2 = new GridIndex(num, i); if (this.IsWithinBounds(index2)) { GridElement gridElement = this.elements[num, i]; if (gridElement.Tile != null) { list.Add(gridElement.Tile); } } } } for (int k = index.u; k > index.u - gridSize.u; k--) { foreach (int num2 in new int[] { index.v + 1, index.v - gridSize.v }) { GridIndex index3 = new GridIndex(k, num2); if (this.IsWithinBounds(index3)) { GridElement gridElement2 = this.elements[k, num2]; if (gridElement2.Tile != null) { list.Add(gridElement2.Tile); } } } } return list; } public bool IsWithinBounds(GridIndex index) { return !index.isInvalid && index.u < this.Size.u && index.v < this.Size.v; } public bool IsWithinBounds(int u, int v) { return u >= 0 && v >= 0 && u < this.Size.u && v < this.Size.v; } public int sizeU = 100; public int sizeV = 100; public Vector2 elementSize = new Vector2(100f, 50f); public float zNear = -2f; public float zFar = -1f; public float zRoadOffset = 1f; public TextAsset elementTypes; public bool readOnlyGrid; public ReadOnlyWrapper readOnlyWapper; [ParentReference] public IsometricIsland island; [SelfReference] public Serializing serializing; [SelfReference] public GridOverlay overlay; protected GridSize size; protected GridElement[,] elements; protected Dictionary tiles; protected bool[] _availableSurfaceTypes; protected bool deserializing; public delegate void GridDeserializedEventHandler(UnityEngine.Object sender); } }