Skip to content

Commit

Permalink
removing all fake news
Browse files Browse the repository at this point in the history
  • Loading branch information
tarunipaleru committed Aug 3, 2023
1 parent 25c93b1 commit 639ee50
Show file tree
Hide file tree
Showing 12 changed files with 259 additions and 274 deletions.
8 changes: 4 additions & 4 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<img src="statics/logo.svg" alt="drawing" width="200"/>
<img src="statics/reg-logo.svg" alt="drawing" width="200"/>

> A multiplayer game development framework & cloud hosting platform
> Democratizing multiplayer game development
Today, Hathora consists of three major components:

- [Hathora Builder](/builder/README.md): opinionated NodeJS framework for multiplayer games
- [Hathora BuildKit](/buildkit/README.md): lightweight SDKs for building networked apps that conform to the Hathora Protocol
- [Hathora Cloud](/cloud/README.md): managed hosting platform to run + scale applications confirming to the Hathora Protocol
- [Hathora BuildKit](/buildkit/README.md): lightweight networking libraries that make it easy to write real-time client-server applications in JavaScript
- [Hathora Cloud](https://hathora.dev/docs): managed hosting platform for multiplayer game servers

This is how the three parts fit in:

Expand Down
9 changes: 2 additions & 7 deletions docs/_sidebar.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
- [Overview](README.md)
- [Architecture](architecture.md)
- [Roadmap](roadmap.md)

- Hathora BuildKit

- [Getting Started](buildkit/README.md)
- [Tutorial: Top Down Shooter](buildkit/tutorial_top_down_shooter.md)
- [Tutorial: Top Down Shooter](https://bullet-mania.vercel.app/)
- [Tutorial: 3D Platformer](buildkit/tutorial_3d_platformer.md)
- [Reference](buildkit/reference.md)

- Hathora Cloud

- [Overview](cloud/README.md)
- [CLI](cloud/reference.md)
- [Get started](https://hathora.dev/docs)

- Hathora Builder

Expand Down
2 changes: 1 addition & 1 deletion docs/builder/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<div class="hathora-logo-with-super">
<img src="statics/logo.svg" alt="drawing" width="200"/>
<img src="statics/reg-logo.svg" alt="drawing" width="200"/>
<span class="hathora-logo-super">Builder</span>
</div>

Expand Down
11 changes: 1 addition & 10 deletions docs/builder/deploy.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,6 @@ For Typescript backends, the only file inside the `server/dist` directory is `in

- Node.js must be installed
- The `DATA_DIR` environment variable must be set to the path where Hathora should write its data files
- The `COORDINATOR_HOST` environment variable must be set to the URL of the Coordinator being used (if you are using a custom Coordinator other than the Hathora managed one)

Example command to start the backend:

```sh
COORDINATOR_HOST=coordinator.example.com DATA_DIR=./data node index.mjs
```

### Hathora Cloud

Expand All @@ -60,6 +53,4 @@ Navigate to the project root for your game and confirm there is a Dockerfile (th
└─ server
```

Run `hathora cloud deploy --appName ${MY_GAME_NAME}` to begin the global deployment process. If you run into any issues, please refer to the [Hathora Cloud](../cloud/README.md) documentation.

> You maybe interested in setting up Continuous Delivery. You can find instructions [here](../cloud/README.md#continuous-delivery).
Run `hathora cloud deploy --appName ${MY_GAME_NAME}` to begin the global deployment process. If you run into any issues, please refer to the [Hathora Cloud](https://hathora.dev/docs) documentation.
206 changes: 155 additions & 51 deletions docs/buildkit/README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<div class="hathora-logo-with-super">
<img src="statics/logo.svg" alt="drawing" width="200"/>
<img src="statics/reg-logo.svg" alt="drawing" width="200"/>
<span class="hathora-logo-super">BuildKit</span>
</div>

<a href="https://github.com/hathora/buildkits" target="_blank" class="hathora-gh-link">
<a href="https://github.com/hathora/buildkits/tree/main/typescript-client-sdk" target="_blank" class="hathora-gh-link">
<img src="statics/GitHub-Mark-Light-32px.png" alt="GitHub logo" height="14" width="14"/>
<span>Hathora BuildKit</span>
<span class="hathora-link-icon">
Expand All @@ -13,11 +13,11 @@
</span>
</a>

Hathora BuildKit makes it easy to write applications that conform to the Hathora Protocol, and therefore can be deployed on [Hathora Cloud](../cloud/README.md).
Hathora BuildKits are lightweight networking libraries. They make it easier to write real-time client-server applications in JavaScript.

## Benefits

- Simple SDKs provide powerful and scalable messaging infrastructure
- Import a simple library to provide powerful and scalable messaging infrastructure
- Easy deployment onto Hathora Cloud, which provides global compute scheduling and an optimized edge network
- Flexible with regards to language, persistence, serialization techniques, etc (currently only Typescript is supported, but more languages coming soon)

Expand All @@ -42,79 +42,183 @@ Hathora BuildKit makes it easy to write applications that conform to the Hathora
```

2. Inside this typescript project, install the server SDKs: `npm i @hathora/server-sdk`. Also install the required dev dependencies: `npm i -D typescript ts-node @types/node`.
3. Grab an `appId` + `appSecret` pair by running `curl -X POST https://coordinator.hathora.dev/registerApp`.
4. Set the `APP_SECRET` environment variable and create the following `server.mts` file:
3. Log onto [Hathora Console](https://console.hathora.dev/login) and [create an application](https://hathora.dev/docs/guides/deploy-hathora#create-an-application).
4. Grab the `appId` + `appSecret` from your application's page as seen below.

<img src="statics/appId-appSecret.png" alt="drawing" width="300"/>

5. Set the `APP_SECRET` environment variable and create the following `server.mts` file:

```ts
// server.mts

import { register } from "@hathora/server-sdk";

const coordinator = await register({
appSecret: process.env.APP_SECRET!,
authInfo: { anonymous: { separator: "-" } },
store: {
newState(roomId, userId, data) {
console.log("newState", roomId.toString(36), userId);
},
subscribeUser(roomId, userId) {
console.log("subscribeUser", roomId.toString(36), userId);
},
unsubscribeUser(roomId, userId) {
console.log("unsubscribeUser", roomId.toString(36), userId);
},
onMessage(roomId, userId, data) {
const dataBuf = Buffer.from(data.buffer, data.byteOffset, data.byteLength);
console.log("onMessage", roomId.toString(36), userId, dataBuf.toString("utf8"));
coordinator.sendMessage(roomId, userId, dataBuf);
},
// ...

const store: Application = {
// A function called by Hathora to verify a connecting user's token
verifyToken(token: string): UserId | undefined {
const userId = verifyJwt(token, "YOUR_HATHORA_APP_SECRET");

if (userId === undefined) {
console.error("Failed to verify token", token);
}

return userId;
},
});

console.log(`Connected to ${coordinator.host} with storeId ${coordinator.storeId}`);
```
// Called when a new user connects to your server, this is a good place to init rooms and spawn players
subscribeUser(roomId: RoomId, userId: string): void {
// Make sure the room exists (or create one if not)
if (!rooms.has(roomId)) {
console.log("Creating new room...");

rooms.set(roomId, {
players: []
});
}

const game = rooms.get(roomId)!;

// Make sure the player hasn't already spawned, then spawn them
if (!game.players.some((player) => player.id === userId)) {
game.players.push({
id: userId,
x: 0,
y: 0
});
}
},

// Called when a user disconnects from your server, this is a good place to cleanup data for that player
unsubscribeUser(roomId: RoomId, userId: string): void {
// Make sure the room exists
if (!rooms.has(roomId)) {
return;
}

const game = rooms.get(roomId)!;
const idx = game.players.findIndex((player) => player.id === userId);

// Remove the player from the room's state
if (idx >= 0) {
game.players.splice(idx, 1);
}
},

5. Run your server via `npx ts-node-esm server.mts`. You should see a message like this:
> Connected to coordinator.hathora.dev with storeId 81e5804a-5ffe-496c-8a68-da071945b558
// Called when a message is sent to the server for handling, much of your core logic will live here
async onMessage(roomId: RoomId, userId: string, data: ArrayBuffer): Promise<void> {
// Make sure the room exists
if (!rooms.has(roomId)) {
return;
}

// Get the player, or return out of the function if they don't exist
const game = rooms.get(roomId)!;
const player = game.players.find((player) => player.id === userId);
if (player === undefined) {
return;
}

// Parse out the data string being sent from the client
const message = JSON.parse(Buffer.from(data).toString("utf8"));

if (message.type === 'test-message') {
if (message.value === 'Hello Hathora server!') {
// Define a response message...
const msg = {
type: 'test-response',
value: 'Hello Hathora clients!'
};

// Then broadcast it to all connected clients in this room
server.broadcastMessage(roomId, Buffer.from(JSON.stringify(msg), "utf8"));
}
}
// else if (message.type === 'some-other-action') {
// // (handle other message types)
// }
}
};

// Boot server
const port = 4000;
const server = await startServer(store, port);
console.log(`Server listening on port ${port}`);
```

#### Client

Once your server is connected to the Coordinator, you can start passing messages back and forth. Let's build a client to do that.

1. In your typescript project, install the client SDKs: `npm i @hathora/client-sdk`
2. Fill in the `APP_ID` from above and implement `onMessage` and `onError` methods:
2. Fill in the `APP_ID` from above. Establish a connection using the `onMessage` and `onError` methods:

```ts
// client.mts

import { HathoraClient } from "@hathora/client-sdk";

const encoder = new TextEncoder();
const decoder = new TextDecoder();
async function establishConnection() {
// Instantiate an object which represents our local connection info...
const connectionInfo = {
host: "localhost",
port: 4000,
transportType: "tcp" as const
};

const client = new HathoraClient(APP_ID);
const token = await client.loginAnonymous();
const roomId = await client.create(token, new Uint8Array());
const connection = await client.connect(token, roomId, onMessage, onError);
// Or pass undefined if working in a production Hathora environment
// const connectionInfo = undefined;

connection.write(encoder.encode("Hello world!"));
// Instantiate our client object (this is where you provide a valid Hathora APP_ID, which here is being passed via an environment variable)
const client = new HathoraClient("YOUR_HATHORA_APP_ID", connectionInfo);

function onMessage(msg: ArrayBuffer) {
console.log(decoder.decode(msg));
}
// Use the client to get a token for the user
const token = await client.loginAnonymous();

// You can now create a new public room
const newPublicRoomId = await client.createPublicLobby(token);

// Or a new private room
const newPrivateRoomId = await client.createPrivateLobby(token);

// And query for existing public rooms
const existingPublicRoomIds = await client.getPublicLobbies(token);

// Create a HathoraConnection instance
const connection = client.newConnection(newPublicRoomId);

function onError(error: any) {
console.error(error);
// Handle connection closing how you like
connection.onClose((error) => {
console.error("Connection closed", error);
});

// Initiate the connection
connection.connect(token);

// Return our connection to be used later...
return connection;
}
```

3. Run your client via `npx ts-node-esm client.mts`. You should see "Hello world!" echoed back like so:
> Hello world!
3. Use the connection by running the code below:

On the server you should see output similar to the following:
> newState 305z91zyocpd4 k8vkwl7692
subscribeUser 305z91zyocpd4 k8vkwl7692
onMessage 305z91zyocpd4 k8vkwl7692 Hello world!
```ts
async function example() {
// Establish a Hathora connection (see above)
const connection = await establishConnection();

// Write JSON messages to the server
connection.writeJson({
type: "test-message",
value: "Hello Hathora server!"
});

// Listen for JSON messages from the server
connection.onMessageJson((json) => {
// Handle the message in your app...
console.log(json);
});
}
```

### Next Steps

Expand Down
Loading

0 comments on commit 639ee50

Please sign in to comment.