Esempio n. 1
0
        private static void ProcessNode(Level level, BlockCoordinates coord, Queue <BlockCoordinates> lightBfsQueue)
        {
            //Log.Debug($"Setting light on block {block.Id} with LightLevel={block.LightLevel} and BlockLight={block.Blocklight}");
            ChunkColumn chunk = GetChunk(level, coord);

            if (chunk == null)
            {
                return;
            }

            int lightLevel = chunk.GetBlocklight(coord.X & 0x0f, coord.Y & 0xff, coord.Z & 0x0f);

            Test(level, coord, coord.BlockUp(), lightBfsQueue, chunk, lightLevel);
            Test(level, coord, coord.BlockDown(), lightBfsQueue, chunk, lightLevel);
            Test(level, coord, coord.BlockWest(), lightBfsQueue, chunk, lightLevel);
            Test(level, coord, coord.BlockEast(), lightBfsQueue, chunk, lightLevel);
            Test(level, coord, coord.BlockSouth(), lightBfsQueue, chunk, lightLevel);
            Test(level, coord, coord.BlockNorth(), lightBfsQueue, chunk, lightLevel);

            //SetLightLevel(level, lightBfsQueue, level.GetBlockId(coord + BlockCoordinates.Down, chunk), lightLevel);
            //SetLightLevel(level, lightBfsQueue, level.GetBlockId(coord + BlockCoordinates.West, chunk), lightLevel);
            //SetLightLevel(level, lightBfsQueue, level.GetBlockId(coord + BlockCoordinates.East, chunk), lightLevel);
            //SetLightLevel(level, lightBfsQueue, level.GetBlockId(coord + BlockCoordinates.South, chunk), lightLevel);
            //SetLightLevel(level, lightBfsQueue, level.GetBlockId(coord + BlockCoordinates.North, chunk), lightLevel);
        }
Esempio n. 2
0
        private static BlockCoordinates?FindRandomTargetBlock(Entity entity, int dxz, int dy, Vector3?targetDirectinon = null)
        {
            Random random = entity.Level.Random;

            BlockCoordinates coords = (BlockCoordinates)entity.KnownPosition;

            double currentWeight = double.MinValue;
            Block  currentBlock  = null;

            for (int i = 0; i < 10; i++)
            {
                int x = random.Next(2 * dxz + 1) - dxz;
                int y = random.Next(2 * dy + 1) - dy;
                int z = random.Next(2 * dxz + 1) - dxz;

                var blockCoordinates = new BlockCoordinates(x, y, z) + coords;
                var block            = entity.Level.GetBlock(blockCoordinates);
                var blockDown        = entity.Level.GetBlock(blockCoordinates.BlockDown());
                if (blockDown.IsSolid)
                {
                    double weight = CalculateBlockWeight(entity, block, blockDown);
                    if (weight > currentWeight)
                    {
                        currentWeight = weight;
                        currentBlock  = block;
                    }
                }
            }

            return(currentBlock?.Coordinates);
        }
