private void Update() { Stopwatch updateTimer = Stopwatch.StartNew(); if (m_players.Count > 0) { Parallel.ForEach(m_players, kvp => { PlayerPeer player = kvp.Value; if (!player.IsConnected) { s_log.Info("[{0}] is disconnected and will be removed", player.ID); player.Dispose(); PlayerPeer removedPlayer = default(PlayerPeer); m_players.TryRemove(kvp.Key, out removedPlayer); } }); } updateTimer.Stop(); m_lastWorldUpdateLength = (int)updateTimer.ElapsedMilliseconds; int restTime = TARGET_UPDATE_TIME_MS - m_lastWorldUpdateLength; if (restTime >= 0) { m_fiber.Schedule(Update, TimeSpan.FromMilliseconds(restTime), false); } else { s_log.Warn("World update ran into overtime by {0}ms", Math.Abs(restTime)); m_fiber.Enqueue(Update, false); } }
public void AcceptSocket(Socket sock) { sock.NoDelay = true; PlayerPeer p = new PlayerPeer(sock, m_accountRepository, m_playerRepository, m_abilityRepository, m_zones); //NOTE: Code here will block the AcceptSocket loop, so make sure it stays lean m_players[p.ID] = p; s_log.Info("[{0}] connected", p.ID); }
private async void Handle_UseAbility(UseAbility_C2S ability) { IEntity target = default(IEntity); AbilityModel abilityModel = m_abilityRepository.GetAbilityByID(ability.AbilityID); UseAbilityResult result = UseAbilityResult.Failed; string targetName = "[No Target]"; if (abilityModel == null) { result = UseAbilityResult.Failed; } else if (m_lastAbility.State == AbilityState.Casting) { result = UseAbilityResult.AlreadyCasting; } else if (Environment.TickCount - m_lastAbilityAcceptTime <= GLOBAL_COOLDOWN_MS) { result = UseAbilityResult.OnCooldown; } else if (Power + abilityModel.SourcePowerDelta < 0) { result = UseAbilityResult.NotEnoughPower; } else { if (ability.TargetID != 0) { target = await CurrentZone.GetTarget(ability.TargetID); if (target != null) { targetName = target.Name; } } if (abilityModel.AbilityType != AbilityModel.ETargetType.AOE && target == null) { result = UseAbilityResult.InvalidTarget; } else if (target is NPCInstance && abilityModel.AbilityType == AbilityModel.EAbilityType.HELP) { result = UseAbilityResult.InvalidTarget; } else if (Vector2.DistanceSquared(target.Position, Position) > Math.Pow(abilityModel.Range, 2)) { result = UseAbilityResult.OutOfRange; } else { m_lastAbility.Dispose(); m_lastAbility = new AbilityInstance(this, target, abilityModel); if (m_lastAbility.State == AbilityState.Casting) { Send(new AbilityCastNotification() { StartTime = m_lastAbility.StartTime, EndTime = m_lastAbility.EndTime }); } result = await m_lastAbility.RunAbility(); } } if (result == UseAbilityResult.OK) { List <IEntity> nearPlayers = m_nearEntities; AbilityUsedNotification notification = new AbilityUsedNotification(); notification.AbilityID = abilityModel.AbilityID; notification.SourceID = ID; notification.TargetID = target != null ? target.ID : 0; notification.Timestamp = Environment.TickCount; for (int i = 0; i < nearPlayers.Count; i++) { PlayerPeer player = nearPlayers[i] as PlayerPeer; if (player != null) { player.EnqueueSend(notification); } } } string abilityName = abilityModel != null ? abilityModel.InternalName : string.Format("[INVALID ID {0}]", ability.AbilityID); Info("Used ability {0} on target {1} with result {2}", abilityName, targetName, result); Respond(ability, new UseAbility_S2C() { Result = (int)result }); }