Exemplo n.º 1
0
        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));
        }