diff --git a/client/.gitignore b/client/.gitignore new file mode 100644 index 0000000..485dee6 --- /dev/null +++ b/client/.gitignore @@ -0,0 +1 @@ +.idea diff --git a/client/flatbuffers.js b/client/flatbuffers.js new file mode 100644 index 0000000..74cd35a --- /dev/null +++ b/client/flatbuffers.js @@ -0,0 +1,1259 @@ +/// @file +/// @addtogroup flatbuffers_javascript_api +/// @{ +/// @cond FLATBUFFERS_INTERNAL + +/** + * @fileoverview + * + * Need to suppress 'global this' error so the Node.js export line doesn't cause + * closure compile to error out. + * @suppress {globalThis} + */ + +/** + * @const + * @namespace + */ +var flatbuffers = {}; + +/** + * @typedef {number} + */ +flatbuffers.Offset; + +/** + * @typedef {{ + * bb: flatbuffers.ByteBuffer, + * bb_pos: number + * }} + */ +flatbuffers.Table; + +/** + * @type {number} + * @const + */ +flatbuffers.SIZEOF_SHORT = 2; + +/** + * @type {number} + * @const + */ +flatbuffers.SIZEOF_INT = 4; + +/** + * @type {number} + * @const + */ +flatbuffers.FILE_IDENTIFIER_LENGTH = 4; + +/** + * @type {number} + * @const + */ +flatbuffers.SIZE_PREFIX_LENGTH = 4; + +/** + * @enum {number} + */ +flatbuffers.Encoding = { + UTF8_BYTES: 1, + UTF16_STRING: 2 +}; + +/** + * @type {Int32Array} + * @const + */ +flatbuffers.int32 = new Int32Array(2); + +/** + * @type {Float32Array} + * @const + */ +flatbuffers.float32 = new Float32Array(flatbuffers.int32.buffer); + +/** + * @type {Float64Array} + * @const + */ +flatbuffers.float64 = new Float64Array(flatbuffers.int32.buffer); + +/** + * @type {boolean} + * @const + */ +flatbuffers.isLittleEndian = new Uint16Array(new Uint8Array([1, 0]).buffer)[0] === 1; + +//////////////////////////////////////////////////////////////////////////////// + +/** + * @constructor + * @param {number} low + * @param {number} high + */ +flatbuffers.Long = function(low, high) { + /** + * @type {number} + * @const + */ + this.low = low | 0; + + /** + * @type {number} + * @const + */ + this.high = high | 0; +}; + +/** + * @param {number} low + * @param {number} high + * @returns {!flatbuffers.Long} + */ +flatbuffers.Long.create = function(low, high) { + // Special-case zero to avoid GC overhead for default values + return low == 0 && high == 0 ? flatbuffers.Long.ZERO : new flatbuffers.Long(low, high); +}; + +/** + * @returns {number} + */ +flatbuffers.Long.prototype.toFloat64 = function() { + return (this.low >>> 0) + this.high * 0x100000000; +}; + +/** + * @param {flatbuffers.Long} other + * @returns {boolean} + */ +flatbuffers.Long.prototype.equals = function(other) { + return this.low == other.low && this.high == other.high; +}; + +/** + * @type {!flatbuffers.Long} + * @const + */ +flatbuffers.Long.ZERO = new flatbuffers.Long(0, 0); + +/// @endcond +//////////////////////////////////////////////////////////////////////////////// +/** + * Create a FlatBufferBuilder. + * + * @constructor + * @param {number=} opt_initial_size + */ +flatbuffers.Builder = function(opt_initial_size) { + if (!opt_initial_size) { + var initial_size = 1024; + } else { + var initial_size = opt_initial_size; + } + + /** + * @type {flatbuffers.ByteBuffer} + * @private + */ + this.bb = flatbuffers.ByteBuffer.allocate(initial_size); + + /** + * Remaining space in the ByteBuffer. + * + * @type {number} + * @private + */ + this.space = initial_size; + + /** + * Minimum alignment encountered so far. + * + * @type {number} + * @private + */ + this.minalign = 1; + + /** + * The vtable for the current table. + * + * @type {Array.} + * @private + */ + this.vtable = null; + + /** + * The amount of fields we're actually using. + * + * @type {number} + * @private + */ + this.vtable_in_use = 0; + + /** + * Whether we are currently serializing a table. + * + * @type {boolean} + * @private + */ + this.isNested = false; + + /** + * Starting offset of the current struct/table. + * + * @type {number} + * @private + */ + this.object_start = 0; + + /** + * List of offsets of all vtables. + * + * @type {Array.} + * @private + */ + this.vtables = []; + + /** + * For the current vector being built. + * + * @type {number} + * @private + */ + this.vector_num_elems = 0; + + /** + * False omits default values from the serialized data + * + * @type {boolean} + * @private + */ + this.force_defaults = false; +}; + +flatbuffers.Builder.prototype.clear = function() { + this.bb.clear(); + this.space = this.bb.capacity(); + this.minalign = 1; + this.vtable = null; + this.vtable_in_use = 0; + this.isNested = false; + this.object_start = 0; + this.vtables = []; + this.vector_num_elems = 0; + this.force_defaults = false; +}; + +/** + * In order to save space, fields that are set to their default value + * don't get serialized into the buffer. Forcing defaults provides a + * way to manually disable this optimization. + * + * @param {boolean} forceDefaults true always serializes default values + */ +flatbuffers.Builder.prototype.forceDefaults = function(forceDefaults) { + this.force_defaults = forceDefaults; +}; + +/** + * Get the ByteBuffer representing the FlatBuffer. Only call this after you've + * called finish(). The actual data starts at the ByteBuffer's current position, + * not necessarily at 0. + * + * @returns {flatbuffers.ByteBuffer} + */ +flatbuffers.Builder.prototype.dataBuffer = function() { + return this.bb; +}; + +/** + * Get the bytes representing the FlatBuffer. Only call this after you've + * called finish(). + * + * @returns {!Uint8Array} + */ +flatbuffers.Builder.prototype.asUint8Array = function() { + return this.bb.bytes().subarray(this.bb.position(), this.bb.position() + this.offset()); +}; + +/// @cond FLATBUFFERS_INTERNAL +/** + * Prepare to write an element of `size` after `additional_bytes` have been + * written, e.g. if you write a string, you need to align such the int length + * field is aligned to 4 bytes, and the string data follows it directly. If all + * you need to do is alignment, `additional_bytes` will be 0. + * + * @param {number} size This is the of the new element to write + * @param {number} additional_bytes The padding size + */ +flatbuffers.Builder.prototype.prep = function(size, additional_bytes) { + // Track the biggest thing we've ever aligned to. + if (size > this.minalign) { + this.minalign = size; + } + + // Find the amount of alignment needed such that `size` is properly + // aligned after `additional_bytes` + var align_size = ((~(this.bb.capacity() - this.space + additional_bytes)) + 1) & (size - 1); + + // Reallocate the buffer if needed. + while (this.space < align_size + size + additional_bytes) { + var old_buf_size = this.bb.capacity(); + this.bb = flatbuffers.Builder.growByteBuffer(this.bb); + this.space += this.bb.capacity() - old_buf_size; + } + + this.pad(align_size); +}; + +/** + * @param {number} byte_size + */ +flatbuffers.Builder.prototype.pad = function(byte_size) { + for (var i = 0; i < byte_size; i++) { + this.bb.writeInt8(--this.space, 0); + } +}; + +/** + * @param {number} value + */ +flatbuffers.Builder.prototype.writeInt8 = function(value) { + this.bb.writeInt8(this.space -= 1, value); +}; + +/** + * @param {number} value + */ +flatbuffers.Builder.prototype.writeInt16 = function(value) { + this.bb.writeInt16(this.space -= 2, value); +}; + +/** + * @param {number} value + */ +flatbuffers.Builder.prototype.writeInt32 = function(value) { + this.bb.writeInt32(this.space -= 4, value); +}; + +/** + * @param {flatbuffers.Long} value + */ +flatbuffers.Builder.prototype.writeInt64 = function(value) { + this.bb.writeInt64(this.space -= 8, value); +}; + +/** + * @param {number} value + */ +flatbuffers.Builder.prototype.writeFloat32 = function(value) { + this.bb.writeFloat32(this.space -= 4, value); +}; + +/** + * @param {number} value + */ +flatbuffers.Builder.prototype.writeFloat64 = function(value) { + this.bb.writeFloat64(this.space -= 8, value); +}; +/// @endcond + +/** + * Add an `int8` to the buffer, properly aligned, and grows the buffer (if necessary). + * @param {number} value The `int8` to add the the buffer. + */ +flatbuffers.Builder.prototype.addInt8 = function(value) { + this.prep(1, 0); + this.writeInt8(value); +}; + +/** + * Add an `int16` to the buffer, properly aligned, and grows the buffer (if necessary). + * @param {number} value The `int16` to add the the buffer. + */ +flatbuffers.Builder.prototype.addInt16 = function(value) { + this.prep(2, 0); + this.writeInt16(value); +}; + +/** + * Add an `int32` to the buffer, properly aligned, and grows the buffer (if necessary). + * @param {number} value The `int32` to add the the buffer. + */ +flatbuffers.Builder.prototype.addInt32 = function(value) { + this.prep(4, 0); + this.writeInt32(value); +}; + +/** + * Add an `int64` to the buffer, properly aligned, and grows the buffer (if necessary). + * @param {flatbuffers.Long} value The `int64` to add the the buffer. + */ +flatbuffers.Builder.prototype.addInt64 = function(value) { + this.prep(8, 0); + this.writeInt64(value); +}; + +/** + * Add a `float32` to the buffer, properly aligned, and grows the buffer (if necessary). + * @param {number} value The `float32` to add the the buffer. + */ +flatbuffers.Builder.prototype.addFloat32 = function(value) { + this.prep(4, 0); + this.writeFloat32(value); +}; + +/** + * Add a `float64` to the buffer, properly aligned, and grows the buffer (if necessary). + * @param {number} value The `float64` to add the the buffer. + */ +flatbuffers.Builder.prototype.addFloat64 = function(value) { + this.prep(8, 0); + this.writeFloat64(value); +}; + +/// @cond FLATBUFFERS_INTERNAL +/** + * @param {number} voffset + * @param {number} value + * @param {number} defaultValue + */ +flatbuffers.Builder.prototype.addFieldInt8 = function(voffset, value, defaultValue) { + if (this.force_defaults || value != defaultValue) { + this.addInt8(value); + this.slot(voffset); + } +}; + +/** + * @param {number} voffset + * @param {number} value + * @param {number} defaultValue + */ +flatbuffers.Builder.prototype.addFieldInt16 = function(voffset, value, defaultValue) { + if (this.force_defaults || value != defaultValue) { + this.addInt16(value); + this.slot(voffset); + } +}; + +/** + * @param {number} voffset + * @param {number} value + * @param {number} defaultValue + */ +flatbuffers.Builder.prototype.addFieldInt32 = function(voffset, value, defaultValue) { + if (this.force_defaults || value != defaultValue) { + this.addInt32(value); + this.slot(voffset); + } +}; + +/** + * @param {number} voffset + * @param {flatbuffers.Long} value + * @param {flatbuffers.Long} defaultValue + */ +flatbuffers.Builder.prototype.addFieldInt64 = function(voffset, value, defaultValue) { + if (this.force_defaults || !value.equals(defaultValue)) { + this.addInt64(value); + this.slot(voffset); + } +}; + +/** + * @param {number} voffset + * @param {number} value + * @param {number} defaultValue + */ +flatbuffers.Builder.prototype.addFieldFloat32 = function(voffset, value, defaultValue) { + if (this.force_defaults || value != defaultValue) { + this.addFloat32(value); + this.slot(voffset); + } +}; + +/** + * @param {number} voffset + * @param {number} value + * @param {number} defaultValue + */ +flatbuffers.Builder.prototype.addFieldFloat64 = function(voffset, value, defaultValue) { + if (this.force_defaults || value != defaultValue) { + this.addFloat64(value); + this.slot(voffset); + } +}; + +/** + * @param {number} voffset + * @param {flatbuffers.Offset} value + * @param {flatbuffers.Offset} defaultValue + */ +flatbuffers.Builder.prototype.addFieldOffset = function(voffset, value, defaultValue) { + if (this.force_defaults || value != defaultValue) { + this.addOffset(value); + this.slot(voffset); + } +}; + +/** + * Structs are stored inline, so nothing additional is being added. `d` is always 0. + * + * @param {number} voffset + * @param {flatbuffers.Offset} value + * @param {flatbuffers.Offset} defaultValue + */ +flatbuffers.Builder.prototype.addFieldStruct = function(voffset, value, defaultValue) { + if (value != defaultValue) { + this.nested(value); + this.slot(voffset); + } +}; + +/** + * Structures are always stored inline, they need to be created right + * where they're used. You'll get this assertion failure if you + * created it elsewhere. + * + * @param {flatbuffers.Offset} obj The offset of the created object + */ +flatbuffers.Builder.prototype.nested = function(obj) { + if (obj != this.offset()) { + throw new Error('FlatBuffers: struct must be serialized inline.'); + } +}; + +/** + * Should not be creating any other object, string or vector + * while an object is being constructed + */ +flatbuffers.Builder.prototype.notNested = function() { + if (this.isNested) { + throw new Error('FlatBuffers: object serialization must not be nested.'); + } +}; + +/** + * Set the current vtable at `voffset` to the current location in the buffer. + * + * @param {number} voffset + */ +flatbuffers.Builder.prototype.slot = function(voffset) { + this.vtable[voffset] = this.offset(); +}; + +/** + * @returns {flatbuffers.Offset} Offset relative to the end of the buffer. + */ +flatbuffers.Builder.prototype.offset = function() { + return this.bb.capacity() - this.space; +}; + +/** + * Doubles the size of the backing ByteBuffer and copies the old data towards + * the end of the new buffer (since we build the buffer backwards). + * + * @param {flatbuffers.ByteBuffer} bb The current buffer with the existing data + * @returns {!flatbuffers.ByteBuffer} A new byte buffer with the old data copied + * to it. The data is located at the end of the buffer. + * + * uint8Array.set() formally takes {Array|ArrayBufferView}, so to pass + * it a uint8Array we need to suppress the type check: + * @suppress {checkTypes} + */ +flatbuffers.Builder.growByteBuffer = function(bb) { + var old_buf_size = bb.capacity(); + + // Ensure we don't grow beyond what fits in an int. + if (old_buf_size & 0xC0000000) { + throw new Error('FlatBuffers: cannot grow buffer beyond 2 gigabytes.'); + } + + var new_buf_size = old_buf_size << 1; + var nbb = flatbuffers.ByteBuffer.allocate(new_buf_size); + nbb.setPosition(new_buf_size - old_buf_size); + nbb.bytes().set(bb.bytes(), new_buf_size - old_buf_size); + return nbb; +}; +/// @endcond + +/** + * Adds on offset, relative to where it will be written. + * + * @param {flatbuffers.Offset} offset The offset to add. + */ +flatbuffers.Builder.prototype.addOffset = function(offset) { + this.prep(flatbuffers.SIZEOF_INT, 0); // Ensure alignment is already done. + this.writeInt32(this.offset() - offset + flatbuffers.SIZEOF_INT); +}; + +/// @cond FLATBUFFERS_INTERNAL +/** + * Start encoding a new object in the buffer. Users will not usually need to + * call this directly. The FlatBuffers compiler will generate helper methods + * that call this method internally. + * + * @param {number} numfields + */ +flatbuffers.Builder.prototype.startObject = function(numfields) { + this.notNested(); + if (this.vtable == null) { + this.vtable = []; + } + this.vtable_in_use = numfields; + for (var i = 0; i < numfields; i++) { + this.vtable[i] = 0; // This will push additional elements as needed + } + this.isNested = true; + this.object_start = this.offset(); +}; + +/** + * Finish off writing the object that is under construction. + * + * @returns {flatbuffers.Offset} The offset to the object inside `dataBuffer` + */ +flatbuffers.Builder.prototype.endObject = function() { + if (this.vtable == null || !this.isNested) { + throw new Error('FlatBuffers: endObject called without startObject'); + } + + this.addInt32(0); + var vtableloc = this.offset(); + + // Trim trailing zeroes. + var i = this.vtable_in_use - 1; + for (; i >= 0 && this.vtable[i] == 0; i--) {} + var trimmed_size = i + 1; + + // Write out the current vtable. + for (; i >= 0; i--) { + // Offset relative to the start of the table. + this.addInt16(this.vtable[i] != 0 ? vtableloc - this.vtable[i] : 0); + } + + var standard_fields = 2; // The fields below: + this.addInt16(vtableloc - this.object_start); + var len = (trimmed_size + standard_fields) * flatbuffers.SIZEOF_SHORT; + this.addInt16(len); + + // Search for an existing vtable that matches the current one. + var existing_vtable = 0; + var vt1 = this.space; +outer_loop: + for (i = 0; i < this.vtables.length; i++) { + var vt2 = this.bb.capacity() - this.vtables[i]; + if (len == this.bb.readInt16(vt2)) { + for (var j = flatbuffers.SIZEOF_SHORT; j < len; j += flatbuffers.SIZEOF_SHORT) { + if (this.bb.readInt16(vt1 + j) != this.bb.readInt16(vt2 + j)) { + continue outer_loop; + } + } + existing_vtable = this.vtables[i]; + break; + } + } + + if (existing_vtable) { + // Found a match: + // Remove the current vtable. + this.space = this.bb.capacity() - vtableloc; + + // Point table to existing vtable. + this.bb.writeInt32(this.space, existing_vtable - vtableloc); + } else { + // No match: + // Add the location of the current vtable to the list of vtables. + this.vtables.push(this.offset()); + + // Point table to current vtable. + this.bb.writeInt32(this.bb.capacity() - vtableloc, this.offset() - vtableloc); + } + + this.isNested = false; + return vtableloc; +}; +/// @endcond + +/** + * Finalize a buffer, poiting to the given `root_table`. + * + * @param {flatbuffers.Offset} root_table + * @param {string=} opt_file_identifier + * @param {boolean=} opt_size_prefix + */ +flatbuffers.Builder.prototype.finish = function(root_table, opt_file_identifier, opt_size_prefix) { + var size_prefix = opt_size_prefix ? flatbuffers.SIZE_PREFIX_LENGTH : 0; + if (opt_file_identifier) { + var file_identifier = opt_file_identifier; + this.prep(this.minalign, flatbuffers.SIZEOF_INT + + flatbuffers.FILE_IDENTIFIER_LENGTH + size_prefix); + if (file_identifier.length != flatbuffers.FILE_IDENTIFIER_LENGTH) { + throw new Error('FlatBuffers: file identifier must be length ' + + flatbuffers.FILE_IDENTIFIER_LENGTH); + } + for (var i = flatbuffers.FILE_IDENTIFIER_LENGTH - 1; i >= 0; i--) { + this.writeInt8(file_identifier.charCodeAt(i)); + } + } + this.prep(this.minalign, flatbuffers.SIZEOF_INT + size_prefix); + this.addOffset(root_table); + if (size_prefix) { + this.addInt32(this.bb.capacity() - this.space); + } + this.bb.setPosition(this.space); +}; + +/** + * Finalize a size prefixed buffer, pointing to the given `root_table`. + * + * @param {flatbuffers.Offset} root_table + * @param {string=} opt_file_identifier + */ +flatbuffers.Builder.prototype.finishSizePrefixed = function (root_table, opt_file_identifier) { + this.finish(root_table, opt_file_identifier, true); +}; + +/// @cond FLATBUFFERS_INTERNAL +/** + * This checks a required field has been set in a given table that has + * just been constructed. + * + * @param {flatbuffers.Offset} table + * @param {number} field + */ +flatbuffers.Builder.prototype.requiredField = function(table, field) { + var table_start = this.bb.capacity() - table; + var vtable_start = table_start - this.bb.readInt32(table_start); + var ok = this.bb.readInt16(vtable_start + field) != 0; + + // If this fails, the caller will show what field needs to be set. + if (!ok) { + throw new Error('FlatBuffers: field ' + field + ' must be set'); + } +}; + +/** + * Start a new array/vector of objects. Users usually will not call + * this directly. The FlatBuffers compiler will create a start/end + * method for vector types in generated code. + * + * @param {number} elem_size The size of each element in the array + * @param {number} num_elems The number of elements in the array + * @param {number} alignment The alignment of the array + */ +flatbuffers.Builder.prototype.startVector = function(elem_size, num_elems, alignment) { + this.notNested(); + this.vector_num_elems = num_elems; + this.prep(flatbuffers.SIZEOF_INT, elem_size * num_elems); + this.prep(alignment, elem_size * num_elems); // Just in case alignment > int. +}; + +/** + * Finish off the creation of an array and all its elements. The array must be + * created with `startVector`. + * + * @returns {flatbuffers.Offset} The offset at which the newly created array + * starts. + */ +flatbuffers.Builder.prototype.endVector = function() { + this.writeInt32(this.vector_num_elems); + return this.offset(); +}; +/// @endcond + +/** + * Encode the string `s` in the buffer using UTF-8. If a Uint8Array is passed + * instead of a string, it is assumed to contain valid UTF-8 encoded data. + * + * @param {string|Uint8Array} s The string to encode + * @return {flatbuffers.Offset} The offset in the buffer where the encoded string starts + */ +flatbuffers.Builder.prototype.createString = function(s) { + if (s instanceof Uint8Array) { + var utf8 = s; + } else { + var utf8 = []; + var i = 0; + + while (i < s.length) { + var codePoint; + + // Decode UTF-16 + var a = s.charCodeAt(i++); + if (a < 0xD800 || a >= 0xDC00) { + codePoint = a; + } else { + var b = s.charCodeAt(i++); + codePoint = (a << 10) + b + (0x10000 - (0xD800 << 10) - 0xDC00); + } + + // Encode UTF-8 + if (codePoint < 0x80) { + utf8.push(codePoint); + } else { + if (codePoint < 0x800) { + utf8.push(((codePoint >> 6) & 0x1F) | 0xC0); + } else { + if (codePoint < 0x10000) { + utf8.push(((codePoint >> 12) & 0x0F) | 0xE0); + } else { + utf8.push( + ((codePoint >> 18) & 0x07) | 0xF0, + ((codePoint >> 12) & 0x3F) | 0x80); + } + utf8.push(((codePoint >> 6) & 0x3F) | 0x80); + } + utf8.push((codePoint & 0x3F) | 0x80); + } + } + } + + this.addInt8(0); + this.startVector(1, utf8.length, 1); + this.bb.setPosition(this.space -= utf8.length); + for (var i = 0, offset = this.space, bytes = this.bb.bytes(); i < utf8.length; i++) { + bytes[offset++] = utf8[i]; + } + return this.endVector(); +}; + +/** + * A helper function to avoid generated code depending on this file directly. + * + * @param {number} low + * @param {number} high + * @returns {!flatbuffers.Long} + */ +flatbuffers.Builder.prototype.createLong = function(low, high) { + return flatbuffers.Long.create(low, high); +}; +//////////////////////////////////////////////////////////////////////////////// +/// @cond FLATBUFFERS_INTERNAL +/** + * Create a new ByteBuffer with a given array of bytes (`Uint8Array`). + * + * @constructor + * @param {Uint8Array} bytes + */ +flatbuffers.ByteBuffer = function(bytes) { + /** + * @type {Uint8Array} + * @private + */ + this.bytes_ = bytes; + + /** + * @type {number} + * @private + */ + this.position_ = 0; +}; + +/** + * Create and allocate a new ByteBuffer with a given size. + * + * @param {number} byte_size + * @returns {!flatbuffers.ByteBuffer} + */ +flatbuffers.ByteBuffer.allocate = function(byte_size) { + return new flatbuffers.ByteBuffer(new Uint8Array(byte_size)); +}; + +flatbuffers.ByteBuffer.prototype.clear = function() { + this.position_ = 0; +}; + +/** + * Get the underlying `Uint8Array`. + * + * @returns {Uint8Array} + */ +flatbuffers.ByteBuffer.prototype.bytes = function() { + return this.bytes_; +}; + +/** + * Get the buffer's position. + * + * @returns {number} + */ +flatbuffers.ByteBuffer.prototype.position = function() { + return this.position_; +}; + +/** + * Set the buffer's position. + * + * @param {number} position + */ +flatbuffers.ByteBuffer.prototype.setPosition = function(position) { + this.position_ = position; +}; + +/** + * Get the buffer's capacity. + * + * @returns {number} + */ +flatbuffers.ByteBuffer.prototype.capacity = function() { + return this.bytes_.length; +}; + +/** + * @param {number} offset + * @returns {number} + */ +flatbuffers.ByteBuffer.prototype.readInt8 = function(offset) { + return this.readUint8(offset) << 24 >> 24; +}; + +/** + * @param {number} offset + * @returns {number} + */ +flatbuffers.ByteBuffer.prototype.readUint8 = function(offset) { + return this.bytes_[offset]; +}; + +/** + * @param {number} offset + * @returns {number} + */ +flatbuffers.ByteBuffer.prototype.readInt16 = function(offset) { + return this.readUint16(offset) << 16 >> 16; +}; + +/** + * @param {number} offset + * @returns {number} + */ +flatbuffers.ByteBuffer.prototype.readUint16 = function(offset) { + return this.bytes_[offset] | this.bytes_[offset + 1] << 8; +}; + +/** + * @param {number} offset + * @returns {number} + */ +flatbuffers.ByteBuffer.prototype.readInt32 = function(offset) { + return this.bytes_[offset] | this.bytes_[offset + 1] << 8 | this.bytes_[offset + 2] << 16 | this.bytes_[offset + 3] << 24; +}; + +/** + * @param {number} offset + * @returns {number} + */ +flatbuffers.ByteBuffer.prototype.readUint32 = function(offset) { + return this.readInt32(offset) >>> 0; +}; + +/** + * @param {number} offset + * @returns {!flatbuffers.Long} + */ +flatbuffers.ByteBuffer.prototype.readInt64 = function(offset) { + return new flatbuffers.Long(this.readInt32(offset), this.readInt32(offset + 4)); +}; + +/** + * @param {number} offset + * @returns {!flatbuffers.Long} + */ +flatbuffers.ByteBuffer.prototype.readUint64 = function(offset) { + return new flatbuffers.Long(this.readUint32(offset), this.readUint32(offset + 4)); +}; + +/** + * @param {number} offset + * @returns {number} + */ +flatbuffers.ByteBuffer.prototype.readFloat32 = function(offset) { + flatbuffers.int32[0] = this.readInt32(offset); + return flatbuffers.float32[0]; +}; + +/** + * @param {number} offset + * @returns {number} + */ +flatbuffers.ByteBuffer.prototype.readFloat64 = function(offset) { + flatbuffers.int32[flatbuffers.isLittleEndian ? 0 : 1] = this.readInt32(offset); + flatbuffers.int32[flatbuffers.isLittleEndian ? 1 : 0] = this.readInt32(offset + 4); + return flatbuffers.float64[0]; +}; + +/** + * @param {number} offset + * @param {number|boolean} value + */ +flatbuffers.ByteBuffer.prototype.writeInt8 = function(offset, value) { + this.bytes_[offset] = /** @type {number} */(value); +}; + +/** + * @param {number} offset + * @param {number} value + */ +flatbuffers.ByteBuffer.prototype.writeUint8 = function(offset, value) { + this.bytes_[offset] = value; +}; + +/** + * @param {number} offset + * @param {number} value + */ +flatbuffers.ByteBuffer.prototype.writeInt16 = function(offset, value) { + this.bytes_[offset] = value; + this.bytes_[offset + 1] = value >> 8; +}; + +/** + * @param {number} offset + * @param {number} value + */ +flatbuffers.ByteBuffer.prototype.writeUint16 = function(offset, value) { + this.bytes_[offset] = value; + this.bytes_[offset + 1] = value >> 8; +}; + +/** + * @param {number} offset + * @param {number} value + */ +flatbuffers.ByteBuffer.prototype.writeInt32 = function(offset, value) { + this.bytes_[offset] = value; + this.bytes_[offset + 1] = value >> 8; + this.bytes_[offset + 2] = value >> 16; + this.bytes_[offset + 3] = value >> 24; +}; + +/** + * @param {number} offset + * @param {number} value + */ +flatbuffers.ByteBuffer.prototype.writeUint32 = function(offset, value) { + this.bytes_[offset] = value; + this.bytes_[offset + 1] = value >> 8; + this.bytes_[offset + 2] = value >> 16; + this.bytes_[offset + 3] = value >> 24; +}; + +/** + * @param {number} offset + * @param {flatbuffers.Long} value + */ +flatbuffers.ByteBuffer.prototype.writeInt64 = function(offset, value) { + this.writeInt32(offset, value.low); + this.writeInt32(offset + 4, value.high); +}; + +/** + * @param {number} offset + * @param {flatbuffers.Long} value + */ +flatbuffers.ByteBuffer.prototype.writeUint64 = function(offset, value) { + this.writeUint32(offset, value.low); + this.writeUint32(offset + 4, value.high); +}; + +/** + * @param {number} offset + * @param {number} value + */ +flatbuffers.ByteBuffer.prototype.writeFloat32 = function(offset, value) { + flatbuffers.float32[0] = value; + this.writeInt32(offset, flatbuffers.int32[0]); +}; + +/** + * @param {number} offset + * @param {number} value + */ +flatbuffers.ByteBuffer.prototype.writeFloat64 = function(offset, value) { + flatbuffers.float64[0] = value; + this.writeInt32(offset, flatbuffers.int32[flatbuffers.isLittleEndian ? 0 : 1]); + this.writeInt32(offset + 4, flatbuffers.int32[flatbuffers.isLittleEndian ? 1 : 0]); +}; + +/** + * Return the file identifier. Behavior is undefined for FlatBuffers whose + * schema does not include a file_identifier (likely points at padding or the + * start of a the root vtable). + * @returns {string} + */ +flatbuffers.ByteBuffer.prototype.getBufferIdentifier = function() { + if (this.bytes_.length < this.position_ + flatbuffers.SIZEOF_INT + + flatbuffers.FILE_IDENTIFIER_LENGTH) { + throw new Error( + 'FlatBuffers: ByteBuffer is too short to contain an identifier.'); + } + var result = ""; + for (var i = 0; i < flatbuffers.FILE_IDENTIFIER_LENGTH; i++) { + result += String.fromCharCode( + this.readInt8(this.position_ + flatbuffers.SIZEOF_INT + i)); + } + return result; +}; + +/** + * Look up a field in the vtable, return an offset into the object, or 0 if the + * field is not present. + * + * @param {number} bb_pos + * @param {number} vtable_offset + * @returns {number} + */ +flatbuffers.ByteBuffer.prototype.__offset = function(bb_pos, vtable_offset) { + var vtable = bb_pos - this.readInt32(bb_pos); + return vtable_offset < this.readInt16(vtable) ? this.readInt16(vtable + vtable_offset) : 0; +}; + +/** + * Initialize any Table-derived type to point to the union at the given offset. + * + * @param {flatbuffers.Table} t + * @param {number} offset + * @returns {flatbuffers.Table} + */ +flatbuffers.ByteBuffer.prototype.__union = function(t, offset) { + t.bb_pos = offset + this.readInt32(offset); + t.bb = this; + return t; +}; + +/** + * Create a JavaScript string from UTF-8 data stored inside the FlatBuffer. + * This allocates a new string and converts to wide chars upon each access. + * + * To avoid the conversion to UTF-16, pass flatbuffers.Encoding.UTF8_BYTES as + * the "optionalEncoding" argument. This is useful for avoiding conversion to + * and from UTF-16 when the data will just be packaged back up in another + * FlatBuffer later on. + * + * @param {number} offset + * @param {flatbuffers.Encoding=} opt_encoding Defaults to UTF16_STRING + * @returns {string|!Uint8Array} + */ +flatbuffers.ByteBuffer.prototype.__string = function(offset, opt_encoding) { + offset += this.readInt32(offset); + + var length = this.readInt32(offset); + var result = ''; + var i = 0; + + offset += flatbuffers.SIZEOF_INT; + + if (opt_encoding === flatbuffers.Encoding.UTF8_BYTES) { + return this.bytes_.subarray(offset, offset + length); + } + + while (i < length) { + var codePoint; + + // Decode UTF-8 + var a = this.readUint8(offset + i++); + if (a < 0xC0) { + codePoint = a; + } else { + var b = this.readUint8(offset + i++); + if (a < 0xE0) { + codePoint = + ((a & 0x1F) << 6) | + (b & 0x3F); + } else { + var c = this.readUint8(offset + i++); + if (a < 0xF0) { + codePoint = + ((a & 0x0F) << 12) | + ((b & 0x3F) << 6) | + (c & 0x3F); + } else { + var d = this.readUint8(offset + i++); + codePoint = + ((a & 0x07) << 18) | + ((b & 0x3F) << 12) | + ((c & 0x3F) << 6) | + (d & 0x3F); + } + } + } + + // Encode UTF-16 + if (codePoint < 0x10000) { + result += String.fromCharCode(codePoint); + } else { + codePoint -= 0x10000; + result += String.fromCharCode( + (codePoint >> 10) + 0xD800, + (codePoint & ((1 << 10) - 1)) + 0xDC00); + } + } + + return result; +}; + +/** + * Retrieve the relative offset stored at "offset" + * @param {number} offset + * @returns {number} + */ +flatbuffers.ByteBuffer.prototype.__indirect = function(offset) { + return offset + this.readInt32(offset); +}; + +/** + * Get the start of data of a vector whose offset is stored at "offset" in this object. + * + * @param {number} offset + * @returns {number} + */ +flatbuffers.ByteBuffer.prototype.__vector = function(offset) { + return offset + this.readInt32(offset) + flatbuffers.SIZEOF_INT; // data starts after the length +}; + +/** + * Get the length of a vector whose offset is stored at "offset" in this object. + * + * @param {number} offset + * @returns {number} + */ +flatbuffers.ByteBuffer.prototype.__vector_len = function(offset) { + return this.readInt32(offset + this.readInt32(offset)); +}; + +/** + * @param {string} ident + * @returns {boolean} + */ +flatbuffers.ByteBuffer.prototype.__has_identifier = function(ident) { + if (ident.length != flatbuffers.FILE_IDENTIFIER_LENGTH) { + throw new Error('FlatBuffers: file identifier must be length ' + + flatbuffers.FILE_IDENTIFIER_LENGTH); + } + for (var i = 0; i < flatbuffers.FILE_IDENTIFIER_LENGTH; i++) { + if (ident.charCodeAt(i) != this.readInt8(this.position_ + flatbuffers.SIZEOF_INT + i)) { + return false; + } + } + return true; +}; + +/** + * A helper function to avoid generated code depending on this file directly. + * + * @param {number} low + * @param {number} high + * @returns {!flatbuffers.Long} + */ +flatbuffers.ByteBuffer.prototype.createLong = function(low, high) { + return flatbuffers.Long.create(low, high); +}; + +// Exports for Node.js and RequireJS +this.flatbuffers = flatbuffers; + +/// @endcond +/// @} diff --git a/client/index.html b/client/index.html new file mode 100644 index 0000000..e080a80 --- /dev/null +++ b/client/index.html @@ -0,0 +1,13 @@ + + + + + Title + + + + + + + + diff --git a/client/sample_generated.js b/client/sample_generated.js new file mode 100644 index 0000000..3ac7c81 --- /dev/null +++ b/client/sample_generated.js @@ -0,0 +1,575 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/** + * @const + * @namespace + */ +var MyGame = MyGame || {}; + +/** + * @const + * @namespace + */ +MyGame.Sample = MyGame.Sample || {}; + +/** + * @enum {number} + */ +MyGame.Sample.Color = { + Red: 0, + Green: 1, + Blue: 2 +}; + +/** + * @enum {string} + */ +MyGame.Sample.ColorName = { + '0': 'Red', + '1': 'Green', + '2': 'Blue' +}; + +/** + * @enum {number} + */ +MyGame.Sample.Equipment = { + NONE: 0, + Weapon: 1 +}; + +/** + * @enum {string} + */ +MyGame.Sample.EquipmentName = { + '0': 'NONE', + '1': 'Weapon' +}; + +/** + * @constructor + */ +MyGame.Sample.Vec3 = function() { + /** + * @type {flatbuffers.ByteBuffer} + */ + this.bb = null; + + /** + * @type {number} + */ + this.bb_pos = 0; +}; + +/** + * @param {number} i + * @param {flatbuffers.ByteBuffer} bb + * @returns {MyGame.Sample.Vec3} + */ +MyGame.Sample.Vec3.prototype.__init = function(i, bb) { + this.bb_pos = i; + this.bb = bb; + return this; +}; + +/** + * @returns {number} + */ +MyGame.Sample.Vec3.prototype.x = function() { + return this.bb.readFloat32(this.bb_pos); +}; + +/** + * @returns {number} + */ +MyGame.Sample.Vec3.prototype.y = function() { + return this.bb.readFloat32(this.bb_pos + 4); +}; + +/** + * @returns {number} + */ +MyGame.Sample.Vec3.prototype.z = function() { + return this.bb.readFloat32(this.bb_pos + 8); +}; + +/** + * @param {flatbuffers.Builder} builder + * @param {number} x + * @param {number} y + * @param {number} z + * @returns {flatbuffers.Offset} + */ +MyGame.Sample.Vec3.createVec3 = function(builder, x, y, z) { + builder.prep(4, 12); + builder.writeFloat32(z); + builder.writeFloat32(y); + builder.writeFloat32(x); + return builder.offset(); +}; + +/** + * @constructor + */ +MyGame.Sample.Monster = function() { + /** + * @type {flatbuffers.ByteBuffer} + */ + this.bb = null; + + /** + * @type {number} + */ + this.bb_pos = 0; +}; + +/** + * @param {number} i + * @param {flatbuffers.ByteBuffer} bb + * @returns {MyGame.Sample.Monster} + */ +MyGame.Sample.Monster.prototype.__init = function(i, bb) { + this.bb_pos = i; + this.bb = bb; + return this; +}; + +/** + * @param {flatbuffers.ByteBuffer} bb + * @param {MyGame.Sample.Monster=} obj + * @returns {MyGame.Sample.Monster} + */ +MyGame.Sample.Monster.getRootAsMonster = function(bb, obj) { + return (obj || new MyGame.Sample.Monster).__init(bb.readInt32(bb.position()) + bb.position(), bb); +}; + +/** + * @param {flatbuffers.ByteBuffer} bb + * @param {MyGame.Sample.Monster=} obj + * @returns {MyGame.Sample.Monster} + */ +MyGame.Sample.Monster.getSizePrefixedRootAsMonster = function(bb, obj) { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new MyGame.Sample.Monster).__init(bb.readInt32(bb.position()) + bb.position(), bb); +}; + +/** + * @param {MyGame.Sample.Vec3=} obj + * @returns {MyGame.Sample.Vec3|null} + */ +MyGame.Sample.Monster.prototype.pos = function(obj) { + var offset = this.bb.__offset(this.bb_pos, 4); + return offset ? (obj || new MyGame.Sample.Vec3).__init(this.bb_pos + offset, this.bb) : null; +}; + +/** + * @returns {number} + */ +MyGame.Sample.Monster.prototype.mana = function() { + var offset = this.bb.__offset(this.bb_pos, 6); + return offset ? this.bb.readInt16(this.bb_pos + offset) : 150; +}; + +/** + * @returns {number} + */ +MyGame.Sample.Monster.prototype.hp = function() { + var offset = this.bb.__offset(this.bb_pos, 8); + return offset ? this.bb.readInt16(this.bb_pos + offset) : 100; +}; + +/** + * @param {flatbuffers.Encoding=} optionalEncoding + * @returns {string|Uint8Array|null} + */ +MyGame.Sample.Monster.prototype.name = function(optionalEncoding) { + var offset = this.bb.__offset(this.bb_pos, 10); + return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null; +}; + +/** + * @param {number} index + * @returns {number} + */ +MyGame.Sample.Monster.prototype.inventory = function(index) { + var offset = this.bb.__offset(this.bb_pos, 14); + return offset ? this.bb.readUint8(this.bb.__vector(this.bb_pos + offset) + index) : 0; +}; + +/** + * @returns {number} + */ +MyGame.Sample.Monster.prototype.inventoryLength = function() { + var offset = this.bb.__offset(this.bb_pos, 14); + return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; +}; + +/** + * @returns {Uint8Array} + */ +MyGame.Sample.Monster.prototype.inventoryArray = function() { + var offset = this.bb.__offset(this.bb_pos, 14); + return offset ? new Uint8Array(this.bb.bytes().buffer, this.bb.bytes().byteOffset + this.bb.__vector(this.bb_pos + offset), this.bb.__vector_len(this.bb_pos + offset)) : null; +}; + +/** + * @returns {MyGame.Sample.Color} + */ +MyGame.Sample.Monster.prototype.color = function() { + var offset = this.bb.__offset(this.bb_pos, 16); + return offset ? /** @type {MyGame.Sample.Color} */ (this.bb.readInt8(this.bb_pos + offset)) : MyGame.Sample.Color.Blue; +}; + +/** + * @param {number} index + * @param {MyGame.Sample.Weapon=} obj + * @returns {MyGame.Sample.Weapon} + */ +MyGame.Sample.Monster.prototype.weapons = function(index, obj) { + var offset = this.bb.__offset(this.bb_pos, 18); + return offset ? (obj || new MyGame.Sample.Weapon).__init(this.bb.__indirect(this.bb.__vector(this.bb_pos + offset) + index * 4), this.bb) : null; +}; + +/** + * @returns {number} + */ +MyGame.Sample.Monster.prototype.weaponsLength = function() { + var offset = this.bb.__offset(this.bb_pos, 18); + return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; +}; + +/** + * @returns {MyGame.Sample.Equipment} + */ +MyGame.Sample.Monster.prototype.equippedType = function() { + var offset = this.bb.__offset(this.bb_pos, 20); + return offset ? /** @type {MyGame.Sample.Equipment} */ (this.bb.readUint8(this.bb_pos + offset)) : MyGame.Sample.Equipment.NONE; +}; + +/** + * @param {flatbuffers.Table} obj + * @returns {?flatbuffers.Table} + */ +MyGame.Sample.Monster.prototype.equipped = function(obj) { + var offset = this.bb.__offset(this.bb_pos, 22); + return offset ? this.bb.__union(obj, this.bb_pos + offset) : null; +}; + +/** + * @param {number} index + * @param {MyGame.Sample.Vec3=} obj + * @returns {MyGame.Sample.Vec3} + */ +MyGame.Sample.Monster.prototype.path = function(index, obj) { + var offset = this.bb.__offset(this.bb_pos, 24); + return offset ? (obj || new MyGame.Sample.Vec3).__init(this.bb.__vector(this.bb_pos + offset) + index * 12, this.bb) : null; +}; + +/** + * @returns {number} + */ +MyGame.Sample.Monster.prototype.pathLength = function() { + var offset = this.bb.__offset(this.bb_pos, 24); + return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; +}; + +/** + * @param {flatbuffers.Builder} builder + */ +MyGame.Sample.Monster.startMonster = function(builder) { + builder.startObject(11); +}; + +/** + * @param {flatbuffers.Builder} builder + * @param {flatbuffers.Offset} posOffset + */ +MyGame.Sample.Monster.addPos = function(builder, posOffset) { + builder.addFieldStruct(0, posOffset, 0); +}; + +/** + * @param {flatbuffers.Builder} builder + * @param {number} mana + */ +MyGame.Sample.Monster.addMana = function(builder, mana) { + builder.addFieldInt16(1, mana, 150); +}; + +/** + * @param {flatbuffers.Builder} builder + * @param {number} hp + */ +MyGame.Sample.Monster.addHp = function(builder, hp) { + builder.addFieldInt16(2, hp, 100); +}; + +/** + * @param {flatbuffers.Builder} builder + * @param {flatbuffers.Offset} nameOffset + */ +MyGame.Sample.Monster.addName = function(builder, nameOffset) { + builder.addFieldOffset(3, nameOffset, 0); +}; + +/** + * @param {flatbuffers.Builder} builder + * @param {flatbuffers.Offset} inventoryOffset + */ +MyGame.Sample.Monster.addInventory = function(builder, inventoryOffset) { + builder.addFieldOffset(5, inventoryOffset, 0); +}; + +/** + * @param {flatbuffers.Builder} builder + * @param {Array.} data + * @returns {flatbuffers.Offset} + */ +MyGame.Sample.Monster.createInventoryVector = function(builder, data) { + builder.startVector(1, data.length, 1); + for (var i = data.length - 1; i >= 0; i--) { + builder.addInt8(data[i]); + } + return builder.endVector(); +}; + +/** + * @param {flatbuffers.Builder} builder + * @param {number} numElems + */ +MyGame.Sample.Monster.startInventoryVector = function(builder, numElems) { + builder.startVector(1, numElems, 1); +}; + +/** + * @param {flatbuffers.Builder} builder + * @param {MyGame.Sample.Color} color + */ +MyGame.Sample.Monster.addColor = function(builder, color) { + builder.addFieldInt8(6, color, MyGame.Sample.Color.Blue); +}; + +/** + * @param {flatbuffers.Builder} builder + * @param {flatbuffers.Offset} weaponsOffset + */ +MyGame.Sample.Monster.addWeapons = function(builder, weaponsOffset) { + builder.addFieldOffset(7, weaponsOffset, 0); +}; + +/** + * @param {flatbuffers.Builder} builder + * @param {Array.} data + * @returns {flatbuffers.Offset} + */ +MyGame.Sample.Monster.createWeaponsVector = function(builder, data) { + builder.startVector(4, data.length, 4); + for (var i = data.length - 1; i >= 0; i--) { + builder.addOffset(data[i]); + } + return builder.endVector(); +}; + +/** + * @param {flatbuffers.Builder} builder + * @param {number} numElems + */ +MyGame.Sample.Monster.startWeaponsVector = function(builder, numElems) { + builder.startVector(4, numElems, 4); +}; + +/** + * @param {flatbuffers.Builder} builder + * @param {MyGame.Sample.Equipment} equippedType + */ +MyGame.Sample.Monster.addEquippedType = function(builder, equippedType) { + builder.addFieldInt8(8, equippedType, MyGame.Sample.Equipment.NONE); +}; + +/** + * @param {flatbuffers.Builder} builder + * @param {flatbuffers.Offset} equippedOffset + */ +MyGame.Sample.Monster.addEquipped = function(builder, equippedOffset) { + builder.addFieldOffset(9, equippedOffset, 0); +}; + +/** + * @param {flatbuffers.Builder} builder + * @param {flatbuffers.Offset} pathOffset + */ +MyGame.Sample.Monster.addPath = function(builder, pathOffset) { + builder.addFieldOffset(10, pathOffset, 0); +}; + +/** + * @param {flatbuffers.Builder} builder + * @param {number} numElems + */ +MyGame.Sample.Monster.startPathVector = function(builder, numElems) { + builder.startVector(12, numElems, 4); +}; + +/** + * @param {flatbuffers.Builder} builder + * @returns {flatbuffers.Offset} + */ +MyGame.Sample.Monster.endMonster = function(builder) { + var offset = builder.endObject(); + return offset; +}; + +/** + * @param {flatbuffers.Builder} builder + * @param {flatbuffers.Offset} offset + */ +MyGame.Sample.Monster.finishMonsterBuffer = function(builder, offset) { + builder.finish(offset); +}; + +/** + * @param {flatbuffers.Builder} builder + * @param {flatbuffers.Offset} offset + */ +MyGame.Sample.Monster.finishSizePrefixedMonsterBuffer = function(builder, offset) { + builder.finish(offset, undefined, true); +}; + +/** + * @param {flatbuffers.Builder} builder + * @param {flatbuffers.Offset} posOffset + * @param {number} mana + * @param {number} hp + * @param {flatbuffers.Offset} nameOffset + * @param {flatbuffers.Offset} inventoryOffset + * @param {MyGame.Sample.Color} color + * @param {flatbuffers.Offset} weaponsOffset + * @param {MyGame.Sample.Equipment} equippedType + * @param {flatbuffers.Offset} equippedOffset + * @param {flatbuffers.Offset} pathOffset + * @returns {flatbuffers.Offset} + */ +MyGame.Sample.Monster.createMonster = function(builder, posOffset, mana, hp, nameOffset, inventoryOffset, color, weaponsOffset, equippedType, equippedOffset, pathOffset) { + MyGame.Sample.Monster.startMonster(builder); + MyGame.Sample.Monster.addPos(builder, posOffset); + MyGame.Sample.Monster.addMana(builder, mana); + MyGame.Sample.Monster.addHp(builder, hp); + MyGame.Sample.Monster.addName(builder, nameOffset); + MyGame.Sample.Monster.addInventory(builder, inventoryOffset); + MyGame.Sample.Monster.addColor(builder, color); + MyGame.Sample.Monster.addWeapons(builder, weaponsOffset); + MyGame.Sample.Monster.addEquippedType(builder, equippedType); + MyGame.Sample.Monster.addEquipped(builder, equippedOffset); + MyGame.Sample.Monster.addPath(builder, pathOffset); + return MyGame.Sample.Monster.endMonster(builder); +} + +/** + * @constructor + */ +MyGame.Sample.Weapon = function() { + /** + * @type {flatbuffers.ByteBuffer} + */ + this.bb = null; + + /** + * @type {number} + */ + this.bb_pos = 0; +}; + +/** + * @param {number} i + * @param {flatbuffers.ByteBuffer} bb + * @returns {MyGame.Sample.Weapon} + */ +MyGame.Sample.Weapon.prototype.__init = function(i, bb) { + this.bb_pos = i; + this.bb = bb; + return this; +}; + +/** + * @param {flatbuffers.ByteBuffer} bb + * @param {MyGame.Sample.Weapon=} obj + * @returns {MyGame.Sample.Weapon} + */ +MyGame.Sample.Weapon.getRootAsWeapon = function(bb, obj) { + return (obj || new MyGame.Sample.Weapon).__init(bb.readInt32(bb.position()) + bb.position(), bb); +}; + +/** + * @param {flatbuffers.ByteBuffer} bb + * @param {MyGame.Sample.Weapon=} obj + * @returns {MyGame.Sample.Weapon} + */ +MyGame.Sample.Weapon.getSizePrefixedRootAsWeapon = function(bb, obj) { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new MyGame.Sample.Weapon).__init(bb.readInt32(bb.position()) + bb.position(), bb); +}; + +/** + * @param {flatbuffers.Encoding=} optionalEncoding + * @returns {string|Uint8Array|null} + */ +MyGame.Sample.Weapon.prototype.name = function(optionalEncoding) { + var offset = this.bb.__offset(this.bb_pos, 4); + return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null; +}; + +/** + * @returns {number} + */ +MyGame.Sample.Weapon.prototype.damage = function() { + var offset = this.bb.__offset(this.bb_pos, 6); + return offset ? this.bb.readInt16(this.bb_pos + offset) : 0; +}; + +/** + * @param {flatbuffers.Builder} builder + */ +MyGame.Sample.Weapon.startWeapon = function(builder) { + builder.startObject(2); +}; + +/** + * @param {flatbuffers.Builder} builder + * @param {flatbuffers.Offset} nameOffset + */ +MyGame.Sample.Weapon.addName = function(builder, nameOffset) { + builder.addFieldOffset(0, nameOffset, 0); +}; + +/** + * @param {flatbuffers.Builder} builder + * @param {number} damage + */ +MyGame.Sample.Weapon.addDamage = function(builder, damage) { + builder.addFieldInt16(1, damage, 0); +}; + +/** + * @param {flatbuffers.Builder} builder + * @returns {flatbuffers.Offset} + */ +MyGame.Sample.Weapon.endWeapon = function(builder) { + var offset = builder.endObject(); + return offset; +}; + +/** + * @param {flatbuffers.Builder} builder + * @param {flatbuffers.Offset} nameOffset + * @param {number} damage + * @returns {flatbuffers.Offset} + */ +MyGame.Sample.Weapon.createWeapon = function(builder, nameOffset, damage) { + MyGame.Sample.Weapon.startWeapon(builder); + MyGame.Sample.Weapon.addName(builder, nameOffset); + MyGame.Sample.Weapon.addDamage(builder, damage); + return MyGame.Sample.Weapon.endWeapon(builder); +} + +// Exports for Node.js and RequireJS +this.MyGame = MyGame; diff --git a/client/script.js b/client/script.js new file mode 100644 index 0000000..bbde060 --- /dev/null +++ b/client/script.js @@ -0,0 +1,81 @@ +let fbsSocket = new WebSocket("ws://localhost:1202/fbs"); +fbsSocket.binaryType = 'arraybuffer'; + +fbsSocket.onopen = function () { + sendFbs(); +}; + +let sendFbs = function () { + var builder = new flatbuffers.Builder(1024); + var weaponOne = builder.createString('Sword'); + var weaponTwo = builder.createString('Axe'); + +// Create the first `Weapon` ('Sword'). + MyGame.Sample.Weapon.startWeapon(builder); + MyGame.Sample.Weapon.addName(builder, weaponOne); + MyGame.Sample.Weapon.addDamage(builder, 3); + var sword = MyGame.Sample.Weapon.endWeapon(builder); + +// Create the second `Weapon` ('Axe'). + MyGame.Sample.Weapon.startWeapon(builder); + MyGame.Sample.Weapon.addName(builder, weaponTwo); + MyGame.Sample.Weapon.addDamage(builder, 5); + var axe = MyGame.Sample.Weapon.endWeapon(builder); + // Serialize a name for our monster, called 'Orc'. + var name = builder.createString('Orc'); + +// Create a `vector` representing the inventory of the Orc. Each number +// could correspond to an item that can be claimed after he is slain. + var treasure = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + var inv = MyGame.Sample.Monster.createInventoryVector(builder, treasure); + // Create an array from the two `Weapon`s and pass it to the +// `createWeaponsVector()` method to create a FlatBuffer vector. + var weaps = [sword, axe]; + var weapons = MyGame.Sample.Monster.createWeaponsVector(builder, weaps); + MyGame.Sample.Monster.startPathVector(builder, 2); + MyGame.Sample.Vec3.createVec3(builder, 1.0, 2.0, 3.0); + MyGame.Sample.Vec3.createVec3(builder, 4.0, 5.0, 6.0); + var path = builder.endVector(); + // Create our monster by using `startMonster()` and `endMonster()`. + MyGame.Sample.Monster.startMonster(builder); + MyGame.Sample.Monster.addPos(builder, + MyGame.Sample.Vec3.createVec3(builder, 1.0, 2.0, 3.0)); + MyGame.Sample.Monster.addHp(builder, 300); + MyGame.Sample.Monster.addColor(builder, MyGame.Sample.Color.Red) + MyGame.Sample.Monster.addName(builder, name); + MyGame.Sample.Monster.addInventory(builder, inv); + MyGame.Sample.Monster.addWeapons(builder, weapons); + MyGame.Sample.Monster.addEquippedType(builder, + MyGame.Sample.Equipment.Weapon); + MyGame.Sample.Monster.addEquipped(builder, axe); + MyGame.Sample.Monster.addPath(builder, path); + var orc = MyGame.Sample.Monster.endMonster(builder); + MyGame.Sample.Monster.addEquippedType(builder, + MyGame.Sample.Equipment.Weapon); // Union type + MyGame.Sample.Monster.addEquipped(builder, axe); // Union data + builder.finish(orc); + + var buf = builder.asUint8Array(); // Of type `Uint8Array`. + + console.log(buf); + + fbsSocket.send(buf); +} + +let jsonSocket = new WebSocket("ws://localhost:1202/json"); + +jsonSocket.onopen = function () { + sendJson(); +}; + +let sendJson = function () { + let data = { + a: 1, + b: true, + c: [1, 2, 3], + d: { + e: 1, + } + } + jsonSocket.send(JSON.stringify(data)); +} diff --git a/server/pom.xml b/server/pom.xml index 6af7430..8f19535 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -13,7 +13,7 @@ flatbuffers-java com.google.flatbuffers - 23.3.3 + 1.12.0 netty-all diff --git a/server/src/main/java/MyGame/Sample/Color.java b/server/src/main/java/MyGame/Sample/Color.java new file mode 100644 index 0000000..18bce4c --- /dev/null +++ b/server/src/main/java/MyGame/Sample/Color.java @@ -0,0 +1,15 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +package MyGame.Sample; + +public final class Color { + private Color() { } + public static final byte Red = 0; + public static final byte Green = 1; + public static final byte Blue = 2; + + public static final String[] names = { "Red", "Green", "Blue", }; + + public static String name(int e) { return names[e]; } +} + diff --git a/server/src/main/java/MyGame/Sample/Equipment.java b/server/src/main/java/MyGame/Sample/Equipment.java new file mode 100644 index 0000000..0618cae --- /dev/null +++ b/server/src/main/java/MyGame/Sample/Equipment.java @@ -0,0 +1,14 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +package MyGame.Sample; + +public final class Equipment { + private Equipment() { } + public static final byte NONE = 0; + public static final byte Weapon = 1; + + public static final String[] names = { "NONE", "Weapon", }; + + public static String name(int e) { return names[e]; } +} + diff --git a/server/src/main/java/MyGame/Sample/Monster.java b/server/src/main/java/MyGame/Sample/Monster.java new file mode 100644 index 0000000..d71e79d --- /dev/null +++ b/server/src/main/java/MyGame/Sample/Monster.java @@ -0,0 +1,76 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +package MyGame.Sample; + +import java.nio.*; +import java.lang.*; +import java.util.*; +import com.google.flatbuffers.*; + +@SuppressWarnings("unused") +public final class Monster extends Table { + public static void ValidateVersion() { Constants.FLATBUFFERS_1_12_0(); } + public static Monster getRootAsMonster(ByteBuffer _bb) { return getRootAsMonster(_bb, new Monster()); } + public static Monster getRootAsMonster(ByteBuffer _bb, Monster obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } + public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } + public Monster __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public MyGame.Sample.Vec3 pos() { return pos(new MyGame.Sample.Vec3()); } + public MyGame.Sample.Vec3 pos(MyGame.Sample.Vec3 obj) { int o = __offset(4); return o != 0 ? obj.__assign(o + bb_pos, bb) : null; } + public short mana() { int o = __offset(6); return o != 0 ? bb.getShort(o + bb_pos) : 150; } + public short hp() { int o = __offset(8); return o != 0 ? bb.getShort(o + bb_pos) : 100; } + public String name() { int o = __offset(10); return o != 0 ? __string(o + bb_pos) : null; } + public ByteBuffer nameAsByteBuffer() { return __vector_as_bytebuffer(10, 1); } + public ByteBuffer nameInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 10, 1); } + public int inventory(int j) { int o = __offset(14); return o != 0 ? bb.get(__vector(o) + j * 1) & 0xFF : 0; } + public int inventoryLength() { int o = __offset(14); return o != 0 ? __vector_len(o) : 0; } + public ByteVector inventoryVector() { return inventoryVector(new ByteVector()); } + public ByteVector inventoryVector(ByteVector obj) { int o = __offset(14); return o != 0 ? obj.__assign(__vector(o), bb) : null; } + public ByteBuffer inventoryAsByteBuffer() { return __vector_as_bytebuffer(14, 1); } + public ByteBuffer inventoryInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 14, 1); } + public byte color() { int o = __offset(16); return o != 0 ? bb.get(o + bb_pos) : 2; } + public MyGame.Sample.Weapon weapons(int j) { return weapons(new MyGame.Sample.Weapon(), j); } + public MyGame.Sample.Weapon weapons(MyGame.Sample.Weapon obj, int j) { int o = __offset(18); return o != 0 ? obj.__assign(__indirect(__vector(o) + j * 4), bb) : null; } + public int weaponsLength() { int o = __offset(18); return o != 0 ? __vector_len(o) : 0; } + public MyGame.Sample.Weapon.Vector weaponsVector() { return weaponsVector(new MyGame.Sample.Weapon.Vector()); } + public MyGame.Sample.Weapon.Vector weaponsVector(MyGame.Sample.Weapon.Vector obj) { int o = __offset(18); return o != 0 ? obj.__assign(__vector(o), 4, bb) : null; } + public byte equippedType() { int o = __offset(20); return o != 0 ? bb.get(o + bb_pos) : 0; } + public Table equipped(Table obj) { int o = __offset(22); return o != 0 ? __union(obj, o + bb_pos) : null; } + public MyGame.Sample.Vec3 path(int j) { return path(new MyGame.Sample.Vec3(), j); } + public MyGame.Sample.Vec3 path(MyGame.Sample.Vec3 obj, int j) { int o = __offset(24); return o != 0 ? obj.__assign(__vector(o) + j * 12, bb) : null; } + public int pathLength() { int o = __offset(24); return o != 0 ? __vector_len(o) : 0; } + public MyGame.Sample.Vec3.Vector pathVector() { return pathVector(new MyGame.Sample.Vec3.Vector()); } + public MyGame.Sample.Vec3.Vector pathVector(MyGame.Sample.Vec3.Vector obj) { int o = __offset(24); return o != 0 ? obj.__assign(__vector(o), 12, bb) : null; } + + public static void startMonster(FlatBufferBuilder builder) { builder.startTable(11); } + public static void addPos(FlatBufferBuilder builder, int posOffset) { builder.addStruct(0, posOffset, 0); } + public static void addMana(FlatBufferBuilder builder, short mana) { builder.addShort(1, mana, 150); } + public static void addHp(FlatBufferBuilder builder, short hp) { builder.addShort(2, hp, 100); } + public static void addName(FlatBufferBuilder builder, int nameOffset) { builder.addOffset(3, nameOffset, 0); } + public static void addInventory(FlatBufferBuilder builder, int inventoryOffset) { builder.addOffset(5, inventoryOffset, 0); } + public static int createInventoryVector(FlatBufferBuilder builder, byte[] data) { return builder.createByteVector(data); } + public static int createInventoryVector(FlatBufferBuilder builder, ByteBuffer data) { return builder.createByteVector(data); } + public static void startInventoryVector(FlatBufferBuilder builder, int numElems) { builder.startVector(1, numElems, 1); } + public static void addColor(FlatBufferBuilder builder, byte color) { builder.addByte(6, color, 2); } + public static void addWeapons(FlatBufferBuilder builder, int weaponsOffset) { builder.addOffset(7, weaponsOffset, 0); } + public static int createWeaponsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addOffset(data[i]); return builder.endVector(); } + public static void startWeaponsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static void addEquippedType(FlatBufferBuilder builder, byte equippedType) { builder.addByte(8, equippedType, 0); } + public static void addEquipped(FlatBufferBuilder builder, int equippedOffset) { builder.addOffset(9, equippedOffset, 0); } + public static void addPath(FlatBufferBuilder builder, int pathOffset) { builder.addOffset(10, pathOffset, 0); } + public static void startPathVector(FlatBufferBuilder builder, int numElems) { builder.startVector(12, numElems, 4); } + public static int endMonster(FlatBufferBuilder builder) { + int o = builder.endTable(); + return o; + } + public static void finishMonsterBuffer(FlatBufferBuilder builder, int offset) { builder.finish(offset); } + public static void finishSizePrefixedMonsterBuffer(FlatBufferBuilder builder, int offset) { builder.finishSizePrefixed(offset); } + + public static final class Vector extends BaseVector { + public Vector __assign(int _vector, int _element_size, ByteBuffer _bb) { __reset(_vector, _element_size, _bb); return this; } + + public Monster get(int j) { return get(new Monster(), j); } + public Monster get(Monster obj, int j) { return obj.__assign(__indirect(__element(j), bb), bb); } + } +} + diff --git a/server/src/main/java/MyGame/Sample/Vec3.java b/server/src/main/java/MyGame/Sample/Vec3.java new file mode 100644 index 0000000..2673c01 --- /dev/null +++ b/server/src/main/java/MyGame/Sample/Vec3.java @@ -0,0 +1,34 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +package MyGame.Sample; + +import java.nio.*; +import java.lang.*; +import java.util.*; +import com.google.flatbuffers.*; + +@SuppressWarnings("unused") +public final class Vec3 extends Struct { + public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } + public Vec3 __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public float x() { return bb.getFloat(bb_pos + 0); } + public float y() { return bb.getFloat(bb_pos + 4); } + public float z() { return bb.getFloat(bb_pos + 8); } + + public static int createVec3(FlatBufferBuilder builder, float x, float y, float z) { + builder.prep(4, 12); + builder.putFloat(z); + builder.putFloat(y); + builder.putFloat(x); + return builder.offset(); + } + + public static final class Vector extends BaseVector { + public Vector __assign(int _vector, int _element_size, ByteBuffer _bb) { __reset(_vector, _element_size, _bb); return this; } + + public Vec3 get(int j) { return get(new Vec3(), j); } + public Vec3 get(Vec3 obj, int j) { return obj.__assign(__element(j), bb); } + } +} + diff --git a/server/src/main/java/MyGame/Sample/Weapon.java b/server/src/main/java/MyGame/Sample/Weapon.java new file mode 100644 index 0000000..8401f2a --- /dev/null +++ b/server/src/main/java/MyGame/Sample/Weapon.java @@ -0,0 +1,47 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +package MyGame.Sample; + +import java.nio.*; +import java.lang.*; +import java.util.*; +import com.google.flatbuffers.*; + +@SuppressWarnings("unused") +public final class Weapon extends Table { + public static void ValidateVersion() { Constants.FLATBUFFERS_1_12_0(); } + public static Weapon getRootAsWeapon(ByteBuffer _bb) { return getRootAsWeapon(_bb, new Weapon()); } + public static Weapon getRootAsWeapon(ByteBuffer _bb, Weapon obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } + public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } + public Weapon __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public String name() { int o = __offset(4); return o != 0 ? __string(o + bb_pos) : null; } + public ByteBuffer nameAsByteBuffer() { return __vector_as_bytebuffer(4, 1); } + public ByteBuffer nameInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 4, 1); } + public short damage() { int o = __offset(6); return o != 0 ? bb.getShort(o + bb_pos) : 0; } + + public static int createWeapon(FlatBufferBuilder builder, + int nameOffset, + short damage) { + builder.startTable(2); + Weapon.addName(builder, nameOffset); + Weapon.addDamage(builder, damage); + return Weapon.endWeapon(builder); + } + + public static void startWeapon(FlatBufferBuilder builder) { builder.startTable(2); } + public static void addName(FlatBufferBuilder builder, int nameOffset) { builder.addOffset(0, nameOffset, 0); } + public static void addDamage(FlatBufferBuilder builder, short damage) { builder.addShort(1, damage, 0); } + public static int endWeapon(FlatBufferBuilder builder) { + int o = builder.endTable(); + return o; + } + + public static final class Vector extends BaseVector { + public Vector __assign(int _vector, int _element_size, ByteBuffer _bb) { __reset(_vector, _element_size, _bb); return this; } + + public Weapon get(int j) { return get(new Weapon(), j); } + public Weapon get(Weapon obj, int j) { return obj.__assign(__indirect(__element(j), bb), bb); } + } +} + diff --git a/server/src/main/java/com/miti99/netty/Main.java b/server/src/main/java/com/miti99/netty/Main.java index c62bc30..bd70c7d 100644 --- a/server/src/main/java/com/miti99/netty/Main.java +++ b/server/src/main/java/com/miti99/netty/Main.java @@ -1,14 +1,73 @@ package com.miti99.netty; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.epoll.Epoll; +import io.netty.channel.epoll.EpollEventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; +import io.netty.handler.codec.http.websocketx.extensions.compression.WebSocketServerCompressionHandler; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import io.netty.util.internal.logging.InternalLoggerFactory; +import io.netty.util.internal.logging.Slf4JLoggerFactory; import lombok.extern.slf4j.Slf4j; +import lombok.val; @Slf4j public class Main { public static void main(String[] args) { - log.debug("debug"); - log.info("info"); - log.warn("warn"); - log.error("error"); + InternalLoggerFactory.setDefaultFactory(Slf4JLoggerFactory.INSTANCE); + var parentGroup = Epoll.isAvailable() ? new EpollEventLoopGroup() : new NioEventLoopGroup(); + var childGroup = Epoll.isAvailable() ? new EpollEventLoopGroup() : new NioEventLoopGroup(); + + val serverBootstrap = new ServerBootstrap(); + serverBootstrap.group(parentGroup, childGroup).channel( + NioServerSocketChannel.class + ).handler(new LoggingHandler(LogLevel.DEBUG)) + .childHandler(new ChannelInitializer<>() { + + @Override + protected void initChannel(Channel channel) { + channel.pipeline() + .addLast(new LoggingHandler(LogLevel.DEBUG)) + .addLast(new HttpServerCodec()) + .addLast(new HttpObjectAggregator(65536)) + .addLast(new WebSocketServerCompressionHandler()) + .addLast(new WebSocketServerProtocolHandler("/fbs", null, true)) + .addLast(new WebsocketDecoder()) + .addLast(new WebsocketHandler()); + } + }) + .childHandler( + new ChannelInitializer<>() { + + @Override + protected void initChannel(Channel channel) { + channel.pipeline() + .addLast(new LoggingHandler(LogLevel.INFO)) + .addLast(new HttpServerCodec()) + .addLast(new HttpObjectAggregator(65536)) + .addLast(new WebSocketServerCompressionHandler()) + .addLast(new WebSocketServerProtocolHandler("/json", null, true)) + .addLast(new WebsocketHandler()); + } + } + ); + + try { + val channelFuture = serverBootstrap.bind(1202).sync(); + channelFuture.channel().closeFuture().sync(); + } catch (InterruptedException interruptedException) { + log.error("Interrupted", interruptedException); + } finally { + parentGroup.shutdownGracefully(); + childGroup.shutdownGracefully(); + } } } diff --git a/server/src/main/java/com/miti99/netty/WebsocketDecoder.java b/server/src/main/java/com/miti99/netty/WebsocketDecoder.java new file mode 100644 index 0000000..b8c9ebf --- /dev/null +++ b/server/src/main/java/com/miti99/netty/WebsocketDecoder.java @@ -0,0 +1,32 @@ +package com.miti99.netty; + +import MyGame.Sample.Monster; +import io.netty.buffer.ByteBufUtil; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToMessageDecoder; +import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame; +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.List; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class WebsocketDecoder extends MessageToMessageDecoder { + + @Override + protected void decode(ChannelHandlerContext channelHandlerContext, + BinaryWebSocketFrame binaryWebSocketFrame, List list) { + var byteBuf = binaryWebSocketFrame.content(); + byteBuf.retain(); + + var bytes = ByteBufUtil.getBytes(byteBuf); + + log.info(Arrays.toString(bytes)); + + var byteBuffer = ByteBuffer.wrap(bytes); + + var monster = Monster.getRootAsMonster(byteBuffer); + + list.add(monster); + } +} diff --git a/server/src/main/java/com/miti99/netty/WebsocketHandler.java b/server/src/main/java/com/miti99/netty/WebsocketHandler.java new file mode 100644 index 0000000..c63bfc4 --- /dev/null +++ b/server/src/main/java/com/miti99/netty/WebsocketHandler.java @@ -0,0 +1,67 @@ +package com.miti99.netty; + + + +import MyGame.Sample.Equipment; +import MyGame.Sample.Monster; +import MyGame.Sample.Weapon; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; +import lombok.extern.slf4j.Slf4j; + +@ChannelHandler.Sharable +@Slf4j +public class WebsocketHandler extends ChannelInboundHandlerAdapter { + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) { + if (msg instanceof Monster monster) { + var hp = monster.hp(); + var mana = monster.mana(); + var name = monster.name(); + + log.info("hp : {}, mana : {}, name : {}", hp, mana, name); + + var pos = monster.pos(); + var x = pos.x(); + var y = pos.y(); + var z = pos.z(); + + log.info("x : {}, y : {}, z : {}", x, y, z); + + var invLength = monster.inventoryLength(); + var thirdItem = monster.inventory(2); + + var weaponsLength = monster.weaponsLength(); + var secondWeaponName = monster.weapons(1).name(); + var secondWeaponDamage = monster.weapons(1).damage(); + + log.info( + "invLength : {}, thirdItem : {}, weaponsLength : {}, secondWeaponName : {}, secondWeaponDamage : {}", + invLength, thirdItem, weaponsLength, secondWeaponName, secondWeaponDamage); + + var unionType = monster.equippedType(); + + if (unionType == Equipment.Weapon) { + var weapon = (Weapon) monster.equipped(new Weapon()); + + var weaponName = weapon.name(); // "Axe" + var weaponDamage = weapon.damage(); // 5 + + log.info("weaponName : {}, weaponDamage : {}", weaponName, weaponDamage); + } + } else if (msg instanceof TextWebSocketFrame textWebSocketFrame) { + log.info(textWebSocketFrame.text()); + }else { + ctx.fireChannelRead(msg); + } + } + + @Override + public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + super.channelReadComplete(ctx); + ctx.flush(); + } +} diff --git a/server/src/main/resources/logback.xml b/server/src/main/resources/logback.xml index d79d535..5914be1 100644 --- a/server/src/main/resources/logback.xml +++ b/server/src/main/resources/logback.xml @@ -40,12 +40,14 @@ - - - - + + + + + + diff --git a/server/src/main/resources/sample.fbs b/server/src/main/resources/sample.fbs new file mode 100644 index 0000000..5ec644e --- /dev/null +++ b/server/src/main/resources/sample.fbs @@ -0,0 +1,33 @@ +// Example IDL file for our monster's schema. + +namespace MyGame.Sample; + +enum Color:byte { Red = 0, Green, Blue = 2 } + +union Equipment { Weapon } // Optionally add more tables. + +struct Vec3 { + x:float; + y:float; + z:float; +} + +table Monster { + pos:Vec3; // Struct. + mana:short = 150; + hp:short = 100; + name:string; + friendly:bool = false (deprecated); + inventory:[ubyte]; // Vector of scalars. + color:Color = Blue; // Enum. + weapons:[Weapon]; // Vector of tables. + equipped:Equipment; // Union. + path:[Vec3]; // Vector of structs. +} + +table Weapon { + name:string; + damage:short; +} + +root_type Monster;