A Demo Project for the UnrealEngineSDK
Loading...
Searching...
No Matches
GrippableStaticMeshActor.cpp
Go to the documentation of this file.
1// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
2
4#include "TimerManager.h"
5#include "Net/UnrealNetwork.h"
6#include "PhysicsReplication.h"
7#if WITH_PUSH_MODEL
8#include "Net/Core/PushModel/PushModel.h"
9#endif
10
11// #TODO: Pull request this? This macro could be very useful
12/*#define DOREPLIFETIME_CHANGE_NOTIFY(c,v,rncond) \
13{ \
14 static UProperty* sp##v = GetReplicatedProperty(StaticClass(), c::StaticClass(),GET_MEMBER_NAME_CHECKED(c,v)); \
15 bool bFound = false; \
16 for ( int32 i = 0; i < OutLifetimeProps.Num(); i++ ) \
17 { \
18 if ( OutLifetimeProps[i].RepIndex == sp##v->RepIndex ) \
19 { \
20 for ( int32 j = 0; j < sp##v->ArrayDim; j++ ) \
21 { \
22 OutLifetimeProps[i + j].RepNotifyCondition = rncond; \
23 } \
24 bFound = true; \
25 break; \
26 } \
27 } \
28 check( bFound ); \
29}*/
30
31
32UOptionalRepStaticMeshComponent::UOptionalRepStaticMeshComponent(const FObjectInitializer& ObjectInitializer)
33 : Super(ObjectInitializer)
34{
35 bReplicateMovement = true;
36}
37
38void UOptionalRepStaticMeshComponent::PreReplication(IRepChangedPropertyTracker & ChangedPropertyTracker)
39{
40 Super::PreReplication(ChangedPropertyTracker);
41
42 // Don't replicate if set to not do it
43 DOREPLIFETIME_ACTIVE_OVERRIDE_PRIVATE_PROPERTY(USceneComponent, RelativeLocation, bReplicateMovement);
44 DOREPLIFETIME_ACTIVE_OVERRIDE_PRIVATE_PROPERTY(USceneComponent, RelativeRotation, bReplicateMovement);
45 DOREPLIFETIME_ACTIVE_OVERRIDE_PRIVATE_PROPERTY(USceneComponent, RelativeScale3D, bReplicateMovement);
46
47
48}
49
50void UOptionalRepStaticMeshComponent::GetLifetimeReplicatedProps(TArray< class FLifetimeProperty > & OutLifetimeProps) const
51{
52 Super::GetLifetimeReplicatedProps(OutLifetimeProps);
53
55}
56
57 //=============================================================================
58AGrippableStaticMeshActor::AGrippableStaticMeshActor(const FObjectInitializer& ObjectInitializer)
59 : Super(ObjectInitializer.SetDefaultSubobjectClass<UOptionalRepStaticMeshComponent>(TEXT("StaticMeshComponent0")))
60{
74
76
77 this->SetMobility(EComponentMobility::Movable);
78
79 // Default replication on for multiplayer
80 //this->bNetLoadOnClient = false;
81 SetReplicatingMovement(true);
82 this->bReplicates = true;
83
87
88 // Setting a minimum of every 3rd frame (VR 90fps) for replication consideration
89 // Otherwise we will get some massive slow downs if the replication is allowed to hit the 2 per second minimum default
90 MinNetUpdateFrequency = 30.0f;
91}
92
93void AGrippableStaticMeshActor::GetLifetimeReplicatedProps(TArray< class FLifetimeProperty > & OutLifetimeProps) const
94{
95 Super::GetLifetimeReplicatedProps(OutLifetimeProps);
96
97 DOREPLIFETIME_CONDITION(AGrippableStaticMeshActor, GripLogicScripts, COND_Custom);
102 DOREPLIFETIME_CONDITION(AGrippableStaticMeshActor, VRGripInterfaceSettings, COND_Custom);
103 DOREPLIFETIME_CONDITION(AGrippableStaticMeshActor, GameplayTags, COND_Custom);
104
105 DISABLE_REPLICATED_PRIVATE_PROPERTY(AActor, AttachmentReplication);
106
107 FDoRepLifetimeParams AttachmentReplicationParams{ COND_Custom, REPNOTIFY_Always, /*bIsPushBased=*/true };
108 DOREPLIFETIME_WITH_PARAMS_FAST(AGrippableStaticMeshActor, AttachmentWeldReplication, AttachmentReplicationParams);
109}
110
111void AGrippableStaticMeshActor::PreReplication(IRepChangedPropertyTracker & ChangedPropertyTracker)
112{
113 //Super::PreReplication(ChangedPropertyTracker);
114
118
119 //Super::PreReplication(ChangedPropertyTracker);
120
121#if WITH_PUSH_MODEL
122 const AActor* const OldAttachParent = AttachmentWeldReplication.AttachParent;
123 const UActorComponent* const OldAttachComponent = AttachmentWeldReplication.AttachComponent;
124#endif
125
126 // Attachment replication gets filled in by GatherCurrentMovement(), but in the case of a detached root we need to trigger remote detachment.
127 AttachmentWeldReplication.AttachParent = nullptr;
128 AttachmentWeldReplication.AttachComponent = nullptr;
129
131
132 DOREPLIFETIME_ACTIVE_OVERRIDE_PRIVATE_PROPERTY(AActor, ReplicatedMovement, IsReplicatingMovement());
133
134 // Don't need to replicate AttachmentReplication if the root component replicates, because it already handles it.
135 DOREPLIFETIME_ACTIVE_OVERRIDE(AGrippableStaticMeshActor, AttachmentWeldReplication, RootComponent && !RootComponent->GetIsReplicated());
136
137 // Don't need to replicate AttachmentReplication if the root component replicates, because it already handles it.
138 DOREPLIFETIME_ACTIVE_OVERRIDE_PRIVATE_PROPERTY(AActor, AttachmentReplication, RootComponent && !RootComponent->GetIsReplicated());
139
140
141#if WITH_PUSH_MODEL
142 if (UNLIKELY(OldAttachParent != AttachmentWeldReplication.AttachParent || OldAttachComponent != AttachmentWeldReplication.AttachComponent))
143 {
144 //MARK_PROPERTY_DIRTY_FROM_NAME(AGrippableStaticMeshActor, AttachmentWeldReplication, this);
145 }
146#endif
147
148 UBlueprintGeneratedClass* BPClass = Cast<UBlueprintGeneratedClass>(GetClass());
149 if (BPClass != nullptr)
150 {
151 BPClass->InstancePreReplication(this, ChangedPropertyTracker);
152 }
153}
154
156{
157 if (IsReplicatingMovement() || (RootComponent && RootComponent->GetAttachParent()))
158 {
159 bool bWasAttachmentModified = false;
160 bool bWasRepMovementModified = false;
161
162 AActor* OldAttachParent = AttachmentWeldReplication.AttachParent;
163 USceneComponent* OldAttachComponent = AttachmentWeldReplication.AttachComponent;
164
165 AttachmentWeldReplication.AttachParent = nullptr;
166 AttachmentWeldReplication.AttachComponent = nullptr;
167
168 FRepMovement& RepMovement = GetReplicatedMovement_Mutable();
169
170 UPrimitiveComponent* RootPrimComp = Cast<UPrimitiveComponent>(GetRootComponent());
171 if (RootPrimComp && RootPrimComp->IsSimulatingPhysics())
172 {
173 FRigidBodyState RBState;
174 RootPrimComp->GetRigidBodyState(RBState);
175
176 RepMovement.FillFrom(RBState, this);
177 // Don't replicate movement if we're welded to another parent actor.
178 // Their replication will affect our position indirectly since we are attached.
179 RepMovement.bRepPhysics = !RootPrimComp->IsWelded();
180
181 if (!RepMovement.bRepPhysics)
182 {
183 if (RootComponent->GetAttachParent() != nullptr)
184 {
185 // Networking for attachments assumes the RootComponent of the AttachParent actor.
186 // If that's not the case, we can't update this, as the client wouldn't be able to resolve the Component and would detach as a result.
187 AttachmentWeldReplication.AttachParent = RootComponent->GetAttachParent()->GetAttachmentRootActor();
188 if (AttachmentWeldReplication.AttachParent != nullptr)
189 {
190 AttachmentWeldReplication.LocationOffset = RootComponent->GetRelativeLocation();
191 AttachmentWeldReplication.RotationOffset = RootComponent->GetRelativeRotation();
192 AttachmentWeldReplication.RelativeScale3D = RootComponent->GetRelativeScale3D();
193 AttachmentWeldReplication.AttachComponent = RootComponent->GetAttachParent();
194 AttachmentWeldReplication.AttachSocket = RootComponent->GetAttachSocketName();
195 AttachmentWeldReplication.bIsWelded = RootPrimComp ? RootPrimComp->IsWelded() : false;
196
197 // Technically, the values might have stayed the same, but we'll just assume they've changed.
198 bWasAttachmentModified = true;
199 }
200 }
201 }
202
203 // Technically, the values might have stayed the same, but we'll just assume they've changed.
204 bWasRepMovementModified = true;
205 }
206 else if (RootComponent != nullptr)
207 {
208 // If we are attached, don't replicate absolute position, use AttachmentReplication instead.
209 if (RootComponent->GetAttachParent() != nullptr)
210 {
211 // Networking for attachments assumes the RootComponent of the AttachParent actor.
212 // If that's not the case, we can't update this, as the client wouldn't be able to resolve the Component and would detach as a result.
213 AttachmentWeldReplication.AttachParent = RootComponent->GetAttachParent()->GetAttachmentRootActor();
214 if (AttachmentWeldReplication.AttachParent != nullptr)
215 {
216 AttachmentWeldReplication.LocationOffset = RootComponent->GetRelativeLocation();
217 AttachmentWeldReplication.RotationOffset = RootComponent->GetRelativeRotation();
218 AttachmentWeldReplication.RelativeScale3D = RootComponent->GetRelativeScale3D();
219 AttachmentWeldReplication.AttachComponent = RootComponent->GetAttachParent();
220 AttachmentWeldReplication.AttachSocket = RootComponent->GetAttachSocketName();
221 AttachmentWeldReplication.bIsWelded = RootPrimComp ? RootPrimComp->IsWelded() : false;
222
223 // Technically, the values might have stayed the same, but we'll just assume they've changed.
224 bWasAttachmentModified = true;
225 }
226 }
227 else
228 {
229 RepMovement.Location = FRepMovement::RebaseOntoZeroOrigin(RootComponent->GetComponentLocation(), this);
230 RepMovement.Rotation = RootComponent->GetComponentRotation();
231 RepMovement.LinearVelocity = GetVelocity();
232 RepMovement.AngularVelocity = FVector::ZeroVector;
233
234 // Technically, the values might have stayed the same, but we'll just assume they've changed.
235 bWasRepMovementModified = true;
236 }
237
238 bWasRepMovementModified = (bWasRepMovementModified || RepMovement.bRepPhysics);
239 RepMovement.bRepPhysics = false;
240 }
241#if WITH_PUSH_MODEL
242 if (bWasRepMovementModified)
243 {
244 // MARK_PROPERTY_DIRTY_FROM_NAME(AActor, ReplicatedMovement, this);
245 }
246
247 if (bWasAttachmentModified ||
248 OldAttachParent != AttachmentWeldReplication.AttachParent ||
249 OldAttachComponent != AttachmentWeldReplication.AttachComponent)
250 {
251 //MARK_PROPERTY_DIRTY_FROM_NAME(AGrippableStaticMeshActor, AttachmentWeldReplication, this);
252 }
253#endif
254 }
255}
256
257bool AGrippableStaticMeshActor::ReplicateSubobjects(UActorChannel* Channel, class FOutBunch *Bunch, FReplicationFlags *RepFlags)
258{
259 bool WroteSomething = Super::ReplicateSubobjects(Channel, Bunch, RepFlags);
260
262 {
263 for (UVRGripScriptBase* Script : GripLogicScripts)
264 {
265 if (Script && !Script->IsPendingKill())
266 {
267 WroteSomething |= Channel->ReplicateSubobject(Script, *Bunch, *RepFlags);
268 }
269 }
270 }
271
272 return WroteSomething;
273}
274
275//=============================================================================
279
281{
282 // Call the base class
283 Super::BeginPlay();
284
285 // Call all grip scripts begin play events so they can perform any needed logic
286 for (UVRGripScriptBase* Script : GripLogicScripts)
287 {
288 if (Script)
289 {
290 Script->BeginPlay(this);
291 }
292 }
293}
294
296{
298}
299
304
305void AGrippableStaticMeshActor::TickGrip_Implementation(UGripMotionControllerComponent * GrippingController, const FBPActorGripInformation & GripInformation, float DeltaTime) {}
307void AGrippableStaticMeshActor::OnGripRelease_Implementation(UGripMotionControllerComponent* ReleasingController, const FBPActorGripInformation& GripInformation, bool bWasSocketed) { }
310void AGrippableStaticMeshActor::OnSecondaryGrip_Implementation(UGripMotionControllerComponent* GripOwningController, USceneComponent* SecondaryGripComponent, const FBPActorGripInformation& GripInformation) { OnSecondaryGripAdded.Broadcast(GripOwningController, GripInformation); }
311void AGrippableStaticMeshActor::OnSecondaryGripRelease_Implementation(UGripMotionControllerComponent* GripOwningController, USceneComponent* ReleasingSecondaryGripComponent, const FBPActorGripInformation& GripInformation) { OnSecondaryGripRemoved.Broadcast(GripOwningController, GripInformation); }
316void AGrippableStaticMeshActor::OnInput_Implementation(FKey Key, EInputEvent KeyEvent) {}
317bool AGrippableStaticMeshActor::RequestsSocketing_Implementation(USceneComponent *& ParentToSocketTo, FName & OptionalSocketName, FTransform_NetQuantize & RelativeTransform) { return false; }
318
323
324
329
334
339
344
349
354
355void AGrippableStaticMeshActor::GetGripStiffnessAndDamping_Implementation(float &GripStiffnessOut, float &GripDampingOut)
356{
359}
360
365
370
371void AGrippableStaticMeshActor::ClosestGripSlotInRange_Implementation(FVector WorldLocation, bool bSecondarySlot, bool & bHadSlotInRange, FTransform & SlotWorldTransform, FName & SlotName, UGripMotionControllerComponent * CallingController, FName OverridePrefix)
372{
373 if (OverridePrefix.IsNone())
374 bSecondarySlot ? OverridePrefix = "VRGripS" : OverridePrefix = "VRGripP";
375
376 UVRExpansionFunctionLibrary::GetGripSlotInRangeByTypeName(OverridePrefix, this, WorldLocation, bSecondarySlot ? VRGripInterfaceSettings.SecondarySlotRange : VRGripInterfaceSettings.PrimarySlotRange, bHadSlotInRange, SlotWorldTransform, SlotName, CallingController);
377}
378
383
384void AGrippableStaticMeshActor::IsHeld_Implementation(TArray<FBPGripPair> & HoldingControllers, bool & bIsHeld)
385{
386 HoldingControllers = VRGripInterfaceSettings.HoldingControllers;
388}
389
391{
393 {
394 // The subsystem automatically removes entries with the same function signature so its safe to just always add here
395 GetWorld()->GetSubsystem<UBucketUpdateSubsystem>()->AddObjectToBucket(ClientAuthReplicationData.UpdateRate, this, FName(TEXT("PollReplicationEvent")));
397
398 if (UWorld * World = GetWorld())
399 ClientAuthReplicationData.TimeAtInitialThrow = World->GetTimeSeconds();
400
401 return true;
402 }
403
404 return false;
405}
406
408{
410 {
411 GetWorld()->GetSubsystem<UBucketUpdateSubsystem>()->RemoveObjectFromBucketByFunctionName(this, FName(TEXT("PollReplicationEvent")));
413 return true;
414 }
415
416 return false;
417}
418
420{
421 if (bGripped)
422 {
423 OnGripped.Broadcast(Controller, GripInformation);
424 }
425 else
426 {
427 OnDropped.Broadcast(Controller, GripInformation, bWasSocketed);
428 }
429}
430
432{
433 if (bIsHeld)
434 {
435 VRGripInterfaceSettings.HoldingControllers.AddUnique(FBPGripPair(HoldingController, GripID));
437
440 }
441 else
442 {
443 VRGripInterfaceSettings.HoldingControllers.Remove(FBPGripPair(HoldingController, GripID));
445
447 {
448 bool bWasLocallyOwned = HoldingController ? HoldingController->IsLocallyControlled() : false;
449 if (bWasLocallyOwned && ShouldWeSkipAttachmentReplication(false))
450 {
451 if (UPrimitiveComponent* PrimComp = Cast<UPrimitiveComponent>(GetRootComponent()))
452 {
453 if (PrimComp->IsSimulatingPhysics())
454 {
456 }
457 }
458 }
459 }
460 }
461}
462
463bool AGrippableStaticMeshActor::GetGripScripts_Implementation(TArray<UVRGripScriptBase*> & ArrayReference)
464{
465 ArrayReference = GripLogicScripts;
466 return GripLogicScripts.Num() > 0;
467}
468
470{
472 return false; // Tell the bucket subsystem to remove us from consideration
473
474 UWorld *OurWorld = GetWorld();
475 if (!OurWorld)
476 return false; // Tell the bucket subsystem to remove us from consideration
477
478 bool bRemoveBlocking = false;
479
480 if ((OurWorld->GetTimeSeconds() - ClientAuthReplicationData.TimeAtInitialThrow) > 10.0f)
481 {
482 // Lets time out sending, its been 10 seconds since we threw the object and its likely that it is conflicting with some server
483 // Authed movement that is forcing it to keep momentum.
484 //return false; // Tell the bucket subsystem to remove us from consideration
485 bRemoveBlocking = true;
486 }
487
488 // Store current transform for resting check
489 FTransform CurTransform = this->GetActorTransform();
490
491 if (!bRemoveBlocking)
492 {
493 if (!CurTransform.GetRotation().Equals(ClientAuthReplicationData.LastActorTransform.GetRotation()) || !CurTransform.GetLocation().Equals(ClientAuthReplicationData.LastActorTransform.GetLocation()))
494 {
496
497 if (UPrimitiveComponent * PrimComp = Cast<UPrimitiveComponent>(RootComponent))
498 {
499 // Need to clamp to a max time since start, to handle cases with conflicting collisions
500 if (PrimComp->IsSimulatingPhysics() && ShouldWeSkipAttachmentReplication(false))
501 {
502 FRepMovementVR ClientAuthMovementRep;
503 if (ClientAuthMovementRep.GatherActorsMovement(this))
504 {
505 Server_GetClientAuthReplication(ClientAuthMovementRep);
506
507 if (PrimComp->RigidBodyIsAwake())
508 {
509 return true;
510 }
511 }
512 }
513 }
514 else
515 {
516 bRemoveBlocking = true;
517 //return false; // Tell the bucket subsystem to remove us from consideration
518 }
519 }
520 //else
521 // {
522 // Difference is too small, lets end sending location
523 //ClientAuthReplicationData.LastActorTransform = FTransform::Identity;
524 // }
525 }
526
527 bool TimedBlockingRelease = false;
528
529 AActor* TopOwner = GetOwner();
530 if (TopOwner != nullptr)
531 {
532 AActor * tempOwner = TopOwner->GetOwner();
533
534 // I have an owner so search that for the top owner
535 while (tempOwner)
536 {
537 TopOwner = tempOwner;
538 tempOwner = TopOwner->GetOwner();
539 }
540
541 if (APlayerController* PlayerController = Cast<APlayerController>(TopOwner))
542 {
543 if (APlayerState* PlayerState = PlayerController->PlayerState)
544 {
546 {
547 OurWorld->GetTimerManager().ClearTimer(ClientAuthReplicationData.ResetReplicationHandle);
548 }
549
550 // Lets clamp the ping to a min / max value just in case
551 float clampedPing = FMath::Clamp(PlayerState->ExactPing * 0.001f, 0.0f, 1000.0f);
552 OurWorld->GetTimerManager().SetTimer(ClientAuthReplicationData.ResetReplicationHandle, this, &AGrippableStaticMeshActor::CeaseReplicationBlocking, clampedPing, false);
553 TimedBlockingRelease = true;
554 }
555 }
556 }
557
558 if (!TimedBlockingRelease)
559 {
561 }
562
563 // Tell server to kill us
565 return false; // Tell the bucket subsystem to remove us from consideration
566}
567
569{
572
573 ClientAuthReplicationData.LastActorTransform = FTransform::Identity;
574
576 {
577 if (UWorld * OurWorld = GetWorld())
578 {
579 OurWorld->GetTimerManager().ClearTimer(ClientAuthReplicationData.ResetReplicationHandle);
580 }
581 }
582}
583
584void AGrippableStaticMeshActor::EndPlay(const EEndPlayReason::Type EndPlayReason)
585{
587
588 // Call all grip scripts begin play events so they can perform any needed logic
589 for (UVRGripScriptBase* Script : GripLogicScripts)
590 {
591 if (Script)
592 {
593 Script->EndPlay(EndPlayReason);
594 }
595 }
596
597 Super::EndPlay(EndPlayReason);
598}
599
600bool AGrippableStaticMeshActor::Server_EndClientAuthReplication_Validate()
601{
602 return true;
603}
604
605void AGrippableStaticMeshActor::Server_EndClientAuthReplication_Implementation()
606{
607 if (UWorld* World = GetWorld())
608 {
609 if (FPhysScene* PhysScene = World->GetPhysicsScene())
610 {
611 if (FPhysicsReplication* PhysicsReplication = PhysScene->GetPhysicsReplication())
612 {
613 PhysicsReplication->RemoveReplicatedTarget(this->GetStaticMeshComponent());
614 }
615 }
616 }
617}
618
619bool AGrippableStaticMeshActor::Server_GetClientAuthReplication_Validate(const FRepMovementVR & newMovement)
620{
621 return true;
622}
623
624void AGrippableStaticMeshActor::Server_GetClientAuthReplication_Implementation(const FRepMovementVR & newMovement)
625{
627 {
628 if (!newMovement.Location.ContainsNaN() && !newMovement.Rotation.ContainsNaN())
629 {
630 FRepMovement& MovementRep = GetReplicatedMovement_Mutable();
631 newMovement.CopyTo(MovementRep);
633 }
634 }
635}
636
638{
640 //if (bAllowIgnoringAttachOnOwner && ShouldWeSkipAttachmentReplication())
641 {
642 return;
643 }
644
645 if (AttachmentWeldReplication.AttachParent)
646 {
647 if (RootComponent)
648 {
649 USceneComponent* AttachParentComponent = (AttachmentWeldReplication.AttachComponent ? AttachmentWeldReplication.AttachComponent : AttachmentWeldReplication.AttachParent->GetRootComponent());
650
651 if (AttachParentComponent)
652 {
653 RootComponent->SetRelativeLocation_Direct(AttachmentWeldReplication.LocationOffset);
654 RootComponent->SetRelativeRotation_Direct(AttachmentWeldReplication.RotationOffset);
655 RootComponent->SetRelativeScale3D_Direct(AttachmentWeldReplication.RelativeScale3D);
656
657 // If we're already attached to the correct Parent and Socket, then the update must be position only.
658 // AttachToComponent would early out in this case.
659 // Note, we ignore the special case for simulated bodies in AttachToComponent as AttachmentReplication shouldn't get updated
660 // if the body is simulated (see AActor::GatherMovement).
661 const bool bAlreadyAttached = (AttachParentComponent == RootComponent->GetAttachParent() && AttachmentWeldReplication.AttachSocket == RootComponent->GetAttachSocketName() && AttachParentComponent->GetAttachChildren().Contains(RootComponent));
662 if (bAlreadyAttached)
663 {
664 // Note, this doesn't match AttachToComponent, but we're assuming it's safe to skip physics (see comment above).
665 RootComponent->UpdateComponentToWorld(EUpdateTransformFlags::SkipPhysicsUpdate, ETeleportType::None);
666 }
667 else
668 {
669 FAttachmentTransformRules attachRules = FAttachmentTransformRules::KeepRelativeTransform;
670 attachRules.bWeldSimulatedBodies = AttachmentWeldReplication.bIsWelded;
671 RootComponent->AttachToComponent(AttachParentComponent, attachRules, AttachmentWeldReplication.AttachSocket);
672 }
673 }
674 }
675 }
676 else
677 {
678 DetachFromActor(FDetachmentTransformRules::KeepWorldTransform);
679
680 // Handle the case where an object was both detached and moved on the server in the same frame.
681 // Calling this extraneously does not hurt but will properly fire events if the movement state changed while attached.
682 // This is needed because client side movement is ignored when attached
683 if (IsReplicatingMovement())
684 {
686 }
687 }
688}
689
691{
693 //if (bAllowIgnoringAttachOnOwner && (ClientAuthReplicationData.bIsCurrentlyClientAuth || ShouldWeSkipAttachmentReplication()))
694 {
695 return;
696 }
697
698 if (RootComponent)
699 {
700 const FRepAttachment ReplicationAttachment = GetAttachmentReplication();
701 if (!ReplicationAttachment.AttachParent)
702 {
703 const FRepMovement& RepMove = GetReplicatedMovement();
704
705 // This "fix" corrects the simulation state not replicating over correctly
706 // If you turn off movement replication, simulate an object, turn movement replication back on and un-simulate, it never knows the difference
707 // This change ensures that it is checking against the current state
708 if (RootComponent->IsSimulatingPhysics() != RepMove.bRepPhysics)//SavedbRepPhysics != ReplicatedMovement.bRepPhysics)
709 {
710 // Turn on/off physics sim to match server.
711 SyncReplicatedPhysicsSimulation();
712
713 // It doesn't really hurt to run it here, the super can call it again but it will fail out as they already match
714 }
715 }
716 }
717
718 Super::OnRep_ReplicateMovement();
719}
720
722{
724 //if (ClientAuthReplicationData.bIsCurrentlyClientAuth && ShouldWeSkipAttachmentReplication(false))
725 {
726 return;
727 }
728
729 Super::OnRep_ReplicatedMovement();
730}
731
733{
735 //if ((ClientAuthReplicationData.bIsCurrentlyClientAuth || VRGripInterfaceSettings.bIsHeld) && bAllowIgnoringAttachOnOwner && ShouldWeSkipAttachmentReplication(false))
736 {
737 return;
738 }
739
740 Super::PostNetReceivePhysicState();
741}
742
744{
745 Super::MarkComponentsAsPendingKill();
746
747 for (int32 i = 0; i < GripLogicScripts.Num(); ++i)
748 {
749 if (UObject *SubObject = GripLogicScripts[i])
750 {
751 SubObject->MarkPendingKill();
752 }
753 }
754
755 GripLogicScripts.Empty();
756}
757
759{
760 Super::PreDestroyFromReplication();
761
762 // Destroy any sub-objects we created
763 for (int32 i = 0; i < GripLogicScripts.Num(); ++i)
764 {
765 if (UObject *SubObject = GripLogicScripts[i])
766 {
767 OnSubobjectDestroyFromReplication(SubObject); //-V595
768 SubObject->PreDestroyFromReplication();
769 SubObject->MarkPendingKill();
770 }
771 }
772
773 for (UActorComponent * ActorComp : GetComponents())
774 {
775 // Pending kill components should have already had this called as they were network spawned and are being killed
776 // We only call this on our interfaced components since they are the only ones that should implement grip scripts
777 if (ActorComp && !ActorComp->IsPendingKill() && ActorComp->GetClass()->ImplementsInterface(UVRGripInterface::StaticClass()))
778 ActorComp->PreDestroyFromReplication();
779 }
780
781 GripLogicScripts.Empty();
782}
783
785{
786 Super::BeginDestroy();
787
788 for (int32 i = 0; i < GripLogicScripts.Num(); i++)
789 {
790 if (UObject *SubObject = GripLogicScripts[i])
791 {
792 SubObject->MarkPendingKill();
793 }
794 }
795
796 GripLogicScripts.Empty();
797}
798
800{
801 Super::GetSubobjectsWithStableNamesForNetworking(ObjList);
802
804 {
805 for (int32 i = 0; i < GripLogicScripts.Num(); ++i)
806 {
807 if (UObject* SubObject = GripLogicScripts[i])
808 {
809 ObjList.Add(SubObject);
810 }
811 }
812 }
813}
EGripMovementReplicationSettings
UENUM(Blueprintable)
ESecondaryGripType
UENUM(Blueprintable)
EGripCollisionType
UENUM(Blueprintable)
EGripLateUpdateSettings
UENUM(Blueprintable)
EGripInterfaceTeleportBehavior
UENUM(Blueprintable)
UCLASS(Blueprintable, meta = (BlueprintSpawnableComponent, ChildCanTick), ClassGroup = (VRExpansionPl...
virtual bool GetGripScripts_Implementation(TArray< UVRGripScriptBase * > &ArrayReference) override
virtual bool SimulateOnDrop_Implementation() override
virtual void MarkComponentsAsPendingKill() override
virtual bool RequestsSocketing_Implementation(USceneComponent *&ParentToSocketTo, FName &OptionalSocketName, FTransform_NetQuantize &RelativeTransform) override
virtual EGripLateUpdateSettings GripLateUpdateSetting_Implementation() override
virtual ESecondaryGripType SecondaryGripType_Implementation() override
FVRClientAuthReplicationData ClientAuthReplicationData
UPROPERTY(EditAnywhere, Replicated, BlueprintReadWrite, Category = "Replication")
virtual void OnEndSecondaryUsed_Implementation() override
virtual void ClosestGripSlotInRange_Implementation(FVector WorldLocation, bool bSecondarySlot, bool &bHadSlotInRange, FTransform &SlotWorldTransform, FName &SlotName, UGripMotionControllerComponent *CallingController=nullptr, FName OverridePrefix=NAME_None) override
virtual void OnGripRelease_Implementation(UGripMotionControllerComponent *ReleasingController, const FBPActorGripInformation &GripInformation, bool bWasSocketed=false) override
virtual void PreReplication(IRepChangedPropertyTracker &ChangedPropertyTracker) override
virtual void GatherCurrentMovement() override
virtual void OnChildGripRelease_Implementation(UGripMotionControllerComponent *ReleasingController, const FBPActorGripInformation &GripInformation, bool bWasSocketed=false) override
TArray< class UVRGripScriptBase * > GripLogicScripts
UPROPERTY(EditAnywhere, Replicated, BlueprintReadOnly, Instanced, Category = "VRGripInterface")
virtual void IsHeld_Implementation(TArray< FBPGripPair > &HoldingControllers, bool &bIsHeld) override
void Server_GetClientAuthReplication(const FRepMovementVR &newMovement)
UFUNCTION(UnReliable, Server, WithValidation, Category = "Networking")
virtual void OnRep_ReplicatedMovement() override
bool AddToClientReplicationBucket()
UFUNCTION(BlueprintCallable, Category = "Networking")
virtual void OnInput_Implementation(FKey Key, EInputEvent KeyEvent) override
FBPInterfaceProperties VRGripInterfaceSettings
UPROPERTY(EditAnywhere, Replicated, BlueprintReadWrite, Category = "VRGripInterface")
virtual void OnRep_ReplicateMovement() override
FVROnDropSignature OnDropped
UPROPERTY(BlueprintAssignable, Category = "Grip Events")
virtual void GetSubobjectsWithStableNamesForNetworking(TArray< UObject * > &ObjList) override
FGameplayTagContainer GameplayTags
UPROPERTY(EditAnywhere, Replicated, BlueprintReadWrite, Category = "GameplayTags")
virtual void OnSecondaryUsed_Implementation() override
FVROnGripSignature OnSecondaryGripRemoved
UPROPERTY(BlueprintAssignable, Category = "Grip Events")
FRepAttachmentWithWeld AttachmentWeldReplication
UPROPERTY(Replicated, ReplicatedUsing = OnRep_AttachmentReplication)
bool bRepGripSettingsAndGameplayTags
UPROPERTY(EditAnywhere, Replicated, BlueprintReadWrite, Category = "VRGripInterface")
virtual void PostNetReceivePhysicState() override
virtual void GetGripStiffnessAndDamping_Implementation(float &GripStiffnessOut, float &GripDampingOut) override
void SetDenyGripping(bool bDenyGripping)
UFUNCTION(BlueprintCallable, Category = "VRGripInterface")
virtual bool DenyGripping_Implementation(UGripMotionControllerComponent *GripInitiator=nullptr) override
virtual float GripBreakDistance_Implementation() override
virtual void PreDestroyFromReplication() override
bool RemoveFromClientReplicationBucket()
UFUNCTION(BlueprintCallable, Category = "Networking")
virtual bool AllowsMultipleGrips_Implementation() override
virtual EGripInterfaceTeleportBehavior TeleportBehavior_Implementation() override
virtual void Native_NotifyThrowGripDelegates(UGripMotionControllerComponent *Controller, bool bGripped, const FBPActorGripInformation &GripInformation, bool bWasSocketed=false) override
bool bAllowIgnoringAttachOnOwner
UPROPERTY(EditAnywhere, Replicated, BlueprintReadWrite, Category = "Replication")
AGrippableStaticMeshActor(const FObjectInitializer &ObjectInitializer)
void Server_EndClientAuthReplication()
UFUNCTION(Reliable, Server, WithValidation, Category = "Networking")
void CeaseReplicationBlocking()
UFUNCTION(Category = "Networking")
bool ShouldWeSkipAttachmentReplication(bool bConsiderHeld=true) const
virtual FBPAdvGripSettings AdvancedGripSettings_Implementation() override
void SetGripPriority(int NewGripPriority)
UFUNCTION(BlueprintCallable, Category = "VRGripInterface")
FVROnGripSignature OnSecondaryGripAdded
UPROPERTY(BlueprintAssignable, Category = "Grip Events")
FVROnGripSignature OnGripped
UPROPERTY(BlueprintAssignable, Category = "Grip Events")
virtual void SetHeld_Implementation(UGripMotionControllerComponent *HoldingController, uint8 GripID, bool bIsHeld) override
bool bReplicateGripScripts
UPROPERTY(EditAnywhere, Replicated, BlueprintReadWrite, Category = "VRGripInterface")
virtual void OnEndUsed_Implementation() override
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override
virtual void OnSecondaryGrip_Implementation(UGripMotionControllerComponent *GripOwningController, USceneComponent *SecondaryGripComponent, const FBPActorGripInformation &GripInformation) override
virtual void OnUsed_Implementation() override
virtual void OnChildGrip_Implementation(UGripMotionControllerComponent *GrippingController, const FBPActorGripInformation &GripInformation) override
virtual void OnRep_AttachmentReplication() override
virtual EGripMovementReplicationSettings GripMovementReplicationType_Implementation() override
bool ReplicateSubobjects(UActorChannel *Channel, class FOutBunch *Bunch, FReplicationFlags *RepFlags) override
virtual void TickGrip_Implementation(UGripMotionControllerComponent *GrippingController, const FBPActorGripInformation &GripInformation, float DeltaTime) override
virtual EGripCollisionType GetPrimaryGripType_Implementation(bool bIsSlot) override
virtual void OnGrip_Implementation(UGripMotionControllerComponent *GrippingController, const FBPActorGripInformation &GripInformation) override
virtual void OnSecondaryGripRelease_Implementation(UGripMotionControllerComponent *GripOwningController, USceneComponent *ReleasingSecondaryGripComponent, const FBPActorGripInformation &GripInformation) override
UCLASS(Blueprintable, meta = (BlueprintSpawnableComponent), ClassGroup = MotionController)
UCLASS(Blueprintable, meta = (BlueprintSpawnableComponent,ChildCanTick), ClassGroup = (VRExpansionPlu...
bool bReplicateMovement
UPROPERTY(EditAnywhere, Replicated, BlueprintReadWrite, Category = "Component Replication")
UOptionalRepStaticMeshComponent(const FObjectInitializer &ObjectInitializer)
virtual void PreReplication(IRepChangedPropertyTracker &ChangedPropertyTracker) override
static void GetGripSlotInRangeByTypeName(FName SlotType, AActor *Actor, FVector WorldLocation, float MaxRange, bool &bHadSlotInRange, FTransform &SlotWorldTransform, FName &SlotName, UGripMotionControllerComponent *QueryController=nullptr)
UFUNCTION(BlueprintPure, Category = "VRGrip", meta = (bIgnoreSelf = "true", DisplayName = "GetGripSlo...
UCLASS(NotBlueprintable, BlueprintType, EditInlineNew, DefaultToInstanced, Abstract,...
USTRUCT(BlueprintType, Category = "VRExpansionLibrary")
USTRUCT(BlueprintType, Category = "VRExpansionLibrary")
uint8 GripPriority
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "AdvancedGripSettings")
USTRUCT(BlueprintType, Category = "VRExpansionLibrary")
ESecondaryGripType SecondaryGripType
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRGripInterface")
bool bDenyGripping
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRGripInterface")
EGripCollisionType FreeDefaultGripType
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRGripInterface")
float ConstraintBreakDistance
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRGripInterface")
bool bAllowMultipleGrips
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRGripInterface")
float SecondarySlotRange
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRGripInterface")
EGripLateUpdateSettings LateUpdateSetting
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRGripInterface")
EGripCollisionType SlotDefaultGripType
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRGripInterface")
EGripInterfaceTeleportBehavior OnTeleportBehavior
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRGripInterface")
float ConstraintStiffness
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRGripInterface")
float PrimarySlotRange
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRGripInterface")
bool bIsHeld
UPROPERTY(BlueprintReadWrite, NotReplicated, Category = "VRGripInterface")
TArray< FBPGripPair > HoldingControllers
UPROPERTY(BlueprintReadWrite, NotReplicated, Category = "VRGripInterface")
float ConstraintDamping
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRGripInterface")
FBPAdvGripSettings AdvancedGripSettings
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRGripInterface|AdvancedGripSettings")
EGripMovementReplicationSettings MovementReplicationType
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRGripInterface")
bool bSimulateOnDrop
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRGripInterface")
void CopyTo(FRepMovement &other) const
bool GatherActorsMovement(AActor *OwningActor)
USTRUCT(BlueprintType, Category = "VRExpansionLibrary|TransformNetQuantize", meta = (HasNativeMake = ...
int32 UpdateRate
UPROPERTY(EditAnywhere, NotReplicated, BlueprintReadOnly, Category = "VRReplication",...
bool bUseClientAuthThrowing
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRReplication")