From a98ce1eb00dfeeefe67d83510d2adf8f0b3f0683 Mon Sep 17 00:00:00 2001 From: hondacrx Date: Mon, 27 Jun 2022 16:56:01 -0400 Subject: [PATCH] Core/WorldStates: Add area requirements to world states Port From (https://github.com/TrinityCore/TrinityCore/commit/70eacebad531af0a4b5b4ac6be6d90ddc56ed5d4) --- Source/Game/Entities/Player/Player.cs | 14 +++--- Source/Game/Maps/Map.cs | 16 ++++++- Source/Game/World/WorldStateManager.cs | 60 +++++++++++++++++++++++--- 3 files changed, 76 insertions(+), 14 deletions(-) diff --git a/Source/Game/Entities/Player/Player.cs b/Source/Game/Entities/Player/Player.cs index 180af02f1..277e876cd 100644 --- a/Source/Game/Entities/Player/Player.cs +++ b/Source/Game/Entities/Player/Player.cs @@ -2899,21 +2899,21 @@ namespace Game.Entities SendPacket(worldstate); } - void SendInitWorldStates(uint zoneid, uint areaid) + void SendInitWorldStates(uint zoneId, uint areaId) { // data depends on zoneid/mapid... Battleground bg = GetBattleground(); uint mapid = GetMapId(); - OutdoorPvP pvp = Global.OutdoorPvPMgr.GetOutdoorPvPToZoneId(zoneid); + OutdoorPvP pvp = Global.OutdoorPvPMgr.GetOutdoorPvPToZoneId(zoneId); InstanceScript instance = GetInstanceScript(); - BattleField battlefield = Global.BattleFieldMgr.GetBattlefieldToZoneId(zoneid); + BattleField battlefield = Global.BattleFieldMgr.GetBattlefieldToZoneId(zoneId); InitWorldStates packet = new(); packet.MapID = mapid; - packet.AreaID = zoneid; - packet.SubareaID = areaid; + packet.AreaID = zoneId; + packet.SubareaID = areaId; - Global.WorldStateMgr.FillInitialWorldStates(packet, GetMap()); + Global.WorldStateMgr.FillInitialWorldStates(packet, GetMap(), areaId); packet.AddState(2264, 0); // SCOURGE_EVENT_WORLDSTATE_EASTERN_PLAGUELANDS packet.AddState(2263, 0); // SCOURGE_EVENT_WORLDSTATE_TANARIS @@ -2947,7 +2947,7 @@ namespace Game.Entities packet.AddState(17043, (uint)(10 + (Global.WorldMgr.GetWarModeDominantFaction() == TeamId.Horde ? Global.WorldMgr.GetWarModeOutnumberedFactionReward() : 0))); // insert - switch (zoneid) + switch (zoneId) { case 1: // Dun Morogh case 11: // Wetlands diff --git a/Source/Game/Maps/Map.cs b/Source/Game/Maps/Map.cs index f8e11188e..619a24b84 100644 --- a/Source/Game/Maps/Map.cs +++ b/Source/Game/Maps/Map.cs @@ -583,7 +583,7 @@ namespace Game.Maps } public Dictionary GetWorldStateValues() { return _worldStateValues; } - + public void SetWorldStateValue(int worldStateId, int value) { int oldValue = _worldStateValues.LookupByKey(worldStateId); @@ -597,7 +597,19 @@ namespace Game.Maps UpdateWorldState updateWorldState = new(); updateWorldState.VariableID = (uint)worldStateId; updateWorldState.Value = value; - SendToPlayers(updateWorldState); + updateWorldState.Write(); + + foreach (var player in GetPlayers()) + { + if (worldStateTemplate != null && !worldStateTemplate.AreaIds.Empty()) + { + bool isInAllowedArea = worldStateTemplate.AreaIds.Any(requiredAreaId => Global.DB2Mgr.IsInArea(player.GetAreaId(), requiredAreaId)); + if (!isInAllowedArea) + continue; + } + + player.SendPacket(updateWorldState); + } } void InitializeObject(WorldObject obj) diff --git a/Source/Game/World/WorldStateManager.cs b/Source/Game/World/WorldStateManager.cs index ad8d78d36..6ec948d99 100644 --- a/Source/Game/World/WorldStateManager.cs +++ b/Source/Game/World/WorldStateManager.cs @@ -16,13 +16,14 @@ */ using Framework.Collections; +using Framework.Constants; using Framework.Database; using Game.DataStorage; using Game.Maps; using Game.Networking.Packets; using System; using System.Collections.Generic; -using Framework.Constants; +using System.Linq; namespace Game { @@ -38,8 +39,8 @@ namespace Game { uint oldMSTime = Time.GetMSTime(); - // 0 1 2 3 - SQLResult result = DB.World.Query("SELECT ID, DefaultValue, MapIDs, ScriptName FROM world_state"); + // 0 1 2 3 4 + SQLResult result = DB.World.Query("SELECT ID, DefaultValue, MapIDs, AreaIDs, ScriptName FROM world_state"); if (result.IsEmpty()) return; @@ -74,7 +75,45 @@ namespace Game continue; } - worldState.ScriptId = Global.ObjectMgr.GetScriptId(result.Read(3)); + string areaIds = result.Read(3); + if (!worldState.MapIds.Empty()) + { + foreach (string areaIdToken in new StringArray(areaIds, ',')) + { + if (!uint.TryParse(areaIdToken, out uint areaId)) + { + Log.outError(LogFilter.Sql, $"Table `world_state` contains a world state {id} with non-integer AreaID ({areaIdToken}), area ignored"); + continue; + } + + var areaTableEntry = CliDB.AreaTableStorage.LookupByKey(areaId); + if (areaTableEntry == null) + { + Log.outError(LogFilter.Sql, $"Table `world_state` contains a world state {id} with invalid AreaID ({areaId}), area ignored"); + continue; + } + + if (!worldState.MapIds.Contains(areaTableEntry.ContinentID)) + { + Log.outError(LogFilter.Sql, $"Table `world_state` contains a world state {id} with AreaID ({areaId}) not on any of required maps, area ignored"); + continue; + } + + worldState.AreaIds.Add(areaId); + } + + if (!areaIds.IsEmpty() && worldState.AreaIds.Empty()) + { + Log.outError(LogFilter.Sql, $"Table `world_state` contains a world state {id} with nonempty AreaIDs ({areaIds}) but no valid area id was found, ignored"); + continue; + } + } + else if (!areaIds.IsEmpty()) + { + Log.outError(LogFilter.Sql, $"Table `world_state` contains a world state {id} with nonempty AreaIDs ({areaIds}) but is a realm wide world state, area requirement ignored"); + } + + worldState.ScriptId = Global.ObjectMgr.GetScriptId(result.Read(4)); if (!worldState.MapIds.Empty()) { @@ -156,13 +195,23 @@ namespace Game return new Dictionary(); } - public void FillInitialWorldStates(InitWorldStates initWorldStates, Map map) + public void FillInitialWorldStates(InitWorldStates initWorldStates, Map map, uint playerAreaId) { foreach (var (worldStateId, value) in _realmWorldStateValues) initWorldStates.AddState(worldStateId, value); foreach (var (worldStateId, value) in map.GetWorldStateValues()) + { + WorldStateTemplate worldStateTemplate = GetWorldStateTemplate(worldStateId); + if (worldStateTemplate != null && !worldStateTemplate.AreaIds.Empty()) + { + bool isInAllowedArea = worldStateTemplate.AreaIds.Any(requiredAreaId => Global.DB2Mgr.IsInArea(playerAreaId, requiredAreaId)); + if (!isInAllowedArea) + continue; + } + initWorldStates.AddState(worldStateId, value); + } } } @@ -173,5 +222,6 @@ namespace Game public uint ScriptId; public List MapIds = new(); + public List AreaIds = new(); } }