98 lines
3.5 KiB
JavaScript
98 lines
3.5 KiB
JavaScript
const ffmpeg = require('fluent-ffmpeg')
|
|
// const tmp = require('tmp')
|
|
const fs = require('fs')
|
|
const path = require('path')
|
|
// const canvas = require('canvas')
|
|
const colorsys = require('colorsys')
|
|
const { randomUUID } = require('crypto')
|
|
const nbt = require('prismarine-nbt')
|
|
const SNBT = require('../util/snbt.js')
|
|
const toNBTUUID = require('./../util/uuid-to-nbt-uuid.js')
|
|
|
|
// const cnv = canvas.createCanvas(256, 144)
|
|
// const ctx = cnv.getContext('2d')
|
|
|
|
function inject (bot) {
|
|
const video = {
|
|
nowPlaying: null,
|
|
_interval: null,
|
|
_tmpobj: null,
|
|
play,
|
|
stop,
|
|
summon
|
|
}
|
|
bot.video = video
|
|
|
|
async function play (input, uuids) {
|
|
uuids ??= await summon(cnv.height)
|
|
video._tmpobj = tmp.dirSync()
|
|
bot.core.run('minecraft:tellraw @a ' + JSON.stringify('Extracting frames from the video...'))
|
|
ffmpeg(input)
|
|
.output(path.join(video._tmpobj.name, '%01d.bmp'))
|
|
.fps(30)
|
|
.size(cnv.width + 'x' + cnv.height)
|
|
.on('error', (err) => bot.core.run('minecraft:tellraw @a ' + JSON.stringify({ text: require('util').inspect(err).replace(/\n.*/g, ''), color: 'red' })))
|
|
.on('end', playVideo)
|
|
.run()
|
|
|
|
function playVideo () {
|
|
bot.core.run('minecraft:tellraw @a ' + JSON.stringify('Now playing the video'))
|
|
|
|
const frames = []
|
|
fs.readdirSync(video._tmpobj.name).forEach((filename) => {
|
|
const filepath = path.join(video._tmpobj.name, filename)
|
|
let num = filename
|
|
// while (num.length !== 0 && !/\d/.test(num[0])) {
|
|
// num = num.slice(1)
|
|
// }
|
|
num = parseInt(num)
|
|
frames[num] = filepath
|
|
})
|
|
|
|
let i = 0
|
|
video._interval = setInterval(async () => {
|
|
const img = await canvas.loadImage(frames[i++]).catch(({ message }) => bot.core.run('minecraft:tellraw @a ' + JSON.stringify({ text: message, color: 'red' })))
|
|
if (!(img ?? false)) return
|
|
fs.unlink(frames[i - 1], () => {})
|
|
ctx.drawImage(img, 0, 0, cnv.width, cnv.height)
|
|
const rgba = ctx.getImageData(0, 0, cnv.width, cnv.height).data
|
|
let line = []
|
|
let k = 0
|
|
for (let j = 0; j < rgba.length; j += 4) {
|
|
const r = rgba[j]
|
|
const g = rgba[j + 1]
|
|
const b = rgba[j + 2]
|
|
const hex = colorsys.rgbToHex(r, g, b)
|
|
if (line.length >= 1 && line[line.length - 1].color === hex) line[line.length - 1].text += '╷'
|
|
else line.push({ text: '╷', color: hex })
|
|
if (((j / 4) % cnv.width) === 0) {
|
|
bot.core.run(`minecraft:data modify entity ${uuids[k++]} CustomName set value ${SNBT.stringify(nbt.string(JSON.stringify(line)))}`)
|
|
line = []
|
|
}
|
|
}
|
|
if (i >= frames.length) stop()
|
|
}, 33.33333)
|
|
}
|
|
}
|
|
function stop () {
|
|
clearInterval(video._interval)
|
|
video._tmpobj?.removeCallback()
|
|
}
|
|
function summon (amount) {
|
|
return new Promise((resolve) => {
|
|
const uuids = []
|
|
bot.core.run('minecraft:tellraw @a ' + JSON.stringify({ text: 'Summoning armor stands...' }))
|
|
video._interval = setInterval(() => {
|
|
const uuid = randomUUID()
|
|
bot.exploits.execute(`at _ChipMC_ run summon armor_stand ~ ~${uuids.length * -0.1} ~ ${SNBT.stringify(nbt.comp({ UUID: toNBTUUID(uuid), CustomNameVisible: nbt.byte(1), Invisible: nbt.byte(1), Marker: nbt.byte(1) }))}`)
|
|
uuids.push(uuid)
|
|
if (uuids.length >= amount) {
|
|
clearInterval(video._interval)
|
|
resolve(uuids)
|
|
}
|
|
}, 100)
|
|
})
|
|
}
|
|
}
|
|
|
|
module.exports = inject
|