Skip to content

Commit

Permalink
Use MapEntityCollectionHashSet for characters/npcs on map
Browse files Browse the repository at this point in the history
  • Loading branch information
ethanmoffat committed May 12, 2023
1 parent 46bc241 commit 6805bc0
Show file tree
Hide file tree
Showing 42 changed files with 178 additions and 218 deletions.
2 changes: 1 addition & 1 deletion EOBot/Interpreter/BuiltInIdentifierConfigurator.cs
Expand Up @@ -275,7 +275,7 @@ private void Chat(string chatText)
var ms = DependencyMaster.TypeRegistry[_botIndex].Resolve<ICurrentMapStateProvider>();

var mapStateObj = new RuntimeEvaluatedMemberObjectVariable();
mapStateObj.SymbolTable["characters"] = (true, () => new ArrayVariable(ms.Characters.Values.Select(GetMapStateCharacter).ToList()));
mapStateObj.SymbolTable["characters"] = (true, () => new ArrayVariable(ms.Characters.Select(GetMapStateCharacter).ToList()));
mapStateObj.SymbolTable["npcs"] = (true, () => new ArrayVariable(ms.NPCs.Select(GetMapStateNPC).ToList()));
mapStateObj.SymbolTable["items"] = (true, () => new ArrayVariable(ms.MapItems.Select(GetMapStateItem).ToList()));

Expand Down
4 changes: 2 additions & 2 deletions EOLib/Domain/Login/LoginActions.cs
Expand Up @@ -183,8 +183,8 @@ public async Task<CharacterLoginReply> CompleteCharacterLogin(int sessionID)
_characterInventoryRepository.ItemInventory = new HashSet<InventoryItem>(data.CharacterItemInventory);
_characterInventoryRepository.SpellInventory = new HashSet<InventorySpell>(data.CharacterSpellInventory);

_currentMapStateRepository.Characters = data.MapCharacters.Except(new[] { mainCharacter }).ToDictionary(k => k.ID, v => v);
_currentMapStateRepository.NPCs = new HashSet<NPC.NPC>(data.MapNPCs);
_currentMapStateRepository.Characters = new MapEntityCollectionHashSet<Character.Character>(c => c.ID, c => new MapCoordinate(c.X, c.Y), data.MapCharacters.Except(new[] { mainCharacter }));
_currentMapStateRepository.NPCs = new MapEntityCollectionHashSet<NPC.NPC>(n => n.Index, n => new MapCoordinate(n.X, n.Y), data.MapNPCs);
_currentMapStateRepository.MapItems = new MapEntityCollectionHashSet<MapItem>(item => item.UniqueID, item => new MapCoordinate(item.X, item.Y), data.MapItems);

_playerInfoRepository.PlayerIsInGame = true;
Expand Down
20 changes: 10 additions & 10 deletions EOLib/Domain/Map/CurrentMapStateRepository.cs
Expand Up @@ -15,9 +15,9 @@ public interface ICurrentMapStateRepository

bool IsJail { get; }

Dictionary<int, Character.Character> Characters { get; set; }
MapEntityCollectionHashSet<Character.Character> Characters { get; set; }

HashSet<NPC.NPC> NPCs { get; set; }
MapEntityCollectionHashSet<NPC.NPC> NPCs { get; set; }

MapEntityCollectionHashSet<MapItem> MapItems { get; set; }

Expand Down Expand Up @@ -50,9 +50,9 @@ public interface ICurrentMapStateProvider

bool IsJail { get; }

IReadOnlyDictionary<int, Character.Character> Characters { get; }
IReadOnlyMapEntityCollection<Character.Character> Characters { get; }

IReadOnlyCollection<NPC.NPC> NPCs { get; }
IReadOnlyMapEntityCollection<NPC.NPC> NPCs { get; }

IReadOnlyMapEntityCollection<MapItem> MapItems { get; }

Expand Down Expand Up @@ -86,9 +86,9 @@ public class CurrentMapStateRepository : ICurrentMapStateRepository, ICurrentMap

public bool IsJail => JailMapID == CurrentMapID;

public Dictionary<int, Character.Character> Characters { get; set; }
public MapEntityCollectionHashSet<Character.Character> Characters { get; set; }

public HashSet<NPC.NPC> NPCs { get; set; }
public MapEntityCollectionHashSet<NPC.NPC> NPCs { get; set; }

