Ported .Net Core commits:
hondacrx: - Initial commit: Switch to .Net Core 2.0 - Fix build and removed not needed files Fabi: - Updated solution platforms. - Changed folder structure. - Change library target framework to netstandard2.0. - Updated solution platforms again... - Removed windows specific kernel32 function usage (Ctrl-C handler).
This commit is contained in:
@@ -0,0 +1,428 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2017 CypherCore <http://github.com/CypherCore>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Framework.Constants;
|
||||
using Game.DataStorage;
|
||||
using Game.Groups;
|
||||
using Game.Maps;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Linq;
|
||||
|
||||
namespace Game.Entities
|
||||
{
|
||||
public class MapManager : Singleton<MapManager>
|
||||
{
|
||||
MapManager()
|
||||
{
|
||||
i_gridCleanUpDelay = WorldConfig.GetUIntValue(WorldCfg.IntervalGridclean);
|
||||
i_timer.SetInterval(WorldConfig.GetIntValue(WorldCfg.IntervalMapupdate));
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
//todo needs alot of support for threadsafe.
|
||||
//int num_threads= WorldConfig.GetIntValue(WorldCfg.Numthreads);
|
||||
// Start mtmaps if needed.
|
||||
//if (num_threads > 0)
|
||||
//m_updater = new MapUpdater(WorldConfig.GetIntValue(WorldCfg.Numthreads));
|
||||
}
|
||||
|
||||
public void InitializeVisibilityDistanceInfo()
|
||||
{
|
||||
foreach (var pair in i_maps)
|
||||
pair.Value.InitVisibilityDistance();
|
||||
}
|
||||
|
||||
public Map CreateBaseMap(uint id)
|
||||
{
|
||||
Map map = FindBaseMap(id);
|
||||
|
||||
if (map == null)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
|
||||
var entry = CliDB.MapStorage.LookupByKey(id);
|
||||
Contract.Assert(entry != null);
|
||||
|
||||
if (entry.Instanceable())
|
||||
map = new MapInstanced(id, i_gridCleanUpDelay);
|
||||
else
|
||||
{
|
||||
map = new Map(id, i_gridCleanUpDelay, 0, Difficulty.None);
|
||||
map.LoadRespawnTimes();
|
||||
map.LoadCorpseData();
|
||||
}
|
||||
|
||||
i_maps[id] = map;
|
||||
}
|
||||
}
|
||||
Contract.Assert(map != null);
|
||||
return map;
|
||||
}
|
||||
|
||||
public Map FindBaseNonInstanceMap(uint mapId)
|
||||
{
|
||||
Map map = FindBaseMap(mapId);
|
||||
if (map != null && map.Instanceable())
|
||||
return null;
|
||||
return map;
|
||||
}
|
||||
|
||||
public Map CreateMap(uint id, Player player, uint loginInstanceId = 0)
|
||||
{
|
||||
Map m = CreateBaseMap(id);
|
||||
|
||||
if (m != null && m.Instanceable())
|
||||
m = ((MapInstanced)m).CreateInstanceForPlayer(id, player, loginInstanceId);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
public Map FindMap(uint mapid, uint instanceId)
|
||||
{
|
||||
Map map = FindBaseMap(mapid);
|
||||
if (map == null)
|
||||
return null;
|
||||
|
||||
if (!map.Instanceable())
|
||||
return instanceId == 0 ? map : null;
|
||||
|
||||
return ((MapInstanced)map).FindInstanceMap(instanceId);
|
||||
}
|
||||
|
||||
public EnterState PlayerCannotEnter(uint mapid, Player player, bool loginCheck = false)
|
||||
{
|
||||
MapRecord entry = CliDB.MapStorage.LookupByKey(mapid);
|
||||
if (entry == null)
|
||||
return EnterState.CannotEnterNoEntry;
|
||||
|
||||
if (!entry.IsDungeon())
|
||||
return EnterState.CanEnter;
|
||||
|
||||
InstanceTemplate instance = Global.ObjectMgr.GetInstanceTemplate(mapid);
|
||||
if (instance == null)
|
||||
return EnterState.CannotEnterUninstancedDungeon;
|
||||
|
||||
Difficulty targetDifficulty, requestedDifficulty;
|
||||
targetDifficulty = requestedDifficulty = player.GetDifficultyID(entry);
|
||||
// Get the highest available difficulty if current setting is higher than the instance allows
|
||||
MapDifficultyRecord mapDiff = Global.DB2Mgr.GetDownscaledMapDifficultyData(entry.Id, ref targetDifficulty);
|
||||
if (mapDiff == null)
|
||||
return EnterState.CannotEnterDifficultyUnavailable;
|
||||
|
||||
//Bypass checks for GMs
|
||||
if (player.IsGameMaster())
|
||||
return EnterState.CanEnter;
|
||||
|
||||
string mapName = entry.MapName[Global.WorldMgr.GetDefaultDbcLocale()];
|
||||
|
||||
Group group = player.GetGroup();
|
||||
if (entry.IsRaid()) // can only enter in a raid group
|
||||
if ((!group || !group.isRaidGroup()) && WorldConfig.GetBoolValue(WorldCfg.InstanceIgnoreRaid))
|
||||
return EnterState.CannotEnterNotInRaid;
|
||||
|
||||
if (!player.IsAlive())
|
||||
{
|
||||
if (player.HasCorpse())
|
||||
{
|
||||
// let enter in ghost mode in instance that connected to inner instance with corpse
|
||||
uint corpseMap = player.GetCorpseLocation().GetMapId();
|
||||
do
|
||||
{
|
||||
if (corpseMap == mapid)
|
||||
break;
|
||||
|
||||
InstanceTemplate corpseInstance = Global.ObjectMgr.GetInstanceTemplate(corpseMap);
|
||||
corpseMap = corpseInstance != null ? corpseInstance.Parent : 0;
|
||||
} while (corpseMap != 0);
|
||||
|
||||
if (corpseMap == 0)
|
||||
return EnterState.CannotEnterCorpseInDifferentInstance;
|
||||
|
||||
Log.outDebug(LogFilter.Maps, "MAP: Player '{0}' has corpse in instance '{1}' and can enter.", player.GetName(), mapName);
|
||||
}
|
||||
else
|
||||
Log.outDebug(LogFilter.Maps, "Map.CanPlayerEnter - player '{0}' is dead but does not have a corpse!", player.GetName());
|
||||
}
|
||||
|
||||
//Get instance where player's group is bound & its map
|
||||
if (!loginCheck && group)
|
||||
{
|
||||
InstanceBind boundInstance = group.GetBoundInstance(entry);
|
||||
if (boundInstance != null && boundInstance.save != null)
|
||||
{
|
||||
Map boundMap = FindMap(mapid, boundInstance.save.GetInstanceId());
|
||||
if (boundMap != null)
|
||||
{
|
||||
EnterState denyReason = boundMap.CannotEnter(player);
|
||||
if (denyReason != 0)
|
||||
return denyReason;
|
||||
}
|
||||
}
|
||||
}
|
||||
// players are only allowed to enter 10 instances per hour
|
||||
if (entry.IsDungeon() && (player.GetGroup() == null || (player.GetGroup() != null && !player.GetGroup().isLFGGroup())))
|
||||
{
|
||||
uint instaceIdToCheck = 0;
|
||||
InstanceSave save = player.GetInstanceSave(mapid);
|
||||
if (save != null)
|
||||
instaceIdToCheck = save.GetInstanceId();
|
||||
|
||||
// instanceId can never be 0 - will not be found
|
||||
if (!player.CheckInstanceCount(instaceIdToCheck) && !player.IsDead())
|
||||
return EnterState.CannotEnterTooManyInstances;
|
||||
}
|
||||
|
||||
//Other requirements
|
||||
if (player.Satisfy(Global.ObjectMgr.GetAccessRequirement(mapid, targetDifficulty), mapid, true))
|
||||
return EnterState.CanEnter;
|
||||
else
|
||||
return EnterState.CannotEnterUnspecifiedReason;
|
||||
}
|
||||
|
||||
public void Update(uint diff)
|
||||
{
|
||||
i_timer.Update(diff);
|
||||
if (!i_timer.Passed())
|
||||
return;
|
||||
|
||||
var time = (uint)i_timer.GetCurrent();
|
||||
foreach (var map in i_maps.Values.ToList())
|
||||
{
|
||||
//if (!m_updater)
|
||||
//m_updater.Enqueue(map, (uint)i_timer.GetCurrent());
|
||||
//else
|
||||
map.Update(time);
|
||||
}
|
||||
|
||||
//List<System.Threading.Tasks.Task> tasks = new List<System.Threading.Tasks.Task>();
|
||||
//foreach (var map in i_maps.Values.ToList())
|
||||
{
|
||||
//tasks.Add(System.Threading.Tasks.Task.Factory.StartNew(() => map.Update(time)));
|
||||
}
|
||||
//System.Threading.Tasks.Task.WaitAll(tasks.ToArray());
|
||||
//if (!m_updater)
|
||||
// m_updater.Wait();
|
||||
|
||||
foreach (var map in i_maps.ToList())
|
||||
map.Value.DelayedUpdate(time);
|
||||
|
||||
i_timer.SetCurrent(0);
|
||||
}
|
||||
|
||||
public bool ExistMapAndVMap(uint mapid, float x, float y)
|
||||
{
|
||||
GridCoord p = GridDefines.ComputeGridCoord(x, y);
|
||||
|
||||
uint gx = 63 - p.x_coord;
|
||||
uint gy = 63 - p.y_coord;
|
||||
|
||||
return Map.ExistMap(mapid, gx, gy) && Map.ExistVMap(mapid, gx, gy);
|
||||
}
|
||||
|
||||
public bool IsValidMAP(uint mapid, bool startUp)
|
||||
{
|
||||
MapRecord mEntry = CliDB.MapStorage.LookupByKey(mapid);
|
||||
|
||||
if (startUp)
|
||||
return mEntry != null ? true : false;
|
||||
else
|
||||
return mEntry != null && (!mEntry.IsDungeon() || Global.ObjectMgr.GetInstanceTemplate(mapid) != null);
|
||||
|
||||
// TODO: add check for Battlegroundtemplate
|
||||
}
|
||||
|
||||
public void UnloadAll()
|
||||
{
|
||||
foreach (var pair in i_maps.ToList())
|
||||
{
|
||||
pair.Value.UnloadAll();
|
||||
i_maps.Remove(pair.Value.GetId());
|
||||
}
|
||||
}
|
||||
|
||||
public uint GetNumInstances()
|
||||
{
|
||||
uint ret = 0;
|
||||
foreach (var pair in i_maps.ToList())
|
||||
{
|
||||
Map map = pair.Value;
|
||||
if (!map.Instanceable())
|
||||
continue;
|
||||
var maps = ((MapInstanced)map).GetInstancedMaps();
|
||||
foreach (var imap in maps)
|
||||
if (imap.Value.IsDungeon())
|
||||
ret++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public uint GetNumPlayersInInstances()
|
||||
{
|
||||
uint ret = 0;
|
||||
foreach (var pair in i_maps)
|
||||
{
|
||||
Map map = pair.Value;
|
||||
if (!map.Instanceable())
|
||||
continue;
|
||||
var maps = ((MapInstanced)map).GetInstancedMaps();
|
||||
foreach (var imap in maps)
|
||||
if (imap.Value.IsDungeon())
|
||||
ret += (uint)imap.Value.GetPlayers().Count;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void InitInstanceIds()
|
||||
{
|
||||
_nextInstanceId = 1;
|
||||
}
|
||||
|
||||
public void RegisterInstanceId(uint instanceId)
|
||||
{
|
||||
// Allocation and sizing was done in InitInstanceIds()
|
||||
_instanceIds[instanceId] = true;
|
||||
}
|
||||
|
||||
public uint GenerateInstanceId()
|
||||
{
|
||||
uint newInstanceId = _nextInstanceId;
|
||||
|
||||
// Find the lowest available id starting from the current NextInstanceId (which should be the lowest according to the logic in FreeInstanceId()
|
||||
for (uint i = ++_nextInstanceId; i < 0xFFFFFFFF; ++i)
|
||||
{
|
||||
if ((i < _instanceIds.Count && !_instanceIds[i]) || i >= _instanceIds.Count)
|
||||
{
|
||||
_nextInstanceId = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (newInstanceId == _nextInstanceId)
|
||||
{
|
||||
Log.outError(LogFilter.Maps, "Instance ID overflow!! Can't continue, shutting down server. ");
|
||||
Global.WorldMgr.StopNow();
|
||||
}
|
||||
|
||||
_instanceIds[newInstanceId] = true;
|
||||
|
||||
return newInstanceId;
|
||||
}
|
||||
|
||||
public void FreeInstanceId(uint instanceId)
|
||||
{
|
||||
// If freed instance id is lower than the next id available for new instances, use the freed one instead
|
||||
if (instanceId < _nextInstanceId)
|
||||
SetNextInstanceId(instanceId);
|
||||
|
||||
_instanceIds[instanceId] = false;
|
||||
}
|
||||
|
||||
public void SetGridCleanUpDelay(uint t)
|
||||
{
|
||||
if (t < MapConst.MinGridDelay)
|
||||
i_gridCleanUpDelay = MapConst.MinGridDelay;
|
||||
else
|
||||
i_gridCleanUpDelay = t;
|
||||
}
|
||||
|
||||
public void SetMapUpdateInterval(int t)
|
||||
{
|
||||
if (t < MapConst.MinMapUpdateDelay)
|
||||
t = MapConst.MinMapUpdateDelay;
|
||||
|
||||
i_timer.SetInterval(t);
|
||||
i_timer.Reset();
|
||||
}
|
||||
|
||||
public uint GetNextInstanceId() { return _nextInstanceId; }
|
||||
|
||||
public void SetNextInstanceId(uint nextInstanceId) { _nextInstanceId = nextInstanceId; }
|
||||
|
||||
Map FindBaseMap(uint mapId)
|
||||
{
|
||||
return i_maps.LookupByKey(mapId);
|
||||
}
|
||||
|
||||
uint GetAreaId(uint mapid, float x, float y, float z)
|
||||
{
|
||||
Map m = CreateBaseMap(mapid);
|
||||
return m.GetAreaId(x, y, z);
|
||||
}
|
||||
|
||||
public uint GetZoneId(uint mapid, float x, float y, float z)
|
||||
{
|
||||
Map m = CreateBaseMap(mapid);
|
||||
return m.GetZoneId(x, y, z);
|
||||
}
|
||||
|
||||
public void GetZoneAndAreaId(out uint zoneid, out uint areaid, uint mapid, float x, float y, float z)
|
||||
{
|
||||
Map m = CreateBaseMap(mapid);
|
||||
m.GetZoneAndAreaId(out zoneid, out areaid, x, y, z);
|
||||
}
|
||||
|
||||
public void DoForAllMaps(Action<Map> worker)
|
||||
{
|
||||
foreach (var map in i_maps.Values)
|
||||
{
|
||||
MapInstanced mapInstanced = map.ToMapInstanced();
|
||||
if (mapInstanced)
|
||||
{
|
||||
var instances = mapInstanced.GetInstancedMaps();
|
||||
foreach (var instance in instances.Values)
|
||||
worker(instance);
|
||||
}
|
||||
else
|
||||
worker(map);
|
||||
}
|
||||
}
|
||||
|
||||
public void DoForAllMapsWithMapId(uint mapId, Action<Map> worker)
|
||||
{
|
||||
var map = i_maps.LookupByKey(mapId);
|
||||
if (map != null)
|
||||
{
|
||||
MapInstanced mapInstanced = map.ToMapInstanced();
|
||||
if (mapInstanced)
|
||||
{
|
||||
var instances = mapInstanced.GetInstancedMaps();
|
||||
foreach (var instance in instances)
|
||||
worker(instance.Value);
|
||||
}
|
||||
else
|
||||
worker(map);
|
||||
}
|
||||
}
|
||||
|
||||
public void IncreaseScheduledScriptsCount() { ++_scheduledScripts; }
|
||||
public void DecreaseScheduledScriptCount() { --_scheduledScripts; }
|
||||
public void DecreaseScheduledScriptCount(uint count) { _scheduledScripts -= count; }
|
||||
public bool IsScriptScheduled() { return _scheduledScripts > 0; }
|
||||
|
||||
Dictionary<uint, Map> i_maps = new Dictionary<uint, Map>();
|
||||
IntervalTimer i_timer = new IntervalTimer();
|
||||
uint i_gridCleanUpDelay;
|
||||
Dictionary<uint, bool> _instanceIds = new Dictionary<uint, bool>();
|
||||
uint _nextInstanceId;
|
||||
//MapUpdater m_updater;
|
||||
uint _scheduledScripts;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user