public bool CheckChest()
        {
            if (workChest == null)
            {
                return(false);
            }

            blockCheck.Begin();
            Block check = blockCheck.GetBlock(workChest);

            if (!blockCheck.LastChunkLoaded)
            {
                return(false);
            }
            if (entity.World.BlockAccessor.GetBlockEntity(workChest) is BlockEntityGenericTypedContainer)
            {
                return(true);
            }

            RemoveChest();
            return(false);
        }
Ejemplo n.º 2
0
        protected bool traversable(PathNode node, float stepHeight, int maxFallHeight, Cuboidf entityCollBox, bool isDiagonal, ref float extraCost)
        {
            tmpVec.Set(node.X + centerOffsetX, node.Y, node.Z + centerOffsetZ);

            if (!api.World.CollisionTester.IsColliding(blockAccess, entityCollBox, tmpVec, false))
            {
                // Down ok?
                while (true)
                {
                    tmpPos.Set(node.X, node.Y - 1, node.Z);

                    Block block = blockAccess.GetBlock(tmpPos);
                    if (block.LiquidCode == "lava")
                    {
                        return(false);                            // TODO: Turn into an entityAvoid boolean
                    }
                    if (block.LiquidCode == "water")
                    {
                        extraCost = 5;
                        //node.Y--; - we swim on top
                        break;
                    }

                    tmpVec.Y--;

                    // Do we collide if we go one block down?
                    // Our hitbox size might be >1 and we might collide with a wall only
                    // so also test if there is actually any collision box right below us.

                    // If collision but no collision box below: Can't really wall-walk, so fail
                    // If no collision but hitbox below: I guess we can step on it to continue from here?
                    // If no collision and no hitbox below: Free fall, lets keep searching downwards

                    Cuboidf[] collboxes           = block.GetCollisionBoxes(blockAccess, tmpPos);
                    bool      collidingBlockBelow = collboxes != null && collboxes.Length > 0;

                    if (api.World.CollisionTester.IsColliding(blockAccess, entityCollBox, tmpVec, false))
                    {
                        if (!collidingBlockBelow)
                        {
                            return(false);
                        }

                        extraCost -= (block.WalkSpeedMultiplier - 1) * 8;
                        break;
                    }
                    else
                    {
                        if (collidingBlockBelow)
                        {
                            extraCost -= (block.WalkSpeedMultiplier - 1) * 8;
                            break;
                        }
                    }


                    node.Y--;
                    maxFallHeight--;

                    if (maxFallHeight < 0)
                    {
                        return(false);
                    }
                }

                // Up ok?
                float height = entityCollBox.Height;
                while (height-- > 0)
                {
                    tmpVec.Y++;
                    if (api.World.CollisionTester.IsColliding(blockAccess, entityCollBox, tmpVec, false))
                    {
                        return(false);
                    }
                }

                return(true);
            }
            else
            {
                tmpVec.Set(node.X + centerOffsetX, node.Y + stepHeight, node.Z + centerOffsetZ);
                bool collideAbove = api.World.CollisionTester.GetCollidingCollisionBox(blockAccess, entityCollBox, tmpVec, ref tmpCub, false);

                if (!collideAbove)
                {
                    if (isDiagonal)
                    {
                        tmpPos.Set(node.X, node.Y, node.Z);
                        Block     block     = blockAccess.GetBlock(tmpPos);
                        Cuboidf[] collboxes = block.GetCollisionBoxes(blockAccess, tmpPos);

                        if (collboxes != null && collboxes.Length > 0)
                        {
                            // Ok, can step on this block
                            node.Y++;
                            return(true);
                        }
                    }
                    else
                    {
                        node.Y++;
                        return(true);
                    }
                }
            }


            return(false);
        }
