Skip to content

Commit

Permalink
Merge pull request #121 from ethanmoffat/friend_ignore_lists
Browse files Browse the repository at this point in the history
Implement friend/ignore lists. Implement online list panel friend filter. Implement ignore for incoming player chat.
  • Loading branch information
ethanmoffat committed Mar 21, 2022
2 parents 0010791 + eeced17 commit 33b77b7
Show file tree
Hide file tree
Showing 52 changed files with 1,629 additions and 770 deletions.
2 changes: 1 addition & 1 deletion EOLib/Net/Translators/OnlineListPacketTranslator.cs
Expand Up @@ -49,7 +49,7 @@ public IOnlineListData TranslatePacket(IPacket packet)
else
title = char.ToUpper(title[0]) + title.Substring(1);

var className = _classFileProvider.ECFFile.Length <= clsId
var className = _classFileProvider.ECFFile.Length >= clsId
? _classFileProvider.ECFFile[clsId].Name
: "-";

Expand Down
3 changes: 3 additions & 0 deletions EOLib/misc.cs
Expand Up @@ -42,6 +42,9 @@ public static class Constants
public const string LogFilePath = "log/debug.log";
public const string LogFileFmt = "log/{0}-debug.log";

public const string FriendListFile = "config/friends.ini";
public const string IgnoreListFile = "config/ignore.ini";

//Should be easily customizable between different clients (based on graphics)
//not a config option because this shouldn't be exposed at the user level
public static readonly int[] TrapSpikeGFXObjectIDs = {449, 450, 451, 452};
Expand Down
51 changes: 51 additions & 0 deletions EndlessClient/Dialogs/Actions/InGameDialogActions.cs
@@ -0,0 +1,51 @@
using AutomaticTypeMapper;
using EndlessClient.Dialogs.Factories;
using Optional;

namespace EndlessClient.Dialogs.Actions
{
[AutoMappedType]
public class InGameDialogActions : IInGameDialogActions
{
private readonly IFriendIgnoreListDialogFactory _friendIgnoreListDialogFactory;
private readonly IActiveDialogRepository _activeDialogRepository;

public InGameDialogActions(IFriendIgnoreListDialogFactory friendIgnoreListDialogFactory,
IActiveDialogRepository activeDialogRepository)
{
_friendIgnoreListDialogFactory = friendIgnoreListDialogFactory;
_activeDialogRepository = activeDialogRepository;
}

public void ShowFriendListDialog()
{
_activeDialogRepository.FriendIgnoreDialog.MatchNone(() =>
{
var dlg = _friendIgnoreListDialogFactory.Create(isFriendList: true);
dlg.DialogClosed += (_, _) => _activeDialogRepository.FriendIgnoreDialog = Option.None<ScrollingListDialog>();
_activeDialogRepository.FriendIgnoreDialog = Option.Some(dlg);
dlg.Show();
});
}

public void ShowIgnoreListDialog()
{
_activeDialogRepository.FriendIgnoreDialog.MatchNone(() =>
{
var dlg = _friendIgnoreListDialogFactory.Create(isFriendList: false);
dlg.DialogClosed += (_, _) => _activeDialogRepository.FriendIgnoreDialog = Option.None<ScrollingListDialog>();
_activeDialogRepository.FriendIgnoreDialog = Option.Some(dlg);
dlg.Show();
});
}
}

public interface IInGameDialogActions
{
void ShowFriendListDialog();

void ShowIgnoreListDialog();
}
}
43 changes: 43 additions & 0 deletions EndlessClient/Dialogs/ActiveDialogRepository.cs
@@ -0,0 +1,43 @@
using AutomaticTypeMapper;
using Optional;
using System.Collections.Generic;
using System.Linq;
using XNAControls;

