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

package MyGame.Example;

import com.google.flatbuffers.BaseVector;
import com.google.flatbuffers.BooleanVector;
import com.google.flatbuffers.ByteVector;
import com.google.flatbuffers.Constants;
import com.google.flatbuffers.DoubleVector;
import com.google.flatbuffers.FlatBufferBuilder;
import com.google.flatbuffers.FloatVector;
import com.google.flatbuffers.IntVector;
import com.google.flatbuffers.LongVector;
import com.google.flatbuffers.ShortVector;
import com.google.flatbuffers.StringVector;
import com.google.flatbuffers.Struct;
import com.google.flatbuffers.Table;
import com.google.flatbuffers.UnionVector;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

@SuppressWarnings("unused")
public final class StructOfStructs extends Struct {
  public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); }
  public StructOfStructs __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }

  public MyGame.Example.Ability a() { return a(new MyGame.Example.Ability()); }
  public MyGame.Example.Ability a(MyGame.Example.Ability obj) { return obj.__assign(bb_pos + 0, bb); }
  public MyGame.Example.Test b() { return b(new MyGame.Example.Test()); }
  public MyGame.Example.Test b(MyGame.Example.Test obj) { return obj.__assign(bb_pos + 8, bb); }
  public MyGame.Example.Ability c() { return c(new MyGame.Example.Ability()); }
  public MyGame.Example.Ability c(MyGame.Example.Ability obj) { return obj.__assign(bb_pos + 12, bb); }

  public static int createStructOfStructs(FlatBufferBuilder builder, long a_id, long a_distance, short b_a, byte b_b, long c_id, long c_distance) {
    builder.prep(4, 20);
    builder.prep(4, 8);
    builder.putInt((int) c_distance);
    builder.putInt((int) c_id);
    builder.prep(2, 4);
    builder.pad(1);
    builder.putByte(b_b);
    builder.putShort(b_a);
    builder.prep(4, 8);
    builder.putInt((int) a_distance);
    builder.putInt((int) a_id);
    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 StructOfStructs get(int j) { return get(new StructOfStructs(), j); }
    public StructOfStructs get(StructOfStructs obj, int j) {  return obj.__assign(__element(j), bb); }
  }
  public StructOfStructsT unpack() {
    StructOfStructsT _o = new StructOfStructsT();
    unpackTo(_o);
    return _o;
  }
  public void unpackTo(StructOfStructsT _o) {
    a().unpackTo(_o.getA());
    b().unpackTo(_o.getB());
    c().unpackTo(_o.getC());
  }
  public static int pack(FlatBufferBuilder builder, StructOfStructsT _o) {
    if (_o == null) return 0;
    int _a_id = (int) _o.getA().getId();
    int _a_distance = (int) _o.getA().getDistance();
    short _b_a = _o.getB().getA();
    byte _b_b = _o.getB().getB();
    int _c_id = (int) _o.getC().getId();
    int _c_distance = (int) _o.getC().getDistance();
    return createStructOfStructs(
      builder,
      _a_id,
      _a_distance,
      _b_a,
      _b_b,
      _c_id,
      _c_distance);
  }
}