Esempio n. 3
0
        private void ProcessNode(IBlockAccess level, ChunkColumn chunk, BlockCoordinates coordinates, Queue <BlockCoordinates> lightBfsQueue, HashSet <BlockCoordinates> lightBfSet)
        {
            //if (section.IsAllAir())

            byte currentSkyLight = GetSkyLight(coordinates, chunk);

            int       sectionIdx = coordinates.Y >> 4;
            ChunkBase section    = chunk.GetChunk(coordinates.Y);

            byte maxSkyLight = currentSkyLight;

            if (coordinates.Y < 255)
            {
                var up = coordinates.BlockUp();
                maxSkyLight = Math.Max(maxSkyLight, SetLightLevel(level, chunk, section, sectionIdx, lightBfsQueue, lightBfSet, up, currentSkyLight, up: true));
            }

            if (coordinates.Y > 0)
            {
                var down = coordinates.BlockDown();
                maxSkyLight = Math.Max(maxSkyLight, SetLightLevel(level, chunk, section, sectionIdx, lightBfsQueue, lightBfSet, down, currentSkyLight, down: true));
            }

            var west = coordinates.BlockWest();

            maxSkyLight = Math.Max(maxSkyLight, SetLightLevel(level, chunk, section, sectionIdx, lightBfsQueue, lightBfSet, west, currentSkyLight));


            var east = coordinates.BlockEast();

            maxSkyLight = Math.Max(maxSkyLight, SetLightLevel(level, chunk, section, sectionIdx, lightBfsQueue, lightBfSet, east, currentSkyLight));


            var south = coordinates.BlockSouth();

            maxSkyLight = Math.Max(maxSkyLight, SetLightLevel(level, chunk, section, sectionIdx, lightBfsQueue, lightBfSet, south, currentSkyLight));

            var north = coordinates.BlockNorth();

            maxSkyLight = Math.Max(maxSkyLight, SetLightLevel(level, chunk, section, sectionIdx, lightBfsQueue, lightBfSet, north, currentSkyLight));

            if (IsTransparent(coordinates, section) && currentSkyLight != 15)
            {
                int diffuseLevel = GetDiffuseLevel(coordinates, section);
                maxSkyLight = (byte)Math.Max(currentSkyLight, maxSkyLight - diffuseLevel);

                if (maxSkyLight > currentSkyLight)
                {
                    level.SetSkyLight(coordinates, maxSkyLight);

                    if (!lightBfSet.Contains(coordinates))
                    {
                        lightBfsQueue.Enqueue(coordinates);
                        lightBfSet.Add(coordinates);
                    }
                }
            }
        }
Esempio n. 4
0
		protected bool IsMobOnGround(Vector3 pos)
		{
			if (pos.Y - Math.Truncate(pos.Y) > 0.1)
				return IsMobInGround(pos);

			BlockCoordinates coord = pos;
			Block block = Level.GetBlock(coord.BlockDown());

			return block.IsSolid;
			//return block.IsSolid && block.GetBoundingBox().Contains(GetBoundingBox().OffsetBy(new Vector3(0, -0.1f, 0))) == ContainmentType.Intersects;
		}
Esempio n. 5
0
        public void ResetLight(Level level, Queue <BlockCoordinates> resetQueue, Queue <BlockCoordinates> sourceQueue, BlockCoordinates coordinates)
        {
            int currentLight = level.GetSkyLight(coordinates);

            if (coordinates.Y < 255)
            {
                TestForSource(level, resetQueue, sourceQueue, coordinates.BlockUp(), currentLight);
            }
            if (coordinates.Y > 0)
            {
                TestForSource(level, resetQueue, sourceQueue, coordinates.BlockDown(), currentLight, true);
            }
            TestForSource(level, resetQueue, sourceQueue, coordinates.BlockWest(), currentLight);
            TestForSource(level, resetQueue, sourceQueue, coordinates.BlockEast(), currentLight);
            TestForSource(level, resetQueue, sourceQueue, coordinates.BlockNorth(), currentLight);
            TestForSource(level, resetQueue, sourceQueue, coordinates.BlockSouth(), currentLight);
        }
Esempio n. 6
0
        protected bool IsMobOnGround(Vector3 pos)
        {
            if (pos.Y - Math.Truncate(pos.Y) > 0.1)
            {
                return(IsMobInGround(pos));
            }

            BlockCoordinates coord = pos;
            Block            block = Level.GetBlock(coord.BlockDown());

            if (block.IsSolid)
            {
                //return true;
                BoundingBox bbox = block.GetBoundingBox();
                return(pos.Y - bbox.Max.Y < 0.01);
            }

            return(false);
            //return block.IsSolid && block.GetBoundingBox().Contains(GetBoundingBox().OffsetBy(new Vector3(0, -0.1f, 0))) == ContainmentType.Intersects;
        }
Esempio n. 7
0
 private void PositionCheck()
 {
     if (Velocity.Y < -0.1)
     {
         int distance           = (int)Math.Ceiling(Velocity.Length());
         BlockCoordinates check = new BlockCoordinates(KnownPosition);
         for (int i = 0; i < distance; i++)
         {
             if (Level.GetBlock(check).IsSolid)
             {
                 _checkPosition = false;
                 KnownPosition  = check.BlockUp();
                 return;
             }
             check = check.BlockDown();
         }
     }
     KnownPosition.X += (float)Velocity.X;
     KnownPosition.Y += (float)Velocity.Y;
     KnownPosition.Z += (float)Velocity.Z;
 }
