public void HandleChangeMapMessage(Bot bot, ChangeMapMessage message) { MapPositionData mapPosition = MapsPositionManager.Instance.GetMapPosition(message.mapId); if (m_lastPath != null && m_lastMapPos != null) { MapNeighbour direction = Map.GetDirectionOfTransitionCell(m_lastPath.End); int? neighbour = m_lastMapPos.GetNeighbourId(direction); if (neighbour == null) { bot.Character.SendWarning("The actual map ({0}) is not the {1} neighbour of the previous map {2} (NOT FOUND)", message.mapId, direction, m_lastMapPos.MapId); } else if (neighbour != message.mapId) { bot.Character.SendWarning("The actual map ({0}) is not the {1} neighbour of the previous map {2}" + "(MISMATCH attempt : {3})", message.mapId, direction, m_lastMapPos.MapId, neighbour); } else { bot.Character.SendDebug("You came from {0}", direction); } } m_lastMapPos = mapPosition; }
public virtual bool Teleport(MapNeighbour mapNeighbour) { var neighbour = Position.Map.GetNeighbouringMap(mapNeighbour); if (neighbour == null) { return(false); } var cell = Position.Map.GetCellAfterChangeMap(Position.Cell.Id, mapNeighbour); if (cell < 0 || cell >= 560) { logger.Error("Cell {0} out of range, current={1} neighbour={2}", cell, Cell.Id, mapNeighbour); return(false); } var destination = new ObjectPosition(neighbour, cell, Position.Direction); if (!destination.Cell.Walkable) { var cells = MapPoint.GetBorderCells(mapNeighbour).Select(x => neighbour.Cells[x.CellId]).Where(x => x.Walkable); var walkableCell = cells.Select(x => new MapPoint(x)).OrderBy(x => x.EuclideanDistanceTo(destination.Point)).FirstOrDefault(); if (walkableCell != null) { destination.Cell = neighbour.Cells[walkableCell.CellId]; } } return(Teleport(destination)); }
public static ICell GetTransitionCell(this IMap map, MapNeighbour mapNeighbour) { int MapChangeMask = GetMapChangeMask(mapNeighbour); // Check if at least one cell allow a transition to the supposed-to-be neighbour return(map.Cells.FirstOrDefault(cell => (cell.MapChangeData & MapChangeMask) != 0)); }
public static int GetNeighbourMapId(this IMap map, MapNeighbour mapNeighbour, bool GetStoredVersion) { if (GetStoredVersion) { switch (mapNeighbour) { case MapNeighbour.Bottom: return(map.BottomNeighbourId); case MapNeighbour.Top: return(map.TopNeighbourId); case MapNeighbour.Left: return(map.LeftNeighbourId); case MapNeighbour.Right: return(map.RightNeighbourId); default: throw new ArgumentOutOfRangeException("MapNeighbour"); } } int MapChangeMask = GetMapChangeMask(mapNeighbour); // Check if at least one cell allow a transition to the supposed-to-be neighbour bool ChangeMapFound = map.Cells.Any(cell => (cell.MapChangeData & MapChangeMask) != 0); if (ChangeMapFound) { return(new WorldPoint(map.Id, mapNeighbour).MapID); } return(-1); }
private int?TryGetMapNeighbour(int mapid, MapNeighbour neighbour) { MapPositionData position; if (!m_mapsPosition.TryGetValue(mapid, out position)) { return(null); } switch (neighbour) { case MapNeighbour.Left: return(position.LeftNeighbourId); case MapNeighbour.Right: return(position.RightNeighbourId); case MapNeighbour.Bottom: return(position.BottomNeighbourId); case MapNeighbour.Top: return(position.TopNeighbourId); } return(null); }
/// <summary> /// Says if there is any transition cell in a given direction within a region /// If subMapId == 0, then considers all non-walkable cells (not set to any subMap). /// </summary> /// <param name="subMapId"></param> /// <returns></returns> public bool HasTransition(byte subMapId, MapNeighbour direction) { int transitionMask = World.Map.MapChangeDatas[direction]; foreach (CellInfo cellinfo in _cells) if (cellinfo.SubMapId == subMapId && (cellinfo.MapLink & transitionMask) != 0) return true; return false; }
public static void HandleChangeMapMessage(WorldClient client, ChangeMapMessage message) { MapNeighbour clientMapRelativePosition = client.Character.Map.GetClientMapRelativePosition(message.mapId); if (clientMapRelativePosition != MapNeighbour.None && client.Character.Position.Cell.MapChangeData != 0) { client.Character.Teleport(clientMapRelativePosition); } }
/// <summary> /// Retrieves the transition cells for in given direction within a region /// If subMapId == 0, then considers all non-walkable cells (not set to any subMap). /// </summary> /// <param name="subMapId"></param> /// <returns></returns> public IEnumerable <Cell> GetTransitionCells(byte subMapId, MapNeighbour direction) { int transitionMask = World.Map.MapChangeDatas[direction]; foreach (CellInfo cellinfo in _cells) { if (cellinfo.SubMapId == subMapId && (cellinfo.MapLink & transitionMask) != 0) { yield return(cellinfo.Cell); } } }
/// <summary> /// Says if there is any transition cell in a given direction within a region /// If subMapId == 0, then considers all non-walkable cells (not set to any subMap). /// </summary> /// <param name="subMapId"></param> /// <returns></returns> public bool HasTransition(byte subMapId, MapNeighbour direction) { int transitionMask = World.Map.MapChangeDatas[direction]; foreach (CellInfo cellinfo in _cells) { if (cellinfo.SubMapId == subMapId && (cellinfo.MapLink & transitionMask) != 0) { return(true); } } return(false); }
public static IEnumerable <MapPoint> GetBorderCells(MapNeighbour mapNeighbour) { switch (mapNeighbour) { case MapNeighbour.Top: return(GetCellsInLine(new MapPoint(546), new MapPoint(559))); case MapNeighbour.Left: return(GetCellsInLine(new MapPoint(27), new MapPoint(559))); case MapNeighbour.Bottom: return(GetCellsInLine(new MapPoint(0), new MapPoint(13))); case MapNeighbour.Right: return(GetCellsInLine(new MapPoint(0), new MapPoint(532))); } return(new MapPoint[0]); }
/* * public bool ChangeMap(MapNeighbour? neighbour, ISimplePathFinder pathfinder=null) * { * * var mapChangeData = Map.MapChangeDatas[neighbour]; * Path path = null; * * if (pathfinder != null && pathfinder is IAdvancedPathFinder) * path = (pathfinder as IAdvancedPathFinder).FindPath(Cell, Map.Cells.Where(cell => cell != Cell && (cell.MapChangeData & mapChangeData) != 0 && Map.IsCellWalkable(cell)), true); * else * { * var cells = Map.Cells.Where(x => x != Cell && (x.MapChangeData & mapChangeData) != 0 && Map.IsCellWalkable(x)). * OrderBy(x => x.DistanceTo(Cell)); * * if (pathfinder == null) * pathfinder = new Pathfinder(Map, Map, true, true); * foreach (Cell cell in cells) * if ((path = pathfinder.FindPath(Cell, cell, true)) != null && !path.IsEmpty()) break; * * } * if (path != null && !path.IsEmpty() ) * { * int? neighbourId = null; * if (neighbour == null) * { * foreach (MapNeighbour neighbourFound in Enum.GetValues(typeof(MapNeighbour))) * if ((Map.MapChangeDatas[neighbourFound] & path.End.MapChangeData) > 0) * neighbour = neighbourFound; * } * Debug.Assert(neighbour.HasValue); * if (!neighbour.HasValue) return false; * * neighbourId = GetNeighbourId(neighbour.Value); * * if (Move(path, path.End)) * { * m_nextMap = neighbourId; * return true; * } * return false; * } * * return false; * }*/ private int GetNeighbourId(MapNeighbour neighbour) { switch (neighbour) { case MapNeighbour.Top: return(Map.TopNeighbourId); case MapNeighbour.Bottom: return(Map.BottomNeighbourId); case MapNeighbour.Right: return(Map.RightNeighbourId); case MapNeighbour.Left: return(Map.LeftNeighbourId); default: return(-1); } }
public int?GetNeighbourId(MapNeighbour neighbour) { switch (neighbour) { case MapNeighbour.Right: return(RightNeighbourId); case MapNeighbour.Left: return(LeftNeighbourId); case MapNeighbour.Top: return(TopNeighbourId); case MapNeighbour.Bottom: return(BottomNeighbourId); default: return(null); } }
private MapNeighbour GetOppositeDirection(MapNeighbour neighbour) { switch (neighbour) { case MapNeighbour.Top: return(MapNeighbour.Bottom); case MapNeighbour.Bottom: return(MapNeighbour.Top); case MapNeighbour.Right: return(MapNeighbour.Left); case MapNeighbour.Left: return(MapNeighbour.Right); default: throw new Exception(string.Format("Invalid MapNeighbour {0}", neighbour)); } }
public void Move(MapNeighbour MapNeighbour) { switch (MapNeighbour) { case MapNeighbour.Bottom: Y += 1; break; case MapNeighbour.Top: Y -= 1; break; case MapNeighbour.Left: X -= 1; break; case MapNeighbour.Right: X += 1; break; } }
public virtual bool Teleport(MapNeighbour mapNeighbour) { Map neighbouringMap = this.Position.Map.GetNeighbouringMap(mapNeighbour); bool result; if (neighbouringMap == null) { result = false; } else { short cellAfterChangeMap = this.Position.Map.GetCellAfterChangeMap(this.Position.Cell.Id, mapNeighbour); if (cellAfterChangeMap < 0 || cellAfterChangeMap >= 560) { throw new System.Exception(string.Format("Cell {0} out of range, current={1} neighbour={2}", cellAfterChangeMap, base.Cell.Id, mapNeighbour)); } ObjectPosition destination = new ObjectPosition(neighbouringMap, cellAfterChangeMap, this.Position.Direction); result = this.Teleport(destination, true); } return(result); }
public MapNeighbour ChangeMap(MapNeighbour neighbour = MapNeighbour.Any) { m_nextMap = null; PathFinder pathFinder = new PathFinder(Map, false); // Select a random cell in the set of all reachable cells that allow map change in the right direction. Cell destCell = pathFinder.FindConnectedCells(Cell, false, true, cell => (cell.Cell.MapChangeData & Map.MapChangeDatas[neighbour]) != 0).GetRandom(); if (destCell == null) { return(MapNeighbour.None); } neighbour = Map.GetDirectionOfTransitionCell(destCell); if (neighbour == MapNeighbour.None) { SendMessage(String.Format("Can't find any linked map from {0}", this), Color.Red); return(MapNeighbour.None); } if (destCell.Id != Cell.Id) { if (Move(destCell, pathFinder, 0, true)) { m_nextMap = GetNeighbourId(neighbour); SendMessage(String.Format("Moving at the {2} of map {0} to map {1}", this, m_nextMap, neighbour), Color.Pink); return(neighbour); } else { return(MapNeighbour.None); } } else { Bot.AddMessage(() => Bot.SendToServer(new ChangeMapMessage(GetNeighbourId(neighbour)))); m_previousMap = Map.Id; SendMessage(String.Format("Moving at the {2} of map {0} to map {1} (direct)", this, m_nextMap, neighbour), Color.Pink); } return(neighbour); }
public bool ChangeMap(MapNeighbour neighbour, Predicate <CellInfo> cellSelector) { try { m_nextMap = null; PathFinder pathFinder = new PathFinder(Map, false); // Select a random cell in the set of all reachable cells that allow map change in the right direction. Cell destCell = pathFinder.FindConnectedCells(Cell, false, true, cell => (cell.Cell.MapChangeData & Map.MapChangeDatas[neighbour]) != 0 && cellSelector(cell)).GetRandom(); if (destCell == null) { return(false); } neighbour = Map.GetDirectionOfTransitionCell(destCell); if (neighbour == MapNeighbour.None) { return(false); } if (Move(destCell, pathFinder, 0, true)) { m_nextMap = GetNeighbourId(neighbour); m_previousMap = Map.Id; return(true); } return(false); } finally { if (m_nextMap == null) { SendMessage(String.Format("Can't find any linked map from {0}", this), Color.Red); } else { SendMessage(String.Format("Moving at the {2} of map {0} to map {1}", this, m_nextMap, neighbour), Color.Pink); } } }
public MovementTransition(MapNeighbour neighbour, short[] cells) { MapNeighbour = neighbour; Cells = cells; }
/// <summary> /// Retrieves the transition cells for in given direction within a region /// If subMapId == 0, then considers all non-walkable cells (not set to any subMap). /// </summary> /// <param name="subMapId"></param> /// <returns></returns> public IEnumerable<Cell> GetTransitionCells(byte subMapId, MapNeighbour direction) { int transitionMask = World.Map.MapChangeDatas[direction]; foreach (CellInfo cellinfo in _cells) if (cellinfo.SubMapId == subMapId && (cellinfo.MapLink & transitionMask) != 0) yield return cellinfo.Cell; }
private void InternalChangeMap() { _changingMap = true; if (IsFighting()) { SendWarning("InternalChangeMap : I'm fighting => stop it !"); _changingMap = false; return; } if (_srcLeaderMap != Map.Id) { SendWarning("I'm not on the proper map to follow leader on the next map"); _changingMap = false; return; } if (_pivotLeaderCell != Cell.Id) { PathFinder pathFinder = new PathFinder(Map, false); if (!Move(_pivotLeaderCell, pathFinder, 0, true)) { if (_nbTryLeft > 0) { SendWarning("InternalChangeMap : Can't join the leader yet, try later"); _nbTryLeft--; Bot.CallDelayed(6000, InternalChangeMap); } else if (_nbTryLeft > -6) { MapNeighbour neighbour = Map.GetDirectionOfTransitionCell(Map.Cells[_pivotLeaderCell]); Cell destCell = pathFinder.FindConnectedCells(Cell, false, true, cell => (cell.Cell.MapChangeData & Map.MapChangeDatas[neighbour]) != 0).GetRandom(); if (destCell == null) { SendWarning("InternalChangeMap : Can't join the leader, no try left. Can't even find any alternate path to go {0}", neighbour); } else { SendWarning("InternalChangeMap : Can't join the leader, no try left. Trying alternative path to go {0} : cell {1}", neighbour, destCell); _pivotLeaderCell = destCell.Id; } _nbTryLeft--; Bot.CallDelayed(2000, InternalChangeMap); } else { SendError("InternalChangeMap : Can't find any path to join the leader. Trying again later. "); _changingMap = false; } return; } SendWarning("InternalChangeMap : Move from {0} to {1} succeeded. When move is complete, should go from map {2} to map {3}. ", Cell, Map.Cells[_pivotLeaderCell], Map.ToString(), new Map(_dstLeaderMap)); _changingMap = false; m_nextMap = _dstLeaderMap; return; } SendError("I'm already on the good Cell, just try to jump to the other map."); Bot.CallDelayed(400, () => Bot.AddMessage(() => Bot.SendToServer(new ChangeMapMessage(_dstLeaderMap)))); m_previousMap = Map.Id; _changingMap = false; return; }
public WorldPoint(WorldPoint point, MapNeighbour MapNeighbour) : this(point) { Move(MapNeighbour); }
public WorldPoint GetNeighbourPosition(MapNeighbour MapNeighbour) { return new WorldPoint(this, MapNeighbour); }
// Select a random transition for another map. If set, limit the search in a given MapNeighbour. static public Cell GetClosestTransitionCell(this Map map, MapNeighbour MapNeighbour, Cell startingCell) { int MapChangeMask = GetMapChangeMask(MapNeighbour); return(map.Cells.Where(cell => (cell.MapChangeData & MapChangeMask) != 0).OrderBy(cell => cell.DistanceTo(startingCell)).FirstOrDefault()); }
public int? GetNeighbourId(MapNeighbour neighbour) { switch (neighbour) { case MapNeighbour.Right: return RightNeighbourId; case MapNeighbour.Left: return LeftNeighbourId; case MapNeighbour.Top: return TopNeighbourId; case MapNeighbour.Bottom: return BottomNeighbourId; default: return null; } }
public int GetMapLinkedToCell(Cell cell) { MapNeighbour neighbour = Map.GetDirectionOfTransitionCell(cell); return(GetNeighbourId(neighbour)); }
private void GenerateSubMaps(ProgressionCounter progression) { double total = MapsManager.Instance.MapsCount; progression.UpdateValue(0, "Loading all maps ..."); m_mapsPosition = MapsPositionManager.Instance.EnumerateAllMaps().ToDictionary(x => x.MapId); int counter = 0; Parallel.ForEach(MapsManager.Instance.EnumerateMaps(), map => { var builder = new SubMapBuilder(); AdjacentSubMap[] submaps = builder.GenerateBinders(map); m_submaps.TryAdd(map.Id, submaps); // update the counter (in percent) Interlocked.Increment(ref counter); if (counter % 30 == 0) { lock (progression) { if (counter % 30 == 0) { progression.UpdateValue(total == 0 ? 100d : (counter / total) * 100d); } } } }); progression.UpdateValue(0, "Binding submaps together ..."); counter = 0; Parallel.ForEach(m_submaps, cacheEntry => { var neighbours = new[] { TryGetMapNeighbour(cacheEntry.Key, MapNeighbour.Right), TryGetMapNeighbour(cacheEntry.Key, MapNeighbour.Top), TryGetMapNeighbour(cacheEntry.Key, MapNeighbour.Left), TryGetMapNeighbour(cacheEntry.Key, MapNeighbour.Bottom), }; foreach (AdjacentSubMap submap in cacheEntry.Value) { for (MapNeighbour neighbour = MapNeighbour.Right; neighbour <= MapNeighbour.Bottom; neighbour++) { int i = (int)neighbour - 1; if (neighbours[i] == null) { continue; } MapNeighbour opposite = GetOppositeDirection(neighbour); AdjacentSubMap[] submaps; int mapChangeData = Map.MapChangeDatas[neighbour]; int oppositeMapChangeData = Map.MapChangeDatas[neighbour]; int cellChangement = Map.MapCellChangement[neighbour]; if (neighbours[i] != null && m_submaps.TryGetValue(neighbours[i].Value, out submaps)) { lock (submaps) foreach (AdjacentSubMap neighbourSubmap in submaps) { // neighbor already set lock (submap.SubMap.Neighbours) if (submap.SubMap.Neighbours.Any(x => x.GlobalId == neighbourSubmap.SubMap.GlobalId)) { continue; } // if any cell of the submaps is a transition to another submap AdjacentSubMap submap1 = neighbourSubmap; short[] links = submap.ChangeCells.Where(x => (x.MapChangeData & mapChangeData) != 0 && submap1.ChangeCells.Any(y => y.Id == x.Id + cellChangement)).Select(x => x.Id).ToArray(); if (links.Length > 0) { // set in the two ways lock (submap.SubMap.Neighbours) lock (neighbourSubmap.SubMap.Neighbours) { submap.SubMap.Neighbours.Add(new SubMapNeighbour(neighbourSubmap.SubMap.GlobalId, new MovementTransition(neighbour, links))); neighbourSubmap.SubMap.Neighbours.Add(new SubMapNeighbour(submap.SubMap.GlobalId, new MovementTransition(opposite, links.Select(x => (short)(x + cellChangement)).ToArray()))); } } } } } } // update the counter (in percent) Interlocked.Increment(ref counter); if (counter % 30 == 0) { lock (progression) { if (counter % 30 == 0) { progression.UpdateValue(counter / (double)m_submaps.Count * 100d); } } } }); using (IRedisClient client = m_clientManager.GetClient()) { progression.UpdateValue(0, "Storing informations on Redis server..."); IRedisTypedClient <SubMapBinder> typedClient1 = client.As <SubMapBinder>(); typedClient1.SetRangeInHash(typedClient1.GetHash <long>(REDIS_KEY), m_submaps.Values.SelectMany(x => x).ToDictionary(x => x.SubMap.GlobalId, x => x.SubMap)); progression.UpdateValue(50); IRedisTypedClient <long[]> typedClient2 = client.As <long[]>(); typedClient2.SetRangeInHash(typedClient2.GetHash <int>(REDIS_MAPS), m_submaps.ToDictionary(x => x.Key, x => x.Value.Select(y => y.SubMap.GlobalId).ToArray())); progression.UpdateValue(100); client.Set(REDIS_VERSION, VERSION); } m_submaps.Clear(); m_mapsPosition.Clear(); progression.NotifyEnded(); }
public bool ChangeMap(MapNeighbour neighbour, Predicate<CellInfo> cellSelector) { try { m_nextMap = null; PathFinder pathFinder = new PathFinder(Map, false); // Select a random cell in the set of all reachable cells that allow map change in the right direction. Cell destCell = pathFinder.FindConnectedCells(Cell, false, true, cell => (cell.Cell.MapChangeData & Map.MapChangeDatas[neighbour]) != 0 && cellSelector(cell)).GetRandom(); if (destCell == null) return false; neighbour = Map.GetDirectionOfTransitionCell(destCell); if (neighbour == MapNeighbour.None) return false; if (Move(destCell, pathFinder, 0, true)) { m_nextMap = GetNeighbourId(neighbour); m_previousMap = Map.Id; return true; } return false; } finally { if (m_nextMap == null) SendMessage(String.Format("Can't find any linked map from {0}", this), Color.Red); else SendMessage(String.Format("Moving at the {2} of map {0} to map {1}", this, m_nextMap, neighbour), Color.Pink); } }
public WorldPoint GetNeighbourPosition(MapNeighbour MapNeighbour) { return(new WorldPoint(this, MapNeighbour)); }
public MapNeighbour ChangeMap(MapNeighbour neighbour = MapNeighbour.Any) { m_nextMap = null; PathFinder pathFinder = new PathFinder(Map, false); // Select a random cell in the set of all reachable cells that allow map change in the right direction. Cell destCell = pathFinder.FindConnectedCells(Cell, false, true, cell => (cell.Cell.MapChangeData & Map.MapChangeDatas[neighbour]) != 0).GetRandom(); if (destCell == null) return MapNeighbour.None; neighbour = Map.GetDirectionOfTransitionCell(destCell); if (neighbour == MapNeighbour.None) { SendMessage(String.Format("Can't find any linked map from {0}", this), Color.Red); return MapNeighbour.None; } if (destCell.Id != Cell.Id) { if (Move(destCell, pathFinder, 0, true)) { m_nextMap = GetNeighbourId(neighbour); SendMessage(String.Format("Moving at the {2} of map {0} to map {1}", this, m_nextMap, neighbour), Color.Pink); return neighbour; } else return MapNeighbour.None; } else { Bot.AddMessage(() => Bot.SendToServer(new ChangeMapMessage(GetNeighbourId(neighbour)))); m_previousMap = Map.Id; SendMessage(String.Format("Moving at the {2} of map {0} to map {1} (direct)", this, m_nextMap, neighbour), Color.Pink); } return neighbour; }
public WorldPoint(int mapId, MapNeighbour MapNeighbour) : this(mapId) { Move(MapNeighbour); }
/* public bool ChangeMap(MapNeighbour? neighbour, ISimplePathFinder pathfinder=null) { var mapChangeData = Map.MapChangeDatas[neighbour]; Path path = null; if (pathfinder != null && pathfinder is IAdvancedPathFinder) path = (pathfinder as IAdvancedPathFinder).FindPath(Cell, Map.Cells.Where(cell => cell != Cell && (cell.MapChangeData & mapChangeData) != 0 && Map.IsCellWalkable(cell)), true); else { var cells = Map.Cells.Where(x => x != Cell && (x.MapChangeData & mapChangeData) != 0 && Map.IsCellWalkable(x)). OrderBy(x => x.DistanceTo(Cell)); if (pathfinder == null) pathfinder = new Pathfinder(Map, Map, true, true); foreach (Cell cell in cells) if ((path = pathfinder.FindPath(Cell, cell, true)) != null && !path.IsEmpty()) break; } if (path != null && !path.IsEmpty() ) { int? neighbourId = null; if (neighbour == null) { foreach (MapNeighbour neighbourFound in Enum.GetValues(typeof(MapNeighbour))) if ((Map.MapChangeDatas[neighbourFound] & path.End.MapChangeData) > 0) neighbour = neighbourFound; } Debug.Assert(neighbour.HasValue); if (!neighbour.HasValue) return false; neighbourId = GetNeighbourId(neighbour.Value); if (Move(path, path.End)) { m_nextMap = neighbourId; return true; } return false; } return false; }*/ private int GetNeighbourId(MapNeighbour neighbour) { switch (neighbour) { case MapNeighbour.Top: return Map.TopNeighbourId; case MapNeighbour.Bottom: return Map.BottomNeighbourId; case MapNeighbour.Right: return Map.RightNeighbourId; case MapNeighbour.Left: return Map.LeftNeighbourId; default: return -1; } }