<commit_before>﻿using System;
using System.Threading;
using Infusion.Packets;
using Infusion.Packets.Both;
using Infusion.Packets.Client;

namespace Infusion.LegacyApi
{
    internal sealed class Targeting
    {
        private readonly UltimaClient client;
        private readonly Legacy legacyApi;
        private readonly AutoResetEvent receivedTargetInfoEvent = new AutoResetEvent(false);
        private readonly UltimaServer server;
        private readonly AutoResetEvent targetFromServerReceivedEvent = new AutoResetEvent(false);
        private bool discardNextTargetLocationRequestIfEmpty;
        private CursorId lastCursorId = new CursorId(0x00000025);
        private ObjectId lastItemIdInfo;

        private string lastTargetInfo;
        private ModelId lastTypeInfo;

        public Targeting(UltimaServer server, UltimaClient client, Legacy legacyApi)
        {
            this.server = server;
            this.client = client;
            this.legacyApi = legacyApi;
            server.Subscribe(PacketDefinitions.TargetCursor, HanldeServerTargetCursorPacket);
            client.RegisterFilter(FilterClientTargetCursorPacket);
        }

        private void HanldeServerTargetCursorPacket(TargetCursorPacket packet)
        {
            targetFromServerReceivedEvent.Set();
            lastCursorId = packet.CursorId;
        }

        private Packet? FilterClientTargetCursorPacket(Packet rawPacket)
        {
            if (rawPacket.Id != PacketDefinitions.TargetCursor.Id)
                return rawPacket;

            var packet = PacketDefinitionRegistry.Materialize<TargetCursorPacket>(rawPacket);

            if (discardNextTargetLocationRequestIfEmpty)
            {
                discardNextTargetLocationRequestIfEmpty = false;
                if (packet.Location.X == 0xFFFF && packet.Location.Y == 0xFFFF &&
                    packet.ClickedOnId.Value == 0)
                {
                    return null;
                }
            }

            if (packet.CursorId == new CursorId(0xDEADBEEF))
            {
                switch (packet.CursorTarget)
                {
                    case CursorTarget.Location:
                        lastTargetInfo =
                            $"{packet.ClickedOnType.Value} {packet.Location.X} {packet.Location.Y} {packet.Location.Z}";
                        break;
                    case CursorTarget.Object:
                        lastTypeInfo = packet.ClickedOnType;
                        lastItemIdInfo = packet.ClickedOnId;
                        var lastItem = legacyApi.GameObjects[lastItemIdInfo];
                        lastTargetInfo = lastItem?.ToString() ??
                                         $"{packet.ClickedOnId} {packet.ClickedOnType} {packet.ClickedOnType}";
                        break;
                }

                receivedTargetInfoEvent.Set();
                return null;
            }

            return rawPacket;
        }

        public void WaitForTarget()
        {
            targetFromServerReceivedEvent.Reset();
            while (!targetFromServerReceivedEvent.WaitOne(TimeSpan.FromSeconds(1)))
            {
                legacyApi.CheckCancellation();
            }
        }

        public string Info()
        {
            receivedTargetInfoEvent.Reset();<commit_msg>Improving target description fallback for ,info command.<commit_after>﻿using System;
using System.Threading;
using Infusion.Packets;
using Infusion.Packets.Both;
using Infusion.Packets.Client;

namespace Infusion.LegacyApi
{
    internal sealed class Targeting
    {
        private readonly UltimaClient client;
        private readonly Legacy legacyApi;
        private readonly AutoResetEvent receivedTargetInfoEvent = new AutoResetEvent(false);
        private readonly UltimaServer server;
        private readonly AutoResetEvent targetFromServerReceivedEvent = new AutoResetEvent(false);
        private bool discardNextTargetLocationRequestIfEmpty;
        private CursorId lastCursorId = new CursorId(0x00000025);
        private ObjectId lastItemIdInfo;

        private string lastTargetInfo;
        private ModelId lastTypeInfo;

        public Targeting(UltimaServer server, UltimaClient client, Legacy legacyApi)
        {
            this.server = server;
            this.client = client;
            this.legacyApi = legacyApi;
            server.Subscribe(PacketDefinitions.TargetCursor, HanldeServerTargetCursorPacket);
            client.RegisterFilter(FilterClientTargetCursorPacket);
        }

        private void HanldeServerTargetCursorPacket(TargetCursorPacket packet)
        {
            targetFromServerReceivedEvent.Set();
            lastCursorId = packet.CursorId;
        }

        private Packet? FilterClientTargetCursorPacket(Packet rawPacket)
        {
            if (rawPacket.Id != PacketDefinitions.TargetCursor.Id)
                return rawPacket;

            var packet = PacketDefinitionRegistry.Materialize<TargetCursorPacket>(rawPacket);

            if (discardNextTargetLocationRequestIfEmpty)
            {
                discardNextTargetLocationRequestIfEmpty = false;
                if (packet.Location.X == 0xFFFF && packet.Location.Y == 0xFFFF &&
                    packet.ClickedOnId.Value == 0)
                {
                    return null;
                }
            }

            if (packet.CursorId == new CursorId(0xDEADBEEF))
            {
                switch (packet.CursorTarget)
                {
                    case CursorTarget.Location:
                        lastTargetInfo =
                            $"{packet.ClickedOnType.Value} {packet.Location.X} {packet.Location.Y} {packet.Location.Z}";
                        break;
                    case CursorTarget.Object:
                        lastTypeInfo = packet.ClickedOnType;
                        lastItemIdInfo = packet.ClickedOnId;
                        var lastObject = legacyApi.GameObjects[lastItemIdInfo];
                        lastTargetInfo = lastObject?.ToString() ??
                                         $"{packet.ClickedOnId} {packet.ClickedOnType}";
                        break;
                }

                receivedTargetInfoEvent.Set();
                return null;
            }

            return rawPacket;
        }

        public void WaitForTarget()
        {
            targetFromServerReceivedEvent.Reset();
            while (!targetFromServerReceivedEvent.WaitOne(TimeSpan.FromSeconds(1)))
            {
                legacyApi.CheckCancellation();
            }
        }

        public string Info()
        {
            receivedTargetInfoEvent.Reset();
{'fraction_non_alphanumeric': 0.06799163179916318, 'fraction_numerical': 0.0041841004184100415, 'mean_word_length': 1.7841098169717138, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6177392', 'n_tokens_mistral': 1623, 'n_tokens_neox': 1523, 'n_words': 304}