bool Process3x3(SpatialConstraintGrid3x3 constraint, PropSocket socket, DungeonModel model)
        {
            var isaacModel = model as GridDungeonModel;

            if (isaacModel == null)
            {
                return(false);
            }

            for (int dx = -1; dx <= 1; dx++)
            {
                for (int dz = -1; dz <= 1; dz++)
                {
                    var cx             = dx + 1;
                    var cz             = 2 - (dz + 1);
                    var index          = cz * 3 + cx;
                    var constraintType = constraint.cells[index];
                    var adjacentPos    = socket.gridPosition + new IntVector(dx, 0, dz);
                    var occupied       = IsOccupied(adjacentPos);
                    if (occupied && constraintType.CellType == SpatialConstraintGridCellType.Empty)
                    {
                        // Expected an empty cell and got an occupied cell
                        return(false);
                    }
                    if (!occupied && constraintType.CellType == SpatialConstraintGridCellType.Occupied)
                    {
                        // Expected an occupied cell and got an empty cell
                        return(false);
                    }
                }
            }

            // All tests passed
            return(true);
        }
        bool Process3x3(SpatialConstraintGrid3x3 constraint, PropSocket socket, DungeonModel model)
        {
            var roomId     = socket.cellId;
            var isaacModel = model as IsaacDungeonModel;

            if (isaacModel == null)
            {
                return(false);
            }

            var room = IsaacBuilderUtils.GetRoom(isaacModel, roomId);

            if (room == null)
            {
                return(false);
            }

            int x, z;

            GetLayoutPosition(room, isaacModel, socket.Transform, out x, out z);

            for (int dx = -1; dx <= 1; dx++)
            {
                for (int dz = -1; dz <= 1; dz++)
                {
                    var  cx             = dx + 1;
                    var  cz             = 2 - (dz + 1);
                    var  index          = cz * 3 + cx;
                    var  constraintType = constraint.cells[index];
                    var  mapTileType    = IsaacBuilderUtils.GetTileAt(x + dx, z + dz, room.layout);
                    bool empty          = (mapTileType.tileType != IsaacRoomTileType.Floor);
                    if (empty && constraintType.CellType == SpatialConstraintGridCellType.Occupied)
                    {
                        // Expected an occupied cell and got an empty cell
                        return(false);
                    }
                    if (!empty && constraintType.CellType == SpatialConstraintGridCellType.Empty)
                    {
                        // Expected an empty cell and got an occupied cell
                        return(false);
                    }
                }
            }

            // All tests passed
            return(true);
        }
        bool Process3x3(SpatialConstraintGrid3x3 constraint, PropSocket socket, DungeonModel model, ref Matrix4x4 outOffset)
        {
            var gridModel = model as GridDungeonModel;

            if (gridModel == null)
            {
                return(false);
            }

            int rotationsRequired = constraint.rotateToFit ? 4 : 1;

            SpatialConstraintGridCell[] constraintCells = constraint.cells;
            for (int rotIndex = 0; rotIndex < rotationsRequired; rotIndex++)
            {
                int baseCellId = -1;
                if (groundPositions.ContainsKey(socket.gridPosition))
                {
                    baseCellId = groundPositions[socket.gridPosition];
                }
                CellType baseCellType = GetCellTypeFromId(baseCellId, gridModel);

                bool isValid = true;
                for (int dx = -1; dx <= 1; dx++)
                {
                    for (int dz = -1; dz <= 1; dz++)
                    {
                        var cx             = dx + 1;
                        var cz             = 2 - (dz + 1);
                        var index          = cz * 3 + cx;
                        var constraintType = constraintCells[index];
                        var adjacentPos    = socket.gridPosition + new IntVector(dx, 0, dz);
                        int adjacentCellId;
                        var occupied = IsOccupied(adjacentPos, out adjacentCellId);

                        CellType adjacentCellType = GetCellTypeFromId(adjacentCellId, gridModel);

                        if (occupied && adjacentCellType != baseCellType && !mergeRoomCorridor)
                        {
                            occupied = false;
                        }

                        if (occupied && constraintType.CellType == SpatialConstraintGridCellType.Empty)
                        {
                            // Expected an empty cell and got an occupied cell
                            isValid = false;
                            break;
                        }
                        if (!occupied && constraintType.CellType == SpatialConstraintGridCellType.Occupied)
                        {
                            // Expected an occupied cell and got an empty cell
                            isValid = false;
                            break;
                        }
                    }
                    if (!isValid)
                    {
                        break;
                    }
                }
                if (isValid)
                {
                    int        rotationAngle = -90 * rotIndex;
                    Quaternion rotation      = Quaternion.Euler(0, rotationAngle, 0);
                    outOffset = Matrix4x4.TRS(Vector3.zero, rotation, Vector3.one);
                    return(true);
                }
                constraintCells = Rotate3x3(constraintCells);
            }


            // All tests failed
            return(false);
        }