Ejemplo n.º 3
0
        private Room FindRoomForPosition(BlockPos pos, ChunkRooms otherRooms)
        {
            QueueOfInt bfsQueue = new QueueOfInt();

            int halfSize = (ARRAYSIZE - 1) / 2;
            int maxSize  = halfSize + halfSize;

            bfsQueue.Enqueue(halfSize << 10 | halfSize << 5 | halfSize);

            int visitedIndex = (halfSize * ARRAYSIZE + halfSize) * ARRAYSIZE + halfSize; // Center node
            int iteration    = ++this.iteration;

            currentVisited[visitedIndex] = iteration;

            int coolingWallCount    = 0;
            int nonCoolingWallCount = 0;

            int skyLightCount    = 0;
            int nonSkyLightCount = 0;
            int exitCount        = 0;

            blockAccess.Begin();

            bool allChunksLoaded = true;

            int      minx = halfSize, miny = halfSize, minz = halfSize, maxx = halfSize, maxy = halfSize, maxz = halfSize;
            int      posX = pos.X - halfSize;
            int      posY = pos.Y - halfSize;
            int      posZ = pos.Z - halfSize;
            BlockPos npos = new BlockPos();
            BlockPos bpos = new BlockPos();
            int      dx, dy, dz;

            while (bfsQueue.Count > 0)
            {
                int compressedPos = bfsQueue.Dequeue();
                dx = compressedPos >> 10;
                dy = (compressedPos >> 5) & 0x1f;
                dz = compressedPos & 0x1f;
                npos.Set(posX + dx, posY + dy, posZ + dz);
                bpos.Set(npos);

                if (dx < minx)
                {
                    minx = dx;
                }
                else if (dx > maxx)
                {
                    maxx = dx;
                }

                if (dy < miny)
                {
                    miny = dy;
                }
                else if (dy > maxy)
                {
                    maxy = dy;
                }

                if (dz < minz)
                {
                    minz = dz;
                }
                else if (dz > maxz)
                {
                    maxz = dz;
                }

                Block bBlock = blockAccess.GetBlock(bpos);

                foreach (BlockFacing facing in BlockFacing.ALLFACES)
                {
                    facing.IterateThruFacingOffsets(npos);  // This must be the first command in the loop, to ensure all facings will be properly looped through regardless of any 'continue;' statements

                    // We cannot exit current block, if the facing is heat retaining (e.g. chiselled block with solid side)
                    if (bBlock.Id != 0 && bBlock.GetHeatRetention(bpos, facing) != 0)
                    {
                        continue;
                    }

                    if (!blockAccess.IsValidPos(npos))
                    {
                        nonCoolingWallCount++;
                        continue;
                    }

                    Block nBlock = blockAccess.GetBlock(npos);
                    allChunksLoaded &= blockAccess.LastChunkLoaded;
                    int heatRetention = nBlock.GetHeatRetention(npos, facing.Opposite);

                    // We hit a wall, no need to scan further
                    if (heatRetention != 0)
                    {
                        if (heatRetention < 0)
                        {
                            coolingWallCount -= heatRetention;
                        }
                        else
                        {
                            nonCoolingWallCount += heatRetention;
                        }

                        continue;
                    }

                    // Compute the new dx, dy, dz offsets for npos
                    dx = npos.X - posX;
                    dy = npos.Y - posY;
                    dz = npos.Z - posZ;

                    // Only traverse within maxSize range, and overall room size must not exceed MAXROOMSIZE
                    //   If outside that, count as an exit and don't continue searching in this direction
                    //   Note: for performance, this switch statement ensures only one conditional check in each case on the dimension which has actually changed, instead of 6 conditionals or more
                    bool outsideCube = false;
                    switch (facing.Index)
                    {
                    case 0:     // North
                        if (dz < minz)
                        {
                            outsideCube = dz < 0 || maxz - minz >= MAXROOMSIZE;
                        }
                        break;

                    case 1:     // East
                        if (dx > maxx)
                        {
                            outsideCube = dx > maxSize || maxx - minx >= MAXROOMSIZE;
                        }
                        break;

                    case 2:     // South
                        if (dz > maxz)
                        {
                            outsideCube = dz > maxSize || maxz - minz >= MAXROOMSIZE;
                        }
                        break;

                    case 3:     // West
                        if (dx < minx)
                        {
                            outsideCube = dx < 0 || maxx - minx >= MAXROOMSIZE;
                        }
                        break;

                    case 4:     // Up
                        if (dy > maxy)
                        {
                            outsideCube = dy > maxSize || maxy - miny >= MAXROOMSIZE;
                        }
                        break;

                    case 5:     // Down
                        if (dy < miny)
                        {
                            outsideCube = dy < 0 || maxy - miny >= MAXROOMSIZE;
                        }
                        break;
                    }
                    if (outsideCube)
                    {
                        exitCount++;
                        continue;
                    }


                    visitedIndex = (dx * ARRAYSIZE + dy) * ARRAYSIZE + dz;
                    if (currentVisited[visitedIndex] == iteration)
                    {
                        continue;                                              // continue if block position was already visited
                    }
                    currentVisited[visitedIndex] = iteration;

                    // We only need to check the skylight if it's a block position not already visited ...
                    int skyLightIndex = dx * ARRAYSIZE + dz;
                    if (skyLightXZChecked[skyLightIndex] < iteration)
                    {
                        skyLightXZChecked[skyLightIndex] = iteration;
                        int light = blockAccess.GetLightLevel(npos, EnumLightLevelType.OnlySunLight);

                        if (light >= api.World.SunBrightness - 1)
                        {
                            skyLightCount++;
                        }
                        else
                        {
                            nonSkyLightCount++;
                        }
                    }

                    bfsQueue.Enqueue(dx << 10 | dy << 5 | dz);
                }
            }



            int sizex = maxx - minx + 1;
            int sizey = maxy - miny + 1;
            int sizez = maxz - minz + 1;

            byte[] posInRoom = new byte[(sizex * sizey * sizez + 7) / 8];

            int volumeCount = 0;

            for (dx = 0; dx < sizex; dx++)
            {
                for (dy = 0; dy < sizey; dy++)
                {
                    visitedIndex = ((dx + minx) * ARRAYSIZE + (dy + miny)) * ARRAYSIZE + minz;
                    for (dz = 0; dz < sizez; dz++)
                    {
                        if (currentVisited[visitedIndex + dz] == iteration)
                        {
                            int index = (dy * sizez + dz) * sizex + dx;

                            posInRoom[index / 8] = (byte)(posInRoom[index / 8] | (1 << (index % 8)));
                            volumeCount++;
                        }
                    }
                }
            }

            bool isCellar = sizex <= MAXCELLARSIZE && sizey <= MAXCELLARSIZE && sizez <= MAXCELLARSIZE;

            if (!isCellar && volumeCount <= ALTMAXCELLARVOLUME)
            {
                isCellar = sizex <= ALTMAXCELLARSIZE && sizey <= MAXCELLARSIZE && sizez <= MAXCELLARSIZE ||
                           sizex <= MAXCELLARSIZE && sizey <= ALTMAXCELLARSIZE && sizez <= MAXCELLARSIZE ||
                           sizex <= MAXCELLARSIZE && sizey <= MAXCELLARSIZE && sizez <= ALTMAXCELLARSIZE;
            }


            return(new Room()
            {
                CoolingWallCount = coolingWallCount,
                NonCoolingWallCount = nonCoolingWallCount,
                SkylightCount = skyLightCount,
                NonSkylightCount = nonSkyLightCount,
                ExitCount = exitCount,
                AnyChunkUnloaded = allChunksLoaded ? 0 : 1,
                Location = new Cuboidi(posX + minx, posY + miny, posZ + minz, posX + maxx, posY + maxy, posZ + maxz),
                PosInRoom = posInRoom,
                IsSmallRoom = isCellar && exitCount == 0
            });
        }
