{"id":28345075,"url":"https://github.com/dockyardmc/tide","last_synced_at":"2025-06-27T19:35:46.501Z","repository":{"id":287426452,"uuid":"964034802","full_name":"DockyardMC/Tide","owner":"DockyardMC","description":"Codecs library made for DockyardMC","archived":false,"fork":false,"pushed_at":"2025-04-29T19:03:26.000Z","size":163,"stargazers_count":3,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-06-03T19:52:56.973Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DockyardMC.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-04-10T15:32:26.000Z","updated_at":"2025-04-29T19:03:30.000Z","dependencies_parsed_at":"2025-04-11T17:41:00.185Z","dependency_job_id":"40ca843d-5763-4e23-9de8-fd50290801bb","html_url":"https://github.com/DockyardMC/Tide","commit_stats":null,"previous_names":["dockyardmc/tide"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/DockyardMC/Tide","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DockyardMC%2FTide","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DockyardMC%2FTide/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DockyardMC%2FTide/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DockyardMC%2FTide/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DockyardMC","download_url":"https://codeload.github.com/DockyardMC/Tide/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DockyardMC%2FTide/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262319568,"owners_count":23293047,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-05-27T11:09:12.522Z","updated_at":"2025-06-27T19:35:46.490Z","avatar_url":"https://github.com/DockyardMC.png","language":"Kotlin","funding_links":["https://ko-fi.com/LukynkaCZE"],"categories":[],"sub_categories":[],"readme":"![Tide Server Banner](https://github.com/user-attachments/assets/a6cc4eb0-3b6b-486b-8e08-d49c51f791d3)\n\n[![Maven metadata URL](https://img.shields.io/maven-metadata/v?metadataUrl=https%3A%2F%2Fmvn.devos.one%2Freleases%2Fio%2Fgithub%2Fdockyardmc%2Ftide%2Fmaven-metadata.xml\u0026style=for-the-badge\u0026logo=maven\u0026logoColor=%23FFFFFF\u0026label=Latest%20Version\u0026color=%23afff87)](https://mvn.devos.one/#/releases/io/github/dockyardmc/dockyard)\n[![Static Badge](https://img.shields.io/badge/Language-Kotlin-Kotlin?style=for-the-badge\u0026color=%23963cf4)](https://kotlinlang.org/)\n\n[![wakatime](https://wakatime.com/badge/user/7398c6f6-bec2-4b9c-b8b9-578d4a500952/project/d3ab2e30-2512-46ae-a8e5-6655e53da514.svg?style=for-the-badge)](https://wakatime.com/badge/github/DockyardMC/Dockyard)\n[![Discord](https://img.shields.io/discord/1242845647892123650?label=Discord%20Server\u0026color=%237289DA\u0026style=for-the-badge\u0026logo=discord\u0026logoColor=%23FFFFFF)](https://discord.gg/SA9nmfMkdc)\n[![Static Badge](https://img.shields.io/badge/Donate-Ko--Fi-pink?style=for-the-badge\u0026logo=ko-fi\u0026logoColor=%23FFFFFF\u0026color=%23ff70c8)](https://ko-fi.com/LukynkaCZE)\n\nTide is a Kotlin codec library that allows for serializing to network protocol and JSON while allowing other formats to be integrated via use custom Transcoders. \n\nIt is purpose built for the [DockyardMC](https://github.com/DockyardMC/Dockyard) project which is reimplementation of the Minecraft server protocol so **some primitive types like **`Strings`**, **`Lists`** and **`Maps`** are not using the standard format, but they are following the Minecraft protocol's implementation**\n\n## Installation\n\n\u003cimg src=\"https://cdn.worldvectorlogo.com/logos/kotlin-2.svg\" width=\"16px\"\u003e\u003c/img\u003e\n**Kotlin DSL**\n```kotlin\nrepositories {\n    maven {\n        name = \"devOS\"\n        url = uri(\"https://mvn.devos.one/releases\")\n    }\n}\n\ndependencies {\n    implementation(\"io.github.dockyardmc:tide:1.7\")\n}\n```\n---\n\n## Usage\n\nYou can create a codec like this:\n```kotlin\ndata class Person(val name: String, val age: Int) {\n    companion object {\n        val codec = Codec.of\u003cPerson\u003e {\n            field(\"name\", Primitives.String, Person::name)\n            field(\"age\", Primitives.Int, Person::age)\n        }\n    }\n}\n```\nYou can either serialize it into a network type by calling the `Codec#writeNetwork` or into json by calling `Codec#writeJson`\n\n---\n\nYou can include other codecs inside a codec to create more complex types:\n\n```kotlin\ndata class Bus(val model: String, val driver: Person, val passengers: List\u003cPerson\u003e) {\n    companion object {\n        val codec = Codec.of\u003cBus\u003e {\n            field(\"name\", Primitives.String, Bus::model)\n            field(\"driver\", Person.codec, Bus::driver)\n            field(\"passengers\", Person.codec.list(), Bus::passengers)\n        }\n    }\n}\n```\n\n---\n\nTo use lists you can simply call `Codec#list` on existing codec like this:\n\n```kotlin\ndata class Book(val pages: List\u003cString\u003e) {\n    companion object {\n        val codec = Codec.of\u003cBook\u003e {\n            field(\"pages\", Primitives.String.list(), Book::pages)\n        }\n    }\n}\n```\n\n---\n\nTo use maps, you can either use `Codec#mapAsKeyTo` which will create map of the current codec as key and provided codec as value or Codec#mapAsValueTo which will use the current coded as value and provided coded as key:\n\n```kotlin\ndata class WarehouseInventory(val iceCreamFlavours: Map\u003cString, Int\u003e, val cookieFlavours: Map\u003cString, Int\u003e) {\n    companion object {\n        val codec = Codec.of\u003cWarehouseInventory\u003e {\n            field(\"ice_cream_flavours\", Primitives.String.mapAsKeyTo(Primitives.VarInt), WarehouseInventory::iceCreamFlavours) //uses current as key of the map \n            field(\"cookie_flavours\", Primitives.Int.mapAsValueTo(Primitives.String), WarehouseInventory::cookieFlavours) // uses current as value of the map\n        }\n    }\n}\n```\n\n---\n\nOptionals are Minecraft protocol specific type. They represent the Java `Optional\u003cT\u003e` class. Optionals in protocol consist of a `boolean` field which indicates if the value is present or not and the actual value. To make things simple, Tide returns **nullable values** instead of the java `Optional\u003cT\u003e` classes\n\nYou can use the `Codec#optional` to make the field optional:\n\n```kotlin\ndata class Book(val pages: List\u003cString\u003e, val synopsis: String?) {\n    companion object {\n        val codec = Codec.of\u003cBook\u003e {\n            field(\"pages\", Primitives.String.list(), Book::pages)\n            field(\"synopsis\", Primitives.String.optional(), Book::synopsis)\n        }\n    }\n}\n```\n\n---\n\nEnums are a special case because in the Minecraft protocol they are represented by VarInt type which is a variable length integer. The value is the ordinal (the index in the entries) of the enum value\n\nYou will need to use `Codec#enum` to create this codec which has a class field to provide the class of the enum for inner reflection shenanigans:\n\n```kotlin\ndata class Book(val pages: List\u003cString\u003e, val synopsis: String?, val type: Book.Type) {\n\n    enum class Type {\n        HORROR,\n        SCI_FI,\n        MEDIEVAL,\n        FANTASY,\n        FICTION,\n        ADVENTURE,\n        THRILLER,\n        MANGA,\n        HENTAI\n    }\n\n    companion object {\n        val codec = Codec.of\u003cBook\u003e {\n            field(\"pages\", Primitives.String.list(), Book::pages)\n            field(\"synopsis\", Primitives.String.optional(), Book::synopsis)\n            field(\"type\", Codec.enum(Book.Type::class), Book::type)\n        }\n    }\n}\n```\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdockyardmc%2Ftide","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdockyardmc%2Ftide","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdockyardmc%2Ftide/lists"}