module Rattletrap.Type.Header where import qualified Rattletrap.ByteGet as ByteGet import qualified Rattletrap.BytePut as BytePut import qualified Rattletrap.Schema as Schema import qualified Rattletrap.Type.Dictionary as Dictionary import qualified Rattletrap.Type.Property as Property import qualified Rattletrap.Type.Str as Str import qualified Rattletrap.Type.U32 as U32 import qualified Rattletrap.Type.Version as Version import qualified Rattletrap.Utility.Json as Json -- | Contains high-level metadata about a 'Rattletrap.Replay.Replay'. data Header = Header { version :: Version.Version, -- | Always @TAGame.Replay_Soccar_TA@. label :: Str.Str, -- | These properties determine how a replay will look in the list of -- replays in-game. One element is required for the replay to show up: -- -- - MapName: This is a 'Rattletrap.PropertyValue.NameProperty' with a -- case-insensitive map identifier, like @Stadium_P@. -- -- There are many other properties that affect how the replay looks in the -- list of replays. -- -- - Date: A 'Rattletrap.PropertyValue.StrProperty' with the format -- @YYYY-mm-dd:HH-MM@. Dates are not validated, but the month must be -- between 1 and 12 to show up. The hour is shown modulo 12 with AM or PM. -- - MatchType: A 'Rattletrap.PropertyValue.NameProperty'. If this is not -- one of the expected values, nothing will be shown next to the replay's -- map. The expected values are: @Online@, @Offline@, @Private@, and -- @Season@. -- - NumFrames: This 'Rattletrap.PropertyValue.IntProperty' is used to -- calculate the length of the match. There are 30 frames per second, -- a typical 5-minute match has about 9,000 frames. -- - PrimaryPlayerTeam: This is an 'Rattletrap.PropertyValue.IntProperty'. -- It is either 0 (blue) or 1 (orange). Any other value is ignored. If -- this would be 0, you don't have to set it at all. -- - ReplayName: An optional 'Rattletrap.PropertyValue.StrProperty' with a -- user-supplied name for the replay. -- - Team0Score: The blue team's score as an -- 'Rattletrap.PropertyValue.IntProperty'. Can be omitted if the score is -- 0. -- - Team1Score: The orange team's score as an -- 'Rattletrap.PropertyValue.IntProperty'. Can also be omitted if the -- score is 0. -- - TeamSize: An 'Rattletrap.PropertyValue.IntProperty' with the number of -- players per team. This value is not validated, so you can put absurd -- values like 99. To get an "unfair" team size like 1v4, you must set the -- bUnfairBots 'Rattletrap.PropertyValue.BoolProperty' to @True@. properties :: Dictionary.Dictionary Property.Property } deriving (Eq, Show) instance Json.FromJSON Header where parseJSON = Json.withObject "Header" $ \object -> do major <- Json.required object "engine_version" minor <- Json.required object "licensee_version" patch <- Json.optional object "patch_version" label <- Json.required object "label" properties <- Json.required object "properties" pure Header { version = Version.Version { Version.major, Version.minor, Version.patch }, label, properties } instance Json.ToJSON Header where toJSON x = Json.object [ Json.pair "engine_version" . Version.major $ version x, Json.pair "licensee_version" . Version.minor $ version x, Json.pair "patch_version" . Version.patch $ version x, Json.pair "label" $ label x, Json.pair "properties" $ properties x ] schema :: Schema.Schema schema = Schema.named "header" $ Schema.object [ (Json.pair "engine_version" $ Schema.ref U32.schema, True), (Json.pair "licensee_version" $ Schema.ref U32.schema, True), (Json.pair "patch_version" . Schema.json $ Schema.maybe U32.schema, False), (Json.pair "label" $ Schema.ref Str.schema, True), ( Json.pair "properties" . Schema.json $ Dictionary.schema Property.schema, True ) ] bytePut :: Header -> BytePut.BytePut bytePut x = Version.bytePut (version x) <> Str.bytePut (label x) <> Dictionary.bytePut Property.bytePut (properties x) byteGet :: ByteGet.ByteGet Header byteGet = ByteGet.label "Header" $ do version <- ByteGet.label "version" Version.byteGet label <- ByteGet.label "label" Str.byteGet properties <- ByteGet.label "properties" $ Dictionary.byteGet Property.byteGet pure Header {version, label, properties}