Esempio n. 8
0
        public void Calculate(Level level, BlockCoordinates coordinates)
        {
            int currentLight = level.GetSkyLight(coordinates);

            var chunk  = level.GetChunk(coordinates);
            var height = chunk.GetRecalatedHeight(coordinates.X & 0x0f, coordinates.Z & 0x0f);

            Queue <BlockCoordinates> sourceQueue = new Queue <BlockCoordinates>();

            sourceQueue.Enqueue(coordinates);
            if (currentLight != 0)
            {
                Queue <BlockCoordinates>   resetQueue = new Queue <BlockCoordinates>();
                HashSet <BlockCoordinates> visits     = new HashSet <BlockCoordinates>();

                // Reset all lights that potentially derive from this
                resetQueue.Enqueue(coordinates);

                Queue <BlockCoordinates> deleteQueue = new Queue <BlockCoordinates>();
                while (resetQueue.Count > 0)
                {
                    var coord = resetQueue.Dequeue();
                    if (visits.Contains(coord))
                    {
                        continue;
                    }

                    visits.Add(coord);

                    if (coord.DistanceTo(coordinates) > 16)
                    {
                        continue;
                    }

                    ResetLight(level, resetQueue, sourceQueue, coord);
                    if (!sourceQueue.Contains(coord))
                    {
                        deleteQueue.Enqueue(coord);
                    }
                }

                level.SetSkyLight(coordinates, 0);

                foreach (var delete in deleteQueue)
                {
                    level.SetSkyLight(delete, 0);
                }
            }
            else
            {
                sourceQueue.Enqueue(coordinates);
                sourceQueue.Enqueue(coordinates.BlockUp());
                sourceQueue.Enqueue(coordinates.BlockDown());
                sourceQueue.Enqueue(coordinates.BlockWest());
                sourceQueue.Enqueue(coordinates.BlockEast());
                sourceQueue.Enqueue(coordinates.BlockNorth());
                sourceQueue.Enqueue(coordinates.BlockSouth());
            }

            chunk.SetHeight(coordinates.X & 0x0f, coordinates.Z & 0x0f, (short)height);

            // Recalc
            Queue <BlockCoordinates>   lightBfQueue = new Queue <BlockCoordinates>(sourceQueue);
            HashSet <BlockCoordinates> lightBfSet   = new HashSet <BlockCoordinates>(sourceQueue);

            SkyLightBlockAccess blockAccess = new SkyLightBlockAccess(level.WorldProvider);

            Calculate(blockAccess, lightBfQueue, lightBfSet);
        }
Esempio n. 9
0
        private bool FindLog(Level level, BlockCoordinates coord, List <BlockCoordinates> visited, int distance)
        {
            if (visited.Contains(coord))
            {
                return(false);
            }

            var block = level.GetBlock(coord);

            if (block is Log)
            {
                return(true);
            }

            visited.Add(coord);

            if (distance >= 4)
            {
                return(false);
            }

            if (!(block is Leaves2))
            {
                return(false);
            }
            var leaves = (Leaves2)block;

            if (leaves.NewLeafType != NewLeafType)
            {
                return(false);
            }

            // check down
            if (FindLog(level, coord.BlockDown(), visited, distance + 1))
            {
                return(true);
            }
            // check west
            if (FindLog(level, coord.BlockWest(), visited, distance + 1))
            {
                return(true);
            }
            // check east
            if (FindLog(level, coord.BlockEast(), visited, distance + 1))
            {
                return(true);
            }
            // check south
            if (FindLog(level, coord.BlockSouth(), visited, distance + 1))
            {
                return(true);
            }
            // check north
            if (FindLog(level, coord.BlockNorth(), visited, distance + 1))
            {
                return(true);
            }
            // check up
            if (FindLog(level, coord.BlockUp(), visited, distance + 1))
            {
                return(true);
            }

            return(false);
        }
