Skip to content

Commit

Permalink
Initial implementation (#1)
Browse files Browse the repository at this point in the history
* Add Bedrock Methods

* Add Java Methods

* Add main handler

* Add tests

* Add examples

* Update HISTORY.md

* Update package.json

* Update README.md

* Update .gitignore

* Remove misc

* Fix definitions

* Inline Functions

* Change User-Agent header

* Remove old API & tests

* Update API

* Update constants, util, examples and add Ts Docs

* Add blank test

Just a temp add

* Update README.md

* Inline Routes

* Remove pauth dep

* Remove auth check

* Explicit fields

* Update constants

* Update example for pauth removal

* Fix explicit again

* Extend RealmAPI from platforms API

* Fix Lint

* Fix options

* Moar explicit fields

* InvitePlayer return Realm instance

* Add open/close endpoints

* Added Realm description and Mineflayer/NMP/BP usage

* Update index.d.ts

* Add options

* Add tests

* Update package.json

* Fix for options undefined
  • Loading branch information
LucienHH authored Apr 2, 2022
1 parent 838fe4a commit cecc7e5
Show file tree
Hide file tree
Showing 20 changed files with 685 additions and 35 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
node_modules/
package-lock.json
.vscode
.vscode

*-cache.json
scripts/
2 changes: 1 addition & 1 deletion HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
## History

### 1.0.0
### 0.0.1

* initial implementation
146 changes: 136 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,147 @@
# prismarine-template
[![NPM version](https://img.shields.io/npm/v/prismarine-template.svg)](http://npmjs.com/package/prismarine-template)
[![Build Status](https://github.com/PrismarineJS/prismarine-template/workflows/CI/badge.svg)](https://github.com/PrismarineJS/prismarine-template/actions?query=workflow%3A%22CI%22)
# prismarine-realms
[![NPM version](https://img.shields.io/npm/v/prismarine-realms.svg)](http://npmjs.com/package/prismarine-realms)
[![Build Status](https://github.com/PrismarineJS/prismarine-realms/workflows/CI/badge.svg)](https://github.com/PrismarineJS/prismarine-realms/actions?query=workflow%3A%22CI%22)
[![Discord](https://img.shields.io/badge/chat-on%20discord-brightgreen.svg)](https://discord.gg/GsEFRM8)
[![Try it on gitpod](https://img.shields.io/badge/try-on%20gitpod-brightgreen.svg)](https://gitpod.io/#https://github.com/PrismarineJS/prismarine-template)
[![Try it on gitpod](https://img.shields.io/badge/try-on%20gitpod-brightgreen.svg)](https://gitpod.io/#https://github.com/PrismarineJS/prismarine-realms)

A template repository to make it easy to create new prismarine repo
Node.JS Wrapper around both the Java & Bedrock Realms API. Minecraft Realms is a subscription based service provided by Mojang where users can create/manage their own private server. The intention of this package is to provide easy access to the internal API used to manage Realms such as opening/closing a Realm, managing players, getting host information and much more.

## Installation
```shell
npm install prismarine-realms
```

## Usage

### RealmAPI

#### .from(authflow: Authflow, platform: 'bedrock' | 'java')

Takes an **Authflow** instance from [prismarine-auth](https://github.com/PrismarineJS/prismarine-auth), you can see the documentation for this [here.](https://github.com/PrismarineJS/prismarine-auth#authflow)

## API

### Definitions

| Param | Type | Description |
| --------------- | -------------------- | --------------------------------------------------------------------- |
| realmId | `string` | The ID of the Realm |
| realmInviteCode | `string` | The invite code for the Realm (Only on Bedrock) |
| username | `string` | The username of player |
| uuid | `string` | The unique ID of the player, w/o hyphens |
| xuid | `string` | The Xbox User ID of the targeted player |

---

```js
const template = require('prismarine-template')
const { Authflow } = require('prismarine-auth')
const { RealmAPI } = require('prismarine-realms')

template.helloWorld()
const authflow = new Authflow()

const api = RealmAPI.from(authflow, 'bedrock')
```

## API
#### getRealms()

Gets a list of Realms the authenticating account has joined or owns

```js
await api.getRealms()
```

### helloWorld()

Prints hello world
#### getRealm(realmId: string)

Gets detailed information about a Realm if owned

```js
await api.getRealm('1234567')
```

#### getAddress()

Gets the address for the Realm

```js
const realm = await api.getRealm('1234567')

await realm.getAddress()
```

#### invitePlayer(uuid: string, name: string)

Invites a player to the Realm

```js
const realm = await api.getRealm('1234567')

await realm.invitePlayer('a8005260a332457097a50bdbe48a9a21', 'Steve')
```

#### open()

Opens a Realm. Allows players to join

```js
const realm = await api.getRealm('1234567')

await realm.open()
```

#### close()

Closes a Realm. Removes all current players and restricts joining

```js
const realm = await api.getRealm('1234567')

await realm.close()
```

---

### Using prismarine-realms with Mineflayer, Node Minecraft Protocol and Bedrock Protocol

Prismarine-auth is used in Mineflayer to allow quick connection to owned/joined Realms by providing a `pickRealm` function which should return a single Realm instance. It will then handle getting the host information and connect your bot to that Realm. The process of getting the Realms connection is handled in the protocol libraries meaning the same options can be passed there as well.

#### Mineflayer

```js
const mineflayer = require('mineflayer')

const bot = mineflayer.createBot({
username: 'example',
auth: 'microsoft',
realms: {
pickRealm: (realms) => realms.find(realm => realm.name === 'My Realm')
}
})
```

#### Node Minecraft Protocol

```js
const protocol = require('minecraft-protocol');

const client = protocol.createClient({
username: 'example',
auth: 'microsoft',
realms: {
pickRealm: (realms) => realms.find(realm => realm.name === 'My Realm')
}
});
```

#### Bedrock Protocol

```js
const protocol = require('bedrock-protocol');

const client = protocol.createClient({
username: 'example',
realms: {
pickRealm: (realms) => realms.find(realm => realm.name === 'My Realm')
}
});
```
3 changes: 0 additions & 3 deletions example.js

This file was deleted.

15 changes: 15 additions & 0 deletions examples/realms.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const { Authflow } = require('prismarine-auth')
const { RealmAPI } = require('prismarine-realms')

const [, , platform] = process.argv

if (!platform) {
console.log('Usage: node realms.js <platform>')
process.exit(1)
}

const authflow = new Authflow()

const api = RealmAPI.from(authflow, platform)

api.getRealms().then(console.log)
79 changes: 79 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/// <reference types="node" />
declare module 'prismarine-realms' {
export class RealmAPI {
/**
* Creates a new RealmAPI instance, which handles and authenticates calls to the Realms API
* @param authflow An Authflow instance from [prismarine-auth](https://github.com/PrismarineJS/prismarine-auth).
* @param platform Which platforms API to access
*/
constructor(authflow: Authflow, platform: 'bedrock' | 'java')

static from(authflow: Authflow, platform: 'bedrock' | 'java'): BedrockRealmAPI | JavaRealmAPI

getRealms(): Promise<Realm[]>

getRealm(realmId?: string): Promise<Realm>

}

export class BedrockRealmAPI extends RealmAPI {
getRealmAddress(realmId: string): Promise<Address>
invitePlayer(realmId: string, uuid: string): Promise<Realm>
changeRealmState(realmId: string, state: 'open' | 'close'): Pomise<void>
}

export class JavaRealmAPI extends RealmAPI {
getRealmAddress(realmId: string): Promise<Address>
invitePlayer(realmId: string, uuid: string, name: string): Promise<Realm>
changeRealmState(realmId: string, state: 'open' | 'close'): Pomise<void>
}

export interface Realm {
getAddress(): Promise<Address>
invitePlayer(uuid: string, name: string): Promise<Realm>
open(): Promise<void>
close(): Promise<void>
id: number
remoteSubscriptionId: string
owner: null
ownerUUID: string
name: string
motd: string
defaultPermission: string
state: string
daysLeft: number
expired: boolean
expiredTrial: boolean
gracePeriod: boolean
worldType: string
players: RealmPlayer[]
maxPlayers: number
minigameName: string
minigameId: number
minigameImage: string
activeSlot: number
slots: Slot[]
member: boolean
clubId: number
subscriptionRefreshStatus: null
}

export interface RealmPlayer {
uuid: string,
name: string,
operator: boolean,
accepted: boolean,
online: boolean,
permission: string
}

export interface Slot {
options: string
slotId: number
}

export interface Address {
address: string
}

}
4 changes: 2 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ if (typeof process !== 'undefined' && parseInt(process.versions.node.split('.')[
process.exit(1)
}

module.exports.helloWorld = function () {
console.log('Hello world !')
module.exports = {
RealmAPI: require('./src/index')
}
30 changes: 19 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,31 +1,39 @@
{
"name": "prismarine-template",
"version": "1.0.0",
"description": "A template repository to make it easy to create new prismarine repo",
"name": "prismarine-realms",
"version": "0.0.1",
"description": "Node.JS Wrapper around both the Java & Bedrock Realms API",
"main": "index.js",
"scripts": {
"test": "mocha --reporter spec --exit",
"test": "mocha --recursive --reporter spec --exit",
"pretest": "npm run lint",
"lint": "standard",
"fix": "standard --fix"
},
"repository": {
"type": "git",
"url": "git+https://github.com/PrismarineJS/prismarine-template.git"
"url": "git+https://github.com/PrismarineJS/prismarine-realms.git"
},
"keywords": [
"prismarine",
"template"
"realms"
],
"author": "Romain Beaumont",
"license": "MIT",
"bugs": {
"url": "https://github.com/PrismarineJS/prismarine-template/issues"
"url": "https://github.com/PrismarineJS/prismarine-realms/issues"
},
"homepage": "https://github.com/PrismarineJS/prismarine-template#readme",
"homepage": "https://github.com/PrismarineJS/prismarine-realms#readme",
"devDependencies": {
"prismarine-template": "file:.",
"standard": "^16.0.1",
"mocha": "^9.1.3"
"chai": "^4.3.6",
"chai-as-promised": "^7.1.1",
"chai-exclude": "^2.1.0",
"mocha": "^9.1.3",
"nock": "^13.2.4",
"prismarine-auth": "^1.5.0",
"prismarine-realms": "file:.",
"standard": "^16.0.1"
},
"dependencies": {
"node-fetch": "^2.6.1"
}
}
24 changes: 24 additions & 0 deletions src/bedrock/api.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const RealmAPI = require('../index')
const Realm = require('../structures/Realm')

module.exports = class BedrockRealmAPI extends RealmAPI {
async getRealmAddress (realmId) {
const data = await this.rest.get(`/worlds/${realmId}/join`)
return { address: data.address }
}

async invitePlayer (realmId, uuid) {
const data = await this.rest.put(`/invites/${realmId}/invite/update`, {
body: {
invites: {
[uuid]: 'ADD'
}
}
})
return new Realm(this, data)
}

async changeRealmState (realmId, state) {
return await this.rest.put(`/worlds/${realmId}/${state}`)
}
}
7 changes: 7 additions & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = {
BedrockHost: 'https://pocket.realms.minecraft.net',
JavaHost: 'https://pc.realms.minecraft.net',
BedrockUserAgent: 'MCPE/UWP',
JavaUserAgent: 'MinecraftLauncher/2.2.10675',
BedrockRealmsRelyingParty: 'https://pocket.realms.minecraft.net/'
}
29 changes: 29 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
const Rest = require('./rest')
const Realm = require('./structures/Realm')

const PlatformTypes = ['java', 'bedrock']

class RealmAPI {
constructor (Authflow, platform, options = {}) {
if (!Authflow) throw new Error('Need to proive an Authflow instance to use the Realm API https://github.com/PrismarineJS/prismarine-auth')
if (!PlatformTypes.includes(platform?.toLowerCase())) throw new Error(`Platform provided is not valid. Must be ${PlatformTypes.join(' | ')}`)

this.rest = new Rest(Authflow, platform, options)
}

static from (authflow, platform, options) {
return (platform === 'bedrock') ? new (require('./bedrock/api'))(authflow, platform, options) : new (require('./java/api'))(authflow, platform, options)
}

async getRealm (realmId) {
const data = await this.rest.get(`/worlds/${realmId}`)
return new Realm(this, data)
}

async getRealms () {
const data = await this.rest.get('/worlds')
return data.servers.map(realm => new Realm(this, realm))
}
}

module.exports = RealmAPI
Loading

0 comments on commit cecc7e5

Please sign in to comment.