{"id":23245187,"url":"https://github.com/wizcorp/megadata","last_synced_at":"2025-08-20T05:31:23.457Z","repository":{"id":57294190,"uuid":"126481781","full_name":"Wizcorp/megadata","owner":"Wizcorp","description":"Smart messaging for games","archived":false,"fork":false,"pushed_at":"2020-06-02T21:43:41.000Z","size":4155,"stargazers_count":8,"open_issues_count":46,"forks_count":2,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-08-09T21:11:42.487Z","etag":null,"topics":["game","game-development","messaging","nodejs","typescript","webpack"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","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/Wizcorp.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}},"created_at":"2018-03-23T12:24:41.000Z","updated_at":"2019-02-25T22:15:59.000Z","dependencies_parsed_at":"2022-09-01T06:40:20.865Z","dependency_job_id":null,"html_url":"https://github.com/Wizcorp/megadata","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Wizcorp%2Fmegadata","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Wizcorp%2Fmegadata/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Wizcorp%2Fmegadata/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Wizcorp%2Fmegadata/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Wizcorp","download_url":"https://codeload.github.com/Wizcorp/megadata/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":230394224,"owners_count":18218707,"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":["game","game-development","messaging","nodejs","typescript","webpack"],"created_at":"2024-12-19T07:12:04.554Z","updated_at":"2024-12-19T07:12:38.649Z","avatar_url":"https://github.com/Wizcorp.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ![Megadata](./images/logo.png)\n\n[![GitHub tag](https://img.shields.io/github/tag/Wizcorp/megadata.svg?style=flat-square)](https://github.com/Wizcorp/megadata/releases/latest)\n[![npm](https://img.shields.io/npm/v/megadata.svg?style=flat-square)](https://www.npmjs.com/package/megadata)\n[![npm](https://img.shields.io/npm/dt/megadata.svg?style=flat-square)](https://www.npmjs.com/package/megadata)\n[![Gitter](https://img.shields.io/gitter/room/Wizcorp/megadata-typescript.svg?style=flat-square)](https://gitter.im/megadata-typescript/Lobby?utm_source=share-link\u0026utm_medium=link\u0026utm_campaign=share-link)\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/Wizcorp/megadata.svg?style=flat-square)](https://greenkeeper.io/)\n[![Build Status: Linux \u0026 macOS](https://img.shields.io/travis/Wizcorp/megadata.svg?style=flat-square\u0026label=ci%20linux%2Fmacos)](https://travis-ci.org/Wizcorp/megadata)\n[![Build Status: Windows](https://img.shields.io/appveyor/ci/mage/megadata/master.svg?style=flat-square\u0026label=ci%20windows)](https://ci.appveyor.com/project/mage/megadata/branch/master)\n[![Coveralls branch](https://img.shields.io/coveralls/Wizcorp/megadata/master.svg?style=flat-square)](https://coveralls.io/github/Wizcorp/megadata)\n\nMegadata is a library you can use to serialize/deserialize network game\ndata.\n\nThis library will help you deal with:\n\n  1. Defining type IDs and type classes\n  2. Definining the serialization/deserialization format to use\n  3. Re-using messages object, by creating and maintaining a message pool\n  4. Sharing message libraries between client (JavaScript) and server (Node.js)\n  5. TypeScript type checks\n\n## Requirements\n\n  - Node.js 8.0 or higher\n\n## Installation\n\n```shell\nnpm install --save megadata\n```\n\nYou will also need to make sure that the following configuration is set in your tsconfig.json:\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true\n  }\n}\n```\n\n## Usage\n\n### Defining message types\n\n\u003e shared/messages/index.ts\n\n```typescript\nimport megadata, { TypeDecorator } from 'megadata'\n\nexport enum TypeIds {\n  Join,\n  Leave\n}\n\nexport const Type: TypeDecorator\u003cTypeIds\u003e = megadata(module)\n```\n\nWe first create a list of message types as a `const enum` and\nlist the messages we will send and receive in our game. We then\ngenerate a `@Type` decorator\n\n\u003e shared/messages/types/Join.ts\n\n```typescript\nimport { Type, TypeIds } from '../'\nimport MessageType from 'megadata/classes/MessageType'\nimport Binary, { Uint32 } from 'megadata/classes/BinarySerializationFormat'\n\n@Type(TypeIds.Join, Binary)\nexport default class Join extends MessageType {\n  @Uint32\n  public time: number\n}\n```\n\n\u003e shared/messages/types/Leave.ts\n\n```typescript\nimport { Type, TypeIds } from '../'\nimport MessageType from 'megadata/classes/MessageType'\nimport Json from 'megadata/classes/JsonSerializationFormat'\n\n@Type(TypeIds.Leave, Json)\nexport default class Leave extends MessageType {\n  public time: number\n}\n```\n\n\nNext, we define what our `Join` and `Leave` messages type will look like, and\nhow we should serialize and deserialize it.\n\nMegadata ships with two serialization formats:\n\n  1. **binary**: deals only with messages containing numbers, but is blazing fast\n  2. **json**: deals with any kind of data, but is slower\n\nYou may notice that the `Binary` serialization format requires additional annotations\nthis is required to define (and optimized) the size and speed of serialization and\ndeserialization.\n\n### Sending and receiving messages\n\n\u003e server/classes/Player.ts\n\n```typescript\nimport Connection from '...'\nimport MessageEmitter from 'megadata/classes/MessageType'\nimport MessageType, { IMessageType, MessageTypeData } from 'megadata/classes/MessageType'\n\nexport class Player extends MessageEmitter {\n  constructor(private connection: Connection) {\n    connection.on('message', async (buffer: ArrayBuffer) =\u003e {\n      const message = MessageType.parse(buffer)\n      await this.emitAsync(message)\n      message.release()\n    })\n  }\n\n  public async function send\u003cT extends MessageType\u003e(type: IMessageType\u003cT\u003e, data: MessageTypeData\u003cT\u003e) {\n    const message = type.create\u003cT\u003e(data)\n    const buffer = message.pack()\n    await this.connection.write(buffer)\n    message.release()\n  }\n}\n```\n\nMessages are recycled from an object pool to reduce the impact of garbage collection; therefore,\nit is important to remember to release messages back into the object pool once you are done with them.\n\n\u003e server/classes/Game.ts\n\n```typescript\nimport Player from './Player'\n\nimport Join from 'shared/messages/types/Join.ts'\n\nexport default class Game {\n  // ...\n\n  public addPlayer(player: Player) {\n    player.on(Join, ({ time }) =\u003e console.log('Join time:', time))\n    player.on(Leave, ({ time }) =\u003e console.log('Leave time:', time))\n  }\n}\n```\n\n### Messages and events auto-loading\n\n#### Running a Node.js server with auto-loading\n\nAuto-loading uses `require.context`, which is a webpack-specific\nAPI. When using Megadata with auto-loading in Node.js, you will\ntherefore need to load the mock provided by the library.\n\n```shell\nts-node -r megadata/register index.ts\n```\n\n#### Setting types auto-loading\n\n\u003e shared/messages/index.ts\n\n```typescript\nimport megadata, { TypeDecorator } from 'megadata'\n\nconst types = require.context('./types/')\n\nexport enum TypeIds {\n  Join,\n  [...]\n}\n\nexport const Type: TypeDecorator\u003cTypeIds\u003e = megadata(module, types)\n```\n\nThe following code will dynamically load type classes on demand from\nthe `shared/messages/types` folder. If no listeners were ever set to\nlisten for messages of this type, an `Event.Unknown` event will be \nemitted (see below).\n\n#### Setting event handlers auto-loading for a class inheriting MessageEmitter\n\n\u003e server/classes/Player.ts\n\n```typescript\nimport MessageEmitter, { AutoloadEvents } from 'megadata/classes/MessageEmitter'\n\nconst events = require.context('../events/')\n\n@AutoloadEvents(events)\nexport default class Player extends MessageEmitter {}\n```\n\nA given message emitter may end up handling a large number or events. Event\nhandlers auto-loading provides a mechanism for breaking event handling\ndown into event handler files that are auto-loaded on demand. In this\ncase, we will auto-load all events under `server/events`.\n\n\n\u003e server/events/Join.ts\n\n```typescript\nimport Player from '../classes/Player'\nimport Join from 'shared/messages/types/Join'\n\nexport default function (player: Player) {\n  player.on(Join, (message) =\u003e console.log('Received join event', message))\n}\n```\n\nEvent handler files export a single default function which will receive \na message emitter instance; you may then set the even listeners according to\nyour needs.\n\n### Custom serialization\n\n\u003e shared/messages/classes/CustomSerializationFormat.ts\n\n```typescript\nimport MessageType from './MessageType'\nimport SerializationFormat, { ISerializerFunctions } from './SerializationFormat'\n\nexport default class CustomSerializationFormat extends SerializationFormat {\n  public create\u003cI, T extends MessageType\u003e(id: I, size: number, attributes: any) {\n    return {\n      create: (...),\n      pack: (...),\n      unpack: (...),\n    } as ISerializerFunctions\u003cI, T\u003e\n  }\n}\n```\n\nYou can create your own custom serialization format. Above is a quick stub, but\nyou should have a look at the [default serialization formats](./classes) provided\nby megadata.\n\n## Acknowledgements\n\n  - Initial code and implementation (JavaScript): @ronkorving\n  - Logo customizations: @lzubiaur\n\n## License\n\nMIT License. Copyright (c) Wizcorp Inc.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwizcorp%2Fmegadata","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwizcorp%2Fmegadata","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwizcorp%2Fmegadata/lists"}