Esempio n. 10
0
        public IEnumerable <Tile> GetNeighbors(Tile start)
        {
            if (!_blockCache.TryGetValue(start, out var block))
            {
                block = _level.GetBlock(new BlockCoordinates(start.X, _startY, start.Y));
                _blockCache.Add(start, block);
            }

            HashSet <Tile> neighbors = new HashSet <Tile>();

            for (int index = 0; index < Neighbors.GetLength(0); ++index)
            {
                var item = new Tile3d(start.X + Neighbors[index, 0], start.Y + Neighbors[index, 1], block.Coordinates.Y);

                bool isDiagonalMove = item.X != start.X && item.Y != start.Y;
                if (isDiagonalMove)
                {
                    // Don't allow cutting corners where there is a block
                    Tile undiagonal = new Tile(start.X, start.Y + Neighbors[index, 1]);
                    if (!_blockCache.TryGetValue(undiagonal, out var udblock))
                    {
                        continue;
                    }
                    if (udblock.Coordinates.Y != block.Coordinates.Y)
                    {
                        continue;
                    }
                }

                // Check for too high steps
                BlockCoordinates coord = new BlockCoordinates(item.X, block.Coordinates.Y, item.Y);

                if (_level.GetBlock(coord).IsSolid)
                {
                    // Only allow diagonal movements if on same Y level
                    if (isDiagonalMove)
                    {
                        continue;
                    }

                    // Check if we hit head if we jump or climb up to next block
                    if (IsObstructed(block.Coordinates.BlockUp()))
                    {
                        continue;
                    }

                    if (_entity.CanClimb)
                    {
                        Block blockUp     = _level.GetBlock(coord.BlockUp());
                        Block currBlockUp = _level.GetBlock(block.Coordinates.BlockUp());                         // Check if we hit ceiling too
                        bool  canMove     = false;
                        for (int i = 0; i < 10; i++)
                        {
                            if (IsBlocked(blockUp) && !IsBlocked(currBlockUp))
                            {
                                blockUp     = _level.GetBlock(blockUp.Coordinates.BlockUp());
                                currBlockUp = _level.GetBlock(currBlockUp.Coordinates.BlockUp());
                                continue;
                            }

                            canMove = true;
                            break;
                        }

                        if (!canMove)
                        {
                            continue;
                        }

                        if (IsObstructed(blockUp.Coordinates))
                        {
                            continue;
                        }

                        if (_blockCache.TryGetValue(item, out var trash) && trash.Coordinates.Y != blockUp.Coordinates.Y)
                        {
                            //Log.Warn("Already had this coordinated but on different Y");
                            continue;
                        }
                        item.RealY        = blockUp.Coordinates.Y;
                        _blockCache[item] = blockUp;
                    }
                    else
                    {
                        // Check block collision box, not hit box
                        if (_level.GetBlock(coord) is Fence)
                        {
                            continue;
                        }

                        Block blockUp = _level.GetBlock(coord.BlockUp());
                        if (blockUp.IsSolid)
                        {
                            // Can't jump. This is hardwired for 1 block jump height for all mobs.
                            continue;
                        }

                        if (IsObstructed(blockUp.Coordinates))
                        {
                            continue;
                        }

                        //TODO: There is a problem when there is a path both under and over a block. It chooses the last checked block.
                        if (_blockCache.TryGetValue(item, out var trash) && trash.Coordinates.Y != blockUp.Coordinates.Y)
                        {
                            //Log.Warn("Already had this coordinated but on different Y");
                            continue;
                        }
                        item.RealY        = blockUp.Coordinates.Y;
                        _blockCache[item] = blockUp;
                    }
                }
                else
                {
                    if (IsObstructed(coord))
                    {
                        continue;
                    }

                    var blockDown = _level.GetBlock(coord.BlockDown());
                    if (blockDown.IsSolid)
                    {
                        // Continue on same Y level
                        if (_blockCache.TryGetValue(item, out var trash) && trash.Coordinates.Y != coord.Y)
                        {
                            //Log.Warn("Already had this coordinated but on different Y");
                            continue;
                        }
                        item.RealY        = coord.Y;
                        _blockCache[item] = _level.GetBlock(coord);
                    }
                    else
                    {
                        // Only allow diagonal movements if on same Y level
                        if (isDiagonalMove)
                        {
                            continue;
                        }

                        if (_entity.CanClimb)
                        {
                            bool canClimb = false;
                            blockDown = _level.GetBlock(blockDown.Coordinates.BlockDown());
                            for (int i = 0; i < 10; i++)
                            {
                                if (!blockDown.IsSolid)
                                {
                                    blockDown = _level.GetBlock(blockDown.Coordinates.BlockDown());
                                    continue;
                                }

                                canClimb = true;
                                break;
                            }

                            if (!canClimb)
                            {
                                continue;
                            }

                            blockDown = _level.GetBlock(blockDown.Coordinates.BlockUp());

                            if (IsObstructed(blockDown.Coordinates))
                            {
                                continue;
                            }

                            if (_blockCache.TryGetValue(item, out var trash) && trash.Coordinates.Y != blockDown.Coordinates.Y)
                            {
                                //Log.Warn("Already had this coordinated but on different Y");
                                continue;
                            }
                            item.RealY        = blockDown.Coordinates.Y;
                            _blockCache[item] = blockDown;
                        }
                        else
                        {
                            if (!_level.GetBlock(coord.BlockDown().BlockDown()).IsSolid)
                            {
                                // Will fall
                                continue;
                            }

                            if (IsObstructed(blockDown.Coordinates))
                            {
                                continue;
                            }

                            if (_blockCache.TryGetValue(item, out var trash) && trash.Coordinates.Y != blockDown.Coordinates.Y)
                            {
                                //Log.Warn("Already had this coordinated but on different Y");
                                continue;
                            }
                            item.RealY        = blockDown.Coordinates.Y;
                            _blockCache[item] = blockDown;
                        }
                    }
                }

                neighbors.Add(item);
            }

            CheckDiagonals(block, neighbors);

            return(neighbors);
        }
