public object Raycast(Ray3 ray, RaycastMode mode, bool raycastTerrain = true, bool raycastBodies = true, bool raycastMovingBlocks = true) { float reach = (m_subsystemGameInfo.WorldSettings.GameMode == GameMode.Creative) ? SettingsManager.CreativeReach : 5f; Vector3 creaturePosition = ComponentCreature.ComponentCreatureModel.EyePosition; Vector3 start = ray.Position; Vector3 direction = Vector3.Normalize(ray.Direction); Vector3 end = ray.Position + direction * 15f; Point3 startCell = Terrain.ToCell(start); BodyRaycastResult? bodyRaycastResult = m_subsystemBodies.Raycast(start, end, 0.35f, (ComponentBody body, float distance) => (Vector3.DistanceSquared(start + distance * direction, creaturePosition) <= reach * reach && body.Entity != base.Entity && !body.IsChildOfBody(ComponentCreature.ComponentBody) && !ComponentCreature.ComponentBody.IsChildOfBody(body) && Vector3.Dot(Vector3.Normalize(body.BoundingBox.Center() - start), direction) > 0.7f) ? true : false); MovingBlocksRaycastResult?movingBlocksRaycastResult = m_subsystemMovingBlocks.Raycast(start, end, extendToFillCells: true); TerrainRaycastResult? terrainRaycastResult = m_subsystemTerrain.Raycast(start, end, useInteractionBoxes : true, skipAirBlocks : true, delegate(int value, float distance) { if (Vector3.DistanceSquared(start + distance * direction, creaturePosition) <= reach * reach) { Block block = BlocksManager.Blocks[Terrain.ExtractContents(value)]; if (distance == 0f && block is CrossBlock && Vector3.Dot(direction, new Vector3(startCell) + new Vector3(0.5f) - start) < 0f) { return(false); } if (mode == RaycastMode.Digging) { return(!block.IsDiggingTransparent); } if (mode == RaycastMode.Interaction) { if (block.IsPlacementTransparent) { return(block.IsInteractive(m_subsystemTerrain, value)); } return(true); } if (mode == RaycastMode.Gathering) { return(block.IsGatherable); } } return(false); }); float num = bodyRaycastResult.HasValue ? bodyRaycastResult.Value.Distance : float.PositiveInfinity; float num2 = movingBlocksRaycastResult.HasValue ? movingBlocksRaycastResult.Value.Distance : float.PositiveInfinity; float num3 = terrainRaycastResult.HasValue ? terrainRaycastResult.Value.Distance : float.PositiveInfinity; if (num < num2 && num < num3) { return(bodyRaycastResult.Value); } if (num2 < num && num2 < num3) { return(movingBlocksRaycastResult.Value); } if (num3 < num && num3 < num2) { return(terrainRaycastResult.Value); } return(new Ray3(start, direction)); }