From c0cae8cf01a9784ac2b07ad5cafc7dacd97b52c1 Mon Sep 17 00:00:00 2001 From: Anton Pupkov Date: Mon, 15 Jan 2024 15:46:53 -0800 Subject: [PATCH 01/24] Implement Equals and GetHashCode for nodes --- Dota2GSI/GameState.cs | 285 ++++-------------- Dota2GSI/Nodes/Abilities.cs | 26 +- Dota2GSI/Nodes/AbilitiesProvider/Ability.cs | 38 +++ .../Nodes/AbilitiesProvider/AbilityDetails.cs | 22 +- Dota2GSI/Nodes/Auth.cs | 20 ++ Dota2GSI/Nodes/Buildings.cs | 23 +- Dota2GSI/Nodes/BuildingsProvider/Building.cs | 22 ++ .../Nodes/BuildingsProvider/BuildingLayout.cs | 49 ++- Dota2GSI/Nodes/Couriers.cs | 23 +- Dota2GSI/Nodes/CouriersProvider/Courier.cs | 43 ++- .../Nodes/CouriersProvider/CourierItem.cs | 22 ++ Dota2GSI/Nodes/Draft.cs | 33 +- Dota2GSI/Nodes/DraftProvider/DraftDetails.cs | 29 +- Dota2GSI/Nodes/Events.cs | 32 +- Dota2GSI/Nodes/EventsProvider/Event.cs | 38 +++ Dota2GSI/Nodes/Helpers/FullPlayerDetails.cs | 35 ++- Dota2GSI/Nodes/Helpers/FullTeamDetails.cs | 43 ++- Dota2GSI/Nodes/Helpers/Vector2D.cs | 11 +- Dota2GSI/Nodes/Hero.cs | 31 +- Dota2GSI/Nodes/HeroProvider/HeroDetails.cs | 212 +++++++++---- Dota2GSI/Nodes/Items.cs | 31 +- Dota2GSI/Nodes/ItemsProvider/Item.cs | 42 +++ Dota2GSI/Nodes/ItemsProvider/ItemDetails.cs | 31 +- Dota2GSI/Nodes/League.cs | 75 ++++- Dota2GSI/Nodes/LeagueProvider/LeagueTeam.cs | 26 ++ .../Nodes/LeagueProvider/SelectionPriority.cs | 30 ++ Dota2GSI/Nodes/LeagueProvider/Stream.cs | 30 ++ Dota2GSI/Nodes/Map.cs | 52 ++++ Dota2GSI/Nodes/Minimap.cs | 31 +- .../Nodes/MinimapProvider/MinimapElement.cs | 36 +++ Dota2GSI/Nodes/NeutralItems.cs | 27 +- .../Nodes/NeutralItemsProvider/NeutralItem.cs | 28 ++ .../NeutralItemsProvider/NeutralTierInfo.cs | 24 ++ .../NeutralItemsProvider/TeamNeutralItems.cs | 27 +- Dota2GSI/Nodes/Node.cs | 154 ++++++++++ Dota2GSI/Nodes/Player.cs | 31 +- .../Nodes/PlayerProvider/PlayerDetails.cs | 99 +++++- Dota2GSI/Nodes/Provider.cs | 26 ++ Dota2GSI/Nodes/Roshan.cs | 34 +++ Dota2GSI/Nodes/RoshanProvider/ItemsDrop.cs | 23 +- Dota2GSI/Nodes/Wearables.cs | 31 +- .../WearablesProvider/PlayerWearables.cs | 23 +- .../Nodes/WearablesProvider/WearableItem.cs | 22 ++ 43 files changed, 1598 insertions(+), 372 deletions(-) diff --git a/Dota2GSI/GameState.cs b/Dota2GSI/GameState.cs index c787fca..f4fa32b 100644 --- a/Dota2GSI/GameState.cs +++ b/Dota2GSI/GameState.cs @@ -1,4 +1,4 @@ -using Dota2GSI.Nodes; +using Dota2GSI.Nodes; using Dota2GSI.Nodes.Helpers; using Newtonsoft.Json.Linq; @@ -9,312 +9,101 @@ namespace Dota2GSI /// public class GameState : Node { - private Auth auth; - private Provider provider; - private Map map; - private Player player; - private Hero hero; - private Abilities abilities; - private Items items; - private Events events; - private Buildings buildings; - private League league; - private Draft draft; - private Wearables wearables; - private Minimap minimap; - private Roshan roshan; - private Couriers couriers; - private NeutralItems neutral_items; - private GameState previously; - // private GameState added; // Added is removed due to only returning bool values instead of proper values. - - // Helpers - - private FullPlayerDetails local_player_details; - private FullTeamDetails radiant_team_details; - private FullTeamDetails dire_team_details; - private FullTeamDetails neutral_team_details; - - - /// - /// Creates a GameState instance based on the given json data. - /// - /// The parsed json data. - public GameState(JObject parsed_data = null) : base(parsed_data) - { - } - /// /// Information about GSI authentication.
/// Enabled by including "auth" "1" in the game state cfg file. ///
- public Auth Auth - { - get - { - if (auth == null) - { - auth = new Auth(GetJObject("auth")); - } - - return auth; - } - } + public readonly Auth Auth; /// /// Information about the provider of this GameState.
/// Enabled by including "provider" "1" in the game state cfg file. ///
- public Provider Provider - { - get - { - if (provider == null) - { - provider = new Provider(GetJObject("provider")); - } - - return provider; - } - } + public readonly Provider Provider; /// /// Information about the current map.
/// Enabled by including "map" "1" in the game state cfg file. ///
- public Map Map - { - get - { - if (map == null) - { - map = new Map(GetJObject("map")); - } - - return map; - } - } + public readonly Map Map; /// /// Information about the local player or team players when spectating.
/// Enabled by including "player" "1" in the game state cfg file. ///
- public Player Player - { - get - { - if (player == null) - { - player = new Player(GetJObject("player")); - } - - return player; - } - } + public readonly Player Player; /// /// Information about the local player's hero or team players heroes when spectating.
/// Enabled by including "hero" "1" in the game state cfg file. ///
- public Hero Hero - { - get - { - if (hero == null) - { - hero = new Hero(GetJObject("hero")); - } - - return hero; - } - } + public readonly Hero Hero; /// /// Information about the local player's hero abilities or team players abilities when spectating.
/// Enabled by including "abilities" "1" in the game state cfg file. ///
- public Abilities Abilities - { - get - { - if (abilities == null) - { - abilities = new Abilities(GetJObject("abilities")); - } - - return abilities; - } - } + public readonly Abilities Abilities; /// /// Information about the local player's hero items or team players items when spectating.
/// Enabled by including "items" "1" in the game state cfg file. ///
- public Items Items - { - get - { - if (items == null) - { - items = new Items(GetJObject("items")); - } - - return items; - } - } + public readonly Items Items; /// /// Information about game events.
/// Enabled by including "events" "1" in the game state cfg file. ///
- public Events Events - { - get - { - if (events == null) - { - events = new Events(GetJArray("events")); - } - - return events; - } - } + public readonly Events Events; /// /// Information about the buildings on the map.
/// Enabled by including "buildings" "1" in the game state cfg file. ///
- public Buildings Buildings - { - get - { - if (buildings == null) - { - buildings = new Buildings(GetJObject("buildings")); - } - - return buildings; - } - } + public readonly Buildings Buildings; /// /// Information about the current league (or game configuration).
/// Enabled by including "league" "1" in the game state cfg file. ///
- public League League - { - get - { - if (league == null) - { - league = new League(GetJObject("league")); - } - - return league; - } - } + public readonly League League; /// /// Information about the draft. (TOURNAMENT ONLY)
/// Enabled by including "draft" "1" in the game state cfg file. ///
- public Draft Draft - { - get - { - if (draft == null) - { - draft = new Draft(GetJObject("draft")); - } - - return draft; - } - } + public readonly Draft Draft; /// /// Information about the local player's wearable items or team players wearable items when spectating.
/// Enabled by including "wearables" "1" in the game state cfg file. ///
- public Wearables Wearables - { - get - { - if (wearables == null) - { - wearables = new Wearables(GetJObject("wearables")); - } - - return wearables; - } - } + public readonly Wearables Wearables; /// /// Information about the minimap.
/// Enabled by including "minimap" "1" in the game state cfg file. ///
- public Minimap Minimap - { - get - { - if (minimap == null) - { - minimap = new Minimap(GetJObject("minimap")); - } - - return minimap; - } - } + public readonly Minimap Minimap; /// /// Information about Roshan. (SPECTATOR ONLY)
/// Enabled by including "roshan" "1" in the game state cfg file. ///
- public Roshan Roshan - { - get - { - if (roshan == null) - { - roshan = new Roshan(GetJObject("roshan")); - } - - return roshan; - } - } + public readonly Roshan Roshan; /// /// Information about couriers. (SPECTATOR ONLY)
/// Enabled by including "couriers" "1" in the game state cfg file. ///
- public Couriers Couriers - { - get - { - if (couriers == null) - { - couriers = new Couriers(GetJObject("couriers")); - } - - return couriers; - } - } + public readonly Couriers Couriers; /// /// Information about neutral items. (SPECTATOR ONLY)
/// Enabled by including "neutralitems" "1" in the game state cfg file. ///
- public NeutralItems NeutralItems - { - get - { - if (neutral_items == null) - { - neutral_items = new NeutralItems(GetJObject("neutralitems")); - } - - return neutral_items; - } - } + public readonly NeutralItems NeutralItems; /// /// A previous GameState. @@ -323,12 +112,12 @@ public GameState Previously { get { - if (previously == null) + if (_previous_game_state == null) { - previously = new GameState(GetJObject("previously")); + _previous_game_state = new GameState(GetJObject("previously")); } - return previously; + return _previous_game_state; } } @@ -425,5 +214,39 @@ public bool IsLocalPlayer return Player.IsValid() && Player.LocalPlayer.IsValid() && (Player.Teams.Count == 0); } } + + private GameState _previous_game_state; + + // Helpers + + private FullPlayerDetails local_player_details; + private FullTeamDetails radiant_team_details; + private FullTeamDetails dire_team_details; + private FullTeamDetails neutral_team_details; + + + /// + /// Creates a GameState instance based on the given json data. + /// + /// The parsed json data. + public GameState(JObject parsed_data = null) : base(parsed_data) + { + Auth = new Auth(GetJObject("auth")); + Provider = new Provider(GetJObject("provider")); + Map = new Map(GetJObject("map")); + Player = new Player(GetJObject("player")); + Hero = new Hero(GetJObject("hero")); + Abilities = new Abilities(GetJObject("abilities")); + Items = new Items(GetJObject("items")); + Events = new Events(GetJArray("events")); + Buildings = new Buildings(GetJObject("buildings")); + League = new League(GetJObject("league")); + Draft = new Draft(GetJObject("draft")); + Wearables = new Wearables(GetJObject("wearables")); + Minimap = new Minimap(GetJObject("minimap")); + Roshan = new Roshan(GetJObject("roshan")); + Couriers = new Couriers(GetJObject("couriers")); + NeutralItems = new NeutralItems(GetJObject("neutralitems")); + } } } diff --git a/Dota2GSI/Nodes/Abilities.cs b/Dota2GSI/Nodes/Abilities.cs index a9c5246..a7088d2 100644 --- a/Dota2GSI/Nodes/Abilities.cs +++ b/Dota2GSI/Nodes/Abilities.cs @@ -19,7 +19,7 @@ public class Abilities : Node /// /// The team players ability details. (SPECTATOR ONLY) /// - public readonly Dictionary> Teams = new Dictionary>(); + public readonly NodeMap> Teams = new NodeMap>(); private Regex _team_id_regex = new Regex(@"team(\d+)"); private Regex _player_id_regex = new Regex(@"player(\d+)"); @@ -36,7 +36,7 @@ internal Abilities(JObject parsed_data = null) : base(parsed_data) if (!Teams.ContainsKey(team_id)) { - Teams.Add(team_id, new Dictionary()); + Teams.Add(team_id, new NodeMap()); } GetMatchingObjects(obj, _player_id_regex, (Match sub_match, JObject sub_obj) => @@ -106,5 +106,27 @@ public override bool IsValid() { return LocalPlayer.IsValid() || base.IsValid(); } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is Abilities other && + LocalPlayer.Equals(other.LocalPlayer) && + Teams.Equals(other.Teams); + } + + /// + public override int GetHashCode() + { + int hashCode = 145729690; + hashCode = hashCode * -516479333 + LocalPlayer.GetHashCode(); + hashCode = hashCode * -516479333 + Teams.GetHashCode(); + return hashCode; + } } } diff --git a/Dota2GSI/Nodes/AbilitiesProvider/Ability.cs b/Dota2GSI/Nodes/AbilitiesProvider/Ability.cs index dac064a..b61263b 100644 --- a/Dota2GSI/Nodes/AbilitiesProvider/Ability.cs +++ b/Dota2GSI/Nodes/AbilitiesProvider/Ability.cs @@ -87,5 +87,43 @@ public override string ToString() $"ChargeCooldown: {ChargeCooldown}" + $"]"; } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is Ability other && + Name.Equals(other.Name) && + Level == other.Level && + CanCast == other.CanCast && + IsPassive == other.IsPassive && + IsActive == other.IsActive && + Cooldown == other.Cooldown && + IsUltimate == other.IsUltimate && + Charges == other.Charges && + MaxCharges == other.MaxCharges && + ChargeCooldown == other.ChargeCooldown; + } + + /// + public override int GetHashCode() + { + int hashCode = 634642291; + hashCode = hashCode * -84013849 + Name.GetHashCode(); + hashCode = hashCode * -84013849 + Level.GetHashCode(); + hashCode = hashCode * -84013849 + CanCast.GetHashCode(); + hashCode = hashCode * -84013849 + IsPassive.GetHashCode(); + hashCode = hashCode * -84013849 + IsActive.GetHashCode(); + hashCode = hashCode * -84013849 + Cooldown.GetHashCode(); + hashCode = hashCode * -84013849 + IsUltimate.GetHashCode(); + hashCode = hashCode * -84013849 + Charges.GetHashCode(); + hashCode = hashCode * -84013849 + MaxCharges.GetHashCode(); + hashCode = hashCode * -84013849 + ChargeCooldown.GetHashCode(); + return hashCode; + } } } diff --git a/Dota2GSI/Nodes/AbilitiesProvider/AbilityDetails.cs b/Dota2GSI/Nodes/AbilitiesProvider/AbilityDetails.cs index 9f2cf1c..a6d886c 100644 --- a/Dota2GSI/Nodes/AbilitiesProvider/AbilityDetails.cs +++ b/Dota2GSI/Nodes/AbilitiesProvider/AbilityDetails.cs @@ -10,7 +10,7 @@ namespace Dota2GSI.Nodes.AbilitiesProvider /// public class AbilityDetails : Node, IEnumerable { - private List _abilities = new List(); + private NodeList _abilities = new NodeList(); /// /// The number of abilities. @@ -65,5 +65,25 @@ public override string ToString() $"Abilities: {_abilities}" + $"]"; } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is AbilityDetails other && + _abilities.Equals(other._abilities); + } + + /// + public override int GetHashCode() + { + int hashCode = 356743140; + hashCode = hashCode * -394407688 + _abilities.GetHashCode(); + return hashCode; + } } } diff --git a/Dota2GSI/Nodes/Auth.cs b/Dota2GSI/Nodes/Auth.cs index df07184..83e8379 100644 --- a/Dota2GSI/Nodes/Auth.cs +++ b/Dota2GSI/Nodes/Auth.cs @@ -24,5 +24,25 @@ public override string ToString() $"Token: {Token}" + $"]"; } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is Auth other && + Token.Equals(other.Token); + } + + /// + public override int GetHashCode() + { + int hashCode = 930327133; + hashCode = hashCode * -487188821 + Token.GetHashCode(); + return hashCode; + } } } diff --git a/Dota2GSI/Nodes/Buildings.cs b/Dota2GSI/Nodes/Buildings.cs index 44c1551..f5d051d 100644 --- a/Dota2GSI/Nodes/Buildings.cs +++ b/Dota2GSI/Nodes/Buildings.cs @@ -1,6 +1,5 @@ using Dota2GSI.Nodes.BuildingsProvider; using Newtonsoft.Json.Linq; -using System.Collections.Generic; namespace Dota2GSI.Nodes { @@ -12,7 +11,7 @@ public class Buildings : Node /// /// Gets all buildings layouts. /// - public readonly Dictionary AllBuildings = new Dictionary(); + public readonly NodeMap AllBuildings = new NodeMap(); /// /// Gets Radiant buildings layout. @@ -69,5 +68,25 @@ public override string ToString() $"AllBuildings: {AllBuildings}" + $"]"; } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is Buildings other && + AllBuildings.Equals(other.AllBuildings); + } + + /// + public override int GetHashCode() + { + int hashCode = 107254384; + hashCode = hashCode * -739411027 + AllBuildings.GetHashCode(); + return hashCode; + } } } diff --git a/Dota2GSI/Nodes/BuildingsProvider/Building.cs b/Dota2GSI/Nodes/BuildingsProvider/Building.cs index 5b87baf..1a49b59 100644 --- a/Dota2GSI/Nodes/BuildingsProvider/Building.cs +++ b/Dota2GSI/Nodes/BuildingsProvider/Building.cs @@ -30,6 +30,28 @@ public override string ToString() $"Health: {Health}, " + $"MaxHealth: {MaxHealth}" + $"]"; + } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is Building other && + Health == other.Health && + MaxHealth == other.MaxHealth; + } + + /// + public override int GetHashCode() + { + int hashCode = 815636796; + hashCode = hashCode * -192822430 + Health.GetHashCode(); + hashCode = hashCode * -192822430 + MaxHealth.GetHashCode(); + return hashCode; } } } diff --git a/Dota2GSI/Nodes/BuildingsProvider/BuildingLayout.cs b/Dota2GSI/Nodes/BuildingsProvider/BuildingLayout.cs index 517ebd4..3be87fe 100644 --- a/Dota2GSI/Nodes/BuildingsProvider/BuildingLayout.cs +++ b/Dota2GSI/Nodes/BuildingsProvider/BuildingLayout.cs @@ -1,6 +1,5 @@ using Newtonsoft.Json.Linq; using System; -using System.Collections.Generic; using System.Text.RegularExpressions; namespace Dota2GSI.Nodes.BuildingsProvider @@ -34,32 +33,32 @@ public class BuildingLayout /// /// Top towers. /// - public readonly Dictionary TopTowers = new Dictionary(); + public readonly NodeMap TopTowers = new NodeMap(); /// /// Middle towers. /// - public readonly Dictionary MiddleTowers = new Dictionary(); + public readonly NodeMap MiddleTowers = new NodeMap(); /// /// Bottom towers. /// - public readonly Dictionary BottomTowers = new Dictionary(); + public readonly NodeMap BottomTowers = new NodeMap(); /// /// Top racks. /// - public readonly Dictionary TopRacks = new Dictionary(); + public readonly NodeMap TopRacks = new NodeMap(); /// /// Middle racks. /// - public readonly Dictionary MiddleRacks = new Dictionary(); + public readonly NodeMap MiddleRacks = new NodeMap(); /// /// Bottom racks. /// - public readonly Dictionary BottomRacks = new Dictionary(); + public readonly NodeMap BottomRacks = new NodeMap(); /// /// Ancient. @@ -69,7 +68,7 @@ public class BuildingLayout /// /// Other buildings. /// - public readonly Dictionary OtherBuildings = new Dictionary(); + public readonly NodeMap OtherBuildings = new NodeMap(); private Regex _tower_regex = new Regex(@"tower(\d+)_(top|mid|bot)"); private Regex _racks_regex = new Regex(@"rax_(melee|range)_(top|mid|bot)"); @@ -162,5 +161,39 @@ public override string ToString() $"OtherBuildings: {OtherBuildings}" + $"]"; } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is BuildingLayout other && + TopTowers.Equals(other.TopTowers) && + MiddleTowers.Equals(other.MiddleTowers) && + BottomTowers.Equals(other.BottomTowers) && + TopRacks.Equals(other.TopRacks) && + MiddleRacks.Equals(other.MiddleRacks) && + BottomRacks.Equals(other.BottomRacks) && + Ancient.Equals(other.Ancient) && + OtherBuildings.Equals(other.OtherBuildings); + } + + /// + public override int GetHashCode() + { + int hashCode = 946659162; + hashCode = hashCode * -439837856 + TopTowers.GetHashCode(); + hashCode = hashCode * -439837856 + MiddleTowers.GetHashCode(); + hashCode = hashCode * -439837856 + BottomTowers.GetHashCode(); + hashCode = hashCode * -439837856 + TopRacks.GetHashCode(); + hashCode = hashCode * -439837856 + MiddleRacks.GetHashCode(); + hashCode = hashCode * -439837856 + BottomRacks.GetHashCode(); + hashCode = hashCode * -439837856 + Ancient.GetHashCode(); + hashCode = hashCode * -439837856 + OtherBuildings.GetHashCode(); + return hashCode; + } } } diff --git a/Dota2GSI/Nodes/Couriers.cs b/Dota2GSI/Nodes/Couriers.cs index 2ddf683..287def3 100644 --- a/Dota2GSI/Nodes/Couriers.cs +++ b/Dota2GSI/Nodes/Couriers.cs @@ -1,7 +1,6 @@ using Dota2GSI.Nodes.CouriersProvider; using Newtonsoft.Json.Linq; using System; -using System.Collections.Generic; using System.Text.RegularExpressions; namespace Dota2GSI.Nodes @@ -14,7 +13,7 @@ public class Couriers : Node /// /// A dictionary mapping of courier ID to courier. /// - public readonly Dictionary CouriersMap = new Dictionary(); + public readonly NodeMap CouriersMap = new NodeMap(); private Regex _courier_regex = new Regex(@"courier(\d+)"); @@ -54,5 +53,25 @@ public override string ToString() $"CouriersMap: {CouriersMap}" + $"]"; } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is Couriers other && + CouriersMap.Equals(other.CouriersMap); + } + + /// + public override int GetHashCode() + { + int hashCode = 743690963; + hashCode = hashCode * -787011489 + CouriersMap.GetHashCode(); + return hashCode; + } } } diff --git a/Dota2GSI/Nodes/CouriersProvider/Courier.cs b/Dota2GSI/Nodes/CouriersProvider/Courier.cs index 8038ee6..1433900 100644 --- a/Dota2GSI/Nodes/CouriersProvider/Courier.cs +++ b/Dota2GSI/Nodes/CouriersProvider/Courier.cs @@ -1,7 +1,6 @@ using Dota2GSI.Nodes.Helpers; using Newtonsoft.Json.Linq; using System; -using System.Collections.Generic; using System.Text.RegularExpressions; namespace Dota2GSI.Nodes.CouriersProvider @@ -64,7 +63,7 @@ public class Courier : Node /// /// Items the courier is carrying. /// - public readonly Dictionary Items = new Dictionary(); + public readonly NodeMap Items = new NodeMap(); private Regex _item_regex = new Regex(@"item(\d+)"); @@ -107,5 +106,45 @@ public override string ToString() $"Items: {Items}" + $"]"; } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is Courier other && + Health == other.Health && + MaxHealth == other.MaxHealth && + IsAlive == other.IsAlive && + RemainingRespawnTime == other.RemainingRespawnTime && + Location.Equals(other.Location) && + Rotation == other.Rotation && + OwnerID.Equals(other.OwnerID) && + HasFlyingUpgrade == other.HasFlyingUpgrade && + IsShielded == other.IsShielded && + IsBoosted == other.IsBoosted && + Items.Equals(other.Items); + } + + /// + public override int GetHashCode() + { + int hashCode = 232969005; + hashCode = hashCode * -115989773 + Health.GetHashCode(); + hashCode = hashCode * -115989773 + MaxHealth.GetHashCode(); + hashCode = hashCode * -115989773 + IsAlive.GetHashCode(); + hashCode = hashCode * -115989773 + RemainingRespawnTime.GetHashCode(); + hashCode = hashCode * -115989773 + Location.GetHashCode(); + hashCode = hashCode * -115989773 + Rotation.GetHashCode(); + hashCode = hashCode * -115989773 + OwnerID.GetHashCode(); + hashCode = hashCode * -115989773 + HasFlyingUpgrade.GetHashCode(); + hashCode = hashCode * -115989773 + IsShielded.GetHashCode(); + hashCode = hashCode * -115989773 + IsBoosted.GetHashCode(); + hashCode = hashCode * -115989773 + Items.GetHashCode(); + return hashCode; + } } } diff --git a/Dota2GSI/Nodes/CouriersProvider/CourierItem.cs b/Dota2GSI/Nodes/CouriersProvider/CourierItem.cs index 69675dd..dee8c54 100644 --- a/Dota2GSI/Nodes/CouriersProvider/CourierItem.cs +++ b/Dota2GSI/Nodes/CouriersProvider/CourierItem.cs @@ -31,5 +31,27 @@ public override string ToString() $"OwnerID: {OwnerID}" + $"]"; } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is CourierItem other && + Name.Equals(other.Name) && + OwnerID == other.OwnerID; + } + + /// + public override int GetHashCode() + { + int hashCode = 710433606; + hashCode = hashCode * -324247450 + Name.GetHashCode(); + hashCode = hashCode * -324247450 + OwnerID.GetHashCode(); + return hashCode; + } } } diff --git a/Dota2GSI/Nodes/Draft.cs b/Dota2GSI/Nodes/Draft.cs index 7f9a8f4..e547ef0 100644 --- a/Dota2GSI/Nodes/Draft.cs +++ b/Dota2GSI/Nodes/Draft.cs @@ -1,7 +1,6 @@ using Dota2GSI.Nodes.DraftProvider; using Newtonsoft.Json.Linq; using System; -using System.Collections.Generic; using System.Text.RegularExpressions; namespace Dota2GSI.Nodes @@ -39,7 +38,7 @@ public class Draft : Node /// /// The team draft information. /// - public readonly Dictionary Teams = new Dictionary(); + public readonly NodeMap Teams = new NodeMap(); private Regex _team_id_regex = new Regex(@"team(\d+)"); @@ -86,5 +85,35 @@ public override string ToString() $"Teams: {Teams}" + $"]"; } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is Draft other && + ActiveTeam == other.ActiveTeam && + Pick == other.Pick && + ActiveTeamRemainingTime == other.ActiveTeamRemainingTime && + RadiantBonusTime == other.RadiantBonusTime && + DireBonusTime == other.DireBonusTime && + Teams.Equals(other.Teams); + } + + /// + public override int GetHashCode() + { + int hashCode = 370669188; + hashCode = hashCode * -824566422 + ActiveTeam.GetHashCode(); + hashCode = hashCode * -824566422 + Pick.GetHashCode(); + hashCode = hashCode * -824566422 + ActiveTeamRemainingTime.GetHashCode(); + hashCode = hashCode * -824566422 + RadiantBonusTime.GetHashCode(); + hashCode = hashCode * -824566422 + DireBonusTime.GetHashCode(); + hashCode = hashCode * -824566422 + Teams.GetHashCode(); + return hashCode; + } } } diff --git a/Dota2GSI/Nodes/DraftProvider/DraftDetails.cs b/Dota2GSI/Nodes/DraftProvider/DraftDetails.cs index 4f26ddc..c01996a 100644 --- a/Dota2GSI/Nodes/DraftProvider/DraftDetails.cs +++ b/Dota2GSI/Nodes/DraftProvider/DraftDetails.cs @@ -1,6 +1,5 @@ using Newtonsoft.Json.Linq; using System; -using System.Collections.Generic; using System.Text.RegularExpressions; namespace Dota2GSI.Nodes.DraftProvider @@ -18,12 +17,12 @@ public class DraftDetails : Node /// /// Pick IDs. /// - public readonly Dictionary PickIDs = new Dictionary(); + public readonly NodeMap PickIDs = new NodeMap(); /// /// Pick Hero IDs. /// - public readonly Dictionary PickHeroIDs = new Dictionary(); + public readonly NodeMap PickHeroIDs = new NodeMap(); private Regex _pick_id_regex = new Regex(@"pick(\d+)_id"); private Regex _pick_class_regex = new Regex(@"pick(\d+)_class"); @@ -56,5 +55,29 @@ public override string ToString() $"PickHeroIDs: {PickHeroIDs}" + $"]"; } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is DraftDetails other && + IsHomeTeam == other.IsHomeTeam && + PickIDs.Equals(other.PickIDs) && + PickHeroIDs.Equals(other.PickHeroIDs); + } + + /// + public override int GetHashCode() + { + int hashCode = 148535770; + hashCode = hashCode * -633163745 + IsHomeTeam.GetHashCode(); + hashCode = hashCode * -633163745 + PickIDs.GetHashCode(); + hashCode = hashCode * -633163745 + PickHeroIDs.GetHashCode(); + return hashCode; + } } } diff --git a/Dota2GSI/Nodes/Events.cs b/Dota2GSI/Nodes/Events.cs index 05dc642..cd622b4 100644 --- a/Dota2GSI/Nodes/Events.cs +++ b/Dota2GSI/Nodes/Events.cs @@ -10,7 +10,7 @@ namespace Dota2GSI.Nodes /// public class Events : IEnumerable { - private List _events = new List(); + private NodeList _events = new NodeList(); /// /// The number of events. @@ -23,7 +23,7 @@ internal Events(JArray parsed_data = null) : base() { if (parsed_data.Type == JTokenType.Array) { - foreach(JToken element in parsed_data.Children()) + foreach (JToken element in parsed_data.Children()) { if (element.Type == JTokenType.Object) { @@ -39,9 +39,9 @@ internal Events(JArray parsed_data = null) : base() /// /// The team. /// List of events. - public List GetForTeam(PlayerTeam team) + public NodeList GetForTeam(PlayerTeam team) { - List found_events = new List(); + NodeList found_events = new NodeList(); foreach (var evt in _events) { @@ -59,9 +59,9 @@ public List GetForTeam(PlayerTeam team) /// /// The player id to match. /// List of events. - public List GetForPlayer(int player_id) + public NodeList GetForPlayer(int player_id) { - List found_events = new List(); + NodeList found_events = new NodeList(); foreach (var evt in _events) { @@ -112,5 +112,25 @@ public override string ToString() $"Events: {_events}" + $"]"; } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is Events other && + _events.Equals(other._events); + } + + /// + public override int GetHashCode() + { + int hashCode = 395433322; + hashCode = hashCode * -356790273 + _events.GetHashCode(); + return hashCode; + } } } diff --git a/Dota2GSI/Nodes/EventsProvider/Event.cs b/Dota2GSI/Nodes/EventsProvider/Event.cs index 43a59b5..2861b4e 100644 --- a/Dota2GSI/Nodes/EventsProvider/Event.cs +++ b/Dota2GSI/Nodes/EventsProvider/Event.cs @@ -151,6 +151,44 @@ public override string ToString() $"BountyValue: {BountyValue}, " + $"TeamGold: {TeamGold}" + $"]"; + } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is Event other && + GameTime == other.GameTime && + EventType == other.EventType && + Team == other.Team && + KillerPlayerID == other.KillerPlayerID && + PlayerID == other.PlayerID && + WasSnatched == other.WasSnatched && + TipReceiverPlayerID == other.TipReceiverPlayerID && + TipAmount == other.TipAmount && + BountyValue == other.BountyValue && + TeamGold == other.TeamGold; + } + + /// + public override int GetHashCode() + { + int hashCode = 973835034; + hashCode = hashCode * -320607063 + GameTime.GetHashCode(); + hashCode = hashCode * -320607063 + EventType.GetHashCode(); + hashCode = hashCode * -320607063 + Team.GetHashCode(); + hashCode = hashCode * -320607063 + KillerPlayerID.GetHashCode(); + hashCode = hashCode * -320607063 + PlayerID.GetHashCode(); + hashCode = hashCode * -320607063 + WasSnatched.GetHashCode(); + hashCode = hashCode * -320607063 + TipReceiverPlayerID.GetHashCode(); + hashCode = hashCode * -320607063 + TipAmount.GetHashCode(); + hashCode = hashCode * -320607063 + BountyValue.GetHashCode(); + hashCode = hashCode * -320607063 + TeamGold.GetHashCode(); + return hashCode; } } } diff --git a/Dota2GSI/Nodes/Helpers/FullPlayerDetails.cs b/Dota2GSI/Nodes/Helpers/FullPlayerDetails.cs index 62b6a71..43ef347 100644 --- a/Dota2GSI/Nodes/Helpers/FullPlayerDetails.cs +++ b/Dota2GSI/Nodes/Helpers/FullPlayerDetails.cs @@ -5,7 +5,6 @@ using Dota2GSI.Nodes.MinimapProvider; using Dota2GSI.Nodes.PlayerProvider; using Dota2GSI.Nodes.WearablesProvider; -using System.Collections.Generic; namespace Dota2GSI.Nodes.Helpers { @@ -47,7 +46,7 @@ public class FullPlayerDetails /// /// Player's minimap elements. /// - public readonly Dictionary MinimapElements = new Dictionary(); + public readonly NodeMap MinimapElements = new NodeMap(); internal FullPlayerDetails(int player_id, GameState game_state) { @@ -84,5 +83,37 @@ public override string ToString() $"PlayerMinimapElements: {MinimapElements}" + $"]"; } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is FullPlayerDetails other && + Details.Equals(other.Details) && + Hero.Equals(other.Hero) && + Abilities.Equals(other.Abilities) && + Items.Equals(other.Items) && + Wearables.Equals(other.Wearables) && + Courier.Equals(other.Courier) && + MinimapElements.Equals(other.MinimapElements); + } + + /// + public override int GetHashCode() + { + int hashCode = 339357341; + hashCode = hashCode * -959873209 + Details.GetHashCode(); + hashCode = hashCode * -959873209 + Hero.GetHashCode(); + hashCode = hashCode * -959873209 + Abilities.GetHashCode(); + hashCode = hashCode * -959873209 + Items.GetHashCode(); + hashCode = hashCode * -959873209 + Wearables.GetHashCode(); + hashCode = hashCode * -959873209 + Courier.GetHashCode(); + hashCode = hashCode * -959873209 + MinimapElements.GetHashCode(); + return hashCode; + } } } diff --git a/Dota2GSI/Nodes/Helpers/FullTeamDetails.cs b/Dota2GSI/Nodes/Helpers/FullTeamDetails.cs index b8fad72..5351685 100644 --- a/Dota2GSI/Nodes/Helpers/FullTeamDetails.cs +++ b/Dota2GSI/Nodes/Helpers/FullTeamDetails.cs @@ -3,7 +3,6 @@ using Dota2GSI.Nodes.EventsProvider; using Dota2GSI.Nodes.MinimapProvider; using Dota2GSI.Nodes.NeutralItemsProvider; -using System.Collections.Generic; namespace Dota2GSI.Nodes.Helpers { @@ -20,7 +19,7 @@ public class FullTeamDetails /// /// This team's players. /// - public readonly Dictionary Players = new Dictionary(); + public readonly NodeMap Players = new NodeMap(); /// /// This team's draft. @@ -42,12 +41,12 @@ public class FullTeamDetails /// Key is element ID.
/// Value is minimap element. ///
- public readonly Dictionary MinimapElements = new Dictionary(); + public readonly NodeMap MinimapElements = new NodeMap(); /// /// This team's recent events. /// - public readonly List Events = new List(); + public readonly NodeList Events = new NodeList(); /// /// Is this team a winner? @@ -58,7 +57,7 @@ internal FullTeamDetails(PlayerTeam team, GameState game_state) { Team = team; - foreach(var team_player_kvp in game_state.Player.GetForTeam(team)) + foreach (var team_player_kvp in game_state.Player.GetForTeam(team)) { Players.Add(team_player_kvp.Key, new FullPlayerDetails(team_player_kvp.Key, game_state)); } @@ -85,5 +84,39 @@ public override string ToString() $"IsWinner: {IsWinner}" + $"]"; } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is FullTeamDetails other && + Team == other.Team && + Players.Equals(other.Players) && + Draft.Equals(other.Draft) && + NeutralItems.Equals(other.NeutralItems) && + Buildings.Equals(other.Buildings) && + MinimapElements.Equals(other.MinimapElements) && + Events.Equals(other.Events) && + IsWinner == other.IsWinner; + } + + /// + public override int GetHashCode() + { + int hashCode = 327356736; + hashCode = hashCode * -578827851 + Team.GetHashCode(); + hashCode = hashCode * -578827851 + Players.GetHashCode(); + hashCode = hashCode * -578827851 + Draft.GetHashCode(); + hashCode = hashCode * -578827851 + NeutralItems.GetHashCode(); + hashCode = hashCode * -578827851 + Buildings.GetHashCode(); + hashCode = hashCode * -578827851 + MinimapElements.GetHashCode(); + hashCode = hashCode * -578827851 + Events.GetHashCode(); + hashCode = hashCode * -578827851 + IsWinner.GetHashCode(); + return hashCode; + } } } diff --git a/Dota2GSI/Nodes/Helpers/Vector2D.cs b/Dota2GSI/Nodes/Helpers/Vector2D.cs index 1e226c0..de4cc14 100644 --- a/Dota2GSI/Nodes/Helpers/Vector2D.cs +++ b/Dota2GSI/Nodes/Helpers/Vector2D.cs @@ -27,11 +27,7 @@ public Vector2D(int x, int y) Y = y; } - /// - /// Equates this Vector2D object to another object. - /// - /// The other object to compare against. - /// True if the two objects are equal, false otherwise. + /// public override bool Equals(object obj) { return obj is Vector2D other && @@ -39,10 +35,7 @@ public override bool Equals(object obj) Y == other.Y; } - /// - /// Calculates unique hash code for this object. - /// - /// The hash code. + /// public override int GetHashCode() { int hashCode = 1861411795; diff --git a/Dota2GSI/Nodes/Hero.cs b/Dota2GSI/Nodes/Hero.cs index dfcaa4c..fdf2365 100644 --- a/Dota2GSI/Nodes/Hero.cs +++ b/Dota2GSI/Nodes/Hero.cs @@ -1,7 +1,6 @@ using Dota2GSI.Nodes.HeroProvider; using Newtonsoft.Json.Linq; using System; -using System.Collections.Generic; using System.Text.RegularExpressions; namespace Dota2GSI.Nodes @@ -19,7 +18,7 @@ public class Hero : Node /// /// The team players hero details. (SPECTATOR ONLY) /// - public readonly Dictionary> Teams = new Dictionary>(); + public readonly NodeMap> Teams = new NodeMap>(); private Regex _team_id_regex = new Regex(@"team(\d+)"); private Regex _player_id_regex = new Regex(@"player(\d+)"); @@ -36,7 +35,7 @@ internal Hero(JObject parsed_data = null) : base(parsed_data) if (!Teams.ContainsKey(team_id)) { - Teams.Add(team_id, new Dictionary()); + Teams.Add(team_id, new NodeMap()); } GetMatchingObjects(obj, _player_id_regex, (Match sub_match, JObject sub_obj) => @@ -61,14 +60,14 @@ internal Hero(JObject parsed_data = null) : base(parsed_data) /// /// The team. /// A dictionary of player id mapped to their hero details. - public Dictionary GetForTeam(PlayerTeam team) + public NodeMap GetForTeam(PlayerTeam team) { if (Teams.ContainsKey(team)) { return Teams[team]; } - return new Dictionary(); + return new NodeMap(); } /// @@ -106,5 +105,27 @@ public override bool IsValid() { return LocalPlayer.IsValid() || base.IsValid(); } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is Hero other && + LocalPlayer.Equals(other.LocalPlayer) && + Teams.Equals(other.Teams); + } + + /// + public override int GetHashCode() + { + int hashCode = 222282086; + hashCode = hashCode * -422594062 + LocalPlayer.GetHashCode(); + hashCode = hashCode * -422594062 + Teams.GetHashCode(); + return hashCode; + } } } diff --git a/Dota2GSI/Nodes/HeroProvider/HeroDetails.cs b/Dota2GSI/Nodes/HeroProvider/HeroDetails.cs index 931fcf1..a35f8f3 100644 --- a/Dota2GSI/Nodes/HeroProvider/HeroDetails.cs +++ b/Dota2GSI/Nodes/HeroProvider/HeroDetails.cs @@ -1,5 +1,6 @@ -using Dota2GSI.Nodes.Helpers; +using Dota2GSI.Nodes.Helpers; using Newtonsoft.Json.Linq; +using System.Linq; namespace Dota2GSI.Nodes.HeroProvider { @@ -29,6 +30,57 @@ public enum TalentTreeSpec Both } + /// + /// The hero state. + /// + public enum HeroState + { + /// + /// No states. + /// + None = 0, + + /// + /// Hero is silenced. + /// + Silenced, + + /// + /// Hero is stunned. + /// + Stunned, + + /// + /// Hero is disarmed. + /// + Disarmed, + + /// + /// Hero is magic immune. + /// + MagicImmune, + + /// + /// Hero is hexed. + /// + Hexed, + + /// + /// Hero is broken. + /// + Broken, + + /// + /// Hero is smoked. + /// + Smoked, + + /// + /// Hero is debuffed. + /// + Debuffed + } + /// /// Class representing hero details. /// @@ -110,40 +162,15 @@ public class HeroDetails : Node public readonly int ManaPercent; /// - /// A boolean representing whether the hero is silenced. - /// - public readonly bool IsSilenced; - - /// - /// A boolean representing whether the hero is stunned. - /// - public readonly bool IsStunned; - - /// - /// A boolean representing whether the hero is disarmed. + /// Current hero state. /// - public readonly bool IsDisarmed; - - /// - /// A boolean representing whether the hero is magic immune. - /// - public readonly bool IsMagicImmune; - - /// - /// A boolean representing whether the hero is hexed. - /// - public readonly bool IsHexed; + public readonly HeroState HeroState; /// /// A boolean representing whether the hero is muted. /// public readonly bool IsMuted; - /// - /// A boolean representing whether the hero is broken. - /// - public readonly bool IsBreak; - /// /// A boolean representing whether the hero has the aghanims scepter upgrade. /// @@ -154,16 +181,6 @@ public class HeroDetails : Node /// public readonly bool HasAghanimsShardUpgrade; - /// - /// A boolean representing whether the hero is smoked. - /// - public readonly bool IsSmoked; - - /// - /// A boolean representing whether the hero is debuffed. - /// - public readonly bool HasDebuff; - /// /// A boolean representing whether this hero is currently selected by the spectator. (SPECTATOR ONLY) /// @@ -196,19 +213,53 @@ internal HeroDetails(JObject parsed_data = null) : base(parsed_data) Mana = GetInt("mana"); MaxMana = GetInt("max_mana"); ManaPercent = GetInt("mana_percent"); - IsSilenced = GetBool("silenced"); - IsStunned = GetBool("stunned"); - IsDisarmed = GetBool("disarmed"); - IsMagicImmune = GetBool("magicimmune"); - IsHexed = GetBool("hexed"); IsMuted = GetBool("muted"); - IsBreak = GetBool("break"); HasAghanimsScepterUpgrade = GetBool("aghanims_scepter"); HasAghanimsShardUpgrade = GetBool("aghanims_shard"); - IsSmoked = GetBool("smoked"); - HasDebuff = GetBool("has_debuff"); SelectedUnit = GetBool("selected_unit"); + HeroState = HeroState.None; + + if (GetBool("silenced")) + { + HeroState &= HeroState.Silenced; + } + + if (GetBool("stunned")) + { + HeroState &= HeroState.Stunned; + } + + if (GetBool("disarmed")) + { + HeroState &= HeroState.Disarmed; + } + + if (GetBool("magicimmune")) + { + HeroState &= HeroState.MagicImmune; + } + + if (GetBool("hexed")) + { + HeroState &= HeroState.Hexed; + } + + if (GetBool("break")) + { + HeroState &= HeroState.Broken; + } + + if (GetBool("smoked")) + { + HeroState &= HeroState.Smoked; + } + + if (GetBool("has_debuff")) + { + HeroState &= HeroState.Debuffed; + } + TalentTree = new TalentTreeSpec[4]; for (int i = 0; i < TalentTree.Length; i++) { @@ -259,21 +310,74 @@ public override string ToString() $"Mana: {Mana}, " + $"MaxMana: {MaxMana}, " + $"ManaPercent: {ManaPercent}, " + - $"IsSilenced: {IsSilenced}, " + - $"IsStunned: {IsStunned}, " + - $"IsDisarmed: {IsDisarmed}, " + - $"IsMagicImmune: {IsMagicImmune}, " + - $"IsHexed: {IsHexed}, " + + $"IsSilenced: {HeroState}, " + $"IsMuted: {IsMuted}, " + - $"IsBreak: {IsBreak}, " + $"HasAghanimsScepterUpgrade: {HasAghanimsScepterUpgrade}, " + $"HasAghanimsShardUpgrade: {HasAghanimsShardUpgrade}, " + - $"IsSmoked: {IsSmoked}, " + - $"HasDebuff: {HasDebuff}, " + $"SelectedUnit: {SelectedUnit}, " + $"TalentTree: {TalentTree}, " + $"AttributesLevel: {AttributesLevel}" + $"]"; } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is HeroDetails other && + Location.Equals(other.Location) && + ID == other.ID && + Name.Equals(other.Name) && + Level == other.Level && + Experience == other.Experience && + IsAlive == other.IsAlive && + SecondsToRespawn == other.SecondsToRespawn && + BuybackCost == other.BuybackCost && + BuybackCooldown == other.BuybackCooldown && + Health == other.Health && + MaxHealth == other.MaxHealth && + HealthPercent == other.HealthPercent && + Mana == other.Mana && + MaxMana == other.MaxMana && + ManaPercent == other.ManaPercent && + IsMuted == other.IsMuted && + HasAghanimsScepterUpgrade == other.HasAghanimsScepterUpgrade && + HasAghanimsShardUpgrade == other.HasAghanimsShardUpgrade && + SelectedUnit == other.SelectedUnit && + Enumerable.SequenceEqual(TalentTree, other.TalentTree) && + AttributesLevel == other.AttributesLevel; + } + + /// + public override int GetHashCode() + { + int hashCode = 189436882; + hashCode = hashCode * -287957234 + Location.GetHashCode(); + hashCode = hashCode * -287957234 + ID.GetHashCode(); + hashCode = hashCode * -287957234 + Name.GetHashCode(); + hashCode = hashCode * -287957234 + Level.GetHashCode(); + hashCode = hashCode * -287957234 + Experience.GetHashCode(); + hashCode = hashCode * -287957234 + IsAlive.GetHashCode(); + hashCode = hashCode * -287957234 + SecondsToRespawn.GetHashCode(); + hashCode = hashCode * -287957234 + BuybackCost.GetHashCode(); + hashCode = hashCode * -287957234 + BuybackCooldown.GetHashCode(); + hashCode = hashCode * -287957234 + Health.GetHashCode(); + hashCode = hashCode * -287957234 + MaxHealth.GetHashCode(); + hashCode = hashCode * -287957234 + HealthPercent.GetHashCode(); + hashCode = hashCode * -287957234 + Mana.GetHashCode(); + hashCode = hashCode * -287957234 + MaxMana.GetHashCode(); + hashCode = hashCode * -287957234 + ManaPercent.GetHashCode(); + hashCode = hashCode * -287957234 + IsMuted.GetHashCode(); + hashCode = hashCode * -287957234 + HasAghanimsScepterUpgrade.GetHashCode(); + hashCode = hashCode * -287957234 + HasAghanimsShardUpgrade.GetHashCode(); + hashCode = hashCode * -287957234 + SelectedUnit.GetHashCode(); + hashCode = hashCode * -287957234 + TalentTree.GetHashCode(); + hashCode = hashCode * -287957234 + AttributesLevel.GetHashCode(); + return hashCode; + } } } diff --git a/Dota2GSI/Nodes/Items.cs b/Dota2GSI/Nodes/Items.cs index 27ed67b..0509ce0 100644 --- a/Dota2GSI/Nodes/Items.cs +++ b/Dota2GSI/Nodes/Items.cs @@ -1,7 +1,6 @@ using Dota2GSI.Nodes.ItemsProvider; using Newtonsoft.Json.Linq; using System; -using System.Collections.Generic; using System.Text.RegularExpressions; namespace Dota2GSI.Nodes @@ -19,7 +18,7 @@ public class Items : Node /// /// The team players items. (SPECTATOR ONLY) /// - public readonly Dictionary> Teams = new Dictionary>(); + public readonly NodeMap> Teams = new NodeMap>(); private Regex _team_id_regex = new Regex(@"team(\d+)"); private Regex _player_id_regex = new Regex(@"player(\d+)"); @@ -36,7 +35,7 @@ internal Items(JObject parsed_data = null) : base(parsed_data) if (!Teams.ContainsKey(team_id)) { - Teams.Add(team_id, new Dictionary()); + Teams.Add(team_id, new NodeMap()); } GetMatchingObjects(parsed_data, _player_id_regex, (Match sub_match, JObject sub_obj) => @@ -61,14 +60,14 @@ internal Items(JObject parsed_data = null) : base(parsed_data) ///
/// The team. /// A dictionary of player id mapped to their item details. - public Dictionary GetForTeam(PlayerTeam team) + public NodeMap GetForTeam(PlayerTeam team) { if (Teams.ContainsKey(team)) { return Teams[team]; } - return new Dictionary(); + return new NodeMap(); } /// @@ -106,5 +105,27 @@ public override bool IsValid() { return LocalPlayer.IsValid() || base.IsValid(); } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is Items other && + LocalPlayer.Equals(other.LocalPlayer) && + Teams.Equals(other.Teams); + } + + /// + public override int GetHashCode() + { + int hashCode = 787251810; + hashCode = hashCode * -635208756 + LocalPlayer.GetHashCode(); + hashCode = hashCode * -635208756 + Teams.GetHashCode(); + return hashCode; + } } } diff --git a/Dota2GSI/Nodes/ItemsProvider/Item.cs b/Dota2GSI/Nodes/ItemsProvider/Item.cs index 90eb332..f0175e1 100644 --- a/Dota2GSI/Nodes/ItemsProvider/Item.cs +++ b/Dota2GSI/Nodes/ItemsProvider/Item.cs @@ -167,6 +167,48 @@ public override string ToString() $"ChargeCooldown: {ChargeCooldown}, " + $"Charges: {Charges}" + $"]"; + } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is Item other && + Name.Equals(other.Name) && + Purchaser == other.Purchaser && + ItemLevel == other.ItemLevel && + ContainsRune == other.ContainsRune && + CanCast == other.CanCast && + Cooldown == other.Cooldown && + IsPassive == other.IsPassive && + ItemCharges == other.ItemCharges && + AbilityCharges == other.AbilityCharges && + MaxCharges == other.MaxCharges && + ChargeCooldown == other.ChargeCooldown && + Charges == other.Charges; + } + + /// + public override int GetHashCode() + { + int hashCode = 578432725; + hashCode = hashCode * -280156728 + Name.GetHashCode(); + hashCode = hashCode * -280156728 + Purchaser.GetHashCode(); + hashCode = hashCode * -280156728 + ItemLevel.GetHashCode(); + hashCode = hashCode * -280156728 + ContainsRune.GetHashCode(); + hashCode = hashCode * -280156728 + CanCast.GetHashCode(); + hashCode = hashCode * -280156728 + Cooldown.GetHashCode(); + hashCode = hashCode * -280156728 + IsPassive.GetHashCode(); + hashCode = hashCode * -280156728 + ItemCharges.GetHashCode(); + hashCode = hashCode * -280156728 + AbilityCharges.GetHashCode(); + hashCode = hashCode * -280156728 + MaxCharges.GetHashCode(); + hashCode = hashCode * -280156728 + ChargeCooldown.GetHashCode(); + hashCode = hashCode * -280156728 + Charges.GetHashCode(); + return hashCode; } } } diff --git a/Dota2GSI/Nodes/ItemsProvider/ItemDetails.cs b/Dota2GSI/Nodes/ItemsProvider/ItemDetails.cs index 61e1ab4..03993af 100644 --- a/Dota2GSI/Nodes/ItemsProvider/ItemDetails.cs +++ b/Dota2GSI/Nodes/ItemsProvider/ItemDetails.cs @@ -1,5 +1,4 @@ using Newtonsoft.Json.Linq; -using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; @@ -13,12 +12,12 @@ public class ItemDetails : Node /// /// List of the inventory items. /// - public readonly List Inventory = new List(); + public readonly NodeList Inventory = new NodeList(); /// /// List of the stash items. /// - public readonly List Stash = new List(); + public readonly NodeList Stash = new NodeList(); /// /// Number of items in the inventory. @@ -216,5 +215,31 @@ public override string ToString() $"Neutral: {Neutral}, " + $"]"; } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is ItemDetails other && + Inventory.Equals(other.Inventory) && + Stash.Equals(other.Stash) && + Teleport.Equals(other.Teleport) && + Neutral.Equals(other.Neutral); + } + + /// + public override int GetHashCode() + { + int hashCode = 74222497; + hashCode = hashCode * -709592358 + Inventory.GetHashCode(); + hashCode = hashCode * -709592358 + Stash.GetHashCode(); + hashCode = hashCode * -709592358 + Teleport.GetHashCode(); + hashCode = hashCode * -709592358 + Neutral.GetHashCode(); + return hashCode; + } } } diff --git a/Dota2GSI/Nodes/League.cs b/Dota2GSI/Nodes/League.cs index ed5a019..50eefb7 100644 --- a/Dota2GSI/Nodes/League.cs +++ b/Dota2GSI/Nodes/League.cs @@ -1,6 +1,5 @@ using Dota2GSI.Nodes.LeagueProvider; using Newtonsoft.Json.Linq; -using System.Collections.Generic; namespace Dota2GSI.Nodes { @@ -168,7 +167,7 @@ public class League : Node /// /// The streams for the league. /// - public readonly List Streams = new List(); + public readonly NodeList Streams = new NodeList(); internal League(JObject parsed_data = null) : base(parsed_data) { @@ -245,5 +244,77 @@ public override string ToString() $"Streams: {Streams}" + $"]"; } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is League other && + SeriesType == other.SeriesType && + SelectionPriority.Equals(other.SelectionPriority) && + LeagueID == other.LeagueID && + MatchID == other.MatchID && + Name.Equals(other.Name) && + Tier == other.Tier && + Region == other.Region && + Url.Equals(other.Url) && + Description.Equals(other.Description) && + Notes.Equals(other.Notes) && + StartTimestamp == other.StartTimestamp && + EndTimestamp == other.EndTimestamp && + ProCircuitPoints == other.ProCircuitPoints && + ImageBits == other.ImageBits && + Status == other.Status && + MostRecentActivity == other.MostRecentActivity && + RegistrationPeriod == other.RegistrationPeriod && + BasePrizePool == other.BasePrizePool && + TotalPrizePool == other.TotalPrizePool && + LeagueNoteID == other.LeagueNoteID && + RadiantTeam.Equals(other.RadiantTeam) && + DireTeam.Equals(other.DireTeam) && + SeriesID == other.SeriesID && + StartTime == other.StartTime && + FirstTeamID == other.FirstTeamID && + SecondTeamID == other.SecondTeamID && + Streams.Equals(other.Streams); + } + + /// + public override int GetHashCode() + { + int hashCode = 761863323; + hashCode = hashCode * -43571779 + SeriesType.GetHashCode(); + hashCode = hashCode * -43571779 + SelectionPriority.GetHashCode(); + hashCode = hashCode * -43571779 + LeagueID.GetHashCode(); + hashCode = hashCode * -43571779 + MatchID.GetHashCode(); + hashCode = hashCode * -43571779 + Name.GetHashCode(); + hashCode = hashCode * -43571779 + Tier.GetHashCode(); + hashCode = hashCode * -43571779 + Region.GetHashCode(); + hashCode = hashCode * -43571779 + Url.GetHashCode(); + hashCode = hashCode * -43571779 + Description.GetHashCode(); + hashCode = hashCode * -43571779 + Notes.GetHashCode(); + hashCode = hashCode * -43571779 + StartTimestamp.GetHashCode(); + hashCode = hashCode * -43571779 + EndTimestamp.GetHashCode(); + hashCode = hashCode * -43571779 + ProCircuitPoints.GetHashCode(); + hashCode = hashCode * -43571779 + ImageBits.GetHashCode(); + hashCode = hashCode * -43571779 + Status.GetHashCode(); + hashCode = hashCode * -43571779 + MostRecentActivity.GetHashCode(); + hashCode = hashCode * -43571779 + RegistrationPeriod.GetHashCode(); + hashCode = hashCode * -43571779 + BasePrizePool.GetHashCode(); + hashCode = hashCode * -43571779 + TotalPrizePool.GetHashCode(); + hashCode = hashCode * -43571779 + LeagueNoteID.GetHashCode(); + hashCode = hashCode * -43571779 + RadiantTeam.GetHashCode(); + hashCode = hashCode * -43571779 + DireTeam.GetHashCode(); + hashCode = hashCode * -43571779 + SeriesID.GetHashCode(); + hashCode = hashCode * -43571779 + StartTime.GetHashCode(); + hashCode = hashCode * -43571779 + FirstTeamID.GetHashCode(); + hashCode = hashCode * -43571779 + SecondTeamID.GetHashCode(); + hashCode = hashCode * -43571779 + Streams.GetHashCode(); + return hashCode; + } } } diff --git a/Dota2GSI/Nodes/LeagueProvider/LeagueTeam.cs b/Dota2GSI/Nodes/LeagueProvider/LeagueTeam.cs index 757bdfd..be7ab8d 100644 --- a/Dota2GSI/Nodes/LeagueProvider/LeagueTeam.cs +++ b/Dota2GSI/Nodes/LeagueProvider/LeagueTeam.cs @@ -45,5 +45,31 @@ public override string ToString() $"SeriesWins: {SeriesWins}" + $"]"; } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is LeagueTeam other && + TeamID == other.TeamID && + TeamTag.Equals(other.TeamTag) && + TeamName.Equals(other.TeamName) && + SeriesWins == other.SeriesWins; + } + + /// + public override int GetHashCode() + { + int hashCode = 248757312; + hashCode = hashCode * -665381140 + TeamID.GetHashCode(); + hashCode = hashCode * -665381140 + TeamTag.GetHashCode(); + hashCode = hashCode * -665381140 + TeamName.GetHashCode(); + hashCode = hashCode * -665381140 + SeriesWins.GetHashCode(); + return hashCode; + } } } diff --git a/Dota2GSI/Nodes/LeagueProvider/SelectionPriority.cs b/Dota2GSI/Nodes/LeagueProvider/SelectionPriority.cs index acd2424..cc7c2af 100644 --- a/Dota2GSI/Nodes/LeagueProvider/SelectionPriority.cs +++ b/Dota2GSI/Nodes/LeagueProvider/SelectionPriority.cs @@ -126,5 +126,35 @@ public override string ToString() $"UsedCoinToss: {UsedCoinToss}" + $"]"; } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is SelectionPriority other && + Rules == other.Rules && + PreviousPriorityTeamID == other.PreviousPriorityTeamID && + CurrentPriorityTeamID == other.CurrentPriorityTeamID && + PriorityTeamChoice == other.PriorityTeamChoice && + NonPriorityTeamChoice == other.NonPriorityTeamChoice && + UsedCoinToss == other.UsedCoinToss; + } + + /// + public override int GetHashCode() + { + int hashCode = 107532357; + hashCode = hashCode * -96977732 + Rules.GetHashCode(); + hashCode = hashCode * -96977732 + PreviousPriorityTeamID.GetHashCode(); + hashCode = hashCode * -96977732 + CurrentPriorityTeamID.GetHashCode(); + hashCode = hashCode * -96977732 + PriorityTeamChoice.GetHashCode(); + hashCode = hashCode * -96977732 + NonPriorityTeamChoice.GetHashCode(); + hashCode = hashCode * -96977732 + UsedCoinToss.GetHashCode(); + return hashCode; + } } } diff --git a/Dota2GSI/Nodes/LeagueProvider/Stream.cs b/Dota2GSI/Nodes/LeagueProvider/Stream.cs index aba4583..c200a56 100644 --- a/Dota2GSI/Nodes/LeagueProvider/Stream.cs +++ b/Dota2GSI/Nodes/LeagueProvider/Stream.cs @@ -59,5 +59,35 @@ public override string ToString() $"VodURL: {VodURL}" + $"]"; } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is Stream other && + StreamID == other.StreamID && + Language == other.Language && + Name.Equals(other.Name) && + BroadcastProvider == other.BroadcastProvider && + StreamURL.Equals(other.StreamURL) && + VodURL.Equals(other.VodURL); + } + + /// + public override int GetHashCode() + { + int hashCode = 192157661; + hashCode = hashCode * -913935863 + StreamID.GetHashCode(); + hashCode = hashCode * -913935863 + Language.GetHashCode(); + hashCode = hashCode * -913935863 + Name.GetHashCode(); + hashCode = hashCode * -913935863 + BroadcastProvider.GetHashCode(); + hashCode = hashCode * -913935863 + StreamURL.GetHashCode(); + hashCode = hashCode * -913935863 + VodURL.GetHashCode(); + return hashCode; + } } } diff --git a/Dota2GSI/Nodes/Map.cs b/Dota2GSI/Nodes/Map.cs index a09d186..fbac0ac 100644 --- a/Dota2GSI/Nodes/Map.cs +++ b/Dota2GSI/Nodes/Map.cs @@ -275,6 +275,58 @@ public override string ToString() $"RoshanState: {RoshanState}, " + $"RoshanStateEndTime: {RoshanStateEndTime}" + $"]"; + } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is Map other && + Name.Equals(other.Name) && + MatchID == other.MatchID && + GameTime == other.GameTime && + ClockTime == other.ClockTime && + IsDaytime == other.IsDaytime && + IsNightstalkerNight == other.IsNightstalkerNight && + RadiantScore == other.RadiantScore && + DireScore == other.DireScore && + GameState == other.GameState && + IsPaused == other.IsPaused && + WinningTeam == other.WinningTeam && + CustomGameName.Equals(other.CustomGameName) && + WardPurchaseCooldown == other.WardPurchaseCooldown && + RadiantWardPurchaseCooldown == other.RadiantWardPurchaseCooldown && + DireWardPurchaseCooldown == other.DireWardPurchaseCooldown && + RoshanState == other.RoshanState && + RoshanStateEndTime == other.RoshanStateEndTime; + } + + /// + public override int GetHashCode() + { + int hashCode = 225797103; + hashCode = hashCode * -955669127 + Name.GetHashCode(); + hashCode = hashCode * -955669127 + MatchID.GetHashCode(); + hashCode = hashCode * -955669127 + GameTime.GetHashCode(); + hashCode = hashCode * -955669127 + ClockTime.GetHashCode(); + hashCode = hashCode * -955669127 + IsDaytime.GetHashCode(); + hashCode = hashCode * -955669127 + IsNightstalkerNight.GetHashCode(); + hashCode = hashCode * -955669127 + RadiantScore.GetHashCode(); + hashCode = hashCode * -955669127 + DireScore.GetHashCode(); + hashCode = hashCode * -955669127 + GameState.GetHashCode(); + hashCode = hashCode * -955669127 + IsPaused.GetHashCode(); + hashCode = hashCode * -955669127 + WinningTeam.GetHashCode(); + hashCode = hashCode * -955669127 + CustomGameName.GetHashCode(); + hashCode = hashCode * -955669127 + WardPurchaseCooldown.GetHashCode(); + hashCode = hashCode * -955669127 + RadiantWardPurchaseCooldown.GetHashCode(); + hashCode = hashCode * -955669127 + DireWardPurchaseCooldown.GetHashCode(); + hashCode = hashCode * -955669127 + RoshanState.GetHashCode(); + hashCode = hashCode * -955669127 + RoshanStateEndTime.GetHashCode(); + return hashCode; } } } diff --git a/Dota2GSI/Nodes/Minimap.cs b/Dota2GSI/Nodes/Minimap.cs index ac022bc..905619b 100644 --- a/Dota2GSI/Nodes/Minimap.cs +++ b/Dota2GSI/Nodes/Minimap.cs @@ -1,7 +1,6 @@ using Dota2GSI.Nodes.MinimapProvider; using Newtonsoft.Json.Linq; using System; -using System.Collections.Generic; using System.Text.RegularExpressions; namespace Dota2GSI.Nodes @@ -16,7 +15,7 @@ public class Minimap : Node /// Key is element ID.
/// Value is minimap element. ///
- public readonly Dictionary Elements = new Dictionary(); + public readonly NodeMap Elements = new NodeMap(); private Regex _object_regex = new Regex(@"o(\d+)"); internal Minimap(JObject parsed_data = null) : base(parsed_data) @@ -36,9 +35,9 @@ internal Minimap(JObject parsed_data = null) : base(parsed_data) ///
/// The team. /// The minimap elements. - public Dictionary GetForTeam(PlayerTeam team) + public NodeMap GetForTeam(PlayerTeam team) { - Dictionary found_elements = new Dictionary(); + NodeMap found_elements = new NodeMap(); foreach (var element_kvp in Elements) { @@ -58,9 +57,9 @@ public Dictionary GetForTeam(PlayerTeam team) /// /// The unit name. /// The minimap elements. - public Dictionary GetByUnitName(string unit_name) + public NodeMap GetByUnitName(string unit_name) { - Dictionary found_elements = new Dictionary(); + NodeMap found_elements = new NodeMap(); if (!string.IsNullOrEmpty(unit_name)) { @@ -83,5 +82,25 @@ public override string ToString() $"Elements: {Elements}" + $"]"; } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is Minimap other && + Elements.Equals(other.Elements); + } + + /// + public override int GetHashCode() + { + int hashCode = 212298410; + hashCode = hashCode * -927590333 + Elements.GetHashCode(); + return hashCode; + } } } diff --git a/Dota2GSI/Nodes/MinimapProvider/MinimapElement.cs b/Dota2GSI/Nodes/MinimapProvider/MinimapElement.cs index 58f8dcf..3137019 100644 --- a/Dota2GSI/Nodes/MinimapProvider/MinimapElement.cs +++ b/Dota2GSI/Nodes/MinimapProvider/MinimapElement.cs @@ -81,5 +81,41 @@ public override string ToString() $"VisionRange: {VisionRange}" + $"]"; } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is MinimapElement other && + Location.Equals(other.Location) && + RemainingTime == other.RemainingTime && + EventDuration == other.EventDuration && + Image.Equals(other.Image) && + Team == other.Team && + Name.Equals(other.Name) && + Rotation == other.Rotation && + UnitName.Equals(other.UnitName) && + VisionRange == other.VisionRange; + } + + /// + public override int GetHashCode() + { + int hashCode = 111327035; + hashCode = hashCode * -71571866 + Location.GetHashCode(); + hashCode = hashCode * -71571866 + RemainingTime.GetHashCode(); + hashCode = hashCode * -71571866 + EventDuration.GetHashCode(); + hashCode = hashCode * -71571866 + Image.GetHashCode(); + hashCode = hashCode * -71571866 + Team.GetHashCode(); + hashCode = hashCode * -71571866 + Name.GetHashCode(); + hashCode = hashCode * -71571866 + Rotation.GetHashCode(); + hashCode = hashCode * -71571866 + UnitName.GetHashCode(); + hashCode = hashCode * -71571866 + VisionRange.GetHashCode(); + return hashCode; + } } } diff --git a/Dota2GSI/Nodes/NeutralItems.cs b/Dota2GSI/Nodes/NeutralItems.cs index 56d2588..04eca22 100644 --- a/Dota2GSI/Nodes/NeutralItems.cs +++ b/Dota2GSI/Nodes/NeutralItems.cs @@ -1,7 +1,6 @@ using Dota2GSI.Nodes.NeutralItemsProvider; using Newtonsoft.Json.Linq; using System; -using System.Collections.Generic; using System.Text.RegularExpressions; namespace Dota2GSI.Nodes @@ -14,12 +13,12 @@ public class NeutralItems : Node /// /// Information about various neutral item tiers. /// - public readonly Dictionary TierInfos = new Dictionary(); + public readonly NodeMap TierInfos = new NodeMap(); /// /// Information about team's neutral items. /// - public readonly Dictionary TeamItems = new Dictionary(); + public readonly NodeMap TeamItems = new NodeMap(); private Regex _tier_id_regex = new Regex(@"tier(\d+)"); private Regex _team_id_regex = new Regex(@"team(\d+)"); @@ -81,5 +80,27 @@ public override string ToString() $"TeamItems: {TeamItems}" + $"]"; } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is NeutralItems other && + TierInfos.Equals(other.TierInfos) && + TeamItems.Equals(other.TeamItems); + } + + /// + public override int GetHashCode() + { + int hashCode = 904745338; + hashCode = hashCode * -700564887 + TierInfos.GetHashCode(); + hashCode = hashCode * -700564887 + TeamItems.GetHashCode(); + return hashCode; + } } } diff --git a/Dota2GSI/Nodes/NeutralItemsProvider/NeutralItem.cs b/Dota2GSI/Nodes/NeutralItemsProvider/NeutralItem.cs index a871e18..2de8ed1 100644 --- a/Dota2GSI/Nodes/NeutralItemsProvider/NeutralItem.cs +++ b/Dota2GSI/Nodes/NeutralItemsProvider/NeutralItem.cs @@ -98,5 +98,33 @@ public override string ToString() $"PlayerID: {PlayerID}" + $"]"; } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is NeutralItem other && + Name.Equals(other.Name) && + Tier == other.Tier && + Charges == other.Charges && + State == other.State && + PlayerID == other.PlayerID; + } + + /// + public override int GetHashCode() + { + int hashCode = 905733096; + hashCode = hashCode * -66160412 + Name.GetHashCode(); + hashCode = hashCode * -66160412 + Tier.GetHashCode(); + hashCode = hashCode * -66160412 + Charges.GetHashCode(); + hashCode = hashCode * -66160412 + State.GetHashCode(); + hashCode = hashCode * -66160412 + PlayerID.GetHashCode(); + return hashCode; + } } } diff --git a/Dota2GSI/Nodes/NeutralItemsProvider/NeutralTierInfo.cs b/Dota2GSI/Nodes/NeutralItemsProvider/NeutralTierInfo.cs index 201af31..f44b24c 100644 --- a/Dota2GSI/Nodes/NeutralItemsProvider/NeutralTierInfo.cs +++ b/Dota2GSI/Nodes/NeutralItemsProvider/NeutralTierInfo.cs @@ -38,5 +38,29 @@ public override string ToString() $"DropAfterTime: {DropAfterTime}" + $"]"; } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is NeutralTierInfo other && + Tier == other.Tier && + MaxCount == other.MaxCount && + DropAfterTime == other.DropAfterTime; + } + + /// + public override int GetHashCode() + { + int hashCode = 919325865; + hashCode = hashCode * -426172320 + Tier.GetHashCode(); + hashCode = hashCode * -426172320 + MaxCount.GetHashCode(); + hashCode = hashCode * -426172320 + DropAfterTime.GetHashCode(); + return hashCode; + } } } diff --git a/Dota2GSI/Nodes/NeutralItemsProvider/TeamNeutralItems.cs b/Dota2GSI/Nodes/NeutralItemsProvider/TeamNeutralItems.cs index 9b0804e..c953daa 100644 --- a/Dota2GSI/Nodes/NeutralItemsProvider/TeamNeutralItems.cs +++ b/Dota2GSI/Nodes/NeutralItemsProvider/TeamNeutralItems.cs @@ -1,6 +1,5 @@ using Newtonsoft.Json.Linq; using System; -using System.Collections.Generic; using System.Text.RegularExpressions; namespace Dota2GSI.Nodes.NeutralItemsProvider @@ -18,7 +17,7 @@ public class TeamNeutralItems : Node /// /// The team neutral items. /// - public readonly Dictionary> TeamItems = new Dictionary>(); + public readonly NodeMap> TeamItems = new NodeMap>(); private Regex _tier_id_regex = new Regex(@"tier(\d+)"); private Regex _item_id_regex = new Regex(@"item(\d+)"); @@ -33,7 +32,7 @@ internal TeamNeutralItems(JObject parsed_data = null) : base(parsed_data) if (!TeamItems.ContainsKey(tier_index)) { - TeamItems.Add(tier_index, new Dictionary()); + TeamItems.Add(tier_index, new NodeMap()); } GetMatchingObjects(obj, _item_id_regex, (Match sub_match, JObject sub_obj) => @@ -61,5 +60,27 @@ public override string ToString() $"TeamItems: {TeamItems}" + $"]"; } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is TeamNeutralItems other && + ItemsFound == other.ItemsFound && + TeamItems.Equals(other.TeamItems); + } + + /// + public override int GetHashCode() + { + int hashCode = 799436177; + hashCode = hashCode * -132257912 + ItemsFound.GetHashCode(); + hashCode = hashCode * -132257912 + TeamItems.GetHashCode(); + return hashCode; + } } } diff --git a/Dota2GSI/Nodes/Node.cs b/Dota2GSI/Nodes/Node.cs index 07763bc..50bb4b8 100644 --- a/Dota2GSI/Nodes/Node.cs +++ b/Dota2GSI/Nodes/Node.cs @@ -1,5 +1,7 @@ using Newtonsoft.Json.Linq; using System; +using System.Collections.Generic; +using System.Linq; using System.Text.RegularExpressions; namespace Dota2GSI.Nodes @@ -216,5 +218,157 @@ public virtual bool IsValid() { return _successfully_retrieved_any_value; } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is Node other && + _ParsedData.Equals(other._ParsedData) && + _successfully_retrieved_any_value.Equals(other._successfully_retrieved_any_value); + } + + /// + public override int GetHashCode() + { + int hashCode = 898763153; + hashCode = hashCode * -405816372 + _ParsedData.GetHashCode(); + hashCode = hashCode * -405816372 + _successfully_retrieved_any_value.GetHashCode(); + return hashCode; + } + } + + /// + /// Helper class,
+ /// A Dictionary class wrapped with proper Equals and GetHashCode functionality.
+ /// Can be safely cast into Dictionary. + ///
+ /// Key type + /// Value type + public class NodeMap : Dictionary + { + public NodeMap() + { + } + + public NodeMap(Dictionary dictionary) + { + foreach (var kvp in dictionary) + { + Add(kvp.Key, kvp.Value); + } + } + + /// + public override string ToString() + { + string return_string = ""; + return_string += "["; + bool first_element = true; + foreach (var kvp in this) + { + if (first_element) + { + first_element = false; + } + else + { + return_string += $", "; + } + + return_string += $"{kvp.Key}: {kvp.Value}"; + } + return_string += "]"; + return return_string; + } + + /// + public override bool Equals(object obj) + { + return obj is NodeMap other && + Count == other.Count && !this.Except(other).Any(); + } + + /// + public override int GetHashCode() + { + int hashCode = 482146548; + + foreach (var kvp in this) + { + hashCode = hashCode * -954782166 + kvp.Key.GetHashCode(); + hashCode = hashCode * -954782166 + kvp.Value.GetHashCode(); + } + + return hashCode; + } + } + + /// + /// Helper class,
+ /// A List class wrapped with proper Equals and GetHashCode functionality.
+ /// Can be safely cast into List. + ///
+ /// Value type + public class NodeList : List + { + public NodeList() + { + } + + public NodeList(IEnumerable list) + { + foreach (var item in list) + { + Add(item); + } + } + + /// + public override string ToString() + { + string return_string = ""; + return_string += "["; + bool first_element = true; + foreach (var item in this) + { + if (first_element) + { + first_element = false; + } + else + { + return_string += $", "; + } + + return_string += $"{item}"; + } + return_string += "]"; + return return_string; + } + + /// + public override bool Equals(object obj) + { + return obj is NodeList other && + Count == other.Count && !this.Except(other).Any(); + } + + /// + public override int GetHashCode() + { + int hashCode = 825543184; + + foreach (var item in this) + { + hashCode = hashCode * -357544921 + item.GetHashCode(); + } + + return hashCode; + } } } diff --git a/Dota2GSI/Nodes/Player.cs b/Dota2GSI/Nodes/Player.cs index a3d903f..e311e5f 100644 --- a/Dota2GSI/Nodes/Player.cs +++ b/Dota2GSI/Nodes/Player.cs @@ -1,7 +1,6 @@ using Dota2GSI.Nodes.PlayerProvider; using Newtonsoft.Json.Linq; using System; -using System.Collections.Generic; using System.Text.RegularExpressions; namespace Dota2GSI.Nodes @@ -19,7 +18,7 @@ public class Player : Node /// /// The team player's details. (SPECTATOR ONLY) /// - public readonly Dictionary> Teams = new Dictionary>(); + public readonly NodeMap> Teams = new NodeMap>(); private Regex _team_id_regex = new Regex(@"team(\d+)"); private Regex _player_id_regex = new Regex(@"player(\d+)"); @@ -36,7 +35,7 @@ internal Player(JObject parsed_data = null) : base(parsed_data) if (!Teams.ContainsKey(team_id)) { - Teams.Add(team_id, new Dictionary()); + Teams.Add(team_id, new NodeMap()); } GetMatchingObjects(obj, _player_id_regex, (Match sub_match, JObject sub_obj) => @@ -61,14 +60,14 @@ internal Player(JObject parsed_data = null) : base(parsed_data) /// /// The team. /// A dictionary of player id mapped to their player details. - public Dictionary GetForTeam(PlayerTeam team) + public NodeMap GetForTeam(PlayerTeam team) { if (Teams.ContainsKey(team)) { return Teams[team]; } - return new Dictionary(); + return new NodeMap(); } /// @@ -106,5 +105,27 @@ public override bool IsValid() { return LocalPlayer.IsValid() || base.IsValid(); } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is Player other && + LocalPlayer.Equals(other.LocalPlayer) && + Teams.Equals(other.Teams); + } + + /// + public override int GetHashCode() + { + int hashCode = 472630013; + hashCode = hashCode * -524857764 + LocalPlayer.GetHashCode(); + hashCode = hashCode * -524857764 + Teams.GetHashCode(); + return hashCode; + } } } diff --git a/Dota2GSI/Nodes/PlayerProvider/PlayerDetails.cs b/Dota2GSI/Nodes/PlayerProvider/PlayerDetails.cs index e35b1bb..8718950 100644 --- a/Dota2GSI/Nodes/PlayerProvider/PlayerDetails.cs +++ b/Dota2GSI/Nodes/PlayerProvider/PlayerDetails.cs @@ -1,6 +1,5 @@ using Newtonsoft.Json.Linq; using System; -using System.Collections.Generic; using System.Text.RegularExpressions; namespace Dota2GSI.Nodes.PlayerProvider @@ -89,7 +88,7 @@ public class PlayerDetails : Node /// /// Player's list of kills. The index corresponds to the player no which can be used to find the playerdetails if in spectator mode using the Teams.AllPlayers property. /// - public readonly Dictionary KillList = new Dictionary(); + public readonly NodeMap KillList = new NodeMap(); /// /// Player's team. @@ -323,5 +322,101 @@ public override string ToString() $"CampsStacked: {CampsStacked}" + $"]"; } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is PlayerDetails other && + SteamID.Equals(other.SteamID) && + AccountID.Equals(other.AccountID) && + Name.Equals(other.Name) && + Activity == other.Activity && + Kills == other.Kills && + Deaths == other.Deaths && + Assists == other.Assists && + LastHits == other.LastHits && + Denies == other.Denies && + KillStreak == other.KillStreak && + CommandsIssued == other.CommandsIssued && + KillList.Equals(other.KillList) && + Team == other.Team && + PlayerSlot == other.PlayerSlot && + PlayerTeamSlot.Equals(other.PlayerTeamSlot) && + Gold == other.Gold && + GoldReliable == other.GoldReliable && + GoldUnreliable == other.GoldUnreliable && + GoldFromHeroKills == other.GoldFromHeroKills && + GoldFromCreepKills == other.GoldFromCreepKills && + GoldFromIncome == other.GoldFromIncome && + GoldFromShared == other.GoldFromShared && + GoldPerMinute == other.GoldPerMinute && + ExperiencePerMinute == other.ExperiencePerMinute && + OnstageSeat == other.OnstageSeat && + NetWorth == other.NetWorth && + HeroDamage == other.HeroDamage && + HeroHealing == other.HeroHealing && + TowerDamage == other.TowerDamage && + SupportGoldSpent == other.SupportGoldSpent && + ConsumableGoldSpent == other.ConsumableGoldSpent && + ItemGoldSpent == other.ItemGoldSpent && + GoldLostToDeath == other.GoldLostToDeath && + GoldSpentOnBuybacks == other.GoldSpentOnBuybacks && + WardsPurchased == other.WardsPurchased && + WardsPlaced == other.WardsPlaced && + WardsDestroyed == other.WardsDestroyed && + RunesActivated == other.RunesActivated && + CampsStacked == other.CampsStacked; + } + + /// + public override int GetHashCode() + { + int hashCode = 602668635; + hashCode = hashCode * -112730515 + SteamID.GetHashCode(); + hashCode = hashCode * -112730515 + AccountID.GetHashCode(); + hashCode = hashCode * -112730515 + Name.GetHashCode(); + hashCode = hashCode * -112730515 + Activity.GetHashCode(); + hashCode = hashCode * -112730515 + Kills.GetHashCode(); + hashCode = hashCode * -112730515 + Deaths.GetHashCode(); + hashCode = hashCode * -112730515 + Assists.GetHashCode(); + hashCode = hashCode * -112730515 + LastHits.GetHashCode(); + hashCode = hashCode * -112730515 + Denies.GetHashCode(); + hashCode = hashCode * -112730515 + KillStreak.GetHashCode(); + hashCode = hashCode * -112730515 + CommandsIssued.GetHashCode(); + hashCode = hashCode * -112730515 + KillList.GetHashCode(); + hashCode = hashCode * -112730515 + Team.GetHashCode(); + hashCode = hashCode * -112730515 + PlayerSlot.GetHashCode(); + hashCode = hashCode * -112730515 + PlayerTeamSlot.GetHashCode(); + hashCode = hashCode * -112730515 + Gold.GetHashCode(); + hashCode = hashCode * -112730515 + GoldReliable.GetHashCode(); + hashCode = hashCode * -112730515 + GoldUnreliable.GetHashCode(); + hashCode = hashCode * -112730515 + GoldFromHeroKills.GetHashCode(); + hashCode = hashCode * -112730515 + GoldFromCreepKills.GetHashCode(); + hashCode = hashCode * -112730515 + GoldFromIncome.GetHashCode(); + hashCode = hashCode * -112730515 + GoldFromShared.GetHashCode(); + hashCode = hashCode * -112730515 + GoldPerMinute.GetHashCode(); + hashCode = hashCode * -112730515 + ExperiencePerMinute.GetHashCode(); + hashCode = hashCode * -112730515 + OnstageSeat.GetHashCode(); + hashCode = hashCode * -112730515 + NetWorth.GetHashCode(); + hashCode = hashCode * -112730515 + HeroDamage.GetHashCode(); + hashCode = hashCode * -112730515 + HeroHealing.GetHashCode(); + hashCode = hashCode * -112730515 + TowerDamage.GetHashCode(); + hashCode = hashCode * -112730515 + SupportGoldSpent.GetHashCode(); + hashCode = hashCode * -112730515 + ConsumableGoldSpent.GetHashCode(); + hashCode = hashCode * -112730515 + ItemGoldSpent.GetHashCode(); + hashCode = hashCode * -112730515 + GoldLostToDeath.GetHashCode(); + hashCode = hashCode * -112730515 + GoldSpentOnBuybacks.GetHashCode(); + hashCode = hashCode * -112730515 + WardsPurchased.GetHashCode(); + hashCode = hashCode * -112730515 + WardsPlaced.GetHashCode(); + hashCode = hashCode * -112730515 + WardsDestroyed.GetHashCode(); + hashCode = hashCode * -112730515 + RunesActivated.GetHashCode(); + hashCode = hashCode * -112730515 + CampsStacked.GetHashCode(); + return hashCode; + } } } diff --git a/Dota2GSI/Nodes/Provider.cs b/Dota2GSI/Nodes/Provider.cs index b5bb9cd..1a73e12 100644 --- a/Dota2GSI/Nodes/Provider.cs +++ b/Dota2GSI/Nodes/Provider.cs @@ -44,6 +44,32 @@ public override string ToString() $"Version: {Version}, " + $"TimeStamp: {TimeStamp}" + $"]"; + } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is Provider other && + Name.Equals(other.Name) && + AppID == other.AppID && + Version == other.Version && + TimeStamp.Equals(other.TimeStamp); + } + + /// + public override int GetHashCode() + { + int hashCode = 464630987; + hashCode = hashCode * -987549067 + Name.GetHashCode(); + hashCode = hashCode * -987549067 + AppID.GetHashCode(); + hashCode = hashCode * -987549067 + Version.GetHashCode(); + hashCode = hashCode * -987549067 + TimeStamp.GetHashCode(); + return hashCode; } } } diff --git a/Dota2GSI/Nodes/Roshan.cs b/Dota2GSI/Nodes/Roshan.cs index 33a6006..ced02b7 100644 --- a/Dota2GSI/Nodes/Roshan.cs +++ b/Dota2GSI/Nodes/Roshan.cs @@ -75,5 +75,39 @@ public override string ToString() $"Drops: {Drops}" + $"]"; } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is Roshan other && + Health == other.Health && + MaxHealth == other.MaxHealth && + IsAlive == other.IsAlive && + SpawnPhase == other.SpawnPhase && + PhaseTimeRemaining == other.PhaseTimeRemaining && + Location.Equals(other.Location) && + Rotation == other.Rotation && + Drops.Equals(other.Drops); + } + + /// + public override int GetHashCode() + { + int hashCode = 289605977; + hashCode = hashCode * -839892812 + Health.GetHashCode(); + hashCode = hashCode * -839892812 + MaxHealth.GetHashCode(); + hashCode = hashCode * -839892812 + IsAlive.GetHashCode(); + hashCode = hashCode * -839892812 + SpawnPhase.GetHashCode(); + hashCode = hashCode * -839892812 + PhaseTimeRemaining.GetHashCode(); + hashCode = hashCode * -839892812 + Location.GetHashCode(); + hashCode = hashCode * -839892812 + Rotation.GetHashCode(); + hashCode = hashCode * -839892812 + Drops.GetHashCode(); + return hashCode; + } } } diff --git a/Dota2GSI/Nodes/RoshanProvider/ItemsDrop.cs b/Dota2GSI/Nodes/RoshanProvider/ItemsDrop.cs index 86477fe..1c7005d 100644 --- a/Dota2GSI/Nodes/RoshanProvider/ItemsDrop.cs +++ b/Dota2GSI/Nodes/RoshanProvider/ItemsDrop.cs @@ -1,6 +1,5 @@ using Newtonsoft.Json.Linq; using System; -using System.Collections.Generic; using System.Text.RegularExpressions; namespace Dota2GSI.Nodes.RoshanProvider @@ -13,7 +12,7 @@ public class ItemsDrop : Node /// /// Items that can drop. /// - public readonly Dictionary Items = new Dictionary(); + public readonly NodeMap Items = new NodeMap(); private Regex _item_regex = new Regex(@"item(\d+)"); internal ItemsDrop(JObject parsed_data = null) : base(parsed_data) @@ -33,5 +32,25 @@ public override string ToString() $"Items: {Items}" + $"]"; } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is ItemsDrop other && + Items.Equals(other.Items); + } + + /// + public override int GetHashCode() + { + int hashCode = 771247438; + hashCode = hashCode * -122023451 + Items.GetHashCode(); + return hashCode; + } } } diff --git a/Dota2GSI/Nodes/Wearables.cs b/Dota2GSI/Nodes/Wearables.cs index abee127..fa9b613 100644 --- a/Dota2GSI/Nodes/Wearables.cs +++ b/Dota2GSI/Nodes/Wearables.cs @@ -1,7 +1,6 @@ using Dota2GSI.Nodes.WearablesProvider; using Newtonsoft.Json.Linq; using System; -using System.Collections.Generic; using System.Text.RegularExpressions; namespace Dota2GSI.Nodes @@ -19,7 +18,7 @@ public class Wearables : Node /// /// The team players wearables. (SPECTATOR ONLY) /// - public readonly Dictionary> Teams = new Dictionary>(); + public readonly NodeMap> Teams = new NodeMap>(); private Regex _team_id_regex = new Regex(@"team(\d+)"); private Regex _player_id_regex = new Regex(@"player(\d+)"); @@ -36,7 +35,7 @@ internal Wearables(JObject parsed_data = null) : base(parsed_data) if (!Teams.ContainsKey(team_id)) { - Teams.Add(team_id, new Dictionary()); + Teams.Add(team_id, new NodeMap()); } GetMatchingObjects(parsed_data, _player_id_regex, (Match sub_match, JObject sub_obj) => @@ -62,14 +61,14 @@ internal Wearables(JObject parsed_data = null) : base(parsed_data) /// /// The team. /// A dictionary of player id mapped to their wearables. - public Dictionary GetForTeam(PlayerTeam team) + public NodeMap GetForTeam(PlayerTeam team) { if (Teams.ContainsKey(team)) { return Teams[team]; } - return new Dictionary(); + return new NodeMap(); } /// @@ -107,5 +106,27 @@ public override bool IsValid() { return LocalPlayer.IsValid() || base.IsValid(); } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is Wearables other && + LocalPlayer.Equals(other.LocalPlayer) && + Teams.Equals(other.Teams); + } + + /// + public override int GetHashCode() + { + int hashCode = 894234507; + hashCode = hashCode * -274381118 + LocalPlayer.GetHashCode(); + hashCode = hashCode * -274381118 + Teams.GetHashCode(); + return hashCode; + } } } diff --git a/Dota2GSI/Nodes/WearablesProvider/PlayerWearables.cs b/Dota2GSI/Nodes/WearablesProvider/PlayerWearables.cs index 1f38d03..6330760 100644 --- a/Dota2GSI/Nodes/WearablesProvider/PlayerWearables.cs +++ b/Dota2GSI/Nodes/WearablesProvider/PlayerWearables.cs @@ -1,6 +1,5 @@ using Newtonsoft.Json.Linq; using System; -using System.Collections.Generic; using System.Text.RegularExpressions; namespace Dota2GSI.Nodes.WearablesProvider @@ -13,7 +12,7 @@ public class PlayerWearables : Node /// /// The dictionary of player's wearable items. /// - public readonly Dictionary Wearables = new Dictionary(); + public readonly NodeMap Wearables = new NodeMap(); private Regex _wearable_regex = new Regex(@"wearable(\d+)"); private Regex _style_regex = new Regex(@"style(\d+)"); @@ -57,6 +56,26 @@ public override string ToString() return $"[" + $"Wearables: {Wearables}" + $"]"; + } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is PlayerWearables other && + Wearables.Equals(other.Wearables); + } + + /// + public override int GetHashCode() + { + int hashCode = 954667287; + hashCode = hashCode * -711254284 + Wearables.GetHashCode(); + return hashCode; } } } diff --git a/Dota2GSI/Nodes/WearablesProvider/WearableItem.cs b/Dota2GSI/Nodes/WearablesProvider/WearableItem.cs index 4ef64d2..1c25deb 100644 --- a/Dota2GSI/Nodes/WearablesProvider/WearableItem.cs +++ b/Dota2GSI/Nodes/WearablesProvider/WearableItem.cs @@ -29,6 +29,28 @@ public override string ToString() $"ID: {ID}, " + $"Style: {Style}" + $"]"; + } + + /// + public override bool Equals(object obj) + { + if (null == obj) + { + return false; + } + + return obj is WearableItem other && + ID == other.ID && + Style == other.Style; + } + + /// + public override int GetHashCode() + { + int hashCode = 652470603; + hashCode = hashCode * -397083684 + ID.GetHashCode(); + hashCode = hashCode * -397083684 + Style.GetHashCode(); + return hashCode; } } } From 6c315843f3ead5e7bc4ddb54a7feea872b2378cb Mon Sep 17 00:00:00 2001 From: Anton Pupkov Date: Mon, 15 Jan 2024 15:49:04 -0800 Subject: [PATCH 02/24] Add EventDispatcher implementation --- Dota2GSI/CMakeLists.txt | 2 + Dota2GSI/EventDispatcher.cs | 151 ++++++++++++++++++++++++++++++++++++ Dota2GSI/EventHandler.cs | 14 ++++ 3 files changed, 167 insertions(+) create mode 100644 Dota2GSI/EventDispatcher.cs create mode 100644 Dota2GSI/EventHandler.cs diff --git a/Dota2GSI/CMakeLists.txt b/Dota2GSI/CMakeLists.txt index 23e9dc7..98a50ea 100644 --- a/Dota2GSI/CMakeLists.txt +++ b/Dota2GSI/CMakeLists.txt @@ -16,6 +16,8 @@ PROJECT(${PRODUCT} VERSION ${PRODUCT_VERSION} LANGUAGES CSharp) INCLUDE(CSharpUtilities) SET(SOURCES + EventDispatcher.cs + EventHandler.cs GameState.cs GameStateListener.cs Nodes/Roshan.cs diff --git a/Dota2GSI/EventDispatcher.cs b/Dota2GSI/EventDispatcher.cs new file mode 100644 index 0000000..db8313a --- /dev/null +++ b/Dota2GSI/EventDispatcher.cs @@ -0,0 +1,151 @@ +using Dota2GSI.EventMessages; +using System; +using System.Collections.Generic; +using System.ComponentModel; + +namespace Dota2GSI +{ + public class EventDispatcher where T : BaseEvent + { + /// + /// Delegate for handing game events. + /// + /// The new game event. + public delegate void GameEventHandler(T game_event); + + /// + /// Event for handing game events. + /// + public event GameEventHandler GameEvent = delegate { }; + + private readonly object subscriptions_lock = new object(); + + private Dictionary>> subscriptions = new Dictionary>>(); + private Dictionary>> pre_processors = new Dictionary>>(); + + public EventDispatcher() + { + Subscribe(RaiseOnGameEventHandler); + } + + ~EventDispatcher() + { + Unsubscribe(RaiseOnGameEventHandler); + } + + private void RaiseOnGameEventHandler(T game_event) + { + foreach (Delegate d in GameEvent.GetInvocationList()) + { + if (d.Target is ISynchronizeInvoke) + { + (d.Target as ISynchronizeInvoke).BeginInvoke(d, new object[] { game_event }); + } + else + { + d.DynamicInvoke(game_event); + } + } + } + + public void RegisterPreProcessor(Func callback) where MessageType : T + { + + var event_type = typeof(MessageType); + + lock (subscriptions_lock) + { + if (!pre_processors.ContainsKey(event_type)) + { + pre_processors.Add(event_type, new HashSet>()); + } + + pre_processors[event_type].Add(callback); + } + } + + public void UnregisterPreProcessor(Func callback) where MessageType : T + { + + var event_type = typeof(MessageType); + + lock (subscriptions_lock) + { + if (!subscriptions.ContainsKey(event_type)) + { + return; + } + + pre_processors[event_type].Remove(callback); + } + } + + + public void Subscribe(Action callback) where MessageType : T + { + var event_type = typeof(MessageType); + + lock (subscriptions_lock) + { + if (!subscriptions.ContainsKey(event_type)) + { + subscriptions.Add(event_type, new HashSet>()); + } + + subscriptions[event_type].Add(callback); + } + } + + public void Unsubscribe(Action callback) where MessageType : T + { + var event_type = typeof(MessageType); + + lock (subscriptions_lock) + { + if (!subscriptions.ContainsKey(event_type)) + { + return; + } + + subscriptions[event_type].Remove(callback); + } + } + + public void Broadcast(MessageType message) where MessageType : T + { + var event_type = typeof(MessageType); + T msg = message; + + lock (subscriptions_lock) + { + if (subscriptions.ContainsKey(event_type)) + { + // Run pre-processors first + if (pre_processors.ContainsKey(event_type)) + { + foreach (var pre_processor in pre_processors[event_type]) + { + msg = pre_processor(msg); + + if (msg == null) + { + // The message was handled. + return; + } + } + } + + foreach (var callback in subscriptions[event_type]) + { + callback.Invoke(msg); + } + } + + if (event_type != typeof(T)) + { + Broadcast(msg); + } + } + } + } +} diff --git a/Dota2GSI/EventHandler.cs b/Dota2GSI/EventHandler.cs new file mode 100644 index 0000000..8be4515 --- /dev/null +++ b/Dota2GSI/EventHandler.cs @@ -0,0 +1,14 @@ +using Dota2GSI.EventMessages; + +namespace Dota2GSI +{ + public class EventHandler where T : BaseEvent + { + protected EventDispatcher dispatcher = new EventDispatcher(); + + public EventHandler(ref EventDispatcher EventDispatcher) + { + dispatcher = EventDispatcher; + } + } +} From d70f003979dd1cee0a2d57c77bacb10be92191eb Mon Sep 17 00:00:00 2001 From: Anton Pupkov Date: Mon, 15 Jan 2024 15:53:07 -0800 Subject: [PATCH 03/24] Add Dota 2 Game Event messages --- Dota2GSI/CMakeLists.txt | 20 +++ Dota2GSI/EventMessages/AbilitiesEvents.cs | 55 ++++++ Dota2GSI/EventMessages/AuthEvents.cs | 14 ++ Dota2GSI/EventMessages/BaseEvent.cs | 7 + Dota2GSI/EventMessages/BuildingsEvents.cs | 167 +++++++++++++++++++ Dota2GSI/EventMessages/CouriersEvents.cs | 35 ++++ Dota2GSI/EventMessages/DotaGameEvent.cs | 10 ++ Dota2GSI/EventMessages/DraftEvents.cs | 25 +++ Dota2GSI/EventMessages/EventsEvents.cs | 45 +++++ Dota2GSI/EventMessages/HeroEvents.cs | 135 +++++++++++++++ Dota2GSI/EventMessages/ItemsEvents.cs | 25 +++ Dota2GSI/EventMessages/LeagueEvents.cs | 14 ++ Dota2GSI/EventMessages/MapEvents.cs | 128 ++++++++++++++ Dota2GSI/EventMessages/MinimapEvents.cs | 35 ++++ Dota2GSI/EventMessages/NeutralItemsEvents.cs | 25 +++ Dota2GSI/EventMessages/PlayerEvents.cs | 145 ++++++++++++++++ Dota2GSI/EventMessages/ProviderEvents.cs | 14 ++ Dota2GSI/EventMessages/RoshanEvents.cs | 14 ++ Dota2GSI/EventMessages/UpdateEvent.cs | 132 +++++++++++++++ Dota2GSI/EventMessages/WearablesEvents.cs | 25 +++ 20 files changed, 1070 insertions(+) create mode 100644 Dota2GSI/EventMessages/AbilitiesEvents.cs create mode 100644 Dota2GSI/EventMessages/AuthEvents.cs create mode 100644 Dota2GSI/EventMessages/BaseEvent.cs create mode 100644 Dota2GSI/EventMessages/BuildingsEvents.cs create mode 100644 Dota2GSI/EventMessages/CouriersEvents.cs create mode 100644 Dota2GSI/EventMessages/DotaGameEvent.cs create mode 100644 Dota2GSI/EventMessages/DraftEvents.cs create mode 100644 Dota2GSI/EventMessages/EventsEvents.cs create mode 100644 Dota2GSI/EventMessages/HeroEvents.cs create mode 100644 Dota2GSI/EventMessages/ItemsEvents.cs create mode 100644 Dota2GSI/EventMessages/LeagueEvents.cs create mode 100644 Dota2GSI/EventMessages/MapEvents.cs create mode 100644 Dota2GSI/EventMessages/MinimapEvents.cs create mode 100644 Dota2GSI/EventMessages/NeutralItemsEvents.cs create mode 100644 Dota2GSI/EventMessages/PlayerEvents.cs create mode 100644 Dota2GSI/EventMessages/ProviderEvents.cs create mode 100644 Dota2GSI/EventMessages/RoshanEvents.cs create mode 100644 Dota2GSI/EventMessages/UpdateEvent.cs create mode 100644 Dota2GSI/EventMessages/WearablesEvents.cs diff --git a/Dota2GSI/CMakeLists.txt b/Dota2GSI/CMakeLists.txt index 98a50ea..1680607 100644 --- a/Dota2GSI/CMakeLists.txt +++ b/Dota2GSI/CMakeLists.txt @@ -20,6 +20,26 @@ SET(SOURCES EventHandler.cs GameState.cs GameStateListener.cs + GameStateHandler.cs + EventMessages/AbilitiesEvents.cs + EventMessages/AuthEvents.cs + EventMessages/BaseEvent.cs + EventMessages/BuildingsEvents.cs + EventMessages/CouriersEvents.cs + EventMessages/DotaGameEvent.cs + EventMessages/DraftEvents.cs + EventMessages/EventsEvents.cs + EventMessages/HeroEvents.cs + EventMessages/ItemsEvents.cs + EventMessages/LeagueEvents.cs + EventMessages/MapEvents.cs + EventMessages/MinimapEvents.cs + EventMessages/NeutralItemsEvents.cs + EventMessages/PlayerEvents.cs + EventMessages/ProviderEvents.cs + EventMessages/RoshanEvents.cs + EventMessages/UpdateEvent.cs + EventMessages/WearablesEvents.cs Nodes/Roshan.cs Nodes/HeroProvider/HeroDetails.cs Nodes/CouriersProvider/Courier.cs diff --git a/Dota2GSI/EventMessages/AbilitiesEvents.cs b/Dota2GSI/EventMessages/AbilitiesEvents.cs new file mode 100644 index 0000000..5192352 --- /dev/null +++ b/Dota2GSI/EventMessages/AbilitiesEvents.cs @@ -0,0 +1,55 @@ +using Dota2GSI.Nodes; +using Dota2GSI.Nodes.AbilitiesProvider; + +namespace Dota2GSI.EventMessages +{ + /// + /// Event for overall Hero Abilities update. + /// + public class AbilitiesStateUpdated : UpdateEvent + { + public AbilitiesStateUpdated(Abilities new_value, Abilities previous_value) : base(new_value, previous_value) + { + } + } + + /// + /// Event for specific Hero Ability Details change. + /// + public class AbilityDetailsChanged : PlayerUpdateEvent + { + public AbilityDetailsChanged(AbilityDetails new_value, AbilityDetails previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + { + } + } + + /// + /// Event for specific Hero Ability addition. + /// + public class AbilityAdded : PlayerValueEvent + { + public AbilityAdded(Ability value, int player_id = -1) : base(value, player_id) + { + } + } + + /// + /// Event for specific Hero Ability removal. + /// + public class AbilityRemoved : PlayerValueEvent + { + public AbilityRemoved(Ability value, int player_id = -1) : base(value, player_id) + { + } + } + + /// + /// Event for specific Hero Ability update. + /// + public class AbilityUpdated : PlayerUpdateEvent + { + public AbilityUpdated(Ability new_value, Ability previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + { + } + } +} diff --git a/Dota2GSI/EventMessages/AuthEvents.cs b/Dota2GSI/EventMessages/AuthEvents.cs new file mode 100644 index 0000000..bee0d94 --- /dev/null +++ b/Dota2GSI/EventMessages/AuthEvents.cs @@ -0,0 +1,14 @@ +using Dota2GSI.Nodes; + +namespace Dota2GSI.EventMessages +{ + /// + /// Event for overall Auth update. + /// + public class AuthStateUpdated : UpdateEvent + { + public AuthStateUpdated(Auth new_value, Auth previous_value) : base(new_value, previous_value) + { + } + } +} diff --git a/Dota2GSI/EventMessages/BaseEvent.cs b/Dota2GSI/EventMessages/BaseEvent.cs new file mode 100644 index 0000000..fab2e4f --- /dev/null +++ b/Dota2GSI/EventMessages/BaseEvent.cs @@ -0,0 +1,7 @@ + +namespace Dota2GSI.EventMessages +{ + public interface BaseEvent + { + } +} diff --git a/Dota2GSI/EventMessages/BuildingsEvents.cs b/Dota2GSI/EventMessages/BuildingsEvents.cs new file mode 100644 index 0000000..eed272e --- /dev/null +++ b/Dota2GSI/EventMessages/BuildingsEvents.cs @@ -0,0 +1,167 @@ +using Dota2GSI.Nodes; +using Dota2GSI.Nodes.BuildingsProvider; + +namespace Dota2GSI.EventMessages +{ + /// + /// Event for overall Buildings update. + /// + public class BuildingsStateUpdated : UpdateEvent + { + public BuildingsStateUpdated(Buildings new_value, Buildings previous_value) : base(new_value, previous_value) + { + } + } + + /// + /// Event for specific team Building Layout update. + /// + public class BuildingsLayoutUpdated : TeamUpdateEvent + { + public BuildingsLayoutUpdated(BuildingLayout new_value, BuildingLayout previous_value, PlayerTeam team) : base(new_value, previous_value, team) + { + } + } + + /// + /// Enum for building locations. + /// + public enum BuildingLocation + { + /// + /// Undefined. + /// + Undefined, + + /// + /// Top lane building. + /// + TopLane, + + /// + /// Middle lane building. + /// + MiddleLane, + + /// + /// Bottom lane building. + /// + BottomLane, + + /// + /// Base building. + /// + Base + } + + /// + /// Event for specific Building update. + /// + public class BuildingUpdated : EntityUpdateEvent + { + public BuildingUpdated(Building new_value, Building previous_value, string entity_id) : base(new_value, previous_value, entity_id) + { + } + } + + /// + /// Event for specific team Building update. + /// + public class TeamBuildingUpdated : BuildingUpdated + { + public readonly PlayerTeam Team; + + /// + /// The location of this building. + /// + public readonly BuildingLocation Location; + + public TeamBuildingUpdated(Building new_value, Building previous_value, string entity_id, PlayerTeam team, BuildingLocation location) : base(new_value, previous_value, entity_id) + { + Team = team; + Location = location; + } + } + + /// + /// Event for specific team Building destruction. + /// + public class TeamBuildingDestroyed : TeamBuildingUpdated + { + public TeamBuildingDestroyed(Building new_value, Building previous_value, string entity_id, PlayerTeam team, BuildingLocation location) : base(new_value, previous_value, entity_id, team, location) + { + } + } + + /// + /// Event for specific team Tower update. + /// + public class TowerUpdated : TeamBuildingUpdated + { + public TowerUpdated(Building new_value, Building previous_value, string entity_id, PlayerTeam team, BuildingLocation location) : base(new_value, previous_value, entity_id, team, location) + { + } + } + + /// + /// Event for specific team Tower destruction. + /// + public class TowerDestroyed : TeamBuildingDestroyed + { + public TowerDestroyed(Building new_value, Building previous_value, string entity_id, PlayerTeam team, BuildingLocation location) : base(new_value, previous_value, entity_id, team, location) + { + } + } + + /// + /// Event for specific team Racks update. + /// + public class RacksUpdated : TeamBuildingUpdated + { + /// + /// The affected racks type. + /// + public readonly RacksType RacksType; + + public RacksUpdated(Building new_value, Building previous_value, RacksType racks_type, string entity_id, PlayerTeam team, BuildingLocation location) : base(new_value, previous_value, entity_id, team, location) + { + RacksType = racks_type; + } + } + + /// + /// Event for specific team Racks destruction. + /// + public class RacksDestroyed : TeamBuildingDestroyed + { + /// + /// The affected racks type. + /// + public readonly RacksType RacksType; + + public RacksDestroyed(Building new_value, Building previous_value, RacksType racks_type, string entity_id, PlayerTeam team, BuildingLocation location) : base(new_value, previous_value, entity_id, team, location) + { + RacksType = racks_type; + } + } + + /// + /// Event for specific team Ancient update. + /// + public class AncientUpdated : TeamBuildingUpdated + { + public AncientUpdated(Building new_value, Building previous_value, string entity_id, PlayerTeam team, BuildingLocation location) : base(new_value, previous_value, entity_id, team, location) + { + } + } + + /// + /// Event for specific team Ancient destruction. + /// + public class AncientDestroyed : TeamBuildingDestroyed + { + public AncientDestroyed(Building new_value, Building previous_value, string entity_id, PlayerTeam team, BuildingLocation location) : base(new_value, previous_value, entity_id, team, location) + { + } + } +} diff --git a/Dota2GSI/EventMessages/CouriersEvents.cs b/Dota2GSI/EventMessages/CouriersEvents.cs new file mode 100644 index 0000000..5f4a652 --- /dev/null +++ b/Dota2GSI/EventMessages/CouriersEvents.cs @@ -0,0 +1,35 @@ +using Dota2GSI.Nodes; +using Dota2GSI.Nodes.CouriersProvider; + +namespace Dota2GSI.EventMessages +{ + /// + /// Event for overall Couriers update. + /// + public class CouriersStateUpdated : UpdateEvent + { + public CouriersStateUpdated(Couriers new_value, Couriers previous_value) : base(new_value, previous_value) + { + } + } + + /// + /// Event for specific player's Courier update. + /// + public class CourierUpdated : PlayerUpdateEvent + { + public CourierUpdated(Courier new_value, Courier previous_value, int player_id) : base(new_value, previous_value, player_id) + { + } + } + + /// + /// Event for specific team's Courier update. + /// + public class TeamCourierUpdated : TeamUpdateEvent + { + public TeamCourierUpdated(Courier new_value, Courier previous_value, PlayerTeam team) : base(new_value, previous_value, team) + { + } + } +} diff --git a/Dota2GSI/EventMessages/DotaGameEvent.cs b/Dota2GSI/EventMessages/DotaGameEvent.cs new file mode 100644 index 0000000..d02082f --- /dev/null +++ b/Dota2GSI/EventMessages/DotaGameEvent.cs @@ -0,0 +1,10 @@ + +namespace Dota2GSI.EventMessages +{ + public class DotaGameEvent : BaseEvent + { + public DotaGameEvent() : base() + { + } + } +} diff --git a/Dota2GSI/EventMessages/DraftEvents.cs b/Dota2GSI/EventMessages/DraftEvents.cs new file mode 100644 index 0000000..556c478 --- /dev/null +++ b/Dota2GSI/EventMessages/DraftEvents.cs @@ -0,0 +1,25 @@ +using Dota2GSI.Nodes; +using Dota2GSI.Nodes.DraftProvider; + +namespace Dota2GSI.EventMessages +{ + /// + /// Event for overall Draft update. + /// + public class DraftStateUpdated : UpdateEvent + { + public DraftStateUpdated(Draft new_value, Draft previous_value) : base(new_value, previous_value) + { + } + } + + /// + /// Event for specific team Draft Details update. + /// + public class TeamDraftDetailsUpdated : TeamUpdateEvent + { + public TeamDraftDetailsUpdated(DraftDetails new_value, DraftDetails previous_value, PlayerTeam team) : base(new_value, previous_value, team) + { + } + } +} diff --git a/Dota2GSI/EventMessages/EventsEvents.cs b/Dota2GSI/EventMessages/EventsEvents.cs new file mode 100644 index 0000000..820c21f --- /dev/null +++ b/Dota2GSI/EventMessages/EventsEvents.cs @@ -0,0 +1,45 @@ +using Dota2GSI.Nodes; +using Dota2GSI.Nodes.EventsProvider; + +namespace Dota2GSI.EventMessages +{ + /// + /// Event for overall Event update. + /// + public class EventsStateUpdated : UpdateEvent + { + public EventsStateUpdated(Events new_value, Events previous_value) : base(new_value, previous_value) + { + } + } + + /// + /// Event for Game Event. + /// + public class GameEvent : ValueEvent + { + public GameEvent(Event value) : base(value) + { + } + } + + /// + /// Event for specific team Event. + /// + public class TeamEvent : TeamValueEvent + { + public TeamEvent(Event value, PlayerTeam team) : base(value, team) + { + } + } + + /// + /// Event for specific player Event. + /// + public class PlayerEvent : PlayerValueEvent + { + public PlayerEvent(Event value, int player_id) : base(value, player_id) + { + } + } +} diff --git a/Dota2GSI/EventMessages/HeroEvents.cs b/Dota2GSI/EventMessages/HeroEvents.cs new file mode 100644 index 0000000..12abf6f --- /dev/null +++ b/Dota2GSI/EventMessages/HeroEvents.cs @@ -0,0 +1,135 @@ +using Dota2GSI.Nodes; +using Dota2GSI.Nodes.HeroProvider; + +namespace Dota2GSI.EventMessages +{ + /// + /// Event for overall Hero update. + /// + public class HeroStateUpdated : UpdateEvent + { + public HeroStateUpdated(Hero new_value, Hero previous_value) : base(new_value, previous_value) + { + } + } + + /// + /// Event for specific player's Hero Details update. + /// + public class HeroDetailsChanged : PlayerUpdateEvent + { + public HeroDetailsChanged(HeroDetails new_value, HeroDetails previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + { + } + } + + /// + /// Event for specific player's Hero level update. + /// + public class HeroLevelChanged : PlayerUpdateEvent + { + public HeroLevelChanged(int new_value, int previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + { + } + } + + /// + /// Event for specific player's Hero health update. + /// + public class HeroHealthChanged : PlayerUpdateEvent + { + public HeroHealthChanged(int new_value, int previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + { + } + } + + /// + /// Event for specific player's Hero death. + /// + public class HeroDied : HeroHealthChanged + { + public HeroDied(int new_value, int previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + { + } + } + + /// + /// Event for specific player's Hero respawn. + /// + public class HeroRespawned : HeroHealthChanged + { + public HeroRespawned(int new_value, int previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + { + } + } + + /// + /// Event for specific player's Hero taking damage. + /// + public class HeroTookDamage : HeroHealthChanged + { + public HeroTookDamage(int new_value, int previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + { + } + } + + /// + /// Event for specific player's Hero mana update. + /// + public class HeroManaChanged : PlayerUpdateEvent + { + public HeroManaChanged(int new_value, int previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + { + } + } + + /// + /// Event for specific player's Hero state update. + /// + public class HeroStateChanged : PlayerUpdateEvent + { + public HeroStateChanged(HeroState new_value, HeroState previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + { + } + } + + /// + /// Event for specific player's Hero mute update. + /// + public class HeroMuteStateChanged : PlayerUpdateEvent + { + public HeroMuteStateChanged(bool new_value, bool previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + { + } + } + + /// + /// Event for specific player's Hero selection. + /// + public class HeroSelectedChanged : PlayerUpdateEvent + { + public HeroSelectedChanged(bool new_value, bool previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + { + } + } + + /// + /// Event for specific player's Hero Talent Tree update. + /// + public class HeroTalentTreeChanged : PlayerUpdateEvent + { + public HeroTalentTreeChanged(TalentTreeSpec[] new_value, TalentTreeSpec[] previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + { + } + } + + /// + /// Event for specific player's Hero Attributes Level update. + /// + public class HeroAttributesLevelChanged : PlayerUpdateEvent + { + public HeroAttributesLevelChanged(int new_value, int previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + { + } + } +} diff --git a/Dota2GSI/EventMessages/ItemsEvents.cs b/Dota2GSI/EventMessages/ItemsEvents.cs new file mode 100644 index 0000000..9b40c12 --- /dev/null +++ b/Dota2GSI/EventMessages/ItemsEvents.cs @@ -0,0 +1,25 @@ +using Dota2GSI.Nodes; +using Dota2GSI.Nodes.ItemsProvider; + +namespace Dota2GSI.EventMessages +{ + /// + /// Event for overall Items update. + /// + public class ItemsStateUpdated : UpdateEvent + { + public ItemsStateUpdated(Items new_value, Items previous_value) : base(new_value, previous_value) + { + } + } + + /// + /// Event for specific player's Item Details update. + /// + public class ItemDetailsChanged : PlayerUpdateEvent + { + public ItemDetailsChanged(ItemDetails new_value, ItemDetails previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + { + } + } +} diff --git a/Dota2GSI/EventMessages/LeagueEvents.cs b/Dota2GSI/EventMessages/LeagueEvents.cs new file mode 100644 index 0000000..c77c658 --- /dev/null +++ b/Dota2GSI/EventMessages/LeagueEvents.cs @@ -0,0 +1,14 @@ +using Dota2GSI.Nodes; + +namespace Dota2GSI.EventMessages +{ + /// + /// Event for overall League update. + /// + public class LeagueStateUpdated : UpdateEvent + { + public LeagueStateUpdated(League new_value, League previous_value) : base(new_value, previous_value) + { + } + } +} diff --git a/Dota2GSI/EventMessages/MapEvents.cs b/Dota2GSI/EventMessages/MapEvents.cs new file mode 100644 index 0000000..6caa13b --- /dev/null +++ b/Dota2GSI/EventMessages/MapEvents.cs @@ -0,0 +1,128 @@ +using Dota2GSI.Nodes; + +namespace Dota2GSI.EventMessages +{ + /// + /// Event for overall Map update. + /// + public class MapStateUpdated : UpdateEvent + { + public MapStateUpdated(Map new_value, Map previous_value) : base(new_value, previous_value) + { + } + } + + /// + /// Event for Time of Day change. + /// + public class TimeOfDayChanged : DotaGameEvent + { + /// + /// True when day time, false when night time. + /// + public readonly bool IsDaytime; + + /// + /// True when nightstalker night, false otherwise. + /// + public readonly bool IsNightstalkerNight; + + public TimeOfDayChanged(bool is_day, bool is_nightstalker_night) : base() + { + IsDaytime = is_day; + IsNightstalkerNight = is_nightstalker_night; + } + } + + /// + /// Event for specific team's score change. + /// + public class TeamScoreChanged : TeamUpdateEvent + { + public TeamScoreChanged(int new_value, int previous_value, PlayerTeam team) : base(new_value, previous_value, team) + { + } + } + + /// + /// Event for Game State change. + /// + public class GameStateChanged : UpdateEvent + { + public GameStateChanged(DOTA_GameState new_value, DOTA_GameState previous_value) : base(new_value, previous_value) + { + } + } + + /// + /// Event for Game Pause State change. + /// + public class PauseStateChanged : UpdateEvent + { + public PauseStateChanged(bool new_value, bool previous_value) : base(new_value, previous_value) + { + } + } + + /// + /// Event for Game Paused. + /// + public class GamePaused : DotaGameEvent + { + public GamePaused() : base() + { + } + } + + /// + /// Event for Game Resumed. + /// + public class GameResumed : DotaGameEvent + { + public GameResumed() : base() + { + } + } + + /// + /// Event for specific team Victory. + /// + public class TeamVictory : DotaGameEvent + { + /// + /// The winning team. + /// + public readonly PlayerTeam Team; + + public TeamVictory(PlayerTeam team) : base() + { + Team = team; + } + } + + /// + /// Event for specific team Defeat. + /// + public class TeamDefeat : DotaGameEvent + { + /// + /// The losing team. + /// + public readonly PlayerTeam Team; + + public TeamDefeat(PlayerTeam team) : base() + { + Team = team; + } + } + + /// + /// Event for Roshan State change. + /// + public class RoshanStateChanged : UpdateEvent + { + public RoshanStateChanged(RoshanState new_value, RoshanState previous_value) : base(new_value, previous_value) + { + } + } +} diff --git a/Dota2GSI/EventMessages/MinimapEvents.cs b/Dota2GSI/EventMessages/MinimapEvents.cs new file mode 100644 index 0000000..1a6128e --- /dev/null +++ b/Dota2GSI/EventMessages/MinimapEvents.cs @@ -0,0 +1,35 @@ +using Dota2GSI.Nodes; +using Dota2GSI.Nodes.MinimapProvider; + +namespace Dota2GSI.EventMessages +{ + /// + /// Event for overall Minimap update. + /// + public class MinimapStateUpdated : UpdateEvent + { + public MinimapStateUpdated(Minimap new_value, Minimap previous_value) : base(new_value, previous_value) + { + } + } + + /// + /// Event for a Minimap Element update. + /// + public class MinimapElementUpdated : EntityUpdateEvent + { + public MinimapElementUpdated(MinimapElement new_value, MinimapElement previous_value, string entity_id) : base(new_value, previous_value, entity_id) + { + } + } + + /// + /// Event for specific team's Minimap Element update. + /// + public class TeamMinimapElementUpdated : TeamUpdateEvent + { + public TeamMinimapElementUpdated(MinimapElement new_value, MinimapElement previous_value, PlayerTeam team) : base(new_value, previous_value, team) + { + } + } +} diff --git a/Dota2GSI/EventMessages/NeutralItemsEvents.cs b/Dota2GSI/EventMessages/NeutralItemsEvents.cs new file mode 100644 index 0000000..c98738d --- /dev/null +++ b/Dota2GSI/EventMessages/NeutralItemsEvents.cs @@ -0,0 +1,25 @@ +using Dota2GSI.Nodes; +using Dota2GSI.Nodes.NeutralItemsProvider; + +namespace Dota2GSI.EventMessages +{ + /// + /// Event for overall Neutral Items update. + /// + public class NeutralItemsStateUpdated : UpdateEvent + { + public NeutralItemsStateUpdated(NeutralItems new_value, NeutralItems previous_value) : base(new_value, previous_value) + { + } + } + + /// + /// Event for specific team's Neutral Items update. + /// + public class TeamNeutralItemsUpdated : TeamUpdateEvent + { + public TeamNeutralItemsUpdated(TeamNeutralItems new_value, TeamNeutralItems previous_value, PlayerTeam team) : base(new_value, previous_value, team) + { + } + } +} diff --git a/Dota2GSI/EventMessages/PlayerEvents.cs b/Dota2GSI/EventMessages/PlayerEvents.cs new file mode 100644 index 0000000..237aba3 --- /dev/null +++ b/Dota2GSI/EventMessages/PlayerEvents.cs @@ -0,0 +1,145 @@ +using Dota2GSI.Nodes; +using Dota2GSI.Nodes.PlayerProvider; + +namespace Dota2GSI.EventMessages +{ + /// + /// Event for overall Player update. + /// + public class PlayerStateUpdated : UpdateEvent + { + public PlayerStateUpdated(Player new_value, Player previous_value) : base(new_value, previous_value) + { + } + } + + /// + /// Event for specific player's Player Details update. + /// + public class PlayerDetailsChanged : PlayerUpdateEvent + { + public PlayerDetailsChanged(PlayerDetails new_value, PlayerDetails previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + { + } + } + + /// + /// Event for specific player's Kills count change. + /// + public class PlayerKillsChanged : PlayerUpdateEvent + { + public PlayerKillsChanged(int new_value, int previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + { + } + } + + /// + /// Event for specific player's Deaths count change. + /// + public class PlayerDeathsChanged : PlayerUpdateEvent + { + public PlayerDeathsChanged(int new_value, int previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + { + } + } + + /// + /// Event for specific player's Assists count change. + /// + public class PlayerAssistsChanged : PlayerUpdateEvent + { + public PlayerAssistsChanged(int new_value, int previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + { + } + } + + /// + /// Event for specific player's Last Hits count change. + /// + public class PlayerLastHitsChanged : PlayerUpdateEvent + { + public PlayerLastHitsChanged(int new_value, int previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + { + } + } + + /// + /// Event for specific player's Denies count change. + /// + public class PlayerDeniesChanged : PlayerUpdateEvent + { + public PlayerDeniesChanged(int new_value, int previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + { + } + } + + /// + /// Event for specific player's Kill Streak count change. + /// + public class PlayerKillStreakChanged : PlayerUpdateEvent + { + public PlayerKillStreakChanged(int new_value, int previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + { + } + } + + /// + /// Event for specific player's Gold count change. + /// + public class PlayerGoldChanged : PlayerUpdateEvent + { + public PlayerGoldChanged(int new_value, int previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + { + } + } + + /// + /// Event for specific player's Purchased Wards count change. + /// + public class PlayerWardsPurchasedChanged : PlayerUpdateEvent + { + public PlayerWardsPurchasedChanged(int new_value, int previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + { + } + } + + /// + /// Event for specific player's Placed Wards count change. + /// + public class PlayerWardsPlacedChanged : PlayerUpdateEvent + { + public PlayerWardsPlacedChanged(int new_value, int previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + { + } + } + + /// + /// Event for specific player's Destroyed Wards count change. + /// + public class PlayerWardsDestroyedChanged : PlayerUpdateEvent + { + public PlayerWardsDestroyedChanged(int new_value, int previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + { + } + } + + /// + /// Event for specific player's Runes Activated count change. + /// + public class PlayerRunesActivatedChanged : PlayerUpdateEvent + { + public PlayerRunesActivatedChanged(int new_value, int previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + { + } + } + + /// + /// Event for specific player's Stacked Camps count change. + /// + public class PlayerCampsStackedChanged : PlayerUpdateEvent + { + public PlayerCampsStackedChanged(int new_value, int previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + { + } + } +} diff --git a/Dota2GSI/EventMessages/ProviderEvents.cs b/Dota2GSI/EventMessages/ProviderEvents.cs new file mode 100644 index 0000000..1699560 --- /dev/null +++ b/Dota2GSI/EventMessages/ProviderEvents.cs @@ -0,0 +1,14 @@ +using Dota2GSI.Nodes; + +namespace Dota2GSI.EventMessages +{ + /// + /// Event for overall Provider update. + /// + public class ProviderStateUpdated : UpdateEvent + { + public ProviderStateUpdated(Provider new_value, Provider previous_value) : base(new_value, previous_value) + { + } + } +} diff --git a/Dota2GSI/EventMessages/RoshanEvents.cs b/Dota2GSI/EventMessages/RoshanEvents.cs new file mode 100644 index 0000000..9be0d17 --- /dev/null +++ b/Dota2GSI/EventMessages/RoshanEvents.cs @@ -0,0 +1,14 @@ +using Dota2GSI.Nodes; + +namespace Dota2GSI.EventMessages +{ + /// + /// Event for overall Roshan update. + /// + public class RoshanStateUpdated : UpdateEvent + { + public RoshanStateUpdated(Roshan new_value, Roshan previous_value) : base(new_value, previous_value) + { + } + } +} diff --git a/Dota2GSI/EventMessages/UpdateEvent.cs b/Dota2GSI/EventMessages/UpdateEvent.cs new file mode 100644 index 0000000..494eaa3 --- /dev/null +++ b/Dota2GSI/EventMessages/UpdateEvent.cs @@ -0,0 +1,132 @@ + +using Dota2GSI.Nodes; + +namespace Dota2GSI.EventMessages +{ + /// + /// Event for a single value update. + /// + /// The value type. + public class ValueEvent : DotaGameEvent + { + /// + /// Value. + /// + public readonly T Value; + + public ValueEvent(T obj) + { + Value = obj; + } + } + + /// + /// Event for specific player's single value update. + /// + /// The value type. + public class PlayerValueEvent : ValueEvent + { + /// + /// The associated player ID. + /// When local player, the player ID is -1. + /// + public readonly int PlayerID; + + public PlayerValueEvent(T obj, int player_id = -1) : base(obj) + { + PlayerID = player_id; + } + } + + /// + /// Event for specific team's single value update. + /// + /// The value type. + public class TeamValueEvent : ValueEvent + { + /// + /// The associated team. + /// + public readonly PlayerTeam Team; + + public TeamValueEvent(T obj, PlayerTeam team) : base(obj) + { + Team = team; + } + } + + /// + /// Event for value change. + /// + /// The value type. + public class UpdateEvent : DotaGameEvent + { + /// + /// New value. + /// + public readonly T New; + + /// + /// Previous value. + /// + public readonly T Previous; + + public UpdateEvent(T new_obj, T previous_obj) + { + New = new_obj; + Previous = previous_obj; + } + } + + /// + /// Event for specific player's value change. + /// + /// The value type. + public class PlayerUpdateEvent : UpdateEvent + { + /// + /// The associated player ID. + /// When local player, the player ID is -1. + /// + public readonly int PlayerID; + + public PlayerUpdateEvent(T new_obj, T previous_obj, int player_id = -1) : base(new_obj, previous_obj) + { + PlayerID = player_id; + } + } + + /// + /// Event for specific team's value change. + /// + /// + public class TeamUpdateEvent : UpdateEvent + { + /// + /// The associated team. + /// + public readonly PlayerTeam Team; + + public TeamUpdateEvent(T new_obj, T previous_obj, PlayerTeam team) : base(new_obj, previous_obj) + { + Team = team; + } + } + + /// + /// Event for specific entity's value change. + /// + /// + public class EntityUpdateEvent : UpdateEvent + { + /// + /// The associated entity ID. + /// + public readonly string EntityID; + + public EntityUpdateEvent(T new_obj, T previous_obj, string entity_id) : base(new_obj, previous_obj) + { + EntityID = entity_id; + } + } +} diff --git a/Dota2GSI/EventMessages/WearablesEvents.cs b/Dota2GSI/EventMessages/WearablesEvents.cs new file mode 100644 index 0000000..15950db --- /dev/null +++ b/Dota2GSI/EventMessages/WearablesEvents.cs @@ -0,0 +1,25 @@ +using Dota2GSI.Nodes; +using Dota2GSI.Nodes.WearablesProvider; + +namespace Dota2GSI.EventMessages +{ + /// + /// Event for overall Wearables update. + /// + public class WearablesStateUpdated : UpdateEvent + { + public WearablesStateUpdated(Wearables new_value, Wearables previous_value) : base(new_value, previous_value) + { + } + } + + /// + /// Event for specific player's Wearables update. + /// + public class PlayerWearablesUpdated : PlayerUpdateEvent + { + public PlayerWearablesUpdated(PlayerWearables new_value, PlayerWearables previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + { + } + } +} From bb4f98287fcc0ca05eae885b53e144867f0f9192 Mon Sep 17 00:00:00 2001 From: Anton Pupkov Date: Mon, 15 Jan 2024 15:48:45 -0800 Subject: [PATCH 04/24] Add Dota 2 Game Events handlers --- Dota2GSI/CMakeLists.txt | 16 + Dota2GSI/GameStateHandler.cs | 113 +++++++ .../StateHandlers/AbilitiesStateHandler.cs | 85 ++++++ Dota2GSI/StateHandlers/AuthStateHandler.cs | 27 ++ .../StateHandlers/BuildingsStateHandler.cs | 275 ++++++++++++++++++ .../StateHandlers/CouriersStateHandler.cs | 56 ++++ Dota2GSI/StateHandlers/DraftStateHandler.cs | 42 +++ Dota2GSI/StateHandlers/EventsStateHandler.cs | 87 ++++++ Dota2GSI/StateHandlers/HeroStateHandler.cs | 110 +++++++ Dota2GSI/StateHandlers/ItemsStateHandler.cs | 46 +++ Dota2GSI/StateHandlers/LeagueStateHandler.cs | 27 ++ Dota2GSI/StateHandlers/MapStateHandler.cs | 80 +++++ Dota2GSI/StateHandlers/MinimapStateHandler.cs | 47 +++ .../StateHandlers/NeutralItemsStateHandler.cs | 42 +++ Dota2GSI/StateHandlers/PlayerStateHandler.cs | 122 ++++++++ .../StateHandlers/ProviderStateHandler.cs | 27 ++ Dota2GSI/StateHandlers/RoshanStateHandler.cs | 27 ++ .../StateHandlers/WearablesStateHandler.cs | 45 +++ 18 files changed, 1274 insertions(+) create mode 100644 Dota2GSI/GameStateHandler.cs create mode 100644 Dota2GSI/StateHandlers/AbilitiesStateHandler.cs create mode 100644 Dota2GSI/StateHandlers/AuthStateHandler.cs create mode 100644 Dota2GSI/StateHandlers/BuildingsStateHandler.cs create mode 100644 Dota2GSI/StateHandlers/CouriersStateHandler.cs create mode 100644 Dota2GSI/StateHandlers/DraftStateHandler.cs create mode 100644 Dota2GSI/StateHandlers/EventsStateHandler.cs create mode 100644 Dota2GSI/StateHandlers/HeroStateHandler.cs create mode 100644 Dota2GSI/StateHandlers/ItemsStateHandler.cs create mode 100644 Dota2GSI/StateHandlers/LeagueStateHandler.cs create mode 100644 Dota2GSI/StateHandlers/MapStateHandler.cs create mode 100644 Dota2GSI/StateHandlers/MinimapStateHandler.cs create mode 100644 Dota2GSI/StateHandlers/NeutralItemsStateHandler.cs create mode 100644 Dota2GSI/StateHandlers/PlayerStateHandler.cs create mode 100644 Dota2GSI/StateHandlers/ProviderStateHandler.cs create mode 100644 Dota2GSI/StateHandlers/RoshanStateHandler.cs create mode 100644 Dota2GSI/StateHandlers/WearablesStateHandler.cs diff --git a/Dota2GSI/CMakeLists.txt b/Dota2GSI/CMakeLists.txt index 1680607..70d1b4e 100644 --- a/Dota2GSI/CMakeLists.txt +++ b/Dota2GSI/CMakeLists.txt @@ -82,6 +82,22 @@ SET(SOURCES Nodes/Provider.cs Nodes/Map.cs Nodes/Auth.cs + StateHandlers/AbilitiesStateHandler.cs + StateHandlers/AuthStateHandler.cs + StateHandlers/BuildingsStateHandler.cs + StateHandlers/CouriersStateHandler.cs + StateHandlers/DraftStateHandler.cs + StateHandlers/EventsStateHandler.cs + StateHandlers/HeroStateHandler.cs + StateHandlers/ItemsStateHandler.cs + StateHandlers/LeagueStateHandler.cs + StateHandlers/MapStateHandler.cs + StateHandlers/MinimapStateHandler.cs + StateHandlers/NeutralItemsStateHandler.cs + StateHandlers/PlayerStateHandler.cs + StateHandlers/ProviderStateHandler.cs + StateHandlers/RoshanStateHandler.cs + StateHandlers/WearablesStateHandler.cs ) SET(README "${CMAKE_SOURCE_DIR}/README.md") diff --git a/Dota2GSI/GameStateHandler.cs b/Dota2GSI/GameStateHandler.cs new file mode 100644 index 0000000..ecc31b1 --- /dev/null +++ b/Dota2GSI/GameStateHandler.cs @@ -0,0 +1,113 @@ +using Dota2GSI.EventMessages; + +namespace Dota2GSI +{ + public class GameStateHandler : EventHandler + { + private GameState previous_game_state = new GameState(); + + public GameStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) + { + } + + public void OnNewGameState(GameState game_state) + { + if (!game_state.IsValid()) + { + // Invalid game state provided, nothing to do here. + return; + } + + if (!previous_game_state.IsValid() && game_state.Previously.IsValid()) + { + // Update previous game state cache. + previous_game_state = game_state.Previously; + } + + // Broadcast changes for providers. + + if (!previous_game_state.Auth.Equals(game_state.Auth)) + { + dispatcher.Broadcast(new AuthStateUpdated(game_state.Auth, previous_game_state.Auth)); + } + + if (!previous_game_state.Provider.Equals(game_state.Provider)) + { + dispatcher.Broadcast(new ProviderStateUpdated(game_state.Provider, previous_game_state.Provider)); + } + + if (!previous_game_state.Map.Equals(game_state.Map)) + { + dispatcher.Broadcast(new MapStateUpdated(game_state.Map, previous_game_state.Map)); + } + + if (!previous_game_state.Player.Equals(game_state.Player)) + { + dispatcher.Broadcast(new PlayerStateUpdated(game_state.Player, previous_game_state.Player)); + } + + if (!previous_game_state.Hero.Equals(game_state.Hero)) + { + dispatcher.Broadcast(new HeroStateUpdated(game_state.Hero, previous_game_state.Hero)); + } + + if (!previous_game_state.Abilities.Equals(game_state.Abilities)) + { + dispatcher.Broadcast(new AbilitiesStateUpdated(game_state.Abilities, previous_game_state.Abilities)); + } + + if (!previous_game_state.Items.Equals(game_state.Items)) + { + dispatcher.Broadcast(new ItemsStateUpdated(game_state.Items, previous_game_state.Items)); + } + + if (!previous_game_state.Events.Equals(game_state.Events)) + { + dispatcher.Broadcast(new EventsStateUpdated(game_state.Events, previous_game_state.Events)); + } + + if (!previous_game_state.Buildings.Equals(game_state.Buildings)) + { + dispatcher.Broadcast(new BuildingsStateUpdated(game_state.Buildings, previous_game_state.Buildings)); + } + + if (!previous_game_state.League.Equals(game_state.League)) + { + dispatcher.Broadcast(new LeagueStateUpdated(game_state.League, previous_game_state.League)); + } + + if (!previous_game_state.Draft.Equals(game_state.Draft)) + { + dispatcher.Broadcast(new DraftStateUpdated(game_state.Draft, previous_game_state.Draft)); + } + + if (!previous_game_state.Wearables.Equals(game_state.Wearables)) + { + dispatcher.Broadcast(new WearablesStateUpdated(game_state.Wearables, previous_game_state.Wearables)); + } + + if (!previous_game_state.Minimap.Equals(game_state.Minimap)) + { + dispatcher.Broadcast(new MinimapStateUpdated(game_state.Minimap, previous_game_state.Minimap)); + } + + if (!previous_game_state.Roshan.Equals(game_state.Roshan)) + { + dispatcher.Broadcast(new RoshanStateUpdated(game_state.Roshan, previous_game_state.Roshan)); + } + + if (!previous_game_state.Couriers.Equals(game_state.Couriers)) + { + dispatcher.Broadcast(new CouriersStateUpdated(game_state.Couriers, previous_game_state.Couriers)); + } + + if (!previous_game_state.NeutralItems.Equals(game_state.NeutralItems)) + { + dispatcher.Broadcast(new NeutralItemsStateUpdated(game_state.NeutralItems, previous_game_state.NeutralItems)); + } + + // Finally update the previous game state cache. + previous_game_state = game_state; + } + } +} diff --git a/Dota2GSI/StateHandlers/AbilitiesStateHandler.cs b/Dota2GSI/StateHandlers/AbilitiesStateHandler.cs new file mode 100644 index 0000000..bc7ba82 --- /dev/null +++ b/Dota2GSI/StateHandlers/AbilitiesStateHandler.cs @@ -0,0 +1,85 @@ +using Dota2GSI.EventMessages; +using Dota2GSI.Nodes.AbilitiesProvider; +using System.Linq; + +namespace Dota2GSI +{ + public class AbilitiesStateHandler : EventHandler + { + public AbilitiesStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) + { + dispatcher.Subscribe(OnAbilitiesStateUpdated); + dispatcher.Subscribe(OnAbilityDetailsChanged); + } + + ~AbilitiesStateHandler() + { + dispatcher.Unsubscribe(OnAbilitiesStateUpdated); + dispatcher.Unsubscribe(OnAbilityDetailsChanged); + } + + private void OnAbilitiesStateUpdated(DotaGameEvent e) + { + AbilitiesStateUpdated evt = (e as AbilitiesStateUpdated); + + if (evt == null) + { + return; + } + + if (!evt.New.LocalPlayer.Equals(evt.Previous.LocalPlayer)) + { + dispatcher.Broadcast(new AbilityDetailsChanged(evt.New.LocalPlayer, evt.Previous.LocalPlayer)); + } + + foreach (var team_kvp in evt.New.Teams) + { + foreach (var player_kvp in team_kvp.Value) + { + // Get corresponding previous hero details. + var previous_ability_details = evt.Previous.GetForPlayer(player_kvp.Key); + + if (!player_kvp.Value.Equals(previous_ability_details)) + { + dispatcher.Broadcast(new AbilityDetailsChanged(player_kvp.Value, previous_ability_details, player_kvp.Key)); + } + } + } + } + + private void OnAbilityDetailsChanged(DotaGameEvent e) + { + AbilityDetailsChanged evt = (e as AbilityDetailsChanged); + + if (evt == null) + { + return; + } + + foreach (var ability in evt.New) + { + Ability found_ability = evt.Previous.FirstOrDefault((Ability element) => { return element.Name.Equals(ability.Name); }, null); + + if (found_ability == null) + { + dispatcher.Broadcast(new AbilityAdded(ability, evt.PlayerID)); + } + + if (!ability.Equals(found_ability)) + { + dispatcher.Broadcast(new AbilityUpdated(ability, found_ability, evt.PlayerID)); + } + } + + foreach (var ability in evt.Previous) + { + Ability found_ability = evt.New.FirstOrDefault((Ability element) => { return element.Name.Equals(ability.Name); }, null); + + if (found_ability == null) + { + dispatcher.Broadcast(new AbilityRemoved(ability, evt.PlayerID)); + } + } + } + } +} diff --git a/Dota2GSI/StateHandlers/AuthStateHandler.cs b/Dota2GSI/StateHandlers/AuthStateHandler.cs new file mode 100644 index 0000000..b35617d --- /dev/null +++ b/Dota2GSI/StateHandlers/AuthStateHandler.cs @@ -0,0 +1,27 @@ +using Dota2GSI.EventMessages; + +namespace Dota2GSI +{ + public class AuthStateHandler : EventHandler + { + public AuthStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) + { + dispatcher.Subscribe(OnAuthStateUpdated); + } + + ~AuthStateHandler() + { + dispatcher.Unsubscribe(OnAuthStateUpdated); + } + + private void OnAuthStateUpdated(DotaGameEvent e) + { + AuthStateUpdated evt = (e as AuthStateUpdated); + + if (evt == null) + { + return; + } + } + } +} diff --git a/Dota2GSI/StateHandlers/BuildingsStateHandler.cs b/Dota2GSI/StateHandlers/BuildingsStateHandler.cs new file mode 100644 index 0000000..5be8838 --- /dev/null +++ b/Dota2GSI/StateHandlers/BuildingsStateHandler.cs @@ -0,0 +1,275 @@ +using Dota2GSI.EventMessages; + +namespace Dota2GSI +{ + public class BuildingsStateHandler : EventHandler + { + public BuildingsStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) + { + dispatcher.Subscribe(OnBuildingsStateUpdated); + dispatcher.Subscribe(OnBuildingsLayoutUpdated); + } + + ~BuildingsStateHandler() + { + dispatcher.Unsubscribe(OnBuildingsStateUpdated); + dispatcher.Unsubscribe(OnBuildingsLayoutUpdated); + } + + private void OnBuildingsStateUpdated(DotaGameEvent e) + { + BuildingsStateUpdated evt = (e as BuildingsStateUpdated); + + if (evt == null) + { + return; + } + + foreach (var building_kvp in evt.New.AllBuildings) + { + if (!evt.Previous.AllBuildings.ContainsKey(building_kvp.Key)) + { + continue; + } + + if (!building_kvp.Value.Equals(evt.Previous.AllBuildings[building_kvp.Key])) + { + dispatcher.Broadcast(new BuildingsLayoutUpdated(building_kvp.Value, evt.Previous.AllBuildings[building_kvp.Key], building_kvp.Key)); + } + } + } + + private void OnBuildingsLayoutUpdated(DotaGameEvent e) + { + BuildingsLayoutUpdated evt = (e as BuildingsLayoutUpdated); + + if (evt == null) + { + return; + } + + if (!evt.New.TopTowers.Equals(evt.Previous.TopTowers)) + { + BuildingLocation location = BuildingLocation.TopLane; + + foreach (var building_kvp in evt.New.TopTowers) + { + if (!evt.Previous.TopTowers.ContainsKey(building_kvp.Key)) + { + // Not much point in having "TowerAdded" event for Dota gameplay. + continue; + } + + var previous_building = evt.Previous.TopTowers[building_kvp.Key]; + + if (!building_kvp.Value.Equals(previous_building)) + { + dispatcher.Broadcast(new TowerUpdated(building_kvp.Value, previous_building, "", evt.Team, location)); + + if (building_kvp.Value.Health == 0) + { + dispatcher.Broadcast(new TowerDestroyed(building_kvp.Value, previous_building, "", evt.Team, location)); + } + } + } + } + + if (!evt.New.MiddleTowers.Equals(evt.Previous.MiddleTowers)) + { + BuildingLocation location = BuildingLocation.MiddleLane; + + foreach (var building_kvp in evt.New.MiddleTowers) + { + if (!evt.Previous.MiddleTowers.ContainsKey(building_kvp.Key)) + { + // Not much point in having "TowerAdded" event for Dota gameplay. + continue; + } + + var previous_building = evt.Previous.MiddleTowers[building_kvp.Key]; + + if (!building_kvp.Value.Equals(previous_building)) + { + dispatcher.Broadcast(new TowerUpdated(building_kvp.Value, previous_building, "", evt.Team, location)); + + if (building_kvp.Value.Health == 0) + { + dispatcher.Broadcast(new TowerDestroyed(building_kvp.Value, previous_building, "", evt.Team, location)); + } + } + } + } + + if (!evt.New.BottomTowers.Equals(evt.Previous.BottomTowers)) + { + BuildingLocation location = BuildingLocation.BottomLane; + + foreach (var building_kvp in evt.New.BottomTowers) + { + if (!evt.Previous.BottomTowers.ContainsKey(building_kvp.Key)) + { + // Not much point in having "TowerAdded" event for Dota gameplay. + continue; + } + + var previous_building = evt.Previous.BottomTowers[building_kvp.Key]; + + if (!building_kvp.Value.Equals(previous_building)) + { + dispatcher.Broadcast(new TowerUpdated(building_kvp.Value, previous_building, "", evt.Team, location)); + + if (building_kvp.Value.Health == 0) + { + dispatcher.Broadcast(new TowerDestroyed(building_kvp.Value, previous_building, "", evt.Team, location)); + } + } + } + } + + if (!evt.New.BottomTowers.Equals(evt.Previous.BottomTowers)) + { + BuildingLocation location = BuildingLocation.BottomLane; + + foreach (var building_kvp in evt.New.BottomTowers) + { + if (!evt.Previous.BottomTowers.ContainsKey(building_kvp.Key)) + { + // Not much point in having "TowerAdded" event for Dota gameplay. + continue; + } + + var previous_building = evt.Previous.BottomTowers[building_kvp.Key]; + + if (!building_kvp.Value.Equals(previous_building)) + { + dispatcher.Broadcast(new TowerUpdated(building_kvp.Value, previous_building, "", evt.Team, location)); + + if (building_kvp.Value.Health == 0) + { + dispatcher.Broadcast(new TowerDestroyed(building_kvp.Value, previous_building, "", evt.Team, location)); + } + } + } + } + + if (!evt.New.TopRacks.Equals(evt.Previous.TopRacks)) + { + BuildingLocation location = BuildingLocation.TopLane; + + foreach (var building_kvp in evt.New.TopRacks) + { + if (!evt.Previous.TopRacks.ContainsKey(building_kvp.Key)) + { + // Not much point in having "RacksAdded" event for Dota gameplay. + continue; + } + + var previous_building = evt.Previous.TopRacks[building_kvp.Key]; + + if (!building_kvp.Value.Equals(previous_building)) + { + dispatcher.Broadcast(new RacksUpdated(building_kvp.Value, previous_building, building_kvp.Key, "", evt.Team, location)); + + if (building_kvp.Value.Health == 0) + { + dispatcher.Broadcast(new RacksDestroyed(building_kvp.Value, previous_building, building_kvp.Key, "", evt.Team, location)); + } + } + } + } + + if (!evt.New.MiddleRacks.Equals(evt.Previous.MiddleRacks)) + { + BuildingLocation location = BuildingLocation.MiddleLane; + + foreach (var building_kvp in evt.New.MiddleRacks) + { + if (!evt.Previous.MiddleRacks.ContainsKey(building_kvp.Key)) + { + // Not much point in having "RacksAdded" event for Dota gameplay. + continue; + } + + var previous_building = evt.Previous.MiddleRacks[building_kvp.Key]; + + if (!building_kvp.Value.Equals(previous_building)) + { + dispatcher.Broadcast(new RacksUpdated(building_kvp.Value, previous_building, building_kvp.Key, "", evt.Team, location)); + + if (building_kvp.Value.Health == 0) + { + dispatcher.Broadcast(new RacksDestroyed(building_kvp.Value, previous_building, building_kvp.Key, "", evt.Team, location)); + } + } + } + } + + if (!evt.New.BottomRacks.Equals(evt.Previous.BottomRacks)) + { + BuildingLocation location = BuildingLocation.BottomLane; + + foreach (var building_kvp in evt.New.BottomRacks) + { + if (!evt.Previous.BottomRacks.ContainsKey(building_kvp.Key)) + { + // Not much point in having "RacksAdded" event for Dota gameplay. + continue; + } + + var previous_building = evt.Previous.BottomRacks[building_kvp.Key]; + + if (!building_kvp.Value.Equals(previous_building)) + { + dispatcher.Broadcast(new RacksUpdated(building_kvp.Value, previous_building, building_kvp.Key, "", evt.Team, location)); + + if (building_kvp.Value.Health == 0) + { + dispatcher.Broadcast(new RacksDestroyed(building_kvp.Value, previous_building, building_kvp.Key, "", evt.Team, location)); + } + } + } + } + + if (!evt.New.Ancient.Equals(evt.Previous.Ancient)) + { + BuildingLocation location = BuildingLocation.Base; + + if (!evt.New.Ancient.Equals(evt.Previous.Ancient)) + { + dispatcher.Broadcast(new AncientUpdated(evt.New.Ancient, evt.Previous.Ancient, "", evt.Team, location)); + + if (evt.New.Ancient.Health == 0) + { + dispatcher.Broadcast(new AncientDestroyed(evt.New.Ancient, evt.Previous.Ancient, "", evt.Team, location)); + } + } + } + + if (!evt.New.OtherBuildings.Equals(evt.Previous.OtherBuildings)) + { + BuildingLocation location = BuildingLocation.Undefined; + + foreach (var building_kvp in evt.New.OtherBuildings) + { + if (!evt.Previous.OtherBuildings.ContainsKey(building_kvp.Key)) + { + // Not much point in having "OtherBuildingsAdded" event for Dota gameplay. + continue; + } + + var previous_building = evt.Previous.OtherBuildings[building_kvp.Key]; + + if (!building_kvp.Value.Equals(previous_building)) + { + dispatcher.Broadcast(new TeamBuildingUpdated(building_kvp.Value, previous_building, building_kvp.Key, evt.Team, location)); + + if (building_kvp.Value.Health == 0) + { + dispatcher.Broadcast(new TeamBuildingDestroyed(building_kvp.Value, previous_building, building_kvp.Key, evt.Team, location)); + } + } + } + } + } + } +} diff --git a/Dota2GSI/StateHandlers/CouriersStateHandler.cs b/Dota2GSI/StateHandlers/CouriersStateHandler.cs new file mode 100644 index 0000000..498df52 --- /dev/null +++ b/Dota2GSI/StateHandlers/CouriersStateHandler.cs @@ -0,0 +1,56 @@ +using Dota2GSI.EventMessages; +using Dota2GSI.Nodes; + +namespace Dota2GSI +{ + public class CouriersStateHandler : EventHandler + { + private Player current_player_state = new Player(); + + public CouriersStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) + { + dispatcher.Subscribe(OnCouriersStateUpdated); + dispatcher.Subscribe(OnPlayerStateUpdated); + } + + ~CouriersStateHandler() + { + dispatcher.Unsubscribe(OnCouriersStateUpdated); + dispatcher.Unsubscribe(OnPlayerStateUpdated); + } + + private void OnPlayerStateUpdated(DotaGameEvent e) + { + PlayerStateUpdated evt = (e as PlayerStateUpdated); + + if (evt == null) + { + return; + } + + current_player_state = evt.New; + } + + private void OnCouriersStateUpdated(DotaGameEvent e) + { + CouriersStateUpdated evt = (e as CouriersStateUpdated); + + if (evt == null) + { + return; + } + + foreach (var courier_kvp in evt.New.CouriersMap) + { + var previous_courier = evt.Previous.GetForPlayer(courier_kvp.Value.OwnerID); + if (!courier_kvp.Value.Equals(previous_courier)) + { + dispatcher.Broadcast(new CourierUpdated(courier_kvp.Value, previous_courier, courier_kvp.Value.OwnerID)); + + var courier_team = current_player_state.GetForPlayer(courier_kvp.Value.OwnerID).Team; + dispatcher.Broadcast(new TeamCourierUpdated(courier_kvp.Value, previous_courier, courier_team)); + } + } + } + } +} diff --git a/Dota2GSI/StateHandlers/DraftStateHandler.cs b/Dota2GSI/StateHandlers/DraftStateHandler.cs new file mode 100644 index 0000000..ad80d3e --- /dev/null +++ b/Dota2GSI/StateHandlers/DraftStateHandler.cs @@ -0,0 +1,42 @@ +using Dota2GSI.EventMessages; + +namespace Dota2GSI +{ + public class DraftStateHandler : EventHandler + { + public DraftStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) + { + dispatcher.Subscribe(OnDraftStateUpdated); + } + + ~DraftStateHandler() + { + dispatcher.Unsubscribe(OnDraftStateUpdated); + } + + private void OnDraftStateUpdated(DotaGameEvent e) + { + DraftStateUpdated evt = (e as DraftStateUpdated); + + if (evt == null) + { + return; + } + + foreach (var team_kvp in evt.New.Teams) + { + if (!evt.Previous.Teams.ContainsKey(team_kvp.Key)) + { + continue; + } + + var previous_draft = evt.Previous.Teams[team_kvp.Key]; + + if (!team_kvp.Value.Equals(previous_draft)) + { + dispatcher.Broadcast(new TeamDraftDetailsUpdated(team_kvp.Value, previous_draft, team_kvp.Key)); + } + } + } + } +} diff --git a/Dota2GSI/StateHandlers/EventsStateHandler.cs b/Dota2GSI/StateHandlers/EventsStateHandler.cs new file mode 100644 index 0000000..31b2a18 --- /dev/null +++ b/Dota2GSI/StateHandlers/EventsStateHandler.cs @@ -0,0 +1,87 @@ +using Dota2GSI.EventMessages; +using Dota2GSI.Nodes; +using Dota2GSI.Nodes.EventsProvider; +using System.Linq; + +namespace Dota2GSI +{ + public class EventsStateHandler : EventHandler + { + private Player current_player_state = new Player(); + + public EventsStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) + { + dispatcher.Subscribe(OnEventsStateUpdated); + dispatcher.Subscribe(OnPlayerStateUpdated); + } + + ~EventsStateHandler() + { + dispatcher.Unsubscribe(OnEventsStateUpdated); + dispatcher.Unsubscribe(OnPlayerStateUpdated); + } + + private void OnPlayerStateUpdated(DotaGameEvent e) + { + PlayerStateUpdated evt = (e as PlayerStateUpdated); + + if (evt == null) + { + return; + } + + current_player_state = evt.New; + } + + private void OnEventsStateUpdated(DotaGameEvent e) + { + EventsStateUpdated evt = (e as EventsStateUpdated); + + if (evt == null) + { + return; + } + + foreach (var game_event in evt.New) + { + Event found_event = evt.Previous.FirstOrDefault((Event element) => { return element.Equals(game_event); }, null); + + if (found_event == null) + { + dispatcher.Broadcast(new GameEvent(game_event)); + + switch (game_event.EventType) + { + case EventType.Courier_killed: + dispatcher.Broadcast(new PlayerEvent(game_event, game_event.KillerPlayerID)); + dispatcher.Broadcast(new TeamEvent(game_event, game_event.Team)); + break; + case EventType.Roshan_killed: + dispatcher.Broadcast(new PlayerEvent(game_event, game_event.KillerPlayerID)); + dispatcher.Broadcast(new TeamEvent(game_event, game_event.Team)); + break; + case EventType.Aegis_picked_up: + dispatcher.Broadcast(new PlayerEvent(game_event, game_event.PlayerID)); + dispatcher.Broadcast(new TeamEvent(game_event, current_player_state.GetForPlayer(game_event.PlayerID).Team)); + break; + case EventType.Aegis_denied: + dispatcher.Broadcast(new PlayerEvent(game_event, game_event.PlayerID)); + dispatcher.Broadcast(new TeamEvent(game_event, current_player_state.GetForPlayer(game_event.PlayerID).Team)); + break; + case EventType.Tip: + dispatcher.Broadcast(new PlayerEvent(game_event, game_event.PlayerID)); + dispatcher.Broadcast(new PlayerEvent(game_event, game_event.TipReceiverPlayerID)); + dispatcher.Broadcast(new TeamEvent(game_event, current_player_state.GetForPlayer(game_event.TipReceiverPlayerID).Team)); + break; + case EventType.Bounty_rune_pickup: + dispatcher.Broadcast(new PlayerEvent(game_event, game_event.PlayerID)); + dispatcher.Broadcast(new TeamEvent(game_event, game_event.Team)); + break; + default: + break; + } + } + } + } + } +} diff --git a/Dota2GSI/StateHandlers/HeroStateHandler.cs b/Dota2GSI/StateHandlers/HeroStateHandler.cs new file mode 100644 index 0000000..5cb382b --- /dev/null +++ b/Dota2GSI/StateHandlers/HeroStateHandler.cs @@ -0,0 +1,110 @@ +using Dota2GSI.EventMessages; + +namespace Dota2GSI +{ + public class HeroStateHandler : EventHandler + { + public HeroStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) + { + dispatcher.Subscribe(OnHeroStateUpdated); + dispatcher.Subscribe(OnHeroDetailsChanged); + } + + ~HeroStateHandler() + { + dispatcher.Unsubscribe(OnHeroStateUpdated); + dispatcher.Unsubscribe(OnHeroDetailsChanged); + } + + private void OnHeroStateUpdated(DotaGameEvent e) + { + HeroStateUpdated evt = (e as HeroStateUpdated); + + if (evt == null) + { + return; + } + + if (!evt.New.LocalPlayer.Equals(evt.Previous.LocalPlayer)) + { + dispatcher.Broadcast(new HeroDetailsChanged(evt.New.LocalPlayer, evt.Previous.LocalPlayer)); + } + + foreach (var team_kvp in evt.New.Teams) + { + foreach (var player_kvp in team_kvp.Value) + { + var previous_hero_details = evt.Previous.GetForPlayer(player_kvp.Key); + + if (!player_kvp.Value.Equals(previous_hero_details)) + { + dispatcher.Broadcast(new HeroDetailsChanged(player_kvp.Value, previous_hero_details, player_kvp.Key)); + } + } + } + } + + private void OnHeroDetailsChanged(DotaGameEvent e) + { + HeroDetailsChanged evt = (e as HeroDetailsChanged); + + if (evt == null) + { + return; + } + + if (!evt.New.Level.Equals(evt.Previous.Level)) + { + dispatcher.Broadcast(new HeroLevelChanged(evt.New.Level, evt.Previous.Level, evt.PlayerID)); + } + + if (!evt.New.Health.Equals(evt.Previous.Health)) + { + dispatcher.Broadcast(new HeroHealthChanged(evt.New.Health, evt.Previous.Health, evt.PlayerID)); + + if (!evt.New.IsAlive && evt.Previous.IsAlive) + { + dispatcher.Broadcast(new HeroDied(evt.New.Health, evt.Previous.Health, evt.PlayerID)); + } + else if (evt.New.IsAlive && !evt.Previous.IsAlive) + { + dispatcher.Broadcast(new HeroRespawned(evt.New.Health, evt.Previous.Health, evt.PlayerID)); + } + else if (evt.New.IsAlive && evt.Previous.IsAlive) + { + dispatcher.Broadcast(new HeroTookDamage(evt.New.Health, evt.Previous.Health, evt.PlayerID)); + } + } + + if (!evt.New.Mana.Equals(evt.Previous.Mana)) + { + dispatcher.Broadcast(new HeroManaChanged(evt.New.Mana, evt.Previous.Mana, evt.PlayerID)); + } + + if (!evt.New.HeroState.Equals(evt.Previous.HeroState)) + { + dispatcher.Broadcast(new HeroStateChanged(evt.New.HeroState, evt.Previous.HeroState, evt.PlayerID)); + } + + if (!evt.New.IsMuted.Equals(evt.Previous.IsMuted)) + { + dispatcher.Broadcast(new HeroMuteStateChanged(evt.New.IsMuted, evt.Previous.IsMuted, evt.PlayerID)); + } + + if (!evt.New.SelectedUnit.Equals(evt.Previous.SelectedUnit)) + { + dispatcher.Broadcast(new HeroSelectedChanged(evt.New.SelectedUnit, evt.Previous.SelectedUnit, evt.PlayerID)); + } + + if (!evt.New.TalentTree.Equals(evt.Previous.TalentTree)) + { + dispatcher.Broadcast(new HeroTalentTreeChanged(evt.New.TalentTree, evt.Previous.TalentTree, evt.PlayerID)); + } + + if (!evt.New.AttributesLevel.Equals(evt.Previous.AttributesLevel)) + { + dispatcher.Broadcast(new HeroAttributesLevelChanged(evt.New.AttributesLevel, evt.Previous.AttributesLevel, evt.PlayerID)); + } + } + } +} diff --git a/Dota2GSI/StateHandlers/ItemsStateHandler.cs b/Dota2GSI/StateHandlers/ItemsStateHandler.cs new file mode 100644 index 0000000..e4f1214 --- /dev/null +++ b/Dota2GSI/StateHandlers/ItemsStateHandler.cs @@ -0,0 +1,46 @@ +using Dota2GSI.EventMessages; + +namespace Dota2GSI +{ + public class ItemsStateHandler : EventHandler + { + public ItemsStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) + { + dispatcher.Subscribe(OnItemsStateUpdated); + } + + ~ItemsStateHandler() + { + dispatcher.Unsubscribe(OnItemsStateUpdated); + } + + private void OnItemsStateUpdated(DotaGameEvent e) + { + ItemsStateUpdated evt = (e as ItemsStateUpdated); + + if (evt == null) + { + return; + } + + if (!evt.New.LocalPlayer.Equals(evt.Previous.LocalPlayer)) + { + dispatcher.Broadcast(new ItemDetailsChanged(evt.New.LocalPlayer, evt.Previous.LocalPlayer)); + } + + foreach (var team_kvp in evt.New.Teams) + { + foreach (var player_kvp in team_kvp.Value) + { + // Get corresponding previous hero details. + var previous_hero_details = evt.Previous.GetForPlayer(player_kvp.Key); + + if (!player_kvp.Value.Equals(previous_hero_details)) + { + dispatcher.Broadcast(new ItemDetailsChanged(player_kvp.Value, previous_hero_details, player_kvp.Key)); + } + } + } + } + } +} diff --git a/Dota2GSI/StateHandlers/LeagueStateHandler.cs b/Dota2GSI/StateHandlers/LeagueStateHandler.cs new file mode 100644 index 0000000..b81f12a --- /dev/null +++ b/Dota2GSI/StateHandlers/LeagueStateHandler.cs @@ -0,0 +1,27 @@ +using Dota2GSI.EventMessages; + +namespace Dota2GSI +{ + public class LeagueStateHandler : EventHandler + { + public LeagueStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) + { + dispatcher.Subscribe(OnLeagueStateUpdated); + } + + ~LeagueStateHandler() + { + dispatcher.Unsubscribe(OnLeagueStateUpdated); + } + + private void OnLeagueStateUpdated(DotaGameEvent e) + { + LeagueStateUpdated evt = (e as LeagueStateUpdated); + + if (evt == null) + { + return; + } + } + } +} diff --git a/Dota2GSI/StateHandlers/MapStateHandler.cs b/Dota2GSI/StateHandlers/MapStateHandler.cs new file mode 100644 index 0000000..2e2e221 --- /dev/null +++ b/Dota2GSI/StateHandlers/MapStateHandler.cs @@ -0,0 +1,80 @@ +using Dota2GSI.EventMessages; + +namespace Dota2GSI +{ + public class MapStateHandler : EventHandler + { + public MapStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) + { + dispatcher.Subscribe(OnMapStateUpdated); + } + + ~MapStateHandler() + { + dispatcher.Unsubscribe(OnMapStateUpdated); + } + + private void OnMapStateUpdated(DotaGameEvent e) + { + MapStateUpdated evt = (e as MapStateUpdated); + + if (evt == null) + { + return; + } + + if (!evt.New.IsDaytime.Equals(evt.Previous.IsDaytime) || !evt.New.IsNightstalkerNight.Equals(evt.Previous.IsNightstalkerNight)) + { + dispatcher.Broadcast(new TimeOfDayChanged(evt.New.IsDaytime, evt.New.IsNightstalkerNight)); + } + + if (!evt.New.RadiantScore.Equals(evt.Previous.RadiantScore)) + { + dispatcher.Broadcast(new TeamScoreChanged(evt.New.RadiantScore, evt.Previous.RadiantScore, Nodes.PlayerTeam.Radiant)); + } + + if (!evt.New.DireScore.Equals(evt.Previous.DireScore)) + { + dispatcher.Broadcast(new TeamScoreChanged(evt.New.DireScore, evt.Previous.DireScore, Nodes.PlayerTeam.Dire)); + } + + if (!evt.New.GameState.Equals(evt.Previous.GameState)) + { + dispatcher.Broadcast(new GameStateChanged(evt.New.GameState, evt.Previous.GameState)); + } + + if (!evt.New.IsPaused.Equals(evt.Previous.IsPaused)) + { + dispatcher.Broadcast(new PauseStateChanged(evt.New.IsPaused, evt.Previous.IsPaused)); + + if (evt.New.IsPaused) + { + dispatcher.Broadcast(new GamePaused()); + } + else + { + dispatcher.Broadcast(new GameResumed()); + } + } + + if (!evt.New.WinningTeam.Equals(evt.Previous.WinningTeam) && evt.New.WinningTeam != Nodes.PlayerTeam.None && evt.New.WinningTeam != Nodes.PlayerTeam.Undefined) + { + dispatcher.Broadcast(new TeamVictory(evt.New.WinningTeam)); + + if (evt.New.WinningTeam == Nodes.PlayerTeam.Radiant) + { + dispatcher.Broadcast(new TeamDefeat(Nodes.PlayerTeam.Dire)); + } + else if (evt.New.WinningTeam == Nodes.PlayerTeam.Dire) + { + dispatcher.Broadcast(new TeamDefeat(Nodes.PlayerTeam.Radiant)); + } + } + + if (!evt.New.RoshanState.Equals(evt.Previous.RoshanState)) + { + dispatcher.Broadcast(new RoshanStateChanged(evt.New.RoshanState, evt.Previous.RoshanState)); + } + } + } +} diff --git a/Dota2GSI/StateHandlers/MinimapStateHandler.cs b/Dota2GSI/StateHandlers/MinimapStateHandler.cs new file mode 100644 index 0000000..2b20c5e --- /dev/null +++ b/Dota2GSI/StateHandlers/MinimapStateHandler.cs @@ -0,0 +1,47 @@ +using Dota2GSI.EventMessages; + +namespace Dota2GSI +{ + public class MinimapStateHandler : EventHandler + { + public MinimapStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) + { + dispatcher.Subscribe(OnMinimapStateUpdated); + } + + ~MinimapStateHandler() + { + dispatcher.Unsubscribe(OnMinimapStateUpdated); + } + + private void OnMinimapStateUpdated(DotaGameEvent e) + { + MinimapStateUpdated evt = (e as MinimapStateUpdated); + + if (evt == null) + { + return; + } + + foreach (var element_kvp in evt.New.Elements) + { + if (!evt.Previous.Elements.ContainsKey(element_kvp.Key)) + { + continue; + } + + var previous_element = evt.Previous.Elements[element_kvp.Key]; + + if (!element_kvp.Value.Equals(previous_element)) + { + dispatcher.Broadcast(new MinimapElementUpdated(element_kvp.Value, previous_element, element_kvp.Key.ToString())); + + if (element_kvp.Value.Team != Nodes.PlayerTeam.Undefined && element_kvp.Value.Team != Nodes.PlayerTeam.Unknown) + { + dispatcher.Broadcast(new TeamMinimapElementUpdated(element_kvp.Value, previous_element, element_kvp.Value.Team)); + } + } + } + } + } +} diff --git a/Dota2GSI/StateHandlers/NeutralItemsStateHandler.cs b/Dota2GSI/StateHandlers/NeutralItemsStateHandler.cs new file mode 100644 index 0000000..cd6a776 --- /dev/null +++ b/Dota2GSI/StateHandlers/NeutralItemsStateHandler.cs @@ -0,0 +1,42 @@ +using Dota2GSI.EventMessages; + +namespace Dota2GSI +{ + public class NeutralItemsStateHandler : EventHandler + { + public NeutralItemsStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) + { + dispatcher.Subscribe(OnNeutralItemsStateUpdated); + } + + ~NeutralItemsStateHandler() + { + dispatcher.Unsubscribe(OnNeutralItemsStateUpdated); + } + + private void OnNeutralItemsStateUpdated(DotaGameEvent e) + { + NeutralItemsStateUpdated evt = (e as NeutralItemsStateUpdated); + + if (evt == null) + { + return; + } + + foreach (var neutral_items_kvp in evt.New.TeamItems) + { + if (!evt.Previous.TeamItems.ContainsKey(neutral_items_kvp.Key)) + { + continue; + } + + var previous_neutral_items = evt.Previous.TeamItems[neutral_items_kvp.Key]; + + if (!neutral_items_kvp.Value.Equals(previous_neutral_items)) + { + dispatcher.Broadcast(new TeamNeutralItemsUpdated(neutral_items_kvp.Value, previous_neutral_items, neutral_items_kvp.Key)); + } + } + } + } +} diff --git a/Dota2GSI/StateHandlers/PlayerStateHandler.cs b/Dota2GSI/StateHandlers/PlayerStateHandler.cs new file mode 100644 index 0000000..4c8c342 --- /dev/null +++ b/Dota2GSI/StateHandlers/PlayerStateHandler.cs @@ -0,0 +1,122 @@ +using Dota2GSI.EventMessages; + +namespace Dota2GSI +{ + public class PlayerStateHandler : EventHandler + { + public PlayerStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) + { + dispatcher.Subscribe(OnPlayerStateUpdated); + dispatcher.Subscribe(OnPlayerDetailsChanged); + } + + ~PlayerStateHandler() + { + dispatcher.Unsubscribe(OnPlayerStateUpdated); + dispatcher.Unsubscribe(OnPlayerDetailsChanged); + } + + private void OnPlayerStateUpdated(DotaGameEvent e) + { + PlayerStateUpdated evt = (e as PlayerStateUpdated); + + if (evt == null) + { + return; + } + + if (!evt.New.LocalPlayer.Equals(evt.Previous.LocalPlayer)) + { + dispatcher.Broadcast(new PlayerDetailsChanged(evt.New.LocalPlayer, evt.Previous.LocalPlayer)); + } + + foreach (var team_kvp in evt.New.Teams) + { + foreach (var player_kvp in team_kvp.Value) + { + var previous_hero_details = evt.Previous.GetForPlayer(player_kvp.Key); + + if (!player_kvp.Value.Equals(previous_hero_details)) + { + dispatcher.Broadcast(new PlayerDetailsChanged(player_kvp.Value, previous_hero_details, player_kvp.Key)); + } + } + } + } + + private void OnPlayerDetailsChanged(DotaGameEvent e) + { + PlayerDetailsChanged evt = (e as PlayerDetailsChanged); + + if (evt == null) + { + return; + } + + if (!evt.New.Kills.Equals(evt.Previous.Kills)) + { + dispatcher.Broadcast(new PlayerKillsChanged(evt.New.Kills, evt.Previous.Kills, evt.PlayerID)); + } + + if (!evt.New.Deaths.Equals(evt.Previous.Deaths)) + { + dispatcher.Broadcast(new PlayerDeathsChanged(evt.New.Deaths, evt.Previous.Deaths, evt.PlayerID)); + } + + if (!evt.New.Assists.Equals(evt.Previous.Assists)) + { + dispatcher.Broadcast(new PlayerAssistsChanged(evt.New.Assists, evt.Previous.Assists, evt.PlayerID)); + } + + if (!evt.New.LastHits.Equals(evt.Previous.LastHits)) + { + dispatcher.Broadcast(new PlayerLastHitsChanged(evt.New.LastHits, evt.Previous.LastHits, evt.PlayerID)); + } + + if (!evt.New.Denies.Equals(evt.Previous.Denies)) + { + dispatcher.Broadcast(new PlayerDeniesChanged(evt.New.Denies, evt.Previous.Denies, evt.PlayerID)); + } + + if (!evt.New.KillStreak.Equals(evt.Previous.KillStreak)) + { + dispatcher.Broadcast(new PlayerKillStreakChanged(evt.New.KillStreak, evt.Previous.KillStreak, evt.PlayerID)); + } + + if (!evt.New.Gold.Equals(evt.Previous.Gold)) + { + dispatcher.Broadcast(new PlayerGoldChanged(evt.New.Gold, evt.Previous.Gold, evt.PlayerID)); + } + + if (!evt.New.Gold.Equals(evt.Previous.Gold)) + { + dispatcher.Broadcast(new PlayerGoldChanged(evt.New.Gold, evt.Previous.Gold, evt.PlayerID)); + } + + if (!evt.New.WardsPurchased.Equals(evt.Previous.WardsPurchased)) + { + dispatcher.Broadcast(new PlayerWardsPurchasedChanged(evt.New.WardsPurchased, evt.Previous.WardsPurchased, evt.PlayerID)); + } + + if (!evt.New.WardsPlaced.Equals(evt.Previous.WardsPlaced)) + { + dispatcher.Broadcast(new PlayerWardsPlacedChanged(evt.New.WardsPlaced, evt.Previous.WardsPlaced, evt.PlayerID)); + } + + if (!evt.New.WardsDestroyed.Equals(evt.Previous.WardsDestroyed)) + { + dispatcher.Broadcast(new PlayerWardsDestroyedChanged(evt.New.WardsDestroyed, evt.Previous.WardsDestroyed, evt.PlayerID)); + } + + if (!evt.New.RunesActivated.Equals(evt.Previous.RunesActivated)) + { + dispatcher.Broadcast(new PlayerRunesActivatedChanged(evt.New.RunesActivated, evt.Previous.RunesActivated, evt.PlayerID)); + } + + if (!evt.New.CampsStacked.Equals(evt.Previous.CampsStacked)) + { + dispatcher.Broadcast(new PlayerCampsStackedChanged(evt.New.CampsStacked, evt.Previous.CampsStacked, evt.PlayerID)); + } + } + } +} diff --git a/Dota2GSI/StateHandlers/ProviderStateHandler.cs b/Dota2GSI/StateHandlers/ProviderStateHandler.cs new file mode 100644 index 0000000..8b0025c --- /dev/null +++ b/Dota2GSI/StateHandlers/ProviderStateHandler.cs @@ -0,0 +1,27 @@ +using Dota2GSI.EventMessages; + +namespace Dota2GSI +{ + public class ProviderStateHandler : EventHandler + { + public ProviderStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) + { + dispatcher.Subscribe(OnProviderStateUpdated); + } + + ~ProviderStateHandler() + { + dispatcher.Unsubscribe(OnProviderStateUpdated); + } + + private void OnProviderStateUpdated(DotaGameEvent e) + { + ProviderStateUpdated evt = (e as ProviderStateUpdated); + + if (evt == null) + { + return; + } + } + } +} diff --git a/Dota2GSI/StateHandlers/RoshanStateHandler.cs b/Dota2GSI/StateHandlers/RoshanStateHandler.cs new file mode 100644 index 0000000..53870e0 --- /dev/null +++ b/Dota2GSI/StateHandlers/RoshanStateHandler.cs @@ -0,0 +1,27 @@ +using Dota2GSI.EventMessages; + +namespace Dota2GSI +{ + public class RoshanStateHandler : EventHandler + { + public RoshanStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) + { + dispatcher.Subscribe(OnRoshanStateUpdated); + } + + ~RoshanStateHandler() + { + dispatcher.Unsubscribe(OnRoshanStateUpdated); + } + + private void OnRoshanStateUpdated(DotaGameEvent e) + { + RoshanStateUpdated roshan_state_updated_event = (e as RoshanStateUpdated); + + if (roshan_state_updated_event == null) + { + return; + } + } + } +} diff --git a/Dota2GSI/StateHandlers/WearablesStateHandler.cs b/Dota2GSI/StateHandlers/WearablesStateHandler.cs new file mode 100644 index 0000000..41374ee --- /dev/null +++ b/Dota2GSI/StateHandlers/WearablesStateHandler.cs @@ -0,0 +1,45 @@ +using Dota2GSI.EventMessages; + +namespace Dota2GSI +{ + public class WearablesStateHandler : EventHandler + { + public WearablesStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) + { + dispatcher.Subscribe(OnWearablesStateUpdated); + } + + ~WearablesStateHandler() + { + dispatcher.Unsubscribe(OnWearablesStateUpdated); + } + + private void OnWearablesStateUpdated(DotaGameEvent e) + { + WearablesStateUpdated evt = (e as WearablesStateUpdated); + + if (evt == null) + { + return; + } + + if (!evt.New.LocalPlayer.Equals(evt.Previous.LocalPlayer)) + { + dispatcher.Broadcast(new PlayerWearablesUpdated(evt.New.LocalPlayer, evt.Previous.LocalPlayer)); + } + + foreach (var team_kvp in evt.New.Teams) + { + foreach (var player_kvp in team_kvp.Value) + { + var previous_hero_details = evt.Previous.GetForPlayer(player_kvp.Key); + + if (!player_kvp.Value.Equals(previous_hero_details)) + { + dispatcher.Broadcast(new PlayerWearablesUpdated(player_kvp.Value, previous_hero_details, player_kvp.Key)); + } + } + } + } + } +} From 954ae6bbc03d374c373d59d5c43e023782078983 Mon Sep 17 00:00:00 2001 From: Anton Pupkov Date: Mon, 15 Jan 2024 12:55:34 -0800 Subject: [PATCH 05/24] Implement GameEvents into GameStateListener --- Dota2GSI/GameStateListener.cs | 92 +++++++++++++++++++++++------------ 1 file changed, 62 insertions(+), 30 deletions(-) diff --git a/Dota2GSI/GameStateListener.cs b/Dota2GSI/GameStateListener.cs index 677d15c..3c3e847 100644 --- a/Dota2GSI/GameStateListener.cs +++ b/Dota2GSI/GameStateListener.cs @@ -1,4 +1,5 @@ -using Newtonsoft.Json.Linq; +using Dota2GSI.EventMessages; +using Newtonsoft.Json.Linq; using System; using System.ComponentModel; using System.IO; @@ -15,23 +16,16 @@ namespace Dota2GSI public delegate void NewGameStateHandler(GameState gamestate); /// - /// Delegate for handing map game state changes. + /// Delegate for handing game events. /// - /// The new map game state. - public delegate void ChangedMapState(Nodes.DOTA_GameState newGameState); + /// The new game event. + public delegate void GameEventHandler(DotaGameEvent game_event); /// /// /// public class GameStateListener : IDisposable { - private bool isRunning = false; - private int connection_port; - private HttpListener net_Listener; - private AutoResetEvent waitForConnection = new AutoResetEvent(false); - private GameState previousGameState = new GameState(); - private GameState currentGameState = new GameState(); - /// /// The previous game state. /// @@ -56,7 +50,7 @@ private set { previousGameState = currentGameState; currentGameState = value; - RaiseOnNewGameState(); + RaiseOnNewGameState(ref currentGameState); } } @@ -76,15 +70,51 @@ private set public event NewGameStateHandler NewGameState = delegate { }; /// - /// Event for when the map's gamestate changes. + /// Event for handing Dota 2 game events. /// - public event ChangedMapState ChangedMapState = delegate { }; + public event GameEventHandler GameEvent = delegate { }; + + private bool isRunning = false; + private int connection_port; + private HttpListener net_Listener; + private AutoResetEvent waitForConnection = new AutoResetEvent(false); + private GameState previousGameState = new GameState(); + private GameState currentGameState = new GameState(); + + private static EventDispatcher dispatcher = new EventDispatcher(); + + private AbilitiesStateHandler abilities_state_handler = new AbilitiesStateHandler(ref dispatcher); + private AuthStateHandler auth_state_handler = new AuthStateHandler(ref dispatcher); + private BuildingsStateHandler buildings_state_handler = new BuildingsStateHandler(ref dispatcher); + private CouriersStateHandler couriers_state_handler = new CouriersStateHandler(ref dispatcher); + private DraftStateHandler draft_state_handler = new DraftStateHandler(ref dispatcher); + private EventsStateHandler events_state_handler = new EventsStateHandler(ref dispatcher); + private HeroStateHandler hero_state_handler = new HeroStateHandler(ref dispatcher); + private ItemsStateHandler items_state_handler = new ItemsStateHandler(ref dispatcher); + private LeagueStateHandler league_state_handler = new LeagueStateHandler(ref dispatcher); + private MapStateHandler map_state_handler = new MapStateHandler(ref dispatcher); + private MinimapStateHandler minimap_state_handler = new MinimapStateHandler(ref dispatcher); + private NeutralItemsStateHandler neutral_items_state_handler = new NeutralItemsStateHandler(ref dispatcher); + private PlayerStateHandler player_state_handler = new PlayerStateHandler(ref dispatcher); + private ProviderStateHandler provider_state_handler = new ProviderStateHandler(ref dispatcher); + private RoshanStateHandler roshan_state_handler = new RoshanStateHandler(ref dispatcher); + private WearablesStateHandler wearables_state_handler = new WearablesStateHandler(ref dispatcher); + + private GameStateHandler game_state_handler = new GameStateHandler(ref dispatcher); + + /// + /// Default constructor. + /// + private GameStateListener() + { + dispatcher.GameEvent += RaiseOnDotaGameEvent; + } /// /// A GameStateListener that listens for connections on http://localhost:port/. /// /// The port to listen on. - public GameStateListener(int Port) + public GameStateListener(int Port) : this() { connection_port = Port; net_Listener = new HttpListener(); @@ -95,7 +125,7 @@ public GameStateListener(int Port) /// A GameStateListener that listens for connections to the specified URI. /// /// The URI to listen to. - public GameStateListener(string URI) + public GameStateListener(string URI) : this() { if (!URI.EndsWith("/")) { @@ -196,34 +226,36 @@ private void ReceiveGameState(IAsyncResult result) } } - private void RaiseOnNewGameState() + private void RaiseOnDotaGameEvent(DotaGameEvent e) { - foreach (Delegate d in NewGameState.GetInvocationList()) + foreach (Delegate d in GameEvent.GetInvocationList()) { if (d.Target is ISynchronizeInvoke) { - (d.Target as ISynchronizeInvoke).BeginInvoke(d, new object[] { CurrentGameState }); + (d.Target as ISynchronizeInvoke).BeginInvoke(d, new object[] { e }); } else { - d.DynamicInvoke(CurrentGameState); + d.DynamicInvoke(e); } } + } - if (CurrentGameState.Map.GameState != PreviousGameState.Map.GameState) + private void RaiseOnNewGameState(ref GameState game_state) + { + foreach (Delegate d in NewGameState.GetInvocationList()) { - foreach (Delegate d in ChangedMapState.GetInvocationList()) + if (d.Target is ISynchronizeInvoke) { - if (d.Target is ISynchronizeInvoke) - { - (d.Target as ISynchronizeInvoke).BeginInvoke(d, new object[] { CurrentGameState.Map.GameState }); - } - else - { - d.DynamicInvoke(CurrentGameState.Map.GameState); - } + (d.Target as ISynchronizeInvoke).BeginInvoke(d, new object[] { game_state }); + } + else + { + d.DynamicInvoke(game_state); } } + + game_state_handler.OnNewGameState(CurrentGameState); } /// From c84c7ea7769e479930d18f92d28589e9ca681d23 Mon Sep 17 00:00:00 2001 From: Anton Pupkov Date: Mon, 15 Jan 2024 15:49:34 -0800 Subject: [PATCH 06/24] Update example program --- .../Dota2GSI Example program/Program.cs | 136 +++++++++++++++++- .../Properties/AssemblyInfo.cs | 1 - 2 files changed, 131 insertions(+), 6 deletions(-) diff --git a/Dota2GSI Example program/Dota2GSI Example program/Program.cs b/Dota2GSI Example program/Dota2GSI Example program/Program.cs index b2f249a..b13fcd6 100644 --- a/Dota2GSI Example program/Dota2GSI Example program/Program.cs +++ b/Dota2GSI Example program/Dota2GSI Example program/Program.cs @@ -1,8 +1,9 @@ -using System; +using Dota2GSI; +using Dota2GSI.EventMessages; +using Microsoft.Win32; +using System; using System.Diagnostics; using System.IO; -using Dota2GSI; -using Microsoft.Win32; using System.Threading; namespace Dota2GSI_Example_program @@ -24,7 +25,8 @@ static void Main(string[] args) } _gsl = new GameStateListener(4000); - _gsl.NewGameState += OnNewGameState; + // _gsl.NewGameState += OnNewGameState; // `NewGameState` can be used alongside `GameEvent`. Just not in this example. + _gsl.GameEvent += OnGameEvent; // `GameEvent` can be used alongside `NewGameState`. if (!_gsl.Start()) { @@ -43,6 +45,130 @@ static void Main(string[] args) } } while (Console.ReadKey(true).Key != ConsoleKey.Escape); } + + private static void OnGameEvent(DotaGameEvent game_event) + { + if (game_event is ProviderStateUpdated provider) + { + Console.WriteLine($"Current Game version: {provider.New.Version}"); + Console.WriteLine($"Current Game time stamp: {provider.New.TimeStamp}"); + } + else if (game_event is PlayerDetailsChanged player_details) + { + Console.WriteLine($"Player Name: {player_details.New.Name}"); + Console.WriteLine($"Player Account ID: {player_details.New.AccountID}"); + } + else if (game_event is TimeOfDayChanged time_of_day) + { + Console.WriteLine($"Is daytime: {time_of_day.IsDaytime} Is Nightstalker night: {time_of_day.IsNightstalkerNight}"); + } + else if (game_event is TeamScoreChanged team_score) + { + Console.WriteLine($"New score for {team_score.Team} is {team_score.New}"); + } + else if (game_event is PauseStateChanged paused_state) + { + Console.WriteLine($"New pause state is {paused_state.New}"); + } + else if (game_event is HeroDetailsChanged hero_details) + { + Console.WriteLine($"Player {hero_details.PlayerID} Hero ID: " + hero_details.New.ID); + Console.WriteLine($"Player {hero_details.PlayerID} Hero XP: " + hero_details.New.Experience); + Console.WriteLine($"Player {hero_details.PlayerID} Hero has Aghanims Shard upgrade: " + hero_details.New.HasAghanimsShardUpgrade); + Console.WriteLine($"Player {hero_details.PlayerID} Hero Health: " + hero_details.New.Health); + Console.WriteLine($"Player {hero_details.PlayerID} Hero Mana: " + hero_details.New.Mana); + Console.WriteLine($"Player {hero_details.PlayerID} Hero Location: " + hero_details.New.Location); + } + else if (game_event is AbilityUpdated ability) + { + Console.WriteLine($"Player {ability.PlayerID} updated their ability: " + ability.New); + } + else if (game_event is ItemDetailsChanged item_details) + { + Console.WriteLine($"Player {item_details.PlayerID} updated their items: " + item_details.New); + + if (item_details.New.InventoryContains("item_blink")) + { + Console.WriteLine($"Player {item_details.PlayerID} has a blink dagger."); + } + else + { + Console.WriteLine($"Player {item_details.PlayerID} DOES NOT have a blink dagger."); + } + } + else if (game_event is PlayerEvent player_event) + { + Console.WriteLine($"Player {player_event.PlayerID} did a thing: " + player_event.Value.EventType); + } + else if (game_event is TeamEvent team_event) + { + Console.WriteLine($"Team {team_event.Team} did a thing: " + team_event.Value.EventType); + } + else if (game_event is TowerUpdated tower_updated) + { + if (tower_updated.New.Health < tower_updated.Previous.Health) + { + Console.WriteLine($"{tower_updated.Team} {tower_updated.Location} tower is under attack! Health: " + tower_updated.New.Health); + } + else if (tower_updated.New.Health > tower_updated.Previous.Health) + { + Console.WriteLine($"{tower_updated.Team} {tower_updated.Location} tower is being healed! Health: " + tower_updated.New.Health); + } + } + else if (game_event is TowerDestroyed tower_destroyed) + { + Console.WriteLine($"{tower_destroyed.Team} {tower_destroyed.Location} tower is destroyed!"); + } + else if (game_event is RacksUpdated racks_updated) + { + if (racks_updated.New.Health < racks_updated.Previous.Health) + { + Console.WriteLine($"{racks_updated.Team} {racks_updated.Location} {racks_updated.RacksType} racks are under attack! Health: " + racks_updated.New.Health); + } + else if (racks_updated.New.Health > racks_updated.Previous.Health) + { + Console.WriteLine($"{racks_updated.Team} {racks_updated.Location} {racks_updated.RacksType} tower are being healed! Health: " + racks_updated.New.Health); + } + } + else if (game_event is RacksDestroyed racks_destroyed) + { + Console.WriteLine($"{racks_destroyed.Team} {racks_destroyed.Location} {racks_destroyed.RacksType} racks is destroyed!"); + } + else if (game_event is AncientUpdated ancient_updated) + { + if (ancient_updated.New.Health < ancient_updated.Previous.Health) + { + Console.WriteLine($"{ancient_updated.Team} ancient is under attack! Health: " + ancient_updated.New.Health); + } + else if (ancient_updated.New.Health > ancient_updated.Previous.Health) + { + Console.WriteLine($"{ancient_updated.Team} ancient is being healed! Health: " + ancient_updated.New.Health); + } + } + else if (game_event is TeamNeutralItemsUpdated team_neutral_items_updated) + { + Console.WriteLine($"{team_neutral_items_updated.Team} neutral items updated: {team_neutral_items_updated.New}"); + } + else if (game_event is CourierUpdated courier_updated) + { + Console.WriteLine($"Player {courier_updated.PlayerID} courier updated: {courier_updated.New}"); + } + else if (game_event is TeamDraftDetailsUpdated draft_details_updated) + { + Console.WriteLine($"{draft_details_updated.Team} draft details updated: {draft_details_updated.New}"); + } + else if (game_event is TeamDefeat team_defeat) + { + Console.WriteLine($"{team_defeat.Team} lost the game."); + } + else if (game_event is TeamVictory team_victory) + { + Console.WriteLine($"{team_victory.Team} won the game!"); + } + } + + // NewGameState example + static void OnNewGameState(GameState gs) { Console.Clear(); @@ -93,7 +219,7 @@ static void OnNewGameState(GameState gs) Console.WriteLine($"{level}"); } - foreach(var game_event in gs.Events) + foreach (var game_event in gs.Events) { if (game_event.EventType == Dota2GSI.Nodes.EventsProvider.EventType.Bounty_rune_pickup) { diff --git a/Dota2GSI Example program/Dota2GSI Example program/Properties/AssemblyInfo.cs b/Dota2GSI Example program/Dota2GSI Example program/Properties/AssemblyInfo.cs index cf3c2b5..35a60cb 100644 --- a/Dota2GSI Example program/Dota2GSI Example program/Properties/AssemblyInfo.cs +++ b/Dota2GSI Example program/Dota2GSI Example program/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] From 533e5b4fc39fa8c98f585bb9bef59dbf84c9dd35 Mon Sep 17 00:00:00 2001 From: Anton Pupkov Date: Wed, 17 Jan 2024 13:08:42 -0800 Subject: [PATCH 07/24] Remove superfluous "State" from event names --- Dota2GSI/EventMessages/AbilitiesEvents.cs | 4 +-- Dota2GSI/EventMessages/AuthEvents.cs | 4 +-- Dota2GSI/EventMessages/BuildingsEvents.cs | 4 +-- Dota2GSI/EventMessages/CouriersEvents.cs | 4 +-- Dota2GSI/EventMessages/DraftEvents.cs | 4 +-- Dota2GSI/EventMessages/EventsEvents.cs | 8 ++--- Dota2GSI/EventMessages/HeroEvents.cs | 4 +-- Dota2GSI/EventMessages/ItemsEvents.cs | 4 +-- Dota2GSI/EventMessages/LeagueEvents.cs | 4 +-- Dota2GSI/EventMessages/MapEvents.cs | 4 +-- Dota2GSI/EventMessages/MinimapEvents.cs | 4 +-- Dota2GSI/EventMessages/NeutralItemsEvents.cs | 4 +-- Dota2GSI/EventMessages/PlayerEvents.cs | 4 +-- Dota2GSI/EventMessages/ProviderEvents.cs | 4 +-- Dota2GSI/EventMessages/RoshanEvents.cs | 4 +-- Dota2GSI/EventMessages/UpdateEvent.cs | 3 +- Dota2GSI/EventMessages/WearablesEvents.cs | 4 +-- Dota2GSI/GameStateHandler.cs | 32 +++++++++---------- .../StateHandlers/AbilitiesStateHandler.cs | 6 ++-- Dota2GSI/StateHandlers/AuthStateHandler.cs | 6 ++-- .../StateHandlers/BuildingsStateHandler.cs | 6 ++-- .../StateHandlers/CouriersStateHandler.cs | 12 +++---- Dota2GSI/StateHandlers/DraftStateHandler.cs | 6 ++-- Dota2GSI/StateHandlers/EventsStateHandler.cs | 14 ++++---- Dota2GSI/StateHandlers/HeroStateHandler.cs | 6 ++-- Dota2GSI/StateHandlers/ItemsStateHandler.cs | 6 ++-- Dota2GSI/StateHandlers/LeagueStateHandler.cs | 6 ++-- Dota2GSI/StateHandlers/MapStateHandler.cs | 6 ++-- Dota2GSI/StateHandlers/MinimapStateHandler.cs | 6 ++-- .../StateHandlers/NeutralItemsStateHandler.cs | 6 ++-- Dota2GSI/StateHandlers/PlayerStateHandler.cs | 6 ++-- .../StateHandlers/ProviderStateHandler.cs | 6 ++-- Dota2GSI/StateHandlers/RoshanStateHandler.cs | 8 ++--- .../StateHandlers/WearablesStateHandler.cs | 6 ++-- 34 files changed, 107 insertions(+), 108 deletions(-) diff --git a/Dota2GSI/EventMessages/AbilitiesEvents.cs b/Dota2GSI/EventMessages/AbilitiesEvents.cs index 5192352..ccbe92f 100644 --- a/Dota2GSI/EventMessages/AbilitiesEvents.cs +++ b/Dota2GSI/EventMessages/AbilitiesEvents.cs @@ -6,9 +6,9 @@ namespace Dota2GSI.EventMessages /// /// Event for overall Hero Abilities update. /// - public class AbilitiesStateUpdated : UpdateEvent + public class AbilitiesUpdated : UpdateEvent { - public AbilitiesStateUpdated(Abilities new_value, Abilities previous_value) : base(new_value, previous_value) + public AbilitiesUpdated(Abilities new_value, Abilities previous_value) : base(new_value, previous_value) { } } diff --git a/Dota2GSI/EventMessages/AuthEvents.cs b/Dota2GSI/EventMessages/AuthEvents.cs index bee0d94..104c317 100644 --- a/Dota2GSI/EventMessages/AuthEvents.cs +++ b/Dota2GSI/EventMessages/AuthEvents.cs @@ -5,9 +5,9 @@ namespace Dota2GSI.EventMessages /// /// Event for overall Auth update. /// - public class AuthStateUpdated : UpdateEvent + public class AuthUpdated : UpdateEvent { - public AuthStateUpdated(Auth new_value, Auth previous_value) : base(new_value, previous_value) + public AuthUpdated(Auth new_value, Auth previous_value) : base(new_value, previous_value) { } } diff --git a/Dota2GSI/EventMessages/BuildingsEvents.cs b/Dota2GSI/EventMessages/BuildingsEvents.cs index eed272e..de2d128 100644 --- a/Dota2GSI/EventMessages/BuildingsEvents.cs +++ b/Dota2GSI/EventMessages/BuildingsEvents.cs @@ -6,9 +6,9 @@ namespace Dota2GSI.EventMessages /// /// Event for overall Buildings update. /// - public class BuildingsStateUpdated : UpdateEvent + public class BuildingsUpdated : UpdateEvent { - public BuildingsStateUpdated(Buildings new_value, Buildings previous_value) : base(new_value, previous_value) + public BuildingsUpdated(Buildings new_value, Buildings previous_value) : base(new_value, previous_value) { } } diff --git a/Dota2GSI/EventMessages/CouriersEvents.cs b/Dota2GSI/EventMessages/CouriersEvents.cs index 5f4a652..2b916f1 100644 --- a/Dota2GSI/EventMessages/CouriersEvents.cs +++ b/Dota2GSI/EventMessages/CouriersEvents.cs @@ -6,9 +6,9 @@ namespace Dota2GSI.EventMessages /// /// Event for overall Couriers update. /// - public class CouriersStateUpdated : UpdateEvent + public class CouriersUpdated : UpdateEvent { - public CouriersStateUpdated(Couriers new_value, Couriers previous_value) : base(new_value, previous_value) + public CouriersUpdated(Couriers new_value, Couriers previous_value) : base(new_value, previous_value) { } } diff --git a/Dota2GSI/EventMessages/DraftEvents.cs b/Dota2GSI/EventMessages/DraftEvents.cs index 556c478..5cd2c81 100644 --- a/Dota2GSI/EventMessages/DraftEvents.cs +++ b/Dota2GSI/EventMessages/DraftEvents.cs @@ -6,9 +6,9 @@ namespace Dota2GSI.EventMessages /// /// Event for overall Draft update. /// - public class DraftStateUpdated : UpdateEvent + public class DraftUpdated : UpdateEvent { - public DraftStateUpdated(Draft new_value, Draft previous_value) : base(new_value, previous_value) + public DraftUpdated(Draft new_value, Draft previous_value) : base(new_value, previous_value) { } } diff --git a/Dota2GSI/EventMessages/EventsEvents.cs b/Dota2GSI/EventMessages/EventsEvents.cs index 820c21f..e2cbe32 100644 --- a/Dota2GSI/EventMessages/EventsEvents.cs +++ b/Dota2GSI/EventMessages/EventsEvents.cs @@ -1,14 +1,14 @@ -using Dota2GSI.Nodes; +using Dota2GSI.Nodes; using Dota2GSI.Nodes.EventsProvider; namespace Dota2GSI.EventMessages { /// - /// Event for overall Event update. + /// Event for overall Events update. /// - public class EventsStateUpdated : UpdateEvent + public class EventsUpdated : UpdateEvent { - public EventsStateUpdated(Events new_value, Events previous_value) : base(new_value, previous_value) + public EventsUpdated(Events new_value, Events previous_value) : base(new_value, previous_value) { } } diff --git a/Dota2GSI/EventMessages/HeroEvents.cs b/Dota2GSI/EventMessages/HeroEvents.cs index 12abf6f..c560c9a 100644 --- a/Dota2GSI/EventMessages/HeroEvents.cs +++ b/Dota2GSI/EventMessages/HeroEvents.cs @@ -6,9 +6,9 @@ namespace Dota2GSI.EventMessages /// /// Event for overall Hero update. /// - public class HeroStateUpdated : UpdateEvent + public class HeroUpdated : UpdateEvent { - public HeroStateUpdated(Hero new_value, Hero previous_value) : base(new_value, previous_value) + public HeroUpdated(Hero new_value, Hero previous_value) : base(new_value, previous_value) { } } diff --git a/Dota2GSI/EventMessages/ItemsEvents.cs b/Dota2GSI/EventMessages/ItemsEvents.cs index 9b40c12..2993604 100644 --- a/Dota2GSI/EventMessages/ItemsEvents.cs +++ b/Dota2GSI/EventMessages/ItemsEvents.cs @@ -6,9 +6,9 @@ namespace Dota2GSI.EventMessages /// /// Event for overall Items update. /// - public class ItemsStateUpdated : UpdateEvent + public class ItemsUpdated : UpdateEvent { - public ItemsStateUpdated(Items new_value, Items previous_value) : base(new_value, previous_value) + public ItemsUpdated(Items new_value, Items previous_value) : base(new_value, previous_value) { } } diff --git a/Dota2GSI/EventMessages/LeagueEvents.cs b/Dota2GSI/EventMessages/LeagueEvents.cs index c77c658..a882cc4 100644 --- a/Dota2GSI/EventMessages/LeagueEvents.cs +++ b/Dota2GSI/EventMessages/LeagueEvents.cs @@ -5,9 +5,9 @@ namespace Dota2GSI.EventMessages /// /// Event for overall League update. /// - public class LeagueStateUpdated : UpdateEvent + public class LeagueUpdated : UpdateEvent { - public LeagueStateUpdated(League new_value, League previous_value) : base(new_value, previous_value) + public LeagueUpdated(League new_value, League previous_value) : base(new_value, previous_value) { } } diff --git a/Dota2GSI/EventMessages/MapEvents.cs b/Dota2GSI/EventMessages/MapEvents.cs index 6caa13b..b50a44c 100644 --- a/Dota2GSI/EventMessages/MapEvents.cs +++ b/Dota2GSI/EventMessages/MapEvents.cs @@ -5,9 +5,9 @@ namespace Dota2GSI.EventMessages /// /// Event for overall Map update. /// - public class MapStateUpdated : UpdateEvent + public class MapUpdated : UpdateEvent { - public MapStateUpdated(Map new_value, Map previous_value) : base(new_value, previous_value) + public MapUpdated(Map new_value, Map previous_value) : base(new_value, previous_value) { } } diff --git a/Dota2GSI/EventMessages/MinimapEvents.cs b/Dota2GSI/EventMessages/MinimapEvents.cs index 1a6128e..3c65427 100644 --- a/Dota2GSI/EventMessages/MinimapEvents.cs +++ b/Dota2GSI/EventMessages/MinimapEvents.cs @@ -6,9 +6,9 @@ namespace Dota2GSI.EventMessages /// /// Event for overall Minimap update. /// - public class MinimapStateUpdated : UpdateEvent + public class MinimapUpdated : UpdateEvent { - public MinimapStateUpdated(Minimap new_value, Minimap previous_value) : base(new_value, previous_value) + public MinimapUpdated(Minimap new_value, Minimap previous_value) : base(new_value, previous_value) { } } diff --git a/Dota2GSI/EventMessages/NeutralItemsEvents.cs b/Dota2GSI/EventMessages/NeutralItemsEvents.cs index c98738d..d28cf74 100644 --- a/Dota2GSI/EventMessages/NeutralItemsEvents.cs +++ b/Dota2GSI/EventMessages/NeutralItemsEvents.cs @@ -6,9 +6,9 @@ namespace Dota2GSI.EventMessages /// /// Event for overall Neutral Items update. /// - public class NeutralItemsStateUpdated : UpdateEvent + public class NeutralItemsUpdated : UpdateEvent { - public NeutralItemsStateUpdated(NeutralItems new_value, NeutralItems previous_value) : base(new_value, previous_value) + public NeutralItemsUpdated(NeutralItems new_value, NeutralItems previous_value) : base(new_value, previous_value) { } } diff --git a/Dota2GSI/EventMessages/PlayerEvents.cs b/Dota2GSI/EventMessages/PlayerEvents.cs index 237aba3..c0d97bc 100644 --- a/Dota2GSI/EventMessages/PlayerEvents.cs +++ b/Dota2GSI/EventMessages/PlayerEvents.cs @@ -6,9 +6,9 @@ namespace Dota2GSI.EventMessages /// /// Event for overall Player update. /// - public class PlayerStateUpdated : UpdateEvent + public class PlayerUpdated : UpdateEvent { - public PlayerStateUpdated(Player new_value, Player previous_value) : base(new_value, previous_value) + public PlayerUpdated(Player new_value, Player previous_value) : base(new_value, previous_value) { } } diff --git a/Dota2GSI/EventMessages/ProviderEvents.cs b/Dota2GSI/EventMessages/ProviderEvents.cs index 1699560..91c1309 100644 --- a/Dota2GSI/EventMessages/ProviderEvents.cs +++ b/Dota2GSI/EventMessages/ProviderEvents.cs @@ -5,9 +5,9 @@ namespace Dota2GSI.EventMessages /// /// Event for overall Provider update. /// - public class ProviderStateUpdated : UpdateEvent + public class ProviderUpdated : UpdateEvent { - public ProviderStateUpdated(Provider new_value, Provider previous_value) : base(new_value, previous_value) + public ProviderUpdated(Provider new_value, Provider previous_value) : base(new_value, previous_value) { } } diff --git a/Dota2GSI/EventMessages/RoshanEvents.cs b/Dota2GSI/EventMessages/RoshanEvents.cs index 9be0d17..41ae019 100644 --- a/Dota2GSI/EventMessages/RoshanEvents.cs +++ b/Dota2GSI/EventMessages/RoshanEvents.cs @@ -5,9 +5,9 @@ namespace Dota2GSI.EventMessages /// /// Event for overall Roshan update. /// - public class RoshanStateUpdated : UpdateEvent + public class RoshanUpdated : UpdateEvent { - public RoshanStateUpdated(Roshan new_value, Roshan previous_value) : base(new_value, previous_value) + public RoshanUpdated(Roshan new_value, Roshan previous_value) : base(new_value, previous_value) { } } diff --git a/Dota2GSI/EventMessages/UpdateEvent.cs b/Dota2GSI/EventMessages/UpdateEvent.cs index 494eaa3..7da04ab 100644 --- a/Dota2GSI/EventMessages/UpdateEvent.cs +++ b/Dota2GSI/EventMessages/UpdateEvent.cs @@ -1,5 +1,4 @@ - -using Dota2GSI.Nodes; +using Dota2GSI.Nodes; namespace Dota2GSI.EventMessages { diff --git a/Dota2GSI/EventMessages/WearablesEvents.cs b/Dota2GSI/EventMessages/WearablesEvents.cs index 15950db..aebabfb 100644 --- a/Dota2GSI/EventMessages/WearablesEvents.cs +++ b/Dota2GSI/EventMessages/WearablesEvents.cs @@ -6,9 +6,9 @@ namespace Dota2GSI.EventMessages /// /// Event for overall Wearables update. /// - public class WearablesStateUpdated : UpdateEvent + public class WearablesUpdated : UpdateEvent { - public WearablesStateUpdated(Wearables new_value, Wearables previous_value) : base(new_value, previous_value) + public WearablesUpdated(Wearables new_value, Wearables previous_value) : base(new_value, previous_value) { } } diff --git a/Dota2GSI/GameStateHandler.cs b/Dota2GSI/GameStateHandler.cs index ecc31b1..37fd955 100644 --- a/Dota2GSI/GameStateHandler.cs +++ b/Dota2GSI/GameStateHandler.cs @@ -28,82 +28,82 @@ public void OnNewGameState(GameState game_state) if (!previous_game_state.Auth.Equals(game_state.Auth)) { - dispatcher.Broadcast(new AuthStateUpdated(game_state.Auth, previous_game_state.Auth)); + dispatcher.Broadcast(new AuthUpdated(game_state.Auth, previous_game_state.Auth)); } if (!previous_game_state.Provider.Equals(game_state.Provider)) { - dispatcher.Broadcast(new ProviderStateUpdated(game_state.Provider, previous_game_state.Provider)); + dispatcher.Broadcast(new ProviderUpdated(game_state.Provider, previous_game_state.Provider)); } if (!previous_game_state.Map.Equals(game_state.Map)) { - dispatcher.Broadcast(new MapStateUpdated(game_state.Map, previous_game_state.Map)); + dispatcher.Broadcast(new MapUpdated(game_state.Map, previous_game_state.Map)); } if (!previous_game_state.Player.Equals(game_state.Player)) { - dispatcher.Broadcast(new PlayerStateUpdated(game_state.Player, previous_game_state.Player)); + dispatcher.Broadcast(new PlayerUpdated(game_state.Player, previous_game_state.Player)); } if (!previous_game_state.Hero.Equals(game_state.Hero)) { - dispatcher.Broadcast(new HeroStateUpdated(game_state.Hero, previous_game_state.Hero)); + dispatcher.Broadcast(new HeroUpdated(game_state.Hero, previous_game_state.Hero)); } if (!previous_game_state.Abilities.Equals(game_state.Abilities)) { - dispatcher.Broadcast(new AbilitiesStateUpdated(game_state.Abilities, previous_game_state.Abilities)); + dispatcher.Broadcast(new AbilitiesUpdated(game_state.Abilities, previous_game_state.Abilities)); } if (!previous_game_state.Items.Equals(game_state.Items)) { - dispatcher.Broadcast(new ItemsStateUpdated(game_state.Items, previous_game_state.Items)); + dispatcher.Broadcast(new ItemsUpdated(game_state.Items, previous_game_state.Items)); } if (!previous_game_state.Events.Equals(game_state.Events)) { - dispatcher.Broadcast(new EventsStateUpdated(game_state.Events, previous_game_state.Events)); + dispatcher.Broadcast(new EventsUpdated(game_state.Events, previous_game_state.Events)); } if (!previous_game_state.Buildings.Equals(game_state.Buildings)) { - dispatcher.Broadcast(new BuildingsStateUpdated(game_state.Buildings, previous_game_state.Buildings)); + dispatcher.Broadcast(new BuildingsUpdated(game_state.Buildings, previous_game_state.Buildings)); } if (!previous_game_state.League.Equals(game_state.League)) { - dispatcher.Broadcast(new LeagueStateUpdated(game_state.League, previous_game_state.League)); + dispatcher.Broadcast(new LeagueUpdated(game_state.League, previous_game_state.League)); } if (!previous_game_state.Draft.Equals(game_state.Draft)) { - dispatcher.Broadcast(new DraftStateUpdated(game_state.Draft, previous_game_state.Draft)); + dispatcher.Broadcast(new DraftUpdated(game_state.Draft, previous_game_state.Draft)); } if (!previous_game_state.Wearables.Equals(game_state.Wearables)) { - dispatcher.Broadcast(new WearablesStateUpdated(game_state.Wearables, previous_game_state.Wearables)); + dispatcher.Broadcast(new WearablesUpdated(game_state.Wearables, previous_game_state.Wearables)); } if (!previous_game_state.Minimap.Equals(game_state.Minimap)) { - dispatcher.Broadcast(new MinimapStateUpdated(game_state.Minimap, previous_game_state.Minimap)); + dispatcher.Broadcast(new MinimapUpdated(game_state.Minimap, previous_game_state.Minimap)); } if (!previous_game_state.Roshan.Equals(game_state.Roshan)) { - dispatcher.Broadcast(new RoshanStateUpdated(game_state.Roshan, previous_game_state.Roshan)); + dispatcher.Broadcast(new RoshanUpdated(game_state.Roshan, previous_game_state.Roshan)); } if (!previous_game_state.Couriers.Equals(game_state.Couriers)) { - dispatcher.Broadcast(new CouriersStateUpdated(game_state.Couriers, previous_game_state.Couriers)); + dispatcher.Broadcast(new CouriersUpdated(game_state.Couriers, previous_game_state.Couriers)); } if (!previous_game_state.NeutralItems.Equals(game_state.NeutralItems)) { - dispatcher.Broadcast(new NeutralItemsStateUpdated(game_state.NeutralItems, previous_game_state.NeutralItems)); + dispatcher.Broadcast(new NeutralItemsUpdated(game_state.NeutralItems, previous_game_state.NeutralItems)); } // Finally update the previous game state cache. diff --git a/Dota2GSI/StateHandlers/AbilitiesStateHandler.cs b/Dota2GSI/StateHandlers/AbilitiesStateHandler.cs index bc7ba82..acc75f3 100644 --- a/Dota2GSI/StateHandlers/AbilitiesStateHandler.cs +++ b/Dota2GSI/StateHandlers/AbilitiesStateHandler.cs @@ -8,19 +8,19 @@ public class AbilitiesStateHandler : EventHandler { public AbilitiesStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { - dispatcher.Subscribe(OnAbilitiesStateUpdated); + dispatcher.Subscribe(OnAbilitiesStateUpdated); dispatcher.Subscribe(OnAbilityDetailsChanged); } ~AbilitiesStateHandler() { - dispatcher.Unsubscribe(OnAbilitiesStateUpdated); + dispatcher.Unsubscribe(OnAbilitiesStateUpdated); dispatcher.Unsubscribe(OnAbilityDetailsChanged); } private void OnAbilitiesStateUpdated(DotaGameEvent e) { - AbilitiesStateUpdated evt = (e as AbilitiesStateUpdated); + AbilitiesUpdated evt = (e as AbilitiesUpdated); if (evt == null) { diff --git a/Dota2GSI/StateHandlers/AuthStateHandler.cs b/Dota2GSI/StateHandlers/AuthStateHandler.cs index b35617d..960f448 100644 --- a/Dota2GSI/StateHandlers/AuthStateHandler.cs +++ b/Dota2GSI/StateHandlers/AuthStateHandler.cs @@ -6,17 +6,17 @@ public class AuthStateHandler : EventHandler { public AuthStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { - dispatcher.Subscribe(OnAuthStateUpdated); + dispatcher.Subscribe(OnAuthStateUpdated); } ~AuthStateHandler() { - dispatcher.Unsubscribe(OnAuthStateUpdated); + dispatcher.Unsubscribe(OnAuthStateUpdated); } private void OnAuthStateUpdated(DotaGameEvent e) { - AuthStateUpdated evt = (e as AuthStateUpdated); + AuthUpdated evt = (e as AuthUpdated); if (evt == null) { diff --git a/Dota2GSI/StateHandlers/BuildingsStateHandler.cs b/Dota2GSI/StateHandlers/BuildingsStateHandler.cs index 5be8838..5267df1 100644 --- a/Dota2GSI/StateHandlers/BuildingsStateHandler.cs +++ b/Dota2GSI/StateHandlers/BuildingsStateHandler.cs @@ -6,19 +6,19 @@ public class BuildingsStateHandler : EventHandler { public BuildingsStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { - dispatcher.Subscribe(OnBuildingsStateUpdated); + dispatcher.Subscribe(OnBuildingsStateUpdated); dispatcher.Subscribe(OnBuildingsLayoutUpdated); } ~BuildingsStateHandler() { - dispatcher.Unsubscribe(OnBuildingsStateUpdated); + dispatcher.Unsubscribe(OnBuildingsStateUpdated); dispatcher.Unsubscribe(OnBuildingsLayoutUpdated); } private void OnBuildingsStateUpdated(DotaGameEvent e) { - BuildingsStateUpdated evt = (e as BuildingsStateUpdated); + BuildingsUpdated evt = (e as BuildingsUpdated); if (evt == null) { diff --git a/Dota2GSI/StateHandlers/CouriersStateHandler.cs b/Dota2GSI/StateHandlers/CouriersStateHandler.cs index 498df52..af1b361 100644 --- a/Dota2GSI/StateHandlers/CouriersStateHandler.cs +++ b/Dota2GSI/StateHandlers/CouriersStateHandler.cs @@ -9,19 +9,19 @@ public class CouriersStateHandler : EventHandler public CouriersStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { - dispatcher.Subscribe(OnCouriersStateUpdated); - dispatcher.Subscribe(OnPlayerStateUpdated); + dispatcher.Subscribe(OnCouriersStateUpdated); + dispatcher.Subscribe(OnPlayerStateUpdated); } ~CouriersStateHandler() { - dispatcher.Unsubscribe(OnCouriersStateUpdated); - dispatcher.Unsubscribe(OnPlayerStateUpdated); + dispatcher.Unsubscribe(OnCouriersStateUpdated); + dispatcher.Unsubscribe(OnPlayerStateUpdated); } private void OnPlayerStateUpdated(DotaGameEvent e) { - PlayerStateUpdated evt = (e as PlayerStateUpdated); + PlayerUpdated evt = (e as PlayerUpdated); if (evt == null) { @@ -33,7 +33,7 @@ private void OnPlayerStateUpdated(DotaGameEvent e) private void OnCouriersStateUpdated(DotaGameEvent e) { - CouriersStateUpdated evt = (e as CouriersStateUpdated); + CouriersUpdated evt = (e as CouriersUpdated); if (evt == null) { diff --git a/Dota2GSI/StateHandlers/DraftStateHandler.cs b/Dota2GSI/StateHandlers/DraftStateHandler.cs index ad80d3e..5d56a03 100644 --- a/Dota2GSI/StateHandlers/DraftStateHandler.cs +++ b/Dota2GSI/StateHandlers/DraftStateHandler.cs @@ -6,17 +6,17 @@ public class DraftStateHandler : EventHandler { public DraftStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { - dispatcher.Subscribe(OnDraftStateUpdated); + dispatcher.Subscribe(OnDraftStateUpdated); } ~DraftStateHandler() { - dispatcher.Unsubscribe(OnDraftStateUpdated); + dispatcher.Unsubscribe(OnDraftStateUpdated); } private void OnDraftStateUpdated(DotaGameEvent e) { - DraftStateUpdated evt = (e as DraftStateUpdated); + DraftUpdated evt = (e as DraftUpdated); if (evt == null) { diff --git a/Dota2GSI/StateHandlers/EventsStateHandler.cs b/Dota2GSI/StateHandlers/EventsStateHandler.cs index 31b2a18..a593b47 100644 --- a/Dota2GSI/StateHandlers/EventsStateHandler.cs +++ b/Dota2GSI/StateHandlers/EventsStateHandler.cs @@ -1,4 +1,4 @@ -using Dota2GSI.EventMessages; +using Dota2GSI.EventMessages; using Dota2GSI.Nodes; using Dota2GSI.Nodes.EventsProvider; using System.Linq; @@ -11,19 +11,19 @@ public class EventsStateHandler : EventHandler public EventsStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { - dispatcher.Subscribe(OnEventsStateUpdated); - dispatcher.Subscribe(OnPlayerStateUpdated); + dispatcher.Subscribe(OnEventsStateUpdated); + dispatcher.Subscribe(OnPlayerStateUpdated); } ~EventsStateHandler() { - dispatcher.Unsubscribe(OnEventsStateUpdated); - dispatcher.Unsubscribe(OnPlayerStateUpdated); + dispatcher.Unsubscribe(OnEventsStateUpdated); + dispatcher.Unsubscribe(OnPlayerStateUpdated); } private void OnPlayerStateUpdated(DotaGameEvent e) { - PlayerStateUpdated evt = (e as PlayerStateUpdated); + PlayerUpdated evt = (e as PlayerUpdated); if (evt == null) { @@ -35,7 +35,7 @@ private void OnPlayerStateUpdated(DotaGameEvent e) private void OnEventsStateUpdated(DotaGameEvent e) { - EventsStateUpdated evt = (e as EventsStateUpdated); + EventsUpdated evt = (e as EventsUpdated); if (evt == null) { diff --git a/Dota2GSI/StateHandlers/HeroStateHandler.cs b/Dota2GSI/StateHandlers/HeroStateHandler.cs index 5cb382b..b5bb356 100644 --- a/Dota2GSI/StateHandlers/HeroStateHandler.cs +++ b/Dota2GSI/StateHandlers/HeroStateHandler.cs @@ -6,19 +6,19 @@ public class HeroStateHandler : EventHandler { public HeroStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { - dispatcher.Subscribe(OnHeroStateUpdated); + dispatcher.Subscribe(OnHeroStateUpdated); dispatcher.Subscribe(OnHeroDetailsChanged); } ~HeroStateHandler() { - dispatcher.Unsubscribe(OnHeroStateUpdated); + dispatcher.Unsubscribe(OnHeroStateUpdated); dispatcher.Unsubscribe(OnHeroDetailsChanged); } private void OnHeroStateUpdated(DotaGameEvent e) { - HeroStateUpdated evt = (e as HeroStateUpdated); + HeroUpdated evt = (e as HeroUpdated); if (evt == null) { diff --git a/Dota2GSI/StateHandlers/ItemsStateHandler.cs b/Dota2GSI/StateHandlers/ItemsStateHandler.cs index e4f1214..e557161 100644 --- a/Dota2GSI/StateHandlers/ItemsStateHandler.cs +++ b/Dota2GSI/StateHandlers/ItemsStateHandler.cs @@ -6,17 +6,17 @@ public class ItemsStateHandler : EventHandler { public ItemsStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { - dispatcher.Subscribe(OnItemsStateUpdated); + dispatcher.Subscribe(OnItemsStateUpdated); } ~ItemsStateHandler() { - dispatcher.Unsubscribe(OnItemsStateUpdated); + dispatcher.Unsubscribe(OnItemsStateUpdated); } private void OnItemsStateUpdated(DotaGameEvent e) { - ItemsStateUpdated evt = (e as ItemsStateUpdated); + ItemsUpdated evt = (e as ItemsUpdated); if (evt == null) { diff --git a/Dota2GSI/StateHandlers/LeagueStateHandler.cs b/Dota2GSI/StateHandlers/LeagueStateHandler.cs index b81f12a..c63eb27 100644 --- a/Dota2GSI/StateHandlers/LeagueStateHandler.cs +++ b/Dota2GSI/StateHandlers/LeagueStateHandler.cs @@ -6,17 +6,17 @@ public class LeagueStateHandler : EventHandler { public LeagueStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { - dispatcher.Subscribe(OnLeagueStateUpdated); + dispatcher.Subscribe(OnLeagueStateUpdated); } ~LeagueStateHandler() { - dispatcher.Unsubscribe(OnLeagueStateUpdated); + dispatcher.Unsubscribe(OnLeagueStateUpdated); } private void OnLeagueStateUpdated(DotaGameEvent e) { - LeagueStateUpdated evt = (e as LeagueStateUpdated); + LeagueUpdated evt = (e as LeagueUpdated); if (evt == null) { diff --git a/Dota2GSI/StateHandlers/MapStateHandler.cs b/Dota2GSI/StateHandlers/MapStateHandler.cs index 2e2e221..1440ee5 100644 --- a/Dota2GSI/StateHandlers/MapStateHandler.cs +++ b/Dota2GSI/StateHandlers/MapStateHandler.cs @@ -6,17 +6,17 @@ public class MapStateHandler : EventHandler { public MapStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { - dispatcher.Subscribe(OnMapStateUpdated); + dispatcher.Subscribe(OnMapStateUpdated); } ~MapStateHandler() { - dispatcher.Unsubscribe(OnMapStateUpdated); + dispatcher.Unsubscribe(OnMapStateUpdated); } private void OnMapStateUpdated(DotaGameEvent e) { - MapStateUpdated evt = (e as MapStateUpdated); + MapUpdated evt = (e as MapUpdated); if (evt == null) { diff --git a/Dota2GSI/StateHandlers/MinimapStateHandler.cs b/Dota2GSI/StateHandlers/MinimapStateHandler.cs index 2b20c5e..1938711 100644 --- a/Dota2GSI/StateHandlers/MinimapStateHandler.cs +++ b/Dota2GSI/StateHandlers/MinimapStateHandler.cs @@ -6,17 +6,17 @@ public class MinimapStateHandler : EventHandler { public MinimapStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { - dispatcher.Subscribe(OnMinimapStateUpdated); + dispatcher.Subscribe(OnMinimapStateUpdated); } ~MinimapStateHandler() { - dispatcher.Unsubscribe(OnMinimapStateUpdated); + dispatcher.Unsubscribe(OnMinimapStateUpdated); } private void OnMinimapStateUpdated(DotaGameEvent e) { - MinimapStateUpdated evt = (e as MinimapStateUpdated); + MinimapUpdated evt = (e as MinimapUpdated); if (evt == null) { diff --git a/Dota2GSI/StateHandlers/NeutralItemsStateHandler.cs b/Dota2GSI/StateHandlers/NeutralItemsStateHandler.cs index cd6a776..9e4d418 100644 --- a/Dota2GSI/StateHandlers/NeutralItemsStateHandler.cs +++ b/Dota2GSI/StateHandlers/NeutralItemsStateHandler.cs @@ -6,17 +6,17 @@ public class NeutralItemsStateHandler : EventHandler { public NeutralItemsStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { - dispatcher.Subscribe(OnNeutralItemsStateUpdated); + dispatcher.Subscribe(OnNeutralItemsStateUpdated); } ~NeutralItemsStateHandler() { - dispatcher.Unsubscribe(OnNeutralItemsStateUpdated); + dispatcher.Unsubscribe(OnNeutralItemsStateUpdated); } private void OnNeutralItemsStateUpdated(DotaGameEvent e) { - NeutralItemsStateUpdated evt = (e as NeutralItemsStateUpdated); + NeutralItemsUpdated evt = (e as NeutralItemsUpdated); if (evt == null) { diff --git a/Dota2GSI/StateHandlers/PlayerStateHandler.cs b/Dota2GSI/StateHandlers/PlayerStateHandler.cs index 4c8c342..e5bc075 100644 --- a/Dota2GSI/StateHandlers/PlayerStateHandler.cs +++ b/Dota2GSI/StateHandlers/PlayerStateHandler.cs @@ -6,19 +6,19 @@ public class PlayerStateHandler : EventHandler { public PlayerStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { - dispatcher.Subscribe(OnPlayerStateUpdated); + dispatcher.Subscribe(OnPlayerStateUpdated); dispatcher.Subscribe(OnPlayerDetailsChanged); } ~PlayerStateHandler() { - dispatcher.Unsubscribe(OnPlayerStateUpdated); + dispatcher.Unsubscribe(OnPlayerStateUpdated); dispatcher.Unsubscribe(OnPlayerDetailsChanged); } private void OnPlayerStateUpdated(DotaGameEvent e) { - PlayerStateUpdated evt = (e as PlayerStateUpdated); + PlayerUpdated evt = (e as PlayerUpdated); if (evt == null) { diff --git a/Dota2GSI/StateHandlers/ProviderStateHandler.cs b/Dota2GSI/StateHandlers/ProviderStateHandler.cs index 8b0025c..fdf1fc0 100644 --- a/Dota2GSI/StateHandlers/ProviderStateHandler.cs +++ b/Dota2GSI/StateHandlers/ProviderStateHandler.cs @@ -6,17 +6,17 @@ public class ProviderStateHandler : EventHandler { public ProviderStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { - dispatcher.Subscribe(OnProviderStateUpdated); + dispatcher.Subscribe(OnProviderStateUpdated); } ~ProviderStateHandler() { - dispatcher.Unsubscribe(OnProviderStateUpdated); + dispatcher.Unsubscribe(OnProviderStateUpdated); } private void OnProviderStateUpdated(DotaGameEvent e) { - ProviderStateUpdated evt = (e as ProviderStateUpdated); + ProviderUpdated evt = (e as ProviderUpdated); if (evt == null) { diff --git a/Dota2GSI/StateHandlers/RoshanStateHandler.cs b/Dota2GSI/StateHandlers/RoshanStateHandler.cs index 53870e0..3c66c4b 100644 --- a/Dota2GSI/StateHandlers/RoshanStateHandler.cs +++ b/Dota2GSI/StateHandlers/RoshanStateHandler.cs @@ -6,19 +6,19 @@ public class RoshanStateHandler : EventHandler { public RoshanStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { - dispatcher.Subscribe(OnRoshanStateUpdated); + dispatcher.Subscribe(OnRoshanStateUpdated); } ~RoshanStateHandler() { - dispatcher.Unsubscribe(OnRoshanStateUpdated); + dispatcher.Unsubscribe(OnRoshanStateUpdated); } private void OnRoshanStateUpdated(DotaGameEvent e) { - RoshanStateUpdated roshan_state_updated_event = (e as RoshanStateUpdated); + RoshanUpdated evt = (e as RoshanUpdated); - if (roshan_state_updated_event == null) + if (evt == null) { return; } diff --git a/Dota2GSI/StateHandlers/WearablesStateHandler.cs b/Dota2GSI/StateHandlers/WearablesStateHandler.cs index 41374ee..9d95e1b 100644 --- a/Dota2GSI/StateHandlers/WearablesStateHandler.cs +++ b/Dota2GSI/StateHandlers/WearablesStateHandler.cs @@ -6,17 +6,17 @@ public class WearablesStateHandler : EventHandler { public WearablesStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { - dispatcher.Subscribe(OnWearablesStateUpdated); + dispatcher.Subscribe(OnWearablesStateUpdated); } ~WearablesStateHandler() { - dispatcher.Unsubscribe(OnWearablesStateUpdated); + dispatcher.Unsubscribe(OnWearablesStateUpdated); } private void OnWearablesStateUpdated(DotaGameEvent e) { - WearablesStateUpdated evt = (e as WearablesStateUpdated); + WearablesUpdated evt = (e as WearablesUpdated); if (evt == null) { From cc7c348c8c28da41caa4ab6bf2ac89661f2cb7b1 Mon Sep 17 00:00:00 2001 From: Anton Pupkov Date: Wed, 17 Jan 2024 13:09:36 -0800 Subject: [PATCH 08/24] Rename GameEvent to GameplayEvent --- Dota2GSI/EventMessages/EventsEvents.cs | 8 ++++---- Dota2GSI/StateHandlers/EventsStateHandler.cs | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Dota2GSI/EventMessages/EventsEvents.cs b/Dota2GSI/EventMessages/EventsEvents.cs index e2cbe32..36c5c53 100644 --- a/Dota2GSI/EventMessages/EventsEvents.cs +++ b/Dota2GSI/EventMessages/EventsEvents.cs @@ -1,4 +1,4 @@ -using Dota2GSI.Nodes; +using Dota2GSI.Nodes; using Dota2GSI.Nodes.EventsProvider; namespace Dota2GSI.EventMessages @@ -14,11 +14,11 @@ public EventsUpdated(Events new_value, Events previous_value) : base(new_value, } /// - /// Event for Game Event. + /// Event for Gameplay Event. /// - public class GameEvent : ValueEvent + public class GameplayEvent : ValueEvent { - public GameEvent(Event value) : base(value) + public GameplayEvent(Event value) : base(value) { } } diff --git a/Dota2GSI/StateHandlers/EventsStateHandler.cs b/Dota2GSI/StateHandlers/EventsStateHandler.cs index a593b47..b3885eb 100644 --- a/Dota2GSI/StateHandlers/EventsStateHandler.cs +++ b/Dota2GSI/StateHandlers/EventsStateHandler.cs @@ -1,4 +1,4 @@ -using Dota2GSI.EventMessages; +using Dota2GSI.EventMessages; using Dota2GSI.Nodes; using Dota2GSI.Nodes.EventsProvider; using System.Linq; @@ -48,7 +48,7 @@ private void OnEventsStateUpdated(DotaGameEvent e) if (found_event == null) { - dispatcher.Broadcast(new GameEvent(game_event)); + dispatcher.Broadcast(new GameplayEvent(game_event)); switch (game_event.EventType) { From c300f604a23641d94294c8a91364869b114adf05 Mon Sep 17 00:00:00 2001 From: Anton Pupkov Date: Wed, 17 Jan 2024 13:10:15 -0800 Subject: [PATCH 09/24] Update Node with changes from CounterStrike2GSI --- Dota2GSI/Nodes/Node.cs | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/Dota2GSI/Nodes/Node.cs b/Dota2GSI/Nodes/Node.cs index 50bb4b8..e0415d2 100644 --- a/Dota2GSI/Nodes/Node.cs +++ b/Dota2GSI/Nodes/Node.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json.Linq; +using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Linq; @@ -26,6 +26,22 @@ internal Node(JObject parsed_data) _ParsedData = parsed_data; } + internal T ToEnum(string str) + { + if (!string.IsNullOrWhiteSpace(str)) + { + try + { + return (T)Enum.Parse(typeof(T), str, true); + } + catch + { + } + } + + return (T)Enum.Parse(typeof(T), "Undefined", true); + } + internal JToken GetJToken(string property_name) { if (_ParsedData != null) @@ -120,18 +136,7 @@ internal T GetEnum(string property_name) { var string_value = GetString(property_name); - if (!string.IsNullOrWhiteSpace(string_value)) - { - try - { - return (T)Enum.Parse(typeof(T), string_value, true); - } - catch - { - } - } - - return (T)Enum.Parse(typeof(T), "Undefined", true); + return ToEnum(string_value); } internal bool GetBool(string Name) From 5ac7e7f515d174e8a0c5d4d1468a1519f6ad467f Mon Sep 17 00:00:00 2001 From: Anton Pupkov Date: Wed, 17 Jan 2024 13:22:25 -0800 Subject: [PATCH 10/24] Remove superfluous "State" from event handlers --- Dota2GSI/CMakeLists.txt | 32 +++++++++--------- Dota2GSI/GameStateListener.cs | 33 ++++++++++--------- ...iesStateHandler.cs => AbilitiesHandler.cs} | 6 ++-- .../{AuthStateHandler.cs => AuthHandler.cs} | 6 ++-- ...ngsStateHandler.cs => BuildingsHandler.cs} | 6 ++-- ...iersStateHandler.cs => CouriersHandler.cs} | 6 ++-- .../{DraftStateHandler.cs => DraftHandler.cs} | 6 ++-- ...EventsStateHandler.cs => EventsHandler.cs} | 6 ++-- .../{HeroStateHandler.cs => HeroHandler.cs} | 6 ++-- .../{ItemsStateHandler.cs => ItemsHandler.cs} | 6 ++-- ...LeagueStateHandler.cs => LeagueHandler.cs} | 6 ++-- .../{MapStateHandler.cs => MapHandler.cs} | 6 ++-- ...nimapStateHandler.cs => MinimapHandler.cs} | 6 ++-- ...StateHandler.cs => NeutralItemsHandler.cs} | 6 ++-- ...PlayerStateHandler.cs => PlayerHandler.cs} | 6 ++-- ...iderStateHandler.cs => ProviderHandler.cs} | 6 ++-- ...RoshanStateHandler.cs => RoshanHandler.cs} | 6 ++-- ...lesStateHandler.cs => WearablesHandler.cs} | 6 ++-- 18 files changed, 81 insertions(+), 80 deletions(-) rename Dota2GSI/StateHandlers/{AbilitiesStateHandler.cs => AbilitiesHandler.cs} (89%) rename Dota2GSI/StateHandlers/{AuthStateHandler.cs => AuthHandler.cs} (66%) rename Dota2GSI/StateHandlers/{BuildingsStateHandler.cs => BuildingsHandler.cs} (95%) rename Dota2GSI/StateHandlers/{CouriersStateHandler.cs => CouriersHandler.cs} (85%) rename Dota2GSI/StateHandlers/{DraftStateHandler.cs => DraftHandler.cs} (79%) rename Dota2GSI/StateHandlers/{EventsStateHandler.cs => EventsHandler.cs} (92%) rename Dota2GSI/StateHandlers/{HeroStateHandler.cs => HeroHandler.cs} (92%) rename Dota2GSI/StateHandlers/{ItemsStateHandler.cs => ItemsHandler.cs} (83%) rename Dota2GSI/StateHandlers/{LeagueStateHandler.cs => LeagueHandler.cs} (66%) rename Dota2GSI/StateHandlers/{MapStateHandler.cs => MapHandler.cs} (90%) rename Dota2GSI/StateHandlers/{MinimapStateHandler.cs => MinimapHandler.cs} (83%) rename Dota2GSI/StateHandlers/{NeutralItemsStateHandler.cs => NeutralItemsHandler.cs} (80%) rename Dota2GSI/StateHandlers/{PlayerStateHandler.cs => PlayerHandler.cs} (93%) rename Dota2GSI/StateHandlers/{ProviderStateHandler.cs => ProviderHandler.cs} (66%) rename Dota2GSI/StateHandlers/{RoshanStateHandler.cs => RoshanHandler.cs} (66%) rename Dota2GSI/StateHandlers/{WearablesStateHandler.cs => WearablesHandler.cs} (82%) diff --git a/Dota2GSI/CMakeLists.txt b/Dota2GSI/CMakeLists.txt index 70d1b4e..8c42a56 100644 --- a/Dota2GSI/CMakeLists.txt +++ b/Dota2GSI/CMakeLists.txt @@ -82,22 +82,22 @@ SET(SOURCES Nodes/Provider.cs Nodes/Map.cs Nodes/Auth.cs - StateHandlers/AbilitiesStateHandler.cs - StateHandlers/AuthStateHandler.cs - StateHandlers/BuildingsStateHandler.cs - StateHandlers/CouriersStateHandler.cs - StateHandlers/DraftStateHandler.cs - StateHandlers/EventsStateHandler.cs - StateHandlers/HeroStateHandler.cs - StateHandlers/ItemsStateHandler.cs - StateHandlers/LeagueStateHandler.cs - StateHandlers/MapStateHandler.cs - StateHandlers/MinimapStateHandler.cs - StateHandlers/NeutralItemsStateHandler.cs - StateHandlers/PlayerStateHandler.cs - StateHandlers/ProviderStateHandler.cs - StateHandlers/RoshanStateHandler.cs - StateHandlers/WearablesStateHandler.cs + StateHandlers/AbilitiesHandler.cs + StateHandlers/AuthHandler.cs + StateHandlers/BuildingsHandler.cs + StateHandlers/CouriersHandler.cs + StateHandlers/DraftHandler.cs + StateHandlers/EventsHandler.cs + StateHandlers/HeroHandler.cs + StateHandlers/ItemsHandler.cs + StateHandlers/LeagueHandler.cs + StateHandlers/MapHandler.cs + StateHandlers/MinimapHandler.cs + StateHandlers/NeutralItemsHandler.cs + StateHandlers/PlayerHandler.cs + StateHandlers/ProviderHandler.cs + StateHandlers/RoshanHandler.cs + StateHandlers/WearablesHandler.cs ) SET(README "${CMAKE_SOURCE_DIR}/README.md") diff --git a/Dota2GSI/GameStateListener.cs b/Dota2GSI/GameStateListener.cs index 3c3e847..224048a 100644 --- a/Dota2GSI/GameStateListener.cs +++ b/Dota2GSI/GameStateListener.cs @@ -1,4 +1,4 @@ -using Dota2GSI.EventMessages; +using Dota2GSI.EventMessages; using Newtonsoft.Json.Linq; using System; using System.ComponentModel; @@ -82,21 +82,22 @@ private set private GameState currentGameState = new GameState(); private static EventDispatcher dispatcher = new EventDispatcher(); - - private AbilitiesStateHandler abilities_state_handler = new AbilitiesStateHandler(ref dispatcher); - private AuthStateHandler auth_state_handler = new AuthStateHandler(ref dispatcher); - private BuildingsStateHandler buildings_state_handler = new BuildingsStateHandler(ref dispatcher); - private CouriersStateHandler couriers_state_handler = new CouriersStateHandler(ref dispatcher); - private DraftStateHandler draft_state_handler = new DraftStateHandler(ref dispatcher); - private EventsStateHandler events_state_handler = new EventsStateHandler(ref dispatcher); - private HeroStateHandler hero_state_handler = new HeroStateHandler(ref dispatcher); - private ItemsStateHandler items_state_handler = new ItemsStateHandler(ref dispatcher); - private LeagueStateHandler league_state_handler = new LeagueStateHandler(ref dispatcher); - private MapStateHandler map_state_handler = new MapStateHandler(ref dispatcher); - private MinimapStateHandler minimap_state_handler = new MinimapStateHandler(ref dispatcher); - private NeutralItemsStateHandler neutral_items_state_handler = new NeutralItemsStateHandler(ref dispatcher); - private PlayerStateHandler player_state_handler = new PlayerStateHandler(ref dispatcher); - private ProviderStateHandler provider_state_handler = new ProviderStateHandler(ref dispatcher); + private AbilitiesHandler _abilities_handler = new AbilitiesHandler(ref _dispatcher); + private AuthHandler _auth_handler = new AuthHandler(ref _dispatcher); + private BuildingsHandler _buildings_handler = new BuildingsHandler(ref _dispatcher); + private CouriersHandler _couriers_handler = new CouriersHandler(ref _dispatcher); + private DraftHandler _draft_handler = new DraftHandler(ref _dispatcher); + private EventsHandler _events_handler = new EventsHandler(ref _dispatcher); + private HeroHandler _hero_handler = new HeroHandler(ref _dispatcher); + private ItemsHandler _items_handler = new ItemsHandler(ref _dispatcher); + private LeagueHandler _league_handler = new LeagueHandler(ref _dispatcher); + private MapHandler _map_handler = new MapHandler(ref _dispatcher); + private MinimapHandler _minimap_handler = new MinimapHandler(ref _dispatcher); + private NeutralItemsHandler _neutral_items_handler = new NeutralItemsHandler(ref _dispatcher); + private PlayerHandler _player_handler = new PlayerHandler(ref _dispatcher); + private ProviderHandler _provider_handler = new ProviderHandler(ref _dispatcher); + private RoshanHandler _roshan_handler = new RoshanHandler(ref _dispatcher); + private WearablesHandler _wearables_handler = new WearablesHandler(ref _dispatcher); private RoshanStateHandler roshan_state_handler = new RoshanStateHandler(ref dispatcher); private WearablesStateHandler wearables_state_handler = new WearablesStateHandler(ref dispatcher); diff --git a/Dota2GSI/StateHandlers/AbilitiesStateHandler.cs b/Dota2GSI/StateHandlers/AbilitiesHandler.cs similarity index 89% rename from Dota2GSI/StateHandlers/AbilitiesStateHandler.cs rename to Dota2GSI/StateHandlers/AbilitiesHandler.cs index acc75f3..1f97e84 100644 --- a/Dota2GSI/StateHandlers/AbilitiesStateHandler.cs +++ b/Dota2GSI/StateHandlers/AbilitiesHandler.cs @@ -4,15 +4,15 @@ namespace Dota2GSI { - public class AbilitiesStateHandler : EventHandler + public class AbilitiesHandler : EventHandler { - public AbilitiesStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) + public AbilitiesHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { dispatcher.Subscribe(OnAbilitiesStateUpdated); dispatcher.Subscribe(OnAbilityDetailsChanged); } - ~AbilitiesStateHandler() + ~AbilitiesHandler() { dispatcher.Unsubscribe(OnAbilitiesStateUpdated); dispatcher.Unsubscribe(OnAbilityDetailsChanged); diff --git a/Dota2GSI/StateHandlers/AuthStateHandler.cs b/Dota2GSI/StateHandlers/AuthHandler.cs similarity index 66% rename from Dota2GSI/StateHandlers/AuthStateHandler.cs rename to Dota2GSI/StateHandlers/AuthHandler.cs index 960f448..0fbb6bb 100644 --- a/Dota2GSI/StateHandlers/AuthStateHandler.cs +++ b/Dota2GSI/StateHandlers/AuthHandler.cs @@ -2,14 +2,14 @@ namespace Dota2GSI { - public class AuthStateHandler : EventHandler + public class AuthHandler : EventHandler { - public AuthStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) + public AuthHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { dispatcher.Subscribe(OnAuthStateUpdated); } - ~AuthStateHandler() + ~AuthHandler() { dispatcher.Unsubscribe(OnAuthStateUpdated); } diff --git a/Dota2GSI/StateHandlers/BuildingsStateHandler.cs b/Dota2GSI/StateHandlers/BuildingsHandler.cs similarity index 95% rename from Dota2GSI/StateHandlers/BuildingsStateHandler.cs rename to Dota2GSI/StateHandlers/BuildingsHandler.cs index 5267df1..92b7f11 100644 --- a/Dota2GSI/StateHandlers/BuildingsStateHandler.cs +++ b/Dota2GSI/StateHandlers/BuildingsHandler.cs @@ -2,15 +2,15 @@ namespace Dota2GSI { - public class BuildingsStateHandler : EventHandler + public class BuildingsHandler : EventHandler { - public BuildingsStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) + public BuildingsHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { dispatcher.Subscribe(OnBuildingsStateUpdated); dispatcher.Subscribe(OnBuildingsLayoutUpdated); } - ~BuildingsStateHandler() + ~BuildingsHandler() { dispatcher.Unsubscribe(OnBuildingsStateUpdated); dispatcher.Unsubscribe(OnBuildingsLayoutUpdated); diff --git a/Dota2GSI/StateHandlers/CouriersStateHandler.cs b/Dota2GSI/StateHandlers/CouriersHandler.cs similarity index 85% rename from Dota2GSI/StateHandlers/CouriersStateHandler.cs rename to Dota2GSI/StateHandlers/CouriersHandler.cs index af1b361..a305806 100644 --- a/Dota2GSI/StateHandlers/CouriersStateHandler.cs +++ b/Dota2GSI/StateHandlers/CouriersHandler.cs @@ -3,17 +3,17 @@ namespace Dota2GSI { - public class CouriersStateHandler : EventHandler + public class CouriersHandler : EventHandler { private Player current_player_state = new Player(); - public CouriersStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) + public CouriersHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { dispatcher.Subscribe(OnCouriersStateUpdated); dispatcher.Subscribe(OnPlayerStateUpdated); } - ~CouriersStateHandler() + ~CouriersHandler() { dispatcher.Unsubscribe(OnCouriersStateUpdated); dispatcher.Unsubscribe(OnPlayerStateUpdated); diff --git a/Dota2GSI/StateHandlers/DraftStateHandler.cs b/Dota2GSI/StateHandlers/DraftHandler.cs similarity index 79% rename from Dota2GSI/StateHandlers/DraftStateHandler.cs rename to Dota2GSI/StateHandlers/DraftHandler.cs index 5d56a03..698480b 100644 --- a/Dota2GSI/StateHandlers/DraftStateHandler.cs +++ b/Dota2GSI/StateHandlers/DraftHandler.cs @@ -2,14 +2,14 @@ namespace Dota2GSI { - public class DraftStateHandler : EventHandler + public class DraftHandler : EventHandler { - public DraftStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) + public DraftHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { dispatcher.Subscribe(OnDraftStateUpdated); } - ~DraftStateHandler() + ~DraftHandler() { dispatcher.Unsubscribe(OnDraftStateUpdated); } diff --git a/Dota2GSI/StateHandlers/EventsStateHandler.cs b/Dota2GSI/StateHandlers/EventsHandler.cs similarity index 92% rename from Dota2GSI/StateHandlers/EventsStateHandler.cs rename to Dota2GSI/StateHandlers/EventsHandler.cs index b3885eb..e71627a 100644 --- a/Dota2GSI/StateHandlers/EventsStateHandler.cs +++ b/Dota2GSI/StateHandlers/EventsHandler.cs @@ -5,17 +5,17 @@ namespace Dota2GSI { - public class EventsStateHandler : EventHandler + public class EventsHandler : EventHandler { private Player current_player_state = new Player(); - public EventsStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) + public EventsHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { dispatcher.Subscribe(OnEventsStateUpdated); dispatcher.Subscribe(OnPlayerStateUpdated); } - ~EventsStateHandler() + ~EventsHandler() { dispatcher.Unsubscribe(OnEventsStateUpdated); dispatcher.Unsubscribe(OnPlayerStateUpdated); diff --git a/Dota2GSI/StateHandlers/HeroStateHandler.cs b/Dota2GSI/StateHandlers/HeroHandler.cs similarity index 92% rename from Dota2GSI/StateHandlers/HeroStateHandler.cs rename to Dota2GSI/StateHandlers/HeroHandler.cs index b5bb356..a73bd00 100644 --- a/Dota2GSI/StateHandlers/HeroStateHandler.cs +++ b/Dota2GSI/StateHandlers/HeroHandler.cs @@ -2,15 +2,15 @@ namespace Dota2GSI { - public class HeroStateHandler : EventHandler + public class HeroHandler : EventHandler { - public HeroStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) + public HeroHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { dispatcher.Subscribe(OnHeroStateUpdated); dispatcher.Subscribe(OnHeroDetailsChanged); } - ~HeroStateHandler() + ~HeroHandler() { dispatcher.Unsubscribe(OnHeroStateUpdated); dispatcher.Unsubscribe(OnHeroDetailsChanged); diff --git a/Dota2GSI/StateHandlers/ItemsStateHandler.cs b/Dota2GSI/StateHandlers/ItemsHandler.cs similarity index 83% rename from Dota2GSI/StateHandlers/ItemsStateHandler.cs rename to Dota2GSI/StateHandlers/ItemsHandler.cs index e557161..369fa8d 100644 --- a/Dota2GSI/StateHandlers/ItemsStateHandler.cs +++ b/Dota2GSI/StateHandlers/ItemsHandler.cs @@ -2,14 +2,14 @@ namespace Dota2GSI { - public class ItemsStateHandler : EventHandler + public class ItemsHandler : EventHandler { - public ItemsStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) + public ItemsHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { dispatcher.Subscribe(OnItemsStateUpdated); } - ~ItemsStateHandler() + ~ItemsHandler() { dispatcher.Unsubscribe(OnItemsStateUpdated); } diff --git a/Dota2GSI/StateHandlers/LeagueStateHandler.cs b/Dota2GSI/StateHandlers/LeagueHandler.cs similarity index 66% rename from Dota2GSI/StateHandlers/LeagueStateHandler.cs rename to Dota2GSI/StateHandlers/LeagueHandler.cs index c63eb27..f329c54 100644 --- a/Dota2GSI/StateHandlers/LeagueStateHandler.cs +++ b/Dota2GSI/StateHandlers/LeagueHandler.cs @@ -2,14 +2,14 @@ namespace Dota2GSI { - public class LeagueStateHandler : EventHandler + public class LeagueHandler : EventHandler { - public LeagueStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) + public LeagueHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { dispatcher.Subscribe(OnLeagueStateUpdated); } - ~LeagueStateHandler() + ~LeagueHandler() { dispatcher.Unsubscribe(OnLeagueStateUpdated); } diff --git a/Dota2GSI/StateHandlers/MapStateHandler.cs b/Dota2GSI/StateHandlers/MapHandler.cs similarity index 90% rename from Dota2GSI/StateHandlers/MapStateHandler.cs rename to Dota2GSI/StateHandlers/MapHandler.cs index 1440ee5..1626462 100644 --- a/Dota2GSI/StateHandlers/MapStateHandler.cs +++ b/Dota2GSI/StateHandlers/MapHandler.cs @@ -2,14 +2,14 @@ namespace Dota2GSI { - public class MapStateHandler : EventHandler + public class MapHandler : EventHandler { - public MapStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) + public MapHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { dispatcher.Subscribe(OnMapStateUpdated); } - ~MapStateHandler() + ~MapHandler() { dispatcher.Unsubscribe(OnMapStateUpdated); } diff --git a/Dota2GSI/StateHandlers/MinimapStateHandler.cs b/Dota2GSI/StateHandlers/MinimapHandler.cs similarity index 83% rename from Dota2GSI/StateHandlers/MinimapStateHandler.cs rename to Dota2GSI/StateHandlers/MinimapHandler.cs index 1938711..14d303b 100644 --- a/Dota2GSI/StateHandlers/MinimapStateHandler.cs +++ b/Dota2GSI/StateHandlers/MinimapHandler.cs @@ -2,14 +2,14 @@ namespace Dota2GSI { - public class MinimapStateHandler : EventHandler + public class MinimapHandler : EventHandler { - public MinimapStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) + public MinimapHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { dispatcher.Subscribe(OnMinimapStateUpdated); } - ~MinimapStateHandler() + ~MinimapHandler() { dispatcher.Unsubscribe(OnMinimapStateUpdated); } diff --git a/Dota2GSI/StateHandlers/NeutralItemsStateHandler.cs b/Dota2GSI/StateHandlers/NeutralItemsHandler.cs similarity index 80% rename from Dota2GSI/StateHandlers/NeutralItemsStateHandler.cs rename to Dota2GSI/StateHandlers/NeutralItemsHandler.cs index 9e4d418..7097236 100644 --- a/Dota2GSI/StateHandlers/NeutralItemsStateHandler.cs +++ b/Dota2GSI/StateHandlers/NeutralItemsHandler.cs @@ -2,14 +2,14 @@ namespace Dota2GSI { - public class NeutralItemsStateHandler : EventHandler + public class NeutralItemsHandler : EventHandler { - public NeutralItemsStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) + public NeutralItemsHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { dispatcher.Subscribe(OnNeutralItemsStateUpdated); } - ~NeutralItemsStateHandler() + ~NeutralItemsHandler() { dispatcher.Unsubscribe(OnNeutralItemsStateUpdated); } diff --git a/Dota2GSI/StateHandlers/PlayerStateHandler.cs b/Dota2GSI/StateHandlers/PlayerHandler.cs similarity index 93% rename from Dota2GSI/StateHandlers/PlayerStateHandler.cs rename to Dota2GSI/StateHandlers/PlayerHandler.cs index e5bc075..f0f487d 100644 --- a/Dota2GSI/StateHandlers/PlayerStateHandler.cs +++ b/Dota2GSI/StateHandlers/PlayerHandler.cs @@ -2,15 +2,15 @@ namespace Dota2GSI { - public class PlayerStateHandler : EventHandler + public class PlayerHandler : EventHandler { - public PlayerStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) + public PlayerHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { dispatcher.Subscribe(OnPlayerStateUpdated); dispatcher.Subscribe(OnPlayerDetailsChanged); } - ~PlayerStateHandler() + ~PlayerHandler() { dispatcher.Unsubscribe(OnPlayerStateUpdated); dispatcher.Unsubscribe(OnPlayerDetailsChanged); diff --git a/Dota2GSI/StateHandlers/ProviderStateHandler.cs b/Dota2GSI/StateHandlers/ProviderHandler.cs similarity index 66% rename from Dota2GSI/StateHandlers/ProviderStateHandler.cs rename to Dota2GSI/StateHandlers/ProviderHandler.cs index fdf1fc0..536a504 100644 --- a/Dota2GSI/StateHandlers/ProviderStateHandler.cs +++ b/Dota2GSI/StateHandlers/ProviderHandler.cs @@ -2,14 +2,14 @@ namespace Dota2GSI { - public class ProviderStateHandler : EventHandler + public class ProviderHandler : EventHandler { - public ProviderStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) + public ProviderHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { dispatcher.Subscribe(OnProviderStateUpdated); } - ~ProviderStateHandler() + ~ProviderHandler() { dispatcher.Unsubscribe(OnProviderStateUpdated); } diff --git a/Dota2GSI/StateHandlers/RoshanStateHandler.cs b/Dota2GSI/StateHandlers/RoshanHandler.cs similarity index 66% rename from Dota2GSI/StateHandlers/RoshanStateHandler.cs rename to Dota2GSI/StateHandlers/RoshanHandler.cs index 3c66c4b..406168d 100644 --- a/Dota2GSI/StateHandlers/RoshanStateHandler.cs +++ b/Dota2GSI/StateHandlers/RoshanHandler.cs @@ -2,14 +2,14 @@ namespace Dota2GSI { - public class RoshanStateHandler : EventHandler + public class RoshanHandler : EventHandler { - public RoshanStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) + public RoshanHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { dispatcher.Subscribe(OnRoshanStateUpdated); } - ~RoshanStateHandler() + ~RoshanHandler() { dispatcher.Unsubscribe(OnRoshanStateUpdated); } diff --git a/Dota2GSI/StateHandlers/WearablesStateHandler.cs b/Dota2GSI/StateHandlers/WearablesHandler.cs similarity index 82% rename from Dota2GSI/StateHandlers/WearablesStateHandler.cs rename to Dota2GSI/StateHandlers/WearablesHandler.cs index 9d95e1b..32358a2 100644 --- a/Dota2GSI/StateHandlers/WearablesStateHandler.cs +++ b/Dota2GSI/StateHandlers/WearablesHandler.cs @@ -2,14 +2,14 @@ namespace Dota2GSI { - public class WearablesStateHandler : EventHandler + public class WearablesHandler : EventHandler { - public WearablesStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) + public WearablesHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { dispatcher.Subscribe(OnWearablesStateUpdated); } - ~WearablesStateHandler() + ~WearablesHandler() { dispatcher.Unsubscribe(OnWearablesStateUpdated); } From 6c71da44db8eb3b587c6e62d5f39c1785945f29a Mon Sep 17 00:00:00 2001 From: Anton Pupkov Date: Wed, 17 Jan 2024 13:25:04 -0800 Subject: [PATCH 11/24] Add Dota2EventsInterface --- Dota2GSI/CMakeLists.txt | 2 + Dota2GSI/Dota2EventsInterface.cs | 831 +++++++++++++++++++++++++++++++ Dota2GSI/EventsInterface.cs | 44 ++ Dota2GSI/GameStateListener.cs | 113 ++--- 4 files changed, 919 insertions(+), 71 deletions(-) create mode 100644 Dota2GSI/Dota2EventsInterface.cs create mode 100644 Dota2GSI/EventsInterface.cs diff --git a/Dota2GSI/CMakeLists.txt b/Dota2GSI/CMakeLists.txt index 8c42a56..05f613d 100644 --- a/Dota2GSI/CMakeLists.txt +++ b/Dota2GSI/CMakeLists.txt @@ -16,8 +16,10 @@ PROJECT(${PRODUCT} VERSION ${PRODUCT_VERSION} LANGUAGES CSharp) INCLUDE(CSharpUtilities) SET(SOURCES + Dota2EventsInterface.cs EventDispatcher.cs EventHandler.cs + EventsInterface.cs GameState.cs GameStateListener.cs GameStateHandler.cs diff --git a/Dota2GSI/Dota2EventsInterface.cs b/Dota2GSI/Dota2EventsInterface.cs new file mode 100644 index 0000000..604c5af --- /dev/null +++ b/Dota2GSI/Dota2EventsInterface.cs @@ -0,0 +1,831 @@ +using Dota2GSI.EventMessages; + +namespace Dota2GSI +{ + public class Dota2EventsInterface : EventsInterface + { + #region AbilitiesEvents + + public delegate void AbilitiesStateUpdatedHandler(AbilitiesUpdated game_event); + + /// + public event AbilitiesStateUpdatedHandler AbilitiesUpdated = delegate { }; + + public delegate void AbilityDetailsChangedHandler(AbilityDetailsChanged game_event); + + /// + public event AbilityDetailsChangedHandler AbilityDetailsChanged = delegate { }; + + public delegate void AbilityAddedHandler(AbilityAdded game_event); + + /// + public event AbilityAddedHandler AbilityAdded = delegate { }; + + public delegate void AbilityRemovedHandler(AbilityRemoved game_event); + + /// + public event AbilityRemovedHandler AbilityRemoved = delegate { }; + + public delegate void AbilityUpdatedHandler(AbilityUpdated game_event); + + /// + public event AbilityUpdatedHandler AbilityUpdated = delegate { }; + + #endregion + + #region AuthEvents + + public delegate void AuthUpdatedHandler(AuthUpdated game_event); + + /// + public event AuthUpdatedHandler AuthUpdated = delegate { }; + + #endregion + + #region BuildingsEvents + + public delegate void BuildingsUpdatedHandler(BuildingsUpdated game_event); + + /// + public event BuildingsUpdatedHandler BuildingsUpdated = delegate { }; + + public delegate void BuildingsLayoutUpdatedHandler(BuildingsLayoutUpdated game_event); + + /// + public event BuildingsLayoutUpdatedHandler BuildingsLayoutUpdated = delegate { }; + + public delegate void BuildingUpdatedHandler(BuildingUpdated game_event); + + /// + public event BuildingUpdatedHandler BuildingUpdated = delegate { }; + + public delegate void TeamBuildingUpdatedHandler(TeamBuildingUpdated game_event); + + /// + public event TeamBuildingUpdatedHandler TeamBuildingUpdated = delegate { }; + + public delegate void TeamBuildingDestroyedHandler(TeamBuildingDestroyed game_event); + + /// + public event TeamBuildingDestroyedHandler TeamBuildingDestroyed = delegate { }; + + public delegate void TowerUpdatedHandler(TowerUpdated game_event); + + /// + public event TowerUpdatedHandler TowerUpdated = delegate { }; + + public delegate void TowerDestroyedHandler(TowerDestroyed game_event); + + /// + public event TowerDestroyedHandler TowerDestroyed = delegate { }; + + public delegate void RacksUpdatedHandler(RacksUpdated game_event); + + /// + public event RacksUpdatedHandler RacksUpdated = delegate { }; + + public delegate void RacksDestroyedHandler(RacksDestroyed game_event); + + /// + public event RacksDestroyedHandler RacksDestroyed = delegate { }; + + public delegate void AncientUpdatedHandler(AncientUpdated game_event); + + /// + public event AncientUpdatedHandler AncientUpdated = delegate { }; + + public delegate void AncientDestroyedHandler(AncientDestroyed game_event); + + /// + public event AncientDestroyedHandler AncientDestroyed = delegate { }; + + #endregion + + #region CouriersEvents + + public delegate void CouriersUpdatedHandler(CouriersUpdated game_event); + + /// + public event CouriersUpdatedHandler CouriersUpdated = delegate { }; + + public delegate void CourierUpdatedHandler(CourierUpdated game_event); + + /// + public event CourierUpdatedHandler CourierUpdated = delegate { }; + + public delegate void TeamCourierUpdatedHandler(TeamCourierUpdated game_event); + + /// + public event TeamCourierUpdatedHandler TeamCourierUpdated = delegate { }; + + #endregion + + #region DraftEvents + + public delegate void DraftUpdatedHandler(DraftUpdated game_event); + + /// + public event DraftUpdatedHandler DraftUpdated = delegate { }; + + public delegate void TeamDraftDetailsUpdatedHandler(TeamDraftDetailsUpdated game_event); + + /// + public event TeamDraftDetailsUpdatedHandler TeamDraftDetailsUpdated = delegate { }; + + #endregion + + #region EventsEvents + + public delegate void EventsUpdatedHandler(EventsUpdated game_event); + + /// + public event EventsUpdatedHandler EventsUpdated = delegate { }; + + public delegate void GameplayEventHandler(GameplayEvent game_event); + + /// + public event GameplayEventHandler GameplayEvent = delegate { }; + + public delegate void TeamEventHandler(TeamEvent game_event); + + /// + public event TeamEventHandler TeamEvent = delegate { }; + + public delegate void PlayerEventHandler(PlayerEvent game_event); + + /// + public event PlayerEventHandler PlayerEvent = delegate { }; + + #endregion + + #region HeroEvents + + public delegate void HeroUpdatedHandler(HeroUpdated game_event); + + /// + public event HeroUpdatedHandler HeroUpdated = delegate { }; + + public delegate void HeroDetailsChangedHandler(HeroDetailsChanged game_event); + + /// + public event HeroDetailsChangedHandler HeroDetailsChanged = delegate { }; + + public delegate void HeroLevelChangedHandler(HeroLevelChanged game_event); + + /// + public event HeroLevelChangedHandler HeroLevelChanged = delegate { }; + + public delegate void HeroHealthChangedHandler(HeroHealthChanged game_event); + + /// + public event HeroHealthChangedHandler HeroHealthChanged = delegate { }; + + public delegate void HeroDiedHandler(HeroDied game_event); + + /// + public event HeroDiedHandler HeroDied = delegate { }; + + public delegate void HeroRespawnedHandler(HeroRespawned game_event); + + /// + public event HeroRespawnedHandler HeroRespawned = delegate { }; + + public delegate void HeroTookDamageHandler(HeroTookDamage game_event); + + /// + public event HeroTookDamageHandler HeroTookDamage = delegate { }; + + public delegate void HeroManaChangedHandler(HeroManaChanged game_event); + + /// + public event HeroManaChangedHandler HeroManaChanged = delegate { }; + + public delegate void HeroStateChangedHandler(HeroStateChanged game_event); + + /// + public event HeroStateChangedHandler HeroStateChanged = delegate { }; + + public delegate void HeroMuteStateChangedHandler(HeroMuteStateChanged game_event); + + /// + public event HeroMuteStateChangedHandler HeroMuteStateChanged = delegate { }; + + public delegate void HeroSelectedChangedHandler(HeroSelectedChanged game_event); + + /// + public event HeroSelectedChangedHandler HeroSelectedChanged = delegate { }; + + public delegate void HeroTalentTreeChangedHandler(HeroTalentTreeChanged game_event); + + /// + public event HeroTalentTreeChangedHandler HeroTalentTreeChanged = delegate { }; + + public delegate void HeroAttributesLevelChangedHandler(HeroAttributesLevelChanged game_event); + + /// + public event HeroAttributesLevelChangedHandler HeroAttributesLevelChanged = delegate { }; + + #endregion + + #region ItemsEvents + + public delegate void ItemsUpdatedHandler(ItemsUpdated game_event); + + /// + public event ItemsUpdatedHandler ItemsUpdated = delegate { }; + + public delegate void ItemDetailsChangedHandler(ItemDetailsChanged game_event); + + /// + public event ItemDetailsChangedHandler ItemDetailsChanged = delegate { }; + + #endregion + + #region LeagueEvents + + public delegate void LeagueUpdatedHandler(LeagueUpdated game_event); + + /// + public event LeagueUpdatedHandler LeagueUpdated = delegate { }; + + #endregion + + #region MapEvents + + public delegate void MapUpdatedHandler(MapUpdated game_event); + + /// + public event MapUpdatedHandler MapUpdated = delegate { }; + + public delegate void TimeOfDayChangedHandler(TimeOfDayChanged game_event); + + /// + public event TimeOfDayChangedHandler TimeOfDayChanged = delegate { }; + + public delegate void TeamScoreChangedHandler(TeamScoreChanged game_event); + + /// + public event TeamScoreChangedHandler TeamScoreChanged = delegate { }; + + public delegate void GameStateChangedHandler(GameStateChanged game_event); + + /// + public event GameStateChangedHandler GameStateChanged = delegate { }; + + public delegate void PauseStateChangedHandler(PauseStateChanged game_event); + + /// + public event PauseStateChangedHandler PauseStateChanged = delegate { }; + + public delegate void GamePausedHandler(GamePaused game_event); + + /// + public event GamePausedHandler GamePaused = delegate { }; + + public delegate void GameResumedHandler(GameResumed game_event); + + /// + public event GameResumedHandler GameResumed = delegate { }; + + public delegate void TeamVictoryHandler(TeamVictory game_event); + + /// + public event TeamVictoryHandler TeamVictory = delegate { }; + + public delegate void TeamDefeatHandler(TeamDefeat game_event); + + /// + public event TeamDefeatHandler TeamDefeat = delegate { }; + + public delegate void RoshanStateChangedHandler(RoshanStateChanged game_event); + + /// + public event RoshanStateChangedHandler RoshanStateChanged = delegate { }; + + #endregion + + #region MinimapEvents + + public delegate void MinimapUpdatedHandler(MinimapUpdated game_event); + + /// + public event MinimapUpdatedHandler MinimapUpdated = delegate { }; + + public delegate void MinimapElementUpdatedHandler(MinimapElementUpdated game_event); + + /// + public event MinimapElementUpdatedHandler MinimapElementUpdated = delegate { }; + + public delegate void TeamMinimapElementUpdatedHandler(TeamMinimapElementUpdated game_event); + + /// + public event TeamMinimapElementUpdatedHandler TeamMinimapElementUpdated = delegate { }; + + #endregion + + #region NeutralItemsEvents + + public delegate void NeutralItemsUpdatedHandler(NeutralItemsUpdated game_event); + + /// + public event NeutralItemsUpdatedHandler NeutralItemsUpdated = delegate { }; + + public delegate void TeamNeutralItemsUpdatedHandler(TeamNeutralItemsUpdated game_event); + + /// + public event TeamNeutralItemsUpdatedHandler TeamNeutralItemsUpdated = delegate { }; + + #endregion + + #region ProviderEvents + + public delegate void PlayerUpdatedHandler(PlayerUpdated game_event); + + /// + public event PlayerUpdatedHandler PlayerUpdated = delegate { }; + + public delegate void PlayerDetailsChangedHandler(PlayerDetailsChanged game_event); + + /// + public event PlayerDetailsChangedHandler PlayerDetailsChanged = delegate { }; + + public delegate void PlayerKillsChangedHandler(PlayerKillsChanged game_event); + + /// + public event PlayerKillsChangedHandler PlayerKillsChanged = delegate { }; + + public delegate void PlayerDeathsChangedHandler(PlayerDeathsChanged game_event); + + /// + public event PlayerDeathsChangedHandler PlayerDeathsChanged = delegate { }; + + public delegate void PlayerAssistsChangedHandler(PlayerAssistsChanged game_event); + + /// + public event PlayerAssistsChangedHandler PlayerAssistsChanged = delegate { }; + + public delegate void PlayerLastHitsChangedHandler(PlayerLastHitsChanged game_event); + + /// + public event PlayerLastHitsChangedHandler PlayerLastHitsChanged = delegate { }; + + public delegate void PlayerDeniesChangedHandler(PlayerDeniesChanged game_event); + + /// + public event PlayerDeniesChangedHandler PlayerDeniesChanged = delegate { }; + + public delegate void PlayerKillStreakChangedHandler(PlayerKillStreakChanged game_event); + + /// + public event PlayerKillStreakChangedHandler PlayerKillStreakChanged = delegate { }; + + public delegate void PlayerGoldChangedHandler(PlayerGoldChanged game_event); + + /// + public event PlayerGoldChangedHandler PlayerGoldChanged = delegate { }; + + public delegate void PlayerWardsPurchasedChangedHandler(PlayerWardsPurchasedChanged game_event); + + /// + public event PlayerWardsPurchasedChangedHandler PlayerWardsPurchasedChanged = delegate { }; + + public delegate void PlayerWardsPlacedChangedHandler(PlayerWardsPlacedChanged game_event); + + /// + public event PlayerWardsPlacedChangedHandler PlayerWardsPlacedChanged = delegate { }; + + public delegate void PlayerWardsDestroyedChangedHandler(PlayerWardsDestroyedChanged game_event); + + /// + public event PlayerWardsDestroyedChangedHandler PlayerWardsDestroyedChanged = delegate { }; + + public delegate void PlayerRunesActivatedChangedHandler(PlayerRunesActivatedChanged game_event); + + /// + public event PlayerRunesActivatedChangedHandler PlayerRunesActivatedChanged = delegate { }; + + public delegate void PlayerCampsStackedChangedHandler(PlayerCampsStackedChanged game_event); + + /// + public event PlayerCampsStackedChangedHandler PlayerCampsStackedChanged = delegate { }; + + #endregion + + #region ProviderEvents + + public delegate void ProviderUpdatedHandler(ProviderUpdated game_event); + + /// + public event ProviderUpdatedHandler ProviderUpdated = delegate { }; + + #endregion + + #region RoshanEvents + + public delegate void RoshanUpdatedHandler(RoshanUpdated game_event); + + /// + public event RoshanUpdatedHandler RoshanUpdated = delegate { }; + + #endregion + + #region WearablesEvents + + public delegate void WearablesUpdatedHandler(WearablesUpdated game_event); + + /// + public event WearablesUpdatedHandler WearablesUpdated = delegate { }; + + public delegate void PlayerWearablesUpdatedHandler(PlayerWearablesUpdated game_event); + + /// + public event PlayerWearablesUpdatedHandler PlayerWearablesUpdated = delegate { }; + + #endregion + + public Dota2EventsInterface() + { + } + + public override void OnNewGameEvent(DotaGameEvent e) + { + base.OnNewGameEvent(e); + + if (e is AbilitiesUpdated) + { + RaiseEvent(AbilitiesUpdated, e); + } + + if (e is AbilityDetailsChanged) + { + RaiseEvent(AbilityDetailsChanged, e); + } + + if (e is AbilityAdded) + { + RaiseEvent(AbilityAdded, e); + } + + if (e is AbilityRemoved) + { + RaiseEvent(AbilityRemoved, e); + } + + if (e is AbilityUpdated) + { + RaiseEvent(AbilityUpdated, e); + } + + if (e is AuthUpdated) + { + RaiseEvent(AuthUpdated, e); + } + + if (e is BuildingsUpdated) + { + RaiseEvent(BuildingsUpdated, e); + } + + if (e is BuildingsLayoutUpdated) + { + RaiseEvent(BuildingsLayoutUpdated, e); + } + + if (e is BuildingUpdated) + { + RaiseEvent(BuildingUpdated, e); + } + + if (e is TeamBuildingUpdated) + { + RaiseEvent(TeamBuildingUpdated, e); + } + + if (e is TeamBuildingDestroyed) + { + RaiseEvent(TeamBuildingDestroyed, e); + } + + if (e is TowerUpdated) + { + RaiseEvent(TowerUpdated, e); + } + + if (e is TowerDestroyed) + { + RaiseEvent(TowerDestroyed, e); + } + + if (e is RacksUpdated) + { + RaiseEvent(RacksUpdated, e); + } + + if (e is RacksDestroyed) + { + RaiseEvent(RacksDestroyed, e); + } + + if (e is AncientUpdated) + { + RaiseEvent(AncientUpdated, e); + } + + if (e is AncientDestroyed) + { + RaiseEvent(AncientDestroyed, e); + } + + if (e is CouriersUpdated) + { + RaiseEvent(CouriersUpdated, e); + } + + if (e is CourierUpdated) + { + RaiseEvent(CourierUpdated, e); + } + + if (e is TeamCourierUpdated) + { + RaiseEvent(TeamCourierUpdated, e); + } + + if (e is DraftUpdated) + { + RaiseEvent(DraftUpdated, e); + } + + if (e is TeamDraftDetailsUpdated) + { + RaiseEvent(TeamDraftDetailsUpdated, e); + } + + if (e is EventsUpdated) + { + RaiseEvent(EventsUpdated, e); + } + + if (e is GameplayEvent) + { + RaiseEvent(GameplayEvent, e); + } + + if (e is TeamEvent) + { + RaiseEvent(TeamEvent, e); + } + + if (e is PlayerEvent) + { + RaiseEvent(PlayerEvent, e); + } + + if (e is HeroUpdated) + { + RaiseEvent(HeroUpdated, e); + } + + if (e is HeroDetailsChanged) + { + RaiseEvent(HeroDetailsChanged, e); + } + + if (e is HeroLevelChanged) + { + RaiseEvent(HeroLevelChanged, e); + } + + if (e is HeroHealthChanged) + { + RaiseEvent(HeroHealthChanged, e); + } + + if (e is HeroDied) + { + RaiseEvent(HeroDied, e); + } + + if (e is HeroRespawned) + { + RaiseEvent(HeroRespawned, e); + } + + if (e is HeroTookDamage) + { + RaiseEvent(HeroTookDamage, e); + } + + if (e is HeroManaChanged) + { + RaiseEvent(HeroManaChanged, e); + } + + if (e is HeroStateChanged) + { + RaiseEvent(HeroStateChanged, e); + } + + if (e is HeroMuteStateChanged) + { + RaiseEvent(HeroMuteStateChanged, e); + } + + if (e is HeroSelectedChanged) + { + RaiseEvent(HeroSelectedChanged, e); + } + + if (e is HeroTalentTreeChanged) + { + RaiseEvent(HeroTalentTreeChanged, e); + } + + if (e is HeroAttributesLevelChanged) + { + RaiseEvent(HeroAttributesLevelChanged, e); + } + + if (e is ItemsUpdated) + { + RaiseEvent(ItemsUpdated, e); + } + + if (e is ItemDetailsChanged) + { + RaiseEvent(ItemDetailsChanged, e); + } + + if (e is LeagueUpdated) + { + RaiseEvent(LeagueUpdated, e); + } + + if (e is MapUpdated) + { + RaiseEvent(MapUpdated, e); + } + + if (e is TimeOfDayChanged) + { + RaiseEvent(TimeOfDayChanged, e); + } + + if (e is TeamScoreChanged) + { + RaiseEvent(TeamScoreChanged, e); + } + + if (e is GameStateChanged) + { + RaiseEvent(GameStateChanged, e); + } + + if (e is PauseStateChanged) + { + RaiseEvent(PauseStateChanged, e); + } + + if (e is GamePaused) + { + RaiseEvent(GamePaused, e); + } + + if (e is GameResumed) + { + RaiseEvent(GameResumed, e); + } + + if (e is TeamVictory) + { + RaiseEvent(TeamVictory, e); + } + + if (e is TeamDefeat) + { + RaiseEvent(TeamDefeat, e); + } + + if (e is RoshanStateChanged) + { + RaiseEvent(RoshanStateChanged, e); + } + + if (e is MinimapUpdated) + { + RaiseEvent(MinimapUpdated, e); + } + + if (e is MinimapElementUpdated) + { + RaiseEvent(MinimapElementUpdated, e); + } + + if (e is TeamMinimapElementUpdated) + { + RaiseEvent(TeamMinimapElementUpdated, e); + } + + if (e is NeutralItemsUpdated) + { + RaiseEvent(NeutralItemsUpdated, e); + } + + if (e is TeamNeutralItemsUpdated) + { + RaiseEvent(TeamNeutralItemsUpdated, e); + } + + if (e is PlayerUpdated) + { + RaiseEvent(PlayerUpdated, e); + } + + if (e is PlayerDetailsChanged) + { + RaiseEvent(PlayerDetailsChanged, e); + } + + if (e is PlayerKillsChanged) + { + RaiseEvent(PlayerKillsChanged, e); + } + + if (e is PlayerDeathsChanged) + { + RaiseEvent(PlayerDeathsChanged, e); + } + + if (e is PlayerAssistsChanged) + { + RaiseEvent(PlayerAssistsChanged, e); + } + + if (e is PlayerLastHitsChanged) + { + RaiseEvent(PlayerLastHitsChanged, e); + } + + if (e is PlayerDeniesChanged) + { + RaiseEvent(PlayerDeniesChanged, e); + } + + if (e is PlayerKillStreakChanged) + { + RaiseEvent(PlayerKillStreakChanged, e); + } + + if (e is PlayerGoldChanged) + { + RaiseEvent(PlayerGoldChanged, e); + } + + if (e is PlayerWardsPurchasedChanged) + { + RaiseEvent(PlayerWardsPurchasedChanged, e); + } + + if (e is PlayerWardsPlacedChanged) + { + RaiseEvent(PlayerWardsPlacedChanged, e); + } + + if (e is PlayerWardsDestroyedChanged) + { + RaiseEvent(PlayerWardsDestroyedChanged, e); + } + + if (e is PlayerRunesActivatedChanged) + { + RaiseEvent(PlayerRunesActivatedChanged, e); + } + + if (e is PlayerCampsStackedChanged) + { + RaiseEvent(PlayerCampsStackedChanged, e); + } + + if (e is ProviderUpdated) + { + RaiseEvent(ProviderUpdated, e); + } + + if (e is RoshanUpdated) + { + RaiseEvent(RoshanUpdated, e); + } + + if (e is WearablesUpdated) + { + RaiseEvent(WearablesUpdated, e); + } + + if (e is PlayerWearablesUpdated) + { + RaiseEvent(PlayerWearablesUpdated, e); + } + } + + } +} diff --git a/Dota2GSI/EventsInterface.cs b/Dota2GSI/EventsInterface.cs new file mode 100644 index 0000000..a3e7bc7 --- /dev/null +++ b/Dota2GSI/EventsInterface.cs @@ -0,0 +1,44 @@ +using Dota2GSI.EventMessages; +using System; +using System.ComponentModel; + +namespace Dota2GSI +{ + public class EventsInterface where T : BaseEvent + { + /// + /// Delegate for handing game events. + /// + /// The new game event. + public delegate void GameEventHandler(T game_event); + + /// + /// Event for handing GSI game events. + /// + public event GameEventHandler GameEvent = delegate { }; + + public EventsInterface() + { + } + + public virtual void OnNewGameEvent(T e) + { + RaiseEvent(GameEvent, e); + } + + protected void RaiseEvent(MulticastDelegate multi_delegate, object obj) + { + foreach (Delegate d in multi_delegate.GetInvocationList()) + { + if (d.Target is ISynchronizeInvoke) + { + (d.Target as ISynchronizeInvoke).BeginInvoke(d, new object[] { obj }); + } + else + { + d.DynamicInvoke(obj); + } + } + } + } +} diff --git a/Dota2GSI/GameStateListener.cs b/Dota2GSI/GameStateListener.cs index 224048a..ff255e7 100644 --- a/Dota2GSI/GameStateListener.cs +++ b/Dota2GSI/GameStateListener.cs @@ -1,7 +1,6 @@ -using Dota2GSI.EventMessages; +using Dota2GSI.EventMessages; using Newtonsoft.Json.Linq; using System; -using System.ComponentModel; using System.IO; using System.Net; using System.Text.RegularExpressions; @@ -24,7 +23,7 @@ namespace Dota2GSI /// /// /// - public class GameStateListener : IDisposable + public class GameStateListener : Dota2EventsInterface, IDisposable { /// /// The previous game state. @@ -33,7 +32,7 @@ public GameState PreviousGameState { get { - return previousGameState; + return _previous_game_state; } } @@ -44,44 +43,42 @@ public GameState CurrentGameState { get { - return currentGameState; + return _current_game_state; } private set { - previousGameState = currentGameState; - currentGameState = value; - RaiseOnNewGameState(ref currentGameState); + _previous_game_state = _current_game_state; + _current_game_state = value; + RaiseOnNewGameState(ref _current_game_state); } } /// /// Gets the port that is being listened. /// - public int Port { get { return connection_port; } } + public int Port { get { return _port; } } /// /// Returns whether or not the listener is running. /// - public bool Running { get { return isRunning; } } + public bool Running { get { return _is_running; } } /// /// Event for handing a newly received game state. /// public event NewGameStateHandler NewGameState = delegate { }; - /// - /// Event for handing Dota 2 game events. - /// - public event GameEventHandler GameEvent = delegate { }; + private bool _is_running = false; + private int _port; + private HttpListener _http_listener; + private AutoResetEvent _wait_for_connection = new AutoResetEvent(false); + private GameState _previous_game_state = new GameState(); + private GameState _current_game_state = new GameState(); - private bool isRunning = false; - private int connection_port; - private HttpListener net_Listener; - private AutoResetEvent waitForConnection = new AutoResetEvent(false); - private GameState previousGameState = new GameState(); - private GameState currentGameState = new GameState(); + // Dispatcher for game events. + private static EventDispatcher _dispatcher = new EventDispatcher(); - private static EventDispatcher dispatcher = new EventDispatcher(); + // Game State handlers. private AbilitiesHandler _abilities_handler = new AbilitiesHandler(ref _dispatcher); private AuthHandler _auth_handler = new AuthHandler(ref _dispatcher); private BuildingsHandler _buildings_handler = new BuildingsHandler(ref _dispatcher); @@ -98,17 +95,16 @@ private set private ProviderHandler _provider_handler = new ProviderHandler(ref _dispatcher); private RoshanHandler _roshan_handler = new RoshanHandler(ref _dispatcher); private WearablesHandler _wearables_handler = new WearablesHandler(ref _dispatcher); - private RoshanStateHandler roshan_state_handler = new RoshanStateHandler(ref dispatcher); - private WearablesStateHandler wearables_state_handler = new WearablesStateHandler(ref dispatcher); - private GameStateHandler game_state_handler = new GameStateHandler(ref dispatcher); + // Overall GameState handler. + private GameStateHandler _game_state_handler = new GameStateHandler(ref _dispatcher); /// /// Default constructor. /// private GameStateListener() { - dispatcher.GameEvent += RaiseOnDotaGameEvent; + _dispatcher.GameEvent += OnNewGameEvent; } /// @@ -117,9 +113,9 @@ private GameStateListener() /// The port to listen on. public GameStateListener(int Port) : this() { - connection_port = Port; - net_Listener = new HttpListener(); - net_Listener.Prefixes.Add("http://localhost:" + Port + "/"); + _port = Port; + _http_listener = new HttpListener(); + _http_listener.Prefixes.Add("http://localhost:" + Port + "/"); } /// @@ -141,10 +137,10 @@ public GameStateListener(string URI) : this() throw new ArgumentException("Not a valid URI: " + URI); } - connection_port = Convert.ToInt32(PortMatch.Groups[1].Value); + _port = Convert.ToInt32(PortMatch.Groups[1].Value); - net_Listener = new HttpListener(); - net_Listener.Prefixes.Add(URI); + _http_listener = new HttpListener(); + _http_listener.Prefixes.Add(URI); } /// @@ -152,18 +148,18 @@ public GameStateListener(string URI) : this() /// public bool Start() { - if (!isRunning) + if (!_is_running) { Thread ListenerThread = new Thread(new ThreadStart(Run)); try { - net_Listener.Start(); + _http_listener.Start(); } catch (HttpListenerException) { return false; } - isRunning = true; + _is_running = true; // Set this to true, so when the program wants to terminate, // this thread won't stop the program from exiting. @@ -181,29 +177,29 @@ public bool Start() /// public void Stop() { - isRunning = false; + _is_running = false; } private void Run() { - while (isRunning) + while (_is_running) { - net_Listener.BeginGetContext(ReceiveGameState, net_Listener); - waitForConnection.WaitOne(); - waitForConnection.Reset(); + _http_listener.BeginGetContext(ReceiveGameState, _http_listener); + _wait_for_connection.WaitOne(); + _wait_for_connection.Reset(); } - net_Listener.Stop(); + _http_listener.Stop(); } private void ReceiveGameState(IAsyncResult result) { try { - HttpListenerContext context = net_Listener.EndGetContext(result); + HttpListenerContext context = _http_listener.EndGetContext(result); HttpListenerRequest request = context.Request; string json_data; - waitForConnection.Set(); + _wait_for_connection.Set(); using (Stream inputStream = request.InputStream) { @@ -227,36 +223,11 @@ private void ReceiveGameState(IAsyncResult result) } } - private void RaiseOnDotaGameEvent(DotaGameEvent e) - { - foreach (Delegate d in GameEvent.GetInvocationList()) - { - if (d.Target is ISynchronizeInvoke) - { - (d.Target as ISynchronizeInvoke).BeginInvoke(d, new object[] { e }); - } - else - { - d.DynamicInvoke(e); - } - } - } - private void RaiseOnNewGameState(ref GameState game_state) { - foreach (Delegate d in NewGameState.GetInvocationList()) - { - if (d.Target is ISynchronizeInvoke) - { - (d.Target as ISynchronizeInvoke).BeginInvoke(d, new object[] { game_state }); - } - else - { - d.DynamicInvoke(game_state); - } - } + RaiseEvent(NewGameState, game_state); - game_state_handler.OnNewGameState(CurrentGameState); + _game_state_handler.OnNewGameState(CurrentGameState); } /// @@ -265,8 +236,8 @@ private void RaiseOnNewGameState(ref GameState game_state) public void Dispose() { Stop(); - waitForConnection.Dispose(); - net_Listener.Close(); + _wait_for_connection.Dispose(); + _http_listener.Close(); } } } From 95d548bf5608988cd0ffe32bfdbbab2e31ca167a Mon Sep 17 00:00:00 2001 From: Anton Pupkov Date: Wed, 17 Jan 2024 14:19:56 -0800 Subject: [PATCH 12/24] Add FullDetailsEvents --- Dota2GSI/CMakeLists.txt | 2 + Dota2GSI/EventMessages/FullDetailsEvents.cs | 44 +++++++++++++ Dota2GSI/GameStateHandler.cs | 22 +++++++ Dota2GSI/GameStateListener.cs | 3 + Dota2GSI/Nodes/Helpers/FullPlayerDetails.cs | 14 +++++ Dota2GSI/StateHandlers/FullDetailsHandler.cs | 65 ++++++++++++++++++++ 6 files changed, 150 insertions(+) create mode 100644 Dota2GSI/EventMessages/FullDetailsEvents.cs create mode 100644 Dota2GSI/StateHandlers/FullDetailsHandler.cs diff --git a/Dota2GSI/CMakeLists.txt b/Dota2GSI/CMakeLists.txt index 05f613d..d6dd3ca 100644 --- a/Dota2GSI/CMakeLists.txt +++ b/Dota2GSI/CMakeLists.txt @@ -31,6 +31,7 @@ SET(SOURCES EventMessages/DotaGameEvent.cs EventMessages/DraftEvents.cs EventMessages/EventsEvents.cs + EventMessages/FullDetailsEvents.cs EventMessages/HeroEvents.cs EventMessages/ItemsEvents.cs EventMessages/LeagueEvents.cs @@ -90,6 +91,7 @@ SET(SOURCES StateHandlers/CouriersHandler.cs StateHandlers/DraftHandler.cs StateHandlers/EventsHandler.cs + StateHandlers/FullDetailsHandler.cs StateHandlers/HeroHandler.cs StateHandlers/ItemsHandler.cs StateHandlers/LeagueHandler.cs diff --git a/Dota2GSI/EventMessages/FullDetailsEvents.cs b/Dota2GSI/EventMessages/FullDetailsEvents.cs new file mode 100644 index 0000000..4d1c403 --- /dev/null +++ b/Dota2GSI/EventMessages/FullDetailsEvents.cs @@ -0,0 +1,44 @@ +using Dota2GSI.Nodes.Helpers; + +namespace Dota2GSI.EventMessages +{ + /// + /// Event for overall Full Player Details update. + /// + public class FullPlayerDetailsUpdated : UpdateEvent + { + public FullPlayerDetailsUpdated(FullPlayerDetails new_value, FullPlayerDetails previous_value) : base(new_value, previous_value) + { + } + } + + /// + /// Event for overall Full Team Details update. + /// + public class FullTeamDetailsUpdated : UpdateEvent + { + public FullTeamDetailsUpdated(FullTeamDetails new_value, FullTeamDetails previous_value) : base(new_value, previous_value) + { + } + } + + /// + /// Event for Player Disconnected event. + /// + public class PlayerDisconnected : ValueEvent + { + public PlayerDisconnected(FullPlayerDetails value) : base(value) + { + } + } + + /// + /// Event for Player Connected event. + /// + public class PlayerConnected : ValueEvent + { + public PlayerConnected(FullPlayerDetails value) : base(value) + { + } + } +} diff --git a/Dota2GSI/GameStateHandler.cs b/Dota2GSI/GameStateHandler.cs index 37fd955..ae9572a 100644 --- a/Dota2GSI/GameStateHandler.cs +++ b/Dota2GSI/GameStateHandler.cs @@ -24,6 +24,28 @@ public void OnNewGameState(GameState game_state) previous_game_state = game_state.Previously; } + // Broadcast changes for custom providers. + + if (!previous_game_state.LocalPlayer.Equals(game_state.LocalPlayer)) + { + dispatcher.Broadcast(new FullPlayerDetailsUpdated(game_state.LocalPlayer, previous_game_state.LocalPlayer)); + } + + if (!previous_game_state.RadiantTeamDetails.Equals(game_state.RadiantTeamDetails)) + { + dispatcher.Broadcast(new FullTeamDetailsUpdated(game_state.RadiantTeamDetails, previous_game_state.RadiantTeamDetails)); + } + + if (!previous_game_state.DireTeamDetails.Equals(game_state.DireTeamDetails)) + { + dispatcher.Broadcast(new FullTeamDetailsUpdated(game_state.DireTeamDetails, previous_game_state.DireTeamDetails)); + } + + if (!previous_game_state.NeutralTeamDetails.Equals(game_state.NeutralTeamDetails)) + { + dispatcher.Broadcast(new FullTeamDetailsUpdated(game_state.NeutralTeamDetails, previous_game_state.NeutralTeamDetails)); + } + // Broadcast changes for providers. if (!previous_game_state.Auth.Equals(game_state.Auth)) diff --git a/Dota2GSI/GameStateListener.cs b/Dota2GSI/GameStateListener.cs index ff255e7..c0fc1de 100644 --- a/Dota2GSI/GameStateListener.cs +++ b/Dota2GSI/GameStateListener.cs @@ -96,6 +96,9 @@ private set private RoshanHandler _roshan_handler = new RoshanHandler(ref _dispatcher); private WearablesHandler _wearables_handler = new WearablesHandler(ref _dispatcher); + // Custom handlers. + private FullDetailsHandler _full_details_handler = new FullDetailsHandler(ref _dispatcher); + // Overall GameState handler. private GameStateHandler _game_state_handler = new GameStateHandler(ref _dispatcher); diff --git a/Dota2GSI/Nodes/Helpers/FullPlayerDetails.cs b/Dota2GSI/Nodes/Helpers/FullPlayerDetails.cs index 43ef347..0994130 100644 --- a/Dota2GSI/Nodes/Helpers/FullPlayerDetails.cs +++ b/Dota2GSI/Nodes/Helpers/FullPlayerDetails.cs @@ -13,6 +13,16 @@ namespace Dota2GSI.Nodes.Helpers /// public class FullPlayerDetails { + /// + /// Player's ID. -1 for local player. + /// + public readonly int PlayerID; + + /// + /// True if player details are for the local player. + /// + public readonly bool IsLocalPlayer; + /// /// Player's basic details. /// @@ -50,6 +60,8 @@ public class FullPlayerDetails internal FullPlayerDetails(int player_id, GameState game_state) { + IsLocalPlayer = false; + PlayerID = player_id; Details = game_state.Player.GetForPlayer(player_id); Hero = game_state.Hero.GetForPlayer(player_id); Abilities = game_state.Abilities.GetForPlayer(player_id); @@ -61,6 +73,8 @@ internal FullPlayerDetails(int player_id, GameState game_state) internal FullPlayerDetails(GameState game_state) { + IsLocalPlayer = true; + PlayerID = -1; Details = game_state.Player.LocalPlayer; Hero = game_state.Hero.LocalPlayer; Abilities = game_state.Abilities.LocalPlayer; diff --git a/Dota2GSI/StateHandlers/FullDetailsHandler.cs b/Dota2GSI/StateHandlers/FullDetailsHandler.cs new file mode 100644 index 0000000..9fbe797 --- /dev/null +++ b/Dota2GSI/StateHandlers/FullDetailsHandler.cs @@ -0,0 +1,65 @@ +using Dota2GSI.EventMessages; + +namespace Dota2GSI +{ + public class FullDetailsHandler : EventHandler + { + public FullDetailsHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) + { + dispatcher.Subscribe(OnFullPlayerDetailsUpdated); + dispatcher.Subscribe(OnFullTeamDetailsUpdated); + } + + ~FullDetailsHandler() + { + dispatcher.Unsubscribe(OnFullPlayerDetailsUpdated); + dispatcher.Unsubscribe(OnFullTeamDetailsUpdated); + } + + private void OnFullPlayerDetailsUpdated(DotaGameEvent e) + { + FullPlayerDetailsUpdated evt = (e as FullPlayerDetailsUpdated); + + if (evt == null) + { + return; + } + } + + private void OnFullTeamDetailsUpdated(DotaGameEvent e) + { + FullTeamDetailsUpdated evt = (e as FullTeamDetailsUpdated); + + if (evt == null) + { + return; + } + + foreach(var player_kvp in evt.New.Players) + { + if (!evt.Previous.Players.ContainsKey(player_kvp.Key)) + { + // The player did not exist before. + dispatcher.Broadcast(new PlayerConnected(player_kvp.Value)); + continue; + } + + var previous_player = evt.Previous.Players[player_kvp.Key]; + + if (!player_kvp.Value.Equals(previous_player)) + { + dispatcher.Broadcast(new FullPlayerDetailsUpdated(player_kvp.Value, previous_player)); + } + } + + foreach (var player_kvp in evt.Previous.Players) + { + if (!evt.New.Players.ContainsKey(player_kvp.Key)) + { + // The player does not exist anymore. + dispatcher.Broadcast(new PlayerDisconnected(player_kvp.Value)); + } + } + } + } +} From b850af4ab5745d94b1573dd1f47046454711c368 Mon Sep 17 00:00:00 2001 From: Anton Pupkov Date: Wed, 17 Jan 2024 15:31:00 -0800 Subject: [PATCH 13/24] Replace PlayerID with FullPlayerDetails in Player events --- Dota2GSI/EventMessages/AbilitiesEvents.cs | 9 ++-- Dota2GSI/EventMessages/CouriersEvents.cs | 3 +- Dota2GSI/EventMessages/EventsEvents.cs | 3 +- Dota2GSI/EventMessages/HeroEvents.cs | 25 +++++----- Dota2GSI/EventMessages/ItemsEvents.cs | 3 +- Dota2GSI/EventMessages/PlayerEvents.cs | 27 ++++++----- Dota2GSI/EventMessages/UpdateEvent.cs | 19 ++++---- Dota2GSI/EventMessages/WearablesEvents.cs | 3 +- Dota2GSI/GameStateHandler.cs | 7 +++ Dota2GSI/StateHandlers/AbilitiesHandler.cs | 31 +++++++++--- Dota2GSI/StateHandlers/CouriersHandler.cs | 21 ++++---- Dota2GSI/StateHandlers/EventsHandler.cs | 35 +++++++------- Dota2GSI/StateHandlers/FullDetailsHandler.cs | 2 +- Dota2GSI/StateHandlers/HeroHandler.cs | 50 +++++++++++++------- Dota2GSI/StateHandlers/ItemsHandler.cs | 22 ++++++++- Dota2GSI/StateHandlers/PlayerHandler.cs | 48 +++++++++++++------ Dota2GSI/StateHandlers/WearablesHandler.cs | 22 ++++++++- 17 files changed, 218 insertions(+), 112 deletions(-) diff --git a/Dota2GSI/EventMessages/AbilitiesEvents.cs b/Dota2GSI/EventMessages/AbilitiesEvents.cs index ccbe92f..b8b8ec3 100644 --- a/Dota2GSI/EventMessages/AbilitiesEvents.cs +++ b/Dota2GSI/EventMessages/AbilitiesEvents.cs @@ -1,5 +1,6 @@ using Dota2GSI.Nodes; using Dota2GSI.Nodes.AbilitiesProvider; +using Dota2GSI.Nodes.Helpers; namespace Dota2GSI.EventMessages { @@ -18,7 +19,7 @@ public AbilitiesUpdated(Abilities new_value, Abilities previous_value) : base(ne /// public class AbilityDetailsChanged : PlayerUpdateEvent { - public AbilityDetailsChanged(AbilityDetails new_value, AbilityDetails previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + public AbilityDetailsChanged(AbilityDetails new_value, AbilityDetails previous_value, FullPlayerDetails player) : base(new_value, previous_value, player) { } } @@ -28,7 +29,7 @@ public AbilityDetailsChanged(AbilityDetails new_value, AbilityDetails previous_v /// public class AbilityAdded : PlayerValueEvent { - public AbilityAdded(Ability value, int player_id = -1) : base(value, player_id) + public AbilityAdded(Ability value, FullPlayerDetails player) : base(value, player) { } } @@ -38,7 +39,7 @@ public AbilityAdded(Ability value, int player_id = -1) : base(value, player_id) /// public class AbilityRemoved : PlayerValueEvent { - public AbilityRemoved(Ability value, int player_id = -1) : base(value, player_id) + public AbilityRemoved(Ability value, FullPlayerDetails player) : base(value, player) { } } @@ -48,7 +49,7 @@ public AbilityRemoved(Ability value, int player_id = -1) : base(value, player_id /// public class AbilityUpdated : PlayerUpdateEvent { - public AbilityUpdated(Ability new_value, Ability previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + public AbilityUpdated(Ability new_value, Ability previous_value, FullPlayerDetails player) : base(new_value, previous_value, player) { } } diff --git a/Dota2GSI/EventMessages/CouriersEvents.cs b/Dota2GSI/EventMessages/CouriersEvents.cs index 2b916f1..8a822b5 100644 --- a/Dota2GSI/EventMessages/CouriersEvents.cs +++ b/Dota2GSI/EventMessages/CouriersEvents.cs @@ -1,5 +1,6 @@ using Dota2GSI.Nodes; using Dota2GSI.Nodes.CouriersProvider; +using Dota2GSI.Nodes.Helpers; namespace Dota2GSI.EventMessages { @@ -18,7 +19,7 @@ public CouriersUpdated(Couriers new_value, Couriers previous_value) : base(new_v /// public class CourierUpdated : PlayerUpdateEvent { - public CourierUpdated(Courier new_value, Courier previous_value, int player_id) : base(new_value, previous_value, player_id) + public CourierUpdated(Courier new_value, Courier previous_value, FullPlayerDetails player) : base(new_value, previous_value, player) { } } diff --git a/Dota2GSI/EventMessages/EventsEvents.cs b/Dota2GSI/EventMessages/EventsEvents.cs index 36c5c53..34234b5 100644 --- a/Dota2GSI/EventMessages/EventsEvents.cs +++ b/Dota2GSI/EventMessages/EventsEvents.cs @@ -1,5 +1,6 @@ using Dota2GSI.Nodes; using Dota2GSI.Nodes.EventsProvider; +using Dota2GSI.Nodes.Helpers; namespace Dota2GSI.EventMessages { @@ -38,7 +39,7 @@ public TeamEvent(Event value, PlayerTeam team) : base(value, team) /// public class PlayerEvent : PlayerValueEvent { - public PlayerEvent(Event value, int player_id) : base(value, player_id) + public PlayerEvent(Event value, FullPlayerDetails player) : base(value, player) { } } diff --git a/Dota2GSI/EventMessages/HeroEvents.cs b/Dota2GSI/EventMessages/HeroEvents.cs index c560c9a..47add26 100644 --- a/Dota2GSI/EventMessages/HeroEvents.cs +++ b/Dota2GSI/EventMessages/HeroEvents.cs @@ -1,4 +1,5 @@ using Dota2GSI.Nodes; +using Dota2GSI.Nodes.Helpers; using Dota2GSI.Nodes.HeroProvider; namespace Dota2GSI.EventMessages @@ -18,7 +19,7 @@ public HeroUpdated(Hero new_value, Hero previous_value) : base(new_value, previo /// public class HeroDetailsChanged : PlayerUpdateEvent { - public HeroDetailsChanged(HeroDetails new_value, HeroDetails previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + public HeroDetailsChanged(HeroDetails new_value, HeroDetails previous_value, FullPlayerDetails player) : base(new_value, previous_value, player) { } } @@ -28,7 +29,7 @@ public HeroDetailsChanged(HeroDetails new_value, HeroDetails previous_value, int /// public class HeroLevelChanged : PlayerUpdateEvent { - public HeroLevelChanged(int new_value, int previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + public HeroLevelChanged(int new_value, int previous_value, FullPlayerDetails player) : base(new_value, previous_value, player) { } } @@ -38,7 +39,7 @@ public HeroLevelChanged(int new_value, int previous_value, int player_id = -1) : /// public class HeroHealthChanged : PlayerUpdateEvent { - public HeroHealthChanged(int new_value, int previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + public HeroHealthChanged(int new_value, int previous_value, FullPlayerDetails player) : base(new_value, previous_value, player) { } } @@ -48,7 +49,7 @@ public HeroHealthChanged(int new_value, int previous_value, int player_id = -1) /// public class HeroDied : HeroHealthChanged { - public HeroDied(int new_value, int previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + public HeroDied(int new_value, int previous_value, FullPlayerDetails player) : base(new_value, previous_value, player) { } } @@ -58,7 +59,7 @@ public HeroDied(int new_value, int previous_value, int player_id = -1) : base(ne /// public class HeroRespawned : HeroHealthChanged { - public HeroRespawned(int new_value, int previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + public HeroRespawned(int new_value, int previous_value, FullPlayerDetails player) : base(new_value, previous_value, player) { } } @@ -68,7 +69,7 @@ public HeroRespawned(int new_value, int previous_value, int player_id = -1) : ba /// public class HeroTookDamage : HeroHealthChanged { - public HeroTookDamage(int new_value, int previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + public HeroTookDamage(int new_value, int previous_value, FullPlayerDetails player) : base(new_value, previous_value, player) { } } @@ -78,7 +79,7 @@ public HeroTookDamage(int new_value, int previous_value, int player_id = -1) : b /// public class HeroManaChanged : PlayerUpdateEvent { - public HeroManaChanged(int new_value, int previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + public HeroManaChanged(int new_value, int previous_value, FullPlayerDetails player) : base(new_value, previous_value, player) { } } @@ -88,7 +89,7 @@ public HeroManaChanged(int new_value, int previous_value, int player_id = -1) : /// public class HeroStateChanged : PlayerUpdateEvent { - public HeroStateChanged(HeroState new_value, HeroState previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + public HeroStateChanged(HeroState new_value, HeroState previous_value, FullPlayerDetails player) : base(new_value, previous_value, player) { } } @@ -98,7 +99,7 @@ public HeroStateChanged(HeroState new_value, HeroState previous_value, int playe /// public class HeroMuteStateChanged : PlayerUpdateEvent { - public HeroMuteStateChanged(bool new_value, bool previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + public HeroMuteStateChanged(bool new_value, bool previous_value, FullPlayerDetails player) : base(new_value, previous_value, player) { } } @@ -108,7 +109,7 @@ public HeroMuteStateChanged(bool new_value, bool previous_value, int player_id = /// public class HeroSelectedChanged : PlayerUpdateEvent { - public HeroSelectedChanged(bool new_value, bool previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + public HeroSelectedChanged(bool new_value, bool previous_value, FullPlayerDetails player) : base(new_value, previous_value, player) { } } @@ -118,7 +119,7 @@ public HeroSelectedChanged(bool new_value, bool previous_value, int player_id = /// public class HeroTalentTreeChanged : PlayerUpdateEvent { - public HeroTalentTreeChanged(TalentTreeSpec[] new_value, TalentTreeSpec[] previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + public HeroTalentTreeChanged(TalentTreeSpec[] new_value, TalentTreeSpec[] previous_value, FullPlayerDetails player) : base(new_value, previous_value, player) { } } @@ -128,7 +129,7 @@ public HeroTalentTreeChanged(TalentTreeSpec[] new_value, TalentTreeSpec[] previo /// public class HeroAttributesLevelChanged : PlayerUpdateEvent { - public HeroAttributesLevelChanged(int new_value, int previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + public HeroAttributesLevelChanged(int new_value, int previous_value, FullPlayerDetails player) : base(new_value, previous_value, player) { } } diff --git a/Dota2GSI/EventMessages/ItemsEvents.cs b/Dota2GSI/EventMessages/ItemsEvents.cs index 2993604..7c92d36 100644 --- a/Dota2GSI/EventMessages/ItemsEvents.cs +++ b/Dota2GSI/EventMessages/ItemsEvents.cs @@ -1,4 +1,5 @@ using Dota2GSI.Nodes; +using Dota2GSI.Nodes.Helpers; using Dota2GSI.Nodes.ItemsProvider; namespace Dota2GSI.EventMessages @@ -18,7 +19,7 @@ public ItemsUpdated(Items new_value, Items previous_value) : base(new_value, pre /// public class ItemDetailsChanged : PlayerUpdateEvent { - public ItemDetailsChanged(ItemDetails new_value, ItemDetails previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + public ItemDetailsChanged(ItemDetails new_value, ItemDetails previous_value, FullPlayerDetails player) : base(new_value, previous_value, player) { } } diff --git a/Dota2GSI/EventMessages/PlayerEvents.cs b/Dota2GSI/EventMessages/PlayerEvents.cs index c0d97bc..08957fb 100644 --- a/Dota2GSI/EventMessages/PlayerEvents.cs +++ b/Dota2GSI/EventMessages/PlayerEvents.cs @@ -1,4 +1,5 @@ using Dota2GSI.Nodes; +using Dota2GSI.Nodes.Helpers; using Dota2GSI.Nodes.PlayerProvider; namespace Dota2GSI.EventMessages @@ -18,7 +19,7 @@ public PlayerUpdated(Player new_value, Player previous_value) : base(new_value, /// public class PlayerDetailsChanged : PlayerUpdateEvent { - public PlayerDetailsChanged(PlayerDetails new_value, PlayerDetails previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + public PlayerDetailsChanged(PlayerDetails new_value, PlayerDetails previous_value, FullPlayerDetails player) : base(new_value, previous_value, player) { } } @@ -28,7 +29,7 @@ public PlayerDetailsChanged(PlayerDetails new_value, PlayerDetails previous_valu /// public class PlayerKillsChanged : PlayerUpdateEvent { - public PlayerKillsChanged(int new_value, int previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + public PlayerKillsChanged(int new_value, int previous_value, FullPlayerDetails player) : base(new_value, previous_value, player) { } } @@ -38,7 +39,7 @@ public PlayerKillsChanged(int new_value, int previous_value, int player_id = -1) /// public class PlayerDeathsChanged : PlayerUpdateEvent { - public PlayerDeathsChanged(int new_value, int previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + public PlayerDeathsChanged(int new_value, int previous_value, FullPlayerDetails player) : base(new_value, previous_value, player) { } } @@ -48,7 +49,7 @@ public PlayerDeathsChanged(int new_value, int previous_value, int player_id = -1 /// public class PlayerAssistsChanged : PlayerUpdateEvent { - public PlayerAssistsChanged(int new_value, int previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + public PlayerAssistsChanged(int new_value, int previous_value, FullPlayerDetails player) : base(new_value, previous_value, player) { } } @@ -58,7 +59,7 @@ public PlayerAssistsChanged(int new_value, int previous_value, int player_id = - /// public class PlayerLastHitsChanged : PlayerUpdateEvent { - public PlayerLastHitsChanged(int new_value, int previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + public PlayerLastHitsChanged(int new_value, int previous_value, FullPlayerDetails player) : base(new_value, previous_value, player) { } } @@ -68,7 +69,7 @@ public PlayerLastHitsChanged(int new_value, int previous_value, int player_id = /// public class PlayerDeniesChanged : PlayerUpdateEvent { - public PlayerDeniesChanged(int new_value, int previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + public PlayerDeniesChanged(int new_value, int previous_value, FullPlayerDetails player) : base(new_value, previous_value, player) { } } @@ -78,7 +79,7 @@ public PlayerDeniesChanged(int new_value, int previous_value, int player_id = -1 /// public class PlayerKillStreakChanged : PlayerUpdateEvent { - public PlayerKillStreakChanged(int new_value, int previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + public PlayerKillStreakChanged(int new_value, int previous_value, FullPlayerDetails player) : base(new_value, previous_value, player) { } } @@ -88,7 +89,7 @@ public PlayerKillStreakChanged(int new_value, int previous_value, int player_id /// public class PlayerGoldChanged : PlayerUpdateEvent { - public PlayerGoldChanged(int new_value, int previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + public PlayerGoldChanged(int new_value, int previous_value, FullPlayerDetails player) : base(new_value, previous_value, player) { } } @@ -98,7 +99,7 @@ public PlayerGoldChanged(int new_value, int previous_value, int player_id = -1) /// public class PlayerWardsPurchasedChanged : PlayerUpdateEvent { - public PlayerWardsPurchasedChanged(int new_value, int previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + public PlayerWardsPurchasedChanged(int new_value, int previous_value, FullPlayerDetails player) : base(new_value, previous_value, player) { } } @@ -108,7 +109,7 @@ public PlayerWardsPurchasedChanged(int new_value, int previous_value, int player /// public class PlayerWardsPlacedChanged : PlayerUpdateEvent { - public PlayerWardsPlacedChanged(int new_value, int previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + public PlayerWardsPlacedChanged(int new_value, int previous_value, FullPlayerDetails player) : base(new_value, previous_value, player) { } } @@ -118,7 +119,7 @@ public PlayerWardsPlacedChanged(int new_value, int previous_value, int player_id /// public class PlayerWardsDestroyedChanged : PlayerUpdateEvent { - public PlayerWardsDestroyedChanged(int new_value, int previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + public PlayerWardsDestroyedChanged(int new_value, int previous_value, FullPlayerDetails player) : base(new_value, previous_value, player) { } } @@ -128,7 +129,7 @@ public PlayerWardsDestroyedChanged(int new_value, int previous_value, int player /// public class PlayerRunesActivatedChanged : PlayerUpdateEvent { - public PlayerRunesActivatedChanged(int new_value, int previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + public PlayerRunesActivatedChanged(int new_value, int previous_value, FullPlayerDetails player) : base(new_value, previous_value, player) { } } @@ -138,7 +139,7 @@ public PlayerRunesActivatedChanged(int new_value, int previous_value, int player /// public class PlayerCampsStackedChanged : PlayerUpdateEvent { - public PlayerCampsStackedChanged(int new_value, int previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + public PlayerCampsStackedChanged(int new_value, int previous_value, FullPlayerDetails player) : base(new_value, previous_value, player) { } } diff --git a/Dota2GSI/EventMessages/UpdateEvent.cs b/Dota2GSI/EventMessages/UpdateEvent.cs index 7da04ab..2b01ff2 100644 --- a/Dota2GSI/EventMessages/UpdateEvent.cs +++ b/Dota2GSI/EventMessages/UpdateEvent.cs @@ -1,4 +1,5 @@ using Dota2GSI.Nodes; +using Dota2GSI.Nodes.Helpers; namespace Dota2GSI.EventMessages { @@ -26,14 +27,13 @@ public ValueEvent(T obj) public class PlayerValueEvent : ValueEvent { /// - /// The associated player ID. - /// When local player, the player ID is -1. + /// The associated player details. /// - public readonly int PlayerID; + public readonly FullPlayerDetails Player; - public PlayerValueEvent(T obj, int player_id = -1) : base(obj) + public PlayerValueEvent(T obj, FullPlayerDetails player) : base(obj) { - PlayerID = player_id; + Player = player; } } @@ -84,14 +84,13 @@ public UpdateEvent(T new_obj, T previous_obj) public class PlayerUpdateEvent : UpdateEvent { /// - /// The associated player ID. - /// When local player, the player ID is -1. + /// The associated player. /// - public readonly int PlayerID; + public readonly FullPlayerDetails Player; - public PlayerUpdateEvent(T new_obj, T previous_obj, int player_id = -1) : base(new_obj, previous_obj) + public PlayerUpdateEvent(T new_obj, T previous_obj, FullPlayerDetails player) : base(new_obj, previous_obj) { - PlayerID = player_id; + Player = player; } } diff --git a/Dota2GSI/EventMessages/WearablesEvents.cs b/Dota2GSI/EventMessages/WearablesEvents.cs index aebabfb..87a3bb8 100644 --- a/Dota2GSI/EventMessages/WearablesEvents.cs +++ b/Dota2GSI/EventMessages/WearablesEvents.cs @@ -1,4 +1,5 @@ using Dota2GSI.Nodes; +using Dota2GSI.Nodes.Helpers; using Dota2GSI.Nodes.WearablesProvider; namespace Dota2GSI.EventMessages @@ -18,7 +19,7 @@ public WearablesUpdated(Wearables new_value, Wearables previous_value) : base(ne /// public class PlayerWearablesUpdated : PlayerUpdateEvent { - public PlayerWearablesUpdated(PlayerWearables new_value, PlayerWearables previous_value, int player_id = -1) : base(new_value, previous_value, player_id) + public PlayerWearablesUpdated(PlayerWearables new_value, PlayerWearables previous_value, FullPlayerDetails player) : base(new_value, previous_value, player) { } } diff --git a/Dota2GSI/GameStateHandler.cs b/Dota2GSI/GameStateHandler.cs index ae9572a..7a5612d 100644 --- a/Dota2GSI/GameStateHandler.cs +++ b/Dota2GSI/GameStateHandler.cs @@ -65,26 +65,31 @@ public void OnNewGameState(GameState game_state) if (!previous_game_state.Player.Equals(game_state.Player)) { + // Depends on FullPlayerDetailsUpdated. This broadcast must happen after FullPlayerDetailsUpdated. dispatcher.Broadcast(new PlayerUpdated(game_state.Player, previous_game_state.Player)); } if (!previous_game_state.Hero.Equals(game_state.Hero)) { + // Depends on FullPlayerDetailsUpdated. This broadcast must happen after FullPlayerDetailsUpdated. dispatcher.Broadcast(new HeroUpdated(game_state.Hero, previous_game_state.Hero)); } if (!previous_game_state.Abilities.Equals(game_state.Abilities)) { + // Depends on FullPlayerDetailsUpdated. This broadcast must happen after FullPlayerDetailsUpdated. dispatcher.Broadcast(new AbilitiesUpdated(game_state.Abilities, previous_game_state.Abilities)); } if (!previous_game_state.Items.Equals(game_state.Items)) { + // Depends on FullPlayerDetailsUpdated. This broadcast must happen after FullPlayerDetailsUpdated. dispatcher.Broadcast(new ItemsUpdated(game_state.Items, previous_game_state.Items)); } if (!previous_game_state.Events.Equals(game_state.Events)) { + // Depends on FullPlayerDetailsUpdated. This broadcast must happen after FullPlayerDetailsUpdated. dispatcher.Broadcast(new EventsUpdated(game_state.Events, previous_game_state.Events)); } @@ -105,6 +110,7 @@ public void OnNewGameState(GameState game_state) if (!previous_game_state.Wearables.Equals(game_state.Wearables)) { + // Depends on FullPlayerDetailsUpdated. This broadcast must happen after FullPlayerDetailsUpdated. dispatcher.Broadcast(new WearablesUpdated(game_state.Wearables, previous_game_state.Wearables)); } @@ -120,6 +126,7 @@ public void OnNewGameState(GameState game_state) if (!previous_game_state.Couriers.Equals(game_state.Couriers)) { + // Depends on FullPlayerDetailsUpdated. This broadcast must happen after FullPlayerDetailsUpdated. dispatcher.Broadcast(new CouriersUpdated(game_state.Couriers, previous_game_state.Couriers)); } diff --git a/Dota2GSI/StateHandlers/AbilitiesHandler.cs b/Dota2GSI/StateHandlers/AbilitiesHandler.cs index 1f97e84..28cbd77 100644 --- a/Dota2GSI/StateHandlers/AbilitiesHandler.cs +++ b/Dota2GSI/StateHandlers/AbilitiesHandler.cs @@ -1,23 +1,41 @@ using Dota2GSI.EventMessages; using Dota2GSI.Nodes.AbilitiesProvider; +using Dota2GSI.Nodes.Helpers; +using System.Collections.Generic; using System.Linq; namespace Dota2GSI { public class AbilitiesHandler : EventHandler { + private Dictionary _player_cache = new Dictionary(); + public AbilitiesHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { + dispatcher.Subscribe(OnFullPlayerDetailsUpdated); dispatcher.Subscribe(OnAbilitiesStateUpdated); dispatcher.Subscribe(OnAbilityDetailsChanged); } ~AbilitiesHandler() { + dispatcher.Unsubscribe(OnFullPlayerDetailsUpdated); dispatcher.Unsubscribe(OnAbilitiesStateUpdated); dispatcher.Unsubscribe(OnAbilityDetailsChanged); } + private void OnFullPlayerDetailsUpdated(DotaGameEvent e) + { + FullPlayerDetailsUpdated evt = (e as FullPlayerDetailsUpdated); + + if (evt == null) + { + return; + } + + _player_cache[evt.New.PlayerID] = evt.New; + } + private void OnAbilitiesStateUpdated(DotaGameEvent e) { AbilitiesUpdated evt = (e as AbilitiesUpdated); @@ -29,7 +47,7 @@ private void OnAbilitiesStateUpdated(DotaGameEvent e) if (!evt.New.LocalPlayer.Equals(evt.Previous.LocalPlayer)) { - dispatcher.Broadcast(new AbilityDetailsChanged(evt.New.LocalPlayer, evt.Previous.LocalPlayer)); + dispatcher.Broadcast(new AbilityDetailsChanged(evt.New.LocalPlayer, evt.Previous.LocalPlayer, _player_cache[-1])); } foreach (var team_kvp in evt.New.Teams) @@ -39,9 +57,9 @@ private void OnAbilitiesStateUpdated(DotaGameEvent e) // Get corresponding previous hero details. var previous_ability_details = evt.Previous.GetForPlayer(player_kvp.Key); - if (!player_kvp.Value.Equals(previous_ability_details)) + if (!player_kvp.Value.Equals(previous_ability_details) && previous_ability_details.IsValid()) { - dispatcher.Broadcast(new AbilityDetailsChanged(player_kvp.Value, previous_ability_details, player_kvp.Key)); + dispatcher.Broadcast(new AbilityDetailsChanged(player_kvp.Value, previous_ability_details, _player_cache[player_kvp.Key])); } } } @@ -62,12 +80,13 @@ private void OnAbilityDetailsChanged(DotaGameEvent e) if (found_ability == null) { - dispatcher.Broadcast(new AbilityAdded(ability, evt.PlayerID)); + dispatcher.Broadcast(new AbilityAdded(ability, evt.Player)); + continue; } if (!ability.Equals(found_ability)) { - dispatcher.Broadcast(new AbilityUpdated(ability, found_ability, evt.PlayerID)); + dispatcher.Broadcast(new AbilityUpdated(ability, found_ability, evt.Player)); } } @@ -77,7 +96,7 @@ private void OnAbilityDetailsChanged(DotaGameEvent e) if (found_ability == null) { - dispatcher.Broadcast(new AbilityRemoved(ability, evt.PlayerID)); + dispatcher.Broadcast(new AbilityRemoved(ability, evt.Player)); } } } diff --git a/Dota2GSI/StateHandlers/CouriersHandler.cs b/Dota2GSI/StateHandlers/CouriersHandler.cs index a305806..139bf7b 100644 --- a/Dota2GSI/StateHandlers/CouriersHandler.cs +++ b/Dota2GSI/StateHandlers/CouriersHandler.cs @@ -1,34 +1,35 @@ using Dota2GSI.EventMessages; -using Dota2GSI.Nodes; +using Dota2GSI.Nodes.Helpers; +using System.Collections.Generic; namespace Dota2GSI { public class CouriersHandler : EventHandler { - private Player current_player_state = new Player(); + private Dictionary _player_cache = new Dictionary(); public CouriersHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { + dispatcher.Subscribe(OnFullPlayerDetailsUpdated); dispatcher.Subscribe(OnCouriersStateUpdated); - dispatcher.Subscribe(OnPlayerStateUpdated); } ~CouriersHandler() { + dispatcher.Unsubscribe(OnFullPlayerDetailsUpdated); dispatcher.Unsubscribe(OnCouriersStateUpdated); - dispatcher.Unsubscribe(OnPlayerStateUpdated); } - private void OnPlayerStateUpdated(DotaGameEvent e) + private void OnFullPlayerDetailsUpdated(DotaGameEvent e) { - PlayerUpdated evt = (e as PlayerUpdated); + FullPlayerDetailsUpdated evt = (e as FullPlayerDetailsUpdated); if (evt == null) { return; } - current_player_state = evt.New; + _player_cache[evt.New.PlayerID] = evt.New; } private void OnCouriersStateUpdated(DotaGameEvent e) @@ -45,10 +46,10 @@ private void OnCouriersStateUpdated(DotaGameEvent e) var previous_courier = evt.Previous.GetForPlayer(courier_kvp.Value.OwnerID); if (!courier_kvp.Value.Equals(previous_courier)) { - dispatcher.Broadcast(new CourierUpdated(courier_kvp.Value, previous_courier, courier_kvp.Value.OwnerID)); + var player_details = _player_cache[courier_kvp.Value.OwnerID]; + dispatcher.Broadcast(new CourierUpdated(courier_kvp.Value, previous_courier, player_details)); - var courier_team = current_player_state.GetForPlayer(courier_kvp.Value.OwnerID).Team; - dispatcher.Broadcast(new TeamCourierUpdated(courier_kvp.Value, previous_courier, courier_team)); + dispatcher.Broadcast(new TeamCourierUpdated(courier_kvp.Value, previous_courier, player_details.Details.Team)); } } } diff --git a/Dota2GSI/StateHandlers/EventsHandler.cs b/Dota2GSI/StateHandlers/EventsHandler.cs index e71627a..ef5845e 100644 --- a/Dota2GSI/StateHandlers/EventsHandler.cs +++ b/Dota2GSI/StateHandlers/EventsHandler.cs @@ -1,36 +1,37 @@ using Dota2GSI.EventMessages; -using Dota2GSI.Nodes; using Dota2GSI.Nodes.EventsProvider; +using Dota2GSI.Nodes.Helpers; +using System.Collections.Generic; using System.Linq; namespace Dota2GSI { public class EventsHandler : EventHandler { - private Player current_player_state = new Player(); + private Dictionary _player_cache = new Dictionary(); public EventsHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { + dispatcher.Subscribe(OnFullPlayerDetailsUpdated); dispatcher.Subscribe(OnEventsStateUpdated); - dispatcher.Subscribe(OnPlayerStateUpdated); } ~EventsHandler() { + dispatcher.Unsubscribe(OnFullPlayerDetailsUpdated); dispatcher.Unsubscribe(OnEventsStateUpdated); - dispatcher.Unsubscribe(OnPlayerStateUpdated); } - private void OnPlayerStateUpdated(DotaGameEvent e) + private void OnFullPlayerDetailsUpdated(DotaGameEvent e) { - PlayerUpdated evt = (e as PlayerUpdated); + FullPlayerDetailsUpdated evt = (e as FullPlayerDetailsUpdated); if (evt == null) { return; } - current_player_state = evt.New; + _player_cache[evt.New.PlayerID] = evt.New; } private void OnEventsStateUpdated(DotaGameEvent e) @@ -53,28 +54,28 @@ private void OnEventsStateUpdated(DotaGameEvent e) switch (game_event.EventType) { case EventType.Courier_killed: - dispatcher.Broadcast(new PlayerEvent(game_event, game_event.KillerPlayerID)); + dispatcher.Broadcast(new PlayerEvent(game_event, _player_cache[game_event.KillerPlayerID])); dispatcher.Broadcast(new TeamEvent(game_event, game_event.Team)); break; case EventType.Roshan_killed: - dispatcher.Broadcast(new PlayerEvent(game_event, game_event.KillerPlayerID)); + dispatcher.Broadcast(new PlayerEvent(game_event, _player_cache[game_event.KillerPlayerID])); dispatcher.Broadcast(new TeamEvent(game_event, game_event.Team)); break; case EventType.Aegis_picked_up: - dispatcher.Broadcast(new PlayerEvent(game_event, game_event.PlayerID)); - dispatcher.Broadcast(new TeamEvent(game_event, current_player_state.GetForPlayer(game_event.PlayerID).Team)); + dispatcher.Broadcast(new PlayerEvent(game_event, _player_cache[game_event.PlayerID])); + dispatcher.Broadcast(new TeamEvent(game_event, _player_cache[game_event.PlayerID].Details.Team)); break; case EventType.Aegis_denied: - dispatcher.Broadcast(new PlayerEvent(game_event, game_event.PlayerID)); - dispatcher.Broadcast(new TeamEvent(game_event, current_player_state.GetForPlayer(game_event.PlayerID).Team)); + dispatcher.Broadcast(new PlayerEvent(game_event, _player_cache[game_event.PlayerID])); + dispatcher.Broadcast(new TeamEvent(game_event, _player_cache[game_event.PlayerID].Details.Team)); break; case EventType.Tip: - dispatcher.Broadcast(new PlayerEvent(game_event, game_event.PlayerID)); - dispatcher.Broadcast(new PlayerEvent(game_event, game_event.TipReceiverPlayerID)); - dispatcher.Broadcast(new TeamEvent(game_event, current_player_state.GetForPlayer(game_event.TipReceiverPlayerID).Team)); + dispatcher.Broadcast(new PlayerEvent(game_event, _player_cache[game_event.PlayerID])); + dispatcher.Broadcast(new PlayerEvent(game_event, _player_cache[game_event.TipReceiverPlayerID])); + dispatcher.Broadcast(new TeamEvent(game_event, _player_cache[game_event.TipReceiverPlayerID].Details.Team)); break; case EventType.Bounty_rune_pickup: - dispatcher.Broadcast(new PlayerEvent(game_event, game_event.PlayerID)); + dispatcher.Broadcast(new PlayerEvent(game_event, _player_cache[game_event.PlayerID])); dispatcher.Broadcast(new TeamEvent(game_event, game_event.Team)); break; default: diff --git a/Dota2GSI/StateHandlers/FullDetailsHandler.cs b/Dota2GSI/StateHandlers/FullDetailsHandler.cs index 9fbe797..f055643 100644 --- a/Dota2GSI/StateHandlers/FullDetailsHandler.cs +++ b/Dota2GSI/StateHandlers/FullDetailsHandler.cs @@ -35,7 +35,7 @@ private void OnFullTeamDetailsUpdated(DotaGameEvent e) return; } - foreach(var player_kvp in evt.New.Players) + foreach (var player_kvp in evt.New.Players) { if (!evt.Previous.Players.ContainsKey(player_kvp.Key)) { diff --git a/Dota2GSI/StateHandlers/HeroHandler.cs b/Dota2GSI/StateHandlers/HeroHandler.cs index a73bd00..a8f7ba6 100644 --- a/Dota2GSI/StateHandlers/HeroHandler.cs +++ b/Dota2GSI/StateHandlers/HeroHandler.cs @@ -1,22 +1,40 @@ using Dota2GSI.EventMessages; +using Dota2GSI.Nodes.Helpers; +using System.Collections.Generic; namespace Dota2GSI { public class HeroHandler : EventHandler { + private Dictionary _player_cache = new Dictionary(); + public HeroHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { - dispatcher.Subscribe(OnHeroStateUpdated); + dispatcher.Subscribe(OnFullPlayerDetailsUpdated); + dispatcher.Subscribe(OnHeroUpdated); dispatcher.Subscribe(OnHeroDetailsChanged); } ~HeroHandler() { - dispatcher.Unsubscribe(OnHeroStateUpdated); + dispatcher.Unsubscribe(OnFullPlayerDetailsUpdated); + dispatcher.Unsubscribe(OnHeroUpdated); dispatcher.Unsubscribe(OnHeroDetailsChanged); } - private void OnHeroStateUpdated(DotaGameEvent e) + private void OnFullPlayerDetailsUpdated(DotaGameEvent e) + { + FullPlayerDetailsUpdated evt = (e as FullPlayerDetailsUpdated); + + if (evt == null) + { + return; + } + + _player_cache[evt.New.PlayerID] = evt.New; + } + + private void OnHeroUpdated(DotaGameEvent e) { HeroUpdated evt = (e as HeroUpdated); @@ -27,7 +45,7 @@ private void OnHeroStateUpdated(DotaGameEvent e) if (!evt.New.LocalPlayer.Equals(evt.Previous.LocalPlayer)) { - dispatcher.Broadcast(new HeroDetailsChanged(evt.New.LocalPlayer, evt.Previous.LocalPlayer)); + dispatcher.Broadcast(new HeroDetailsChanged(evt.New.LocalPlayer, evt.Previous.LocalPlayer, _player_cache[-1])); } foreach (var team_kvp in evt.New.Teams) @@ -38,7 +56,7 @@ private void OnHeroStateUpdated(DotaGameEvent e) if (!player_kvp.Value.Equals(previous_hero_details)) { - dispatcher.Broadcast(new HeroDetailsChanged(player_kvp.Value, previous_hero_details, player_kvp.Key)); + dispatcher.Broadcast(new HeroDetailsChanged(player_kvp.Value, previous_hero_details, _player_cache[player_kvp.Key])); } } } @@ -55,55 +73,55 @@ private void OnHeroDetailsChanged(DotaGameEvent e) if (!evt.New.Level.Equals(evt.Previous.Level)) { - dispatcher.Broadcast(new HeroLevelChanged(evt.New.Level, evt.Previous.Level, evt.PlayerID)); + dispatcher.Broadcast(new HeroLevelChanged(evt.New.Level, evt.Previous.Level, evt.Player)); } if (!evt.New.Health.Equals(evt.Previous.Health)) { - dispatcher.Broadcast(new HeroHealthChanged(evt.New.Health, evt.Previous.Health, evt.PlayerID)); + dispatcher.Broadcast(new HeroHealthChanged(evt.New.Health, evt.Previous.Health, evt.Player)); if (!evt.New.IsAlive && evt.Previous.IsAlive) { - dispatcher.Broadcast(new HeroDied(evt.New.Health, evt.Previous.Health, evt.PlayerID)); + dispatcher.Broadcast(new HeroDied(evt.New.Health, evt.Previous.Health, evt.Player)); } else if (evt.New.IsAlive && !evt.Previous.IsAlive) { - dispatcher.Broadcast(new HeroRespawned(evt.New.Health, evt.Previous.Health, evt.PlayerID)); + dispatcher.Broadcast(new HeroRespawned(evt.New.Health, evt.Previous.Health, evt.Player)); } else if (evt.New.IsAlive && evt.Previous.IsAlive) { - dispatcher.Broadcast(new HeroTookDamage(evt.New.Health, evt.Previous.Health, evt.PlayerID)); + dispatcher.Broadcast(new HeroTookDamage(evt.New.Health, evt.Previous.Health, evt.Player)); } } if (!evt.New.Mana.Equals(evt.Previous.Mana)) { - dispatcher.Broadcast(new HeroManaChanged(evt.New.Mana, evt.Previous.Mana, evt.PlayerID)); + dispatcher.Broadcast(new HeroManaChanged(evt.New.Mana, evt.Previous.Mana, evt.Player)); } if (!evt.New.HeroState.Equals(evt.Previous.HeroState)) { - dispatcher.Broadcast(new HeroStateChanged(evt.New.HeroState, evt.Previous.HeroState, evt.PlayerID)); + dispatcher.Broadcast(new HeroStateChanged(evt.New.HeroState, evt.Previous.HeroState, evt.Player)); } if (!evt.New.IsMuted.Equals(evt.Previous.IsMuted)) { - dispatcher.Broadcast(new HeroMuteStateChanged(evt.New.IsMuted, evt.Previous.IsMuted, evt.PlayerID)); + dispatcher.Broadcast(new HeroMuteStateChanged(evt.New.IsMuted, evt.Previous.IsMuted, evt.Player)); } if (!evt.New.SelectedUnit.Equals(evt.Previous.SelectedUnit)) { - dispatcher.Broadcast(new HeroSelectedChanged(evt.New.SelectedUnit, evt.Previous.SelectedUnit, evt.PlayerID)); + dispatcher.Broadcast(new HeroSelectedChanged(evt.New.SelectedUnit, evt.Previous.SelectedUnit, evt.Player)); } if (!evt.New.TalentTree.Equals(evt.Previous.TalentTree)) { - dispatcher.Broadcast(new HeroTalentTreeChanged(evt.New.TalentTree, evt.Previous.TalentTree, evt.PlayerID)); + dispatcher.Broadcast(new HeroTalentTreeChanged(evt.New.TalentTree, evt.Previous.TalentTree, evt.Player)); } if (!evt.New.AttributesLevel.Equals(evt.Previous.AttributesLevel)) { - dispatcher.Broadcast(new HeroAttributesLevelChanged(evt.New.AttributesLevel, evt.Previous.AttributesLevel, evt.PlayerID)); + dispatcher.Broadcast(new HeroAttributesLevelChanged(evt.New.AttributesLevel, evt.Previous.AttributesLevel, evt.Player)); } } } diff --git a/Dota2GSI/StateHandlers/ItemsHandler.cs b/Dota2GSI/StateHandlers/ItemsHandler.cs index 369fa8d..d179c42 100644 --- a/Dota2GSI/StateHandlers/ItemsHandler.cs +++ b/Dota2GSI/StateHandlers/ItemsHandler.cs @@ -1,19 +1,37 @@ using Dota2GSI.EventMessages; +using Dota2GSI.Nodes.Helpers; +using System.Collections.Generic; namespace Dota2GSI { public class ItemsHandler : EventHandler { + private Dictionary _player_cache = new Dictionary(); + public ItemsHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { + dispatcher.Subscribe(OnFullPlayerDetailsUpdated); dispatcher.Subscribe(OnItemsStateUpdated); } ~ItemsHandler() { + dispatcher.Unsubscribe(OnFullPlayerDetailsUpdated); dispatcher.Unsubscribe(OnItemsStateUpdated); } + private void OnFullPlayerDetailsUpdated(DotaGameEvent e) + { + FullPlayerDetailsUpdated evt = (e as FullPlayerDetailsUpdated); + + if (evt == null) + { + return; + } + + _player_cache[evt.New.PlayerID] = evt.New; + } + private void OnItemsStateUpdated(DotaGameEvent e) { ItemsUpdated evt = (e as ItemsUpdated); @@ -25,7 +43,7 @@ private void OnItemsStateUpdated(DotaGameEvent e) if (!evt.New.LocalPlayer.Equals(evt.Previous.LocalPlayer)) { - dispatcher.Broadcast(new ItemDetailsChanged(evt.New.LocalPlayer, evt.Previous.LocalPlayer)); + dispatcher.Broadcast(new ItemDetailsChanged(evt.New.LocalPlayer, evt.Previous.LocalPlayer, _player_cache[-1])); } foreach (var team_kvp in evt.New.Teams) @@ -37,7 +55,7 @@ private void OnItemsStateUpdated(DotaGameEvent e) if (!player_kvp.Value.Equals(previous_hero_details)) { - dispatcher.Broadcast(new ItemDetailsChanged(player_kvp.Value, previous_hero_details, player_kvp.Key)); + dispatcher.Broadcast(new ItemDetailsChanged(player_kvp.Value, previous_hero_details, _player_cache[player_kvp.Key])); } } } diff --git a/Dota2GSI/StateHandlers/PlayerHandler.cs b/Dota2GSI/StateHandlers/PlayerHandler.cs index f0f487d..f744d97 100644 --- a/Dota2GSI/StateHandlers/PlayerHandler.cs +++ b/Dota2GSI/StateHandlers/PlayerHandler.cs @@ -1,21 +1,39 @@ using Dota2GSI.EventMessages; +using Dota2GSI.Nodes.Helpers; +using System.Collections.Generic; namespace Dota2GSI { public class PlayerHandler : EventHandler { + private Dictionary _player_cache = new Dictionary(); + public PlayerHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { + dispatcher.Subscribe(OnFullPlayerDetailsUpdated); dispatcher.Subscribe(OnPlayerStateUpdated); dispatcher.Subscribe(OnPlayerDetailsChanged); } ~PlayerHandler() { + dispatcher.Unsubscribe(OnFullPlayerDetailsUpdated); dispatcher.Unsubscribe(OnPlayerStateUpdated); dispatcher.Unsubscribe(OnPlayerDetailsChanged); } + private void OnFullPlayerDetailsUpdated(DotaGameEvent e) + { + FullPlayerDetailsUpdated evt = (e as FullPlayerDetailsUpdated); + + if (evt == null) + { + return; + } + + _player_cache[evt.New.PlayerID] = evt.New; + } + private void OnPlayerStateUpdated(DotaGameEvent e) { PlayerUpdated evt = (e as PlayerUpdated); @@ -27,7 +45,7 @@ private void OnPlayerStateUpdated(DotaGameEvent e) if (!evt.New.LocalPlayer.Equals(evt.Previous.LocalPlayer)) { - dispatcher.Broadcast(new PlayerDetailsChanged(evt.New.LocalPlayer, evt.Previous.LocalPlayer)); + dispatcher.Broadcast(new PlayerDetailsChanged(evt.New.LocalPlayer, evt.Previous.LocalPlayer, _player_cache[-1])); } foreach (var team_kvp in evt.New.Teams) @@ -38,7 +56,7 @@ private void OnPlayerStateUpdated(DotaGameEvent e) if (!player_kvp.Value.Equals(previous_hero_details)) { - dispatcher.Broadcast(new PlayerDetailsChanged(player_kvp.Value, previous_hero_details, player_kvp.Key)); + dispatcher.Broadcast(new PlayerDetailsChanged(player_kvp.Value, previous_hero_details, _player_cache[player_kvp.Key])); } } } @@ -55,67 +73,67 @@ private void OnPlayerDetailsChanged(DotaGameEvent e) if (!evt.New.Kills.Equals(evt.Previous.Kills)) { - dispatcher.Broadcast(new PlayerKillsChanged(evt.New.Kills, evt.Previous.Kills, evt.PlayerID)); + dispatcher.Broadcast(new PlayerKillsChanged(evt.New.Kills, evt.Previous.Kills, evt.Player)); } if (!evt.New.Deaths.Equals(evt.Previous.Deaths)) { - dispatcher.Broadcast(new PlayerDeathsChanged(evt.New.Deaths, evt.Previous.Deaths, evt.PlayerID)); + dispatcher.Broadcast(new PlayerDeathsChanged(evt.New.Deaths, evt.Previous.Deaths, evt.Player)); } if (!evt.New.Assists.Equals(evt.Previous.Assists)) { - dispatcher.Broadcast(new PlayerAssistsChanged(evt.New.Assists, evt.Previous.Assists, evt.PlayerID)); + dispatcher.Broadcast(new PlayerAssistsChanged(evt.New.Assists, evt.Previous.Assists, evt.Player)); } if (!evt.New.LastHits.Equals(evt.Previous.LastHits)) { - dispatcher.Broadcast(new PlayerLastHitsChanged(evt.New.LastHits, evt.Previous.LastHits, evt.PlayerID)); + dispatcher.Broadcast(new PlayerLastHitsChanged(evt.New.LastHits, evt.Previous.LastHits, evt.Player)); } if (!evt.New.Denies.Equals(evt.Previous.Denies)) { - dispatcher.Broadcast(new PlayerDeniesChanged(evt.New.Denies, evt.Previous.Denies, evt.PlayerID)); + dispatcher.Broadcast(new PlayerDeniesChanged(evt.New.Denies, evt.Previous.Denies, evt.Player)); } if (!evt.New.KillStreak.Equals(evt.Previous.KillStreak)) { - dispatcher.Broadcast(new PlayerKillStreakChanged(evt.New.KillStreak, evt.Previous.KillStreak, evt.PlayerID)); + dispatcher.Broadcast(new PlayerKillStreakChanged(evt.New.KillStreak, evt.Previous.KillStreak, evt.Player)); } if (!evt.New.Gold.Equals(evt.Previous.Gold)) { - dispatcher.Broadcast(new PlayerGoldChanged(evt.New.Gold, evt.Previous.Gold, evt.PlayerID)); + dispatcher.Broadcast(new PlayerGoldChanged(evt.New.Gold, evt.Previous.Gold, evt.Player)); } if (!evt.New.Gold.Equals(evt.Previous.Gold)) { - dispatcher.Broadcast(new PlayerGoldChanged(evt.New.Gold, evt.Previous.Gold, evt.PlayerID)); + dispatcher.Broadcast(new PlayerGoldChanged(evt.New.Gold, evt.Previous.Gold, evt.Player)); } if (!evt.New.WardsPurchased.Equals(evt.Previous.WardsPurchased)) { - dispatcher.Broadcast(new PlayerWardsPurchasedChanged(evt.New.WardsPurchased, evt.Previous.WardsPurchased, evt.PlayerID)); + dispatcher.Broadcast(new PlayerWardsPurchasedChanged(evt.New.WardsPurchased, evt.Previous.WardsPurchased, evt.Player)); } if (!evt.New.WardsPlaced.Equals(evt.Previous.WardsPlaced)) { - dispatcher.Broadcast(new PlayerWardsPlacedChanged(evt.New.WardsPlaced, evt.Previous.WardsPlaced, evt.PlayerID)); + dispatcher.Broadcast(new PlayerWardsPlacedChanged(evt.New.WardsPlaced, evt.Previous.WardsPlaced, evt.Player)); } if (!evt.New.WardsDestroyed.Equals(evt.Previous.WardsDestroyed)) { - dispatcher.Broadcast(new PlayerWardsDestroyedChanged(evt.New.WardsDestroyed, evt.Previous.WardsDestroyed, evt.PlayerID)); + dispatcher.Broadcast(new PlayerWardsDestroyedChanged(evt.New.WardsDestroyed, evt.Previous.WardsDestroyed, evt.Player)); } if (!evt.New.RunesActivated.Equals(evt.Previous.RunesActivated)) { - dispatcher.Broadcast(new PlayerRunesActivatedChanged(evt.New.RunesActivated, evt.Previous.RunesActivated, evt.PlayerID)); + dispatcher.Broadcast(new PlayerRunesActivatedChanged(evt.New.RunesActivated, evt.Previous.RunesActivated, evt.Player)); } if (!evt.New.CampsStacked.Equals(evt.Previous.CampsStacked)) { - dispatcher.Broadcast(new PlayerCampsStackedChanged(evt.New.CampsStacked, evt.Previous.CampsStacked, evt.PlayerID)); + dispatcher.Broadcast(new PlayerCampsStackedChanged(evt.New.CampsStacked, evt.Previous.CampsStacked, evt.Player)); } } } diff --git a/Dota2GSI/StateHandlers/WearablesHandler.cs b/Dota2GSI/StateHandlers/WearablesHandler.cs index 32358a2..ca4f62b 100644 --- a/Dota2GSI/StateHandlers/WearablesHandler.cs +++ b/Dota2GSI/StateHandlers/WearablesHandler.cs @@ -1,19 +1,37 @@ using Dota2GSI.EventMessages; +using Dota2GSI.Nodes.Helpers; +using System.Collections.Generic; namespace Dota2GSI { public class WearablesHandler : EventHandler { + private Dictionary _player_cache = new Dictionary(); + public WearablesHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { + dispatcher.Subscribe(OnFullPlayerDetailsUpdated); dispatcher.Subscribe(OnWearablesStateUpdated); } ~WearablesHandler() { + dispatcher.Unsubscribe(OnFullPlayerDetailsUpdated); dispatcher.Unsubscribe(OnWearablesStateUpdated); } + private void OnFullPlayerDetailsUpdated(DotaGameEvent e) + { + FullPlayerDetailsUpdated evt = (e as FullPlayerDetailsUpdated); + + if (evt == null) + { + return; + } + + _player_cache[evt.New.PlayerID] = evt.New; + } + private void OnWearablesStateUpdated(DotaGameEvent e) { WearablesUpdated evt = (e as WearablesUpdated); @@ -25,7 +43,7 @@ private void OnWearablesStateUpdated(DotaGameEvent e) if (!evt.New.LocalPlayer.Equals(evt.Previous.LocalPlayer)) { - dispatcher.Broadcast(new PlayerWearablesUpdated(evt.New.LocalPlayer, evt.Previous.LocalPlayer)); + dispatcher.Broadcast(new PlayerWearablesUpdated(evt.New.LocalPlayer, evt.Previous.LocalPlayer, _player_cache[-1])); } foreach (var team_kvp in evt.New.Teams) @@ -36,7 +54,7 @@ private void OnWearablesStateUpdated(DotaGameEvent e) if (!player_kvp.Value.Equals(previous_hero_details)) { - dispatcher.Broadcast(new PlayerWearablesUpdated(player_kvp.Value, previous_hero_details, player_kvp.Key)); + dispatcher.Broadcast(new PlayerWearablesUpdated(player_kvp.Value, previous_hero_details, _player_cache[player_kvp.Key])); } } } From 57e9ccc014da5f1ebc4864ba0eb96aa1f49dc0df Mon Sep 17 00:00:00 2001 From: Anton Pupkov Date: Wed, 17 Jan 2024 15:50:38 -0800 Subject: [PATCH 14/24] Rename Events to GameplayEvents --- Dota2GSI/CMakeLists.txt | 4 +-- Dota2GSI/Dota2EventsInterface.cs | 20 ++++++------ .../{EventsEvents.cs => GameplayEvents.cs} | 10 +++--- Dota2GSI/GameStateListener.cs | 2 +- ...ntsHandler.cs => GameplayEventsHandler.cs} | 32 +++++++++---------- 5 files changed, 34 insertions(+), 34 deletions(-) rename Dota2GSI/EventMessages/{EventsEvents.cs => GameplayEvents.cs} (66%) rename Dota2GSI/StateHandlers/{EventsHandler.cs => GameplayEventsHandler.cs} (53%) diff --git a/Dota2GSI/CMakeLists.txt b/Dota2GSI/CMakeLists.txt index d6dd3ca..13d6c85 100644 --- a/Dota2GSI/CMakeLists.txt +++ b/Dota2GSI/CMakeLists.txt @@ -30,7 +30,7 @@ SET(SOURCES EventMessages/CouriersEvents.cs EventMessages/DotaGameEvent.cs EventMessages/DraftEvents.cs - EventMessages/EventsEvents.cs + EventMessages/GameplayEvents.cs EventMessages/FullDetailsEvents.cs EventMessages/HeroEvents.cs EventMessages/ItemsEvents.cs @@ -90,7 +90,7 @@ SET(SOURCES StateHandlers/BuildingsHandler.cs StateHandlers/CouriersHandler.cs StateHandlers/DraftHandler.cs - StateHandlers/EventsHandler.cs + StateHandlers/GameplayEventsHandler.cs StateHandlers/FullDetailsHandler.cs StateHandlers/HeroHandler.cs StateHandlers/ItemsHandler.cs diff --git a/Dota2GSI/Dota2EventsInterface.cs b/Dota2GSI/Dota2EventsInterface.cs index 604c5af..305f1b0 100644 --- a/Dota2GSI/Dota2EventsInterface.cs +++ b/Dota2GSI/Dota2EventsInterface.cs @@ -146,15 +146,15 @@ public class Dota2EventsInterface : EventsInterface /// public event GameplayEventHandler GameplayEvent = delegate { }; - public delegate void TeamEventHandler(TeamEvent game_event); + public delegate void TeamGameplayEventHandler(TeamGameplayEvent game_event); - /// - public event TeamEventHandler TeamEvent = delegate { }; + /// + public event TeamGameplayEventHandler TeamGameplayEvent = delegate { }; - public delegate void PlayerEventHandler(PlayerEvent game_event); + public delegate void PlayerGameplayEventHandler(PlayerGameplayEvent game_event); - /// - public event PlayerEventHandler PlayerEvent = delegate { }; + /// + public event PlayerGameplayEventHandler PlayerGameplayEvent = delegate { }; #endregion @@ -571,14 +571,14 @@ public override void OnNewGameEvent(DotaGameEvent e) RaiseEvent(GameplayEvent, e); } - if (e is TeamEvent) + if (e is TeamGameplayEvent) { - RaiseEvent(TeamEvent, e); + RaiseEvent(TeamGameplayEvent, e); } - if (e is PlayerEvent) + if (e is PlayerGameplayEvent) { - RaiseEvent(PlayerEvent, e); + RaiseEvent(PlayerGameplayEvent, e); } if (e is HeroUpdated) diff --git a/Dota2GSI/EventMessages/EventsEvents.cs b/Dota2GSI/EventMessages/GameplayEvents.cs similarity index 66% rename from Dota2GSI/EventMessages/EventsEvents.cs rename to Dota2GSI/EventMessages/GameplayEvents.cs index 34234b5..c6ec0e0 100644 --- a/Dota2GSI/EventMessages/EventsEvents.cs +++ b/Dota2GSI/EventMessages/GameplayEvents.cs @@ -25,11 +25,11 @@ public GameplayEvent(Event value) : base(value) } /// - /// Event for specific team Event. + /// Event for specific team Gameplay Event. /// - public class TeamEvent : TeamValueEvent + public class TeamGameplayEvent : TeamValueEvent { - public TeamEvent(Event value, PlayerTeam team) : base(value, team) + public TeamGameplayEvent(Event value, PlayerTeam team) : base(value, team) { } } @@ -37,9 +37,9 @@ public TeamEvent(Event value, PlayerTeam team) : base(value, team) /// /// Event for specific player Event. /// - public class PlayerEvent : PlayerValueEvent + public class PlayerGameplayEvent : PlayerValueEvent { - public PlayerEvent(Event value, FullPlayerDetails player) : base(value, player) + public PlayerGameplayEvent(Event value, FullPlayerDetails player) : base(value, player) { } } diff --git a/Dota2GSI/GameStateListener.cs b/Dota2GSI/GameStateListener.cs index c0fc1de..cb4d951 100644 --- a/Dota2GSI/GameStateListener.cs +++ b/Dota2GSI/GameStateListener.cs @@ -84,7 +84,7 @@ private set private BuildingsHandler _buildings_handler = new BuildingsHandler(ref _dispatcher); private CouriersHandler _couriers_handler = new CouriersHandler(ref _dispatcher); private DraftHandler _draft_handler = new DraftHandler(ref _dispatcher); - private EventsHandler _events_handler = new EventsHandler(ref _dispatcher); + private GameplayEventsHandler _gameplay_events_handler = new GameplayEventsHandler(ref _dispatcher); private HeroHandler _hero_handler = new HeroHandler(ref _dispatcher); private ItemsHandler _items_handler = new ItemsHandler(ref _dispatcher); private LeagueHandler _league_handler = new LeagueHandler(ref _dispatcher); diff --git a/Dota2GSI/StateHandlers/EventsHandler.cs b/Dota2GSI/StateHandlers/GameplayEventsHandler.cs similarity index 53% rename from Dota2GSI/StateHandlers/EventsHandler.cs rename to Dota2GSI/StateHandlers/GameplayEventsHandler.cs index ef5845e..1c2742c 100644 --- a/Dota2GSI/StateHandlers/EventsHandler.cs +++ b/Dota2GSI/StateHandlers/GameplayEventsHandler.cs @@ -6,17 +6,17 @@ namespace Dota2GSI { - public class EventsHandler : EventHandler + public class GameplayEventsHandler : EventHandler { private Dictionary _player_cache = new Dictionary(); - public EventsHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) + public GameplayEventsHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { dispatcher.Subscribe(OnFullPlayerDetailsUpdated); dispatcher.Subscribe(OnEventsStateUpdated); } - ~EventsHandler() + ~GameplayEventsHandler() { dispatcher.Unsubscribe(OnFullPlayerDetailsUpdated); dispatcher.Unsubscribe(OnEventsStateUpdated); @@ -54,29 +54,29 @@ private void OnEventsStateUpdated(DotaGameEvent e) switch (game_event.EventType) { case EventType.Courier_killed: - dispatcher.Broadcast(new PlayerEvent(game_event, _player_cache[game_event.KillerPlayerID])); - dispatcher.Broadcast(new TeamEvent(game_event, game_event.Team)); + dispatcher.Broadcast(new PlayerGameplayEvent(game_event, _player_cache[game_event.KillerPlayerID])); + dispatcher.Broadcast(new TeamGameplayEvent(game_event, game_event.Team)); break; case EventType.Roshan_killed: - dispatcher.Broadcast(new PlayerEvent(game_event, _player_cache[game_event.KillerPlayerID])); - dispatcher.Broadcast(new TeamEvent(game_event, game_event.Team)); + dispatcher.Broadcast(new PlayerGameplayEvent(game_event, _player_cache[game_event.KillerPlayerID])); + dispatcher.Broadcast(new TeamGameplayEvent(game_event, game_event.Team)); break; case EventType.Aegis_picked_up: - dispatcher.Broadcast(new PlayerEvent(game_event, _player_cache[game_event.PlayerID])); - dispatcher.Broadcast(new TeamEvent(game_event, _player_cache[game_event.PlayerID].Details.Team)); + dispatcher.Broadcast(new PlayerGameplayEvent(game_event, _player_cache[game_event.PlayerID])); + dispatcher.Broadcast(new TeamGameplayEvent(game_event, _player_cache[game_event.PlayerID].Details.Team)); break; case EventType.Aegis_denied: - dispatcher.Broadcast(new PlayerEvent(game_event, _player_cache[game_event.PlayerID])); - dispatcher.Broadcast(new TeamEvent(game_event, _player_cache[game_event.PlayerID].Details.Team)); + dispatcher.Broadcast(new PlayerGameplayEvent(game_event, _player_cache[game_event.PlayerID])); + dispatcher.Broadcast(new TeamGameplayEvent(game_event, _player_cache[game_event.PlayerID].Details.Team)); break; case EventType.Tip: - dispatcher.Broadcast(new PlayerEvent(game_event, _player_cache[game_event.PlayerID])); - dispatcher.Broadcast(new PlayerEvent(game_event, _player_cache[game_event.TipReceiverPlayerID])); - dispatcher.Broadcast(new TeamEvent(game_event, _player_cache[game_event.TipReceiverPlayerID].Details.Team)); + dispatcher.Broadcast(new PlayerGameplayEvent(game_event, _player_cache[game_event.PlayerID])); + dispatcher.Broadcast(new PlayerGameplayEvent(game_event, _player_cache[game_event.TipReceiverPlayerID])); + dispatcher.Broadcast(new TeamGameplayEvent(game_event, _player_cache[game_event.TipReceiverPlayerID].Details.Team)); break; case EventType.Bounty_rune_pickup: - dispatcher.Broadcast(new PlayerEvent(game_event, _player_cache[game_event.PlayerID])); - dispatcher.Broadcast(new TeamEvent(game_event, game_event.Team)); + dispatcher.Broadcast(new PlayerGameplayEvent(game_event, _player_cache[game_event.PlayerID])); + dispatcher.Broadcast(new TeamGameplayEvent(game_event, game_event.Team)); break; default: break; From 0d9ddf0b718a5bea38180807afa922aaa687b56b Mon Sep 17 00:00:00 2001 From: Anton Pupkov Date: Wed, 17 Jan 2024 16:54:21 -0800 Subject: [PATCH 15/24] Add more item events --- Dota2GSI/Dota2EventsInterface.cs | 70 +++++++++++++++++++++++ Dota2GSI/EventMessages/ItemsEvents.cs | 70 +++++++++++++++++++++++ Dota2GSI/StateHandlers/ItemsHandler.cs | 78 ++++++++++++++++++++++++++ 3 files changed, 218 insertions(+) diff --git a/Dota2GSI/Dota2EventsInterface.cs b/Dota2GSI/Dota2EventsInterface.cs index 305f1b0..0c5afb1 100644 --- a/Dota2GSI/Dota2EventsInterface.cs +++ b/Dota2GSI/Dota2EventsInterface.cs @@ -239,6 +239,41 @@ public class Dota2EventsInterface : EventsInterface /// public event ItemDetailsChangedHandler ItemDetailsChanged = delegate { }; + public delegate void ItemUpdatedHandler(ItemUpdated game_event); + + /// + public event ItemUpdatedHandler ItemUpdated = delegate { }; + + public delegate void InventoryItemAddedHandler(InventoryItemAdded game_event); + + /// + public event InventoryItemAddedHandler InventoryItemAdded = delegate { }; + + public delegate void InventoryItemRemovedHandler(InventoryItemRemoved game_event); + + /// + public event InventoryItemRemovedHandler InventoryItemRemoved = delegate { }; + + public delegate void InventoryItemUpdatedHandler(InventoryItemUpdated game_event); + + /// + public event InventoryItemUpdatedHandler InventoryItemUpdated = delegate { }; + + public delegate void StashItemAddedHandler(StashItemAdded game_event); + + /// + public event StashItemAddedHandler StashItemAdded = delegate { }; + + public delegate void StashItemRemovedHandler(StashItemRemoved game_event); + + /// + public event StashItemRemovedHandler StashItemRemoved = delegate { }; + + public delegate void StashItemUpdatedHandler(StashItemUpdated game_event); + + /// + public event StashItemUpdatedHandler StashItemUpdated = delegate { }; + #endregion #region LeagueEvents @@ -656,6 +691,41 @@ public override void OnNewGameEvent(DotaGameEvent e) RaiseEvent(ItemDetailsChanged, e); } + if (e is ItemUpdated) + { + RaiseEvent(ItemUpdated, e); + } + + if (e is InventoryItemAdded) + { + RaiseEvent(InventoryItemAdded, e); + } + + if (e is InventoryItemRemoved) + { + RaiseEvent(InventoryItemRemoved, e); + } + + if (e is InventoryItemUpdated) + { + RaiseEvent(InventoryItemUpdated, e); + } + + if (e is StashItemAdded) + { + RaiseEvent(StashItemAdded, e); + } + + if (e is StashItemRemoved) + { + RaiseEvent(StashItemRemoved, e); + } + + if (e is StashItemUpdated) + { + RaiseEvent(StashItemUpdated, e); + } + if (e is LeagueUpdated) { RaiseEvent(LeagueUpdated, e); diff --git a/Dota2GSI/EventMessages/ItemsEvents.cs b/Dota2GSI/EventMessages/ItemsEvents.cs index 7c92d36..04492df 100644 --- a/Dota2GSI/EventMessages/ItemsEvents.cs +++ b/Dota2GSI/EventMessages/ItemsEvents.cs @@ -23,4 +23,74 @@ public ItemDetailsChanged(ItemDetails new_value, ItemDetails previous_value, Ful { } } + + /// + /// Event for specific player's Item update. + /// + public class ItemUpdated : PlayerUpdateEvent + { + public ItemUpdated(Item new_value, Item previous_value, FullPlayerDetails player) : base(new_value, previous_value, player) + { + } + } + + /// + /// Event for specific player gaining an item in their inventory. + /// + public class InventoryItemAdded : PlayerValueEvent + { + public InventoryItemAdded(Item value, FullPlayerDetails player) : base(value, player) + { + } + } + + /// + /// Event for specific player losing an item from their inventory. + /// + public class InventoryItemRemoved : PlayerValueEvent + { + public InventoryItemRemoved(Item value, FullPlayerDetails player) : base(value, player) + { + } + } + + /// + /// Event for specific player's inventory item updating. + /// + public class InventoryItemUpdated : ItemUpdated + { + public InventoryItemUpdated(Item new_value, Item previous_value, FullPlayerDetails player) : base(new_value, previous_value, player) + { + } + } + + /// + /// Event for specific player gaining an item in their stash. + /// + public class StashItemAdded : PlayerValueEvent + { + public StashItemAdded(Item value, FullPlayerDetails player) : base(value, player) + { + } + } + + /// + /// Event for specific player losing an item from their stash. + /// + public class StashItemRemoved : PlayerValueEvent + { + public StashItemRemoved(Item value, FullPlayerDetails player) : base(value, player) + { + } + } + + /// + /// Event for specific player's stash item updating. + /// + public class StashItemUpdated : ItemUpdated + { + public StashItemUpdated(Item new_value, Item previous_value, FullPlayerDetails player) : base(new_value, previous_value, player) + { + } + } } diff --git a/Dota2GSI/StateHandlers/ItemsHandler.cs b/Dota2GSI/StateHandlers/ItemsHandler.cs index d179c42..25f05cb 100644 --- a/Dota2GSI/StateHandlers/ItemsHandler.cs +++ b/Dota2GSI/StateHandlers/ItemsHandler.cs @@ -12,12 +12,14 @@ public ItemsHandler(ref EventDispatcher EventDispatcher) : base(r { dispatcher.Subscribe(OnFullPlayerDetailsUpdated); dispatcher.Subscribe(OnItemsStateUpdated); + dispatcher.Subscribe(OnItemDetailsChanged); } ~ItemsHandler() { dispatcher.Unsubscribe(OnFullPlayerDetailsUpdated); dispatcher.Unsubscribe(OnItemsStateUpdated); + dispatcher.Unsubscribe(OnItemDetailsChanged); } private void OnFullPlayerDetailsUpdated(DotaGameEvent e) @@ -60,5 +62,81 @@ private void OnItemsStateUpdated(DotaGameEvent e) } } } + + private void OnItemDetailsChanged(DotaGameEvent e) + { + ItemDetailsChanged evt = (e as ItemDetailsChanged); + + if (evt == null) + { + return; + } + + foreach (var item in evt.New.Inventory) + { + if (!evt.Previous.InventoryContains(item.Name)) + { + // Player gained an inventory item. + dispatcher.Broadcast(new InventoryItemAdded(item, evt.Player)); + continue; + } + + var previous_item = evt.Previous.GetInventoryItem(item.Name); + + if (!item.Equals(previous_item)) + { + // Item updated. + dispatcher.Broadcast(new InventoryItemUpdated(item, previous_item, evt.Player)); + } + } + + foreach (var item in evt.Previous.Inventory) + { + if (!evt.New.InventoryContains(item.Name)) + { + // Player lost an inventory item. + dispatcher.Broadcast(new InventoryItemRemoved(item, evt.Player)); + } + } + + foreach (var item in evt.New.Stash) + { + if (!evt.Previous.StashContains(item.Name)) + { + // Player gained a stash item. + dispatcher.Broadcast(new StashItemAdded(item, evt.Player)); + continue; + } + + var previous_item = evt.Previous.GetStashItem(item.Name); + + if (!item.Equals(previous_item)) + { + // Stash item updated. + dispatcher.Broadcast(new StashItemUpdated(item, previous_item, evt.Player)); + } + } + + foreach (var item in evt.Previous.Inventory) + { + if (!evt.New.StashContains(item.Name)) + { + // Player lost a stash item. + dispatcher.Broadcast(new StashItemRemoved(item, evt.Player)); + } + } + + if (!evt.New.Teleport.Equals(evt.Previous.Teleport)) + { + // Teleport item updated. + dispatcher.Broadcast(new ItemUpdated(evt.New.Teleport, evt.Previous.Teleport, evt.Player)); + } + + if (!evt.New.Neutral.Equals(evt.Previous.Neutral)) + { + // Neutral item updated. + dispatcher.Broadcast(new ItemUpdated(evt.New.Neutral, evt.Previous.Neutral, evt.Player)); + } + } } } From 3ca5d7c7598815cde89693a3e33fe9d0f3cd0e3c Mon Sep 17 00:00:00 2001 From: Anton Pupkov Date: Wed, 17 Jan 2024 19:10:40 -0800 Subject: [PATCH 16/24] Add courier item events --- Dota2GSI/Dota2EventsInterface.cs | 30 ++++++++++ Dota2GSI/EventMessages/CouriersEvents.cs | 49 ++++++++++++++++ Dota2GSI/Nodes/CouriersProvider/Courier.cs | 67 ++++++++++++++++++++++ Dota2GSI/StateHandlers/CouriersHandler.cs | 45 ++++++++++++++- 4 files changed, 188 insertions(+), 3 deletions(-) diff --git a/Dota2GSI/Dota2EventsInterface.cs b/Dota2GSI/Dota2EventsInterface.cs index 0c5afb1..fb26bf1 100644 --- a/Dota2GSI/Dota2EventsInterface.cs +++ b/Dota2GSI/Dota2EventsInterface.cs @@ -118,6 +118,21 @@ public class Dota2EventsInterface : EventsInterface /// public event TeamCourierUpdatedHandler TeamCourierUpdated = delegate { }; + public delegate void CourierItemAddedHandler(CourierItemAdded game_event); + + /// + public event CourierItemAddedHandler CourierItemAdded = delegate { }; + + public delegate void CourierItemRemovedHandler(CourierItemRemoved game_event); + + /// + public event CourierItemRemovedHandler CourierItemRemoved = delegate { }; + + public delegate void CourierItemUpdatedHandler(CourierItemUpdated game_event); + + /// + public event CourierItemUpdatedHandler CourierItemUpdated = delegate { }; + #endregion #region DraftEvents @@ -586,6 +601,21 @@ public override void OnNewGameEvent(DotaGameEvent e) RaiseEvent(TeamCourierUpdated, e); } + if (e is CourierItemAdded) + { + RaiseEvent(CourierItemAdded, e); + } + + if (e is CourierItemRemoved) + { + RaiseEvent(CourierItemRemoved, e); + } + + if (e is CourierItemUpdated) + { + RaiseEvent(CourierItemUpdated, e); + } + if (e is DraftUpdated) { RaiseEvent(DraftUpdated, e); diff --git a/Dota2GSI/EventMessages/CouriersEvents.cs b/Dota2GSI/EventMessages/CouriersEvents.cs index 8a822b5..af6efd9 100644 --- a/Dota2GSI/EventMessages/CouriersEvents.cs +++ b/Dota2GSI/EventMessages/CouriersEvents.cs @@ -33,4 +33,53 @@ public TeamCourierUpdated(Courier new_value, Courier previous_value, PlayerTeam { } } + + + /// + /// Event for specific player's courier gaining an item in their inventory. + /// + public class CourierItemAdded : PlayerValueEvent + { + /// + /// The player's courier. + /// + public readonly Courier Courier; + + public CourierItemAdded(CourierItem value, Courier courier, FullPlayerDetails player) : base(value, player) + { + Courier = courier; + } + } + + /// + /// Event for specific player's courier losing an item from their inventory. + /// + public class CourierItemRemoved : PlayerValueEvent + { + /// + /// The player's courier. + /// + public readonly Courier Courier; + + public CourierItemRemoved(CourierItem value, Courier courier, FullPlayerDetails player) : base(value, player) + { + Courier = courier; + } + } + + /// + /// Event for specific player's courier item updating in their inventory. + /// + public class CourierItemUpdated : PlayerUpdateEvent + { + /// + /// The player's courier. + /// + public readonly Courier Courier; + + public CourierItemUpdated(CourierItem new_value, CourierItem previous_value, Courier courier, FullPlayerDetails player) : base(new_value, previous_value, player) + { + Courier = courier; + } + } } diff --git a/Dota2GSI/Nodes/CouriersProvider/Courier.cs b/Dota2GSI/Nodes/CouriersProvider/Courier.cs index 1433900..3086196 100644 --- a/Dota2GSI/Nodes/CouriersProvider/Courier.cs +++ b/Dota2GSI/Nodes/CouriersProvider/Courier.cs @@ -89,6 +89,73 @@ internal Courier(JObject parsed_data = null) : base(parsed_data) }); } + /// + /// Gets the inventory item at the specified index. + /// + /// The index. + /// The inventory item. + public CourierItem GetItemAt(int index) + { + if (index < 0 || index > Items.Count - 1) + { + return new CourierItem(); + } + + return Items[index]; + } + + /// + /// Gets the inventory item by item name. + /// + /// The item name to look for. + /// The inventory item. + public CourierItem GetInventoryItem(string item_name) + { + foreach (var item in Items) + { + if (item.Value.Name.Equals(item_name)) + { + return item.Value; + } + } + + return new CourierItem(); + } + + /// + /// Checks if item exists in the inventory. + /// + /// The item name. + /// True if item is in the inventory, false otherwise. + public bool InventoryContains(string item_name) + { + var found_index = InventoryIndexOf(item_name); + if (found_index > -1) + { + return true; + } + + return false; + } + + /// + /// Gets index of the first occurence of the item in the inventory. + /// + /// The item name. + /// The first index at which item is found, -1 if not found. + public int InventoryIndexOf(string item_name) + { + for (int x = 0; x < Items.Count; x++) + { + if (Items[x].Name == item_name) + { + return x; + } + } + + return -1; + } + /// public override string ToString() { diff --git a/Dota2GSI/StateHandlers/CouriersHandler.cs b/Dota2GSI/StateHandlers/CouriersHandler.cs index 139bf7b..98a5782 100644 --- a/Dota2GSI/StateHandlers/CouriersHandler.cs +++ b/Dota2GSI/StateHandlers/CouriersHandler.cs @@ -11,13 +11,15 @@ public class CouriersHandler : EventHandler public CouriersHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { dispatcher.Subscribe(OnFullPlayerDetailsUpdated); - dispatcher.Subscribe(OnCouriersStateUpdated); + dispatcher.Subscribe(OnCouriersUpdated); + dispatcher.Subscribe(OnCourierUpdated); } ~CouriersHandler() { dispatcher.Unsubscribe(OnFullPlayerDetailsUpdated); - dispatcher.Unsubscribe(OnCouriersStateUpdated); + dispatcher.Unsubscribe(OnCouriersUpdated); + dispatcher.Unsubscribe(OnCourierUpdated); } private void OnFullPlayerDetailsUpdated(DotaGameEvent e) @@ -32,7 +34,7 @@ private void OnFullPlayerDetailsUpdated(DotaGameEvent e) _player_cache[evt.New.PlayerID] = evt.New; } - private void OnCouriersStateUpdated(DotaGameEvent e) + private void OnCouriersUpdated(DotaGameEvent e) { CouriersUpdated evt = (e as CouriersUpdated); @@ -53,5 +55,42 @@ private void OnCouriersStateUpdated(DotaGameEvent e) } } } + + private void OnCourierUpdated(DotaGameEvent e) + { + CourierUpdated evt = (e as CourierUpdated); + + if (evt == null) + { + return; + } + + foreach (var item in evt.New.Items) + { + if (!evt.Previous.InventoryContains(item.Value.Name)) + { + // Courier gained an item. + dispatcher.Broadcast(new CourierItemAdded(item.Value, evt.New, evt.Player)); + continue; + } + + var previous_item = evt.Previous.GetInventoryItem(item.Value.Name); + + if (!item.Value.Equals(previous_item)) + { + // Item updated. + dispatcher.Broadcast(new CourierItemUpdated(item.Value, previous_item, evt.New, evt.Player)); + } + } + + foreach (var item in evt.Previous.Items) + { + if (!evt.New.InventoryContains(item.Value.Name)) + { + // Player lost an inventory item. + dispatcher.Broadcast(new CourierItemRemoved(item.Value, evt.New, evt.Player)); + } + } + } } } From 66043aac0634ee8c9b92dcf4e0957c9c243ccb48 Mon Sep 17 00:00:00 2001 From: Anton Pupkov Date: Wed, 17 Jan 2024 19:14:59 -0800 Subject: [PATCH 17/24] Remove superfluous "State" from event callbacks --- Dota2GSI/StateHandlers/AbilitiesHandler.cs | 6 +++--- Dota2GSI/StateHandlers/AuthHandler.cs | 6 +++--- Dota2GSI/StateHandlers/BuildingsHandler.cs | 6 +++--- Dota2GSI/StateHandlers/DraftHandler.cs | 6 +++--- Dota2GSI/StateHandlers/GameplayEventsHandler.cs | 6 +++--- Dota2GSI/StateHandlers/ItemsHandler.cs | 6 +++--- Dota2GSI/StateHandlers/LeagueHandler.cs | 6 +++--- Dota2GSI/StateHandlers/MapHandler.cs | 6 +++--- Dota2GSI/StateHandlers/MinimapHandler.cs | 6 +++--- Dota2GSI/StateHandlers/NeutralItemsHandler.cs | 6 +++--- Dota2GSI/StateHandlers/PlayerHandler.cs | 6 +++--- Dota2GSI/StateHandlers/ProviderHandler.cs | 6 +++--- Dota2GSI/StateHandlers/RoshanHandler.cs | 6 +++--- Dota2GSI/StateHandlers/WearablesHandler.cs | 6 +++--- 14 files changed, 42 insertions(+), 42 deletions(-) diff --git a/Dota2GSI/StateHandlers/AbilitiesHandler.cs b/Dota2GSI/StateHandlers/AbilitiesHandler.cs index 28cbd77..638b20b 100644 --- a/Dota2GSI/StateHandlers/AbilitiesHandler.cs +++ b/Dota2GSI/StateHandlers/AbilitiesHandler.cs @@ -13,14 +13,14 @@ public class AbilitiesHandler : EventHandler public AbilitiesHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { dispatcher.Subscribe(OnFullPlayerDetailsUpdated); - dispatcher.Subscribe(OnAbilitiesStateUpdated); + dispatcher.Subscribe(OnAbilitiesUpdated); dispatcher.Subscribe(OnAbilityDetailsChanged); } ~AbilitiesHandler() { dispatcher.Unsubscribe(OnFullPlayerDetailsUpdated); - dispatcher.Unsubscribe(OnAbilitiesStateUpdated); + dispatcher.Unsubscribe(OnAbilitiesUpdated); dispatcher.Unsubscribe(OnAbilityDetailsChanged); } @@ -36,7 +36,7 @@ private void OnFullPlayerDetailsUpdated(DotaGameEvent e) _player_cache[evt.New.PlayerID] = evt.New; } - private void OnAbilitiesStateUpdated(DotaGameEvent e) + private void OnAbilitiesUpdated(DotaGameEvent e) { AbilitiesUpdated evt = (e as AbilitiesUpdated); diff --git a/Dota2GSI/StateHandlers/AuthHandler.cs b/Dota2GSI/StateHandlers/AuthHandler.cs index 0fbb6bb..4809b95 100644 --- a/Dota2GSI/StateHandlers/AuthHandler.cs +++ b/Dota2GSI/StateHandlers/AuthHandler.cs @@ -6,15 +6,15 @@ public class AuthHandler : EventHandler { public AuthHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { - dispatcher.Subscribe(OnAuthStateUpdated); + dispatcher.Subscribe(OnAuthUpdated); } ~AuthHandler() { - dispatcher.Unsubscribe(OnAuthStateUpdated); + dispatcher.Unsubscribe(OnAuthUpdated); } - private void OnAuthStateUpdated(DotaGameEvent e) + private void OnAuthUpdated(DotaGameEvent e) { AuthUpdated evt = (e as AuthUpdated); diff --git a/Dota2GSI/StateHandlers/BuildingsHandler.cs b/Dota2GSI/StateHandlers/BuildingsHandler.cs index 92b7f11..0985bf3 100644 --- a/Dota2GSI/StateHandlers/BuildingsHandler.cs +++ b/Dota2GSI/StateHandlers/BuildingsHandler.cs @@ -6,17 +6,17 @@ public class BuildingsHandler : EventHandler { public BuildingsHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { - dispatcher.Subscribe(OnBuildingsStateUpdated); + dispatcher.Subscribe(OnBuildingsUpdated); dispatcher.Subscribe(OnBuildingsLayoutUpdated); } ~BuildingsHandler() { - dispatcher.Unsubscribe(OnBuildingsStateUpdated); + dispatcher.Unsubscribe(OnBuildingsUpdated); dispatcher.Unsubscribe(OnBuildingsLayoutUpdated); } - private void OnBuildingsStateUpdated(DotaGameEvent e) + private void OnBuildingsUpdated(DotaGameEvent e) { BuildingsUpdated evt = (e as BuildingsUpdated); diff --git a/Dota2GSI/StateHandlers/DraftHandler.cs b/Dota2GSI/StateHandlers/DraftHandler.cs index 698480b..bd0fd32 100644 --- a/Dota2GSI/StateHandlers/DraftHandler.cs +++ b/Dota2GSI/StateHandlers/DraftHandler.cs @@ -6,15 +6,15 @@ public class DraftHandler : EventHandler { public DraftHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { - dispatcher.Subscribe(OnDraftStateUpdated); + dispatcher.Subscribe(OnDraftUpdated); } ~DraftHandler() { - dispatcher.Unsubscribe(OnDraftStateUpdated); + dispatcher.Unsubscribe(OnDraftUpdated); } - private void OnDraftStateUpdated(DotaGameEvent e) + private void OnDraftUpdated(DotaGameEvent e) { DraftUpdated evt = (e as DraftUpdated); diff --git a/Dota2GSI/StateHandlers/GameplayEventsHandler.cs b/Dota2GSI/StateHandlers/GameplayEventsHandler.cs index 1c2742c..8ff0378 100644 --- a/Dota2GSI/StateHandlers/GameplayEventsHandler.cs +++ b/Dota2GSI/StateHandlers/GameplayEventsHandler.cs @@ -13,13 +13,13 @@ public class GameplayEventsHandler : EventHandler public GameplayEventsHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { dispatcher.Subscribe(OnFullPlayerDetailsUpdated); - dispatcher.Subscribe(OnEventsStateUpdated); + dispatcher.Subscribe(OnEventsUpdated); } ~GameplayEventsHandler() { dispatcher.Unsubscribe(OnFullPlayerDetailsUpdated); - dispatcher.Unsubscribe(OnEventsStateUpdated); + dispatcher.Unsubscribe(OnEventsUpdated); } private void OnFullPlayerDetailsUpdated(DotaGameEvent e) @@ -34,7 +34,7 @@ private void OnFullPlayerDetailsUpdated(DotaGameEvent e) _player_cache[evt.New.PlayerID] = evt.New; } - private void OnEventsStateUpdated(DotaGameEvent e) + private void OnEventsUpdated(DotaGameEvent e) { EventsUpdated evt = (e as EventsUpdated); diff --git a/Dota2GSI/StateHandlers/ItemsHandler.cs b/Dota2GSI/StateHandlers/ItemsHandler.cs index 25f05cb..4c87693 100644 --- a/Dota2GSI/StateHandlers/ItemsHandler.cs +++ b/Dota2GSI/StateHandlers/ItemsHandler.cs @@ -11,14 +11,14 @@ public class ItemsHandler : EventHandler public ItemsHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { dispatcher.Subscribe(OnFullPlayerDetailsUpdated); - dispatcher.Subscribe(OnItemsStateUpdated); + dispatcher.Subscribe(OnItemsUpdated); dispatcher.Subscribe(OnItemDetailsChanged); } ~ItemsHandler() { dispatcher.Unsubscribe(OnFullPlayerDetailsUpdated); - dispatcher.Unsubscribe(OnItemsStateUpdated); + dispatcher.Unsubscribe(OnItemsUpdated); dispatcher.Unsubscribe(OnItemDetailsChanged); } @@ -34,7 +34,7 @@ private void OnFullPlayerDetailsUpdated(DotaGameEvent e) _player_cache[evt.New.PlayerID] = evt.New; } - private void OnItemsStateUpdated(DotaGameEvent e) + private void OnItemsUpdated(DotaGameEvent e) { ItemsUpdated evt = (e as ItemsUpdated); diff --git a/Dota2GSI/StateHandlers/LeagueHandler.cs b/Dota2GSI/StateHandlers/LeagueHandler.cs index f329c54..a2dd44e 100644 --- a/Dota2GSI/StateHandlers/LeagueHandler.cs +++ b/Dota2GSI/StateHandlers/LeagueHandler.cs @@ -6,15 +6,15 @@ public class LeagueHandler : EventHandler { public LeagueHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { - dispatcher.Subscribe(OnLeagueStateUpdated); + dispatcher.Subscribe(OnLeagueUpdated); } ~LeagueHandler() { - dispatcher.Unsubscribe(OnLeagueStateUpdated); + dispatcher.Unsubscribe(OnLeagueUpdated); } - private void OnLeagueStateUpdated(DotaGameEvent e) + private void OnLeagueUpdated(DotaGameEvent e) { LeagueUpdated evt = (e as LeagueUpdated); diff --git a/Dota2GSI/StateHandlers/MapHandler.cs b/Dota2GSI/StateHandlers/MapHandler.cs index 1626462..b9aac11 100644 --- a/Dota2GSI/StateHandlers/MapHandler.cs +++ b/Dota2GSI/StateHandlers/MapHandler.cs @@ -6,15 +6,15 @@ public class MapHandler : EventHandler { public MapHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { - dispatcher.Subscribe(OnMapStateUpdated); + dispatcher.Subscribe(OnMapUpdated); } ~MapHandler() { - dispatcher.Unsubscribe(OnMapStateUpdated); + dispatcher.Unsubscribe(OnMapUpdated); } - private void OnMapStateUpdated(DotaGameEvent e) + private void OnMapUpdated(DotaGameEvent e) { MapUpdated evt = (e as MapUpdated); diff --git a/Dota2GSI/StateHandlers/MinimapHandler.cs b/Dota2GSI/StateHandlers/MinimapHandler.cs index 14d303b..799a868 100644 --- a/Dota2GSI/StateHandlers/MinimapHandler.cs +++ b/Dota2GSI/StateHandlers/MinimapHandler.cs @@ -6,15 +6,15 @@ public class MinimapHandler : EventHandler { public MinimapHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { - dispatcher.Subscribe(OnMinimapStateUpdated); + dispatcher.Subscribe(OnMinimapUpdated); } ~MinimapHandler() { - dispatcher.Unsubscribe(OnMinimapStateUpdated); + dispatcher.Unsubscribe(OnMinimapUpdated); } - private void OnMinimapStateUpdated(DotaGameEvent e) + private void OnMinimapUpdated(DotaGameEvent e) { MinimapUpdated evt = (e as MinimapUpdated); diff --git a/Dota2GSI/StateHandlers/NeutralItemsHandler.cs b/Dota2GSI/StateHandlers/NeutralItemsHandler.cs index 7097236..bdaca88 100644 --- a/Dota2GSI/StateHandlers/NeutralItemsHandler.cs +++ b/Dota2GSI/StateHandlers/NeutralItemsHandler.cs @@ -6,15 +6,15 @@ public class NeutralItemsHandler : EventHandler { public NeutralItemsHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { - dispatcher.Subscribe(OnNeutralItemsStateUpdated); + dispatcher.Subscribe(OnNeutralItemsUpdated); } ~NeutralItemsHandler() { - dispatcher.Unsubscribe(OnNeutralItemsStateUpdated); + dispatcher.Unsubscribe(OnNeutralItemsUpdated); } - private void OnNeutralItemsStateUpdated(DotaGameEvent e) + private void OnNeutralItemsUpdated(DotaGameEvent e) { NeutralItemsUpdated evt = (e as NeutralItemsUpdated); diff --git a/Dota2GSI/StateHandlers/PlayerHandler.cs b/Dota2GSI/StateHandlers/PlayerHandler.cs index f744d97..e8ed22e 100644 --- a/Dota2GSI/StateHandlers/PlayerHandler.cs +++ b/Dota2GSI/StateHandlers/PlayerHandler.cs @@ -11,14 +11,14 @@ public class PlayerHandler : EventHandler public PlayerHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { dispatcher.Subscribe(OnFullPlayerDetailsUpdated); - dispatcher.Subscribe(OnPlayerStateUpdated); + dispatcher.Subscribe(OnPlayerUpdated); dispatcher.Subscribe(OnPlayerDetailsChanged); } ~PlayerHandler() { dispatcher.Unsubscribe(OnFullPlayerDetailsUpdated); - dispatcher.Unsubscribe(OnPlayerStateUpdated); + dispatcher.Unsubscribe(OnPlayerUpdated); dispatcher.Unsubscribe(OnPlayerDetailsChanged); } @@ -34,7 +34,7 @@ private void OnFullPlayerDetailsUpdated(DotaGameEvent e) _player_cache[evt.New.PlayerID] = evt.New; } - private void OnPlayerStateUpdated(DotaGameEvent e) + private void OnPlayerUpdated(DotaGameEvent e) { PlayerUpdated evt = (e as PlayerUpdated); diff --git a/Dota2GSI/StateHandlers/ProviderHandler.cs b/Dota2GSI/StateHandlers/ProviderHandler.cs index 536a504..3108a8b 100644 --- a/Dota2GSI/StateHandlers/ProviderHandler.cs +++ b/Dota2GSI/StateHandlers/ProviderHandler.cs @@ -6,15 +6,15 @@ public class ProviderHandler : EventHandler { public ProviderHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { - dispatcher.Subscribe(OnProviderStateUpdated); + dispatcher.Subscribe(OnProviderUpdated); } ~ProviderHandler() { - dispatcher.Unsubscribe(OnProviderStateUpdated); + dispatcher.Unsubscribe(OnProviderUpdated); } - private void OnProviderStateUpdated(DotaGameEvent e) + private void OnProviderUpdated(DotaGameEvent e) { ProviderUpdated evt = (e as ProviderUpdated); diff --git a/Dota2GSI/StateHandlers/RoshanHandler.cs b/Dota2GSI/StateHandlers/RoshanHandler.cs index 406168d..c878a80 100644 --- a/Dota2GSI/StateHandlers/RoshanHandler.cs +++ b/Dota2GSI/StateHandlers/RoshanHandler.cs @@ -6,15 +6,15 @@ public class RoshanHandler : EventHandler { public RoshanHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { - dispatcher.Subscribe(OnRoshanStateUpdated); + dispatcher.Subscribe(OnRoshanUpdated); } ~RoshanHandler() { - dispatcher.Unsubscribe(OnRoshanStateUpdated); + dispatcher.Unsubscribe(OnRoshanUpdated); } - private void OnRoshanStateUpdated(DotaGameEvent e) + private void OnRoshanUpdated(DotaGameEvent e) { RoshanUpdated evt = (e as RoshanUpdated); diff --git a/Dota2GSI/StateHandlers/WearablesHandler.cs b/Dota2GSI/StateHandlers/WearablesHandler.cs index ca4f62b..d1a8203 100644 --- a/Dota2GSI/StateHandlers/WearablesHandler.cs +++ b/Dota2GSI/StateHandlers/WearablesHandler.cs @@ -11,13 +11,13 @@ public class WearablesHandler : EventHandler public WearablesHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { dispatcher.Subscribe(OnFullPlayerDetailsUpdated); - dispatcher.Subscribe(OnWearablesStateUpdated); + dispatcher.Subscribe(OnWearablesUpdated); } ~WearablesHandler() { dispatcher.Unsubscribe(OnFullPlayerDetailsUpdated); - dispatcher.Unsubscribe(OnWearablesStateUpdated); + dispatcher.Unsubscribe(OnWearablesUpdated); } private void OnFullPlayerDetailsUpdated(DotaGameEvent e) @@ -32,7 +32,7 @@ private void OnFullPlayerDetailsUpdated(DotaGameEvent e) _player_cache[evt.New.PlayerID] = evt.New; } - private void OnWearablesStateUpdated(DotaGameEvent e) + private void OnWearablesUpdated(DotaGameEvent e) { WearablesUpdated evt = (e as WearablesUpdated); From e2aeb23f18a571e56588f0aeaa26bf03cfa16d45 Mon Sep 17 00:00:00 2001 From: Anton Pupkov Date: Wed, 17 Jan 2024 19:15:50 -0800 Subject: [PATCH 18/24] Update example program --- .../Dota2GSI Example program/Program.cs | 88 ++++++++++++------- 1 file changed, 56 insertions(+), 32 deletions(-) diff --git a/Dota2GSI Example program/Dota2GSI Example program/Program.cs b/Dota2GSI Example program/Dota2GSI Example program/Program.cs index b13fcd6..f2b667f 100644 --- a/Dota2GSI Example program/Dota2GSI Example program/Program.cs +++ b/Dota2GSI Example program/Dota2GSI Example program/Program.cs @@ -25,8 +25,18 @@ static void Main(string[] args) } _gsl = new GameStateListener(4000); + + // There are many callbacks that can be subscribed. + // This example shows a few. // _gsl.NewGameState += OnNewGameState; // `NewGameState` can be used alongside `GameEvent`. Just not in this example. _gsl.GameEvent += OnGameEvent; // `GameEvent` can be used alongside `NewGameState`. + _gsl.TimeOfDayChanged += OnTimeOfDayChanged; + _gsl.TeamScoreChanged += OnTeamScoreChanged; + _gsl.PauseStateChanged += OnPauseStateChanged; + _gsl.PlayerGameplayEvent += OnPlayerGameplayEvent; + _gsl.TeamGameplayEvent += OnTeamGameplayEvent; + _gsl.InventoryItemAdded += OnInventoryItemAdded; + _gsl.InventoryItemRemoved += OnInventoryItemRemoved; if (!_gsl.Start()) { @@ -46,9 +56,43 @@ static void Main(string[] args) } while (Console.ReadKey(true).Key != ConsoleKey.Escape); } + private static void OnTimeOfDayChanged(TimeOfDayChanged game_event) + { + Console.WriteLine($"Is daytime: {game_event.IsDaytime} Is Nightstalker night: {game_event.IsNightstalkerNight}"); + } + private static void OnTeamScoreChanged(TeamScoreChanged game_event) + { + Console.WriteLine($"New score for {game_event.Team} is {game_event.New}"); + } + + private static void OnPauseStateChanged(PauseStateChanged game_event) + { + Console.WriteLine($"New pause state is {game_event.New}"); + } + + private static void OnPlayerGameplayEvent(PlayerGameplayEvent game_event) + { + Console.WriteLine($"Player {game_event.Player.Details.Name} did a thing: " + game_event.Value.EventType); + } + + private static void OnTeamGameplayEvent(TeamGameplayEvent game_event) + { + Console.WriteLine($"Team {game_event.Team} did a thing: " + game_event.Value.EventType); + } + + private static void OnInventoryItemAdded(InventoryItemAdded game_event) + { + Console.WriteLine($"Player {game_event.Player.Details.Name} gained an item in their inventory: " + game_event.Value.Name); + } + + private static void OnInventoryItemRemoved(InventoryItemRemoved game_event) + { + Console.WriteLine($"Player {game_event.Player.Details.Name} lost an item from their inventory: " + game_event.Value.Name); + } + private static void OnGameEvent(DotaGameEvent game_event) { - if (game_event is ProviderStateUpdated provider) + if (game_event is ProviderUpdated provider) { Console.WriteLine($"Current Game version: {provider.New.Version}"); Console.WriteLine($"Current Game time stamp: {provider.New.TimeStamp}"); @@ -58,52 +102,32 @@ private static void OnGameEvent(DotaGameEvent game_event) Console.WriteLine($"Player Name: {player_details.New.Name}"); Console.WriteLine($"Player Account ID: {player_details.New.AccountID}"); } - else if (game_event is TimeOfDayChanged time_of_day) - { - Console.WriteLine($"Is daytime: {time_of_day.IsDaytime} Is Nightstalker night: {time_of_day.IsNightstalkerNight}"); - } - else if (game_event is TeamScoreChanged team_score) - { - Console.WriteLine($"New score for {team_score.Team} is {team_score.New}"); - } - else if (game_event is PauseStateChanged paused_state) - { - Console.WriteLine($"New pause state is {paused_state.New}"); - } else if (game_event is HeroDetailsChanged hero_details) { - Console.WriteLine($"Player {hero_details.PlayerID} Hero ID: " + hero_details.New.ID); - Console.WriteLine($"Player {hero_details.PlayerID} Hero XP: " + hero_details.New.Experience); - Console.WriteLine($"Player {hero_details.PlayerID} Hero has Aghanims Shard upgrade: " + hero_details.New.HasAghanimsShardUpgrade); - Console.WriteLine($"Player {hero_details.PlayerID} Hero Health: " + hero_details.New.Health); - Console.WriteLine($"Player {hero_details.PlayerID} Hero Mana: " + hero_details.New.Mana); - Console.WriteLine($"Player {hero_details.PlayerID} Hero Location: " + hero_details.New.Location); + Console.WriteLine($"Player {hero_details.Player.Details.Name} Hero ID: " + hero_details.New.ID); + Console.WriteLine($"Player {hero_details.Player.Details.Name} Hero XP: " + hero_details.New.Experience); + Console.WriteLine($"Player {hero_details.Player.Details.Name} Hero has Aghanims Shard upgrade: " + hero_details.New.HasAghanimsShardUpgrade); + Console.WriteLine($"Player {hero_details.Player.Details.Name} Hero Health: " + hero_details.New.Health); + Console.WriteLine($"Player {hero_details.Player.Details.Name} Hero Mana: " + hero_details.New.Mana); + Console.WriteLine($"Player {hero_details.Player.Details.Name} Hero Location: " + hero_details.New.Location); } else if (game_event is AbilityUpdated ability) { - Console.WriteLine($"Player {ability.PlayerID} updated their ability: " + ability.New); + Console.WriteLine($"Player {ability.Player.Details.Name} updated their ability: " + ability.New); } else if (game_event is ItemDetailsChanged item_details) { - Console.WriteLine($"Player {item_details.PlayerID} updated their items: " + item_details.New); + Console.WriteLine($"Player {item_details.Player.Details.Name} updated their items: " + item_details.New); if (item_details.New.InventoryContains("item_blink")) { - Console.WriteLine($"Player {item_details.PlayerID} has a blink dagger."); + Console.WriteLine($"Player {item_details.Player.Details.Name} has a blink dagger."); } else { - Console.WriteLine($"Player {item_details.PlayerID} DOES NOT have a blink dagger."); + Console.WriteLine($"Player {item_details.Player.Details.Name} DOES NOT have a blink dagger."); } } - else if (game_event is PlayerEvent player_event) - { - Console.WriteLine($"Player {player_event.PlayerID} did a thing: " + player_event.Value.EventType); - } - else if (game_event is TeamEvent team_event) - { - Console.WriteLine($"Team {team_event.Team} did a thing: " + team_event.Value.EventType); - } else if (game_event is TowerUpdated tower_updated) { if (tower_updated.New.Health < tower_updated.Previous.Health) @@ -151,7 +175,7 @@ private static void OnGameEvent(DotaGameEvent game_event) } else if (game_event is CourierUpdated courier_updated) { - Console.WriteLine($"Player {courier_updated.PlayerID} courier updated: {courier_updated.New}"); + Console.WriteLine($"Player {courier_updated.Player.Details.Name} courier updated: {courier_updated.New}"); } else if (game_event is TeamDraftDetailsUpdated draft_details_updated) { From d160773a05d704aa6c0e06516dcc0932daf2ea84 Mon Sep 17 00:00:00 2001 From: Anton Pupkov Date: Thu, 18 Jan 2024 12:05:58 -0800 Subject: [PATCH 19/24] Resolve code review comments --- .../Dota2GSI Example program/Program.cs | 2 +- Dota2GSI/Dota2EventsInterface.cs | 30 ++- Dota2GSI/EventDispatcher.cs | 2 - Dota2GSI/EventMessages/AbilitiesEvents.cs | 8 +- Dota2GSI/EventMessages/BaseEvent.cs | 3 +- Dota2GSI/EventMessages/BuildingsEvents.cs | 18 +- Dota2GSI/EventMessages/CouriersEvents.cs | 1 - Dota2GSI/EventMessages/DotaGameEvent.cs | 3 +- Dota2GSI/EventMessages/DraftEvents.cs | 2 +- Dota2GSI/EventMessages/GameplayEvents.cs | 4 +- Dota2GSI/EventMessages/HeroEvents.cs | 2 +- Dota2GSI/EventMessages/MapEvents.cs | 4 +- Dota2GSI/EventMessages/MinimapEvents.cs | 20 ++ Dota2GSI/EventMessages/UpdateEvent.cs | 37 ++- Dota2GSI/GameState.cs | 32 +-- Dota2GSI/GameStateHandler.cs | 88 +++--- Dota2GSI/Nodes/AbilitiesProvider/Ability.cs | 18 +- Dota2GSI/Nodes/BuildingsProvider/Building.cs | 4 +- Dota2GSI/Nodes/CouriersProvider/Courier.cs | 29 +- .../Nodes/CouriersProvider/CourierItem.cs | 2 +- Dota2GSI/Nodes/Draft.cs | 10 +- Dota2GSI/Nodes/DraftProvider/DraftDetails.cs | 2 +- Dota2GSI/Nodes/EventsProvider/Event.cs | 20 +- Dota2GSI/Nodes/Helpers/FullPlayerDetails.cs | 4 +- Dota2GSI/Nodes/Helpers/FullTeamDetails.cs | 4 +- Dota2GSI/Nodes/HeroProvider/HeroDetails.cs | 76 ++++-- Dota2GSI/Nodes/ItemsProvider/Item.cs | 22 +- Dota2GSI/Nodes/League.cs | 38 +-- Dota2GSI/Nodes/LeagueProvider/LeagueTeam.cs | 4 +- .../Nodes/LeagueProvider/SelectionPriority.cs | 12 +- Dota2GSI/Nodes/LeagueProvider/Stream.cs | 6 +- Dota2GSI/Nodes/Map.cs | 30 +-- .../Nodes/MinimapProvider/MinimapElement.cs | 10 +- .../Nodes/NeutralItemsProvider/NeutralItem.cs | 8 +- .../NeutralItemsProvider/NeutralTierInfo.cs | 6 +- .../NeutralItemsProvider/TeamNeutralItems.cs | 2 +- Dota2GSI/Nodes/Node.cs | 4 +- .../Nodes/PlayerProvider/PlayerDetails.cs | 68 ++--- Dota2GSI/Nodes/Provider.cs | 4 +- Dota2GSI/Nodes/Roshan.cs | 12 +- .../Nodes/WearablesProvider/WearableItem.cs | 4 +- Dota2GSI/StateHandlers/BuildingsHandler.cs | 254 +++++++----------- Dota2GSI/StateHandlers/CouriersHandler.cs | 2 +- Dota2GSI/StateHandlers/ItemsHandler.cs | 2 +- Dota2GSI/StateHandlers/MapHandler.cs | 13 +- Dota2GSI/StateHandlers/MinimapHandler.cs | 11 + 46 files changed, 486 insertions(+), 451 deletions(-) diff --git a/Dota2GSI Example program/Dota2GSI Example program/Program.cs b/Dota2GSI Example program/Dota2GSI Example program/Program.cs index f2b667f..b8e0945 100644 --- a/Dota2GSI Example program/Dota2GSI Example program/Program.cs +++ b/Dota2GSI Example program/Dota2GSI Example program/Program.cs @@ -67,7 +67,7 @@ private static void OnTeamScoreChanged(TeamScoreChanged game_event) private static void OnPauseStateChanged(PauseStateChanged game_event) { - Console.WriteLine($"New pause state is {game_event.New}"); + Console.WriteLine($"New pause state is {(game_event.New ? "paused" : "not paused")}"); } private static void OnPlayerGameplayEvent(PlayerGameplayEvent game_event) diff --git a/Dota2GSI/Dota2EventsInterface.cs b/Dota2GSI/Dota2EventsInterface.cs index fb26bf1..e62a308 100644 --- a/Dota2GSI/Dota2EventsInterface.cs +++ b/Dota2GSI/Dota2EventsInterface.cs @@ -149,7 +149,7 @@ public class Dota2EventsInterface : EventsInterface #endregion - #region EventsEvents + #region GameplayEvents public delegate void EventsUpdatedHandler(EventsUpdated game_event); @@ -361,11 +361,21 @@ public class Dota2EventsInterface : EventsInterface /// public event MinimapUpdatedHandler MinimapUpdated = delegate { }; + public delegate void MinimapElementAddedHandler(MinimapElementAdded game_event); + + /// + public event MinimapElementAddedHandler MinimapElementAdded = delegate { }; + public delegate void MinimapElementUpdatedHandler(MinimapElementUpdated game_event); /// public event MinimapElementUpdatedHandler MinimapElementUpdated = delegate { }; + public delegate void MinimapElementRemovedHandler(MinimapElementRemoved game_event); + + /// + public event MinimapElementRemovedHandler MinimapElementRemoved = delegate { }; + public delegate void TeamMinimapElementUpdatedHandler(TeamMinimapElementUpdated game_event); /// @@ -382,7 +392,7 @@ public class Dota2EventsInterface : EventsInterface public delegate void TeamNeutralItemsUpdatedHandler(TeamNeutralItemsUpdated game_event); - /// + /// public event TeamNeutralItemsUpdatedHandler TeamNeutralItemsUpdated = delegate { }; #endregion @@ -421,17 +431,17 @@ public class Dota2EventsInterface : EventsInterface public delegate void PlayerDeniesChangedHandler(PlayerDeniesChanged game_event); - /// + /// public event PlayerDeniesChangedHandler PlayerDeniesChanged = delegate { }; public delegate void PlayerKillStreakChangedHandler(PlayerKillStreakChanged game_event); - /// + /// public event PlayerKillStreakChangedHandler PlayerKillStreakChanged = delegate { }; public delegate void PlayerGoldChangedHandler(PlayerGoldChanged game_event); - /// + /// public event PlayerGoldChangedHandler PlayerGoldChanged = delegate { }; public delegate void PlayerWardsPurchasedChangedHandler(PlayerWardsPurchasedChanged game_event); @@ -816,11 +826,21 @@ public override void OnNewGameEvent(DotaGameEvent e) RaiseEvent(MinimapUpdated, e); } + if (e is MinimapElementAdded) + { + RaiseEvent(MinimapElementAdded, e); + } + if (e is MinimapElementUpdated) { RaiseEvent(MinimapElementUpdated, e); } + if (e is MinimapElementRemoved) + { + RaiseEvent(MinimapElementRemoved, e); + } + if (e is TeamMinimapElementUpdated) { RaiseEvent(TeamMinimapElementUpdated, e); diff --git a/Dota2GSI/EventDispatcher.cs b/Dota2GSI/EventDispatcher.cs index db8313a..4089f44 100644 --- a/Dota2GSI/EventDispatcher.cs +++ b/Dota2GSI/EventDispatcher.cs @@ -50,7 +50,6 @@ private void RaiseOnGameEventHandler(T game_event) public void RegisterPreProcessor(Func callback) where MessageType : T { - var event_type = typeof(MessageType); lock (subscriptions_lock) @@ -66,7 +65,6 @@ public void RegisterPreProcessor(Func callback) where Message public void UnregisterPreProcessor(Func callback) where MessageType : T { - var event_type = typeof(MessageType); lock (subscriptions_lock) diff --git a/Dota2GSI/EventMessages/AbilitiesEvents.cs b/Dota2GSI/EventMessages/AbilitiesEvents.cs index b8b8ec3..2927de1 100644 --- a/Dota2GSI/EventMessages/AbilitiesEvents.cs +++ b/Dota2GSI/EventMessages/AbilitiesEvents.cs @@ -15,7 +15,7 @@ public AbilitiesUpdated(Abilities new_value, Abilities previous_value) : base(ne } /// - /// Event for specific Hero Ability Details change. + /// Event for specific player's Hero Ability Details change. /// public class AbilityDetailsChanged : PlayerUpdateEvent { @@ -25,7 +25,7 @@ public AbilityDetailsChanged(AbilityDetails new_value, AbilityDetails previous_v } /// - /// Event for specific Hero Ability addition. + /// Event for specific player's Hero Ability addition. /// public class AbilityAdded : PlayerValueEvent { @@ -35,7 +35,7 @@ public AbilityAdded(Ability value, FullPlayerDetails player) : base(value, playe } /// - /// Event for specific Hero Ability removal. + /// Event for specific player's Hero Ability removal. /// public class AbilityRemoved : PlayerValueEvent { @@ -45,7 +45,7 @@ public AbilityRemoved(Ability value, FullPlayerDetails player) : base(value, pla } /// - /// Event for specific Hero Ability update. + /// Event for specific player's Hero Ability update. /// public class AbilityUpdated : PlayerUpdateEvent { diff --git a/Dota2GSI/EventMessages/BaseEvent.cs b/Dota2GSI/EventMessages/BaseEvent.cs index fab2e4f..911618a 100644 --- a/Dota2GSI/EventMessages/BaseEvent.cs +++ b/Dota2GSI/EventMessages/BaseEvent.cs @@ -1,5 +1,4 @@ - -namespace Dota2GSI.EventMessages +namespace Dota2GSI.EventMessages { public interface BaseEvent { diff --git a/Dota2GSI/EventMessages/BuildingsEvents.cs b/Dota2GSI/EventMessages/BuildingsEvents.cs index de2d128..7741fce 100644 --- a/Dota2GSI/EventMessages/BuildingsEvents.cs +++ b/Dota2GSI/EventMessages/BuildingsEvents.cs @@ -14,7 +14,7 @@ public BuildingsUpdated(Buildings new_value, Buildings previous_value) : base(ne } /// - /// Event for specific team Building Layout update. + /// Event for specific team's Building Layout update. /// public class BuildingsLayoutUpdated : TeamUpdateEvent { @@ -65,7 +65,7 @@ public BuildingUpdated(Building new_value, Building previous_value, string entit } /// - /// Event for specific team Building update. + /// Event for specific team's Building update. /// public class TeamBuildingUpdated : BuildingUpdated { @@ -84,7 +84,7 @@ public TeamBuildingUpdated(Building new_value, Building previous_value, string e } /// - /// Event for specific team Building destruction. + /// Event for specific team's Building destruction. /// public class TeamBuildingDestroyed : TeamBuildingUpdated { @@ -94,7 +94,7 @@ public TeamBuildingDestroyed(Building new_value, Building previous_value, string } /// - /// Event for specific team Tower update. + /// Event for specific team's Tower update. /// public class TowerUpdated : TeamBuildingUpdated { @@ -104,7 +104,7 @@ public TowerUpdated(Building new_value, Building previous_value, string entity_i } /// - /// Event for specific team Tower destruction. + /// Event for specific team's Tower destruction. /// public class TowerDestroyed : TeamBuildingDestroyed { @@ -114,7 +114,7 @@ public TowerDestroyed(Building new_value, Building previous_value, string entity } /// - /// Event for specific team Racks update. + /// Event for specific team's Racks update. /// public class RacksUpdated : TeamBuildingUpdated { @@ -130,7 +130,7 @@ public RacksUpdated(Building new_value, Building previous_value, RacksType racks } /// - /// Event for specific team Racks destruction. + /// Event for specific team's Racks destruction. /// public class RacksDestroyed : TeamBuildingDestroyed { @@ -146,7 +146,7 @@ public RacksDestroyed(Building new_value, Building previous_value, RacksType rac } /// - /// Event for specific team Ancient update. + /// Event for specific team's Ancient update. /// public class AncientUpdated : TeamBuildingUpdated { @@ -156,7 +156,7 @@ public AncientUpdated(Building new_value, Building previous_value, string entity } /// - /// Event for specific team Ancient destruction. + /// Event for specific team's Ancient destruction. /// public class AncientDestroyed : TeamBuildingDestroyed { diff --git a/Dota2GSI/EventMessages/CouriersEvents.cs b/Dota2GSI/EventMessages/CouriersEvents.cs index af6efd9..f27b062 100644 --- a/Dota2GSI/EventMessages/CouriersEvents.cs +++ b/Dota2GSI/EventMessages/CouriersEvents.cs @@ -34,7 +34,6 @@ public TeamCourierUpdated(Courier new_value, Courier previous_value, PlayerTeam } } - /// /// Event for specific player's courier gaining an item in their inventory. /// diff --git a/Dota2GSI/EventMessages/DotaGameEvent.cs b/Dota2GSI/EventMessages/DotaGameEvent.cs index d02082f..6763596 100644 --- a/Dota2GSI/EventMessages/DotaGameEvent.cs +++ b/Dota2GSI/EventMessages/DotaGameEvent.cs @@ -1,5 +1,4 @@ - -namespace Dota2GSI.EventMessages +namespace Dota2GSI.EventMessages { public class DotaGameEvent : BaseEvent { diff --git a/Dota2GSI/EventMessages/DraftEvents.cs b/Dota2GSI/EventMessages/DraftEvents.cs index 5cd2c81..71a722a 100644 --- a/Dota2GSI/EventMessages/DraftEvents.cs +++ b/Dota2GSI/EventMessages/DraftEvents.cs @@ -14,7 +14,7 @@ public DraftUpdated(Draft new_value, Draft previous_value) : base(new_value, pre } /// - /// Event for specific team Draft Details update. + /// Event for specific team's Draft Details update. /// public class TeamDraftDetailsUpdated : TeamUpdateEvent { diff --git a/Dota2GSI/EventMessages/GameplayEvents.cs b/Dota2GSI/EventMessages/GameplayEvents.cs index c6ec0e0..2da2121 100644 --- a/Dota2GSI/EventMessages/GameplayEvents.cs +++ b/Dota2GSI/EventMessages/GameplayEvents.cs @@ -25,7 +25,7 @@ public GameplayEvent(Event value) : base(value) } /// - /// Event for specific team Gameplay Event. + /// Event for specific team's Gameplay Event. /// public class TeamGameplayEvent : TeamValueEvent { @@ -35,7 +35,7 @@ public TeamGameplayEvent(Event value, PlayerTeam team) : base(value, team) } /// - /// Event for specific player Event. + /// Event for specific player's Event. /// public class PlayerGameplayEvent : PlayerValueEvent { diff --git a/Dota2GSI/EventMessages/HeroEvents.cs b/Dota2GSI/EventMessages/HeroEvents.cs index 47add26..379d8fa 100644 --- a/Dota2GSI/EventMessages/HeroEvents.cs +++ b/Dota2GSI/EventMessages/HeroEvents.cs @@ -105,7 +105,7 @@ public HeroMuteStateChanged(bool new_value, bool previous_value, FullPlayerDetai } /// - /// Event for specific player's Hero selection. + /// Event for specific player's Hero selection update. /// public class HeroSelectedChanged : PlayerUpdateEvent { diff --git a/Dota2GSI/EventMessages/MapEvents.cs b/Dota2GSI/EventMessages/MapEvents.cs index b50a44c..395e46e 100644 --- a/Dota2GSI/EventMessages/MapEvents.cs +++ b/Dota2GSI/EventMessages/MapEvents.cs @@ -85,7 +85,7 @@ public GameResumed() : base() } /// - /// Event for specific team Victory. + /// Event for specific team's Victory. /// public class TeamVictory : DotaGameEvent { @@ -101,7 +101,7 @@ public TeamVictory(PlayerTeam team) : base() } /// - /// Event for specific team Defeat. + /// Event for specific team's Defeat. /// public class TeamDefeat : DotaGameEvent { diff --git a/Dota2GSI/EventMessages/MinimapEvents.cs b/Dota2GSI/EventMessages/MinimapEvents.cs index 3c65427..3ed2ba9 100644 --- a/Dota2GSI/EventMessages/MinimapEvents.cs +++ b/Dota2GSI/EventMessages/MinimapEvents.cs @@ -13,6 +13,16 @@ public MinimapUpdated(Minimap new_value, Minimap previous_value) : base(new_valu } } + /// + /// Event for a Minimap Element addition. + /// + public class MinimapElementAdded : EntityValueEvent + { + public MinimapElementAdded(MinimapElement value, string entity_id) : base(value, entity_id) + { + } + } + /// /// Event for a Minimap Element update. /// @@ -23,6 +33,16 @@ public MinimapElementUpdated(MinimapElement new_value, MinimapElement previous_v } } + /// + /// Event for a Minimap Element removal. + /// + public class MinimapElementRemoved : EntityValueEvent + { + public MinimapElementRemoved(MinimapElement value, string entity_id) : base(value, entity_id) + { + } + } + /// /// Event for specific team's Minimap Element update. /// diff --git a/Dota2GSI/EventMessages/UpdateEvent.cs b/Dota2GSI/EventMessages/UpdateEvent.cs index 2b01ff2..47bf68f 100644 --- a/Dota2GSI/EventMessages/UpdateEvent.cs +++ b/Dota2GSI/EventMessages/UpdateEvent.cs @@ -14,9 +14,9 @@ public class ValueEvent : DotaGameEvent /// public readonly T Value; - public ValueEvent(T obj) + public ValueEvent(T value) { - Value = obj; + Value = value; } } @@ -31,7 +31,7 @@ public class PlayerValueEvent : ValueEvent /// public readonly FullPlayerDetails Player; - public PlayerValueEvent(T obj, FullPlayerDetails player) : base(obj) + public PlayerValueEvent(T value, FullPlayerDetails player) : base(value) { Player = player; } @@ -48,7 +48,7 @@ public class TeamValueEvent : ValueEvent /// public readonly PlayerTeam Team; - public TeamValueEvent(T obj, PlayerTeam team) : base(obj) + public TeamValueEvent(T value, PlayerTeam team) : base(value) { Team = team; } @@ -70,10 +70,10 @@ public class UpdateEvent : DotaGameEvent /// public readonly T Previous; - public UpdateEvent(T new_obj, T previous_obj) + public UpdateEvent(T new_value, T previous_value) { - New = new_obj; - Previous = previous_obj; + New = new_value; + Previous = previous_value; } } @@ -88,7 +88,7 @@ public class PlayerUpdateEvent : UpdateEvent /// public readonly FullPlayerDetails Player; - public PlayerUpdateEvent(T new_obj, T previous_obj, FullPlayerDetails player) : base(new_obj, previous_obj) + public PlayerUpdateEvent(T new_value, T previous_value, FullPlayerDetails player) : base(new_value, previous_value) { Player = player; } @@ -105,12 +105,29 @@ public class TeamUpdateEvent : UpdateEvent /// public readonly PlayerTeam Team; - public TeamUpdateEvent(T new_obj, T previous_obj, PlayerTeam team) : base(new_obj, previous_obj) + public TeamUpdateEvent(T new_value, T previous_value, PlayerTeam team) : base(new_value, previous_value) { Team = team; } } + /// + /// Event for specific entity's single value update. + /// + /// + public class EntityValueEvent : ValueEvent + { + /// + /// The associated entity ID. + /// + public readonly string EntityID; + + public EntityValueEvent(T value, string entity_id) : base(value) + { + EntityID = entity_id; + } + } + /// /// Event for specific entity's value change. /// @@ -122,7 +139,7 @@ public class EntityUpdateEvent : UpdateEvent /// public readonly string EntityID; - public EntityUpdateEvent(T new_obj, T previous_obj, string entity_id) : base(new_obj, previous_obj) + public EntityUpdateEvent(T new_value, T previous_value, string entity_id) : base(new_value, previous_value) { EntityID = entity_id; } diff --git a/Dota2GSI/GameState.cs b/Dota2GSI/GameState.cs index f4fa32b..c05c021 100644 --- a/Dota2GSI/GameState.cs +++ b/Dota2GSI/GameState.cs @@ -129,12 +129,12 @@ public FullPlayerDetails LocalPlayer { get { - if (local_player_details == null) + if (_local_player_details == null) { - local_player_details = new FullPlayerDetails(this); + _local_player_details = new FullPlayerDetails(this); } - return local_player_details; + return _local_player_details; } } @@ -146,12 +146,12 @@ public FullTeamDetails RadiantTeamDetails { get { - if (radiant_team_details == null) + if (_radiant_team_details == null) { - radiant_team_details = new FullTeamDetails(PlayerTeam.Radiant, this); + _radiant_team_details = new FullTeamDetails(PlayerTeam.Radiant, this); } - return radiant_team_details; + return _radiant_team_details; } } @@ -163,12 +163,12 @@ public FullTeamDetails DireTeamDetails { get { - if (dire_team_details == null) + if (_dire_team_details == null) { - dire_team_details = new FullTeamDetails(PlayerTeam.Dire, this); + _dire_team_details = new FullTeamDetails(PlayerTeam.Dire, this); } - return dire_team_details; + return _dire_team_details; } } @@ -180,12 +180,12 @@ public FullTeamDetails NeutralTeamDetails { get { - if (neutral_team_details == null) + if (_neutral_team_details == null) { - neutral_team_details = new FullTeamDetails(PlayerTeam.Neutrals, this); + _neutral_team_details = new FullTeamDetails(PlayerTeam.Neutrals, this); } - return neutral_team_details; + return _neutral_team_details; } } @@ -219,10 +219,10 @@ public bool IsLocalPlayer // Helpers - private FullPlayerDetails local_player_details; - private FullTeamDetails radiant_team_details; - private FullTeamDetails dire_team_details; - private FullTeamDetails neutral_team_details; + private FullPlayerDetails _local_player_details; + private FullTeamDetails _radiant_team_details; + private FullTeamDetails _dire_team_details; + private FullTeamDetails _neutral_team_details; /// diff --git a/Dota2GSI/GameStateHandler.cs b/Dota2GSI/GameStateHandler.cs index 7a5612d..781f1d4 100644 --- a/Dota2GSI/GameStateHandler.cs +++ b/Dota2GSI/GameStateHandler.cs @@ -4,7 +4,7 @@ namespace Dota2GSI { public class GameStateHandler : EventHandler { - private GameState previous_game_state = new GameState(); + private GameState _previous_game_state = new GameState(); public GameStateHandler(ref EventDispatcher EventDispatcher) : base(ref EventDispatcher) { @@ -18,125 +18,125 @@ public void OnNewGameState(GameState game_state) return; } - if (!previous_game_state.IsValid() && game_state.Previously.IsValid()) + if (!_previous_game_state.IsValid() && game_state.Previously.IsValid()) { // Update previous game state cache. - previous_game_state = game_state.Previously; + _previous_game_state = game_state.Previously; } // Broadcast changes for custom providers. - if (!previous_game_state.LocalPlayer.Equals(game_state.LocalPlayer)) + if (!_previous_game_state.LocalPlayer.Equals(game_state.LocalPlayer)) { - dispatcher.Broadcast(new FullPlayerDetailsUpdated(game_state.LocalPlayer, previous_game_state.LocalPlayer)); + dispatcher.Broadcast(new FullPlayerDetailsUpdated(game_state.LocalPlayer, _previous_game_state.LocalPlayer)); } - if (!previous_game_state.RadiantTeamDetails.Equals(game_state.RadiantTeamDetails)) + if (!_previous_game_state.RadiantTeamDetails.Equals(game_state.RadiantTeamDetails)) { - dispatcher.Broadcast(new FullTeamDetailsUpdated(game_state.RadiantTeamDetails, previous_game_state.RadiantTeamDetails)); + dispatcher.Broadcast(new FullTeamDetailsUpdated(game_state.RadiantTeamDetails, _previous_game_state.RadiantTeamDetails)); } - if (!previous_game_state.DireTeamDetails.Equals(game_state.DireTeamDetails)) + if (!_previous_game_state.DireTeamDetails.Equals(game_state.DireTeamDetails)) { - dispatcher.Broadcast(new FullTeamDetailsUpdated(game_state.DireTeamDetails, previous_game_state.DireTeamDetails)); + dispatcher.Broadcast(new FullTeamDetailsUpdated(game_state.DireTeamDetails, _previous_game_state.DireTeamDetails)); } - if (!previous_game_state.NeutralTeamDetails.Equals(game_state.NeutralTeamDetails)) + if (!_previous_game_state.NeutralTeamDetails.Equals(game_state.NeutralTeamDetails)) { - dispatcher.Broadcast(new FullTeamDetailsUpdated(game_state.NeutralTeamDetails, previous_game_state.NeutralTeamDetails)); + dispatcher.Broadcast(new FullTeamDetailsUpdated(game_state.NeutralTeamDetails, _previous_game_state.NeutralTeamDetails)); } // Broadcast changes for providers. - if (!previous_game_state.Auth.Equals(game_state.Auth)) + if (!_previous_game_state.Auth.Equals(game_state.Auth)) { - dispatcher.Broadcast(new AuthUpdated(game_state.Auth, previous_game_state.Auth)); + dispatcher.Broadcast(new AuthUpdated(game_state.Auth, _previous_game_state.Auth)); } - if (!previous_game_state.Provider.Equals(game_state.Provider)) + if (!_previous_game_state.Provider.Equals(game_state.Provider)) { - dispatcher.Broadcast(new ProviderUpdated(game_state.Provider, previous_game_state.Provider)); + dispatcher.Broadcast(new ProviderUpdated(game_state.Provider, _previous_game_state.Provider)); } - if (!previous_game_state.Map.Equals(game_state.Map)) + if (!_previous_game_state.Map.Equals(game_state.Map)) { - dispatcher.Broadcast(new MapUpdated(game_state.Map, previous_game_state.Map)); + dispatcher.Broadcast(new MapUpdated(game_state.Map, _previous_game_state.Map)); } - if (!previous_game_state.Player.Equals(game_state.Player)) + if (!_previous_game_state.Player.Equals(game_state.Player)) { // Depends on FullPlayerDetailsUpdated. This broadcast must happen after FullPlayerDetailsUpdated. - dispatcher.Broadcast(new PlayerUpdated(game_state.Player, previous_game_state.Player)); + dispatcher.Broadcast(new PlayerUpdated(game_state.Player, _previous_game_state.Player)); } - if (!previous_game_state.Hero.Equals(game_state.Hero)) + if (!_previous_game_state.Hero.Equals(game_state.Hero)) { // Depends on FullPlayerDetailsUpdated. This broadcast must happen after FullPlayerDetailsUpdated. - dispatcher.Broadcast(new HeroUpdated(game_state.Hero, previous_game_state.Hero)); + dispatcher.Broadcast(new HeroUpdated(game_state.Hero, _previous_game_state.Hero)); } - if (!previous_game_state.Abilities.Equals(game_state.Abilities)) + if (!_previous_game_state.Abilities.Equals(game_state.Abilities)) { // Depends on FullPlayerDetailsUpdated. This broadcast must happen after FullPlayerDetailsUpdated. - dispatcher.Broadcast(new AbilitiesUpdated(game_state.Abilities, previous_game_state.Abilities)); + dispatcher.Broadcast(new AbilitiesUpdated(game_state.Abilities, _previous_game_state.Abilities)); } - if (!previous_game_state.Items.Equals(game_state.Items)) + if (!_previous_game_state.Items.Equals(game_state.Items)) { // Depends on FullPlayerDetailsUpdated. This broadcast must happen after FullPlayerDetailsUpdated. - dispatcher.Broadcast(new ItemsUpdated(game_state.Items, previous_game_state.Items)); + dispatcher.Broadcast(new ItemsUpdated(game_state.Items, _previous_game_state.Items)); } - if (!previous_game_state.Events.Equals(game_state.Events)) + if (!_previous_game_state.Events.Equals(game_state.Events)) { // Depends on FullPlayerDetailsUpdated. This broadcast must happen after FullPlayerDetailsUpdated. - dispatcher.Broadcast(new EventsUpdated(game_state.Events, previous_game_state.Events)); + dispatcher.Broadcast(new EventsUpdated(game_state.Events, _previous_game_state.Events)); } - if (!previous_game_state.Buildings.Equals(game_state.Buildings)) + if (!_previous_game_state.Buildings.Equals(game_state.Buildings)) { - dispatcher.Broadcast(new BuildingsUpdated(game_state.Buildings, previous_game_state.Buildings)); + dispatcher.Broadcast(new BuildingsUpdated(game_state.Buildings, _previous_game_state.Buildings)); } - if (!previous_game_state.League.Equals(game_state.League)) + if (!_previous_game_state.League.Equals(game_state.League)) { - dispatcher.Broadcast(new LeagueUpdated(game_state.League, previous_game_state.League)); + dispatcher.Broadcast(new LeagueUpdated(game_state.League, _previous_game_state.League)); } - if (!previous_game_state.Draft.Equals(game_state.Draft)) + if (!_previous_game_state.Draft.Equals(game_state.Draft)) { - dispatcher.Broadcast(new DraftUpdated(game_state.Draft, previous_game_state.Draft)); + dispatcher.Broadcast(new DraftUpdated(game_state.Draft, _previous_game_state.Draft)); } - if (!previous_game_state.Wearables.Equals(game_state.Wearables)) + if (!_previous_game_state.Wearables.Equals(game_state.Wearables)) { // Depends on FullPlayerDetailsUpdated. This broadcast must happen after FullPlayerDetailsUpdated. - dispatcher.Broadcast(new WearablesUpdated(game_state.Wearables, previous_game_state.Wearables)); + dispatcher.Broadcast(new WearablesUpdated(game_state.Wearables, _previous_game_state.Wearables)); } - if (!previous_game_state.Minimap.Equals(game_state.Minimap)) + if (!_previous_game_state.Minimap.Equals(game_state.Minimap)) { - dispatcher.Broadcast(new MinimapUpdated(game_state.Minimap, previous_game_state.Minimap)); + dispatcher.Broadcast(new MinimapUpdated(game_state.Minimap, _previous_game_state.Minimap)); } - if (!previous_game_state.Roshan.Equals(game_state.Roshan)) + if (!_previous_game_state.Roshan.Equals(game_state.Roshan)) { - dispatcher.Broadcast(new RoshanUpdated(game_state.Roshan, previous_game_state.Roshan)); + dispatcher.Broadcast(new RoshanUpdated(game_state.Roshan, _previous_game_state.Roshan)); } - if (!previous_game_state.Couriers.Equals(game_state.Couriers)) + if (!_previous_game_state.Couriers.Equals(game_state.Couriers)) { // Depends on FullPlayerDetailsUpdated. This broadcast must happen after FullPlayerDetailsUpdated. - dispatcher.Broadcast(new CouriersUpdated(game_state.Couriers, previous_game_state.Couriers)); + dispatcher.Broadcast(new CouriersUpdated(game_state.Couriers, _previous_game_state.Couriers)); } - if (!previous_game_state.NeutralItems.Equals(game_state.NeutralItems)) + if (!_previous_game_state.NeutralItems.Equals(game_state.NeutralItems)) { - dispatcher.Broadcast(new NeutralItemsUpdated(game_state.NeutralItems, previous_game_state.NeutralItems)); + dispatcher.Broadcast(new NeutralItemsUpdated(game_state.NeutralItems, _previous_game_state.NeutralItems)); } // Finally update the previous game state cache. - previous_game_state = game_state; + _previous_game_state = game_state; } } } diff --git a/Dota2GSI/Nodes/AbilitiesProvider/Ability.cs b/Dota2GSI/Nodes/AbilitiesProvider/Ability.cs index b61263b..93fa7d1 100644 --- a/Dota2GSI/Nodes/AbilitiesProvider/Ability.cs +++ b/Dota2GSI/Nodes/AbilitiesProvider/Ability.cs @@ -98,15 +98,15 @@ public override bool Equals(object obj) return obj is Ability other && Name.Equals(other.Name) && - Level == other.Level && - CanCast == other.CanCast && - IsPassive == other.IsPassive && - IsActive == other.IsActive && - Cooldown == other.Cooldown && - IsUltimate == other.IsUltimate && - Charges == other.Charges && - MaxCharges == other.MaxCharges && - ChargeCooldown == other.ChargeCooldown; + Level.Equals(other.Level) && + CanCast.Equals(other.CanCast) && + IsPassive.Equals(other.IsPassive) && + IsActive.Equals(other.IsActive) && + Cooldown.Equals(other.Cooldown) && + IsUltimate.Equals(other.IsUltimate) && + Charges.Equals(other.Charges) && + MaxCharges.Equals(other.MaxCharges) && + ChargeCooldown.Equals(other.ChargeCooldown); } /// diff --git a/Dota2GSI/Nodes/BuildingsProvider/Building.cs b/Dota2GSI/Nodes/BuildingsProvider/Building.cs index 1a49b59..344abaa 100644 --- a/Dota2GSI/Nodes/BuildingsProvider/Building.cs +++ b/Dota2GSI/Nodes/BuildingsProvider/Building.cs @@ -41,8 +41,8 @@ public override bool Equals(object obj) } return obj is Building other && - Health == other.Health && - MaxHealth == other.MaxHealth; + Health.Equals(other.Health) && + MaxHealth.Equals(other.MaxHealth); } /// diff --git a/Dota2GSI/Nodes/CouriersProvider/Courier.cs b/Dota2GSI/Nodes/CouriersProvider/Courier.cs index 3086196..b5741c5 100644 --- a/Dota2GSI/Nodes/CouriersProvider/Courier.cs +++ b/Dota2GSI/Nodes/CouriersProvider/Courier.cs @@ -130,12 +130,7 @@ public CourierItem GetInventoryItem(string item_name) public bool InventoryContains(string item_name) { var found_index = InventoryIndexOf(item_name); - if (found_index > -1) - { - return true; - } - - return false; + return found_index > -1; } /// @@ -145,11 +140,11 @@ public bool InventoryContains(string item_name) /// The first index at which item is found, -1 if not found. public int InventoryIndexOf(string item_name) { - for (int x = 0; x < Items.Count; x++) + foreach (var item_kvp in Items) { - if (Items[x].Name == item_name) + if (item_kvp.Value.Name == item_name) { - return x; + return item_kvp.Key; } } @@ -183,16 +178,16 @@ public override bool Equals(object obj) } return obj is Courier other && - Health == other.Health && - MaxHealth == other.MaxHealth && - IsAlive == other.IsAlive && - RemainingRespawnTime == other.RemainingRespawnTime && + Health.Equals(other.Health) && + MaxHealth.Equals(other.MaxHealth) && + IsAlive.Equals(other.IsAlive) && + RemainingRespawnTime.Equals(other.RemainingRespawnTime) && Location.Equals(other.Location) && - Rotation == other.Rotation && + Rotation.Equals(other.Rotation) && OwnerID.Equals(other.OwnerID) && - HasFlyingUpgrade == other.HasFlyingUpgrade && - IsShielded == other.IsShielded && - IsBoosted == other.IsBoosted && + HasFlyingUpgrade.Equals(other.HasFlyingUpgrade) && + IsShielded.Equals(other.IsShielded) && + IsBoosted.Equals(other.IsBoosted) && Items.Equals(other.Items); } diff --git a/Dota2GSI/Nodes/CouriersProvider/CourierItem.cs b/Dota2GSI/Nodes/CouriersProvider/CourierItem.cs index dee8c54..58105da 100644 --- a/Dota2GSI/Nodes/CouriersProvider/CourierItem.cs +++ b/Dota2GSI/Nodes/CouriersProvider/CourierItem.cs @@ -42,7 +42,7 @@ public override bool Equals(object obj) return obj is CourierItem other && Name.Equals(other.Name) && - OwnerID == other.OwnerID; + OwnerID.Equals(other.OwnerID); } /// diff --git a/Dota2GSI/Nodes/Draft.cs b/Dota2GSI/Nodes/Draft.cs index e547ef0..56b1ce5 100644 --- a/Dota2GSI/Nodes/Draft.cs +++ b/Dota2GSI/Nodes/Draft.cs @@ -95,11 +95,11 @@ public override bool Equals(object obj) } return obj is Draft other && - ActiveTeam == other.ActiveTeam && - Pick == other.Pick && - ActiveTeamRemainingTime == other.ActiveTeamRemainingTime && - RadiantBonusTime == other.RadiantBonusTime && - DireBonusTime == other.DireBonusTime && + ActiveTeam.Equals(other.ActiveTeam) && + Pick.Equals(other.Pick) && + ActiveTeamRemainingTime.Equals(other.ActiveTeamRemainingTime) && + RadiantBonusTime.Equals(other.RadiantBonusTime) && + DireBonusTime.Equals(other.DireBonusTime) && Teams.Equals(other.Teams); } diff --git a/Dota2GSI/Nodes/DraftProvider/DraftDetails.cs b/Dota2GSI/Nodes/DraftProvider/DraftDetails.cs index c01996a..945fa58 100644 --- a/Dota2GSI/Nodes/DraftProvider/DraftDetails.cs +++ b/Dota2GSI/Nodes/DraftProvider/DraftDetails.cs @@ -65,7 +65,7 @@ public override bool Equals(object obj) } return obj is DraftDetails other && - IsHomeTeam == other.IsHomeTeam && + IsHomeTeam.Equals(other.IsHomeTeam) && PickIDs.Equals(other.PickIDs) && PickHeroIDs.Equals(other.PickHeroIDs); } diff --git a/Dota2GSI/Nodes/EventsProvider/Event.cs b/Dota2GSI/Nodes/EventsProvider/Event.cs index 2861b4e..5b91a5b 100644 --- a/Dota2GSI/Nodes/EventsProvider/Event.cs +++ b/Dota2GSI/Nodes/EventsProvider/Event.cs @@ -162,16 +162,16 @@ public override bool Equals(object obj) } return obj is Event other && - GameTime == other.GameTime && - EventType == other.EventType && - Team == other.Team && - KillerPlayerID == other.KillerPlayerID && - PlayerID == other.PlayerID && - WasSnatched == other.WasSnatched && - TipReceiverPlayerID == other.TipReceiverPlayerID && - TipAmount == other.TipAmount && - BountyValue == other.BountyValue && - TeamGold == other.TeamGold; + GameTime.Equals(other.GameTime) && + EventType.Equals(other.EventType) && + Team.Equals(other.Team) && + KillerPlayerID.Equals(other.KillerPlayerID) && + PlayerID.Equals(other.PlayerID) && + WasSnatched.Equals(other.WasSnatched) && + TipReceiverPlayerID.Equals(other.TipReceiverPlayerID) && + TipAmount.Equals(other.TipAmount) && + BountyValue.Equals(other.BountyValue) && + TeamGold.Equals(other.TeamGold); } /// diff --git a/Dota2GSI/Nodes/Helpers/FullPlayerDetails.cs b/Dota2GSI/Nodes/Helpers/FullPlayerDetails.cs index 0994130..772cd4c 100644 --- a/Dota2GSI/Nodes/Helpers/FullPlayerDetails.cs +++ b/Dota2GSI/Nodes/Helpers/FullPlayerDetails.cs @@ -21,7 +21,7 @@ public class FullPlayerDetails /// /// True if player details are for the local player. /// - public readonly bool IsLocalPlayer; + public bool IsLocalPlayer => PlayerID.Equals(-1); /// /// Player's basic details. @@ -60,7 +60,6 @@ public class FullPlayerDetails internal FullPlayerDetails(int player_id, GameState game_state) { - IsLocalPlayer = false; PlayerID = player_id; Details = game_state.Player.GetForPlayer(player_id); Hero = game_state.Hero.GetForPlayer(player_id); @@ -73,7 +72,6 @@ internal FullPlayerDetails(int player_id, GameState game_state) internal FullPlayerDetails(GameState game_state) { - IsLocalPlayer = true; PlayerID = -1; Details = game_state.Player.LocalPlayer; Hero = game_state.Hero.LocalPlayer; diff --git a/Dota2GSI/Nodes/Helpers/FullTeamDetails.cs b/Dota2GSI/Nodes/Helpers/FullTeamDetails.cs index 5351685..3d1b294 100644 --- a/Dota2GSI/Nodes/Helpers/FullTeamDetails.cs +++ b/Dota2GSI/Nodes/Helpers/FullTeamDetails.cs @@ -94,14 +94,14 @@ public override bool Equals(object obj) } return obj is FullTeamDetails other && - Team == other.Team && + Team.Equals(other.Team) && Players.Equals(other.Players) && Draft.Equals(other.Draft) && NeutralItems.Equals(other.NeutralItems) && Buildings.Equals(other.Buildings) && MinimapElements.Equals(other.MinimapElements) && Events.Equals(other.Events) && - IsWinner == other.IsWinner; + IsWinner.Equals(other.IsWinner); } /// diff --git a/Dota2GSI/Nodes/HeroProvider/HeroDetails.cs b/Dota2GSI/Nodes/HeroProvider/HeroDetails.cs index a35f8f3..142238f 100644 --- a/Dota2GSI/Nodes/HeroProvider/HeroDetails.cs +++ b/Dota2GSI/Nodes/HeroProvider/HeroDetails.cs @@ -166,6 +166,46 @@ public class HeroDetails : Node /// public readonly HeroState HeroState; + /// + /// A boolean representing whether the hero is silenced. + /// + public bool IsSilenced => HeroState.HasFlag(HeroState.Silenced); + + /// + /// A boolean representing whether the hero is stunned. + /// + public bool IsStunned => HeroState.HasFlag(HeroState.Stunned); + + /// + /// A boolean representing whether the hero is disarmed. + /// + public bool IsDisarmed => HeroState.HasFlag(HeroState.Disarmed); + + /// + /// A boolean representing whether the hero is magic immune. + /// + public bool IsMagicImmune => HeroState.HasFlag(HeroState.MagicImmune); + + /// + /// A boolean representing whether the hero is hexed. + /// + public bool IsHexed => HeroState.HasFlag(HeroState.Hexed); + + /// + /// A boolean representing whether the hero is broken. + /// + public bool IsBreak => HeroState.HasFlag(HeroState.Broken); + + /// + /// A boolean representing whether the hero is smoked. + /// + public bool IsSmoked => HeroState.HasFlag(HeroState.Smoked); + + /// + /// A boolean representing whether the hero is debuffed. + /// + public bool HasDebuff => HeroState.HasFlag(HeroState.Debuffed); + /// /// A boolean representing whether the hero is muted. /// @@ -330,26 +370,26 @@ public override bool Equals(object obj) return obj is HeroDetails other && Location.Equals(other.Location) && - ID == other.ID && + ID.Equals(other.ID) && Name.Equals(other.Name) && - Level == other.Level && - Experience == other.Experience && - IsAlive == other.IsAlive && - SecondsToRespawn == other.SecondsToRespawn && - BuybackCost == other.BuybackCost && - BuybackCooldown == other.BuybackCooldown && - Health == other.Health && - MaxHealth == other.MaxHealth && - HealthPercent == other.HealthPercent && - Mana == other.Mana && - MaxMana == other.MaxMana && - ManaPercent == other.ManaPercent && - IsMuted == other.IsMuted && - HasAghanimsScepterUpgrade == other.HasAghanimsScepterUpgrade && - HasAghanimsShardUpgrade == other.HasAghanimsShardUpgrade && - SelectedUnit == other.SelectedUnit && + Level.Equals(other.Level) && + Experience.Equals(other.Experience) && + IsAlive.Equals(other.IsAlive) && + SecondsToRespawn.Equals(other.SecondsToRespawn) && + BuybackCost.Equals(other.BuybackCost) && + BuybackCooldown.Equals(other.BuybackCooldown) && + Health.Equals(other.Health) && + MaxHealth.Equals(other.MaxHealth) && + HealthPercent.Equals(other.HealthPercent) && + Mana.Equals(other.Mana) && + MaxMana.Equals(other.MaxMana) && + ManaPercent.Equals(other.ManaPercent) && + IsMuted.Equals(other.IsMuted) && + HasAghanimsScepterUpgrade.Equals(other.HasAghanimsScepterUpgrade) && + HasAghanimsShardUpgrade.Equals(other.HasAghanimsShardUpgrade) && + SelectedUnit.Equals(other.SelectedUnit) && Enumerable.SequenceEqual(TalentTree, other.TalentTree) && - AttributesLevel == other.AttributesLevel; + AttributesLevel.Equals(other.AttributesLevel); } /// diff --git a/Dota2GSI/Nodes/ItemsProvider/Item.cs b/Dota2GSI/Nodes/ItemsProvider/Item.cs index f0175e1..49f718f 100644 --- a/Dota2GSI/Nodes/ItemsProvider/Item.cs +++ b/Dota2GSI/Nodes/ItemsProvider/Item.cs @@ -179,17 +179,17 @@ public override bool Equals(object obj) return obj is Item other && Name.Equals(other.Name) && - Purchaser == other.Purchaser && - ItemLevel == other.ItemLevel && - ContainsRune == other.ContainsRune && - CanCast == other.CanCast && - Cooldown == other.Cooldown && - IsPassive == other.IsPassive && - ItemCharges == other.ItemCharges && - AbilityCharges == other.AbilityCharges && - MaxCharges == other.MaxCharges && - ChargeCooldown == other.ChargeCooldown && - Charges == other.Charges; + Purchaser.Equals(other.Purchaser) && + ItemLevel.Equals(other.ItemLevel) && + ContainsRune.Equals(other.ContainsRune) && + CanCast.Equals(other.CanCast) && + Cooldown.Equals(other.Cooldown) && + IsPassive.Equals(other.IsPassive) && + ItemCharges.Equals(other.ItemCharges) && + AbilityCharges.Equals(other.AbilityCharges) && + MaxCharges.Equals(other.MaxCharges) && + ChargeCooldown.Equals(other.ChargeCooldown) && + Charges.Equals(other.Charges); } /// diff --git a/Dota2GSI/Nodes/League.cs b/Dota2GSI/Nodes/League.cs index 50eefb7..51e8b43 100644 --- a/Dota2GSI/Nodes/League.cs +++ b/Dota2GSI/Nodes/League.cs @@ -254,32 +254,32 @@ public override bool Equals(object obj) } return obj is League other && - SeriesType == other.SeriesType && + SeriesType.Equals(other.SeriesType) && SelectionPriority.Equals(other.SelectionPriority) && - LeagueID == other.LeagueID && - MatchID == other.MatchID && + LeagueID.Equals(other.LeagueID) && + MatchID.Equals(other.MatchID) && Name.Equals(other.Name) && - Tier == other.Tier && - Region == other.Region && + Tier.Equals(other.Tier) && + Region.Equals(other.Region) && Url.Equals(other.Url) && Description.Equals(other.Description) && Notes.Equals(other.Notes) && - StartTimestamp == other.StartTimestamp && - EndTimestamp == other.EndTimestamp && - ProCircuitPoints == other.ProCircuitPoints && - ImageBits == other.ImageBits && - Status == other.Status && - MostRecentActivity == other.MostRecentActivity && - RegistrationPeriod == other.RegistrationPeriod && - BasePrizePool == other.BasePrizePool && - TotalPrizePool == other.TotalPrizePool && - LeagueNoteID == other.LeagueNoteID && + StartTimestamp.Equals(other.StartTimestamp) && + EndTimestamp.Equals(other.EndTimestamp) && + ProCircuitPoints.Equals(other.ProCircuitPoints) && + ImageBits.Equals(other.ImageBits) && + Status.Equals(other.Status) && + MostRecentActivity.Equals(other.MostRecentActivity) && + RegistrationPeriod.Equals(other.RegistrationPeriod) && + BasePrizePool.Equals(other.BasePrizePool) && + TotalPrizePool.Equals(other.TotalPrizePool) && + LeagueNoteID.Equals(other.LeagueNoteID) && RadiantTeam.Equals(other.RadiantTeam) && DireTeam.Equals(other.DireTeam) && - SeriesID == other.SeriesID && - StartTime == other.StartTime && - FirstTeamID == other.FirstTeamID && - SecondTeamID == other.SecondTeamID && + SeriesID.Equals(other.SeriesID) && + StartTime.Equals(other.StartTime) && + FirstTeamID.Equals(other.FirstTeamID) && + SecondTeamID.Equals(other.SecondTeamID) && Streams.Equals(other.Streams); } diff --git a/Dota2GSI/Nodes/LeagueProvider/LeagueTeam.cs b/Dota2GSI/Nodes/LeagueProvider/LeagueTeam.cs index be7ab8d..c3e6067 100644 --- a/Dota2GSI/Nodes/LeagueProvider/LeagueTeam.cs +++ b/Dota2GSI/Nodes/LeagueProvider/LeagueTeam.cs @@ -55,10 +55,10 @@ public override bool Equals(object obj) } return obj is LeagueTeam other && - TeamID == other.TeamID && + TeamID.Equals(other.TeamID) && TeamTag.Equals(other.TeamTag) && TeamName.Equals(other.TeamName) && - SeriesWins == other.SeriesWins; + SeriesWins.Equals(other.SeriesWins); } /// diff --git a/Dota2GSI/Nodes/LeagueProvider/SelectionPriority.cs b/Dota2GSI/Nodes/LeagueProvider/SelectionPriority.cs index cc7c2af..ae0ae7f 100644 --- a/Dota2GSI/Nodes/LeagueProvider/SelectionPriority.cs +++ b/Dota2GSI/Nodes/LeagueProvider/SelectionPriority.cs @@ -136,12 +136,12 @@ public override bool Equals(object obj) } return obj is SelectionPriority other && - Rules == other.Rules && - PreviousPriorityTeamID == other.PreviousPriorityTeamID && - CurrentPriorityTeamID == other.CurrentPriorityTeamID && - PriorityTeamChoice == other.PriorityTeamChoice && - NonPriorityTeamChoice == other.NonPriorityTeamChoice && - UsedCoinToss == other.UsedCoinToss; + Rules.Equals(other.Rules) && + PreviousPriorityTeamID.Equals(other.PreviousPriorityTeamID) && + CurrentPriorityTeamID.Equals(other.CurrentPriorityTeamID) && + PriorityTeamChoice.Equals(other.PriorityTeamChoice) && + NonPriorityTeamChoice.Equals(other.NonPriorityTeamChoice) && + UsedCoinToss.Equals(other.UsedCoinToss); } /// diff --git a/Dota2GSI/Nodes/LeagueProvider/Stream.cs b/Dota2GSI/Nodes/LeagueProvider/Stream.cs index c200a56..ce0d81c 100644 --- a/Dota2GSI/Nodes/LeagueProvider/Stream.cs +++ b/Dota2GSI/Nodes/LeagueProvider/Stream.cs @@ -69,10 +69,10 @@ public override bool Equals(object obj) } return obj is Stream other && - StreamID == other.StreamID && - Language == other.Language && + StreamID.Equals(other.StreamID) && + Language.Equals(other.Language) && Name.Equals(other.Name) && - BroadcastProvider == other.BroadcastProvider && + BroadcastProvider.Equals(other.BroadcastProvider) && StreamURL.Equals(other.StreamURL) && VodURL.Equals(other.VodURL); } diff --git a/Dota2GSI/Nodes/Map.cs b/Dota2GSI/Nodes/Map.cs index fbac0ac..66ddd8d 100644 --- a/Dota2GSI/Nodes/Map.cs +++ b/Dota2GSI/Nodes/Map.cs @@ -287,22 +287,22 @@ public override bool Equals(object obj) return obj is Map other && Name.Equals(other.Name) && - MatchID == other.MatchID && - GameTime == other.GameTime && - ClockTime == other.ClockTime && - IsDaytime == other.IsDaytime && - IsNightstalkerNight == other.IsNightstalkerNight && - RadiantScore == other.RadiantScore && - DireScore == other.DireScore && - GameState == other.GameState && - IsPaused == other.IsPaused && - WinningTeam == other.WinningTeam && + MatchID.Equals(other.MatchID) && + GameTime.Equals(other.GameTime) && + ClockTime.Equals(other.ClockTime) && + IsDaytime.Equals(other.IsDaytime) && + IsNightstalkerNight.Equals(other.IsNightstalkerNight) && + RadiantScore.Equals(other.RadiantScore) && + DireScore.Equals(other.DireScore) && + GameState.Equals(other.GameState) && + IsPaused.Equals(other.IsPaused) && + WinningTeam.Equals(other.WinningTeam) && CustomGameName.Equals(other.CustomGameName) && - WardPurchaseCooldown == other.WardPurchaseCooldown && - RadiantWardPurchaseCooldown == other.RadiantWardPurchaseCooldown && - DireWardPurchaseCooldown == other.DireWardPurchaseCooldown && - RoshanState == other.RoshanState && - RoshanStateEndTime == other.RoshanStateEndTime; + WardPurchaseCooldown.Equals(other.WardPurchaseCooldown) && + RadiantWardPurchaseCooldown.Equals(other.RadiantWardPurchaseCooldown) && + DireWardPurchaseCooldown.Equals(other.DireWardPurchaseCooldown) && + RoshanState.Equals(other.RoshanState) && + RoshanStateEndTime.Equals(other.RoshanStateEndTime); } /// diff --git a/Dota2GSI/Nodes/MinimapProvider/MinimapElement.cs b/Dota2GSI/Nodes/MinimapProvider/MinimapElement.cs index 3137019..5ae08b7 100644 --- a/Dota2GSI/Nodes/MinimapProvider/MinimapElement.cs +++ b/Dota2GSI/Nodes/MinimapProvider/MinimapElement.cs @@ -92,14 +92,14 @@ public override bool Equals(object obj) return obj is MinimapElement other && Location.Equals(other.Location) && - RemainingTime == other.RemainingTime && - EventDuration == other.EventDuration && + RemainingTime.Equals(other.RemainingTime) && + EventDuration.Equals(other.EventDuration) && Image.Equals(other.Image) && - Team == other.Team && + Team.Equals(other.Team) && Name.Equals(other.Name) && - Rotation == other.Rotation && + Rotation.Equals(other.Rotation) && UnitName.Equals(other.UnitName) && - VisionRange == other.VisionRange; + VisionRange.Equals(other.VisionRange); } /// diff --git a/Dota2GSI/Nodes/NeutralItemsProvider/NeutralItem.cs b/Dota2GSI/Nodes/NeutralItemsProvider/NeutralItem.cs index 2de8ed1..cddbd9a 100644 --- a/Dota2GSI/Nodes/NeutralItemsProvider/NeutralItem.cs +++ b/Dota2GSI/Nodes/NeutralItemsProvider/NeutralItem.cs @@ -109,10 +109,10 @@ public override bool Equals(object obj) return obj is NeutralItem other && Name.Equals(other.Name) && - Tier == other.Tier && - Charges == other.Charges && - State == other.State && - PlayerID == other.PlayerID; + Tier.Equals(other.Tier) && + Charges.Equals(other.Charges) && + State.Equals(other.State) && + PlayerID.Equals(other.PlayerID); } /// diff --git a/Dota2GSI/Nodes/NeutralItemsProvider/NeutralTierInfo.cs b/Dota2GSI/Nodes/NeutralItemsProvider/NeutralTierInfo.cs index f44b24c..bf1713b 100644 --- a/Dota2GSI/Nodes/NeutralItemsProvider/NeutralTierInfo.cs +++ b/Dota2GSI/Nodes/NeutralItemsProvider/NeutralTierInfo.cs @@ -48,9 +48,9 @@ public override bool Equals(object obj) } return obj is NeutralTierInfo other && - Tier == other.Tier && - MaxCount == other.MaxCount && - DropAfterTime == other.DropAfterTime; + Tier.Equals(other.Tier) && + MaxCount.Equals(other.MaxCount) && + DropAfterTime.Equals(other.DropAfterTime); } /// diff --git a/Dota2GSI/Nodes/NeutralItemsProvider/TeamNeutralItems.cs b/Dota2GSI/Nodes/NeutralItemsProvider/TeamNeutralItems.cs index c953daa..d56d41a 100644 --- a/Dota2GSI/Nodes/NeutralItemsProvider/TeamNeutralItems.cs +++ b/Dota2GSI/Nodes/NeutralItemsProvider/TeamNeutralItems.cs @@ -70,7 +70,7 @@ public override bool Equals(object obj) } return obj is TeamNeutralItems other && - ItemsFound == other.ItemsFound && + ItemsFound.Equals(other.ItemsFound) && TeamItems.Equals(other.TeamItems); } diff --git a/Dota2GSI/Nodes/Node.cs b/Dota2GSI/Nodes/Node.cs index e0415d2..9007cd6 100644 --- a/Dota2GSI/Nodes/Node.cs +++ b/Dota2GSI/Nodes/Node.cs @@ -282,7 +282,7 @@ public override string ToString() } else { - return_string += $", "; + return_string += ", "; } return_string += $"{kvp.Key}: {kvp.Value}"; @@ -347,7 +347,7 @@ public override string ToString() } else { - return_string += $", "; + return_string += ", "; } return_string += $"{item}"; diff --git a/Dota2GSI/Nodes/PlayerProvider/PlayerDetails.cs b/Dota2GSI/Nodes/PlayerProvider/PlayerDetails.cs index 8718950..c177f38 100644 --- a/Dota2GSI/Nodes/PlayerProvider/PlayerDetails.cs +++ b/Dota2GSI/Nodes/PlayerProvider/PlayerDetails.cs @@ -335,42 +335,42 @@ public override bool Equals(object obj) SteamID.Equals(other.SteamID) && AccountID.Equals(other.AccountID) && Name.Equals(other.Name) && - Activity == other.Activity && - Kills == other.Kills && - Deaths == other.Deaths && - Assists == other.Assists && - LastHits == other.LastHits && - Denies == other.Denies && - KillStreak == other.KillStreak && - CommandsIssued == other.CommandsIssued && + Activity.Equals(other.Activity) && + Kills.Equals(other.Kills) && + Deaths.Equals(other.Deaths) && + Assists.Equals(other.Assists) && + LastHits.Equals(other.LastHits) && + Denies.Equals(other.Denies) && + KillStreak.Equals(other.KillStreak) && + CommandsIssued.Equals(other.CommandsIssued) && KillList.Equals(other.KillList) && - Team == other.Team && - PlayerSlot == other.PlayerSlot && + Team.Equals(other.Team) && + PlayerSlot.Equals(other.PlayerSlot) && PlayerTeamSlot.Equals(other.PlayerTeamSlot) && - Gold == other.Gold && - GoldReliable == other.GoldReliable && - GoldUnreliable == other.GoldUnreliable && - GoldFromHeroKills == other.GoldFromHeroKills && - GoldFromCreepKills == other.GoldFromCreepKills && - GoldFromIncome == other.GoldFromIncome && - GoldFromShared == other.GoldFromShared && - GoldPerMinute == other.GoldPerMinute && - ExperiencePerMinute == other.ExperiencePerMinute && - OnstageSeat == other.OnstageSeat && - NetWorth == other.NetWorth && - HeroDamage == other.HeroDamage && - HeroHealing == other.HeroHealing && - TowerDamage == other.TowerDamage && - SupportGoldSpent == other.SupportGoldSpent && - ConsumableGoldSpent == other.ConsumableGoldSpent && - ItemGoldSpent == other.ItemGoldSpent && - GoldLostToDeath == other.GoldLostToDeath && - GoldSpentOnBuybacks == other.GoldSpentOnBuybacks && - WardsPurchased == other.WardsPurchased && - WardsPlaced == other.WardsPlaced && - WardsDestroyed == other.WardsDestroyed && - RunesActivated == other.RunesActivated && - CampsStacked == other.CampsStacked; + Gold.Equals(other.Gold) && + GoldReliable.Equals(other.GoldReliable) && + GoldUnreliable.Equals(other.GoldUnreliable) && + GoldFromHeroKills.Equals(other.GoldFromHeroKills) && + GoldFromCreepKills.Equals(other.GoldFromCreepKills) && + GoldFromIncome.Equals(other.GoldFromIncome) && + GoldFromShared.Equals(other.GoldFromShared) && + GoldPerMinute.Equals(other.GoldPerMinute) && + ExperiencePerMinute.Equals(other.ExperiencePerMinute) && + OnstageSeat.Equals(other.OnstageSeat) && + NetWorth.Equals(other.NetWorth) && + HeroDamage.Equals(other.HeroDamage) && + HeroHealing.Equals(other.HeroHealing) && + TowerDamage.Equals(other.TowerDamage) && + SupportGoldSpent.Equals(other.SupportGoldSpent) && + ConsumableGoldSpent.Equals(other.ConsumableGoldSpent) && + ItemGoldSpent.Equals(other.ItemGoldSpent) && + GoldLostToDeath.Equals(other.GoldLostToDeath) && + GoldSpentOnBuybacks.Equals(other.GoldSpentOnBuybacks) && + WardsPurchased.Equals(other.WardsPurchased) && + WardsPlaced.Equals(other.WardsPlaced) && + WardsDestroyed.Equals(other.WardsDestroyed) && + RunesActivated.Equals(other.RunesActivated) && + CampsStacked.Equals(other.CampsStacked); } /// diff --git a/Dota2GSI/Nodes/Provider.cs b/Dota2GSI/Nodes/Provider.cs index 1a73e12..51901c2 100644 --- a/Dota2GSI/Nodes/Provider.cs +++ b/Dota2GSI/Nodes/Provider.cs @@ -56,8 +56,8 @@ public override bool Equals(object obj) return obj is Provider other && Name.Equals(other.Name) && - AppID == other.AppID && - Version == other.Version && + AppID.Equals(other.AppID) && + Version.Equals(other.Version) && TimeStamp.Equals(other.TimeStamp); } diff --git a/Dota2GSI/Nodes/Roshan.cs b/Dota2GSI/Nodes/Roshan.cs index ced02b7..f54f45c 100644 --- a/Dota2GSI/Nodes/Roshan.cs +++ b/Dota2GSI/Nodes/Roshan.cs @@ -85,13 +85,13 @@ public override bool Equals(object obj) } return obj is Roshan other && - Health == other.Health && - MaxHealth == other.MaxHealth && - IsAlive == other.IsAlive && - SpawnPhase == other.SpawnPhase && - PhaseTimeRemaining == other.PhaseTimeRemaining && + Health.Equals(other.Health) && + MaxHealth.Equals(other.MaxHealth) && + IsAlive.Equals(other.IsAlive) && + SpawnPhase.Equals(other.SpawnPhase) && + PhaseTimeRemaining.Equals(other.PhaseTimeRemaining) && Location.Equals(other.Location) && - Rotation == other.Rotation && + Rotation.Equals(other.Rotation) && Drops.Equals(other.Drops); } diff --git a/Dota2GSI/Nodes/WearablesProvider/WearableItem.cs b/Dota2GSI/Nodes/WearablesProvider/WearableItem.cs index 1c25deb..e3361b1 100644 --- a/Dota2GSI/Nodes/WearablesProvider/WearableItem.cs +++ b/Dota2GSI/Nodes/WearablesProvider/WearableItem.cs @@ -40,8 +40,8 @@ public override bool Equals(object obj) } return obj is WearableItem other && - ID == other.ID && - Style == other.Style; + ID.Equals(other.ID) && + Style.Equals(other.Style); } /// diff --git a/Dota2GSI/StateHandlers/BuildingsHandler.cs b/Dota2GSI/StateHandlers/BuildingsHandler.cs index 0985bf3..383d6e4 100644 --- a/Dota2GSI/StateHandlers/BuildingsHandler.cs +++ b/Dota2GSI/StateHandlers/BuildingsHandler.cs @@ -1,4 +1,8 @@ using Dota2GSI.EventMessages; +using Dota2GSI.Nodes; +using Dota2GSI.Nodes.BuildingsProvider; +using System; +using System.Collections.Generic; namespace Dota2GSI { @@ -8,12 +12,20 @@ public BuildingsHandler(ref EventDispatcher EventDispatcher) : ba { dispatcher.Subscribe(OnBuildingsUpdated); dispatcher.Subscribe(OnBuildingsLayoutUpdated); + dispatcher.Subscribe(OnTowerUpdated); + dispatcher.Subscribe(OnRacksUpdated); + dispatcher.Subscribe(OnAncientUpdated); + dispatcher.Subscribe(OnTeamBuildingUpdated); } ~BuildingsHandler() { dispatcher.Unsubscribe(OnBuildingsUpdated); dispatcher.Unsubscribe(OnBuildingsLayoutUpdated); + dispatcher.Unsubscribe(OnTowerUpdated); + dispatcher.Unsubscribe(OnRacksUpdated); + dispatcher.Unsubscribe(OnAncientUpdated); + dispatcher.Unsubscribe(OnTeamBuildingUpdated); } private void OnBuildingsUpdated(DotaGameEvent e) @@ -48,227 +60,153 @@ private void OnBuildingsLayoutUpdated(DotaGameEvent e) return; } - if (!evt.New.TopTowers.Equals(evt.Previous.TopTowers)) + Dictionary, NodeMap>> towers = new Dictionary, NodeMap>>() { - BuildingLocation location = BuildingLocation.TopLane; + { BuildingLocation.TopLane, new Tuple, NodeMap>(evt.New.TopTowers, evt.Previous.TopTowers) }, + { BuildingLocation.MiddleLane, new Tuple, NodeMap>(evt.New.MiddleTowers, evt.Previous.MiddleTowers) }, + { BuildingLocation.BottomLane, new Tuple, NodeMap>(evt.New.BottomTowers, evt.Previous.BottomTowers) } + }; - foreach (var building_kvp in evt.New.TopTowers) + foreach (var tower_kvp in towers) + { + if (!tower_kvp.Value.Item1.Equals(tower_kvp.Value.Item2)) { - if (!evt.Previous.TopTowers.ContainsKey(building_kvp.Key)) + foreach (var building_kvp in tower_kvp.Value.Item1) { - // Not much point in having "TowerAdded" event for Dota gameplay. - continue; - } - - var previous_building = evt.Previous.TopTowers[building_kvp.Key]; - - if (!building_kvp.Value.Equals(previous_building)) - { - dispatcher.Broadcast(new TowerUpdated(building_kvp.Value, previous_building, "", evt.Team, location)); - - if (building_kvp.Value.Health == 0) + if (!tower_kvp.Value.Item2.ContainsKey(building_kvp.Key)) { - dispatcher.Broadcast(new TowerDestroyed(building_kvp.Value, previous_building, "", evt.Team, location)); + // Not much point in having "TowerAdded" event for Dota gameplay. + continue; } - } - } - } - - if (!evt.New.MiddleTowers.Equals(evt.Previous.MiddleTowers)) - { - BuildingLocation location = BuildingLocation.MiddleLane; - foreach (var building_kvp in evt.New.MiddleTowers) - { - if (!evt.Previous.MiddleTowers.ContainsKey(building_kvp.Key)) - { - // Not much point in having "TowerAdded" event for Dota gameplay. - continue; - } + var previous_building = tower_kvp.Value.Item2[building_kvp.Key]; - var previous_building = evt.Previous.MiddleTowers[building_kvp.Key]; - - if (!building_kvp.Value.Equals(previous_building)) - { - dispatcher.Broadcast(new TowerUpdated(building_kvp.Value, previous_building, "", evt.Team, location)); - - if (building_kvp.Value.Health == 0) + if (!building_kvp.Value.Equals(previous_building)) { - dispatcher.Broadcast(new TowerDestroyed(building_kvp.Value, previous_building, "", evt.Team, location)); + dispatcher.Broadcast(new TowerUpdated(building_kvp.Value, previous_building, "", evt.Team, tower_kvp.Key)); } } } } - if (!evt.New.BottomTowers.Equals(evt.Previous.BottomTowers)) + Dictionary, NodeMap>> racks = new Dictionary, NodeMap>>() { - BuildingLocation location = BuildingLocation.BottomLane; + { BuildingLocation.TopLane, new Tuple, NodeMap>(evt.New.TopRacks, evt.Previous.TopRacks) }, + { BuildingLocation.MiddleLane, new Tuple, NodeMap>(evt.New.MiddleRacks, evt.Previous.MiddleRacks) }, + { BuildingLocation.BottomLane, new Tuple, NodeMap>(evt.New.BottomRacks, evt.Previous.BottomRacks) } + }; - foreach (var building_kvp in evt.New.BottomTowers) + foreach (var rack_kvp in racks) + { + if (!rack_kvp.Value.Item1.Equals(rack_kvp.Value.Item2)) { - if (!evt.Previous.BottomTowers.ContainsKey(building_kvp.Key)) - { - // Not much point in having "TowerAdded" event for Dota gameplay. - continue; - } - - var previous_building = evt.Previous.BottomTowers[building_kvp.Key]; - - if (!building_kvp.Value.Equals(previous_building)) + foreach (var building_kvp in rack_kvp.Value.Item1) { - dispatcher.Broadcast(new TowerUpdated(building_kvp.Value, previous_building, "", evt.Team, location)); - - if (building_kvp.Value.Health == 0) + if (!rack_kvp.Value.Item2.ContainsKey(building_kvp.Key)) { - dispatcher.Broadcast(new TowerDestroyed(building_kvp.Value, previous_building, "", evt.Team, location)); + // Not much point in having "RacksAdded" event for Dota gameplay. + continue; } - } - } - } - - if (!evt.New.BottomTowers.Equals(evt.Previous.BottomTowers)) - { - BuildingLocation location = BuildingLocation.BottomLane; - foreach (var building_kvp in evt.New.BottomTowers) - { - if (!evt.Previous.BottomTowers.ContainsKey(building_kvp.Key)) - { - // Not much point in having "TowerAdded" event for Dota gameplay. - continue; - } - - var previous_building = evt.Previous.BottomTowers[building_kvp.Key]; - - if (!building_kvp.Value.Equals(previous_building)) - { - dispatcher.Broadcast(new TowerUpdated(building_kvp.Value, previous_building, "", evt.Team, location)); + var previous_building = rack_kvp.Value.Item2[building_kvp.Key]; - if (building_kvp.Value.Health == 0) + if (!building_kvp.Value.Equals(previous_building)) { - dispatcher.Broadcast(new TowerDestroyed(building_kvp.Value, previous_building, "", evt.Team, location)); + dispatcher.Broadcast(new RacksUpdated(building_kvp.Value, previous_building, building_kvp.Key, "", evt.Team, rack_kvp.Key)); } } } } - if (!evt.New.TopRacks.Equals(evt.Previous.TopRacks)) + if (!evt.New.Ancient.Equals(evt.Previous.Ancient)) { - BuildingLocation location = BuildingLocation.TopLane; + BuildingLocation location = BuildingLocation.Base; - foreach (var building_kvp in evt.New.TopRacks) + if (!evt.New.Ancient.Equals(evt.Previous.Ancient)) { - if (!evt.Previous.TopRacks.ContainsKey(building_kvp.Key)) - { - // Not much point in having "RacksAdded" event for Dota gameplay. - continue; - } - - var previous_building = evt.Previous.TopRacks[building_kvp.Key]; - - if (!building_kvp.Value.Equals(previous_building)) - { - dispatcher.Broadcast(new RacksUpdated(building_kvp.Value, previous_building, building_kvp.Key, "", evt.Team, location)); - - if (building_kvp.Value.Health == 0) - { - dispatcher.Broadcast(new RacksDestroyed(building_kvp.Value, previous_building, building_kvp.Key, "", evt.Team, location)); - } - } + dispatcher.Broadcast(new AncientUpdated(evt.New.Ancient, evt.Previous.Ancient, "", evt.Team, location)); } } - if (!evt.New.MiddleRacks.Equals(evt.Previous.MiddleRacks)) + if (!evt.New.OtherBuildings.Equals(evt.Previous.OtherBuildings)) { - BuildingLocation location = BuildingLocation.MiddleLane; + BuildingLocation location = BuildingLocation.Undefined; - foreach (var building_kvp in evt.New.MiddleRacks) + foreach (var building_kvp in evt.New.OtherBuildings) { - if (!evt.Previous.MiddleRacks.ContainsKey(building_kvp.Key)) + if (!evt.Previous.OtherBuildings.ContainsKey(building_kvp.Key)) { - // Not much point in having "RacksAdded" event for Dota gameplay. + // Not much point in having "OtherBuildingsAdded" event for Dota gameplay. continue; } - var previous_building = evt.Previous.MiddleRacks[building_kvp.Key]; + var previous_building = evt.Previous.OtherBuildings[building_kvp.Key]; if (!building_kvp.Value.Equals(previous_building)) { - dispatcher.Broadcast(new RacksUpdated(building_kvp.Value, previous_building, building_kvp.Key, "", evt.Team, location)); - - if (building_kvp.Value.Health == 0) - { - dispatcher.Broadcast(new RacksDestroyed(building_kvp.Value, previous_building, building_kvp.Key, "", evt.Team, location)); - } + dispatcher.Broadcast(new TeamBuildingUpdated(building_kvp.Value, previous_building, building_kvp.Key, evt.Team, location)); } } } + } - if (!evt.New.BottomRacks.Equals(evt.Previous.BottomRacks)) - { - BuildingLocation location = BuildingLocation.BottomLane; + private void OnTowerUpdated(DotaGameEvent e) + { + TowerUpdated evt = (e as TowerUpdated); - foreach (var building_kvp in evt.New.BottomRacks) - { - if (!evt.Previous.BottomRacks.ContainsKey(building_kvp.Key)) - { - // Not much point in having "RacksAdded" event for Dota gameplay. - continue; - } + if (evt == null) + { + return; + } - var previous_building = evt.Previous.BottomRacks[building_kvp.Key]; + if (evt.New.Health == 0 && evt.Previous.Health > 0) + { + dispatcher.Broadcast(new TowerDestroyed(evt.New, evt.Previous, evt.EntityID, evt.Team, evt.Location)); + } + } - if (!building_kvp.Value.Equals(previous_building)) - { - dispatcher.Broadcast(new RacksUpdated(building_kvp.Value, previous_building, building_kvp.Key, "", evt.Team, location)); + private void OnRacksUpdated(DotaGameEvent e) + { + RacksUpdated evt = (e as RacksUpdated); - if (building_kvp.Value.Health == 0) - { - dispatcher.Broadcast(new RacksDestroyed(building_kvp.Value, previous_building, building_kvp.Key, "", evt.Team, location)); - } - } - } + if (evt == null) + { + return; } - if (!evt.New.Ancient.Equals(evt.Previous.Ancient)) + if (evt.New.Health == 0 && evt.Previous.Health > 0) { - BuildingLocation location = BuildingLocation.Base; + dispatcher.Broadcast(new RacksDestroyed(evt.New, evt.Previous, evt.RacksType, evt.EntityID, evt.Team, evt.Location)); + } + } - if (!evt.New.Ancient.Equals(evt.Previous.Ancient)) - { - dispatcher.Broadcast(new AncientUpdated(evt.New.Ancient, evt.Previous.Ancient, "", evt.Team, location)); + private void OnAncientUpdated(DotaGameEvent e) + { + AncientUpdated evt = (e as AncientUpdated); - if (evt.New.Ancient.Health == 0) - { - dispatcher.Broadcast(new AncientDestroyed(evt.New.Ancient, evt.Previous.Ancient, "", evt.Team, location)); - } - } + if (evt == null) + { + return; } - if (!evt.New.OtherBuildings.Equals(evt.Previous.OtherBuildings)) + if (evt.New.Health == 0 && evt.Previous.Health > 0) { - BuildingLocation location = BuildingLocation.Undefined; - - foreach (var building_kvp in evt.New.OtherBuildings) - { - if (!evt.Previous.OtherBuildings.ContainsKey(building_kvp.Key)) - { - // Not much point in having "OtherBuildingsAdded" event for Dota gameplay. - continue; - } + dispatcher.Broadcast(new AncientDestroyed(evt.New, evt.Previous, evt.EntityID, evt.Team, evt.Location)); + } + } - var previous_building = evt.Previous.OtherBuildings[building_kvp.Key]; + private void OnTeamBuildingUpdated(DotaGameEvent e) + { + TeamBuildingUpdated evt = (e as TeamBuildingUpdated); - if (!building_kvp.Value.Equals(previous_building)) - { - dispatcher.Broadcast(new TeamBuildingUpdated(building_kvp.Value, previous_building, building_kvp.Key, evt.Team, location)); + if (evt == null) + { + return; + } - if (building_kvp.Value.Health == 0) - { - dispatcher.Broadcast(new TeamBuildingDestroyed(building_kvp.Value, previous_building, building_kvp.Key, evt.Team, location)); - } - } - } + if (evt.New.Health == 0 && evt.Previous.Health > 0) + { + dispatcher.Broadcast(new TeamBuildingDestroyed(evt.New, evt.Previous, evt.EntityID, evt.Team, evt.Location)); } } } diff --git a/Dota2GSI/StateHandlers/CouriersHandler.cs b/Dota2GSI/StateHandlers/CouriersHandler.cs index 98a5782..903f02e 100644 --- a/Dota2GSI/StateHandlers/CouriersHandler.cs +++ b/Dota2GSI/StateHandlers/CouriersHandler.cs @@ -87,7 +87,7 @@ private void OnCourierUpdated(DotaGameEvent e) { if (!evt.New.InventoryContains(item.Value.Name)) { - // Player lost an inventory item. + // Courier lost an inventory item. dispatcher.Broadcast(new CourierItemRemoved(item.Value, evt.New, evt.Player)); } } diff --git a/Dota2GSI/StateHandlers/ItemsHandler.cs b/Dota2GSI/StateHandlers/ItemsHandler.cs index 4c87693..b5bcf88 100644 --- a/Dota2GSI/StateHandlers/ItemsHandler.cs +++ b/Dota2GSI/StateHandlers/ItemsHandler.cs @@ -117,7 +117,7 @@ private void OnItemDetailsChanged(DotaGameEvent e) } } - foreach (var item in evt.Previous.Inventory) + foreach (var item in evt.Previous.Stash) { if (!evt.New.StashContains(item.Name)) { diff --git a/Dota2GSI/StateHandlers/MapHandler.cs b/Dota2GSI/StateHandlers/MapHandler.cs index b9aac11..b458291 100644 --- a/Dota2GSI/StateHandlers/MapHandler.cs +++ b/Dota2GSI/StateHandlers/MapHandler.cs @@ -61,13 +61,14 @@ private void OnMapUpdated(DotaGameEvent e) { dispatcher.Broadcast(new TeamVictory(evt.New.WinningTeam)); - if (evt.New.WinningTeam == Nodes.PlayerTeam.Radiant) + switch (evt.New.WinningTeam) { - dispatcher.Broadcast(new TeamDefeat(Nodes.PlayerTeam.Dire)); - } - else if (evt.New.WinningTeam == Nodes.PlayerTeam.Dire) - { - dispatcher.Broadcast(new TeamDefeat(Nodes.PlayerTeam.Radiant)); + case Nodes.PlayerTeam.Radiant: + dispatcher.Broadcast(new TeamDefeat(Nodes.PlayerTeam.Dire)); + break; + case Nodes.PlayerTeam.Dire: + dispatcher.Broadcast(new TeamDefeat(Nodes.PlayerTeam.Radiant)); + break; } } diff --git a/Dota2GSI/StateHandlers/MinimapHandler.cs b/Dota2GSI/StateHandlers/MinimapHandler.cs index 799a868..6b13a3d 100644 --- a/Dota2GSI/StateHandlers/MinimapHandler.cs +++ b/Dota2GSI/StateHandlers/MinimapHandler.cs @@ -27,6 +27,8 @@ private void OnMinimapUpdated(DotaGameEvent e) { if (!evt.Previous.Elements.ContainsKey(element_kvp.Key)) { + // The element did not exist before. + dispatcher.Broadcast(new MinimapElementAdded(element_kvp.Value, element_kvp.Key.ToString())); continue; } @@ -42,6 +44,15 @@ private void OnMinimapUpdated(DotaGameEvent e) } } } + + foreach (var element_kvp in evt.Previous.Elements) + { + if (!evt.New.Elements.ContainsKey(element_kvp.Key)) + { + // The element does not exist anymore. + dispatcher.Broadcast(new MinimapElementRemoved(element_kvp.Value, element_kvp.Key.ToString())); + } + } } } } From d57242173c24491bdb5e64f6387a171f88f169f9 Mon Sep 17 00:00:00 2001 From: Anton Pupkov Date: Thu, 18 Jan 2024 15:45:57 -0800 Subject: [PATCH 20/24] Minor corrections --- Dota2GSI/Dota2EventsInterface.cs | 2 +- Dota2GSI/GameState.cs | 1 - Dota2GSI/Nodes/ItemsProvider/ItemDetails.cs | 22 ++++++--------------- 3 files changed, 7 insertions(+), 18 deletions(-) diff --git a/Dota2GSI/Dota2EventsInterface.cs b/Dota2GSI/Dota2EventsInterface.cs index e62a308..bb4879b 100644 --- a/Dota2GSI/Dota2EventsInterface.cs +++ b/Dota2GSI/Dota2EventsInterface.cs @@ -397,7 +397,7 @@ public class Dota2EventsInterface : EventsInterface #endregion - #region ProviderEvents + #region PlayerEvents public delegate void PlayerUpdatedHandler(PlayerUpdated game_event); diff --git a/Dota2GSI/GameState.cs b/Dota2GSI/GameState.cs index c05c021..b801566 100644 --- a/Dota2GSI/GameState.cs +++ b/Dota2GSI/GameState.cs @@ -224,7 +224,6 @@ public bool IsLocalPlayer private FullTeamDetails _dire_team_details; private FullTeamDetails _neutral_team_details; - /// /// Creates a GameState instance based on the given json data. /// diff --git a/Dota2GSI/Nodes/ItemsProvider/ItemDetails.cs b/Dota2GSI/Nodes/ItemsProvider/ItemDetails.cs index 03993af..04853ab 100644 --- a/Dota2GSI/Nodes/ItemsProvider/ItemDetails.cs +++ b/Dota2GSI/Nodes/ItemsProvider/ItemDetails.cs @@ -112,12 +112,7 @@ public Item GetInventoryItem(string item_name) public bool InventoryContains(string item_name) { var found_index = InventoryIndexOf(item_name); - if (found_index > -1) - { - return true; - } - - return false; + return found_index > -1; } /// @@ -127,9 +122,9 @@ public bool InventoryContains(string item_name) /// The first index at which item is found, -1 if not found. public int InventoryIndexOf(string item_name) { - for (int x = 0; x < this.Inventory.Count; x++) + for (int x = 0; x < Inventory.Count; x++) { - if (this.Inventory[x].Name == item_name) + if (Inventory[x].Name == item_name) { return x; } @@ -179,12 +174,7 @@ public Item GetStashItem(string item_name) public bool StashContains(string item_name) { var found_index = StashIndexOf(item_name); - if (found_index > -1) - { - return true; - } - - return false; + return found_index > -1; } /// @@ -194,9 +184,9 @@ public bool StashContains(string item_name) /// The first index at which item is found, -1 if not found. public int StashIndexOf(string item_name) { - for (int x = 0; x < this.Stash.Count; x++) + for (int x = 0; x < Stash.Count; x++) { - if (this.Stash[x].Name == item_name) + if (Stash[x].Name == item_name) { return x; } From f8a47fad759b5488a34f063a8d1528eae7a0b0b5 Mon Sep 17 00:00:00 2001 From: Anton Pupkov Date: Thu, 18 Jan 2024 15:50:55 -0800 Subject: [PATCH 21/24] Update readme --- README.md | 500 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 356 insertions(+), 144 deletions(-) diff --git a/README.md b/README.md index a5e3dce..5dbe43a 100644 --- a/README.md +++ b/README.md @@ -1,60 +1,271 @@ -# Dota 2 GSI (Game State Integration) -A C# library to interface with the Game State Integration found in Dota 2. +Dota 2 GSI (Game State Integration) +=================================== -## What is Game State Integration -You can read about Game State Integration for Counter-Strike: Global Offensive [here](https://developer.valvesoftware.com/wiki/Counter-Strike:_Global_Offensive_Game_State_Integration). +[![.NET](https://github.com/antonpup/Dota2GSI/actions/workflows/dotnet.yml/badge.svg?branch=master)](https://github.com/antonpup/Dota2GSI/actions/workflows/dotnet.yml) +![GitHub Release](https://img.shields.io/github/v/release/antonpup/Dota2GSI) +[![NuGet Version](https://img.shields.io/nuget/v/Dota2GSI)](https://www.nuget.org/packages/Dota2GSI) + +A C# library to interface with the Game State Integration found in Dota 2. ## About Dota 2 GSI -This library provides easy means of implementing Game State Integration from Dota 2 into C# applications. Library listens for HTTP POST requests made by the game on a specific address and port. Upon receiving a request, the game state is parsed and can be used. -JSON parsing is done though help of Newtonsoft's [JSON.Net Framework](http://www.newtonsoft.com/json). +This library provides an easy way to implement Game State Integration from Dota 2 into C# applications through exposing a number of events. + +Underneath the hood, once the library is started, it continuously listens for HTTP POST requests made by the game on a specific address and port. When a request is received, the JSON data is parsed into [GameState object](#game-state-structure) and is offered to your C# application through `NewGameState` event. The library also subscribes to `NewGameState` to determine more granular changes to raise more specific events _(such as `TimeOfDayChanged`, `InventoryItemAdded`, or `TowerDestroyed` to name a few)_. A full list of exposed Game Events can be found in the [Implemented Game Events](#implemented-game-events) section. + +## About Game State Integration -After starting the `GameStateListener` instance, it will continuously listen for incoming HTTP requests. Upon a received request, the contents will be parsed into a `GameState` object. +Game State Integration is Valve's implementation for exposing current game state _(such as player health, mana, ammo, etc.)_ and game events without the need to read game memory or risking anti-cheat detection. The information exposed by GSI is limited to what Valve has determined to expose. For example, the game can expose information about all players in the game while spectating a match, but will only expose local player's infomration when playing a game. While the information is limited, there is enough information to create a live game analysis tool, create custom RGB ligthing effects, or create live streaming plugin to show additional game information. For example, GSI can be seen used during competitive tournament live streams to show currently spectated player's information and in-game statistics. + +You can read about Game State Integration for Counter-Strike: Global Offensive [here](https://developer.valvesoftware.com/wiki/Counter-Strike:_Global_Offensive_Game_State_Integration). ## Installation + Install from [nuget](https://www.nuget.org/packages/Dota2GSI). -## Manual installation: -1. Get the [latest binaries](https://github.com/antonpup/Dota2GSI/releases/latest) -2. Get the [JSON Framework .dll by Newtonsoft](https://github.com/JamesNK/Newtonsoft.Json/releases) -3. Extract Newtonsoft.Json.dll from `Bin\Net80\Newtonsoft.Json.dll` -4. Add a reference to both Dota2GSI.dll and Newtonsoft.Json.dll in your project +## Building Dota 2 GSI -## Build Dota 2 GSI 1. Make sure you have Visual Studio installed with `.NET desktop development` workload and `.Net 8.0 Runtime` individual component. 2. Make sure you have CMake 3.26 or later installed from [https://cmake.org/](https://cmake.org/). 3. In the repository root directory run: `cmake -B build/ .` to generate the project solution file. 4. Open the project solution located in `build/Dota2GSI.sln`. -## Usage -1. Create a `GameStateListener` instance by providing a port or passing a specific URI: +## How to use +1. Before `Dota2GSI` can be used, you must create a Game State Integration configuration file where you would specify the URI for the HTTP Requests and select which providers the game should expose to your application. To do this you must create a new configuration file in `/game/dota/cfg/gamestate_integration/gamestate_integration_.cfg` where `` should be the name of your application (it can be anything). Add the following content to your configuration file (make sure you replace `` with your application's name, `` with the port you would like to use for your application, and other values can also be tweaked as you wish): +``` +" Integration Configuration" +{ + "uri" "http://localhost:/" + "timeout" "5.0" + "buffer" "0.1" + "throttle" "0.1" + "heartbeat" "30.0" + "data" + { + "auth" "1" + "provider" "1" + "map" "1" + "player" "1" + "hero" "1" + "abilities" "1" + "items" "1" + "events" "1" + "buildings" "1" + "league" "1" + "draft" "1" + "wearables" "1" + "minimap" "1" + "roshan" "1" + "couriers" "1" + "neutralitems" "1" + } +} +``` + +2. After installing the [Dota2GSI nuget package](https://www.nuget.org/packages/Dota2GSI) in your project, create an instance of `GameStateListener`, providing a custom port or custom URI you defined in the configuration file in the previous step. ```C# GameStateListener gsl = new GameStateListener(3000); //http://localhost:3000/ -GameStateListener gsl = new GameStateListener("http://127.0.0.1:81/"); ``` +or +```C# +GameStateListener gsl = new GameStateListener("http://127.0.0.1:1234/"); +``` +> **Please note**: If your application needs to listen to a URI other than `http://localhost:*/` (for example `http://192.168.0.2:100/`), you will need to run your application with administrator privileges. -**Please note**: If your application needs to listen to a URI other than `http://localhost:*/` (for example `http://192.168.2.2:100/`), you need to ensure that it is run with administrator privileges. -In this case, `http://127.0.0.1:*/` is **not** equivalent to `http://localhost:*/`. - -2. Create a handler: - +3. Create handlers and subscribe for events your application will be using. (A full list of exposed Game Events can be found in the [Implemented Game Events](#implemented-game-events) section.) +If your application just needs `GameState` information, this is done by subscribing to `NewGameState` event and creating a handler for it: ```C# +... +gsl.NewGameState += OnNewGameState; +... + void OnNewGameState(GameState gs) { - //do stuff + // Read information from the game state. } ``` +If you would like to utilize `Game Events` in your application, this is done by subscribing to an event from the [Implemented Game Events](#implemented-game-events) list and creating a handler for it: +```C# +... +gsl.GameEvent += OnGameEvent; // Will fire on every GameEvent +gsl.TimeOfDayChanged += OnTimeOfDayChanged; // Will only fire on TimeOfDayChanged events. +gsl.InventoryItemAdded += OnInventoryItemAdded; // Will only fire on InventoryItemAdded events. +... -3. Subscribe to the `NewGameState` event: +void OnGameEvent(DotaGameEvent game_event) +{ + // Read information from the game event. + + if (game_event is TimeOfDayChanged tod_changed) + { + Console.WriteLine($"Is daytime: {tod_changed.IsDaytime} Is Nightstalker night: {tod_changed.IsNightstalkerNight}"); + } +} + +void OnTimeOfDayChanged(TimeOfDayChanged game_event) +{ + Console.WriteLine($"Is daytime: {game_event.IsDaytime} Is Nightstalker night: {game_event.IsNightstalkerNight}"); +} +void OnInventoryItemAdded(InventoryItemAdded game_event) +{ + Console.WriteLine($"Player {game_event.Player.Details.Name} gained an item in their inventory: {game_event.Value.Name}"); +} +``` +Both `NewGameState` and `Game Events` can be used alongside one another. The `Game Events` are generated based on the `GameState`, and are there to provide ease of use. + +4. Finally you want to start the `GameStateListener` to begin capturing HTTP POST requests. This is done by calling `Start()` method of `GameStateListener`. The method will return `True` if started successfully, or `False` when failed to start. Often the failure to start is due to insufficient permissions or another application is already using the same port. ```C# -gsl.NewGameState += new NewGameStateHandler(OnNewGameState); +if (!gsl.Start()) +{ + // GameStateListener could not start. +} +// GameStateListener started and is listening for Game State requests. ``` -4. Use `GameStateListener.Start()` to start listening for HTTP POST requests from the game client. This method will return `false` if starting the listener fails (most likely due to insufficient privileges). +## Implemented Game Events + +* `GameEvent` The base game event, will fire for all other listed events. + +### Abilities Events + +* `AbilitiesUpdated` +* `AbilityDetailsChanged` +* `AbilityAdded` +* `AbilityRemoved` +* `AbilityUpdated` + +### Auth Events + +* `AuthUpdated` + +### Buildings Events + +* `BuildingsUpdated` +* `BuildingsLayoutUpdated` +* `BuildingUpdated` +* `TeamBuildingUpdated` +* `TeamBuildingDestroyed` +* `TowerUpdated` +* `TowerDestroyed` +* `RacksUpdated` +* `RacksDestroyed` +* `AncientUpdated` +* `AncientDestroyed` + +### Couriers Events + +* `CouriersUpdated` +* `CourierUpdated` +* `TeamCourierUpdated` +* `CourierItemAdded` +* `CourierItemRemoved` +* `CourierItemUpdated` + +### Draft Events + +* `DraftUpdated` +* `TeamDraftDetailsUpdated` + +### Gameplay Events + +* `EventsUpdated` +* `GameplayEvent` +* `TeamGameplayEvent` +* `PlayerGameplayEvent` + +### Hero Events + +* `HeroUpdated` +* `HeroDetailsChanged` +* `HeroLevelChanged` +* `HeroHealthChanged` +* `HeroDied` +* `HeroRespawned` +* `HeroTookDamage` +* `HeroManaChanged` +* `HeroStateChanged` +* `HeroMuteStateChanged` +* `HeroSelectedChanged` +* `HeroTalentTreeChanged` +* `HeroAttributesLevelChanged` + +### Items Events + +* `ItemsUpdated` +* `ItemDetailsChanged` +* `ItemUpdated` +* `InventoryItemAdded` +* `InventoryItemRemoved` +* `InventoryItemUpdated` +* `StashItemAdded` +* `StashItemRemoved` +* `StashItemUpdated` + +### League Events + +* `LeagueUpdated` + +### Map Events + +* `MapUpdated` +* `TimeOfDayChanged` +* `TeamScoreChanged` +* `GameStateChanged` +* `PauseStateChanged` +* `GamePaused` +* `GameResumed` +* `TeamVictory` +* `TeamDefeat` +* `RoshanStateChanged` + +### Minimap Events + +* `MinimapUpdated` +* `MinimapElementAdded` +* `MinimapElementUpdated` +* `MinimapElementRemoved` +* `TeamMinimapElementUpdated` + +### NeutralItems Events + +* `NeutralItemsUpdated` +* `TeamNeutralItemsUpdated` + +### Player Events + +* `PlayerUpdated` +* `PlayerDetailsChanged` +* `PlayerKillsChanged` +* `PlayerDeathsChanged` +* `PlayerAssistsChanged` +* `PlayerLastHitsChanged` +* `PlayerDeniesChanged` +* `PlayerKillStreakChanged` +* `PlayerGoldChanged` +* `PlayerWardsPurchasedChanged` +* `PlayerWardsPlacedChanged` +* `PlayerWardsDestroyedChanged` +* `PlayerRunesActivatedChanged` +* `PlayerCampsStackedChanged` + +### Provider Events + +* `ProviderUpdated` + +### Roshan Events + +* `RoshanUpdated` + +### Wearables Events + +* `RoshanUpdated` +* `WearablesUpdated` +* `PlayerWearablesUpdated` + +## Game State Structure -## Layout ``` GameState +-- Auth @@ -77,11 +288,11 @@ GameState | +-- IsPaused | +-- Winningteam | +-- CustomGameName +| +-- WardPurchaseCooldown | +-- RadiantWardPurchaseCooldown | +-- DireWardPurchaseCooldown | +-- RoshanState | +-- RoshanStateEndTime -| +-- WardPurchaseCooldown +-- Player | +-- LocalPlayer | | +-- SteamID @@ -96,6 +307,9 @@ GameState | | +-- KillStreak | | +-- CommandsIssued | | +-- KillList +| | | \ +| | | (Map of kill id to player id) +| | | ... | | +-- Team | | +-- PlayerSlot | | +-- PlayerTeamSlot @@ -113,17 +327,19 @@ GameState | | +-- HeroDamage | | +-- HeroHealing | | +-- TowerDamage -| | +-- WardsPurchased -| | +-- WardsPlaced -| | +-- WardsDestroyed -| | +-- RunesActivated -| | +-- CampsStacked | | +-- SupportGoldSpent | | +-- ConsumableGoldSpent | | +-- ItemGoldSpent | | +-- GoldLostToDeath | | +-- GoldSpentOnBuybacks +| | +-- WardsPurchased +| | +-- WardsPlaced +| | +-- WardsDestroyed +| | +-- RunesActivated +| | +-- CampsStacked | +-- Teams +| | \ +| | (Multi-map of team to player id to Player Details) | | ... | +-- GetForTeam( team ) | +-- GetForPlayer( player_id ) @@ -144,21 +360,24 @@ GameState | | +-- Mana | | +-- MaxMana | | +-- ManaPercent +| | +-- HeroState | | +-- IsSilenced | | +-- IsStunned | | +-- IsDisarmed | | +-- IsMagicImmune | | +-- IsHexed -| | +-- IsMuted | | +-- IsBreak -| | +-- HasAghanimsScepterUpgrade -| | +-- HasAghanimsShardUpgrade | | +-- IsSmoked | | +-- HasDebuff +| | +-- IsMuted +| | +-- HasAghanimsScepterUpgrade +| | +-- HasAghanimsShardUpgrade | | +-- SelectedUnit | | +-- TalentTree[] | | +-- AttributesLevel | +-- Teams +| | \ +| | (Multi-map of team to player id to Hero Details) | | ... | +-- GetForTeam( team ) | +-- GetForPlayer( player_id ) @@ -178,17 +397,35 @@ GameState | | | +-- MaxCharges | | | +-- ChargeCooldown | +-- Teams +| | \ +| | (Multi-map of team to player id to Ability Details) | | ... | +-- GetForTeam( team ) | +-- GetForPlayer( player_id ) +-- Items | +-- LocalPlayer -| | +-- Inventory -| | +-- Stash +| | +-- Inventory[] +| | | \ +| | | +-- Name +| | | +-- Purchaser +| | | +-- ItemLevel +| | | +-- ContainsRune +| | | +-- CanCast +| | | +-- Cooldown +| | | +-- IsPassive +| | | +-- ItemCharges +| | | +-- AbilityCharges +| | | +-- MaxCharges +| | | +-- ChargeCooldown +| | | +-- Charges +| | +-- Stash[] +| | | ... | | +-- CountInventory | | +-- CountStash | | +-- Teleport +| | | ... | | +-- Neutral +| | | ... | | +-- GetInventoryAt( index ) | | +-- GetInventoryItem( item_name ) | | +-- InventoryContains( item_name ) @@ -198,6 +435,8 @@ GameState | | +-- StashContains( item_name ) | | +-- StashIndexOf( item_name ) | +-- Teams +| | \ +| | (Multi-map of team to player id to Item Details) | | ... | +-- GetForTeam( team ) | +-- GetForPlayer( player_id ) @@ -218,21 +457,52 @@ GameState +-- Buildings | +-- RadiantBuildings | | +-- TopTowers +| | | \ +| | | (Map of tower id to Building) +| | | +-- Health +| | | +-- MaxHealth | | +-- MiddleTowers +| | | \ +| | | (Map of tower id to Building) +| | | ... | | +-- BottomTowers +| | | \ +| | | (Map of tower id to Building) +| | | ... | | +-- TopRacks +| | | \ +| | | (Map of Racks Type to Building) +| | | ... | | +-- MiddleRacks +| | | \ +| | | (Map of Racks Type to Building) +| | | ... | | +-- BottomRacks +| | | \ +| | | (Map of Racks Type to Building) +| | | ... | | +-- Ancient +| | | ... | | +-- OtherBuildings +| | | \ +| | | (Map of building id to Building) +| | | ... | +-- DireBuildings | | ... | +-- AllBuildings +| | \ +| | (Map of team to Building Layout) | | ... | +-- GetForTeam( team ) +-- League | +-- SeriesType | +-- SelectionPriority +| | +-- Rules +| | +-- PreviousPriorityTeamID +| | +-- CurrentPriorityTeamID +| | +-- PriorityTeamChoice +| | +-- NonPriorityTeamChoice +| | +-- UsedCoinToss | +-- LeagueID | +-- MatchID | +-- Name @@ -262,7 +532,7 @@ GameState | +-- StartTime | +-- FirstTeamID | +-- SecondTeamID -| +-- Stream[] +| +-- Streams[] | | \ | | +-- StreamID | | +-- Language @@ -277,21 +547,33 @@ GameState | +-- RadiantBonusTime | +-- DireBonusTime | +-- Teams +| | | \ +| | | (Map of team to Draft Details) | | +-- IsHomeTeam | | +-- PickIDs +| | | \ +| | | (Map of slot number to picked hero ID) | | +-- PickHeroIDs +| | | \ +| | | (Map of slot number to picked hero name) | +-- GetForTeam( team ) +-- Wearables | +-- LocalPlayer | | +-- Wearables +| | | \ +| | | (Map of slot number to Wearable Item) | | | +-- ID | | | +-- Style | +-- Teams +| | \ +| | (Multi-map of team to player id to Item Wearable Item) | | ... | +-- GetForTeam( team ) | +-- GetForPlayer( player_id ) +-- Minimap | +-- Elements +| | | \ +| | | (Map of element ID to Minimap Element) | | +-- Location | | +-- RemainingTime | | +-- EventDuration @@ -302,19 +584,23 @@ GameState | | +-- UnitName | | +-- VisionRange | +-- GetForTeam( team ) -| +-- GetForPlayer( player_id ) +| +-- GetByUnitName( unit_name ) +-- Roshan -| +-- Location | +-- Health | +-- MaxHealth | +-- IsAlive | +-- SpawnPhase | +-- PhaseTimeRemaining +| +-- Location | +-- Rotation | +-- Drops | | +-- Items +| | | \ +| | | (Map of item index to item name) +-- Couriers | +-- CouriersMap +| | \ +| | (Map of courier ID to Courier) | | +-- Health | | +-- MaxHealth | | +-- IsAlive @@ -326,17 +612,29 @@ GameState | | +-- IsShielded | | +-- IsBoosted | | +-- Items +| | | \ +| | | (Map of item index to Courier Item) | | | +-- OwnerID | | | +-- Name +| | +-- GetItemAt( index ) +| | +-- GetInventoryItem( item_name ) +| | +-- InventoryContains( item_name ) +| | +-- InventoryIndexOf( item_name ) | +-- GetForPlayer( player_id ) +-- NeutralItems | +-- TierInfos +| | | \ +| | | (Map of tier index to Neutral Tier Info) | | +-- Tier | | +-- MaxCount | | +-- DropAfterTime | +-- TeamItems +| | | \ +| | | (Map of team to Team Neutral Items) | | +-- ItemsFound | | +-- TeamItems +| | | \ +| | | (Map of item index to Neutral Item) | | | +-- Name | | | +-- Tier | | | +-- Charges @@ -345,6 +643,8 @@ GameState | +-- GetForTeam( team ) +-- Previously (Previous information from Game State) +-- LocalPlayer +| +-- PlayerID +| +-- IsLocalPlayer | +-- Details | +-- Hero | +-- Abilities @@ -369,119 +669,31 @@ GameState +-- IsLocalPlayer ``` -### Item, and Hero names -Item and hero names are presented in their "internal name" format. A full list of item names can be found [here](http://dota2.gamepedia.com/Cheats#Item_names) and a full list of heroes can be located [here](http://dota2.gamepedia.com/Cheats#Hero_names). - -##### Examples: -```C# -int Health = gs.Hero.LocalPlayer.Health; // 560 -int MaxHealth = gs.Hero.LocalPlayer.MaxHealth; // 560 -string HeroName = gs.Hero.LocalPlayer.Name; //npc_dota_hero_omniknight -int Level = gs.Hero.LocalPlayer.Level; //1 - -Console.WriteLine("You are playing as " + HeroName + " with " + Health + "/" + MaxHealth + " health and level " + Level); -//You are playing as npc_dota_hero_omniknight with 560/560 health and level 1 - -``` - ## Null value handling -In case the JSON did not contain the requested information, these values will be returned: - -Type |Default value ---------|------------- -bool | false -int | -1 -long | -1 -float | -1 -string | String.Empty +In the event that the game state is missing information, a default value will be returned: -All Enums have a value `enum.Undefined` that serves the same purpose. +| Type | Default value | +|:---------|:---------------| +| `bool` | `False` | +| `int` | `-1` | +| `long` | `-1` | +| `float` | `-1` | +| `string` | `String.Empty` | +| `enum` | `Undefined` | ## Example program -A user, [judge2020](https://github.com/judge2020), has created an example program to demonstrate Dota2GSI functionalities. It can be found in the "Dota2GSI Example program" folder. - -## Example implementation -Prints "You bought an item" when you buy an item, and "It is night time" when it is night time. - -```C# -using Dota2GSI; -using System; -namespace DOTA2GSI_sample -{ - static class Program - { - GameStateListener gsl; - - static void Main(string[] args) - { - gsl = new GameStateListener(4000); - gsl.NewGameState += new NewGameStateHandler(OnNewGameState); - - if (!gsl.Start()) - { - System.Windows.MessageBox.Show("GameStateListener could not start. Try running this program as Administrator.\r\nExiting."); - Environment.Exit(0); - } - Console.WriteLine("Listening for game integration calls..."); - } - - static void OnNewGameState(GameState gs) - { - if(gs.Map.GameState == DOTA_GameState.DOTA_GAMERULES_STATE_GAME_IN_PROGRESS) - { - if(gs.Previously.Items.LocalPlayer.CountInventory > gs.Items.LocalPlayer.CountInventory) - { - Console.WriteLine("You bought an item"); - } - - if(!gs.Map.IsDaytime || gs.Map.IsNightstalkerNight) - { - Console.WriteLine("It is night time"); - } - } - } - } -} -``` +An example program for `Dota2GSI` can be found in the `Dota2GSI Example program` directory in the root of the repository. It was initially created by [judge2020](https://github.com/judge2020). -You will also need to create a custom `gamestate_integration_*.cfg` in `game/dota/cfg/gamestate_integration/`, for example: -`gamestate_integration_test.cfg`: -``` -"Dota 2 Integration Configuration" -{ - "uri" "http://localhost:4000/" - "timeout" "5.0" - "buffer" "0.1" - "throttle" "0.1" - "heartbeat" "30.0" - "data" - { - "auth" "1" - "provider" "1" - "map" "1" - "player" "1" - "hero" "1" - "abilities" "1" - "items" "1" - "events" "1" - "buildings" "1" - "league" "1" - "draft" "1" - "wearables" "1" - "minimap" "1" - "roshan" "1" - "couriers" "1" - "neutralitems" "1" - } -} +### Item and hero names -``` +A full list of item names can be found [here](https://dota2.fandom.com/wiki/Cheats#Item_names). -**Please note**: In order to run this test application without explicit administrator privileges, you need to use the URI `http://localhost:` in this configuration file. +A full list of hero names can be found [here](https://dota2.fandom.com/wiki/Cheats#Hero_Names). ## Credits -Special thanks to [rakijah](https://github.com/rakijah) for his CSGO Game State Integration library. -Thanks to [judge2020](https://github.com/judge2020) for providing an example program. +Thank you to [rakijah](https://github.com/rakijah) for his work on the CSGO Game State Integration library. + +Thank you to [judge2020](https://github.com/judge2020) for providing an example program. From 53380e290687a26a5ff39eb9cdc712b4d9def051 Mon Sep 17 00:00:00 2001 From: Anton Pupkov Date: Thu, 18 Jan 2024 16:52:29 -0800 Subject: [PATCH 22/24] Update example program --- .../Dota2GSI Example program/Program.cs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/Dota2GSI Example program/Dota2GSI Example program/Program.cs b/Dota2GSI Example program/Dota2GSI Example program/Program.cs index b8e0945..3b69055 100644 --- a/Dota2GSI Example program/Dota2GSI Example program/Program.cs +++ b/Dota2GSI Example program/Dota2GSI Example program/Program.cs @@ -115,19 +115,6 @@ private static void OnGameEvent(DotaGameEvent game_event) { Console.WriteLine($"Player {ability.Player.Details.Name} updated their ability: " + ability.New); } - else if (game_event is ItemDetailsChanged item_details) - { - Console.WriteLine($"Player {item_details.Player.Details.Name} updated their items: " + item_details.New); - - if (item_details.New.InventoryContains("item_blink")) - { - Console.WriteLine($"Player {item_details.Player.Details.Name} has a blink dagger."); - } - else - { - Console.WriteLine($"Player {item_details.Player.Details.Name} DOES NOT have a blink dagger."); - } - } else if (game_event is TowerUpdated tower_updated) { if (tower_updated.New.Health < tower_updated.Previous.Health) From a523851cce64313ae1e2941d00434f437db0852c Mon Sep 17 00:00:00 2001 From: Anton Pupkov Date: Thu, 18 Jan 2024 16:52:57 -0800 Subject: [PATCH 23/24] Minor corrections --- Dota2GSI/Dota2EventsInterface.cs | 2 +- Dota2GSI/EventsInterface.cs | 2 +- Dota2GSI/StateHandlers/AbilitiesHandler.cs | 12 ++-- Dota2GSI/StateHandlers/CouriersHandler.cs | 5 +- .../StateHandlers/GameplayEventsHandler.cs | 68 +++++++++++++++---- Dota2GSI/StateHandlers/HeroHandler.cs | 11 +-- Dota2GSI/StateHandlers/ItemsHandler.cs | 11 +-- Dota2GSI/StateHandlers/PlayerHandler.cs | 12 ++-- Dota2GSI/StateHandlers/WearablesHandler.cs | 11 +-- 9 files changed, 97 insertions(+), 37 deletions(-) diff --git a/Dota2GSI/Dota2EventsInterface.cs b/Dota2GSI/Dota2EventsInterface.cs index bb4879b..5b042d6 100644 --- a/Dota2GSI/Dota2EventsInterface.cs +++ b/Dota2GSI/Dota2EventsInterface.cs @@ -507,7 +507,7 @@ public Dota2EventsInterface() { } - public override void OnNewGameEvent(DotaGameEvent e) + internal override void OnNewGameEvent(DotaGameEvent e) { base.OnNewGameEvent(e); diff --git a/Dota2GSI/EventsInterface.cs b/Dota2GSI/EventsInterface.cs index a3e7bc7..06e4cd9 100644 --- a/Dota2GSI/EventsInterface.cs +++ b/Dota2GSI/EventsInterface.cs @@ -21,7 +21,7 @@ public EventsInterface() { } - public virtual void OnNewGameEvent(T e) + internal virtual void OnNewGameEvent(T e) { RaiseEvent(GameEvent, e); } diff --git a/Dota2GSI/StateHandlers/AbilitiesHandler.cs b/Dota2GSI/StateHandlers/AbilitiesHandler.cs index 638b20b..56563b8 100644 --- a/Dota2GSI/StateHandlers/AbilitiesHandler.cs +++ b/Dota2GSI/StateHandlers/AbilitiesHandler.cs @@ -45,9 +45,11 @@ private void OnAbilitiesUpdated(DotaGameEvent e) return; } - if (!evt.New.LocalPlayer.Equals(evt.Previous.LocalPlayer)) + var local_player_details = _player_cache.GetValueOrDefault(-1, null); + + if (!evt.New.LocalPlayer.Equals(evt.Previous.LocalPlayer) && local_player_details != null) { - dispatcher.Broadcast(new AbilityDetailsChanged(evt.New.LocalPlayer, evt.Previous.LocalPlayer, _player_cache[-1])); + dispatcher.Broadcast(new AbilityDetailsChanged(evt.New.LocalPlayer, evt.Previous.LocalPlayer, local_player_details)); } foreach (var team_kvp in evt.New.Teams) @@ -57,9 +59,11 @@ private void OnAbilitiesUpdated(DotaGameEvent e) // Get corresponding previous hero details. var previous_ability_details = evt.Previous.GetForPlayer(player_kvp.Key); - if (!player_kvp.Value.Equals(previous_ability_details) && previous_ability_details.IsValid()) + var player_details = _player_cache.GetValueOrDefault(player_kvp.Key, null); + + if (!player_kvp.Value.Equals(previous_ability_details) && previous_ability_details.IsValid() && player_details != null) { - dispatcher.Broadcast(new AbilityDetailsChanged(player_kvp.Value, previous_ability_details, _player_cache[player_kvp.Key])); + dispatcher.Broadcast(new AbilityDetailsChanged(player_kvp.Value, previous_ability_details, player_details)); } } } diff --git a/Dota2GSI/StateHandlers/CouriersHandler.cs b/Dota2GSI/StateHandlers/CouriersHandler.cs index 903f02e..e82a74d 100644 --- a/Dota2GSI/StateHandlers/CouriersHandler.cs +++ b/Dota2GSI/StateHandlers/CouriersHandler.cs @@ -46,9 +46,10 @@ private void OnCouriersUpdated(DotaGameEvent e) foreach (var courier_kvp in evt.New.CouriersMap) { var previous_courier = evt.Previous.GetForPlayer(courier_kvp.Value.OwnerID); - if (!courier_kvp.Value.Equals(previous_courier)) + var player_details = _player_cache.GetValueOrDefault(courier_kvp.Value.OwnerID, null); + + if (!courier_kvp.Value.Equals(previous_courier) && player_details != null) { - var player_details = _player_cache[courier_kvp.Value.OwnerID]; dispatcher.Broadcast(new CourierUpdated(courier_kvp.Value, previous_courier, player_details)); dispatcher.Broadcast(new TeamCourierUpdated(courier_kvp.Value, previous_courier, player_details.Details.Team)); diff --git a/Dota2GSI/StateHandlers/GameplayEventsHandler.cs b/Dota2GSI/StateHandlers/GameplayEventsHandler.cs index 8ff0378..fce9e86 100644 --- a/Dota2GSI/StateHandlers/GameplayEventsHandler.cs +++ b/Dota2GSI/StateHandlers/GameplayEventsHandler.cs @@ -54,29 +54,71 @@ private void OnEventsUpdated(DotaGameEvent e) switch (game_event.EventType) { case EventType.Courier_killed: - dispatcher.Broadcast(new PlayerGameplayEvent(game_event, _player_cache[game_event.KillerPlayerID])); - dispatcher.Broadcast(new TeamGameplayEvent(game_event, game_event.Team)); + { + var killer_player_details = _player_cache.GetValueOrDefault(game_event.KillerPlayerID, null); + if (killer_player_details != null) + { + dispatcher.Broadcast(new PlayerGameplayEvent(game_event, killer_player_details)); + } + dispatcher.Broadcast(new TeamGameplayEvent(game_event, game_event.Team)); + } break; case EventType.Roshan_killed: - dispatcher.Broadcast(new PlayerGameplayEvent(game_event, _player_cache[game_event.KillerPlayerID])); - dispatcher.Broadcast(new TeamGameplayEvent(game_event, game_event.Team)); + { + var killer_player_details = _player_cache.GetValueOrDefault(game_event.KillerPlayerID, null); + if (killer_player_details != null) + { + dispatcher.Broadcast(new PlayerGameplayEvent(game_event, killer_player_details)); + } + dispatcher.Broadcast(new TeamGameplayEvent(game_event, game_event.Team)); + } break; case EventType.Aegis_picked_up: - dispatcher.Broadcast(new PlayerGameplayEvent(game_event, _player_cache[game_event.PlayerID])); - dispatcher.Broadcast(new TeamGameplayEvent(game_event, _player_cache[game_event.PlayerID].Details.Team)); + { + var player_details = _player_cache.GetValueOrDefault(game_event.PlayerID, null); + if (player_details != null) + { + dispatcher.Broadcast(new PlayerGameplayEvent(game_event, player_details)); + dispatcher.Broadcast(new TeamGameplayEvent(game_event, player_details.Details.Team)); + } + } break; case EventType.Aegis_denied: - dispatcher.Broadcast(new PlayerGameplayEvent(game_event, _player_cache[game_event.PlayerID])); - dispatcher.Broadcast(new TeamGameplayEvent(game_event, _player_cache[game_event.PlayerID].Details.Team)); + { + var player_details = _player_cache.GetValueOrDefault(game_event.PlayerID, null); + if (player_details != null) + { + dispatcher.Broadcast(new PlayerGameplayEvent(game_event, player_details)); + dispatcher.Broadcast(new TeamGameplayEvent(game_event, player_details.Details.Team)); + } + } break; case EventType.Tip: - dispatcher.Broadcast(new PlayerGameplayEvent(game_event, _player_cache[game_event.PlayerID])); - dispatcher.Broadcast(new PlayerGameplayEvent(game_event, _player_cache[game_event.TipReceiverPlayerID])); - dispatcher.Broadcast(new TeamGameplayEvent(game_event, _player_cache[game_event.TipReceiverPlayerID].Details.Team)); + { + var player_details = _player_cache.GetValueOrDefault(game_event.PlayerID, null); + var tip_receiver_player_details = _player_cache.GetValueOrDefault(game_event.TipReceiverPlayerID, null); + if (player_details != null) + { + dispatcher.Broadcast(new PlayerGameplayEvent(game_event, player_details)); + } + + if (tip_receiver_player_details != null) + { + dispatcher.Broadcast(new PlayerGameplayEvent(game_event, tip_receiver_player_details)); + dispatcher.Broadcast(new TeamGameplayEvent(game_event, tip_receiver_player_details.Details.Team)); + } + } break; case EventType.Bounty_rune_pickup: - dispatcher.Broadcast(new PlayerGameplayEvent(game_event, _player_cache[game_event.PlayerID])); - dispatcher.Broadcast(new TeamGameplayEvent(game_event, game_event.Team)); + { + var player_details = _player_cache.GetValueOrDefault(game_event.PlayerID, null); + if (player_details != null) + { + dispatcher.Broadcast(new PlayerGameplayEvent(game_event, player_details)); + } + + dispatcher.Broadcast(new TeamGameplayEvent(game_event, game_event.Team)); + } break; default: break; diff --git a/Dota2GSI/StateHandlers/HeroHandler.cs b/Dota2GSI/StateHandlers/HeroHandler.cs index a8f7ba6..090a53a 100644 --- a/Dota2GSI/StateHandlers/HeroHandler.cs +++ b/Dota2GSI/StateHandlers/HeroHandler.cs @@ -43,20 +43,23 @@ private void OnHeroUpdated(DotaGameEvent e) return; } - if (!evt.New.LocalPlayer.Equals(evt.Previous.LocalPlayer)) + var local_player_details = _player_cache.GetValueOrDefault(-1, null); + + if (!evt.New.LocalPlayer.Equals(evt.Previous.LocalPlayer) && local_player_details != null) { - dispatcher.Broadcast(new HeroDetailsChanged(evt.New.LocalPlayer, evt.Previous.LocalPlayer, _player_cache[-1])); + dispatcher.Broadcast(new HeroDetailsChanged(evt.New.LocalPlayer, evt.Previous.LocalPlayer, local_player_details)); } foreach (var team_kvp in evt.New.Teams) { foreach (var player_kvp in team_kvp.Value) { + var player_details = _player_cache.GetValueOrDefault(player_kvp.Key, null); var previous_hero_details = evt.Previous.GetForPlayer(player_kvp.Key); - if (!player_kvp.Value.Equals(previous_hero_details)) + if (!player_kvp.Value.Equals(previous_hero_details) && player_details != null) { - dispatcher.Broadcast(new HeroDetailsChanged(player_kvp.Value, previous_hero_details, _player_cache[player_kvp.Key])); + dispatcher.Broadcast(new HeroDetailsChanged(player_kvp.Value, previous_hero_details, player_details)); } } } diff --git a/Dota2GSI/StateHandlers/ItemsHandler.cs b/Dota2GSI/StateHandlers/ItemsHandler.cs index b5bcf88..caf42dd 100644 --- a/Dota2GSI/StateHandlers/ItemsHandler.cs +++ b/Dota2GSI/StateHandlers/ItemsHandler.cs @@ -43,9 +43,11 @@ private void OnItemsUpdated(DotaGameEvent e) return; } - if (!evt.New.LocalPlayer.Equals(evt.Previous.LocalPlayer)) + var local_player_details = _player_cache.GetValueOrDefault(-1, null); + + if (!evt.New.LocalPlayer.Equals(evt.Previous.LocalPlayer) && local_player_details != null) { - dispatcher.Broadcast(new ItemDetailsChanged(evt.New.LocalPlayer, evt.Previous.LocalPlayer, _player_cache[-1])); + dispatcher.Broadcast(new ItemDetailsChanged(evt.New.LocalPlayer, evt.Previous.LocalPlayer, local_player_details)); } foreach (var team_kvp in evt.New.Teams) @@ -53,11 +55,12 @@ private void OnItemsUpdated(DotaGameEvent e) foreach (var player_kvp in team_kvp.Value) { // Get corresponding previous hero details. + var player_details = _player_cache.GetValueOrDefault(player_kvp.Key, null); var previous_hero_details = evt.Previous.GetForPlayer(player_kvp.Key); - if (!player_kvp.Value.Equals(previous_hero_details)) + if (!player_kvp.Value.Equals(previous_hero_details) && player_details != null) { - dispatcher.Broadcast(new ItemDetailsChanged(player_kvp.Value, previous_hero_details, _player_cache[player_kvp.Key])); + dispatcher.Broadcast(new ItemDetailsChanged(player_kvp.Value, previous_hero_details, player_details)); } } } diff --git a/Dota2GSI/StateHandlers/PlayerHandler.cs b/Dota2GSI/StateHandlers/PlayerHandler.cs index e8ed22e..5ea0d3e 100644 --- a/Dota2GSI/StateHandlers/PlayerHandler.cs +++ b/Dota2GSI/StateHandlers/PlayerHandler.cs @@ -43,9 +43,11 @@ private void OnPlayerUpdated(DotaGameEvent e) return; } - if (!evt.New.LocalPlayer.Equals(evt.Previous.LocalPlayer)) + var local_player_details = _player_cache.GetValueOrDefault(-1, null); + + if (!evt.New.LocalPlayer.Equals(evt.Previous.LocalPlayer) && local_player_details != null) { - dispatcher.Broadcast(new PlayerDetailsChanged(evt.New.LocalPlayer, evt.Previous.LocalPlayer, _player_cache[-1])); + dispatcher.Broadcast(new PlayerDetailsChanged(evt.New.LocalPlayer, evt.Previous.LocalPlayer, local_player_details)); } foreach (var team_kvp in evt.New.Teams) @@ -54,9 +56,11 @@ private void OnPlayerUpdated(DotaGameEvent e) { var previous_hero_details = evt.Previous.GetForPlayer(player_kvp.Key); - if (!player_kvp.Value.Equals(previous_hero_details)) + var player_details = _player_cache.GetValueOrDefault(player_kvp.Key, null); + + if (!player_kvp.Value.Equals(previous_hero_details) && player_details != null) { - dispatcher.Broadcast(new PlayerDetailsChanged(player_kvp.Value, previous_hero_details, _player_cache[player_kvp.Key])); + dispatcher.Broadcast(new PlayerDetailsChanged(player_kvp.Value, previous_hero_details, player_details)); } } } diff --git a/Dota2GSI/StateHandlers/WearablesHandler.cs b/Dota2GSI/StateHandlers/WearablesHandler.cs index d1a8203..785b863 100644 --- a/Dota2GSI/StateHandlers/WearablesHandler.cs +++ b/Dota2GSI/StateHandlers/WearablesHandler.cs @@ -41,20 +41,23 @@ private void OnWearablesUpdated(DotaGameEvent e) return; } - if (!evt.New.LocalPlayer.Equals(evt.Previous.LocalPlayer)) + var local_player_details = _player_cache.GetValueOrDefault(-1, null); + + if (!evt.New.LocalPlayer.Equals(evt.Previous.LocalPlayer) && local_player_details != null) { - dispatcher.Broadcast(new PlayerWearablesUpdated(evt.New.LocalPlayer, evt.Previous.LocalPlayer, _player_cache[-1])); + dispatcher.Broadcast(new PlayerWearablesUpdated(evt.New.LocalPlayer, evt.Previous.LocalPlayer, local_player_details)); } foreach (var team_kvp in evt.New.Teams) { foreach (var player_kvp in team_kvp.Value) { + var player_details = _player_cache.GetValueOrDefault(player_kvp.Key, null); var previous_hero_details = evt.Previous.GetForPlayer(player_kvp.Key); - if (!player_kvp.Value.Equals(previous_hero_details)) + if (!player_kvp.Value.Equals(previous_hero_details) && player_details != null) { - dispatcher.Broadcast(new PlayerWearablesUpdated(player_kvp.Value, previous_hero_details, _player_cache[player_kvp.Key])); + dispatcher.Broadcast(new PlayerWearablesUpdated(player_kvp.Value, previous_hero_details, player_details)); } } } From 6abd20cb43f1fa5f897aad7006bfde5fb0130df2 Mon Sep 17 00:00:00 2001 From: Anton Pupkov Date: Thu, 18 Jan 2024 17:18:29 -0800 Subject: [PATCH 24/24] Fix NodeList and NodeMap equality check --- Dota2GSI/Nodes/Node.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dota2GSI/Nodes/Node.cs b/Dota2GSI/Nodes/Node.cs index 9007cd6..ec3a50f 100644 --- a/Dota2GSI/Nodes/Node.cs +++ b/Dota2GSI/Nodes/Node.cs @@ -295,7 +295,7 @@ public override string ToString() public override bool Equals(object obj) { return obj is NodeMap other && - Count == other.Count && !this.Except(other).Any(); + this.SequenceEqual(other); } /// @@ -360,7 +360,7 @@ public override string ToString() public override bool Equals(object obj) { return obj is NodeList other && - Count == other.Count && !this.Except(other).Any(); + this.SequenceEqual(other); } ///