public void MoveCharacter(IClientConnection clientConnection, MovementDirection direction) { if (clientConnection.Character.State != CharacterState.Normal) { return; } var oldLocation = clientConnection.Location; string newXyz; switch (direction) { case MovementDirection.North when oldLocation.Exits.Contains(MovementDirection.North): newXyz = $"{oldLocation.XCoord},{oldLocation.YCoord - 1},{oldLocation.ZCoord}"; break; case MovementDirection.East when oldLocation.Exits.Contains(MovementDirection.East): newXyz = $"{oldLocation.XCoord + 1},{oldLocation.YCoord},{oldLocation.ZCoord}"; break; case MovementDirection.South when oldLocation.Exits.Contains(MovementDirection.South): newXyz = $"{oldLocation.XCoord},{oldLocation.YCoord + 1},{oldLocation.ZCoord}"; break; case MovementDirection.West when oldLocation.Exits.Contains(MovementDirection.West): newXyz = $"{oldLocation.XCoord - 1},{oldLocation.YCoord},{oldLocation.ZCoord}"; break; default: clientConnection.InvokeMessageReceived(new LocalEventMessage("There is no exit in that direction.")); return; } if (!_world.Locations.TryGet(newXyz, out var newLocation)) { newLocation = GetRandomLocation(newXyz); _world.Locations.AddOrUpdate(newLocation.XYZ, newLocation); } else { AddLogicalExits(newLocation.Exits, _world, newXyz); } oldLocation.LastAccessed = DateTimeOffset.Now; newLocation.LastAccessed = DateTimeOffset.Now; oldLocation.RemoveCharacter(clientConnection.Character); newLocation.AddCharacter(clientConnection.Character); clientConnection.Location = newLocation; clientConnection.Character.Stats.FarthestDistanceTravelled = (long)Calculator.GetDistanceBetween(0, 0, newLocation.XCoord, newLocation.YCoord); _clientManager.SendToOtherLocals(clientConnection, oldLocation, new LocalEventMessage($"{clientConnection.Character.Name} left to the {direction}.")); _clientManager.SendToOtherLocals(clientConnection, newLocation, new LocalEventMessage($"{clientConnection.Character.Name} entered from the {GetOppositeDirection(direction)}.")); clientConnection.InvokeMessageReceived(MessageBase.LocationChanged); if (!newLocation.NpcsAlive.Any(x => x.AggressionModel > AggressionModel.OnAttacked)) { _encounterService.SpawnNpcs(clientConnection, TimeSpan.FromSeconds(3), 1); } // If character is party leader, have members follow. if (clientConnection.Character?.Party is Party party && party.Leader == clientConnection.Character) { var membersNearby = oldLocation.PlayersAlive .Except(new[] { clientConnection.Character }) .Where(x => party.Members.Contains(x)); foreach (var member in membersNearby) { if (member.Settings.AutoFollowPartyLeader) { MoveCharacter(_clientManager.FindConnection(member), direction); } } } }