Skip to content

Commit

Permalink
feat(minecraft): support minecraft adapter
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed Aug 13, 2021
1 parent fbf26fa commit 77c448d
Show file tree
Hide file tree
Showing 6 changed files with 174 additions and 0 deletions.
37 changes: 37 additions & 0 deletions packages/adapter-minecraft/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"name": "koishi-adapter-minecraft",
"description": "Minecraft adapter for Koishi",
"version": "0.1.0",
"main": "lib/index.js",
"typings": "lib/index.d.ts",
"files": [
"lib"
],
"author": "undefined <i@undefined.moe>",
"maintainers": [
"Shigma <1700011071@pku.edu.cn>",
"undefined <i@undefined.moe>"
],
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/koishijs/koishi.git"
},
"bugs": {
"url": "https://github.com/koishijs/koishi/issues"
},
"homepage": "https://koishi.js.org/api/adapter/minecraft.html",
"keywords": [
"bot",
"minecraft",
"mineflayer",
"chatbot",
"koishi"
],
"peerDependencies": {
"koishi-core": "^3.13.0"
},
"dependencies": {
"mineflayer": "^3.9.0"
}
}
49 changes: 49 additions & 0 deletions packages/adapter-minecraft/src/bot.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { Bot, Random, segment } from 'koishi-core'

const noop = async () => null

export class MinecraftBot extends Bot<'minecraft'> {
version = 'minecraft'
client: import('mineflayer').Bot

async sendMessage(channelId: string, content: string, groupId?: string) {
const session = this.createSession({ channelId, content, groupId, subtype: groupId ? 'group' : 'private' })
if (await this.app.serial(session, 'before-send', session)) return
const image = { type: 'text', data: { content: '[Image]' } }
content = segment.join(segment.parse(content).map(i => i.type === 'image' ? image : i))
if (content.length > 512) content = content.substr(0, 512) + '...'
if (channelId === '_public') this.client.chat(content)
else this.client.whisper(channelId, content)

this.app.emit(session, 'send', session)
return Random.uuid()
}

async sendPrivateMessage(channelId: string, content: string) {
return this.sendMessage(channelId, content)
}

handleFriendRequest = noop
handleGroupMemberRequest = noop
handleGroupRequest = noop
editMessage = noop
deleteMessage = noop
deleteFriend = noop
getMessage = noop
getUser = noop
getChannel = noop
getGroupMember = noop
getGroup = noop

async getGroupMemberList() {
return []
}

async getGroupList() {
return []
}

async getChannelList() {
return []
}
}
18 changes: 18 additions & 0 deletions packages/adapter-minecraft/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Adapter } from 'koishi-core'
import { MinecraftBot } from './bot'
import WsClient from './ws'
export * from './bot'

declare module 'koishi-core' {
interface AppOptions {
minecraft?: {}
}

namespace Bot {
interface Platforms {
minecraft: MinecraftBot
}
}
}

Adapter.types['minecraft'] = WsClient
59 changes: 59 additions & 0 deletions packages/adapter-minecraft/src/ws.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { App, Adapter, Session } from 'koishi-core'
import { createBot } from 'mineflayer'
import { MinecraftBot } from './bot'

export default class WsClient extends Adapter.WsClient<'minecraft'> {
constructor(app: App) {
super(app, MinecraftBot)
}

async prepare(bot: MinecraftBot) {
const config = {
skipValidation: true,
host: '1.1.1.1', // minecraft server ip
username: 'bot', // minecraft username
password: '12345678', // minecraft password, comment out if you want to log into online-mode=false servers
port: 25565, // only set if you need a port that isn't 25565
}
bot.client = createBot(config)
return {
url: 'minecraft://' + config.host + ':' + config.port + '/' + config.username,
on(name, event) {
if (name === 'open') bot.client.on('login', () => event())
if (name === 'error') bot.client.on('error', (err) => event(err))
if (name === 'close') bot.client.on('kicked', (reason) => event(reason))
},
} as any
}

async connect(bot: MinecraftBot) {
const common: Partial<Session> = {
platform: 'minecraft',
type: 'message',
selfId: bot.client.username,
}

bot.client.on('chat', (author, content, translate, jsonMsg, matches) => {
if (author === bot.client.username) return
this.dispatch(new Session(this.app, {
...common,
content,
author: { userId: author },
channelId: '_public',
}))
})
bot.client.on('whisper', (author, content, translate, jsonMsg, matches) => {
this.dispatch(new Session(this.app, {
...common,
content,
author: { userId: author },
channelId: author,
}))
})
setInterval(() => {
// Keep alive
bot.client.setControlState('jump', true)
bot.client.setControlState('jump', false)
}, 3000)
}
}
10 changes: 10 additions & 0 deletions packages/adapter-minecraft/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"extends": "../../tsconfig.base",
"compilerOptions": {
"outDir": "lib",
"rootDir": "src",
},
"include": [
"src",
],
}
1 change: 1 addition & 0 deletions tsconfig.base.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"emitDeclarationOnly": true,
"composite": true,
"incremental": true,
"skipLibCheck": true,
"esModuleInterop": true,
"moduleResolution": "node",
"strictBindCallApply": true,
Expand Down

0 comments on commit 77c448d

Please sign in to comment.