Esempio n. 11
0
        public bool Generate(Level level, BlockCoordinates position)
        {
            Random rand   = new Random();
            int    height = rand.Next(3) + _minTreeHeight;

            bool canGrow = true;

            if (position.Y >= 1 && position.Y + height + 1 <= 256)
            {
                for (int y = position.Y; y <= position.Y + 1 + height; ++y)
                {
                    int k = 1;

                    if (y == position.Y)
                    {
                        k = 0;
                    }

                    if (y >= position.Y + 1 + height - 2)
                    {
                        k = 2;
                    }

                    for (int x = position.X - k; x <= position.X + k && canGrow; ++x)
                    {
                        for (int z = position.Z - k; z <= position.Z + k && canGrow; ++z)
                        {
                            if (y >= 0 && y < 256)
                            {
                                if (!CanGrowInto(level.GetBlock(x, y, z)))
                                {
                                    canGrow = false;
                                }
                            }
                            else
                            {
                                canGrow = false;
                            }
                        }
                    }
                }

                if (!canGrow)
                {
                    return(false);
                }
                else
                {
                    Block block = level.GetBlock(position.BlockDown());

                    if ((block is Grass || block is Dirt || block is Farmland) && position.Y < 256 - height - 1)
                    {
                        level.SetBlock(new Dirt {
                            Coordinates = position.BlockDown()
                        });

                        for (int y = position.Y - 3 + height; y <= position.Y + height; ++y)
                        {
                            int yd     = y - (position.Y + height);
                            int ydHalf = 1 - yd / 2;

                            for (int x = position.X - ydHalf; x <= position.X + ydHalf; ++x)
                            {
                                int xd = x - position.X;

                                for (int z = position.Z - ydHalf; z <= position.Z + ydHalf; ++z)
                                {
                                    int zd = z - position.Z;

                                    if (Math.Abs(xd) != ydHalf || Math.Abs(zd) != ydHalf || rand.Next(2) != 0 && yd != 0)
                                    {
                                        BlockCoordinates blockpos = new BlockCoordinates(x, y, z);
                                        Block            material = level.GetBlock(blockpos);

                                        if (material is Air || material is Leaves || material is Leaves2)
                                        {
                                            _leave.Coordinates = blockpos;
                                            level.SetBlock(_leave);
                                        }
                                    }
                                }
                            }
                        }

                        for (int y = 0; y < height; ++y)
                        {
                            BlockCoordinates blockpos = position + (BlockCoordinates.Up * y);
                            Block            material = level.GetBlock(blockpos);

                            if (material is Air || material is Leaves || material is Leaves2)
                            {
                                _log.Coordinates = blockpos;
                                level.SetBlock(_log);
                            }
                        }

                        return(true);
                    }
                    else
                    {
                        return(false);
                    }
                }
            }
            else
            {
                return(false);
            }
        }