public MapEntityCollectionHashSet<MapItem> MapItems { get; set; }

Expand All @@ -110,9 +110,9 @@ public class CurrentMapStateRepository : ICurrentMapStateRepository, ICurrentMap

public HashSet<int> UnknownNPCIndexes { get; set; }

IReadOnlyDictionary<int, Character.Character> ICurrentMapStateProvider.Characters => Characters;
IReadOnlyMapEntityCollection<Character.Character> ICurrentMapStateProvider.Characters => Characters;

IReadOnlyCollection<NPC.NPC> ICurrentMapStateProvider.NPCs => NPCs;
IReadOnlyMapEntityCollection<NPC.NPC> ICurrentMapStateProvider.NPCs => NPCs;

IReadOnlyMapEntityCollection<MapItem> ICurrentMapStateProvider.MapItems => MapItems;

Expand All @@ -133,8 +133,8 @@ public void ResetState()
ShowMiniMap = false;
JailMapID = 0;

Characters = new Dictionary<int, Character.Character>();
NPCs = new HashSet<NPC.NPC>();
Characters = new MapEntityCollectionHashSet<Character.Character>(x => x.ID, x => new MapCoordinate(x.X, x.Y));
NPCs = new MapEntityCollectionHashSet<NPC.NPC>(x => x.Index, x => new MapCoordinate(x.X, x.Y));
MapItems = new MapEntityCollectionHashSet<MapItem>(x => x.UniqueID, x => new MapCoordinate(x.X, x.Y));
OpenDoors = new HashSet<Warp>();
PendingDoors = new HashSet<Warp>();
Expand Down
29 changes: 9 additions & 20 deletions EOLib/Domain/Map/MapCellStateProvider.cs
Expand Up @@ -39,11 +39,14 @@ public IMapCellState GetCellStateAt(int x, int y)
var chest = CurrentMap.Chests.Where(c => c.X == x && c.Y == y && c.Key != ChestKey.None).Select(c => c.Key).FirstOrDefault();
var sign = CurrentMap.Signs.FirstOrDefault(s => s.X == x && s.Y == y);

var characters = _mapStateProvider.Characters.Values
.Concat(new[] { _characterProvider.MainCharacter })
.Where(c => CharacterAtCoordinates(c, x, y))
.ToList();
var npc = _mapStateProvider.NPCs.FirstOrNone(n => NPCAtCoordinates(n, x, y));
_mapStateProvider.Characters.TryGetValues(new MapCoordinate(x, y), out var characters);
if (_characterProvider.MainCharacter.X == x && _characterProvider.MainCharacter.Y == y)
characters.Add(_characterProvider.MainCharacter);

Option<NPC.NPC> npc = Option.None<NPC.NPC>();
if (_mapStateProvider.NPCs.TryGetValues(new MapCoordinate(x, y), out var npcs))
npc = npcs.FirstOrNone();

var items = _mapStateProvider.MapItems.TryGetValues(new MapCoordinate(x, y), out var mapItems)
? mapItems.OrderByDescending(i => i.UniqueID)
: Enumerable.Empty<MapItem>();
Expand All @@ -58,25 +61,11 @@ public IMapCellState GetCellStateAt(int x, int y)
ChestKey = chest.SomeNotNull(),
Sign = sign.SomeNotNull().Map(s => new Sign(s)),
Character = characters.FirstOrNone(),
Characters = characters,
Characters = characters.ToList(),
NPC = npc
};
}

private static bool CharacterAtCoordinates(Character.Character character, int x, int y)
{
return character.RenderProperties.IsActing(CharacterActionState.Walking)
? character.RenderProperties.GetDestinationX() == x && character.RenderProperties.GetDestinationY() == y
: character.RenderProperties.MapX == x && character.RenderProperties.MapY == y;
}

private static bool NPCAtCoordinates(NPC.NPC npc, int x, int y)
{
return npc.IsActing(NPCActionState.Walking)
? npc.GetDestinationX() == x && npc.GetDestinationY() == y
: npc.X == x && npc.Y == y;
}

private IMapFile CurrentMap => _mapFileProvider.MapFiles[_mapStateProvider.CurrentMapID];
}