namespace EndlessClient.Dialogs
{
public interface IActiveDialogProvider
{
Option<ScrollingListDialog> FriendIgnoreDialog { get; }

IReadOnlyList<Option<IXNADialog>> ActiveDialogs { get; }
}

public interface IActiveDialogRepository
{
Option<ScrollingListDialog> FriendIgnoreDialog { get; set; }

IReadOnlyList<Option<IXNADialog>> ActiveDialogs { get; }
}

[AutoMappedType(IsSingleton = true)]
public class ActiveDialogRepository : IActiveDialogRepository, IActiveDialogProvider
{
public Option<ScrollingListDialog> FriendIgnoreDialog { get; set; }

IReadOnlyList<Option<IXNADialog>> ActiveDialogs
{
get
{
return new[]
{
FriendIgnoreDialog.Map(d => (IXNADialog)d),
}.ToList();
}
}

IReadOnlyList<Option<IXNADialog>> IActiveDialogRepository.ActiveDialogs => ActiveDialogs;

IReadOnlyList<Option<IXNADialog>> IActiveDialogProvider.ActiveDialogs => ActiveDialogs;
}
}
140 changes: 140 additions & 0 deletions EndlessClient/Dialogs/Factories/FriendIgnoreListDialogFactory.cs
@@ -0,0 +1,140 @@
using AutomaticTypeMapper;
using EndlessClient.ControlSets;
using EndlessClient.Dialogs.Services;
using EndlessClient.GameExecution;
using EndlessClient.HUD.Controls;
using EndlessClient.Old;
using EndlessClient.Services;
using EndlessClient.UIControls;
using EOLib;
using EOLib.Domain.Character;
using EOLib.Graphics;
using EOLib.Localization;
using System;
using System.Linq;
using XNAControls;

namespace EndlessClient.Dialogs.Factories
{
[AutoMappedType]
public class FriendIgnoreListDialogFactory : IFriendIgnoreListDialogFactory
{
private readonly IGameStateProvider _gameStateProvider;
private readonly INativeGraphicsManager _nativeGraphicsManager;
private readonly IEODialogButtonService _dialogButtonService;
private readonly ILocalizedStringFinder _localizedStringFinder;
private readonly ICharacterProvider _characterProvider;
private readonly IHudControlProvider _hudControlProvider;
private readonly ITextInputDialogFactory _textInputDialogFactory;
private readonly IEOMessageBoxFactory _eoMessageBoxFactory;
private readonly IFriendIgnoreListService _friendIgnoreListService;

public FriendIgnoreListDialogFactory(IGameStateProvider gameStateProvider,
INativeGraphicsManager nativeGraphicsManager,
IEODialogButtonService dialogButtonService,
ILocalizedStringFinder localizedStringFinder,
ICharacterProvider characterProvider,
IHudControlProvider hudControlProvider,
ITextInputDialogFactory textInputDialogFactory,
IEOMessageBoxFactory eoMessageBoxFactory,
IFriendIgnoreListService friendIgnoreListService)
{
_gameStateProvider = gameStateProvider;
_nativeGraphicsManager = nativeGraphicsManager;
_dialogButtonService = dialogButtonService;
_localizedStringFinder = localizedStringFinder;
_characterProvider = characterProvider;
_hudControlProvider = hudControlProvider;
_textInputDialogFactory = textInputDialogFactory;
_eoMessageBoxFactory = eoMessageBoxFactory;
_friendIgnoreListService = friendIgnoreListService;
}

public ScrollingListDialog Create(bool isFriendList)
{
var textFileLines = _friendIgnoreListService.LoadList(isFriendList ? Constants.FriendListFile : Constants.IgnoreListFile);

var dialog = new ScrollingListDialog(_gameStateProvider, _nativeGraphicsManager, _dialogButtonService)
{
Buttons = ScrollingListDialogButtons.AddCancel,
ListItemType = ListDialogItem.ListItemStyle.Small,
};

var listItems = textFileLines.Select(x => new ListDialogItem(dialog, ListDialogItem.ListItemStyle.Small) { PrimaryText = x }).ToList();
foreach (var item in listItems)
SetClickEventHandlers(item, dialog, isFriendList);
dialog.SetItemList(listItems);

dialog.Title = GetDialogTitle(dialog, isFriendList);

dialog.AddAction += (_, _) => InvokeAdd(isFriendList, dialog);
dialog.DialogClosing += (_, _) =>
{
if (isFriendList)
_friendIgnoreListService.SaveFriends(Constants.FriendListFile, dialog.NamesList);
else
_friendIgnoreListService.SaveIgnored(Constants.IgnoreListFile, dialog.NamesList);
};

return dialog;
}

private void InvokeAdd(bool isFriendList, ScrollingListDialog parentDialog)
{
string prompt = _localizedStringFinder.GetString(isFriendList ? EOResourceID.DIALOG_WHO_TO_MAKE_FRIEND : EOResourceID.DIALOG_WHO_TO_MAKE_IGNORE);
var inputDialog = _textInputDialogFactory.Create(prompt);

inputDialog.DialogClosing += (_, e) =>
{
if (e.Result == XNADialogResult.Cancel)
return;
if (inputDialog.ResponseText.Length < 4)
{
e.Cancel = true;
var messageBox = _eoMessageBoxFactory.CreateMessageBox(DialogResourceID.CHARACTER_CREATE_NAME_TOO_SHORT);
messageBox.ShowDialog();
return;
}
if (parentDialog.NamesList.Any(name => string.Equals(name, inputDialog.ResponseText, StringComparison.InvariantCultureIgnoreCase)))
{
e.Cancel = true;
var messageBox = _eoMessageBoxFactory.CreateMessageBox("You are already friends with that person!", "Invalid entry!", EODialogButtons.Ok, EOMessageBoxStyle.SmallDialogSmallHeader);
messageBox.ShowDialog();
return;
}
var charName = char.ToUpper(inputDialog.ResponseText[0]) + inputDialog.ResponseText.Substring(1);
var newItem = new ListDialogItem(parentDialog, ListDialogItem.ListItemStyle.Small) { PrimaryText = charName };
SetClickEventHandlers(newItem, parentDialog, isFriendList);
parentDialog.AddItemToList(newItem, sortList: true);
parentDialog.Title = GetDialogTitle(parentDialog, isFriendList);
};

inputDialog.ShowDialog();
}

private void SetClickEventHandlers(ListDialogItem item, ScrollingListDialog dialog, bool isFriendList)
{
item.LeftClick += (o, e) => _hudControlProvider.GetComponent<ChatTextBox>(HudControlIdentifier.ChatTextBox).Text = $"!{item.PrimaryText} ";
item.RightClick += (o, e) =>
{
dialog.RemoveFromList(item);
dialog.Title = GetDialogTitle(dialog, isFriendList);
};
}

private string GetDialogTitle(ScrollingListDialog dialog, bool isFriendList)
{
var friendOrIgnoreStr = _localizedStringFinder.GetString(isFriendList ? EOResourceID.STATUS_LABEL_FRIEND_LIST : EOResourceID.STATUS_LABEL_IGNORE_LIST);
return $"{_characterProvider.MainCharacter.Name}'s {friendOrIgnoreStr} [{dialog.NamesList.Count}]";
}
}

public interface IFriendIgnoreListDialogFactory
{
ScrollingListDialog Create(bool isFriendList);
}
}
48 changes: 48 additions & 0 deletions EndlessClient/Dialogs/Factories/TextInputDialogFactory.cs
@@ -0,0 +1,48 @@
using AutomaticTypeMapper;
using EndlessClient.Content;
using EndlessClient.Dialogs.Services;
using EndlessClient.GameExecution;
using EndlessClient.Input;
using EOLib.Graphics;

