// 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.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);
  }
}

