190 - Server-Side Rewind for Shotguns

This commit is contained in:
Kingsmedia 2022-05-27 19:13:59 +02:00
parent de7d73125b
commit eec38a37db
2 changed files with 102 additions and 36 deletions

View File

@ -36,12 +36,37 @@ void ULagCompensationComponent::ServerScoreRequest_Implementation(ABlasterCharac
} }
} }
void ULagCompensationComponent::SaveFramePackage()
{
if (Character == nullptr || !Character->HasAuthority()) return;
if (FrameHistory.Num() <= 1)
{
FFramePackage ThisFrame;
SaveFramePackage(ThisFrame);
FrameHistory.AddHead(ThisFrame);
}
else
{
float HistoryLength = FrameHistory.GetHead()->GetValue().Time - FrameHistory.GetTail()->GetValue().Time;
while (HistoryLength > MaxRecordTime)
{
FrameHistory.RemoveNode(FrameHistory.GetTail());
HistoryLength = FrameHistory.GetHead()->GetValue().Time - FrameHistory.GetTail()->GetValue().Time;
}
FFramePackage ThisFrame;
SaveFramePackage(ThisFrame);
FrameHistory.AddHead(ThisFrame);
// ShowFramePackage(ThisFrame, FColor::Red);
}
}
void ULagCompensationComponent::SaveFramePackage(FFramePackage& Package) void ULagCompensationComponent::SaveFramePackage(FFramePackage& Package)
{ {
Character = Character == nullptr ? Cast<ABlasterCharacter>(GetOwner()) : Character; Character = Character == nullptr ? Cast<ABlasterCharacter>(GetOwner()) : Character;
if (Character) if (Character)
{ {
Package.Time = GetWorld()->GetTimeSeconds(); Package.Time = GetWorld()->GetTimeSeconds();
Package.Character = Character;
for (auto& BoxPair : Character->HitCollisionBoxes) for (auto& BoxPair : Character->HitCollisionBoxes)
{ {
FBoxInformation BoxInformation; FBoxInformation BoxInformation;
@ -210,13 +235,37 @@ void ULagCompensationComponent::ShowFramePackage(const FFramePackage& Package, c
FServerSideRewindResult ULagCompensationComponent::ServerSideRewind(ABlasterCharacter* HitCharacter, const FVector_NetQuantize& TraceStart, const FVector_NetQuantize& HitLocation, FServerSideRewindResult ULagCompensationComponent::ServerSideRewind(ABlasterCharacter* HitCharacter, const FVector_NetQuantize& TraceStart, const FVector_NetQuantize& HitLocation,
float HitTime) float HitTime)
{
const FFramePackage FrameToCheck = GetFrameToCheck(HitCharacter, HitTime);
return ConfirmHit(FrameToCheck, HitCharacter, TraceStart, HitLocation);
}
FShotgunServerSideRewindResult ULagCompensationComponent::ShotgunServerSideRewind(const TArray<ABlasterCharacter*>& HitCharacters,
const FVector_NetQuantize& TraceStart, const TArray<FVector_NetQuantize>& HitLocations, float HitTime)
{
TArray<FFramePackage> FramesToCheck;
for (ABlasterCharacter* HitCharacter : HitCharacters)
{
FramesToCheck.Add(GetFrameToCheck(HitCharacter, HitTime));
}
return FShotgunServerSideRewindResult();
}
FShotgunServerSideRewindResult ULagCompensationComponent::ShotgunConfirmHit(const TArray<FFramePackage>& FramePackages,
const FVector_NetQuantize& TraceStart, const TArray<FVector_NetQuantize>& HitLocations)
{
}
FFramePackage ULagCompensationComponent::GetFrameToCheck(ABlasterCharacter* HitCharacter, float HitTime)
{ {
bool bReturn = HitCharacter == nullptr || bool bReturn = HitCharacter == nullptr ||
HitCharacter->GetLagCompensation() == nullptr || HitCharacter->GetLagCompensation() == nullptr ||
HitCharacter->GetLagCompensation()->FrameHistory.GetHead() == nullptr || HitCharacter->GetLagCompensation()->FrameHistory.GetHead() == nullptr ||
HitCharacter->GetLagCompensation()->FrameHistory.GetTail() == nullptr; HitCharacter->GetLagCompensation()->FrameHistory.GetTail() == nullptr;
if (bReturn) FServerSideRewindResult(); if (bReturn) FFramePackage();
// Frame package that we check to verify a hit // Frame package that we check to verify a hit
FFramePackage FrameToCheck; FFramePackage FrameToCheck;
@ -228,7 +277,7 @@ FServerSideRewindResult ULagCompensationComponent::ServerSideRewind(ABlasterChar
if (OldestHistoryTime > HitTime) if (OldestHistoryTime > HitTime)
{ {
// Too far back, too laggy to do SSR // Too far back, too laggy to do SSR
FServerSideRewindResult(); FFramePackage();
} }
if (OldestHistoryTime == HitTime) if (OldestHistoryTime == HitTime)
{ {
@ -259,11 +308,11 @@ FServerSideRewindResult ULagCompensationComponent::ServerSideRewind(ABlasterChar
if (bShouldInterpolate) // Why not just check if FrameToCheck == nullptr? if (bShouldInterpolate) // Why not just check if FrameToCheck == nullptr?
{ {
// Interpolate between Younger and Older // Interpolate between Younger and Older
FrameToCheck = InterpBetweenFrames(Older->GetValue(), Younger->GetValue(), HitTime); FrameToCheck = InterpBetweenFrames(Older->GetValue(), Younger->GetValue(), HitTime);
} }
return ConfirmHit(FrameToCheck, HitCharacter, TraceStart, HitLocation); return FrameToCheck;
} }
void ULagCompensationComponent::EnableCharacterMeshCollision(ABlasterCharacter* HitCharacter, ECollisionEnabled::Type CollisionEnabled) void ULagCompensationComponent::EnableCharacterMeshCollision(ABlasterCharacter* HitCharacter, ECollisionEnabled::Type CollisionEnabled)
@ -280,27 +329,3 @@ void ULagCompensationComponent::TickComponent(float DeltaTime, ELevelTick TickTy
SaveFramePackage(); SaveFramePackage();
} }
void ULagCompensationComponent::SaveFramePackage()
{
if (Character == nullptr || !Character->HasAuthority()) return;
if (FrameHistory.Num() <= 1)
{
FFramePackage ThisFrame;
SaveFramePackage(ThisFrame);
FrameHistory.AddHead(ThisFrame);
}
else
{
float HistoryLength = FrameHistory.GetHead()->GetValue().Time - FrameHistory.GetTail()->GetValue().Time;
while (HistoryLength > MaxRecordTime)
{
FrameHistory.RemoveNode(FrameHistory.GetTail());
HistoryLength = FrameHistory.GetHead()->GetValue().Time - FrameHistory.GetTail()->GetValue().Time;
}
FFramePackage ThisFrame;
SaveFramePackage(ThisFrame);
FrameHistory.AddHead(ThisFrame);
// ShowFramePackage(ThisFrame, FColor::Red);
}
}

View File

@ -30,7 +30,11 @@ struct FFramePackage
UPROPERTY() UPROPERTY()
float Time; float Time;
UPROPERTY()
TMap<FName, FBoxInformation> HitBoxInfo; TMap<FName, FBoxInformation> HitBoxInfo;
UPROPERTY()
ABlasterCharacter* Character;
}; };
USTRUCT(BlueprintType) USTRUCT(BlueprintType)
@ -45,17 +49,34 @@ struct FServerSideRewindResult
bool bHeadShot; bool bHeadShot;
}; };
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) ) USTRUCT(BlueprintType)
struct FShotgunServerSideRewindResult
{
GENERATED_BODY()
UPROPERTY()
TMap<ABlasterCharacter*, uint32> Headshots;
UPROPERTY()
TMap<ABlasterCharacter*, uint32> BodyShots;
};
UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
class BLASTER_API ULagCompensationComponent : public UActorComponent class BLASTER_API ULagCompensationComponent : public UActorComponent
{ {
GENERATED_BODY() GENERATED_BODY()
public: public:
ULagCompensationComponent(); ULagCompensationComponent();
friend ABlasterCharacter; friend ABlasterCharacter;
virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
void ShowFramePackage(const FFramePackage& Package, const FColor Color); void ShowFramePackage(const FFramePackage& Package, const FColor Color);
FServerSideRewindResult ServerSideRewind(class ABlasterCharacter* HitCharacter, const FVector_NetQuantize& TraceStart, const FVector_NetQuantize& HitLocation, float HitTime); FServerSideRewindResult ServerSideRewind(
ABlasterCharacter* HitCharacter,
const FVector_NetQuantize& TraceStart,
const FVector_NetQuantize& HitLocation,
float HitTime
);
UFUNCTION(Server, Reliable) UFUNCTION(Server, Reliable)
void ServerScoreRequest( void ServerScoreRequest(
@ -63,20 +84,41 @@ public:
const FVector_NetQuantize& TraceStart, const FVector_NetQuantize& TraceStart,
const FVector_NetQuantize& HitLocation, const FVector_NetQuantize& HitLocation,
float HitTime, float HitTime,
class AWeapon* DamageCauser AWeapon* DamageCauser
); );
protected: protected:
virtual void BeginPlay() override; virtual void BeginPlay() override;
void SaveFramePackage(); void SaveFramePackage();
void SaveFramePackage(FFramePackage& Package); void SaveFramePackage(FFramePackage& Package);
FFramePackage InterpBetweenFrames(const FFramePackage& OlderFrame, const FFramePackage& YoungerFrame, float HitTime); FFramePackage InterpBetweenFrames(const FFramePackage& OlderFrame, const FFramePackage& YoungerFrame, float HitTime);
FServerSideRewindResult ConfirmHit(const FFramePackage& Package, ABlasterCharacter* HitCharacter, const FVector_NetQuantize& TraceStart, const FVector_NetQuantize HitLocation); FServerSideRewindResult ConfirmHit(
const FFramePackage& Package,
ABlasterCharacter* HitCharacter,
const FVector_NetQuantize& TraceStart,
const FVector_NetQuantize HitLocation
);
void CacheBoxPositions(ABlasterCharacter* HitCharacter, FFramePackage& OutFramePackage); void CacheBoxPositions(ABlasterCharacter* HitCharacter, FFramePackage& OutFramePackage);
void MoveBoxes(ABlasterCharacter* HitCharacter, const FFramePackage& Package); void MoveBoxes(ABlasterCharacter* HitCharacter, const FFramePackage& Package);
void ResetHitBoxes(ABlasterCharacter* HitCharacter, const FFramePackage& Package); void ResetHitBoxes(ABlasterCharacter* HitCharacter, const FFramePackage& Package);
void EnableCharacterMeshCollision(ABlasterCharacter* HitCharacter, ECollisionEnabled::Type CollisionEnabled); void EnableCharacterMeshCollision(ABlasterCharacter* HitCharacter, ECollisionEnabled::Type CollisionEnabled);
private: FFramePackage GetFrameToCheck(ABlasterCharacter* HitCharacter, float HitTime);
// Shotgun related stuff
FShotgunServerSideRewindResult ShotgunServerSideRewind(
const TArray<ABlasterCharacter*>& HitCharacters,
const FVector_NetQuantize& TraceStart,
const TArray<FVector_NetQuantize>& HitLocations,
float HitTime
);
FShotgunServerSideRewindResult ShotgunConfirmHit(
const TArray<FFramePackage>& FramePackages,
const FVector_NetQuantize& TraceStart,
const TArray<FVector_NetQuantize>& HitLocations
);
private:
UPROPERTY() UPROPERTY()
ABlasterCharacter* Character; ABlasterCharacter* Character;
@ -87,5 +129,4 @@ private:
UPROPERTY(EditAnywhere) UPROPERTY(EditAnywhere)
float MaxRecordTime = 4.f; float MaxRecordTime = 4.f;
}; };