// automatically generated by the FlatBuffers compiler, do not modify


#ifndef FLATBUFFERS_GENERATED_MONSTEREXTRA_MYGAME_H_
#define FLATBUFFERS_GENERATED_MONSTEREXTRA_MYGAME_H_

#include "flatbuffers/flatbuffers.h"

// Ensure the included flatbuffers.h is the same version as when this file was
// generated, otherwise it may not be compatible.
static_assert(FLATBUFFERS_VERSION_MAJOR == 25 &&
              FLATBUFFERS_VERSION_MINOR == 12 &&
              FLATBUFFERS_VERSION_REVISION == 19,
             "Non-compatible flatbuffers version included");

namespace MyGame {

struct MonsterExtra;
struct MonsterExtraBuilder;
struct MonsterExtraT;

bool operator==(const MonsterExtraT &lhs, const MonsterExtraT &rhs);
bool operator!=(const MonsterExtraT &lhs, const MonsterExtraT &rhs);

inline const ::flatbuffers::TypeTable *MonsterExtraTypeTable();

struct MonsterExtraT : public ::flatbuffers::NativeTable {
  typedef MonsterExtra TableType;
  double d0 = std::numeric_limits<double>::quiet_NaN();
  double d1 = std::numeric_limits<double>::quiet_NaN();
  double d2 = std::numeric_limits<double>::infinity();
  double d3 = -std::numeric_limits<double>::infinity();
  float f0 = std::numeric_limits<float>::quiet_NaN();
  float f1 = std::numeric_limits<float>::quiet_NaN();
  float f2 = std::numeric_limits<float>::infinity();
  float f3 = -std::numeric_limits<float>::infinity();
  std::vector<double> dvec{};
  std::vector<float> fvec{};
};

struct MonsterExtra FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
  typedef MonsterExtraT NativeTableType;
  typedef MonsterExtraBuilder Builder;
  static const ::flatbuffers::TypeTable *MiniReflectTypeTable() {
    return MonsterExtraTypeTable();
  }
  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
    VT_D0 = 4,
    VT_D1 = 6,
    VT_D2 = 8,
    VT_D3 = 10,
    VT_F0 = 12,
    VT_F1 = 14,
    VT_F2 = 16,
    VT_F3 = 18,
    VT_DVEC = 20,
    VT_FVEC = 22
  };
  double d0() const {
    return GetField<double>(VT_D0, std::numeric_limits<double>::quiet_NaN());
  }
  bool mutate_d0(double _d0 = std::numeric_limits<double>::quiet_NaN()) {
    return SetField<double>(VT_D0, _d0, std::numeric_limits<double>::quiet_NaN());
  }
  double d1() const {
    return GetField<double>(VT_D1, std::numeric_limits<double>::quiet_NaN());
  }
  bool mutate_d1(double _d1 = std::numeric_limits<double>::quiet_NaN()) {
    return SetField<double>(VT_D1, _d1, std::numeric_limits<double>::quiet_NaN());
  }
  double d2() const {
    return GetField<double>(VT_D2, std::numeric_limits<double>::infinity());
  }
  bool mutate_d2(double _d2 = std::numeric_limits<double>::infinity()) {
    return SetField<double>(VT_D2, _d2, std::numeric_limits<double>::infinity());
  }
  double d3() const {
    return GetField<double>(VT_D3, -std::numeric_limits<double>::infinity());
  }
  bool mutate_d3(double _d3 = -std::numeric_limits<double>::infinity()) {
    return SetField<double>(VT_D3, _d3, -std::numeric_limits<double>::infinity());
  }
  float f0() const {
    return GetField<float>(VT_F0, std::numeric_limits<float>::quiet_NaN());
  }
  bool mutate_f0(float _f0 = std::numeric_limits<float>::quiet_NaN()) {
    return SetField<float>(VT_F0, _f0, std::numeric_limits<float>::quiet_NaN());
  }
  float f1() const {
    return GetField<float>(VT_F1, std::numeric_limits<float>::quiet_NaN());
  }
  bool mutate_f1(float _f1 = std::numeric_limits<float>::quiet_NaN()) {
    return SetField<float>(VT_F1, _f1, std::numeric_limits<float>::quiet_NaN());
  }
  float f2() const {
    return GetField<float>(VT_F2, std::numeric_limits<float>::infinity());
  }
  bool mutate_f2(float _f2 = std::numeric_limits<float>::infinity()) {
    return SetField<float>(VT_F2, _f2, std::numeric_limits<float>::infinity());
  }
  float f3() const {
    return GetField<float>(VT_F3, -std::numeric_limits<float>::infinity());
  }
  bool mutate_f3(float _f3 = -std::numeric_limits<float>::infinity()) {
    return SetField<float>(VT_F3, _f3, -std::numeric_limits<float>::infinity());
  }
  const ::flatbuffers::Vector<double> *dvec() const {
    return GetPointer<const ::flatbuffers::Vector<double> *>(VT_DVEC);
  }
  ::flatbuffers::Vector<double> *mutable_dvec() {
    return GetPointer<::flatbuffers::Vector<double> *>(VT_DVEC);
  }
  const ::flatbuffers::Vector<float> *fvec() const {
    return GetPointer<const ::flatbuffers::Vector<float> *>(VT_FVEC);
  }
  ::flatbuffers::Vector<float> *mutable_fvec() {
    return GetPointer<::flatbuffers::Vector<float> *>(VT_FVEC);
  }
  template <bool B = false>
  bool Verify(::flatbuffers::VerifierTemplate<B> &verifier) const {
    return VerifyTableStart(verifier) &&
           VerifyField<double>(verifier, VT_D0, 8) &&
           VerifyField<double>(verifier, VT_D1, 8) &&
           VerifyField<double>(verifier, VT_D2, 8) &&
           VerifyField<double>(verifier, VT_D3, 8) &&
           VerifyField<float>(verifier, VT_F0, 4) &&
           VerifyField<float>(verifier, VT_F1, 4) &&
           VerifyField<float>(verifier, VT_F2, 4) &&
           VerifyField<float>(verifier, VT_F3, 4) &&
           VerifyOffset(verifier, VT_DVEC) &&
           verifier.VerifyVector(dvec()) &&
           VerifyOffset(verifier, VT_FVEC) &&
           verifier.VerifyVector(fvec()) &&
           verifier.EndTable();
  }
  MonsterExtraT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
  void UnPackTo(MonsterExtraT *_o, const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
  static ::flatbuffers::Offset<MonsterExtra> Pack(::flatbuffers::FlatBufferBuilder &_fbb, const MonsterExtraT* _o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
};

struct MonsterExtraBuilder {
  typedef MonsterExtra Table;
  ::flatbuffers::FlatBufferBuilder &fbb_;
  ::flatbuffers::uoffset_t start_;
  void add_d0(double d0) {
    fbb_.AddElement<double>(MonsterExtra::VT_D0, d0, std::numeric_limits<double>::quiet_NaN());
  }
  void add_d1(double d1) {
    fbb_.AddElement<double>(MonsterExtra::VT_D1, d1, std::numeric_limits<double>::quiet_NaN());
  }
  void add_d2(double d2) {
    fbb_.AddElement<double>(MonsterExtra::VT_D2, d2, std::numeric_limits<double>::infinity());
  }
  void add_d3(double d3) {
    fbb_.AddElement<double>(MonsterExtra::VT_D3, d3, -std::numeric_limits<double>::infinity());
  }
  void add_f0(float f0) {
    fbb_.AddElement<float>(MonsterExtra::VT_F0, f0, std::numeric_limits<float>::quiet_NaN());
  }
  void add_f1(float f1) {
    fbb_.AddElement<float>(MonsterExtra::VT_F1, f1, std::numeric_limits<float>::quiet_NaN());
  }
  void add_f2(float f2) {
    fbb_.AddElement<float>(MonsterExtra::VT_F2, f2, std::numeric_limits<float>::infinity());
  }
  void add_f3(float f3) {
    fbb_.AddElement<float>(MonsterExtra::VT_F3, f3, -std::numeric_limits<float>::infinity());
  }
  void add_dvec(::flatbuffers::Offset<::flatbuffers::Vector<double>> dvec) {
    fbb_.AddOffset(MonsterExtra::VT_DVEC, dvec);
  }
  void add_fvec(::flatbuffers::Offset<::flatbuffers::Vector<float>> fvec) {
    fbb_.AddOffset(MonsterExtra::VT_FVEC, fvec);
  }
  explicit MonsterExtraBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
        : fbb_(_fbb) {
    start_ = fbb_.StartTable();
  }
  ::flatbuffers::Offset<MonsterExtra> Finish() {
    const auto end = fbb_.EndTable(start_);
    auto o = ::flatbuffers::Offset<MonsterExtra>(end);
    return o;
  }
};

inline ::flatbuffers::Offset<MonsterExtra> CreateMonsterExtra(
    ::flatbuffers::FlatBufferBuilder &_fbb,
    double d0 = std::numeric_limits<double>::quiet_NaN(),
    double d1 = std::numeric_limits<double>::quiet_NaN(),
    double d2 = std::numeric_limits<double>::infinity(),
    double d3 = -std::numeric_limits<double>::infinity(),
    float f0 = std::numeric_limits<float>::quiet_NaN(),
    float f1 = std::numeric_limits<float>::quiet_NaN(),
    float f2 = std::numeric_limits<float>::infinity(),
    float f3 = -std::numeric_limits<float>::infinity(),
    ::flatbuffers::Offset<::flatbuffers::Vector<double>> dvec = 0,
    ::flatbuffers::Offset<::flatbuffers::Vector<float>> fvec = 0) {
  MonsterExtraBuilder builder_(_fbb);
  builder_.add_d3(d3);
  builder_.add_d2(d2);
  builder_.add_d1(d1);
  builder_.add_d0(d0);
  builder_.add_fvec(fvec);
  builder_.add_dvec(dvec);
  builder_.add_f3(f3);
  builder_.add_f2(f2);
  builder_.add_f1(f1);
  builder_.add_f0(f0);
  return builder_.Finish();
}

inline ::flatbuffers::Offset<MonsterExtra> CreateMonsterExtraDirect(
    ::flatbuffers::FlatBufferBuilder &_fbb,
    double d0 = std::numeric_limits<double>::quiet_NaN(),
    double d1 = std::numeric_limits<double>::quiet_NaN(),
    double d2 = std::numeric_limits<double>::infinity(),
    double d3 = -std::numeric_limits<double>::infinity(),
    float f0 = std::numeric_limits<float>::quiet_NaN(),
    float f1 = std::numeric_limits<float>::quiet_NaN(),
    float f2 = std::numeric_limits<float>::infinity(),
    float f3 = -std::numeric_limits<float>::infinity(),
    const std::vector<double> *dvec = nullptr,
    const std::vector<float> *fvec = nullptr) {
  auto dvec__ = dvec ? _fbb.CreateVector<double>(*dvec) : 0;
  auto fvec__ = fvec ? _fbb.CreateVector<float>(*fvec) : 0;
  return MyGame::CreateMonsterExtra(
      _fbb,
      d0,
      d1,
      d2,
      d3,
      f0,
      f1,
      f2,
      f3,
      dvec__,
      fvec__);
}

::flatbuffers::Offset<MonsterExtra> CreateMonsterExtra(::flatbuffers::FlatBufferBuilder &_fbb, const MonsterExtraT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);


inline bool operator==(const MonsterExtraT &lhs, const MonsterExtraT &rhs) {
  return
      (lhs.d0 == rhs.d0) &&
      (lhs.d1 == rhs.d1) &&
      (lhs.d2 == rhs.d2) &&
      (lhs.d3 == rhs.d3) &&
      (lhs.f0 == rhs.f0) &&
      (lhs.f1 == rhs.f1) &&
      (lhs.f2 == rhs.f2) &&
      (lhs.f3 == rhs.f3) &&
      (lhs.dvec == rhs.dvec) &&
      (lhs.fvec == rhs.fvec);
}

inline bool operator!=(const MonsterExtraT &lhs, const MonsterExtraT &rhs) {
    return !(lhs == rhs);
}


inline MonsterExtraT *MonsterExtra::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const {
  auto _o = std::unique_ptr<MonsterExtraT>(new MonsterExtraT());
  UnPackTo(_o.get(), _resolver);
  return _o.release();
}

inline void MonsterExtra::UnPackTo(MonsterExtraT *_o, const ::flatbuffers::resolver_function_t *_resolver) const {
  (void)_o;
  (void)_resolver;
  { auto _e = d0(); _o->d0 = _e; }
  { auto _e = d1(); _o->d1 = _e; }
  { auto _e = d2(); _o->d2 = _e; }
  { auto _e = d3(); _o->d3 = _e; }
  { auto _e = f0(); _o->f0 = _e; }
  { auto _e = f1(); _o->f1 = _e; }
  { auto _e = f2(); _o->f2 = _e; }
  { auto _e = f3(); _o->f3 = _e; }
  { auto _e = dvec(); if (_e) { _o->dvec.resize(_e->size()); for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->dvec[_i] = _e->Get(_i); } } else { _o->dvec.resize(0); } }
  { auto _e = fvec(); if (_e) { _o->fvec.resize(_e->size()); for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->fvec[_i] = _e->Get(_i); } } else { _o->fvec.resize(0); } }
}

