Skip to content

Commit

Permalink
Merge pull request #340 from ethanmoffat/reports
Browse files Browse the repository at this point in the history
Implement handling for reports and ADMININTERACT packet family.
  • Loading branch information
ethanmoffat authored Apr 15, 2024
2 parents e3dbbe6 + 49b5715 commit 2a35a95
Show file tree
Hide file tree
Showing 33 changed files with 987 additions and 100 deletions.
27 changes: 27 additions & 0 deletions EOLib.Localization/EOResourceID.cs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ public enum EOResourceID

DIALOG_TRANSFER_TRANSFER = 176,

ADMIN_INFO_WORD_BANK_ACCOUNT = 181,

SETTING_KEYBOARD_ENGLISH = 253,
SETTING_KEYBOARD_DUTCH = 254,
SETTING_KEYBOARD_SWEDISH = 255,
Expand Down Expand Up @@ -257,6 +259,11 @@ public enum EOResourceID
SKILLMASTER_CLICK_HERE_TO_FORGET_ALL = 351,
SKILLMASTER_RESET_YOUR_CHARACTER = 352,

ADMIN_INFO_WORD_LOCATION = 353,
ADMIN_INFO_WORD_COORDINATES = 354,
ADMIN_INFO_WORD_HITPOINTS = 355,
ADMIN_INFO_WORD_TECHPOINTS = 356,

ACCOUNT_CREATE_WARNING_DIALOG_1 = 357,
ACCOUNT_CREATE_WARNING_DIALOG_2 = 358,
ACCOUNT_CREATE_WARNING_DIALOG_3 = 359,
Expand All @@ -271,6 +278,14 @@ public enum EOResourceID
LOADING_GAME_HINT_FIRST = 368,
LOADING_GAME_HINT_LAST = 374,

ENDLESS_HELP = 375,
ENDLESS_HELP_SUMMARY_1 = 376,
ENDLESS_HELP_SUMMARY_2 = 377,

ENDLESS_HELP_LINK_RESET_PASSWORD = 378,
ENDLESS_HELP_LINK_REPORT_SOMEONE = 379,
ENDLESS_HELP_LINK_SPEAK_TO_ADMIN = 380,

INN_REGISTRATION_SERVICE = 384,
INN_CITIZEN_REGISTRATION_SERVICE = 385,
INN_SIGN_UP = 386,
Expand Down Expand Up @@ -303,6 +318,18 @@ public enum EOResourceID

STATUS_LABEL_ITEM_EQUIP_THIS_ITEM_REQUIRES = 411,

ADMIN_INFO_WORD_DAMAGE = 412,
ADMIN_INFO_WORD_HITRATE = 413,
ADMIN_INFO_WORD_ARMOR = 414,
ADMIN_INFO_WORD_DODGE = 415,
ADMIN_INFO_WORD_WEIGHT = 416,
ADMIN_INFO_WORD_LIGHT = 417,
ADMIN_INFO_WORD_DARK = 418,
ADMIN_INFO_WORD_FIRE = 419,
ADMIN_INFO_WORD_WATER = 420,
ADMIN_INFO_WORD_EARTH = 421,
ADMIN_INFO_WORD_WIND = 422,

STATUS_LABEL_UNABLE_TO_ATTACK = 423,
STATUS_LABEL_YOU_HAVE_NO_ARROWS = 424,

Expand Down
9 changes: 8 additions & 1 deletion EOLib/Domain/Character/CharacterStat.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,17 @@ public enum CharacterStat
Intelligence,
Wisdom,
Agility,
Constituion,
Constitution,
Charisma,

Weight,
MaxWeight,

Light,
Dark,
Fire,
Water,
Earth,
Wind,
}
}
4 changes: 2 additions & 2 deletions EOLib/Domain/Character/TrainingActions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ private static bool InvalidStat(CharacterStat whichStat)
case CharacterStat.Intelligence:
case CharacterStat.Wisdom:
case CharacterStat.Agility:
case CharacterStat.Constituion:
case CharacterStat.Constitution:
case CharacterStat.Charisma: return false;
default: return true;
}
Expand All @@ -60,7 +60,7 @@ private static int GetStatIndex(CharacterStat whichStat)
case CharacterStat.Intelligence: return 2;
case CharacterStat.Wisdom: return 3;
case CharacterStat.Agility: return 4;
case CharacterStat.Constituion: return 5;
case CharacterStat.Constitution: return 5;
case CharacterStat.Charisma: return 6;
}

Expand Down
2 changes: 1 addition & 1 deletion EOLib/Domain/Item/ItemEquipValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public ItemEquipValidator(IECFFileProvider ecfFileProvider,
var reqNames = new[] { "STR", "INT", "WIS", "AGI", "CON", "CHA" };
if ((reqs[0] = itemData.StrReq) > c.Stats[CharacterStat.Strength] || (reqs[1] = itemData.IntReq) > c.Stats[CharacterStat.Intelligence]
|| (reqs[2] = itemData.WisReq) > c.Stats[CharacterStat.Wisdom] || (reqs[3] = itemData.AgiReq) > c.Stats[CharacterStat.Agility]
|| (reqs[4] = itemData.ConReq) > c.Stats[CharacterStat.Constituion] || (reqs[5] = itemData.ChaReq) > c.Stats[CharacterStat.Charisma])
|| (reqs[4] = itemData.ConReq) > c.Stats[CharacterStat.Constitution] || (reqs[5] = itemData.ChaReq) > c.Stats[CharacterStat.Charisma])
{
var req = reqs.Select((i, n) => new { Req = n, Ndx = i }).First(x => x.Req > 0);
return (ItemEquipResult.StatRequirementNotMet, $" {reqs[req.Ndx]} {reqNames[req.Ndx]}", isAlternateEquipLocation);
Expand Down
10 changes: 10 additions & 0 deletions EOLib/Domain/Notifiers/IUserInterfaceNotifier.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using AutomaticTypeMapper;
using EOLib.Domain.Character;
using EOLib.Domain.Map;
using EOLib.Net;
using System.Collections.Generic;

Expand All @@ -9,6 +11,10 @@ public interface IUserInterfaceNotifier
void NotifyPacketDialog(PacketFamily packetFamily);

void NotifyMessageDialog(string title, IReadOnlyList<string> messages);

void NotifyCharacterInfo(string name, int mapId, MapCoordinate mapCoords, CharacterStats stats);

void NotifyCharacterInventory(string name, int usage, int gold, IReadOnlyList<InventoryItem> inventory, IReadOnlyList<InventoryItem> bank);
}

[AutoMappedType]
Expand All @@ -17,5 +23,9 @@ public class NoOpUserInterfaceNotifier : IUserInterfaceNotifier
public void NotifyPacketDialog(PacketFamily packetFamily) { }

public void NotifyMessageDialog(string title, IReadOnlyList<string> messages) { }

public void NotifyCharacterInfo(string name, int mapId, MapCoordinate mapCoords, CharacterStats stats) { }

public void NotifyCharacterInventory(string name, int usage, int gold, IReadOnlyList<InventoryItem> inventory, IReadOnlyList<InventoryItem> bank) { }
}
}
42 changes: 42 additions & 0 deletions EOLib/Domain/Report/ReportActions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using AutomaticTypeMapper;
using EOLib.Net;
using EOLib.Net.Communication;

