Skip to content

Commit

Permalink
fallback p2p discovery server (#211)
Browse files Browse the repository at this point in the history
  • Loading branch information
zardoy authored Sep 30, 2024
2 parents 2953554 + 5b56518 commit 0a0b87b
Show file tree
Hide file tree
Showing 21 changed files with 236 additions and 152 deletions.
2 changes: 2 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
"defaultHost": "<from-proxy>",
"defaultProxy": "proxy.mcraft.fun",
"mapsProvider": "https://maps.mcraft.fun/",
"peerJsServer": "",
"peerJsServerFallback": "https://p2p.mcraft.fun",
"promoteServers": [
{
"ip": "kaboom.pw",
Expand Down
1 change: 1 addition & 0 deletions prismarine-viewer/viewer/lib/entities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,7 @@ export class Entities extends EventEmitter {
}

update (entity: import('prismarine-entity').Entity & { delete?; pos }, overrides) {
console.log('entity', entity)
const isPlayerModel = entity.name === 'player'
if (entity.name === 'zombie' || entity.name === 'zombie_villager' || entity.name === 'husk') {
overrides.texture = `textures/1.16.4/entity/${entity.name === 'zombie_villager' ? 'zombie_villager/zombie_villager.png' : `zombie/${entity.name}.png`}`
Expand Down
2 changes: 1 addition & 1 deletion prismarine-viewer/viewer/lib/worldDataEmitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { EventEmitter } from 'events'
import { generateSpiralMatrix, ViewRect } from 'flying-squid/dist/utils'
import { Vec3 } from 'vec3'
import { BotEvents } from 'mineflayer'
import { getItemFromBlock } from '../../../src/botUtils'
import { getItemFromBlock } from '../../../src/chatUtils'
import { chunkPos } from './simpleUtils'

export type ChunkPosKey = string
Expand Down
122 changes: 0 additions & 122 deletions src/botUtils.ts
Original file line number Diff line number Diff line change
@@ -1,127 +1,5 @@
// this should actually be moved to mineflayer / prismarine-viewer

import { fromFormattedString, TextComponent } from '@xmcl/text-component'
import type { IndexedData } from 'minecraft-data'
import { versionToNumber } from 'prismarine-viewer/viewer/prepare/utils'

export type MessageFormatPart = Pick<TextComponent, 'hoverEvent' | 'clickEvent'> & {
text: string
color?: string
bold?: boolean
italic?: boolean
underlined?: boolean
strikethrough?: boolean
obfuscated?: boolean
}

type MessageInput = {
text?: string
translate?: string
with?: Array<MessageInput | string>
color?: string
bold?: boolean
italic?: boolean
underlined?: boolean
strikethrough?: boolean
obfuscated?: boolean
extra?: MessageInput[]
json?: any
}

const global = globalThis as any

// todo move to sign-renderer, replace with prismarine-chat, fix mcData issue!
export const formatMessage = (message: MessageInput, mcData: IndexedData = global.loadedData) => {
let msglist: MessageFormatPart[] = []

const readMsg = (msg: MessageInput) => {
const styles = {
color: msg.color,
bold: !!msg.bold,
italic: !!msg.italic,
underlined: !!msg.underlined,
strikethrough: !!msg.strikethrough,
obfuscated: !!msg.obfuscated
}

if (msg.text) {
msglist.push({
...msg,
text: msg.text,
...styles
})
} else if (msg.translate) {
const tText = mcData?.language[msg.translate] ?? msg.translate

if (msg.with) {
const splitted = tText.split(/%s|%\d+\$s/g)

let i = 0
for (const [j, part] of splitted.entries()) {
msglist.push({ text: part, ...styles })

if (j + 1 < splitted.length) {
if (msg.with[i]) {
const msgWith = msg.with[i]
if (typeof msgWith === 'string') {
readMsg({
...styles,
text: msgWith
})
} else {
readMsg({
...styles,
...msgWith
})
}
}
i++
}
}
} else {
msglist.push({
...msg,
text: tText,
...styles
})
}
}

if (msg.extra) {
for (const ex of msg.extra) {
readMsg({ ...styles, ...ex })
}
}
}

readMsg(message)

const flat = (msg) => {
return [msg, msg.extra?.flatMap(flat) ?? []]
}

msglist = msglist.map(msg => {
// normalize §
if (!msg.text.includes?.('§')) return msg
const newMsg = fromFormattedString(msg.text)
return flat(newMsg)
}).flat(Infinity)

return msglist
}

const blockToItemRemaps = {
water: 'water_bucket',
lava: 'lava_bucket',
redstone_wire: 'redstone',
tripwire: 'tripwire_hook'
}

export const getItemFromBlock = (block: import('prismarine-block').Block) => {
const item = global.loadedData.itemsByName[blockToItemRemaps[block.name] ?? block.name]
return item
}

export const displayClientChat = (text: string) => {
const message = {
text
Expand Down
2 changes: 1 addition & 1 deletion src/botUtils.test.ts → src/chatUtils.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { test, expect } from 'vitest'
import mcData from 'minecraft-data'
import { formatMessage } from './botUtils'
import { formatMessage } from './chatUtils'

//@ts-expect-error
globalThis.loadedData ??= mcData('1.20.1')
Expand Down
123 changes: 123 additions & 0 deletions src/chatUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// this should actually be moved to mineflayer / prismarine-viewer

import { fromFormattedString, TextComponent } from '@xmcl/text-component'
import type { IndexedData } from 'minecraft-data'
import { versionToNumber } from 'prismarine-viewer/viewer/prepare/utils'

export type MessageFormatPart = Pick<TextComponent, 'hoverEvent' | 'clickEvent'> & {
text: string
color?: string
bold?: boolean
italic?: boolean
underlined?: boolean
strikethrough?: boolean
obfuscated?: boolean
}

type MessageInput = {
text?: string
translate?: string
with?: Array<MessageInput | string>
color?: string
bold?: boolean
italic?: boolean
underlined?: boolean
strikethrough?: boolean
obfuscated?: boolean
extra?: MessageInput[]
json?: any
}

const global = globalThis as any

// todo move to sign-renderer, replace with prismarine-chat, fix mcData issue!
export const formatMessage = (message: MessageInput, mcData: IndexedData = global.loadedData) => {
let msglist: MessageFormatPart[] = []

const readMsg = (msg: MessageInput) => {
const styles = {
color: msg.color,
bold: !!msg.bold,
italic: !!msg.italic,
underlined: !!msg.underlined,
strikethrough: !!msg.strikethrough,
obfuscated: !!msg.obfuscated
}

if (msg.text) {
msglist.push({
...msg,
text: msg.text,
...styles
})
} else if (msg.translate) {
const tText = mcData?.language[msg.translate] ?? msg.translate

if (msg.with) {
const splitted = tText.split(/%s|%\d+\$s/g)

let i = 0
for (const [j, part] of splitted.entries()) {
msglist.push({ text: part, ...styles })

if (j + 1 < splitted.length) {
if (msg.with[i]) {
const msgWith = msg.with[i]
if (typeof msgWith === 'string') {
readMsg({
...styles,
text: msgWith
})
} else {
readMsg({
...styles,
...msgWith
})
}
}
i++
}
}
} else {
msglist.push({
...msg,
text: tText,
...styles
})
}
}

if (msg.extra) {
for (const ex of msg.extra) {
readMsg({ ...styles, ...ex })
}
}
}

readMsg(message)

const flat = (msg) => {
return [msg, msg.extra?.flatMap(flat) ?? []]
}

msglist = msglist.map(msg => {
// normalize §
if (!msg.text.includes?.('§')) return msg
const newMsg = fromFormattedString(msg.text)
return flat(newMsg)
}).flat(Infinity)

return msglist
}

const blockToItemRemaps = {
water: 'water_bucket',
lava: 'lava_bucket',
redstone_wire: 'redstone',
tripwire: 'tripwire_hook'
}

export const getItemFromBlock = (block: import('prismarine-block').Block) => {
const item = global.loadedData.itemsByName[blockToItemRemaps[block.name] ?? block.name]
return item
}
1 change: 1 addition & 0 deletions src/connect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ export type ConnectOptions = {
serverIndex?: string
/** If true, will show a UI to authenticate with a new account */
authenticatedAccount?: AuthenticatedAccount | true
peerOptions?: any
}
2 changes: 1 addition & 1 deletion src/controls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { customCommandsConfig } from './customCommands'
import type { CustomCommand } from './react/KeybindingsCustom'
import { showOptionsModal } from './react/SelectOption'
import widgets from './react/widgets'
import { getItemFromBlock } from './botUtils'
import { getItemFromBlock } from './chatUtils'
import { gamepadUiCursorState, moveGamepadCursorByPx } from './react/GamepadUiCursor'
import { completeTexturePackInstall, resourcePackState } from './resourcePack'
import { showNotification } from './react/NotificationProvider'
Expand Down
7 changes: 3 additions & 4 deletions src/entities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,9 @@ customEvents.on('gameLoaded', () => {
const isWalking = Math.abs(speed.x) > WALKING_SPEED || Math.abs(speed.z) > WALKING_SPEED
const isSprinting = Math.abs(speed.x) > SPRINTING_SPEED || Math.abs(speed.z) > SPRINTING_SPEED
const newAnimation = isWalking ? (isSprinting ? 'running' : 'walking') : 'idle'
const username = e.username!
if (newAnimation !== playerPerAnimation[username]) {
if (newAnimation !== playerPerAnimation[id]) {
viewer.entities.playAnimation(e.id, newAnimation)
playerPerAnimation[username] = newAnimation
playerPerAnimation[id] = newAnimation
}
}
})
Expand Down Expand Up @@ -122,7 +121,7 @@ customEvents.on('gameLoaded', () => {
}
viewer.entities.addListener('remove', (e) => {
loadedSkinEntityIds.delete(e.id)
playerPerAnimation[e.username] = ''
playerPerAnimation[e.id] = ''
bot.tracker.stopTrackingEntity(e, true)
})

Expand Down
3 changes: 3 additions & 0 deletions src/globalState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ export type AppConfig = {
defaultProxy?: string
// defaultProxySave?: string
// defaultVersion?: string
peerJsServer?: string
peerJsServerFallback?: string
promoteServers?: Array<{ ip, description, version? }>
mapsProvider?: string
}
Expand All @@ -120,6 +122,7 @@ export const miscUiState = proxy({
singleplayer: false,
flyingSquid: false,
wanOpened: false,
wanOpening: false,
/** wether game hud is shown (in playing state) */
gameLoaded: false,
showUI: true,
Expand Down
11 changes: 8 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ import defaultServerOptions from './defaultLocalServerOptions'
import dayCycle from './dayCycle'

import { onAppLoad, resourcepackReload } from './resourcePack'
import { connectToPeer } from './localServerMultiplayer'
import { ConnectPeerOptions, connectToPeer } from './localServerMultiplayer'
import CustomChannelClient from './customClient'
import { loadScript } from 'prismarine-viewer/viewer/lib/utils'
import { registerServiceWorker } from './serviceWorker'
Expand Down Expand Up @@ -486,7 +486,7 @@ async function connect (connectOptions: ConnectOptions) {
port: server.port ? +server.port : undefined,
version: connectOptions.botVersion || false,
...p2pMultiplayer ? {
stream: await connectToPeer(connectOptions.peerId!),
stream: await connectToPeer(connectOptions.peerId!, connectOptions.peerOptions),
} : {},
...singleplayer || p2pMultiplayer ? {
keepAlive: false,
Expand Down Expand Up @@ -1022,6 +1022,10 @@ downloadAndOpenFile().then((downloadAction) => {
void Promise.resolve().then(() => {
// try to connect to peer
const peerId = qs.get('connectPeer')
const peerOptions = {} as ConnectPeerOptions
if (qs.get('server')) {
peerOptions.server = qs.get('server')!
}
const version = qs.get('peerVersion')
if (peerId) {
let username: string | null = options.guestUsername
Expand All @@ -1031,7 +1035,8 @@ downloadAndOpenFile().then((downloadAction) => {
void connect({
username,
botVersion: version || undefined,
peerId
peerId,
peerOptions
})
}
})
Expand Down
3 changes: 2 additions & 1 deletion src/inventoryWindows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ import { appReplacableResources } from './generated/resources'
import { activeModalStack, hideCurrentModal, hideModal, miscUiState, showModal } from './globalState'
import { options } from './optionsStorage'
import { assertDefined, inGameError } from './utils'
import { displayClientChat, MessageFormatPart } from './botUtils'
import { displayClientChat } from './botUtils'
import { currentScaling } from './scaleInterface'
import { getItemDescription } from './itemsDescriptions'
import { MessageFormatPart } from './chatUtils'

const loadedImagesCache = new Map<string, HTMLImageElement>()
const cleanLoadedImagesCache = () => {
Expand Down
Loading

0 comments on commit 0a0b87b

Please sign in to comment.