inline ::flatbuffers::Offset<MonsterExtra> CreateMonsterExtra(::flatbuffers::FlatBufferBuilder &_fbb, const MonsterExtraT *_o, const ::flatbuffers::rehasher_function_t *_rehasher) {
  return MonsterExtra::Pack(_fbb, _o, _rehasher);
}

inline ::flatbuffers::Offset<MonsterExtra> MonsterExtra::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const MonsterExtraT* _o, const ::flatbuffers::rehasher_function_t *_rehasher) {
  (void)_rehasher;
  (void)_o;
  struct _VectorArgs { ::flatbuffers::FlatBufferBuilder *__fbb; const MonsterExtraT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
  auto _d0 = _o->d0;
  auto _d1 = _o->d1;
  auto _d2 = _o->d2;
  auto _d3 = _o->d3;
  auto _f0 = _o->f0;
  auto _f1 = _o->f1;
  auto _f2 = _o->f2;
  auto _f3 = _o->f3;
  auto _dvec = _o->dvec.size() ? _fbb.CreateVector(_o->dvec) : 0;
  auto _fvec = _o->fvec.size() ? _fbb.CreateVector(_o->fvec) : 0;
  return MyGame::CreateMonsterExtra(
      _fbb,
      _d0,
      _d1,
      _d2,
      _d3,
      _f0,
      _f1,
      _f2,
      _f3,
      _dvec,
      _fvec);
}

inline const ::flatbuffers::TypeTable *MonsterExtraTypeTable() {
  static const ::flatbuffers::TypeCode type_codes[] = {
    { ::flatbuffers::ET_DOUBLE, 0, -1 },
    { ::flatbuffers::ET_DOUBLE, 0, -1 },
    { ::flatbuffers::ET_DOUBLE, 0, -1 },
    { ::flatbuffers::ET_DOUBLE, 0, -1 },
    { ::flatbuffers::ET_FLOAT, 0, -1 },
    { ::flatbuffers::ET_FLOAT, 0, -1 },
    { ::flatbuffers::ET_FLOAT, 0, -1 },
    { ::flatbuffers::ET_FLOAT, 0, -1 },
    { ::flatbuffers::ET_DOUBLE, 1, -1 },
    { ::flatbuffers::ET_FLOAT, 1, -1 },
    { ::flatbuffers::ET_INT, 0, -1 }
  };
  static const char * const names[] = {
    "d0",
    "d1",
    "d2",
    "d3",
    "f0",
    "f1",
    "f2",
    "f3",
    "dvec",
    "fvec",
    "deprec"
  };
  static const ::flatbuffers::TypeTable tt = {
    ::flatbuffers::ST_TABLE, 11, type_codes, nullptr, nullptr, nullptr, names
  };
  return &tt;
}

inline const MyGame::MonsterExtra *GetMonsterExtra(const void *buf) {
  return ::flatbuffers::GetRoot<MyGame::MonsterExtra>(buf);
}

inline const MyGame::MonsterExtra *GetSizePrefixedMonsterExtra(const void *buf) {
  return ::flatbuffers::GetSizePrefixedRoot<MyGame::MonsterExtra>(buf);
}

inline MonsterExtra *GetMutableMonsterExtra(void *buf) {
  return ::flatbuffers::GetMutableRoot<MonsterExtra>(buf);
}

inline MyGame::MonsterExtra *GetMutableSizePrefixedMonsterExtra(void *buf) {
  return ::flatbuffers::GetMutableSizePrefixedRoot<MyGame::MonsterExtra>(buf);
}

inline const char *MonsterExtraIdentifier() {
  return "MONE";
}

inline bool MonsterExtraBufferHasIdentifier(const void *buf) {
  return ::flatbuffers::BufferHasIdentifier(
      buf, MonsterExtraIdentifier());
}

inline bool SizePrefixedMonsterExtraBufferHasIdentifier(const void *buf) {
  return ::flatbuffers::BufferHasIdentifier(
      buf, MonsterExtraIdentifier(), true);
}

template <bool B = false>
inline bool VerifyMonsterExtraBuffer(
    ::flatbuffers::VerifierTemplate<B> &verifier) {
  return verifier.template VerifyBuffer<MyGame::MonsterExtra>(MonsterExtraIdentifier());
}

template <bool B = false>
inline bool VerifySizePrefixedMonsterExtraBuffer(
    ::flatbuffers::VerifierTemplate<B> &verifier) {
  return verifier.template VerifySizePrefixedBuffer<MyGame::MonsterExtra>(MonsterExtraIdentifier());
}

inline const char *MonsterExtraExtension() {
  return "mon";
}

inline void FinishMonsterExtraBuffer(
    ::flatbuffers::FlatBufferBuilder &fbb,
    ::flatbuffers::Offset<MyGame::MonsterExtra> root) {
  fbb.Finish(root, MonsterExtraIdentifier());
}

inline void FinishSizePrefixedMonsterExtraBuffer(
    ::flatbuffers::FlatBufferBuilder &fbb,
    ::flatbuffers::Offset<MyGame::MonsterExtra> root) {
  fbb.FinishSizePrefixed(root, MonsterExtraIdentifier());
}

inline std::unique_ptr<MyGame::MonsterExtraT> UnPackMonsterExtra(
    const void *buf,
    const ::flatbuffers::resolver_function_t *res = nullptr) {
  return std::unique_ptr<MyGame::MonsterExtraT>(GetMonsterExtra(buf)->UnPack(res));
}

inline std::unique_ptr<MyGame::MonsterExtraT> UnPackSizePrefixedMonsterExtra(
    const void *buf,
    const ::flatbuffers::resolver_function_t *res = nullptr) {
  return std::unique_ptr<MyGame::MonsterExtraT>(GetSizePrefixedMonsterExtra(buf)->UnPack(res));
}

}  // namespace MyGame

#endif  // FLATBUFFERS_GENERATED_MONSTEREXTRA_MYGAME_H_
