107 lines
3.8 KiB
TypeScript
107 lines
3.8 KiB
TypeScript
import md from 'minecraft-data'
|
|
import Cubbot from '../Cubbot'
|
|
import Data from '../utils/Data'
|
|
import Module from '../utils/Module'
|
|
import Chat, { IMessage } from './Chat'
|
|
import Spawn from './Spawn'
|
|
|
|
type DisconnectReason = 'authservers_down' | 'banned' | 'banned.reason' | 'banned.expiration' | 'banned_ip.reason' |
|
|
'banned_ip.expiration' | 'duplicate_login' | 'flying' | 'generic' | 'idling' | 'illegal_characters' |
|
|
'invalid_entity_attacked' | 'invalid_player_movement' | 'invalid_vehicle_movement' | 'ip_banned' | 'kicked' |
|
|
'outdated_client' | 'outdated_server' | 'server_shutdown' | 'slow_login' | 'unverified_username' |
|
|
'not_whitelisted' | 'server_full' | 'name_taken' | 'unexpected_query_response' | 'genericReason' |
|
|
'disconnected' | 'lost' | 'kicked' | 'timeout' | 'closed' | 'loginFailed' | 'loginFailedInfo' |
|
|
'loginFailedInfo.serversUnavailable' | 'loginFailedInfo.invalidSession' | 'quitting' | 'endOfStream' |
|
|
'overflow' | 'spam'
|
|
const REASON_PREFIX = 'disconnect.'
|
|
|
|
interface IConfig {
|
|
/** Game data url */
|
|
dataSource: string
|
|
/** Game data cache path */
|
|
dataDir: string
|
|
|
|
reconnect: DisconnectReason[] | boolean
|
|
reconnectDelay: number
|
|
}
|
|
|
|
/** Connection informations */
|
|
export default class Connection extends Module<IConfig> {
|
|
|
|
private _connected = false
|
|
public get connected() {
|
|
return this._connected
|
|
}
|
|
|
|
private _oldData = md('1.14')
|
|
public get oldData() {
|
|
return this._oldData
|
|
}
|
|
|
|
private _data = new Data()
|
|
public get data() {
|
|
return this._data
|
|
}
|
|
|
|
private _engine?: Cubbot
|
|
public setEngine(value: Cubbot) {
|
|
this._engine = value
|
|
}
|
|
|
|
protected mount() {
|
|
const spawn = this.load<Spawn>(Spawn)
|
|
spawn.addCheck('data')
|
|
|
|
this.client.on('connect', () => {
|
|
this._connected = true
|
|
this.logger.trace('Connected')
|
|
this._data.onReady(() => spawn.validateCheck('data'))
|
|
})
|
|
this.client.on('disconnect', ({ reason }) => {
|
|
this._connected = false
|
|
const message: IMessage = JSON.parse(reason)
|
|
this.logger.warn({ msg: 'Disconnected', type: 'reason', value: Chat.parse(message, this.oldData.language) })
|
|
this.bye(message.translate)
|
|
})
|
|
this.client.on('kick_disconnect', ({ reason }) => {
|
|
this._connected = false
|
|
const message: IMessage = JSON.parse(reason)
|
|
this.logger.warn({ msg: 'Kicked', type: 'reason', value: Chat.parse(message, this.oldData.language) })
|
|
this.bye(message.translate)
|
|
})
|
|
this.client.on('login', () => {
|
|
this.logger.trace('Logged')
|
|
this._data.load(this.conf.dataSource, this.conf.dataDir, (this.client as any).version,
|
|
this.logger.child({ name: 'Data', level: 'info' }))
|
|
// FIXME: use 'minecraft-data' when it include 1.15+
|
|
})
|
|
this.client.on('error', error => {
|
|
this.logger.error({ msg: 'Error', value: error })
|
|
})
|
|
}
|
|
|
|
protected getConf() {
|
|
return {
|
|
dataDir: './data/',
|
|
dataSource: 'https://pokechu22.github.io/Burger/',
|
|
reconnect: false,
|
|
reconnectDelay: 5000,
|
|
}
|
|
}
|
|
|
|
private bye(reason?: string) {
|
|
if (this.conf.reconnect === true || (this.conf.reconnect !== false && reason !== undefined &&
|
|
this.conf.reconnect.some(r => reason.endsWith(REASON_PREFIX + r)))
|
|
) {
|
|
this._engine?.umount(false)
|
|
this.logger.info({ msg: 'Reconnecting', type: 'ms', value: this.conf.reconnectDelay })
|
|
// MAYBE: exponental backoff
|
|
setTimeout(() => this._engine?.mount(), this.conf.reconnectDelay)
|
|
} else {
|
|
this.logger.info('Bye')
|
|
this._engine?.umount(true)
|
|
}
|
|
}
|
|
|
|
}
|