Last active
November 22, 2020 22:14
-
-
Save seleb/19bae2ac7e73177e8623d9af96f4c180 to your computer and use it in GitHub Desktop.
simple client for zone usable from console as a bot
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// avatar utils (mostly copied from blitsy) | |
function encodeM1(pixels) { | |
var pixels32 = new Uint32Array(pixels); | |
var data = new Uint8ClampedArray(Math.ceil(pixels32.length / 8)); | |
for (var i = 0; i < data.length; ++i) { | |
var byte = 0; | |
for (var bit = 0; bit < 8; ++bit) { | |
byte <<= 1; | |
byte |= pixels32[i * 8 + (7 - bit)] > 0 ? 1 : 0; | |
} | |
data[i] = byte; | |
} | |
return data; | |
} | |
function uint8ToBase64(u8Arr) { | |
var CHUNK_SIZE = 0x8000; // arbitrary number | |
var index = 0; | |
var length = u8Arr.length; | |
var result = ''; | |
while (index < length) { | |
var slice = u8Arr.subarray(index, Math.min(index + CHUNK_SIZE, length)); | |
result += String.fromCharCode.apply(null, slice); | |
index += CHUNK_SIZE; | |
} | |
return btoa(result); | |
} | |
function stringToAvatar(string) { | |
return uint8ToBase64( | |
encodeM1( | |
string | |
.replace(/\s/g, '') | |
.split('') | |
.map(i => parseInt(i, 2)) | |
) | |
); | |
} | |
function stringToAvatars(string) { | |
return string.trim().split(/\n\n+/).map(stringToAvatar); | |
} | |
// zonebot | |
class ZoneBot { | |
constructor() { | |
this.connect(); | |
this.intervalAvatar = undefined; | |
this._name = ''; | |
} | |
connect() { | |
// socket setup | |
this.socket = new WebSocket(`${window.location.origin.replace('http', 'ws')}/zone`); | |
this.connectionPromise = new Promise((resolve, reject) => { | |
this.socket.onopen = resolve; | |
this.socket.onerror = reject; | |
}); | |
this.socket.onmessage = event => { | |
const data = JSON.parse(event.data); | |
if (data.type === 'heartbeat') { | |
this.send({ type: 'heartbeat' }); | |
return; | |
} | |
if (this.onmessage) { | |
this.onmessage(data); | |
} | |
}; | |
} | |
async send(data) { | |
await this.connectionPromise; | |
this.socket.send(JSON.stringify(data)); | |
} | |
// api | |
join(name) { | |
this._name = name; | |
this.send({ type: 'join', name }); | |
} | |
disconnect() { | |
if (this.socket) { | |
this.stopCycle(); | |
this.socket.close(); | |
this.socket = undefined; | |
} | |
} | |
say(text) { | |
this.send({ type: 'chat', text }); | |
} | |
name(name) { | |
this._name = name; | |
this.send({ type: 'user', name }); | |
} | |
move(x, y) { | |
this.send({ type: 'user', position: [x, 0, y] }); | |
} | |
emotes(emotes) { | |
this.send({ type: 'user', emotes }); | |
} | |
_avatar(avatar) { | |
this.send({ type: 'user', avatar }); | |
} | |
avatar(avatar) { | |
this._avatar(stringToAvatar(avatar)); | |
} | |
cycleAvatars(avatars, interval) { | |
const frames = stringToAvatars(avatars); | |
this.stopCycle(); | |
let frame = 0; | |
this.intervalAvatar = setInterval(() => { | |
++frame; | |
frame %= frames.length; | |
this._avatar(frames[frame]); | |
}, interval || 400); | |
} | |
stopCycle() { | |
clearInterval(this.intervalAvatar); | |
this.intervalAvatar = undefined; | |
} | |
} | |
// demo | |
(function () { | |
const bot = new ZoneBot(); | |
bot.join('zonebot'); | |
bot.move(Math.random() * 16, Math.random() * 16); | |
bot.cycleAvatars(` | |
00011000 | |
00001001 | |
00111110 | |
00011000 | |
11111000 | |
00011000 | |
00001000 | |
00001000 | |
00011000 | |
00001000 | |
00011000 | |
00111000 | |
00111000 | |
00011110 | |
00010000 | |
00010000 | |
`); | |
bot.emotes(['wvy', 'spn']); | |
bot.say('jumping is not a crime'); | |
// simple chat response | |
bot.onmessage = data => { | |
if (data.type === 'chat') { | |
if (data.text.includes(bot._name)) { | |
bot.say('THE ZONE'); | |
} | |
} | |
}; | |
return bot; | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment