Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Various Typing Fixes & Client-Side Render Event (Multiple Client Compatible) #428

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
node_modules
package-lock.json
yarn.lock
/test/*.png
versions/
public/index.js*
Expand Down
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"print.colourScheme": "GitHub"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove

}
7 changes: 5 additions & 2 deletions examples/bot.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@ const mineflayer = require('mineflayer')
const mineflayerViewer = require('prismarine-viewer').mineflayer

const bot = mineflayer.createBot({
username: 'Bot'
username: 'Bot',
host: process.argv[2],
port: isNaN(parseInt(process.argv[3])) ? 25565 : parseInt(process.argv[3]),
version: process.argv[4] ?? '1.16.5'
})

bot.once('spawn', () => {
bot.once('spawn', async () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That doesn't do anything, please undo

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

mineflayerViewer(bot, { port: 3000 })

const path = [bot.entity.position.clone()]
Expand Down
18 changes: 18 additions & 0 deletions examples/typescript/bot.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import * as mineflayer from "mineflayer";
import { mineflayer as mineflayerLoader } from "prismarine-viewer";

import type { Vec3 } from "vec3";

const bot = mineflayer.createBot({
username: "Bot",
});

bot.once("spawn", async () => {
mineflayerLoader(bot, { port: 3000 });

const path: Vec3[] = [bot.entity.position.clone()];
if (path[path.length - 1].distanceTo(bot.entity.position) > 1) {
path.push(bot.entity.position.clone());
bot.viewer.drawLine("path", path);
}
});
30 changes: 29 additions & 1 deletion index.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,32 @@
import {Bot} from "mineflayer";
import type {Bot} from "mineflayer";

// TODO: BlockFace should be from here (0 to 5)
import { Block } from "prismarine-block";
import type { Vec3 } from "vec3";

import type {PointsMaterialParameters} from 'three'


interface BotViewerEvents {
blockClicked: (block: Block, face: number, button: number) => void;
onRender: (fps: number) => void;
}

interface BotViewer {
erase: (id: string) => void;
drawBoxGrid: (id: string, start: Vec3, end: Vec3, color: PointsMaterialParameters) => void;
drawLine: (id: string, points: Vec3[], color?: PointsMaterialParameters) => void;
drawPoints: (id: string, points: Vec3[], color?: PointsMaterialParameters, size?: number) => void;
close: () => void;
}


declare module 'mineflayer' {
interface Bot {
viewer: BotViewer;
}
}


export function mineflayer(bot: Bot, settings: {
viewDistance?: number;
Expand Down
20 changes: 19 additions & 1 deletion lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,28 @@ const viewer = new Viewer(renderer)

let controls = new THREE.OrbitControls(viewer.camera, renderer.domElement)

const fpsCheck = 1000 // ms
let lastTime = performance.now()
let frameCount = 0

function handleUpdate () {
frameCount++
const currentTime = performance.now()

if (currentTime - lastTime > fpsCheck) {
const fps = Math.ceil((frameCount / ((currentTime - lastTime) / fpsCheck)))
lastTime = currentTime
frameCount = 0
if (fps != null) socket.emit('renderFPS', { id: socket.id, fps })
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add to doc + use it in an example to explain what it's good for

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not know where I would put this server-sided event (renderFPS) firing into docs as there is no mention of server-sided code in the READMEs.

I included documentation on the bot.viewer event firing, however.

}

viewer.update()
}

function animate () {
window.requestAnimationFrame(animate)
if (controls) controls.update()
viewer.update()
handleUpdate()
renderer.render(viewer.scene, viewer.camera)
}
animate()
Expand Down
81 changes: 81 additions & 0 deletions lib/mineflayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,83 @@ module.exports = (bot, { viewDistance = 6, firstPerson = false, port = 3000, pre
}
}

let renderInterval = null

let maxFPS = 0
let maxFPSId = null

const fpsMap = new Map()

io.on('connection', (socket) => {
const getRenderInterval = (fps) => setInterval(() => bot.viewer.emit('onRender', fps), 1000 / fps)

const updateListener = ({ id, fps }) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add a comment explaining the intent of this; it's far from obvious

if (id == null || fps == null) return

fpsMap.set(id, fps)

if (fps > maxFPS) {
maxFPS = fps
if (renderInterval) clearInterval(renderInterval)

renderInterval = getRenderInterval(maxFPS)
} else if (id === maxFPSId && fps < maxFPS) {
// handle where maxFPSId's fps decreases

let secondHighest = 0
let secondHighestId = null

// check for alternative highest fps
for (const [id1, fps1] of fpsMap) {
if (fps1 > secondHighest && id1 !== id) {
secondHighest = fps1
secondHighestId = id1
}
}

// if there is no alternative highest fps, set maxFPS to current fps
// note: if secondHighest is 0, then there is no alternative highest fps
if (fps > secondHighest) {
maxFPS = fps
maxFPSId = id
if (renderInterval) clearInterval(renderInterval)

renderInterval = getRenderInterval(maxFPS)
} else {
// if there is an alternative highest fps that is higher than current FPS,
// set maxFPS to the alternative highest fps
maxFPS = secondHighest
maxFPSId = secondHighestId
if (renderInterval) clearInterval(renderInterval)

renderInterval = getRenderInterval(maxFPS)
}
}
}

const onSocketRemoval = () => {
if (fpsMap.has(socket.id)) {
fpsMap.delete(socket.id)
}

if (fpsMap.size === 0) {
maxFPS = 0
if (renderInterval) clearInterval(renderInterval)
return
}

for (const [, fps] of fpsMap) {
if (fps > maxFPS) {
maxFPS = fps
}
}

if (renderInterval) clearInterval(renderInterval)

renderInterval = getRenderInterval(maxFPS)
}

socket.on('renderFPS', updateListener)
socket.emit('version', bot.version)
sockets.push(socket)

Expand Down Expand Up @@ -75,6 +151,7 @@ module.exports = (bot, { viewDistance = 6, firstPerson = false, port = 3000, pre
bot.removeListener('move', botPosition)
worldView.removeListenersFromBot(bot)
sockets.splice(sockets.indexOf(socket), 1)
onSocketRemoval()
})
})

Expand All @@ -87,5 +164,9 @@ module.exports = (bot, { viewDistance = 6, firstPerson = false, port = 3000, pre
for (const socket of sockets) {
socket.disconnect()
}

// should already always be handled, but hey you never know.
if (renderInterval) clearInterval(renderInterval)
fpsMap.clear()
}
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"vec3": "^0.1.7"
},
"devDependencies": {
"@types/three": "^0.161.2",
"assert": "^2.0.0",
"buffer": "^6.0.3",
"canvas": "^2.6.1",
Expand Down
2 changes: 1 addition & 1 deletion viewer/lib/viewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class Viewer {
this.primitives = new Primitives(this.scene, this.camera)

this.domElement = renderer.domElement
this.playerHeight = 1.6
this.playerHeight = 1.62
this.isSneaking = false
}

Expand Down
Loading