no message

This commit is contained in:
PC-20230316NUNE\Administrator
2024-02-20 18:39:12 +08:00
parent 97b3671979
commit 2b467e56ad
1876 changed files with 440340 additions and 35266 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c252000f45a359844bbc365b3584318c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,81 @@
using System;
namespace HPJ.Simulation.Map
{
public class AgentMap
{
/// <summary>
/// Base map related to this map
/// </summary>
public Map Base { get; protected set; }
/// <summary>
/// Tile that descripe the agent ownership
/// </summary>
public ushort[,] Tiles { get; protected set; }
/// <summary>
/// Initializes the agent map based on the base map
/// </summary>
/// <param name="baseMap"></param>
public AgentMap(Map baseMap)
{
Base = baseMap;
Tiles = new ushort[baseMap.Settings.MapWidth, baseMap.Settings.MapHeight];
}
/// <summary>
/// Disowns this tile so other agents can claim it or to know its availible
/// </summary>
/// <param name="ownedTile"></param>
public void DisownTile(IntVector2 ownedTile, ushort ID)
{
if (ownedTile.x < 0 || ownedTile.y < 0 || ownedTile.x >= Base.Settings.MapWidth || ownedTile.y >= Base.Settings.MapHeight)
{
return;
}
if (Tiles[ownedTile.x, ownedTile.y] == ID)
{
Tiles[ownedTile.x, ownedTile.y] = 0;
}
}
/// <summary>
/// Attempts to claim a tile for a specified ID
/// </summary>
/// <param name="newTilePosition"></param>
/// <param name="ID"></param>
/// <returns></returns>
public bool ClaimTile(IntVector2 newTilePosition, ushort ID)
{
if (newTilePosition.x < 0 || newTilePosition.y < 0 || newTilePosition.x >= Base.Settings.MapWidth || newTilePosition.y >= Base.Settings.MapHeight)
{
return false;
}
if (Tiles[newTilePosition.x, newTilePosition.y] == 0)
{
Tiles[newTilePosition.x, newTilePosition.y] = ID;
return true;
}
return false;
}
internal bool IsBlocked(int x, int y, ushort CompareID)
{
return Tiles[x, y] != 0 && Tiles[x, y] != CompareID;
}
public bool ValidTileForAgent(ushort simNavigationAgentID, int x, int y)
{
if (Tiles[x, y] == 0 || Tiles[x, y] == simNavigationAgentID)
{
return true;
}
return false;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6d12e6518def9eb4698b61dd77af94a1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,129 @@
using HPJ.Simulation.Enums;
using HPJ.Simulation.Utilities;
using System.Linq;
namespace HPJ.Simulation.Map
{
/// <summary>
/// A Flattenned version of a map that changes every tile type into a 1 or 0. Is it traverable or is it not
/// </summary>
[System.Serializable]
public class BytePointMap
{
private byte[,] _tiles;
/// <summary>
/// The Tiles for the Byte Map
/// </summary>
public byte[,] Tiles { get { return _tiles; } }
private int _width;
/// <summary>
/// The Width of the Byte Map
/// </summary>
public int Width { get { return _width; } }
private int _length;
/// <summary>
/// The Length of the Byte Map
/// </summary>
public int Length { get { return _length; } }
private bool _cornerCutting;
/// <summary>
/// Whether corner cuttins is enabled on this map
/// </summary>
public bool CornerCutting { get { return _cornerCutting; } set { _cornerCutting = value; } }
private string _traversableKey;
/// <summary>
/// The Key used to flatten the map
/// </summary>
public string TraversableKey { get { return _traversableKey; } }
private TileTypes[] _traversable;
/// <summary>
/// The Tiles that are traversable on this map
/// </summary>
public TileTypes[] Traversable { get { return _traversable; } }
public BytePointMap(byte[,] TileTypeMap, TileTypes[] TraversableTiles, int TileMapWidth, int TileMapLength, bool CornerCuttingEnabled)
{
_traversable = TraversableTiles;
_traversableKey = TraversableTiles.TilesToString();
_cornerCutting = CornerCuttingEnabled;
_tiles = new byte[TileMapWidth, TileMapLength];
_width = TileMapWidth;
_length = TileMapLength;
for (int x = 0; x < TileMapWidth; x++)
{
for (int y = 0; y < TileMapLength; y++)
{
if (_traversable.Contains((TileTypes)TileTypeMap[x, y]))
{
_tiles[x, y] = 100;
}
else
{
_tiles[x, y] = 0;
}
}
}
}
/// <summary>
/// Changes the tile of the byte map
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="newType"></param>
public void ChangeTile(int x, int y, TileTypes newType)
{
if (_traversable.Contains(newType))
{
_tiles[x, y] = 100;
}
else
{
_tiles[x, y] = 0;
}
}
/// <summary>
/// Changes the tile of the byte map
/// </summary>
/// <param name="TileIndex"></param>
/// <param name="newType"></param>
public void ChangeTile(IntVector2 TileIndex, TileTypes newType)
{
if (_traversable.Contains(newType))
{
_tiles[TileIndex.x, TileIndex.y] = 100;
}
else
{
_tiles[TileIndex.x, TileIndex.y] = 0;
}
}
/// <summary>
/// Gets the speed of the tile
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
public byte GetTileSpeed(int x, int y)
{
if (x < 0 || x >= _width)
{
return 0;
}
if (y < 0 || y >= _length)
{
return 0;
}
return _tiles[x, y];
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a78ad3bb786105e4498376a108278248
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,27 @@
using HPJ.Simulation.Enums;
using System.Collections;
using System.Collections.Generic;
namespace HPJ.Simulation.Map
{
[System.Serializable]
public class ChangeMapJob
{
public List<(IntVector2, TileTypes)> TilesToBeChanged;
public ChangeMapJob(List<(IntVector2, TileTypes)> TilesChanged)
{
TilesToBeChanged = TilesChanged;
}
public ChangeMapJob()
{
TilesToBeChanged = new List<(IntVector2, TileTypes)>();
}
public void AddTileChange(IntVector2 TileIndex, TileTypes TypeChange)
{
TilesToBeChanged.Add((TileIndex, TypeChange));
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4dee08e2c91f0874cb9ddeb7d3b8261f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 76e9eb321b9adff43b8e51b251db8e1d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b9694e0d5a80a3c4eb0b89141c221aff
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,26 @@
namespace HPJ.Simulation
{
public struct TileOwnershipClaim
{
public ushort OwnerID;
public IntVector2 RequestTile;
public TileOwnershipClaim(ushort ID, IntVector2 Tile)
{
OwnerID = ID;
RequestTile = Tile;
}
}
public struct DisownTileOwnership
{
public ushort OwnerID;
public IntVector2 RequestTile;
public DisownTileOwnership(ushort ID, IntVector2 Tile)
{
OwnerID = ID;
RequestTile = Tile;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6db62976e6c7e20499490631bbbc2382
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 48809749fb43d0b45800347fa4e2a389
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,294 @@
using HPJ.Simulation.Enums;
using HPJ.Simulation.Map;
using HPJ.Simulation.Utilities;
using System;
using System.Collections.Generic;
using System.Linq;
namespace HPJ.Simulation.Pathing
{
public class AStar : PathingCalculation
{
public static AStar Instance = null;
public override void Initialize()
{
NavigationType = Enums.NavigationTypes.AStar;
if (!PathingTypes.ContainsKey(NavigationType))
{
PathingTypes.Add(NavigationType, this);
}
}
public override void CalculatePath(NavigationPath Path, Map.Map OccuringMap, out string Status, out bool Succeeded)
{
try
{
List<IntVector2> OpenList = new List<IntVector2>();
HashSet<IntVector2> ClosedList = new HashSet<IntVector2>();
Dictionary<IntVector2, AStarTileData> SortedList = new Dictionary<IntVector2, AStarTileData>();
IntVector2 StartTile = Path.Info.PointA;
IntVector2 EndTile = Path.Info.PointB;
OpenList.Add(StartTile);
AStarTileData StartingTileData = new AStarTileData(new IntVector2(-1, -1), CalculateDistanceCost(StartTile.x, StartTile.y, EndTile.x, EndTile.y));
StartingTileData.GCost = 0;
StartingTileData.FCost = StartingTileData.GCost + StartingTileData.HCost;
SortedList.Add(StartTile, StartingTileData);
int TentativeGCost = 0;
IntVector2 CurrentTile = StartTile;
int Iterations = 0;
bool MaxIterationsMade = false;
int MaxIterations = 3000;
// Get BitMap
BytePointMap BitMap = Path.HostMap.GetBytePointMap(Path);
TileTypes[] PrefferedTiles = Path.Info.PrefferedTilesKey.StringToTilesArray();
while (OpenList.Count > 0)
{
// Give a safty range of 2 times the range in terms of iterations, if it cannot find a path by then, it's failed. can probably cannot be reached
if (Iterations > MaxIterations)
{
MaxIterationsMade = true;
break;
}
Iterations++;
int CurrentNodeIndex = GetLowestFCostTileIndex(OpenList, Path.HostMap, StartTile, EndTile, CurrentTile, PrefferedTiles);
CurrentTile = OpenList[CurrentNodeIndex];
if (EndTile == CurrentTile)
{
// Reached the end
//Debug.Log("Found the End - Should be Path Complete");
break;
}
// Remove current
OpenList.RemoveAt(CurrentNodeIndex);
ClosedList.Add(CurrentTile);
AStarTileData CurrentData = SortedList[CurrentTile];
for (int x = -1; x <= 1; x++)
{
for (int y = -1; y <= 1; y++)
{
if (x == 0 && y == 0)
{
continue;
}
IntVector2 neighbourPosition = new IntVector2(CurrentTile.x + x, CurrentTile.y + y);
if (BitMap.GetTileSpeed(neighbourPosition.x, neighbourPosition.y) == 0)
{
continue;
}
if (ClosedList.Contains(neighbourPosition))
{
continue;
}
// Get Corner Types, if its a wall, continue (DO NOT WALK THROUGH WALLS)
if (!BitMap.CornerCutting)
{
if (x != 0 && y != 0)
{
IntVector2 cornerAdjacentPosition = new IntVector2(CurrentTile.x + x, CurrentTile.y);
if (BitMap.Tiles[cornerAdjacentPosition.x, cornerAdjacentPosition.y] == 0)
{
continue;
}
cornerAdjacentPosition.x = CurrentTile.x;
cornerAdjacentPosition.y = CurrentTile.y + y;
if (BitMap.Tiles[cornerAdjacentPosition.x, cornerAdjacentPosition.y] == 0)
{
continue;
}
}
}
AStarTileData NeighbourData;
if (!SortedList.TryGetValue(neighbourPosition, out NeighbourData))
{
NeighbourData = new AStarTileData(new IntVector2(-1, -1), CalculateDistanceCost(neighbourPosition.x, neighbourPosition.y, EndTile.x, EndTile.y));
SortedList.Add(neighbourPosition, NeighbourData);
}
TentativeGCost = CurrentData.GCost + CalculateDistanceCost(CurrentTile.x, CurrentTile.y, neighbourPosition.x, neighbourPosition.y);
if (TentativeGCost < NeighbourData.GCost)
{
//Debug.Log("Lower G Cost");
NeighbourData.RouteFromTileIndex = CurrentTile;
NeighbourData.GCost = TentativeGCost;
NeighbourData.FCost = NeighbourData.GCost + NeighbourData.HCost;
SortedList[neighbourPosition] = NeighbourData;
if (!OpenList.Contains(neighbourPosition))
{
//Debug.Log("LEnter To OpenList");
OpenList.Add(neighbourPosition);
}
}
}
}
}
AStarTileData EndTileData;
if (MaxIterationsMade)
{
Succeeded = false;
Status = $"Path is too far away, or cannot be reached --> Iteration Max Reached {MaxIterations}";
}
else if (!SortedList.TryGetValue(EndTile, out EndTileData) || EndTileData.RouteFromTileIndex.x == -1)
{
// No Valid Path Found
Succeeded = false;
Status = "Open list emptied - But did NOT reach the End, Likely Trapped";
}
else
{
Succeeded = true;
// Path should be valid
SortPath(Path, SortedList, EndTile);
Status = $"Found a Valid Path 'Iterations ({Iterations} / {MaxIterations})' -> 'List Counts (Open:{OpenList.Count} / Closed:{ClosedList.Count})'";
}
}
catch (Exception ex)
{
Status = "Faled";
OccuringMap.LogError($"{ex.Message}: {ex.Source}: {ex.StackTrace}");
Succeeded = false;
}
}
protected int GetLowestFCostTileIndex(List<IntVector2> OpenList, Map.Map OccuringMap, IntVector2 Start, IntVector2 End, IntVector2 CurrentTileIndex, TileTypes[] PrefferedTiles)
{
int LowestCostIndex = 0;
if (PrefferedTiles.Contains(OccuringMap.GetTileType(CurrentTileIndex)))
{
// Try to stick to the group tile unless the tile is farther from the start AND closer to the end
int CurrentStartScore = CalculateDistanceCost(CurrentTileIndex.x, CurrentTileIndex.y, Start.x, Start.y);
int CurrentEndScore = CalculateDistanceCost(CurrentTileIndex.x, CurrentTileIndex.y, End.x, End.y);
int LowestSameCostIndex = -1;
TileTypes ZeroTileType = OccuringMap.GetTileType(OpenList[0].x, OpenList[0].y);
byte TileSpeed = OccuringMap.GetTileSpeedData(ZeroTileType);
int ZeroStartScore = CalculateDistanceCost(OpenList[0].x, OpenList[0].y, Start.x, Start.y);
int ZeroEndScore = CalculateDistanceCost(OpenList[0].x, OpenList[0].y, End.x, End.y);
int CurrentLowestCost = ZeroEndScore / TileSpeed;
int CurrentSameLowestCost = int.MaxValue;
if (PrefferedTiles.Contains(ZeroTileType) || (ZeroStartScore > CurrentStartScore && ZeroEndScore < CurrentEndScore))
{
LowestSameCostIndex = 0;
CurrentSameLowestCost = CurrentLowestCost;
}
for (int i = 1; i < OpenList.Count; i++)
{
TileTypes iTileType = OccuringMap.GetTileType(OpenList[i].x, OpenList[i].y);
TileSpeed = OccuringMap.GetTileSpeedData(iTileType);
int iStartScore = CalculateDistanceCost(OpenList[i].x, OpenList[i].y, Start.x, Start.y);
int iEndScore = CalculateDistanceCost(OpenList[i].x, OpenList[i].y, End.x, End.y);
int testCost = iEndScore / TileSpeed;
if (testCost < CurrentLowestCost)
{
CurrentLowestCost = testCost;
LowestCostIndex = i;
}
if (PrefferedTiles.Contains(iTileType) || (iStartScore > CurrentStartScore && iEndScore < CurrentEndScore))
{
if (testCost < CurrentSameLowestCost)
{
LowestSameCostIndex = i;
CurrentSameLowestCost = testCost;
}
}
}
if (LowestSameCostIndex != -1)
{
return LowestSameCostIndex;
}
}
else
{
// Typical AStar pathfinding
int TileSpeed = OccuringMap.GetTileSpeedData(OccuringMap.GetTileType(OpenList[0].x, OpenList[0].y));
int CurrentLowestCost = CalculateDistanceCost(OpenList[0].x, OpenList[0].y, End.x, End.y) / TileSpeed;
for (int i = 1; i < OpenList.Count; i++)
{
TileSpeed = OccuringMap.GetTileSpeedData(OccuringMap.GetTileType(OpenList[i].x, OpenList[i].y));
int testCost = CalculateDistanceCost(OpenList[i].x, OpenList[i].y, End.x, End.y) / TileSpeed;
if (testCost < CurrentLowestCost)
{
CurrentLowestCost = testCost;
LowestCostIndex = i;
}
}
}
return LowestCostIndex;
}
protected int CalculateDistanceCost(int x1, int y1, int x2, int y2)
{
int X_Distance = x1 - x2;
X_Distance = X_Distance < 0 ? -X_Distance : X_Distance;
int Y_Distance = y1 - y2;
Y_Distance = Y_Distance < 0 ? -Y_Distance : Y_Distance;
int remaining = X_Distance - Y_Distance;
remaining = remaining < 0 ? -remaining : remaining;
if (Y_Distance < X_Distance)
{
return 14 * Y_Distance + 10 * remaining;
}
else
{
return 14 * X_Distance + 10 * remaining;
}
}
protected void SortPath(NavigationPath Path, Dictionary<IntVector2, AStarTileData> SortedData, IntVector2 EndTileIndex)
{
AStarTileData CurrentTile = SortedData[EndTileIndex];
int InsertIndex = Path.Path.Count;
Path.Path.Insert(InsertIndex, EndTileIndex);
// The Route From Index of the starting tile should be the only one with a (-1, -1) index
while (CurrentTile.RouteFromTileIndex.x != -1)
{
Path.Path.Insert(InsertIndex, CurrentTile.RouteFromTileIndex);
CurrentTile = SortedData[CurrentTile.RouteFromTileIndex];
}
}
public struct AStarTileData
{
public IntVector2 RouteFromTileIndex;
public int FCost;
public int GCost;
public int HCost;
public AStarTileData(IntVector2 RouteFromTile, int EndCost)
{
RouteFromTileIndex = RouteFromTile;
FCost = int.MaxValue;
GCost = int.MaxValue;
HCost = EndCost;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 183160215d33bde4981db6e6901c2972
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 91124dce985e03b428dfcfd28071da97
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,340 @@
using HPJ.Simulation.Enums;
using HPJ.Simulation.Map;
using HPJ.Simulation.Utilities;
using System;
using System.Collections;
using System.Collections.Generic;
namespace HPJ.Simulation.Pathing
{
/// <summary>
/// The Base class for any pathfinding algorithms
/// </summary>
public abstract class PathingCalculation
{
/// <summary>
/// The Navigation Type this pathing is. Will need to add yours to the enum
/// </summary>
public NavigationTypes NavigationType { get; protected set; }
/// <summary>
/// The Dictionary of all the pathing algorithms
/// </summary>
public static Dictionary<NavigationTypes, PathingCalculation> PathingTypes = new Dictionary<NavigationTypes, PathingCalculation>();
public PathingCalculation()
{
Initialize();
}
/// <summary>
/// Initializes the Algorithm, You will need to call this or add this for your algorithm
/// </summary>
public virtual void Initialize()
{
NavigationType = NavigationTypes.None;
if (!PathingTypes.ContainsKey(NavigationType))
{
PathingTypes.Add(NavigationType, this);
}
}
/// <summary>
/// Calculates the Path for a Navigation Job Request on a specific Map
/// </summary>
/// <param name="Path"></param>
/// <param name="OccuringMap"></param>
/// <param name="Status"></param>
/// <param name="Succeeded"></param>
public abstract void CalculatePath(NavigationPath Path, Map.Map OccuringMap, out string Status, out bool Succeeded);
}
/// <summary>
/// A Navigation Job Request
/// </summary>
[Serializable]
public class NavigationJob
{
#region Navigation Info
/// <summary>
/// Infomation on this Job
/// </summary>
public PathingInfo Info;
/// <summary>
/// Current Step on the Pathfinding Calculation
/// </summary>
public PathfindingCalculationStep CurrentStep;
/// <summary>
/// The Number of tiles away from the start to the end
/// </summary>
public int TilesAway;
/// <summary>
/// Point A of the Path
/// </summary>
public IntVector3 WorldPointA;
/// <summary>
/// Point B of the Path
/// </summary>
public IntVector3 WorldPointB;
/// <summary>
/// If this Job was compatable or not
/// </summary>
public bool Compatable;
/// <summary>
/// Next time this path is pathed, repath it
/// </summary>
public bool RepathSavedPath;
/// <summary>
/// List of Traversable Tiles
/// </summary>
public List<TileTypes> TraverableTileTypes;
/// <summary>
/// List of Prefferred Tiles
/// </summary>
public List<TileTypes> PrefferedTileTypes;
#endregion
#region Navigation Results
/// <summary>
/// The Resulting Path for this Job Request
/// </summary>
public NavigationPath CurrentPath { get; protected set; }
public ushort AgentID { get; set; }
/// <summary>
/// The Callback to the presentation side
/// </summary>
public Action OnCompleteCallback;
#endregion
public NavigationJob(Action onCompleteCallback)
{
Info = new PathingInfo();
CurrentPath = null;
CurrentStep = PathfindingCalculationStep.Incomplete;
OnCompleteCallback = onCompleteCallback;
AgentID = 0;
}
/// <summary>
/// Clears the Job and reverts it back to default
/// </summary>
public void Clear()
{
Info = new PathingInfo();
CurrentPath = null;
CurrentStep = PathfindingCalculationStep.Incomplete;
}
/// <summary>
/// Initializes the Job with the neccessary pathing information
/// </summary>
/// <param name="Start"></param>
/// <param name="End"></param>
/// <param name="TraverableKey"></param>
/// <param name="PrefferedTilesKey"></param>
/// <param name="Navigation"></param>
/// <param name="ForMap"></param>
/// <param name="RepathAnyway"></param>
public void SetDestinationInfo(IntVector3 Start, IntVector3 End, List<TileTypes> TraverableTiles, List<TileTypes> PrefferedTiles, NavigationTypes Navigation, MapSet ForMap, bool RepathAnyway = false)
{
if (Start.x < End.x)
{
WorldPointA = Start;
WorldPointB = End;
}
else if (Start.x > End.x)
{
WorldPointA = End;
WorldPointB = Start;
}
else
{
if (Start.z < End.z)
{
WorldPointA = Start;
WorldPointB = End;
}
else if (Start.z > End.z)
{
WorldPointA = End;
WorldPointB = Start;
}
else
{
WorldPointA = Start;
WorldPointB = End;
}
}
TraverableTileTypes = TraverableTiles;
PrefferedTileTypes = PrefferedTiles;
RepathSavedPath = RepathAnyway;
Info = new PathingInfo(ForMap.GetMapTileIndex(WorldPointA), ForMap.GetMapTileIndex(WorldPointB), Navigation, TraverableTiles.TilesToString(), PrefferedTiles.TilesToString());
TilesAway = JumpPointSearch.Instance.CalculateDistanceCost(Start.x, Start.z, End.x, End.z);
Compatable = ForMap.JobCompatible(this);
}
/// <summary>
/// Sets the resulting path to the request
/// </summary>
/// <param name="path"></param>
internal void SetNewCurrentPath(NavigationPath path)
{
CurrentPath = path;
}
/// <summary>
/// The callback from the simulation when the job request is finished
/// </summary>
internal void PathfindingComplete()
{
CurrentStep = PathfindingCalculationStep.Complete;
OnCompleteCallback?.Invoke();
}
}
/// <summary>
/// The Calculated Path on a specific Map
/// </summary>
[System.Serializable]
public class NavigationPath
{
/// <summary>
/// The map the path was calculated on
/// </summary>
public Map.Map HostMap;
/// <summary>
/// The Information on this Path
/// </summary>
public PathingInfo Info;
/// <summary>
/// The Resulting Path
/// </summary>
public List<IntVector2> Path;
/// <summary>
/// If this Path resulting in a valid path
/// </summary>
public bool ValidPath;
/// <summary>
/// Previous status on the path
/// </summary>
public string PreviousStatus { get; set; }
/// <summary>
/// Asking For Path from specific agent
/// </summary>
public ushort AgentID;
public NavigationPath()
{
Info = new PathingInfo();
Path = new List<IntVector2>();
ValidPath = false;
PreviousStatus = "";
AgentID = 0;
}
public NavigationPath(PathingInfo PathInfo, Map.Map hostMap, ushort ID = 0)
{
Info = PathInfo;
Path = new List<IntVector2>();
ValidPath = false;
HostMap = hostMap;
PreviousStatus = "";
AgentID = 0;
}
/// <summary>
/// Checks to see if your starting point is the first index of the path or the last
/// </summary>
/// <param name="startPoint"></param>
/// <returns></returns>
public bool NeedToReverse(IntVector3 startPoint)
{
if (!ValidPath)
{
return false;
}
if (Path.Count <= 0)
{
return false;
}
return Path[0] != HostMap.GetTileIndexPosition(startPoint);
}
}
/// <summary>
/// The information on a given path
/// </summary>
[System.Serializable]
public struct PathingInfo
{
/// <summary>
/// Point A of a Path
/// </summary>
public IntVector2 PointA;
/// <summary>
/// Point B of a Path
/// </summary>
public IntVector2 PointB;
/// <summary>
/// Navigation type used for this Path
/// </summary>
public NavigationTypes NavigationType;
/// <summary>
/// Traversable Tiles Key
/// </summary>
public string TraversableTilesKey;
/// <summary>
/// Preffered Tile Kep
/// </summary>
public string PrefferedTilesKey;
public PathingInfo(IntVector2 A, IntVector2 B, NavigationTypes Type, string Traverable, string Preffered)
{
// Sort tiles by bottom left so there is no repeats in the saved path Dictionary
if (A.x < B.x)
{
PointA = A;
PointB = B;
}
else if (A.x > B.x)
{
PointA = B;
PointB = A;
}
else
{
if (A.y < B.y)
{
PointA = A;
PointB = B;
}
else if (A.y > B.y)
{
PointA = B;
PointB = A;
}
else
{
PointA = A;
PointB = B;
}
}
NavigationType = Type;
TraversableTilesKey = Traverable;
PrefferedTilesKey = Preffered;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5785cb1e31a25e948b0f11f9b7ae1b5d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b47d43b65afd2aa41bc9924ebeebe679
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,140 @@
namespace HPJ.Simulation.Enums
{
/// <summary>
/// The Navigation Types a agent can use for pathfinding
/// </summary>
public enum NavigationTypes
{
None = 0, // No Navigation Possible
Free = 1,
JumpPointSearch = 2,
AStar = 3,
Unknown = 4,
}
/// <summary>
/// The Navigation Tile Types that are availble on a Map, add more as needed
/// </summary>
public enum TileTypes : byte
{
Standard = 0,
Blocked = 1,
Free = 2,
Void = 3,
Obstacle = 4,
Water = 5,
OutOfBounds = 6,
}
/// <summary>
/// Bridge Direction Types
/// </summary>
public enum BridgeDirections : byte
{
Both = 0,
A_To_B = 1,
B_To_A = 2,
}
/// <summary>
/// Who has right of way based on your moving direction
/// </summary>
public enum RightOfWay : byte
{
NorthWest = 0,
SouthEast = 1,
}
/// <summary>
/// How agents try to avoid each other
/// </summary>
public enum AvoidenceType : byte
{
StopAndGo = 0,
TryToPathAround = 1,
}
/// <summary>
/// The seam connection side
/// </summary>
public enum SeamConnectionSide : byte
{
North = 0,
West = 1,
South = 2,
East = 3,
}
public enum DistanceCheck
{
Manhatten = 0,
Distance = 1,
SqrDistance,
}
public enum MovementType
{
FourDirection = 0,
EightDirection = 1,
}
public enum PathfindingCalculationStep
{
Incomplete = 0,
Pathfinding = 1,
Complete = 2,
Finalized = 3,
}
public enum SimulationDebugLog
{
Log = 0,
Warning = 1,
Error = 2,
}
public enum MapExpansionSide
{
Top = 0,
Bottom = 1,
Left = 2,
Right = 3,
}
public enum PainterTypes
{
Square = 0,
Circle = 1,
}
public enum ObstacleValidationStates : byte
{
Validated = 0,
Invalidated = 1,
Added = 2,
}
public enum AgentStates : byte
{
Stopped = 0,
Paused = 1,
Pathfinding = 2,
Moving = 3,
FailedPathing = 4,
SucceededPathing = 5,
Idle = 6,
}
public enum DestinationStates : byte
{
None = 0,
SameMap = 1,
Bridge = 2,
NextMap_FromBridge = 3,
ClosestPoint = 4,
Null = 5,
SamePosition = 6,
Seam = 7,
NextMap_FromSeam = 8,
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1e598b475ade85241be20aea419b3429
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2528b26349a8af24c93f6911e62a23fd
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,79 @@
using HPJ.Simulation.Enums;
using System.Collections;
using System.Collections.Generic;
namespace HPJ.Simulation.Utilities
{
public static class Extensions
{
public static float Distance(this IntVector2 vector)
{
return (float)System.Math.Sqrt(vector.x * vector.x + vector.y * vector.y);
}
public static int SqrDistance(this IntVector2 vector)
{
return vector.x * vector.x + vector.y * vector.y;
}
public static string TilesToString(this TileTypes[] Tiles)
{
if (Tiles.Length == 0)
{
return "";
}
string ReturnString = "";
for(int i = 0; i < Tiles.Length - 1; i++)
{
ReturnString += $"{Tiles[i]}.";
}
ReturnString += $"{Tiles[Tiles.Length - 1]}.";
return ReturnString;
}
public static string TilesToString(this List<TileTypes> Tiles)
{
if (Tiles.Count == 0)
{
return "";
}
string ReturnString = "";
for (int i = 0; i < Tiles.Count - 1; i++)
{
ReturnString += $"{Tiles[i]}.";
}
ReturnString += $"{Tiles[Tiles.Count - 1]}.";
return ReturnString;
}
public static TileTypes[] StringToTilesArray(this string TilesStringArray)
{
string[] Split = TilesStringArray.Split('.');
if (Split.Length == 0)
{
return new TileTypes[1] { TileTypes.Free };
}
TileTypes[] ReturnArr = new TileTypes[Split.Length];
string[] EnumNames = System.Enum.GetNames(typeof(TileTypes));
for (int splitIndex = 0; splitIndex < Split.Length; splitIndex++)
{
for(int enumIndex = 0; enumIndex < EnumNames.Length; enumIndex++)
{
if (EnumNames[enumIndex] == Split[splitIndex])
{
ReturnArr[splitIndex] = (TileTypes)enumIndex;
}
}
}
return ReturnArr;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bf82f03bbe52cc14c8644aca8076615f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5b17713f3d6762747909224fe3c9184e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,59 @@
using System.Collections.Generic;
namespace HPJ.Simulation.Utilities
{
[System.Serializable]
public class Pool<T>
{
public List<T> Active;
public List<T> Inactive;
public Pool()
{
Active = new List<T>();
Inactive = new List<T>();
}
public T GetItem()
{
if (Inactive.Count > 0)
{
T Item = Inactive[0];
Inactive.RemoveAt(0);
return Item;
}
return default(T);
}
public void ReturnItem(T Item)
{
if (Active.Contains(Item))
{
Active.Remove(Item);
Inactive.Add(Item);
}
}
public void AddItem(T Item, bool AddToActiveList = true)
{
if (AddToActiveList)
{
Active.Add(Item);
}
else
{
Inactive.Add(Item);
}
}
public void ReturnAll()
{
for (int i = 0; i < Active.Count; i++)
{
Inactive.Add(Active[i]);
}
Active.Clear();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f8bf26b81289be840af5d4dfdb184443
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,16 @@
{
"name": "HPJ_Simulation",
"rootNamespace": "HPJ.Simulation",
"references": [],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": true,
"precompiledReferences": [
"Newtonsoft.Json.dll"
],
"autoReferenced": false,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": true
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 2964754212fd90b4188341fc9783c7d6
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: