Skip to content

Instantly share code, notes, and snippets.

@Jadd
Created January 11, 2019 08:23
Show Gist options
  • Save Jadd/29b8b3cf8a82577ccad7d852a1d06ff6 to your computer and use it in GitHub Desktop.
Save Jadd/29b8b3cf8a82577ccad7d852a1d06ff6 to your computer and use it in GitHub Desktop.
Packet tools for Albion Online
using System;
using Albion.Common.Photon;
using Afterglow.Internal.Client.Objects;
using Afterglow.Internal.Memory;
using Afterglow.Internal.Runtime;
using ExitGames.Client.Photon;
using UnityEngine;
namespace Afterglow.Internal.Client {
public enum PacketType {
OperationRequest,
OperationResponse,
Event
}
public enum PacketConnectionType {
Login,
Game,
Chat
}
[Flags]
public enum PacketFlags {
None = 0,
Discard = 1 << 0
}
public static class Packet {
#region Properties
public static FilteredPacketLog Log { get; private set; }
public static PacketBlocker Blocker { get; private set; }
#endregion
internal static void Initialize() {
// Create the default packet logger instance.
Log = new FilteredPacketLog();
Log.Hide(OperationCodes.Move);
Log.Hide(PacketType.Event, 2); // Heartbeat.
Log.Hide(PacketType.Event, 60); // Chat.
// Create the default packet blocker instance.
Blocker = new PacketBlocker();
Blocker.Add(OperationCodes.ReportClientError);
Blocker.Add(OperationCodes.SendCrashLog);
#if PRIVATE
// Register default packet logger events.
Log.OperationAddFiltered += (log, opcode) => Chat.WriteLine(MessageType.Normal, $"Started hiding {opcode}!");
Log.OperationRemoveFiltered += (log, opcode) => Chat.WriteLine(MessageType.Normal, $"Stopped hiding {opcode}!");
// Register the default packet logger commands.
Chat.Commands["hide"] = OnLogHideCommand;
Chat.Commands["show"] = OnLogShowCommand;
// Register default packet blocker events.
Blocker.AddBlocked += (blocker, opcode) => Chat.WriteLine(MessageType.Normal, $"Started blocking {opcode}!");
Blocker.RemoveBlocked += (blocker, opcode) => Chat.WriteLine(MessageType.Normal, $"Stopped blocking {opcode}!");
Blocker.PacketBlocked += (blocker, opcode) => Chat.WriteLine(MessageType.Warning, $"Blocked a \"{opcode}\" packet!");
// Register the default packet blocker commands.
Chat.Commands["lookup"] = OnLookupCommand;
Chat.Commands["block"] = OnBlockCommand;
Chat.Commands["unblock"] = OnUnblockCommand;
#endif
// Register the packet handlers.
PacketHandler.Register(1000, Blocker);
PacketHandler.Register(2000, Log);
}
#if PRIVATE
private static void OnLogHideCommand(string command, string[] args) {
if (args.Length < 2)
throw new ChatUsageException(command, "\"searchString\"");
Log.Hide(args[1]);
}
private static void OnLogShowCommand(string command, string[] args) {
if (args.Length < 2)
throw new ChatUsageException(command, "\"searchString\"");
Log.Show(args[1]);
}
private static void OnLookupCommand(string command, string[] args) {
if (args.Length < 2)
throw new ChatUsageException(command, "\"searchString\"");
var results = PacketHandler.GetOpcodes(args[1]);
Chat.WriteLine(MessageType.Normal, $"Searching for opcodes containing \"{args[1]}\"...");
foreach (var opcode in results)
Chat.WriteLine(MessageType.Normal, $"Found opcode: \"{opcode}\"");
}
private static void OnBlockCommand(string command, string[] args) {
if (args.Length < 2)
throw new ChatUsageException(command, "opcode");
Blocker.Add(args[1]);
}
private static void OnUnblockCommand(string command, string[] args) {
if (args.Length < 2)
throw new ChatUsageException(command, "opcode");
Blocker.Remove(args[1]);
}
private static bool IsPacketFiltered(PacketInfo packet) {
// Heartbeat packets. Get sent at a very high rate.
if (packet.Type == PacketType.Event && packet.Opcode == 2)
return true;
// Chat packets. Annoying...
if (packet.Type == PacketType.Event && packet.Opcode == 60)
return true;
return false;
}
#endif
#region Detours
[DetourMethod("Albion.PhotonClient", "AlbionPeer.SendOperationRequest_0")]
private static bool AlbionPeer_OnSendOperationRequest(ap3 connection, lc request, bool reliable) {
var opcode = request.GetAttribute<afo>().b();
var packet = new PacketInfo(connection, request, opcode);
PacketHandler.DispatchPacket(packet);
if (packet.IsDiscarded)
return false;
using (Detour.Current.Disabler)
return connection.e(request, reliable);
}
[DetourMethod("Albion.PhotonClient", "AlbionPeer.SendOperationRequest_1")]
private static bool AlbionPeer_OnSendOperationRequest(ap3 connection, lc request, Action<OperationResponse> callback, bool reliable) {
var opcode = request.GetAttribute<afo>().b();
var packet = new PacketInfo(connection, request, opcode);
PacketHandler.DispatchPacket(packet);
if (packet.IsDiscarded)
return false;
using (Detour.Current.Disabler)
return connection.e(request, callback, reliable);
}
[DetourMethod("Albion.PhotonClient", "AlbionPeer.OnOperationResponse")]
private static void AlbionPeer_OnOperationResponse(ap3 connection, OperationResponse response) {
var opcode = (short) response.Parameters[253];
var packet = new PacketInfo(connection, response, opcode);
PacketHandler.DispatchPacket(packet);
if (packet.IsDiscarded)
return;
if (packet.DebugText != null)
Chat.WriteLine(MessageType.Debug, packet.DebugText);
using (Detour.Current.Disabler)
connection.OnOperationResponse(response);
}
[DetourMethod("Albion.PhotonClient", "AlbionPeer.OnEvent")]
private static void AlbionPeer_OnEvent(ap3 connection, EventData @event) {
var opcode = @event.Code == 2 ? (short) 2 : (short) @event.Parameters[252];
var packet = new PacketInfo(connection, @event, opcode);
PacketHandler.DispatchPacket(packet);
if (packet.IsDiscarded)
return;
using (Detour.Current.Disabler)
connection.OnEvent(@event);
}
[DetourMethod("Albion.PhotonClient", "AlbionPeer.OnStatusChanged")]
private static void AlbionPeer_OnStatusChanged(ap3 connection, StatusCode status) {
Debug.Log($"{Connection.GetConnectionType(connection)}.OnStatusChanged: {status}");
using (Detour.Current.Disabler)
connection.OnStatusChanged(status);
}
#endregion
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment