Skip to content

Commit

Permalink
feat: add ping display view in pause menu!
Browse files Browse the repository at this point in the history
  • Loading branch information
zardoy committed Feb 18, 2025
1 parent 1910433 commit 612b354
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 25 deletions.
18 changes: 2 additions & 16 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ import { playerState, PlayerStateManager } from './mineflayer/playerState'
import { states } from 'minecraft-protocol'
import { initMotionTracking } from './react/uiMotion'
import { UserError } from './mineflayer/userError'
import ping from './mineflayer/plugins/ping'

window.debug = debug
window.THREE = THREE
Expand Down Expand Up @@ -643,22 +644,7 @@ export async function connect (connectOptions: ConnectOptions) {
})
})
})
let i = 0
//@ts-expect-error
bot.pingProxy = async () => {
const curI = ++i
return new Promise(resolve => {
//@ts-expect-error
bot._client.socket._ws.send(`ping:${curI}`)
const date = Date.now()
const onPong = (received) => {
if (received !== curI.toString()) return
bot._client.socket.off('pong' as any, onPong)
resolve(Date.now() - date)
}
bot._client.socket.on('pong' as any, onPong)
})
}
bot.loadPlugin(ping)
}
// socket setup actually can be delayed because of dns lookup
if (bot._client.socket) {
Expand Down
18 changes: 10 additions & 8 deletions src/mineflayer/plugins/ping.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { versionToNumber } from 'renderer/viewer/prepare/utils'

export default () => {
let i = 0
bot.pingProxy = async () => {
Expand All @@ -15,19 +17,19 @@ export default () => {
})
}

let pingPending = false
let pingId = 0
bot.pingServer = async () => {
if (pingPending) return
pingPending = true
if (versionToNumber(bot.version) < versionToNumber('1.20.2')) return bot.player.ping
return new Promise<number>((resolve) => {
bot._client.write('ping' as any, { time: [0, 0] })
const curId = pingId++
bot._client.write('ping_request', { id: BigInt(curId) })
const date = Date.now()
const onPong = () => {
bot._client.off('ping' as any, onPong)
const onPong = (data: { id: bigint }) => {
if (BigInt(data.id) !== BigInt(curId)) return
bot._client.off('ping_response' as any, onPong)
resolve(Date.now() - date)
pingPending = false
}
bot._client.on('ping' as any, onPong)
bot._client.on('ping_response' as any, onPong)
})
}
}
Expand Down
42 changes: 42 additions & 0 deletions src/react/NetworkStatus.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
.container {
scale: 0.8;
transform-origin: left;
display: grid;
grid-template-columns: auto auto auto auto auto;
gap: 2px 4px;
font-size: 8px;
color: #fff;
opacity: 0.8;
align-items: center;
justify-content: center;
text-align: center;
justify-items: center;
}

.iconRow {
display: block;
}
.arrowRow {
scale: 1.5 1;
}

.dataRow {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 70px;
font-size: 5px;
}

.ping {
font-size: 6px;
}

/* .dataRow > span:nth-child(3) {
max-width: 120px;
} */

.totalRow {
grid-column: span 3;
font-size: 7px;
}
12 changes: 12 additions & 0 deletions src/react/NetworkStatus.module.css.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// This file is automatically generated.
// Please do not change this file!
interface CssExports {
arrowRow: string;
container: string;
dataRow: string;
iconRow: string;
ping: string;
totalRow: string;
}
declare const cssExports: CssExports;
export default cssExports;
64 changes: 64 additions & 0 deletions src/react/NetworkStatus.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { useEffect, useState } from 'react'
import { lastConnectOptions } from './AppStatusProvider'
import PixelartIcon, { pixelartIcons } from './PixelartIcon'
import styles from './NetworkStatus.module.css'

export default () => {
const [proxyPing, setProxyPing] = useState<number | null>(null)
const [serverPing, setServerPing] = useState<number | null>(null)

useEffect(() => {
if (!lastConnectOptions.value?.proxy) return

let update = 0

const updatePing = async () => {
const currentUpdate = ++update

const updateServerPing = async () => {
const ping = await bot.pingServer()
if (ping) setServerPing(ping)
}

const updateProxyPing = async () => {
const ping = await bot.pingProxy()
setProxyPing(ping)
}

try {
await Promise.all([updateServerPing(), updateProxyPing()])
} catch (err) {
console.error('Failed to ping:', err)
}
}

void updatePing()
const interval = setInterval(updatePing, 1000)
return () => clearInterval(interval)
}, [])

// if (!lastConnectOptions.value?.proxy) return null

const { username } = bot.player
const { proxy: proxyUrl, server: serverIp } = lastConnectOptions.value!
const pingTotal = serverPing

const ICON_SIZE = 18
return (
<div className={styles.container}>
<PixelartIcon className={styles.iconRow} iconName={pixelartIcons.monitor} width={ICON_SIZE} />
<PixelartIcon className={`${styles.iconRow} ${styles.arrowRow}`} iconName={pixelartIcons['arrow-right']} width={16} />
<PixelartIcon className={styles.iconRow} iconName={pixelartIcons.server} width={ICON_SIZE} />
<PixelartIcon className={`${styles.iconRow} ${styles.arrowRow}`} iconName={pixelartIcons['arrow-right']} width={16} />
<PixelartIcon className={styles.iconRow} iconName={pixelartIcons['list-box']} width={ICON_SIZE} />

<span className={styles.dataRow}>{username}</span>
<span className={`${styles.dataRow} ${styles.ping}`}>{proxyPing}ms</span>
<span className={styles.dataRow}>{proxyUrl}</span>
<span className={`${styles.dataRow} ${styles.ping}`}>{pingTotal ? pingTotal - (proxyPing ?? 0) : '...'}ms</span>
<span className={styles.dataRow}>{serverIp}</span>

<span className={styles.totalRow}>Ping: {pingTotal}ms</span>
</div>
)
}
4 changes: 4 additions & 0 deletions src/react/PauseScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import styles from './PauseScreen.module.css'
import { DiscordButton } from './DiscordButton'
import { showNotification } from './NotificationProvider'
import { appStatusState, reconnectReload } from './AppStatusProvider'
import NetworkStatus from './NetworkStatus'

const waitForPotentialRender = async () => {
return new Promise<void>(resolve => {
Expand Down Expand Up @@ -226,6 +227,9 @@ export default () => {
style={{ position: 'fixed', top: '5px', left: 'calc(env(safe-area-inset-left) + 5px)' }}
onClick={async () => openWorldActions()}
/>
<div style={{ position: 'fixed', top: '5px', left: 'calc(env(safe-area-inset-left) + 35px)' }}>
<NetworkStatus />
</div>
<div className={styles.pause_container}>
<Button className="button" style={{ width: '204px' }} onClick={onReturnPress}>Back to Game</Button>
<div className={styles.row}>
Expand Down
2 changes: 1 addition & 1 deletion src/react/PixelartIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export default ({
className = undefined as undefined | string,
onClick = () => { }
}) => {
if (width !== undefined) styles = { width, height: width, ...styles }
if (width !== undefined) styles = { width, height: width, fontSize: width, ...styles }
iconName = iconName.replace('pixelarticons:', '')

return <div
Expand Down

0 comments on commit 612b354

Please sign in to comment.