modernuo/Projects/Server/Network/Packets/OutgoingMovementPackets.cs
Kamron Batman 146abad36e
feat: Adds a movement throttle system. Removes Fastwalk system. (#1511)
### Summary

- Removes Fastwalk system
  - Removed the following settings:
    - `movement.enableFastWalkPrevention`
    - `movement.fastwalkExemptionLevel`
- Adds movement throttle system.
  - Adds the following settings:
    - `movement.throttleReset` - Default value is `1000` (1 second).
    - `movement.throttleThreshold` - Default value is `400` (400ms).

### Movement Throttling

This new system will trigger if a player requests 400ms (configurable) worth of movements quicker than wall clock time. When this happens, the player is throttled (all incoming packets to the server are halted) until wall clock time catches up with the requests. Upon each throttle, the player receives enough credit to handle up to 400ms of "lag" as a grace/catch-up.


### Developer Notes
We use two throttle queues to prevent an infinite loop.
2023-09-27 20:53:22 -07:00

79 lines
2.9 KiB
C#

/*************************************************************************
* ModernUO *
* Copyright 2019-2023 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: OutgoingMovementPackets.cs *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/
using System.Buffers;
using System.Runtime.CompilerServices;
namespace Server.Network;
public enum SpeedControlSetting
{
Disable,
Mount,
Walk
}
public static class OutgoingMovementPackets
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SendSpeedControl(this NetState ns, SpeedControlSetting speedControl) =>
ns?.Send(stackalloc byte[] { 0xBF, 0x00, 0x6, 0x00, 0x26, (byte)speedControl });
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SendMovePlayer(this NetState ns, Direction d) => ns?.Send(stackalloc byte[] { 0x97, (byte)d });
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SendMovementAck(this NetState ns, int seq, Mobile m) =>
ns.SendMovementAck(seq, Notoriety.Compute(m, m));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SendMovementAck(this NetState ns, int seq, int noto) =>
ns?.Send(stackalloc byte[] { 0x22, (byte)seq, (byte)noto });
public static void SendMovementRej(this NetState ns, int seq, Mobile m)
{
if (ns.CannotSendPackets())
{
return;
}
var writer = new SpanWriter(stackalloc byte[8]);
writer.Write((byte)0x21); // Packet ID
writer.Write((byte)seq);
writer.Write((short)m.X);
writer.Write((short)m.Y);
writer.Write((byte)m.Direction);
writer.Write((sbyte)m.Z);
ns.Send(writer.Span);
}
public static void SendTimeSyncResponse(this NetState ns)
{
if (ns.CannotSendPackets())
{
return;
}
var writer = new SpanWriter(stackalloc byte[25]);
writer.Write((byte)0xF2); // Packet ID
writer.Write(Core.TickCount); // ??
writer.Write(Core.TickCount); // ??
writer.Write(Core.TickCount); // ??
ns.Send(writer.Span);
}
}