namespace EndlessClient.Dialogs.Factories
{
[AutoMappedType]
public class TextInputDialogFactory : ITextInputDialogFactory
{
private readonly IGameStateProvider _gameStateProvider;
private readonly INativeGraphicsManager _nativeGraphicsManager;
private readonly IEODialogButtonService _eoDialogButtonService;
private readonly IKeyboardDispatcherRepository _keyboardDispatcherRepository;
private readonly IContentManagerProvider _contentManagerProvider;

public TextInputDialogFactory(IGameStateProvider gameStateProvider,
INativeGraphicsManager nativeGraphicsManager,
IEODialogButtonService eoDialogButtonService,
IKeyboardDispatcherRepository keyboardDispatcherRepository,
IContentManagerProvider contentManagerProvider)
{
_gameStateProvider = gameStateProvider;
_nativeGraphicsManager = nativeGraphicsManager;
_eoDialogButtonService = eoDialogButtonService;
_keyboardDispatcherRepository = keyboardDispatcherRepository;
_contentManagerProvider = contentManagerProvider;
}

public TextInputDialog Create(string prompt, int maxInputChars = 12)
{
return new TextInputDialog(_gameStateProvider,
_nativeGraphicsManager,
_eoDialogButtonService,
_keyboardDispatcherRepository,
_contentManagerProvider,
prompt,
maxInputChars);
}
}

public interface ITextInputDialogFactory
{
TextInputDialog Create(string prompt, int maxInputChars = 12);
}
}

0 comments on commit 33b77b7

Please sign in to comment.