Jump to content
  • 0

[Help] Rubber-banding on slopes with high movement speed (2.0x+) - Even with AntiHack disabled


Question

Posted (edited)

Hi, I'm running a PvE Rust server.
I am currently Vibe Coding with Gemini to create a custom plugin based on the logic from the existing `MovementSpeed` plugin.
*(Note: This is for my personal server use only, not for sale.)*

The Problem:
I implemented a component to increase player movement speed.
It works perfectly on flat terrain. However, when a player with high speed (e.g., 2.0x multiplier) runs up slopes or hills, they experience severe rubber-banding (getting pulled back to previous position).

[My Environment]

* This is a PvE server.
* I have already disabled most server-side anti-cheat convars (e.g., `server.secure 0`, `antihack.flyhack_protection 0`, `antihack.speedhack_protection 0`, etc.).
* Even with these settings, the physics engine seems to reject the movement on steep slopes.

Crucially, this issue DOES NOT happen to Admins.

* Admins: Can run up slopes at 2.0x speed smoothly without any issues.
* Regular Players: Get rubber-banded / lag-backed immediately when running up slopes.

What I've tried:
Gemini and I tried to bypass this by:

1. Pausing FlyHack/SpeedHack detection (`player.PauseFlyHackDetection`).
2. Resetting `speedhackDistance` every frame.
3. Updating `lastAdminCheatTime` to `UnityEngine.Time.time` every frame (to trick the server into thinking an admin command was used).
4. Clamping the Y velocity in `FixedUpdate`.

Despite these efforts, regular players still suffer from rubber-banding on slopes.

Here is the logic I'm currently testing:

Quote

```csharp
public class CardSpeedController : FacepunchBehaviour
{
    public BasePlayer player;
    public float Interval = 0.05f; 
    private float NextUpdate; 

    public float CardBonusPct = 0f;      
    public float ExternalMultiplier = 1.0f; 
    public float CurrentRunVelocity; 

    private bool applied;
    private bool Paused;

    public bool runEnabled = true;
    public bool allowWounded = false;
    public bool alwaysRunning = false;
    public bool allowCrouching = true;

    void Awake()
    {
        player = GetComponent<BasePlayer>();
        // Initialization
        player.PauseSpeedHackDetection(float.MaxValue);
        player.PauseFlyHackDetection(float.MaxValue);
        player.ResetAntiHack();
        
        NextUpdate = Time.time + Interval;
    }

    public void UpdateVelocity()
    {
        float baseSpeed = 5.5f;
        float multiplier = 1.0f + CardBonusPct;
        float finalSpeed = (baseSpeed * multiplier) * ExternalMultiplier;
        CurrentRunVelocity = Mathf.Max(0, finalSpeed - baseSpeed);
    }

    void FixedUpdate()
    {
        if (player == null || !player.IsConnected || player.IsSleeping()) return;
        
        if (Time.time < NextUpdate) return;
        NextUpdate = Time.time + Interval;

        if (CurrentRunVelocity <= 0.01f) return;

        if (Paused || !IsPlayerMoving(player, out var direction, out var velocity) || (!allowWounded && player.IsCrawling()) || (!allowCrouching && player.IsDucked()))
        {
            if (applied)
            {
                player.ApplyInheritedVelocity(Vector3.zero);
                applied = false;
            }
            return;
        }

        applied = true;
        player.ApplyInheritedVelocity(direction * velocity);
        
        // --- Anti-Cheat Bypass Attempts ---
        player.speedhackPauseTime = 0f;
        player.speedhackDistance = 0f;
        
        // Trick the server: "This player just used an admin move command"
        player.lastAdminCheatTime = UnityEngine.Time.time; 
        
        // Force pause flyhack for this frame
        player.PauseFlyHackDetection(1.0f);
    }

    private bool IsMovingFoward()
    {
        return player.serverInput.IsDown(BUTTON.FORWARD) &&
                (!player.serverInput.IsDown(BUTTON.BACKWARD) &&
                 !player.serverInput.IsDown(BUTTON.LEFT) &&
                 !player.serverInput.IsDown(BUTTON.RIGHT));
    }

    private bool IsPlayerMoving(BasePlayer player, out Vector3 direction, out float velocity)
    {
        velocity = 0;
        if ((!alwaysRunning && !player.serverInput.IsDown(BUTTON.SPRINT)) || !IsMovingFoward() || player.isMounted || player.IsFlying)
        {
            direction = Vector3.zero;
            return false;
        }

        if (player.IsSwimming())
        {
            direction = player.eyes.BodyForward();
            velocity = CurrentRunVelocity;
            return true;
        }
        
        direction = player.eyes.HeadForward();
        // Clamping Y to prevent flyhack on slopes
        direction.y = Mathf.Clamp(direction.y, -0.3f, 0.3f); 
        
        velocity = CurrentRunVelocity;
        return true;
    }
}

```
 

Is there any other server-side check that restricts player movement on slopes (specifically for non-admins)? Or am I missing something in the physics calculation?

Any advice would be greatly appreciated. Thank you!

Edited by MooDDang

0 answers to this question

Recommended Posts

There have been no answers to this question yet

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
2.1m

Downloads

Total number of downloads.

10k

Customers

Total customers served.

145.4k

Files Sold

Total number of files sold.

3.1m

Payments Processed

Total payments processed.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.