koishi-plugin-beatsaber-bot
Version:
一个 用于 BeatSaber 的 koishi Bot 插件
282 lines (281 loc) • 9.41 kB
JavaScript
;
// export function checkBSOR(file, isLink, completion) {
// if (isLink) {
// const filename = file.split('?')[0];
// if (filename.split('.').pop() == 'bsor' || filename.split('.').pop() == 'bsortemp') {
// file = file.replace('https://cdn.discordapp.com/', '/cors/discord-cdn/');
// var xhr = new XMLHttpRequest();
// xhr.open('GET', file, true);
// xhr.responseType = 'blob';
//
// xhr.onload = function () {
// checkBSORFile(xhr.response, completion);
// };
// xhr.send();
// } else {
// completion('Error: wrong file format');
// }
// } else {
// checkBSORFile(file, completion);
// }
// }
Object.defineProperty(exports, "__esModule", { value: true });
exports.DecodeNotes = exports.DecodeInfo = exports.decode = exports.NoteEventType = exports.checkBSORFile = void 0;
function checkBSORFile(file, completion) {
var reader = new FileReader();
// (await fetch("")).arrayBuffer()
reader.onload = function (e) {
decode(e.target.result, completion);
};
reader.onerror = function (e) {
// error occurred
completion('Error: ' + e.type);
};
reader.readAsArrayBuffer(file);
}
exports.checkBSORFile = checkBSORFile;
const StructType = {
info: 0,
frames: 1,
notes: 2,
walls: 3,
heights: 4,
pauses: 5,
};
exports.NoteEventType = {
good: 0,
bad: 1,
miss: 2,
bomb: 3,
};
function decode(arrayBuffer, completion) {
const dataView = new DataView(arrayBuffer);
dataView.pointer = 0;
const magic = DecodeInt(dataView);
const version = DecodeUint8(dataView);
if (version == 1 && magic == 0x442d3d69) {
var replay = {};
for (var a = 0; a < StructType.pauses + 1; a++) {
const type = DecodeUint8(dataView);
switch (type) {
case StructType.info:
replay.info = DecodeInfo(dataView);
break;
case StructType.frames:
replay.frames = DecodeFrames(dataView);
break;
case StructType.notes:
replay.notes = DecodeNotes(dataView);
break;
case StructType.walls:
replay.walls = DecodeWalls(dataView);
break;
case StructType.heights:
replay.heights = DecodeHeight(dataView);
break;
case StructType.pauses:
replay.pauses = DecodePauses(dataView);
break;
}
}
completion(replay);
}
else {
completion('Error: failed to decode replay');
}
}
exports.decode = decode;
function DecodeInfo(dataView) {
var result = {};
result.version = DecodeString(dataView);
result.gameVersion = DecodeString(dataView);
result.timestamp = DecodeString(dataView);
result.playerID = DecodeString(dataView);
result.playerName = DecodeName(dataView);
result.platform = DecodeString(dataView);
result.trackingSystem = DecodeString(dataView);
result.hmd = DecodeString(dataView);
result.controller = DecodeString(dataView);
result.hash = DecodeString(dataView);
result.songName = DecodeString(dataView);
result.mapper = DecodeString(dataView);
result.difficulty = DecodeString(dataView);
result.score = DecodeInt(dataView);
result.mode = DecodeString(dataView);
result.environment = DecodeString(dataView);
result.modifiers = DecodeString(dataView);
result.jumpDistance = DecodeFloat(dataView);
result.leftHanded = DecodeBool(dataView);
result.height = DecodeFloat(dataView);
result.startTime = DecodeFloat(dataView);
result.failTime = DecodeFloat(dataView);
result.speed = DecodeFloat(dataView);
return result;
}
exports.DecodeInfo = DecodeInfo;
function DecodeFrames(dataView) {
const length = DecodeInt(dataView);
var result = [];
for (var i = 0; i < length; i++) {
var frame = DecodeFrame(dataView);
if (frame.time != 0 && (result.length == 0 || frame.time != result[result.length - 1].time)) {
result.push(frame);
}
}
return result;
}
function DecodeFrame(dataView) {
var result = {};
result.time = DecodeFloat(dataView);
result.fps = DecodeInt(dataView);
result.head = DecodeEuler(dataView);
result.left = DecodeEuler(dataView);
result.right = DecodeEuler(dataView);
return result;
}
function DecodeNotes(dataView) {
const length = DecodeInt(dataView);
var result = [];
for (var i = 0; i < length; i++) {
result.push(DecodeNote(dataView));
}
return result;
}
exports.DecodeNotes = DecodeNotes;
function DecodeWalls(dataView) {
const length = DecodeInt(dataView);
var result = [];
for (var i = 0; i < length; i++) {
var wall = {};
wall.wallID = DecodeInt(dataView);
wall.energy = DecodeFloat(dataView);
wall.time = DecodeFloat(dataView);
wall.spawnTime = DecodeFloat(dataView);
result.push(wall);
}
return result;
}
function DecodeHeight(dataView) {
const length = DecodeInt(dataView);
var result = [];
for (var i = 0; i < length; i++) {
var height = {};
height.height = DecodeFloat(dataView);
height.time = DecodeFloat(dataView);
result.push(height);
}
return result;
}
function DecodePauses(dataView) {
const length = DecodeInt(dataView);
var result = [];
for (var i = 0; i < length; i++) {
var pause = {};
pause.duration = DecodeLong(dataView);
pause.time = DecodeFloat(dataView);
result.push(pause);
}
return result;
}
function DecodeNote(dataView) {
var result = {};
result.noteID = DecodeInt(dataView);
result.eventTime = DecodeFloat(dataView);
result.spawnTime = DecodeFloat(dataView);
result.eventType = DecodeInt(dataView);
if (result.eventType == exports.NoteEventType.good || result.eventType == exports.NoteEventType.bad) {
result.noteCutInfo = DecodeCutInfo(dataView);
}
return result;
}
function DecodeCutInfo(dataView) {
var result = {};
result.speedOK = DecodeBool(dataView);
result.directionOK = DecodeBool(dataView);
result.saberTypeOK = DecodeBool(dataView);
result.wasCutTooSoon = DecodeBool(dataView);
result.saberSpeed = DecodeFloat(dataView);
result.saberDir = DecodeVector3(dataView);
result.saberType = DecodeInt(dataView);
result.timeDeviation = DecodeFloat(dataView);
result.cutDirDeviation = DecodeFloat(dataView);
result.cutPoint = DecodeVector3(dataView);
result.cutNormal = DecodeVector3(dataView);
result.cutDistanceToCenter = DecodeFloat(dataView);
result.cutAngle = DecodeFloat(dataView);
result.beforeCutRating = DecodeFloat(dataView);
result.afterCutRating = DecodeFloat(dataView);
return result;
}
function DecodeEuler(dataView) {
var result = {};
result.position = DecodeVector3(dataView);
result.rotation = DecodeQuaternion(dataView);
return result;
}
function DecodeVector3(dataView) {
var result = {};
result.x = DecodeFloat(dataView);
result.y = DecodeFloat(dataView);
result.z = DecodeFloat(dataView);
return result;
}
function DecodeQuaternion(dataView) {
var result = {};
result.x = DecodeFloat(dataView);
result.y = DecodeFloat(dataView);
result.z = DecodeFloat(dataView);
result.w = DecodeFloat(dataView);
return result;
}
function DecodeLong(dataView) {
const result = dataView.getBigInt64(dataView.pointer, true);
dataView.pointer += 8;
return result;
}
function DecodeInt(dataView) {
const result = dataView.getInt32(dataView.pointer, true);
dataView.pointer += 4;
return result;
}
function DecodeUint8(dataView) {
const result = dataView.getUint8(dataView.pointer, true);
dataView.pointer++;
return result;
}
function DecodeString(dataView) {
const length = dataView.getInt32(dataView.pointer, true);
if (length < 0 || length > 300) {
dataView.pointer += 1;
return DecodeString(dataView);
}
var enc = new TextDecoder('utf-8');
const string = enc.decode(new Int8Array(dataView.buffer.slice(dataView.pointer + 4, length + dataView.pointer + 4)));
dataView.pointer += length + 4;
return string;
}
function DecodeName(dataView) {
const length = dataView.getInt32(dataView.pointer, true);
var enc = new TextDecoder('utf-8');
let lengthOffset = 0;
if (length > 0) {
while (dataView.getInt32(length + dataView.pointer + 4 + lengthOffset, true) != 6 &&
dataView.getInt32(length + dataView.pointer + 4 + lengthOffset, true) != 5 &&
dataView.getInt32(length + dataView.pointer + 4 + lengthOffset, true) != 8) {
lengthOffset++;
}
}
const string = enc.decode(new Int8Array(dataView.buffer.slice(dataView.pointer + 4, length + dataView.pointer + 4 + lengthOffset)));
dataView.pointer += length + 4 + lengthOffset;
return string;
}
function DecodeFloat(dataView) {
const result = dataView.getFloat32(dataView.pointer, true);
dataView.pointer += 4;
return result;
}
function DecodeBool(dataView) {
const result = dataView.getUint8(dataView.pointer, true) != 0;
dataView.pointer++;
return result;
}