-- |
-- 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.Serde.QQ
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

-- 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 -> ShowS
[PackedXZ] -> ShowS
PackedXZ -> String
(Int -> PackedXZ -> ShowS)
-> (PackedXZ -> String) -> ([PackedXZ] -> ShowS) -> Show PackedXZ
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> PackedXZ -> ShowS
showsPrec :: Int -> PackedXZ -> ShowS
$cshow :: PackedXZ -> String
show :: PackedXZ -> String
$cshowList :: [PackedXZ] -> ShowS
showList :: [PackedXZ] -> ShowS
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 #-}

[serde|
.derive
  Show Read Data Typeable

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
 |]

runusercoercion
  borrowderivepackunpack
  properderivepackunpack
  [ ''Generic,
    ''NFData,
    ''Eq,
    ''Ord
  ]