Esempio n. 12
0
        public void MoveForward(double speedMultiplier, Entity[] entities)
        {
            if (_jumpCooldown > 0)
            {
                _jumpCooldown--;
                //return;
            }

            float speedFactor  = (float)(_entity.Speed * speedMultiplier * 0.7f);
            var   level        = _entity.Level;
            var   currPosition = _entity.KnownPosition;
            var   direction    = Vector3.Normalize(_entity.GetHorizDir() * new Vector3(1, 0, 1));

            bool entityCollide = false;
            var  boundingBox   = _entity.GetBoundingBox().OffsetBy(direction * speedFactor);

            var players = level.GetSpawnedPlayers();

            foreach (var player in players)
            {
                var bbox = boundingBox + 0.15f;
                if (player.GetBoundingBox().Intersects(bbox))
                {
                    entityCollide = true;
                    break;
                }
            }

            if (!entityCollide)
            {
                var bbox = boundingBox + 0.3f;
                foreach (var ent in entities)
                {
                    if (ent == _entity)
                    {
                        continue;
                    }

                    if (ent.EntityId < _entity.EntityId && _entity.IsColliding(bbox, ent))
                    {
                        if (_entity.Velocity == Vector3.Zero && level.Random.Next(1000) == 0)
                        {
                            break;
                        }
                        entityCollide = true;
                        break;
                    }
                }
            }

            BlockCoordinates coord = (BlockCoordinates)(currPosition + (direction * speedFactor) + (direction * (float)(_entity.Length * 0.5f)));
            var block     = level.GetBlock(coord);
            var blockUp   = level.GetBlock(coord.BlockUp());
            var blockUpUp = level.GetBlock(coord.BlockUp().BlockUp());

            var colliding = block.IsSolid || (_entity.Height > 1 && blockUp.IsSolid);

            if (!colliding && !entityCollide)
            {
                var blockDown = level.GetBlock(coord.BlockDown());
                if (!_entity.IsOnGround && !blockDown.IsSolid)
                {
                    return;
                }

                //Log.Debug($"Move forward: {block}, {(_entity.IsOnGround ? "On ground" : "not on ground")}, Position: {(Vector3) _entity.KnownPosition}");
                //if (!_entity.IsOnGround) return;

                var velocity = direction * speedFactor;
                //Log.Debug($"Moving sheep ({_entity.KnownPosition.Yaw}: {velocity}, {_entity.Velocity}");
                if ((_entity.Velocity * new Vector3(1, 0, 1)).Length() < velocity.Length())
                {
                    _entity.Velocity += velocity - _entity.Velocity;
                }
                else
                {
                    _entity.Velocity = velocity;
                }
            }
            else
            {
                if (_entity.CanClimb && !entityCollide)
                {
                    _entity.Velocity = new Vector3(0, 0.2f, 0);
                }
                else if (!entityCollide && !blockUp.IsSolid && !(_entity.Height > 1 && blockUpUp.IsSolid) /*&& level.Random.Next(4) != 0*/)
                {
                    // Above is wrong. Checks the wrong block in the wrong way.

                    //Log.Debug($"Block ahead: {block}, {(_entity.IsOnGround ? "jumping" : "no jump")}, Position: {(Vector3)_entity.KnownPosition}");
                    //_entity.Level.SetBlock(new StainedGlass() {Coordinates = block.Coordinates, Metadata = (byte) _entity.Level.Random.Next(16)});

                    if (_entity.IsOnGround && _jumpCooldown <= 0)
                    {
                        _jumpCooldown     = 10;
                        _entity.Velocity += new Vector3(0, 0.42f, 0);
                    }
                }
                else
                {
                    if (entityCollide)
                    {
                        //Log.Debug($"Entity ahead: {block}, stopping");
                        _entity.Velocity *= new Vector3(0, 1, 0);
                    }
                    else
                    {
                        //Log.Debug($"Block ahead: {block}, ignoring");
                        //_entity.Level.SetBlock(new StainedGlass() { Coordinates = block.Coordinates + BlockCoordinates.Down, Metadata = (byte)_entity.Level.Random.Next(16) });
                        _entity.Velocity *= new Vector3(0, 1, 0);
                    }
                }
            }
        }