UNPKG

dcl-npc-toolkit-ai-version

Version:

A collection of tools for creating Non-Player-Characters (NPCs). These are capable of having conversations with the player, and play different animations. AI usage is added atop of it

278 lines (230 loc) 7.44 kB
/** * Copyright (c) 2018 Endel Dreyer * Copyright (c) 2014 Ion Drive Software Ltd. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE */ import { SWITCH_TO_STRUCTURE } from "../spec"; /** * msgpack implementation highly based on notepack.io * https://github.com/darrachequesne/notepack */ export interface Iterator { offset: number; } function utf8Read(bytes, offset, length) { var string = '', chr = 0; for (var i = offset, end = offset + length; i < end; i++) { var byte = bytes[i]; if ((byte & 0x80) === 0x00) { string += String.fromCharCode(byte); continue; } if ((byte & 0xe0) === 0xc0) { string += String.fromCharCode( ((byte & 0x1f) << 6) | (bytes[++i] & 0x3f) ); continue; } if ((byte & 0xf0) === 0xe0) { string += String.fromCharCode( ((byte & 0x0f) << 12) | ((bytes[++i] & 0x3f) << 6) | ((bytes[++i] & 0x3f) << 0) ); continue; } if ((byte & 0xf8) === 0xf0) { chr = ((byte & 0x07) << 18) | ((bytes[++i] & 0x3f) << 12) | ((bytes[++i] & 0x3f) << 6) | ((bytes[++i] & 0x3f) << 0); if (chr >= 0x010000) { // surrogate pair chr -= 0x010000; string += String.fromCharCode((chr >>> 10) + 0xD800, (chr & 0x3FF) + 0xDC00); } else { string += String.fromCharCode(chr); } continue; } console.error('Invalid byte ' + byte.toString(16)); // (do not throw error to avoid server/client from crashing due to hack attemps) // throw new Error('Invalid byte ' + byte.toString(16)); } return string; } export function int8 (bytes: number[], it: Iterator) { return uint8(bytes, it) << 24 >> 24; }; export function uint8 (bytes: number[], it: Iterator) { return bytes[it.offset++]; }; export function int16 (bytes: number[], it: Iterator) { return uint16(bytes, it) << 16 >> 16; }; export function uint16 (bytes: number[], it: Iterator) { return bytes[it.offset++] | bytes[it.offset++] << 8; }; export function int32 (bytes: number[], it: Iterator) { return bytes[it.offset++] | bytes[it.offset++] << 8 | bytes[it.offset++] << 16 | bytes[it.offset++] << 24; }; export function uint32 (bytes: number[], it: Iterator) { return int32(bytes, it) >>> 0; }; export function float32(bytes: number[], it: Iterator) { return readFloat32(bytes, it); } export function float64(bytes: number[], it: Iterator) { return readFloat64(bytes, it); } export function int64(bytes: number[], it: Iterator) { const low = uint32(bytes, it); const high = int32(bytes, it) * Math.pow(2, 32); return high + low; }; export function uint64(bytes: number[], it: Iterator) { const low = uint32(bytes, it); const high = uint32(bytes, it) * Math.pow(2, 32); return high + low; }; // force little endian to facilitate decoding on multiple implementations const _isLittleEndian = true; // new Uint16Array(new Uint8Array([1, 0]).buffer)[0] === 1; const _int32 = new Int32Array(2); const _float32 = new Float32Array(_int32.buffer); const _float64 = new Float64Array(_int32.buffer); export function readFloat32 (bytes: number[], it: Iterator) { _int32[0] = int32(bytes, it); return _float32[0]; }; export function readFloat64 (bytes: number[], it: Iterator) { _int32[_isLittleEndian ? 0 : 1] = int32(bytes, it); _int32[_isLittleEndian ? 1 : 0] = int32(bytes, it); return _float64[0]; }; export function boolean (bytes: number[], it: Iterator) { return uint8(bytes, it) > 0; }; export function string (bytes, it: Iterator) { const prefix = bytes[it.offset++]; let length: number; if (prefix < 0xc0) { // fixstr length = prefix & 0x1f; } else if (prefix === 0xd9) { length = uint8(bytes, it); } else if (prefix === 0xda) { length = uint16(bytes, it); } else if (prefix === 0xdb) { length = uint32(bytes, it); } const value = utf8Read(bytes, it.offset, length); it.offset += length; return value; } export function stringCheck(bytes, it: Iterator) { const prefix = bytes[it.offset]; return ( // fixstr (prefix < 0xc0 && prefix > 0xa0) || // str 8 prefix === 0xd9 || // str 16 prefix === 0xda || // str 32 prefix === 0xdb ); } export function number (bytes, it: Iterator) { const prefix = bytes[it.offset++]; if (prefix < 0x80) { // positive fixint return prefix; } else if (prefix === 0xca) { // float 32 return readFloat32(bytes, it); } else if (prefix === 0xcb) { // float 64 return readFloat64(bytes, it); } else if (prefix === 0xcc) { // uint 8 return uint8(bytes, it); } else if (prefix === 0xcd) { // uint 16 return uint16(bytes, it); } else if (prefix === 0xce) { // uint 32 return uint32(bytes, it); } else if (prefix === 0xcf) { // uint 64 return uint64(bytes, it); } else if (prefix === 0xd0) { // int 8 return int8(bytes, it); } else if (prefix === 0xd1) { // int 16 return int16(bytes, it); } else if (prefix === 0xd2) { // int 32 return int32(bytes, it); } else if (prefix === 0xd3) { // int 64 return int64(bytes, it); } else if (prefix > 0xdf) { // negative fixint return (0xff - prefix + 1) * -1 } }; export function numberCheck (bytes, it: Iterator) { const prefix = bytes[it.offset]; // positive fixint - 0x00 - 0x7f // float 32 - 0xca // float 64 - 0xcb // uint 8 - 0xcc // uint 16 - 0xcd // uint 32 - 0xce // uint 64 - 0xcf // int 8 - 0xd0 // int 16 - 0xd1 // int 32 - 0xd2 // int 64 - 0xd3 return ( prefix < 0x80 || (prefix >= 0xca && prefix <= 0xd3) ); } export function arrayCheck (bytes, it: Iterator) { return bytes[it.offset] < 0xa0; // const prefix = bytes[it.offset] ; // if (prefix < 0xa0) { // return prefix; // // array // } else if (prefix === 0xdc) { // it.offset += 2; // } else if (0xdd) { // it.offset += 4; // } // return prefix; } export function switchStructureCheck(bytes, it: Iterator) { return ( // previous byte should be `SWITCH_TO_STRUCTURE` bytes[it.offset - 1] === SWITCH_TO_STRUCTURE && // next byte should be a number (bytes[it.offset] < 0x80 || (bytes[it.offset] >= 0xca && bytes[it.offset] <= 0xd3)) ); }