First validate the existing/synced cursor.
If there is a real cursor hit but it is not valid liquid, do not synthesize water. This prevents looking at ground/terrain near a pond from creating a synthetic cursor.
Server stops here. It should not invent a cursor from camera state.
Client fallback: build synthetic cursor only when current cursor is invalid.
Do not immediately drop a previously valid cursor. A single frame can fail because the camera ray is shallow or surface detection missed.
Validate the generated cursor once.
637 {
638 resolvedHitPosition = currentHitPosition;
640
642 if (
TryValidateHitCursor(player, playerPos, currentHitPosition, resolvedHitPosition, resolvedLiquidType))
643 return true;
644
646 if (currentHitPosition != vector.Zero)
647 {
649
650 #ifdef DIAG_DEVELOPER
651 if (m_DebugSyntheticCursor)
652 DebugDrawSyntheticCursor(player, currentHitPosition, vector.Zero,
false,
"current non-liquid hit prevents synthetic cursor",
LIQUID_NONE);
653 else
654 ClearDebugCursorShapes();
655 #endif
656
657 return false;
658 }
659
661 if (
g_Game.IsHeadlessOrDedicatedServer())
662 return false;
663
665 vector syntheticHitPosition;
666 int syntheticLiquidType;
667
669 {
672 {
673 #ifdef DIAG_DEVELOPER
674 if (m_DebugSyntheticCursor)
675 DebugDrawSyntheticCursor(player, currentHitPosition, resolvedHitPosition, true, "accepted cached synthetic cursor", resolvedLiquidType);
676 else
677 ClearDebugCursorShapes();
678 #endif
679
680 return true;
681 }
682
684
685 #ifdef DIAG_DEVELOPER
686 if (m_DebugSyntheticCursor)
687 DebugDrawSyntheticCursor(player, currentHitPosition, syntheticHitPosition,
false,
"synthetic cursor failed",
LIQUID_NONE);
688 else
689 ClearDebugCursorShapes();
690 #endif
691
692 return false;
693 }
694
696 if (!
TryValidateHitCursor(player, playerPos, syntheticHitPosition, resolvedHitPosition, resolvedLiquidType))
697 {
699
700 #ifdef DIAG_DEVELOPER
701 if (m_DebugSyntheticCursor)
702 DebugDrawSyntheticCursor(player, currentHitPosition, syntheticHitPosition, false, "synthetic cursor invalid after build", syntheticLiquidType);
703 else
704 ClearDebugCursorShapes();
705 #endif
706
707 return false;
708 }
709
710 #ifdef DIAG_DEVELOPER
711 if (m_DebugSyntheticCursor)
712 DebugDrawSyntheticCursor(player, currentHitPosition, resolvedHitPosition, true, "accepted synthetic cursor", resolvedLiquidType);
713 else
714 ClearDebugCursorShapes();
715 #endif
716
717 return true;
718 }
void ClearSyntheticCursorCache()
bool TryBuildSyntheticCursor(PlayerBase player, vector playerPos, out vector syntheticHitPosition, out int syntheticLiquidType)
bool TryUseCachedSyntheticCursor(PlayerBase player, vector playerPos, vector currentHitPosition, out vector resolvedHitPosition, out int resolvedLiquidType)
bool TryValidateHitCursor(PlayerBase player, vector playerPos, vector hitPosition, out vector resolvedHitPosition, out int resolvedLiquidType)