Ejemplo n.º 4
0
        private Room FindRoomForPosition(BlockPos pos, ChunkRooms otherRooms, HashSet <BlockPos> visitedPositions)
        {
            Queue <BlockPos> bfsQueue = new Queue <BlockPos>();

            bfsQueue.Enqueue(pos);
            visitedPositions.Add(pos);

            int maxHalfSize = 7;

            int coolingWallCount    = 0;
            int nonCoolingWallCount = 0;

            int skyLightCount    = 0;
            int nonSkyLightCount = 0;
            int exitCount        = 0;

            blockAccess.Begin();

            HashSet <Vec2i> skyLightXZChecked = new HashSet <Vec2i>();

            bool allChunksLoaded = true;

            int minx = pos.X, miny = pos.Y, minz = pos.Z, maxx = pos.X + 1, maxy = pos.Y + 1, maxz = pos.Z + 1;

            while (bfsQueue.Count > 0)
            {
                BlockPos bpos = bfsQueue.Dequeue();

                foreach (BlockFacing facing in BlockFacing.ALLFACES)
                {
                    BlockPos npos = bpos.AddCopy(facing);

                    if (!api.World.BlockAccessor.IsValidPos(npos))
                    {
                        nonCoolingWallCount++;
                        continue;
                    }

                    Block nBlock = blockAccess.GetBlock(npos);
                    allChunksLoaded &= blockAccess.LastChunkLoaded;
                    int heatRetention = nBlock.GetHeatRetention(npos, facing);

                    // We hit a wall, no need to scan further
                    if (heatRetention != 0)
                    {
                        if (heatRetention < 0)
                        {
                            coolingWallCount -= heatRetention;
                        }
                        else
                        {
                            nonCoolingWallCount += heatRetention;
                        }

                        continue;
                    }

                    // Only traverse within maxHalfSize range
                    bool inCube = Math.Abs(npos.X - pos.X) <= maxHalfSize && Math.Abs(npos.Y - pos.Y) <= maxHalfSize && Math.Abs(npos.Z - pos.Z) <= maxHalfSize;

                    // Outside maxHalfSize range. Count as exit and don't continue searching in this direction
                    if (!inCube)
                    {
                        exitCount++;
                        continue;
                    }

                    minx = Math.Min(minx, bpos.X);
                    miny = Math.Min(miny, bpos.Y);
                    minz = Math.Min(minz, bpos.Z);

                    maxx = Math.Max(maxx, bpos.X);
                    maxy = Math.Max(maxy, bpos.Y);
                    maxz = Math.Max(maxz, bpos.Z);

                    Vec2i vec = new Vec2i(npos.X, npos.Z);
                    if (!skyLightXZChecked.Contains(vec))
                    {
                        skyLightXZChecked.Add(vec);

                        int light = api.World.BlockAccessor.GetLightLevel(npos, EnumLightLevelType.OnlySunLight);

                        if (light >= api.World.SunBrightness - 1)
                        {
                            skyLightCount++;
                        }
                        else
                        {
                            nonSkyLightCount++;
                        }
                    }


                    if (!visitedPositions.Contains(npos))
                    {
                        bfsQueue.Enqueue(npos);
                        visitedPositions.Add(npos);
                    }
                }
            }

            // Find all rooms inside this boundary
            // Lame but what can we do salasinji

            /*BlockPos cpos = new BlockPos();
             * for (int x = minx; x < maxx; x++)
             * {
             *  for (int y = miny; y < maxy; y++)
             *  {
             *      for (int z = minz; z < maxz; z++)
             *      {
             *          cpos.Set(x, y, z);
             *          if (visitedPositions.Contains(cpos)) continue;
             *
             *          Block cBlock = api.World.BlockAccessor.GetBlock(cpos);
             *          if (cBlock.Replaceable > 6000)
             *          {
             *              bool contains = false;
             *              for (int i = 0; !contains && i < otherRooms.Rooms.Count; i++)
             *              {
             *                  Room exroom = otherRooms.Rooms[i];
             *                  contains = exroom.Location.Contains(pos);
             *              }
             *
             *              if (!contains)
             *              {
             *                  Room room = FindRoomForPosition(cpos, otherRooms, visitedPositions);
             *                  otherRooms.AddRoom(room);
             *              }
             *          }
             *      }
             *  }
             * }*/

            return(new Room()
            {
                CoolingWallCount = coolingWallCount,
                NonCoolingWallCount = nonCoolingWallCount,
                SkylightCount = skyLightCount,
                NonSkylightCount = nonSkyLightCount,
                ExitCount = exitCount,
                AnyChunkUnloaded = !allChunksLoaded,
                Location = new Cuboidi(minx, miny, minz, maxx, maxy, maxz)
            });
        }