public void InitializeArrays()
{
// If initialising on fresh creation, both arrays will be null (otherwise fruitPoints was already initialised in FromTreeAttributes)
if (fruitPoints == null)
{
// This code path is called on block placement (i.e. when previous stage crop grows to final stage)
// This initialises each fruit point with a different germination time
// (if called after FromTreeAttributes, fruitPoints will already have been populated, and GetGerminationDate() will be called in the next CheckForGrowth() call instead)
fruitPoints = new FruitData[positionsCount];
int randomSelector = Math.Abs(this.Blockentity.Pos.GetHashCode()) % fruitCodeBases.Length;
for (int i = 0; i < positionsCount; i++)
{
int fruitVariant = i;
if (i >= fruitCodeBases.Length) fruitVariant = randomSelector++ % fruitCodeBases.Length;
fruitPoints[i] = new FruitData(fruitVariant, GetGerminationDate(), this, null);
}
}
positions = new Vec3d[positionsCount];
Vec3f temp = new Vec3f();
float[] matrix = null;
if (Blockentity.Block.RandomizeRotations)
{
// For performance, only call the hash function once per blockEntity loaded
int randomSelector = GameMath.MurmurHash3(-Blockentity.Pos.X, Blockentity.Block.RandomizeAxes == EnumRandomizeAxes.XYZ ? Blockentity.Pos.Y : 0, Blockentity.Pos.Z);
matrix = randomRotMatrices[GameMath.Mod(randomSelector, randomRotations.Length)];
}
for (int i = 0; i < positionsCount; i++)
{
if (Api.Side == EnumAppSide.Client)
{
positions[i] = new Vec3d(points[i * 3], points[i * 3 + 1], points[i * 3 + 2]);
if (matrix != null)
{
Mat4f.MulWithVec3_Position(matrix, (float)positions[i].X, (float)positions[i].Y, (float)positions[i].Z, temp);
positions[i].X = temp.X;
positions[i].Y = temp.Y;
positions[i].Z = temp.Z;
}
}
else
{
positions[i] = new Vec3d((i + 1) / positionsCount, (i + 1) / positionsCount, (i + 1) / positionsCount); //dummy vector for serverside - exact positions don't matter because they won't be rendered
}
positions[i].Add(Blockentity.Pos);
}
}