# automatically generated by the FlatBuffers compiler, do not modify

# namespace: MyGame

import flatbuffers
from flatbuffers.compat import import_numpy
from typing import Any
from typing import Iterable
np = import_numpy()

class MonsterExtra(object):
    __slots__ = ['_tab']

    @classmethod
    def GetRootAs(cls, buf, offset: int = 0):
        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
        x = MonsterExtra()
        x.Init(buf, n + offset)
        return x

    @classmethod
    def GetRootAsMonsterExtra(cls, buf, offset=0):
        """This method is deprecated. Please switch to GetRootAs."""
        return cls.GetRootAs(buf, offset)
    @classmethod
    def MonsterExtraBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
        return flatbuffers.util.BufferHasIdentifier(buf, offset, b"\x4D\x4F\x4E\x45", size_prefixed=size_prefixed)

    # MonsterExtra
    def Init(self, buf: bytes, pos: int):
        self._tab = flatbuffers.table.Table(buf, pos)

    # MonsterExtra
    def D0(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
        if o != 0:
            return self._tab.Get(flatbuffers.number_types.Float64Flags, o + self._tab.Pos)
        return float('nan')

    # MonsterExtra
    def D1(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
        if o != 0:
            return self._tab.Get(flatbuffers.number_types.Float64Flags, o + self._tab.Pos)
        return float('nan')

    # MonsterExtra
    def D2(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
        if o != 0:
            return self._tab.Get(flatbuffers.number_types.Float64Flags, o + self._tab.Pos)
        return float('inf')

    # MonsterExtra
    def D3(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
        if o != 0:
            return self._tab.Get(flatbuffers.number_types.Float64Flags, o + self._tab.Pos)
        return float('-inf')

    # MonsterExtra
    def F0(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
        if o != 0:
            return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos)
        return float('nan')

    # MonsterExtra
    def F1(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
        if o != 0:
            return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos)
        return float('nan')

    # MonsterExtra
    def F2(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(16))
        if o != 0:
            return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos)
        return float('inf')

    # MonsterExtra
    def F3(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(18))
        if o != 0:
            return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos)
        return float('-inf')

    # MonsterExtra
    def Dvec(self, j: int):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(20))
        if o != 0:
            a = self._tab.Vector(o)
            return self._tab.Get(flatbuffers.number_types.Float64Flags, a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 8))
        return 0

    # MonsterExtra
    def DvecAsNumpy(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(20))
        if o != 0:
            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Float64Flags, o)
        return 0

    # MonsterExtra
    def DvecLength(self) -> int:
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(20))
        if o != 0:
            return self._tab.VectorLen(o)
        return 0

    # MonsterExtra
    def DvecIsNone(self) -> bool:
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(20))
        return o == 0

    # MonsterExtra
    def Fvec(self, j: int):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(22))
        if o != 0:
            a = self._tab.Vector(o)
            return self._tab.Get(flatbuffers.number_types.Float32Flags, a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 4))
        return 0

    # MonsterExtra
    def FvecAsNumpy(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(22))
        if o != 0:
            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Float32Flags, o)
        return 0

    # MonsterExtra
    def FvecLength(self) -> int:
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(22))
        if o != 0:
            return self._tab.VectorLen(o)
        return 0

    # MonsterExtra
    def FvecIsNone(self) -> bool:
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(22))
        return o == 0

def MonsterExtraStart(builder: flatbuffers.Builder):
    builder.StartObject(11)

def Start(builder: flatbuffers.Builder):
    MonsterExtraStart(builder)

def MonsterExtraAddD0(builder: flatbuffers.Builder, d0: float):
    builder.PrependFloat64Slot(0, d0, float('nan'))

def AddD0(builder: flatbuffers.Builder, d0: float):
    MonsterExtraAddD0(builder, d0)

def MonsterExtraAddD1(builder: flatbuffers.Builder, d1: float):
    builder.PrependFloat64Slot(1, d1, float('nan'))

def AddD1(builder: flatbuffers.Builder, d1: float):
    MonsterExtraAddD1(builder, d1)