namespace EOLib.Domain.Report
{
[AutoMappedType]
public class ReportActions : IReportActions
{
private readonly IPacketSendService _packetSendService;

public ReportActions(IPacketSendService packetSendService)
{
_packetSendService = packetSendService;
}

public void ReportPlayer(string player, string message)
{
var packet = new PacketBuilder(PacketFamily.AdminInteract, PacketAction.Report)
.AddString(player)
.AddByte(255)
.AddString(message)
.Build();
_packetSendService.SendPacket(packet);
}

public void SpeakToAdmin(string message)
{
var packet = new PacketBuilder(PacketFamily.AdminInteract, PacketAction.Tell)
.AddString(message)
.Build();
_packetSendService.SendPacket(packet);
}
}

public interface IReportActions
{
void ReportPlayer(string player, string message);

void SpeakToAdmin(string message);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ public LoginRequestGrantedData TranslatePacket(IPacket packet)
.WithNewStat(CharacterStat.Intelligence, dispInt)
.WithNewStat(CharacterStat.Wisdom, dispWis)
.WithNewStat(CharacterStat.Agility, dispAgi)
.WithNewStat(CharacterStat.Constituion, dispCon)
.WithNewStat(CharacterStat.Constitution, dispCon)
.WithNewStat(CharacterStat.Charisma, dispCha);

var paperDoll = new Dictionary<EquipLocation, int>();
Expand Down
67 changes: 67 additions & 0 deletions EOLib/PacketHandlers/AdminInteract/AdminInteractList.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using AutomaticTypeMapper;
using EOLib.Domain.Character;
using EOLib.Domain.Login;
using EOLib.Domain.Notifiers;
using EOLib.Net;
using EOLib.Net.Handlers;
using System.Collections.Generic;

namespace EOLib.PacketHandlers.AdminInteract
{
/// <summary>
/// Response to $inventory <character> command.
/// </summary>
[AutoMappedType]
public class AdminInteractList: InGameOnlyPacketHandler
{
private readonly IEnumerable<IUserInterfaceNotifier> _userInterfaceNotifiers;

public override PacketFamily Family => PacketFamily.AdminInteract;

public override PacketAction Action => PacketAction.List;

public AdminInteractList(IPlayerInfoProvider playerInfoProvider,
IEnumerable<IUserInterfaceNotifier> userInterfaceNotifiers)
: base(playerInfoProvider)
{
_userInterfaceNotifiers = userInterfaceNotifiers;
}

public override bool HandlePacket(IPacket packet)
{
var name = packet.ReadBreakString();

var usage = packet.ReadInt();
if (packet.ReadByte() != 255)
return false;

var gold_bank = packet.ReadInt();
if (packet.ReadByte() != 255)
return false;

var inventory = new List<InventoryItem>();
while (packet.PeekByte() != 255)
{
var id = packet.ReadShort();
var amount = packet.ReadInt();
inventory.Add(new InventoryItem(id, amount));
}
packet.ReadByte();

var bank = new List<InventoryItem>();
while (packet.ReadPosition < packet.Length)
{
var id = packet.ReadShort();
var amount = packet.ReadThree();
bank.Add(new InventoryItem(id, amount));
}

foreach (var notifier in _userInterfaceNotifiers)
{
notifier.NotifyCharacterInventory(name, usage, gold_bank, inventory, bank);
}

return true;
}
}
}
55 changes: 55 additions & 0 deletions EOLib/PacketHandlers/AdminInteract/AdminInteractReply.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using AutomaticTypeMapper;
using EOLib.Domain.Chat;
using EOLib.Domain.Login;
using EOLib.Net;
using EOLib.Net.Handlers;

namespace EOLib.PacketHandlers.AdminInteract
{
/// <summary>
/// Received by admins when a report is made by another player.
/// </summary>
[AutoMappedType]
public class AdminInteractReply : InGameOnlyPacketHandler
{
private readonly IChatRepository _chatRepository;

public override PacketFamily Family => PacketFamily.AdminInteract;

public override PacketAction Action => PacketAction.Reply;

public AdminInteractReply(IPlayerInfoProvider playerInfoProvider,
IChatRepository chatRepository)
: base(playerInfoProvider)
{
_chatRepository = chatRepository;
}

public override bool HandlePacket(IPacket packet)
{
var messageType = (AdminMessageType)packet.ReadChar();
packet.ReadByte();

var playerName = packet.ReadBreakString();
var message = packet.ReadBreakString();

ChatData chatData;
switch (messageType)
{
case AdminMessageType.Message:
chatData = new ChatData(ChatTab.Group, playerName, $"needs help: {message}", ChatIcon.Information, ChatColor.ServerGlobal, filter: false);
break;
case AdminMessageType.Report:
var reporteeName = packet.ReadBreakString();
chatData = new ChatData(ChatTab.Group, playerName, $"reports: {reporteeName}, {message}", ChatIcon.Information, ChatColor.ServerGlobal, filter: false);
break;
default:
return false;
}

_chatRepository.AllChat[ChatTab.Group].Add(chatData);

return true;
}
}
}
82 changes: 82 additions & 0 deletions EOLib/PacketHandlers/AdminInteract/AdminInteractTell.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
using AutomaticTypeMapper;
using EOLib.Domain.Character;
using EOLib.Domain.Login;
using EOLib.Domain.Map;
using EOLib.Domain.Notifiers;
using EOLib.Net;
using EOLib.Net.Handlers;
using System.Collections.Generic;

namespace EOLib.PacketHandlers.AdminInteract
{
/// <summary>
/// Response to $info <character> command.
/// </summary>
[AutoMappedType]
public class AdminInteractTell: InGameOnlyPacketHandler
{
private readonly IEnumerable<IUserInterfaceNotifier> _userInterfaceNotifiers;

public override PacketFamily Family => PacketFamily.AdminInteract;

public override PacketAction Action => PacketAction.Tell;

public AdminInteractTell(IPlayerInfoProvider playerInfoProvider,
IEnumerable<IUserInterfaceNotifier> userInterfaceNotifiers)
: base(playerInfoProvider)
{
_userInterfaceNotifiers = userInterfaceNotifiers;
}

public override bool HandlePacket(IPacket packet)
{
var name = packet.ReadBreakString();

var stats = new Dictionary<CharacterStat, int>();
stats[CharacterStat.Usage] = packet.ReadInt();
if (packet.ReadByte() != 255 || packet.ReadByte() != 255)
return false;

stats[CharacterStat.Experience] = packet.ReadInt();
stats[CharacterStat.Level] = packet.ReadChar();

var mapId = packet.ReadShort();
var mapCoords = new MapCoordinate(packet.ReadShort(), packet.ReadShort());

stats[CharacterStat.HP] = packet.ReadShort();
stats[CharacterStat.MaxHP] = packet.ReadShort();
stats[CharacterStat.TP] = packet.ReadShort();
stats[CharacterStat.MaxTP] = packet.ReadShort();

stats[CharacterStat.Strength] = packet.ReadShort();
stats[CharacterStat.Intelligence] = packet.ReadShort();
stats[CharacterStat.Wisdom] = packet.ReadShort();
stats[CharacterStat.Agility] = packet.ReadShort();
stats[CharacterStat.Constitution] = packet.ReadShort();
stats[CharacterStat.Charisma] = packet.ReadShort();

stats[CharacterStat.MaxDam] = packet.ReadShort();
stats[CharacterStat.MinDam] = packet.ReadShort();
stats[CharacterStat.Accuracy] = packet.ReadShort();
stats[CharacterStat.Evade] = packet.ReadShort();
stats[CharacterStat.Armor] = packet.ReadShort();

stats[CharacterStat.Light] = packet.ReadShort();
stats[CharacterStat.Dark] = packet.ReadShort();
stats[CharacterStat.Fire] = packet.ReadShort();
stats[CharacterStat.Water] = packet.ReadShort();
stats[CharacterStat.Earth] = packet.ReadShort();
stats[CharacterStat.Wind] = packet.ReadShort();

stats[CharacterStat.Weight] = packet.ReadChar();
stats[CharacterStat.MaxWeight] = packet.ReadChar();

foreach (var notifier in _userInterfaceNotifiers)
{
notifier.NotifyCharacterInfo(name, mapId, mapCoords, new CharacterStats(stats));
}

return true;
}
}
}
8 changes: 8 additions & 0 deletions EOLib/PacketHandlers/AdminInteract/AdminMessageType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace EOLib.PacketHandlers.AdminInteract
{
public enum AdminMessageType
{
Message = 1,
Report = 2,
}
}
Loading

0 comments on commit 2a35a95

Please sign in to comment.