Expand Down
23 changes: 18 additions & 5 deletions EOLib/Domain/Map/MapEntityCollectionHashSet.cs
Expand Up @@ -56,9 +56,11 @@ public void Add(TValue value)
_valueSet[hash] = value;
}

public IEnumerator<TValue> GetEnumerator() => _valueSet.Values.GetEnumerator();

IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public void Update(TValue oldValue, TValue newValue)
{
Remove(oldValue);
Add(newValue);
}

public void Remove(TValue value)
{
Expand All @@ -74,6 +76,10 @@ public void Remove(TValue value)
_valueSet.Remove(hash);
}

public bool ContainsKey(int uniqueId) => _uniqueIdToHash.ContainsKey(uniqueId);

public bool ContainsKey(MapCoordinate coordinate) => _mapCoordinateToHashList.ContainsKey(coordinate);

public bool TryGetValue(int uniqueId, out TValue value)
{
value = default;
Expand All @@ -92,7 +98,7 @@ public bool TryGetValue(int uniqueId, out TValue value)

public bool TryGetValues(MapCoordinate mapCoordinate, out HashSet<TValue> values)
{
values = default;
values = new HashSet<TValue>();

if (!_mapCoordinateToHashList.ContainsKey(mapCoordinate))
return false;
Expand All @@ -101,17 +107,24 @@ public bool TryGetValues(MapCoordinate mapCoordinate, out HashSet<TValue> values
if (!_valueSet.Any(x => hashes.Contains(x.Key)))
return false;

values = new HashSet<TValue>(_mapCoordinateToHashList[mapCoordinate].Select(x => _valueSet[x]));
values = this[mapCoordinate];

return true;
}

public IEnumerator<TValue> GetEnumerator() => _valueSet.Values.GetEnumerator();

IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}

public interface IReadOnlyMapEntityCollection<TValue> : IEnumerable<TValue>
{
TValue this[int key1] { get; }
HashSet<TValue> this[MapCoordinate key2] { get; }

bool ContainsKey(int characterID);
bool ContainsKey(MapCoordinate mapCoordinate);

bool TryGetValue(int key1, out TValue value);
bool TryGetValues(MapCoordinate key2, out HashSet<TValue> values);
}
Expand Down
6 changes: 2 additions & 4 deletions EOLib/PacketHandlers/AdminInteract/AdminInteractAgree.cs
Expand Up @@ -36,12 +36,10 @@ public override bool HandlePacket(IPacket packet)
_characterRepository.MainCharacter = Shown(_characterRepository.MainCharacter);
else
{
if (_currentMapStateRepository.Characters.ContainsKey(id))
if (_currentMapStateRepository.Characters.TryGetValue(id, out var character))
{
var character = _currentMapStateRepository.Characters[id];

var updatedCharacter = Shown(character);
_currentMapStateRepository.Characters[id] = updatedCharacter;
_currentMapStateRepository.Characters.Update(character, updatedCharacter);
}
else
{
Expand Down
6 changes: 2 additions & 4 deletions EOLib/PacketHandlers/AdminInteract/AdminInteractRemove.cs
Expand Up @@ -36,12 +36,10 @@ public override bool HandlePacket(IPacket packet)
_characterRepository.MainCharacter = Hidden(_characterRepository.MainCharacter);
else
{
if (_currentMapStateRepository.Characters.ContainsKey(id))
if (_currentMapStateRepository.Characters.TryGetValue(id, out var character))
{
var character = _currentMapStateRepository.Characters[id];

var updatedCharacter = Hidden(character);
_currentMapStateRepository.Characters[id] = updatedCharacter;
_currentMapStateRepository.Characters.Update(character, updatedCharacter);
}
else
{
Expand Down
5 changes: 2 additions & 3 deletions EOLib/PacketHandlers/Attack/AttackPlayerHandler.cs
Expand Up @@ -35,13 +35,12 @@ public override bool HandlePacket(IPacket packet)
var playerID = packet.ReadShort();
var direction = (EODirection)packet.ReadChar();

if (_currentMapStateRepository.Characters.ContainsKey(playerID))
if (_currentMapStateRepository.Characters.TryGetValue(playerID, out var character))
{
var character = _currentMapStateRepository.Characters[playerID];
if (character.RenderProperties.Direction != direction)
{
var renderProperties = character.RenderProperties.WithDirection(direction);
_currentMapStateRepository.Characters[playerID] = character.WithRenderProperties(renderProperties);
_currentMapStateRepository.Characters.Update(character, character.WithRenderProperties(renderProperties));
}

foreach (var notifier in _otherCharacterAnimationNotifiers)
Expand Down
17 changes: 7 additions & 10 deletions EOLib/PacketHandlers/Avatar/AvatarAdminHandler.cs
Expand Up @@ -49,11 +49,10 @@ public override bool HandlePacket(IPacket packet)
var renderProps = _characterRepository.MainCharacter.RenderProperties.WithDirection(sourcePlayerDirection);
_characterRepository.MainCharacter = _characterRepository.MainCharacter.WithRenderProperties(renderProps);
}
else if (_currentMapStateRepository.Characters.ContainsKey(sourcePlayerId))
else if (_currentMapStateRepository.Characters.TryGetValue(sourcePlayerId, out var sourceCharacter))
{
var character = _currentMapStateRepository.Characters[sourcePlayerId];
var updatedCharacter = character.WithRenderProperties(character.RenderProperties.WithDirection(sourcePlayerDirection));
_currentMapStateRepository.Characters[sourcePlayerId] = updatedCharacter;
var updatedCharacter = sourceCharacter.WithRenderProperties(sourceCharacter.RenderProperties.WithDirection(sourcePlayerDirection));
_currentMapStateRepository.Characters.Update(sourceCharacter, updatedCharacter);
}
else
{
Expand All @@ -72,16 +71,14 @@ public override bool HandlePacket(IPacket packet)
.WithStats(stats)
.WithRenderProperties(renderProps);
}
else if (_currentMapStateRepository.Characters.ContainsKey(targetPlayerId))
else if (_currentMapStateRepository.Characters.TryGetValue(targetPlayerId, out var targetCharacter))
{
var c = _currentMapStateRepository.Characters[targetPlayerId];
var renderProps = targetCharacter.RenderProperties.WithIsDead(targetIsDead);

var renderProps = c.RenderProperties.WithIsDead(targetIsDead);

var stats = c.Stats;
var stats = targetCharacter.Stats;
stats = stats.WithNewStat(CharacterStat.HP, stats[CharacterStat.HP] - damage);

_currentMapStateRepository.Characters[targetPlayerId] = c.WithStats(stats).WithRenderProperties(renderProps);
_currentMapStateRepository.Characters.Update(targetCharacter, targetCharacter.WithStats(stats).WithRenderProperties(renderProps));
}
else
{
Expand Down
8 changes: 2 additions & 6 deletions EOLib/PacketHandlers/Avatar/AvatarAgreeHandler.cs
Expand Up @@ -43,11 +43,7 @@ public override bool HandlePacket(IPacket packet)
{
currentCharacter = _characterRepository.MainCharacter;
}
else if (_currentMapStateRepository.Characters.ContainsKey(playerID))
{
currentCharacter = _currentMapStateRepository.Characters[playerID];
}
else
else if (!_currentMapStateRepository.Characters.TryGetValue(playerID, out currentCharacter))
{
_currentMapStateRepository.UnknownPlayerIDs.Add(playerID);
return true;
Expand Down Expand Up @@ -106,7 +102,7 @@ public override bool HandlePacket(IPacket packet)
}
else
{
_currentMapStateRepository.Characters[playerID] = updatedCharacter;
_currentMapStateRepository.Characters.Update(currentCharacter, updatedCharacter);
}

return true;
Expand Down
5 changes: 2 additions & 3 deletions EOLib/PacketHandlers/Avatar/AvatarRemoveHandler.cs
Expand Up @@ -51,10 +51,9 @@ public override bool HandlePacket(IPacket packet)
_characterRepository.HasAvatar = false;
_currentMapStateRepository.VisibleSpikeTraps.Remove(_characterRepository.MainCharacter.RenderProperties.Coordinates());
}
else if (_currentMapStateRepository.Characters.ContainsKey(id))
else if (_currentMapStateRepository.Characters.TryGetValue(id, out var character))
{
var character = _currentMapStateRepository.Characters[id];
_currentMapStateRepository.Characters.Remove(id);
_currentMapStateRepository.Characters.Remove(character);
_currentMapStateRepository.VisibleSpikeTraps.Remove(character.RenderProperties.Coordinates());
}
else
Expand Down
4 changes: 2 additions & 2 deletions EOLib/PacketHandlers/Chat/PlayerChatByIDHandler.cs
Expand Up @@ -22,10 +22,10 @@ public abstract class PlayerChatByIDHandler : InGameOnlyPacketHandler
public override bool HandlePacket(IPacket packet)
{
var fromPlayerID = packet.ReadShort();
if (!_currentMapStateProvider.Characters.ContainsKey(fromPlayerID))
if (!_currentMapStateProvider.Characters.TryGetValue(fromPlayerID, out var character))
return false;

DoTalk(packet, _currentMapStateProvider.Characters[fromPlayerID]);
DoTalk(packet, character);

return true;
}
Expand Down
6 changes: 3 additions & 3 deletions EOLib/PacketHandlers/Effects/PlayerSpikeDamageHandler.cs
Expand Up @@ -35,10 +35,10 @@ public override bool HandlePacket(IPacket packet)
var isDead = packet.ReadChar() != 0;
var damageTaken = packet.ReadThree();

if (_currentMapStateRepository.Characters.ContainsKey(characterId))
if (_currentMapStateRepository.Characters.TryGetValue(characterId, out var character))
{
var updatedCharacter = _currentMapStateRepository.Characters[characterId].WithDamage(damageTaken, isDead);
_currentMapStateRepository.Characters[characterId] = updatedCharacter;
var updatedCharacter = character.WithDamage(damageTaken, isDead);
_currentMapStateRepository.Characters.Update(character, updatedCharacter);

foreach (var notifier in _otherCharacterEventNotifiers)
{
Expand Down
7 changes: 5 additions & 2 deletions EOLib/PacketHandlers/Face/FacePlayerHandler.cs
Expand Up @@ -31,14 +31,17 @@ public override bool HandlePacket(IPacket packet)
var direction = (EODirection)packet.ReadChar();

if (!_mapStateRepository.Characters.ContainsKey(id))
return false;
{
_mapStateRepository.UnknownPlayerIDs.Add(id);
return true;
}

var character = _mapStateRepository.Characters[id];

var newRenderProps = character.RenderProperties.WithDirection(direction);
var newCharacter = character.WithRenderProperties(newRenderProps);

_mapStateRepository.Characters[id] = newCharacter;
_mapStateRepository.Characters.Update(character, newCharacter);

return true;
}
Expand Down
3 changes: 2 additions & 1 deletion EOLib/PacketHandlers/Items/ItemGetHandler.cs
Expand Up @@ -58,7 +58,8 @@ public override bool HandlePacket(IPacket packet)
.WithNewStat(CharacterStat.MaxWeight, maxWeight);
_characterRepository.MainCharacter = _characterRepository.MainCharacter.WithStats(newStats);

_mapStateRepository.MapItems.Remove(_mapStateRepository.MapItems[uid]);
if (_mapStateRepository.MapItems.ContainsKey(uid))
_mapStateRepository.MapItems.Remove(_mapStateRepository.MapItems[uid]);

foreach (var notifier in _mainCharacterEventNotifiers)
{
Expand Down
10 changes: 4 additions & 6 deletions EOLib/PacketHandlers/Jukebox/JukeboxMessageHandler.cs
Expand Up @@ -34,14 +34,12 @@ public override bool HandlePacket(IPacket packet)
var instrument = packet.ReadChar();
var note = packet.ReadChar();

if (_currentMapStateRepository.Characters.ContainsKey(playerId))
if (_currentMapStateRepository.Characters.TryGetValue(playerId, out var character))
{
var c = _currentMapStateRepository.Characters[playerId];

if (c.RenderProperties.WeaponGraphic == instrument)
if (character.RenderProperties.WeaponGraphic == instrument)
{
c = c.WithRenderProperties(c.RenderProperties.WithDirection(direction));
_currentMapStateRepository.Characters[playerId] = c;
var updatedCharacter = character.WithRenderProperties(character.RenderProperties.WithDirection(direction));
_currentMapStateRepository.Characters.Update(character, updatedCharacter);

foreach (var notifier in _otherCharacterAnimationNotifiers)
notifier.StartOtherCharacterAttackAnimation(playerId, note - 1);
Expand Down

0 comments on commit 6805bc0

Please sign in to comment.