def MonsterExtraAddD2(builder: flatbuffers.Builder, d2: float):
    builder.PrependFloat64Slot(2, d2, float('inf'))

def AddD2(builder: flatbuffers.Builder, d2: float):
    MonsterExtraAddD2(builder, d2)

def MonsterExtraAddD3(builder: flatbuffers.Builder, d3: float):
    builder.PrependFloat64Slot(3, d3, float('-inf'))

def AddD3(builder: flatbuffers.Builder, d3: float):
    MonsterExtraAddD3(builder, d3)

def MonsterExtraAddF0(builder: flatbuffers.Builder, f0: float):
    builder.PrependFloat32Slot(4, f0, float('nan'))

def AddF0(builder: flatbuffers.Builder, f0: float):
    MonsterExtraAddF0(builder, f0)

def MonsterExtraAddF1(builder: flatbuffers.Builder, f1: float):
    builder.PrependFloat32Slot(5, f1, float('nan'))

def AddF1(builder: flatbuffers.Builder, f1: float):
    MonsterExtraAddF1(builder, f1)

def MonsterExtraAddF2(builder: flatbuffers.Builder, f2: float):
    builder.PrependFloat32Slot(6, f2, float('inf'))

def AddF2(builder: flatbuffers.Builder, f2: float):
    MonsterExtraAddF2(builder, f2)

def MonsterExtraAddF3(builder: flatbuffers.Builder, f3: float):
    builder.PrependFloat32Slot(7, f3, float('-inf'))

def AddF3(builder: flatbuffers.Builder, f3: float):
    MonsterExtraAddF3(builder, f3)

def MonsterExtraAddDvec(builder: flatbuffers.Builder, dvec: int):
    builder.PrependUOffsetTRelativeSlot(8, flatbuffers.number_types.UOffsetTFlags.py_type(dvec), 0)

def AddDvec(builder: flatbuffers.Builder, dvec: int):
    MonsterExtraAddDvec(builder, dvec)

def MonsterExtraStartDvecVector(builder, numElems: int) -> int:
    return builder.StartVector(8, numElems, 8)

def StartDvecVector(builder, numElems: int) -> int:
    return MonsterExtraStartDvecVector(builder, numElems)

def MonsterExtraCreateDvecVector(builder: flatbuffers.Builder, data: Iterable[Any]) -> int:
    data = list(data)
    builder.StartVector(8, len(data), 8)
    for item in reversed(data):
        builder.PrependFloat64(item)
    return builder.EndVector()

def CreateDvecVector(builder: flatbuffers.Builder, data: Iterable[Any]) -> int:
    return MonsterExtraCreateDvecVector(builder, data)

def MonsterExtraAddFvec(builder: flatbuffers.Builder, fvec: int):
    builder.PrependUOffsetTRelativeSlot(9, flatbuffers.number_types.UOffsetTFlags.py_type(fvec), 0)

def AddFvec(builder: flatbuffers.Builder, fvec: int):
    MonsterExtraAddFvec(builder, fvec)

def MonsterExtraStartFvecVector(builder, numElems: int) -> int:
    return builder.StartVector(4, numElems, 4)

def StartFvecVector(builder, numElems: int) -> int:
    return MonsterExtraStartFvecVector(builder, numElems)

def MonsterExtraCreateFvecVector(builder: flatbuffers.Builder, data: Iterable[Any]) -> int:
    data = list(data)
    builder.StartVector(4, len(data), 4)
    for item in reversed(data):
        builder.PrependFloat32(item)
    return builder.EndVector()

def CreateFvecVector(builder: flatbuffers.Builder, data: Iterable[Any]) -> int:
    return MonsterExtraCreateFvecVector(builder, data)

def MonsterExtraEnd(builder: flatbuffers.Builder) -> int:
    return builder.EndObject()

def End(builder: flatbuffers.Builder) -> int:
    return MonsterExtraEnd(builder)

try:
    from typing import List
except:
    pass

class MonsterExtraT(object):

    # MonsterExtraT
    def __init__(
        self,
        d0 = float('nan'),
        d1 = float('nan'),
        d2 = float('inf'),
        d3 = float('-inf'),
        f0 = float('nan'),
        f1 = float('nan'),
        f2 = float('inf'),
        f3 = float('-inf'),
        dvec = None,
        fvec = None,
    ):
        self.d0 = d0  # type: float
        self.d1 = d1  # type: float
        self.d2 = d2  # type: float
        self.d3 = d3  # type: float
        self.f0 = f0  # type: float
        self.f1 = f1  # type: float
        self.f2 = f2  # type: float
        self.f3 = f3  # type: float
        self.dvec = dvec  # type: Optional[List[float]]
        self.fvec = fvec  # type: Optional[List[float]]

    @classmethod
    def InitFromBuf(cls, buf, pos):
        monsterExtra = MonsterExtra()
        monsterExtra.Init(buf, pos)
        return cls.InitFromObj(monsterExtra)

    @classmethod
    def InitFromPackedBuf(cls, buf, pos=0):
        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
        return cls.InitFromBuf(buf, pos+n)

    @classmethod
    def InitFromObj(cls, monsterExtra):
        x = MonsterExtraT()
        x._UnPack(monsterExtra)
        return x

    def __eq__(self, other):
        return type(self) == type(other) and \
            self.d0 == other.d0 and \
            self.d1 == other.d1 and \
            self.d2 == other.d2 and \
            self.d3 == other.d3 and \
            self.f0 == other.f0 and \
            self.f1 == other.f1 and \
            self.f2 == other.f2 and \
            self.f3 == other.f3 and \
            np.array_equal(self.dvec, other.dvec) and \
            np.array_equal(self.fvec, other.fvec)

    # MonsterExtraT
    def _UnPack(self, monsterExtra):
        if monsterExtra is None:
            return
        self.d0 = monsterExtra.D0()
        self.d1 = monsterExtra.D1()
        self.d2 = monsterExtra.D2()
        self.d3 = monsterExtra.D3()
        self.f0 = monsterExtra.F0()
        self.f1 = monsterExtra.F1()
        self.f2 = monsterExtra.F2()
        self.f3 = monsterExtra.F3()
        if not monsterExtra.DvecIsNone():
            if np is None:
                self.dvec = []
                for i in range(monsterExtra.DvecLength()):
                    self.dvec.append(monsterExtra.Dvec(i))
            else:
                self.dvec = monsterExtra.DvecAsNumpy()
        if not monsterExtra.FvecIsNone():
            if np is None:
                self.fvec = []
                for i in range(monsterExtra.FvecLength()):
                    self.fvec.append(monsterExtra.Fvec(i))
            else:
                self.fvec = monsterExtra.FvecAsNumpy()

    # MonsterExtraT
    def Pack(self, builder):
        if self.dvec is not None:
            if np is not None and type(self.dvec) is np.ndarray:
                dvec = builder.CreateNumpyVector(self.dvec)
            else:
                MonsterExtraStartDvecVector(builder, len(self.dvec))
                for i in reversed(range(len(self.dvec))):
                    builder.PrependFloat64(self.dvec[i])
                dvec = builder.EndVector()
        if self.fvec is not None:
            if np is not None and type(self.fvec) is np.ndarray:
                fvec = builder.CreateNumpyVector(self.fvec)
            else:
                MonsterExtraStartFvecVector(builder, len(self.fvec))
                for i in reversed(range(len(self.fvec))):
                    builder.PrependFloat32(self.fvec[i])
                fvec = builder.EndVector()
        MonsterExtraStart(builder)
        MonsterExtraAddD0(builder, self.d0)
        MonsterExtraAddD1(builder, self.d1)
        MonsterExtraAddD2(builder, self.d2)
        MonsterExtraAddD3(builder, self.d3)
        MonsterExtraAddF0(builder, self.f0)
        MonsterExtraAddF1(builder, self.f1)
        MonsterExtraAddF2(builder, self.f2)
        MonsterExtraAddF3(builder, self.f3)
        if self.dvec is not None:
            MonsterExtraAddDvec(builder, dvec)
        if self.fvec is not None:
            MonsterExtraAddFvec(builder, fvec)
        monsterExtra = MonsterExtraEnd(builder)
        return monsterExtra
