-- |
-- Module: M.Chunk.Net
-- Description: Network serialization types for chunk data
-- Copyright: (c) axionbuster, 2025
-- License: BSD-3-Clause
--
-- Defines data types for chunk and lighting data used in network serialization.
-- Includes block entities and packed coordinate representations.
module M.Chunk.Net (ChunkData (..), BlockEntity (..), LightData (..)) where

import Control.DeepSeq
import Data.Bits
import Data.ByteString (ByteString)
import Data.Data
import Data.Functor
import Data.Hashable
import Data.Int
import Data.Vector qualified as V
import Data.Word
import GHC.Generics
import Language.Haskell.TH.Syntax (Lift)
import Linear
import M.LEB
import M.NBT
import M.Pack
import M.PkMacro

-- only for internal use
newtype PackedXZ = PackedXZ {PackedXZ -> V2 Word8
getpackedxz :: V2 Word8}
  deriving stock ((forall x. PackedXZ -> Rep PackedXZ x)
-> (forall x. Rep PackedXZ x -> PackedXZ) -> Generic PackedXZ
forall x. Rep PackedXZ x -> PackedXZ
forall x. PackedXZ -> Rep PackedXZ x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. PackedXZ -> Rep PackedXZ x
from :: forall x. PackedXZ -> Rep PackedXZ x
$cto :: forall x. Rep PackedXZ x -> PackedXZ
to :: forall x. Rep PackedXZ x -> PackedXZ
Generic, Typeable, Typeable PackedXZ
Typeable PackedXZ =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> PackedXZ -> c PackedXZ)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c PackedXZ)
-> (PackedXZ -> Constr)
-> (PackedXZ -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c PackedXZ))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c PackedXZ))
-> ((forall b. Data b => b -> b) -> PackedXZ -> PackedXZ)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> PackedXZ -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> PackedXZ -> r)
-> (forall u. (forall d. Data d => d -> u) -> PackedXZ -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> PackedXZ -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> PackedXZ -> m PackedXZ)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> PackedXZ -> m PackedXZ)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> PackedXZ -> m PackedXZ)
-> Data PackedXZ
PackedXZ -> Constr
PackedXZ -> DataType
(forall b. Data b => b -> b) -> PackedXZ -> PackedXZ
forall a.
Typeable a =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> PackedXZ -> u
forall u. (forall d. Data d => d -> u) -> PackedXZ -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> PackedXZ -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> PackedXZ -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> PackedXZ -> m PackedXZ
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> PackedXZ -> m PackedXZ
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c PackedXZ
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> PackedXZ -> c PackedXZ
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c PackedXZ)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c PackedXZ)
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> PackedXZ -> c PackedXZ
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> PackedXZ -> c PackedXZ
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c PackedXZ
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c PackedXZ
$ctoConstr :: PackedXZ -> Constr
toConstr :: PackedXZ -> Constr
$cdataTypeOf :: PackedXZ -> DataType
dataTypeOf :: PackedXZ -> DataType
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c PackedXZ)
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c PackedXZ)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c PackedXZ)
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c PackedXZ)
$cgmapT :: (forall b. Data b => b -> b) -> PackedXZ -> PackedXZ
gmapT :: (forall b. Data b => b -> b) -> PackedXZ -> PackedXZ
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> PackedXZ -> r
gmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> PackedXZ -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> PackedXZ -> r
gmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> PackedXZ -> r
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> PackedXZ -> [u]
gmapQ :: forall u. (forall d. Data d => d -> u) -> PackedXZ -> [u]
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> PackedXZ -> u
gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> PackedXZ -> u
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> PackedXZ -> m PackedXZ
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> PackedXZ -> m PackedXZ
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> PackedXZ -> m PackedXZ
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> PackedXZ -> m PackedXZ
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> PackedXZ -> m PackedXZ
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> PackedXZ -> m PackedXZ
Data, (forall (m :: * -> *). Quote m => PackedXZ -> m Exp)
-> (forall (m :: * -> *). Quote m => PackedXZ -> Code m PackedXZ)
-> Lift PackedXZ
forall t.
(forall (m :: * -> *). Quote m => t -> m Exp)
-> (forall (m :: * -> *). Quote m => t -> Code m t) -> Lift t
forall (m :: * -> *). Quote m => PackedXZ -> m Exp
forall (m :: * -> *). Quote m => PackedXZ -> Code m PackedXZ
$clift :: forall (m :: * -> *). Quote m => PackedXZ -> m Exp
lift :: forall (m :: * -> *). Quote m => PackedXZ -> m Exp
$cliftTyped :: forall (m :: * -> *). Quote m => PackedXZ -> Code m PackedXZ
liftTyped :: forall (m :: * -> *). Quote m => PackedXZ -> Code m PackedXZ
Lift)
  deriving newtype (PackedXZ -> PackedXZ -> Bool
(PackedXZ -> PackedXZ -> Bool)
-> (PackedXZ -> PackedXZ -> Bool) -> Eq PackedXZ
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PackedXZ -> PackedXZ -> Bool
== :: PackedXZ -> PackedXZ -> Bool
$c/= :: PackedXZ -> PackedXZ -> Bool
/= :: PackedXZ -> PackedXZ -> Bool
Eq, Eq PackedXZ
Eq PackedXZ =>
(PackedXZ -> PackedXZ -> Ordering)
-> (PackedXZ -> PackedXZ -> Bool)
-> (PackedXZ -> PackedXZ -> Bool)
-> (PackedXZ -> PackedXZ -> Bool)
-> (PackedXZ -> PackedXZ -> Bool)
-> (PackedXZ -> PackedXZ -> PackedXZ)
-> (PackedXZ -> PackedXZ -> PackedXZ)
-> Ord PackedXZ
PackedXZ -> PackedXZ -> Bool
PackedXZ -> PackedXZ -> Ordering
PackedXZ -> PackedXZ -> PackedXZ
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: PackedXZ -> PackedXZ -> Ordering
compare :: PackedXZ -> PackedXZ -> Ordering
$c< :: PackedXZ -> PackedXZ -> Bool
< :: PackedXZ -> PackedXZ -> Bool
$c<= :: PackedXZ -> PackedXZ -> Bool
<= :: PackedXZ -> PackedXZ -> Bool
$c> :: PackedXZ -> PackedXZ -> Bool
> :: PackedXZ -> PackedXZ -> Bool
$c>= :: PackedXZ -> PackedXZ -> Bool
>= :: PackedXZ -> PackedXZ -> Bool
$cmax :: PackedXZ -> PackedXZ -> PackedXZ
max :: PackedXZ -> PackedXZ -> PackedXZ
$cmin :: PackedXZ -> PackedXZ -> PackedXZ
min :: PackedXZ -> PackedXZ -> PackedXZ
Ord, Int -> PackedXZ -> String -> String
[PackedXZ] -> String -> String
PackedXZ -> String
(Int -> PackedXZ -> String -> String)
-> (PackedXZ -> String)
-> ([PackedXZ] -> String -> String)
-> Show PackedXZ
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> PackedXZ -> String -> String
showsPrec :: Int -> PackedXZ -> String -> String
$cshow :: PackedXZ -> String
show :: PackedXZ -> String
$cshowList :: [PackedXZ] -> String -> String
showList :: [PackedXZ] -> String -> String
Show, ReadPrec [PackedXZ]
ReadPrec PackedXZ
Int -> ReadS PackedXZ
ReadS [PackedXZ]
(Int -> ReadS PackedXZ)
-> ReadS [PackedXZ]
-> ReadPrec PackedXZ
-> ReadPrec [PackedXZ]
-> Read PackedXZ
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS PackedXZ
readsPrec :: Int -> ReadS PackedXZ
$creadList :: ReadS [PackedXZ]
readList :: ReadS [PackedXZ]
$creadPrec :: ReadPrec PackedXZ
readPrec :: ReadPrec PackedXZ
$creadListPrec :: ReadPrec [PackedXZ]
readListPrec :: ReadPrec [PackedXZ]
Read, Eq PackedXZ
Eq PackedXZ =>
(Int -> PackedXZ -> Int) -> (PackedXZ -> Int) -> Hashable PackedXZ
Int -> PackedXZ -> Int
PackedXZ -> Int
forall a. Eq a => (Int -> a -> Int) -> (a -> Int) -> Hashable a
$chashWithSalt :: Int -> PackedXZ -> Int
hashWithSalt :: Int -> PackedXZ -> Int
$chash :: PackedXZ -> Int
hash :: PackedXZ -> Int
Hashable, PackedXZ -> ()
(PackedXZ -> ()) -> NFData PackedXZ
forall a. (a -> ()) -> NFData a
$crnf :: PackedXZ -> ()
rnf :: PackedXZ -> ()
NFData)

