{-# LANGUAGE RecordWildCards #-}
{-
License:
This code is placed in the Public Domain.
Author:
Douglas Burke (dburke.gw@gmail.com)
Usage:
./flatten []
Convert all blocks within the given distance of the player,
and at a height one below that of the player, to gold.
Any blocks above this are removed.
If radius is not given then it defaults to 5. There is no
sanity check to ensure that radius is positive.
It could check that we are not about to place blocks onto
air/water.
-}
module Main where
import Control.Monad (forM_, when)
import Control.Monad.IO.Class
import Data.Maybe (listToMaybe)
import System.Environment
import System.Exit
import System.IO
import Data.MineCraft.Pi.Block
import Data.MineCraft.Pi.Other
import Data.MineCraft.Pi.Player
import Data.MineCraft.Pi.Types
import Network.MineCraft.Pi.Client
-- | Given x0,y0 and a radius, return all the block positions within
-- the circle. We use the coordinate of each block to determine
-- whether it is in or out.
--
-- Could be much-more efficient.
circleCoords :: Int -> Int -> Int -> [(Int, Int)]
circleCoords x0 y0 r =
let r2 = r * r
isIn (a,b) = (a-x0)*(a-x0) + (b-y0)*(b-y0) <= r2
in filter isIn [(i,j) | i <- [x0-r .. x0+r], j <- [y0-r .. y0+r]]
-- | Flatten the area surrounding the user to a distance
-- of r (radius) blocks. The ground is set to the given
-- block type.
--
-- TODO: shoud check that the blocks are not going onto
-- water/over air/replacing ice so that they do not sink,
-- but it may not be worth the effort.
--
flattenArea :: BlockType -> Int -> MCPI ()
flattenArea bType r = do
liftIO $ putStrLn "Connected to MineCraft"
Pos {..} <- getPlayerTile
liftIO $ putStrLn $ "User is at x,y=" ++ show _x ++ "," ++ show _y ++
" and a height of " ++ show _z
forM_ (circleCoords _x _y r) $ \(i,j) -> do
-- clear everything above this point
-- it depends on whether height means max z containing a
-- block, or the max connected z (probably the latter)
--
let p0 = Pos i j $ _z - 1
h <- getHeight p0
when (h >= _z) $ setBlocks
(Pos i j _z)
(Pos i j h)
air
setBlock p0 bType
liftIO $ putStrLn "Exiting from MineCraft"
maybeRead :: Read a => String -> Maybe a
maybeRead = fmap fst . listToMaybe . reads
usage :: IO ()
usage = do
progName <- getProgName
hPutStrLn stderr $ "usage: " ++ progName ++ " []"
exitFailure
main :: IO ()
main = do
args <- getArgs
case args of
[] -> runMCPI (flattenArea goldOre 5)
[rstr] -> case maybeRead rstr of
Just r -> runMCPI (flattenArea goldOre r)
_ -> usage
_ -> usage