Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Botbases/RSBot.Training/Bundle/Buff/BuffBundle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ var buff in SkillManager.Buffs.Union(new[] { SkillManager.ImbueSkill, SkillManag
//#377 bug detected!
Log.Notify($"[#377] The buff [{buff.Token}-{buff.Record?.GetRealName()}] expired");

EventManager.FireEvent("OnRemoveBuff", buff);
EventManager.FireEvent("OnRemoveBuff", info);

var playerSkill = Game.Player.Skills.GetSkillInfoById(buff.Id);
var playerSkill = Game.Player.Skills.GetSkillInfoById(info.Id);
playerSkill?.Reset();
Game.Player.State.TryRemoveActiveBuff(info.Token, out _);
}
Expand Down
64 changes: 43 additions & 21 deletions Library/RSBot.Core/Components/SkillManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -439,42 +439,64 @@ public static void CastBuff(SkillInfo skill, uint target = 0, bool awaitBuffResp
packet.WriteByte(ActionTarget.None);
}

var asyncCallback = new AwaitCallback(
var castCallback = new AwaitCallback(
response =>
{
var targetId = response.ReadUInt();
var castedSkillId = response.ReadUInt();
var result = response.ReadByte();

if (targetId == (target == 0 ? Game.Player.UniqueId : target) && castedSkillId == skill.Id)
return AwaitCallbackResult.Success;
if (result != 0x01)
return AwaitCallbackResult.Fail;

return AwaitCallbackResult.ConditionFailed;
var action = Objects.Action.DeserializeBegin(response);

return action.PlayerIsExecutor && action.SkillId == skill.Id
? AwaitCallbackResult.Success
: AwaitCallbackResult.ConditionFailed;
},
0xB0BD
0xB070
);

var callback = new AwaitCallback(
var actionStateCallback = new AwaitCallback(
response =>
{
return response.ReadByte() == 0x02 && response.ReadByte() == 0x00
? AwaitCallbackResult.Success
: AwaitCallbackResult.ConditionFailed;
var state = response.ReadByte();
var recurring = response.ReadByte();

if (state == 0x02 && recurring == 0x00)
return AwaitCallbackResult.Success;

if (state == 0x03)
return AwaitCallbackResult.Fail;

return AwaitCallbackResult.ConditionFailed;
},
0xB074
);

PacketManager.SendPacket(packet, PacketDestination.Server, asyncCallback, callback);
if (!awaitBuffResponse)
{
PacketManager.SendPacket(packet, PacketDestination.Server);
return;
}

if (awaitBuffResponse)
asyncCallback.AwaitResponse(
skill.Record.Action_CastingTime
+ skill.Record.Action_ActionDuration
+ skill.Record.Action_PreparingTime
+ 1500
);
if (skill.Record.Basic_Activity != 1)
PacketManager.SendPacket(packet, PacketDestination.Server, castCallback, actionStateCallback);
else
PacketManager.SendPacket(packet, PacketDestination.Server, castCallback);

var timeout =
skill.Record.Action_CastingTime
+ skill.Record.Action_ActionDuration
+ skill.Record.Action_PreparingTime
+ 1500;

castCallback.AwaitResponse(timeout);

if (skill.Record.Basic_Activity != 1 && awaitBuffResponse)
callback.AwaitResponse();
if (!castCallback.IsCompleted)
return;

if (skill.Record.Basic_Activity != 1)
actionStateCallback.AwaitResponse(timeout);
Comment on lines +487 to +499

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Keep a single timeout budget for the full cast lifecycle.

timeout already models the whole cast window. Reusing that full value for actionStateCallback.AwaitResponse(...) can block almost 2× that budget when the 0xB070 response arrives late, which slows the non-basic buff path and attack loop. Carry a deadline forward and wait only on the remaining time for the second callback.

⏱️ Proposed fix
         var timeout =
             skill.Record.Action_CastingTime
             + skill.Record.Action_ActionDuration
             + skill.Record.Action_PreparingTime
             + 1500;
+        var deadline = Environment.TickCount64 + timeout;
 
         castCallback.AwaitResponse(timeout);
 
         if (!castCallback.IsCompleted)
             return;
 
         if (skill.Record.Basic_Activity != 1)
-            actionStateCallback.AwaitResponse(timeout);
+        {
+            var remaining = (int)Math.Max(0L, deadline - Environment.TickCount64);
+            actionStateCallback.AwaitResponse(remaining);
+        }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
var timeout =
skill.Record.Action_CastingTime
+ skill.Record.Action_ActionDuration
+ skill.Record.Action_PreparingTime
+ 1500;
castCallback.AwaitResponse(timeout);
if (skill.Record.Basic_Activity != 1 && awaitBuffResponse)
callback.AwaitResponse();
if (!castCallback.IsCompleted)
return;
if (skill.Record.Basic_Activity != 1)
actionStateCallback.AwaitResponse(timeout);
var timeout =
skill.Record.Action_CastingTime
skill.Record.Action_ActionDuration
skill.Record.Action_PreparingTime
1500;
var deadline = Environment.TickCount64 + timeout;
castCallback.AwaitResponse(timeout);
if (!castCallback.IsCompleted)
return;
if (skill.Record.Basic_Activity != 1)
{
var remaining = (int)Math.Max(0L, deadline - Environment.TickCount64);
actionStateCallback.AwaitResponse(remaining);
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Library/RSBot.Core/Components/SkillManager.cs` around lines 487 - 499, The
current code reuses the full timeout for both castCallback.AwaitResponse and
actionStateCallback.AwaitResponse, effectively doubling the allowed wait; change
to compute a single deadline (e.g., now + timeout) before calling
castCallback.AwaitResponse, then after castCallback returns compute the
remaining time (deadline - now) and pass only that remaining timeout to
actionStateCallback.AwaitResponse (and return immediately if remaining <= 0);
reference the existing symbols castCallback, actionStateCallback, AwaitResponse,
IsCompleted, and the timeout calculation using
skill.Record.Action_CastingTime/Action_ActionDuration/Action_PreparingTime to
implement this.

}

/// <summary>
Expand Down
38 changes: 21 additions & 17 deletions Library/RSBot.Core/Network/Socket/Server.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
using System;
using System.Net;
using System.Net.Sockets;
using RSBot.Core.Event;
using RSBot.Core.Event;
using RSBot.Core.Extensions;
using RSBot.Core.Network.Protocol;
using System;
using System.Net;
using System.Net.Sockets;

namespace RSBot.Core.Network;

public class Server : NetBase
{
private bool _receivedInitialHandshake;
private bool _receivedPostInitialHandshakePacket;

/// <summary>
/// Gets or sets the ip.
/// </summary>
Expand Down Expand Up @@ -42,6 +45,8 @@ public void Connect(string ip, ushort port)
{
_protocol = new SecurityProtocol();
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_receivedInitialHandshake = false;
_receivedPostInitialHandshakePacket = false;

try
{
Expand All @@ -62,7 +67,7 @@ public void Connect(string ip, ushort port)
{
_socket.Connect(ip, port, 3000);
}
}
}
catch (AggregateException s)
{
Log.Error(s.Message);
Expand Down Expand Up @@ -111,26 +116,26 @@ private void OnBeginReceiveCallback(IAsyncResult ar)
try
{
receivedSize = _socket.EndReceive(ar, out var error);
var rawOpcode = receivedSize >= 4 ? $"0x{BitConverter.ToUInt16(_buffer, 2):X4}" : "n/a";

if (receivedSize == 0 || error != SocketError.Success)
{
Log.Debug($"Socket closed: receivedSize={receivedSize}, error={error}");
if (_socket != null)
{
try
{
Log.Debug($"Socket.Connected={_socket.Connected}, LocalEndPoint={_socket.LocalEndPoint}, RemoteEndPoint={_socket.RemoteEndPoint}");
}
catch { }
}
if (!IsClosing && EnablePacketDispatcher && _receivedInitialHandshake && !_receivedPostInitialHandshakePacket)
Log.Notify("Gateway closed immediately after initial 0x5000 before handshake completed. Possible IP/session limit");

OnDisconnected();
return;
}

if (!_receivedInitialHandshake && rawOpcode == "0x5000")
_receivedInitialHandshake = true;
else if (_receivedInitialHandshake)
_receivedPostInitialHandshakePacket = true;

_protocol.Recv(_buffer, 0, receivedSize);
}
catch (SocketException se)
{
Log.Debug($"SocketException: Code={se.SocketErrorCode}, NativeErrorCode={se.NativeErrorCode}, Message={se.Message}");
if (se.SocketErrorCode == SocketError.ConnectionReset) //Client OnDisconnected > Mostly occurs during GW->AS switch
OnDisconnected();
}
Expand All @@ -146,9 +151,8 @@ private void OnBeginReceiveCallback(IAsyncResult ar)
if (receivedSize != 0 && _socket != null && _socket.Connected)
_socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, OnBeginReceiveCallback, null);
}
catch (Exception ex)
catch
{
Log.Debug($"Exception in BeginReceive: {ex.Message}");
OnDisconnected();
}
}
Expand Down
22 changes: 16 additions & 6 deletions Plugins/RSBot.Party/Bundle/AutoParty/AutoPartyBundle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,16 @@ public AutoPartyBundle()
/// </value>
public AutoPartyConfig Config { get; set; }

private void ApplyPartySettingsFromConfig()
{
if (!Game.Party.IsInParty)
Game.Party.Settings = new PartySettings(
Config.ExperienceAutoShare,
Config.ItemAutoShare,
Config.AllowInvitations
);
}

/// <summary>
/// Refreshes this instance.
/// </summary>
Expand Down Expand Up @@ -70,12 +80,7 @@ public void Refresh()
AlwaysFollowThePartyMaster = PlayerConfig.Get("RSBot.Party.AlwaysFollowPartyMaster", false),
};

if (!Game.Party.IsInParty)
Game.Party.Settings = new PartySettings(
Config.ExperienceAutoShare,
Config.ItemAutoShare,
Config.AllowInvitations
);
ApplyPartySettingsFromConfig();
}

public void OnTick()
Expand Down Expand Up @@ -154,6 +159,9 @@ private void CheckForAutoPartyJoin()
/// </summary>
public void CheckForPlayers()
{
if (Config == null)
return;

if (
Game.Party.IsInParty
&& !Game.Party.IsLeader
Expand All @@ -163,6 +171,8 @@ public void CheckForPlayers()
if (Config.LeaveIfMasterNotName != Game.Party.Leader.Name)
Game.Party.Leave();

ApplyPartySettingsFromConfig();

if (!Game.Party.CanInvite || Game.Party.Settings == null)
return;

Expand Down
2 changes: 1 addition & 1 deletion Plugins/RSBot.Skills/Views/Main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,7 @@ private void OnRemoveBuff(SkillInfo removingBuff)
var itemBuffInfo = listItem.Tag as SkillInfo;
if (
itemBuffInfo != null
&& itemBuffInfo.Id == removingBuff.Id
/*&& itemBuffInfo.Id == removingBuff.Id*/
&& itemBuffInfo.Token == removingBuff.Token
)
{
Expand Down
Loading