Keeps the repo root clean - only README.md visible on landing page. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
140 lines
3.1 KiB
C#
140 lines
3.1 KiB
C#
using System;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
|
|
IEntity? targetUser = null;
|
|
CancellationTokenSource? followCts = null;
|
|
string initialTargetUsername = "Dengat";
|
|
|
|
async Task FollowLoop(IEntity userToFollow, CancellationToken cancellationToken)
|
|
{
|
|
targetUser = userToFollow;
|
|
|
|
|
|
while (!cancellationToken.IsCancellationRequested)
|
|
{
|
|
IEntity? currentTargetState = null;
|
|
try
|
|
{
|
|
currentTargetState = Users.FirstOrDefault(u => u.Id == userToFollow.Id);
|
|
|
|
if (currentTargetState == null || cancellationToken.IsCancellationRequested)
|
|
{
|
|
break;
|
|
}
|
|
|
|
int targetX = currentTargetState.Location.X;
|
|
int targetY = currentTargetState.Location.Y;
|
|
|
|
Move(targetX, targetY);
|
|
|
|
await Task.Delay(500, cancellationToken);
|
|
}
|
|
catch (OperationCanceledException)
|
|
{
|
|
break;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log($"FollowLoop: Error following {userToFollow?.Name ?? "Unknown"}: {ex.Message}");
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
if (ReferenceEquals(targetUser, userToFollow))
|
|
{
|
|
targetUser = null;
|
|
}
|
|
}
|
|
|
|
void StopFollowing()
|
|
{
|
|
if (followCts != null)
|
|
{
|
|
try
|
|
{
|
|
if (!followCts.IsCancellationRequested)
|
|
{
|
|
followCts.Cancel();
|
|
}
|
|
}
|
|
catch (ObjectDisposedException)
|
|
{
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log($"StopFollowing: Error during Cancel: {ex.Message}");
|
|
}
|
|
|
|
try
|
|
{
|
|
followCts.Dispose();
|
|
}
|
|
catch (ObjectDisposedException)
|
|
{
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log($"StopFollowing: Error during Dispose: {ex.Message}");
|
|
}
|
|
finally
|
|
{
|
|
followCts = null;
|
|
}
|
|
}
|
|
targetUser = null;
|
|
}
|
|
|
|
async Task StartFollowing(string targetName)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(targetName) || targetName.Equals(Self.Name, StringComparison.OrdinalIgnoreCase)) {
|
|
return;
|
|
}
|
|
|
|
var userToFollow = Users.FirstOrDefault(u => u.Name.Equals(targetName, StringComparison.OrdinalIgnoreCase));
|
|
|
|
if (userToFollow != null)
|
|
{
|
|
StopFollowing();
|
|
|
|
followCts = new CancellationTokenSource();
|
|
CancellationToken token = followCts.Token;
|
|
|
|
_ = Task.Run(() => FollowLoop(userToFollow, token), token);
|
|
}
|
|
else
|
|
{
|
|
Log($"StartFollowing: User '{targetName}' not found.");
|
|
}
|
|
}
|
|
|
|
OnChat(async e =>
|
|
{
|
|
string message = e.Message.Trim();
|
|
string[] parts = message.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
|
if (parts.Length == 0) return;
|
|
|
|
string command = parts[0].ToLowerInvariant();
|
|
|
|
if (command == "+followstop")
|
|
{
|
|
StopFollowing();
|
|
}
|
|
});
|
|
|
|
OnIntercept(In["UserRemove"], e => {
|
|
int userIndexLeaving = e.Packet.ReadInt();
|
|
if (targetUser != null && targetUser.Index == userIndexLeaving)
|
|
{
|
|
StopFollowing();
|
|
}
|
|
});
|
|
|
|
Task.Run(async () => {
|
|
await Task.Delay(2000);
|
|
await StartFollowing(initialTargetUsername);
|
|
});
|
|
|
|
Wait(); |