XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

DeathMod

【Terraria】DeathMod (now aka Soul Harvest)

公开
关注 0 Fork 0 Star 0
UTF-8
using Microsoft.Xna.Framework;
using System;
using Terraria;
using Terraria.ID;

namespace SoulHarvest.Common;


/// <summary>
/// Holds a server movement destination until the owning client confirms the
/// sequenced correction. TCP ordering guarantees every pre-dash vanilla controls
/// packet is processed before that acknowledgement; confirmation reapplies the
/// destination once, then releases normal owner movement immediately.
/// </summary>
internal sealed class ReaperMovementAuthorityPlayer : Terraria.ModLoader.ModPlayer
{
    private uint nextSequence;
    private uint activeSequence;
    private Vector2 authoritativePosition;
    private Vector2 authoritativeVelocity;
    private int lockFrames;

    public override void Initialize()
    {
        nextSequence = 0;
        ClearMovementLock();
    }

    internal void BeginAuthoritativeMovement(Vector2 position, Vector2 velocity)
    {
        if (Main.netMode != NetmodeID.Server)
            return;
        nextSequence++;
        if (nextSequence == 0)
            nextSequence++;
        activeSequence = nextSequence;
        authoritativePosition = position;
        authoritativeVelocity = velocity;
        lockFrames = 60;
        ApplyDestination();
        SoulHarvest.BroadcastReaperMovement(Player, activeSequence);
    }

    internal void ConfirmAuthoritativeMovement(uint sequence)
    {
        if (Main.netMode != NetmodeID.Server || lockFrames <= 0 || sequence != activeSequence)
            return;

        // Reapply after all older owner packets, then send an acknowledgement-free
        // final correction so every observer converges on the same landing point.
        ApplyDestination();
        ClearMovementLock();
        SoulHarvest.BroadcastReaperMovement(Player, sequence: 0);
    }

    public override void PostUpdate()
    {
        if (Main.netMode != NetmodeID.Server || lockFrames <= 0)
            return;
        if (!Player.active || Player.dead)
        {
            ClearMovementLock();
            return;
        }

        ApplyDestination();
        lockFrames--;
        if (lockFrames <= 0)
            SoulHarvest.BroadcastReaperMovement(Player, sequence: 0);
    }

    private void ApplyDestination()
    {
        Player.position = authoritativePosition;
        Player.velocity = authoritativeVelocity;
    }

    private void ClearMovementLock()
    {
        activeSequence = 0;
        authoritativePosition = Vector2.Zero;
        authoritativeVelocity = Vector2.Zero;
        lockFrames = 0;
    }
}