// automatically generated by the FlatBuffers compiler, do not modify
// ignore_for_file: unused_import, unused_field, unused_local_variable

library my_game;

import 'dart:typed_data' show Uint8List;
import 'package:flat_buffers/flat_buffers.dart' as fb;


class MonsterExtra {
  MonsterExtra._(this._bc, this._bcOffset);
  factory MonsterExtra(List<int> bytes) {
    fb.BufferContext rootRef = new fb.BufferContext.fromBytes(bytes);
    return reader.read(rootRef, 0);
  }

  static const fb.Reader<MonsterExtra> reader = const _MonsterExtraReader();

  final fb.BufferContext _bc;
  final int _bcOffset;

  double get d0 => const fb.Float64Reader().vTableGet(_bc, _bcOffset, 4, double.nan);
  double get d1 => const fb.Float64Reader().vTableGet(_bc, _bcOffset, 6, double.nan);
  double get d2 => const fb.Float64Reader().vTableGet(_bc, _bcOffset, 8, double.infinity);
  double get d3 => const fb.Float64Reader().vTableGet(_bc, _bcOffset, 10, double.negativeInfinity);
  double get f0 => const fb.Float32Reader().vTableGet(_bc, _bcOffset, 12, double.nan);
  double get f1 => const fb.Float32Reader().vTableGet(_bc, _bcOffset, 14, double.nan);
  double get f2 => const fb.Float32Reader().vTableGet(_bc, _bcOffset, 16, double.infinity);
  double get f3 => const fb.Float32Reader().vTableGet(_bc, _bcOffset, 18, double.negativeInfinity);
  List<double> get dvec => const fb.ListReader<double>(const fb.Float64Reader()).vTableGet(_bc, _bcOffset, 20, null);
  List<double> get fvec => const fb.ListReader<double>(const fb.Float32Reader()).vTableGet(_bc, _bcOffset, 22, null);

  @override
  String toString() {
    return 'MonsterExtra{d0: $d0, d1: $d1, d2: $d2, d3: $d3, f0: $f0, f1: $f1, f2: $f2, f3: $f3, dvec: $dvec, fvec: $fvec}';
  }
}

class _MonsterExtraReader extends fb.TableReader<MonsterExtra> {
  const _MonsterExtraReader();

  @override
  MonsterExtra createObject(fb.BufferContext bc, int offset) => 
    new MonsterExtra._(bc, offset);
}

class MonsterExtraBuilder {
  MonsterExtraBuilder(this.fbBuilder) {
    assert(fbBuilder != null);
  }

  final fb.Builder fbBuilder;

  void begin() {
    fbBuilder.startTable();
  }

  int addD0(double d0) {
    fbBuilder.addFloat64(0, d0);
    return fbBuilder.offset;
  }
  int addD1(double d1) {
    fbBuilder.addFloat64(1, d1);
    return fbBuilder.offset;
  }
  int addD2(double d2) {
    fbBuilder.addFloat64(2, d2);
    return fbBuilder.offset;
  }
  int addD3(double d3) {
    fbBuilder.addFloat64(3, d3);
    return fbBuilder.offset;
  }
  int addF0(double f0) {
    fbBuilder.addFloat32(4, f0);
    return fbBuilder.offset;
  }
  int addF1(double f1) {
    fbBuilder.addFloat32(5, f1);
    return fbBuilder.offset;
  }
  int addF2(double f2) {
    fbBuilder.addFloat32(6, f2);
    return fbBuilder.offset;
  }
  int addF3(double f3) {
    fbBuilder.addFloat32(7, f3);
    return fbBuilder.offset;
  }
  int addDvecOffset(int offset) {
    fbBuilder.addOffset(8, offset);
    return fbBuilder.offset;
  }
  int addFvecOffset(int offset) {
    fbBuilder.addOffset(9, offset);
    return fbBuilder.offset;
  }

  int finish() {
    return fbBuilder.endTable();
  }
}

class MonsterExtraObjectBuilder extends fb.ObjectBuilder {
  final double _d0;
  final double _d1;
  final double _d2;
  final double _d3;
  final double _f0;
  final double _f1;
  final double _f2;
  final double _f3;
  final List<double> _dvec;
  final List<double> _fvec;

  MonsterExtraObjectBuilder({
    double d0,
    double d1,
    double d2,
    double d3,
    double f0,
    double f1,
    double f2,
    double f3,
    List<double> dvec,
    List<double> fvec,
  })
      : _d0 = d0,
        _d1 = d1,
        _d2 = d2,
        _d3 = d3,
        _f0 = f0,
        _f1 = f1,
        _f2 = f2,
        _f3 = f3,
        _dvec = dvec,
        _fvec = fvec;

  /// Finish building, and store into the [fbBuilder].
  @override
  int finish(
    fb.Builder fbBuilder) {
    assert(fbBuilder != null);
    final int dvecOffset = _dvec?.isNotEmpty == true
        ? fbBuilder.writeListFloat64(_dvec)
        : null;
    final int fvecOffset = _fvec?.isNotEmpty == true
        ? fbBuilder.writeListFloat32(_fvec)
        : null;

    fbBuilder.startTable();
    fbBuilder.addFloat64(0, _d0);
    fbBuilder.addFloat64(1, _d1);
    fbBuilder.addFloat64(2, _d2);
    fbBuilder.addFloat64(3, _d3);
    fbBuilder.addFloat32(4, _f0);
    fbBuilder.addFloat32(5, _f1);
    fbBuilder.addFloat32(6, _f2);
    fbBuilder.addFloat32(7, _f3);
    if (dvecOffset != null) {
      fbBuilder.addOffset(8, dvecOffset);
    }
    if (fvecOffset != null) {
      fbBuilder.addOffset(9, fvecOffset);
    }
    return fbBuilder.endTable();
  }

  /// Convenience method to serialize to byte list.
  @override
  Uint8List toBytes([String fileIdentifier]) {
    fb.Builder fbBuilder = new fb.Builder();
    int offset = finish(fbBuilder);
    return fbBuilder.finish(offset, fileIdentifier);
  }
}