pxzx :: (Num a) => PackedXZ -> a
pxzx :: forall a. Num a => PackedXZ -> a
pxzx (PackedXZ (V2 Word8
x Word8
_)) = Word8 -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
x
{-# INLINE pxzx #-}

pxzz :: (Num a) => PackedXZ -> a
pxzz :: forall a. Num a => PackedXZ -> a
pxzz (PackedXZ (V2 Word8
_ Word8
z)) = Word8 -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
z
{-# INLINE pxzz #-}

instance Pack PackedXZ where
  pack :: PackedXZ -> Builder
pack PackedXZ
p = forall a. Pack a => a -> Builder
pack @Word8 (Word8 -> Builder) -> Word8 -> Builder
forall a b. (a -> b) -> a -> b
$ ((PackedXZ -> Word8
forall a. Num a => PackedXZ -> a
pxzx PackedXZ
p Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
15) Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
.<<. Int
4) Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.|. (PackedXZ -> Word8
forall a. Num a => PackedXZ -> a
pxzz PackedXZ
p Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
15)
  {-# INLINEABLE pack #-}

instance Unpack PackedXZ where
  unpack :: forall (st :: ZeroBitType) r. Parser st r PackedXZ
unpack = forall a (st :: ZeroBitType) r. Unpack a => Parser st r a
unpack @Word8 Parser st r Word8
-> (Word8 -> PackedXZ) -> ParserT st r ParseError PackedXZ
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> \Word8
w -> V2 Word8 -> PackedXZ
PackedXZ (Word8 -> Word8 -> V2 Word8
forall a. a -> a -> V2 a
V2 (Word8
w Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
.>>. Int
4) (Word8
w Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
15))
  {-# INLINEABLE unpack #-}

setdefaultderives
addproperderives [''NFData, ''Typeable, ''Show, ''Eq]

[pkmacro|
data BlockEntity {
  bexz :: V2 Word8 via PackedXZ,
  berelheight :: Int16,
  betype :: Int32 via VarInt,
  bedata :: Tg,
}

data ChunkData {
  cdhmaps :: Tg,
  cddata :: ByteString,
  cdblockentities :: V.Vector BlockEntity,
}

data LightData {
  ldskymask :: Bitset,
  ldblockmask :: Bitset,
  ld0skymask :: Bitset,
  ld0blockmask :: Bitset,
  -- inner ByteStrings are always 2048 bytes long by contract
  ldskylights :: V.Vector ByteString,
  ldblocklights :: V.Vector ByteString,
}
 |]