|
|
|
@@ -39,7 +39,12 @@ public class BlockEntityBehaviorRoamingBees(BlockEntity blockEntity) : BlockEnti
|
|
|
|
|
|
|
|
|
|
|
|
private ClimateCondition? climate;
|
|
|
|
private ClimateCondition? climate;
|
|
|
|
private Vec3d? windVec;
|
|
|
|
private Vec3d? windVec;
|
|
|
|
private readonly Stopwatch stopwatch = new();
|
|
|
|
private int onParticleTickStopwatchTriggerCount;
|
|
|
|
|
|
|
|
private int spawnStopwatchTriggerCount;
|
|
|
|
|
|
|
|
private readonly Stopwatch plantInfoStopwatch = new();
|
|
|
|
|
|
|
|
private readonly Stopwatch particleStopwatch = new();
|
|
|
|
|
|
|
|
private readonly Stopwatch serverSpawnStopwatch = new();
|
|
|
|
|
|
|
|
private readonly Stopwatch handleSpawnStopwatch = new();
|
|
|
|
private readonly List<StructVec3i> flowerPositions = [];
|
|
|
|
private readonly List<StructVec3i> flowerPositions = [];
|
|
|
|
private readonly List<StructVec3i> cropPositions = [];
|
|
|
|
private readonly List<StructVec3i> cropPositions = [];
|
|
|
|
private readonly List<Vector3> relativePlantPositions = [];
|
|
|
|
private readonly List<Vector3> relativePlantPositions = [];
|
|
|
|
@@ -47,7 +52,6 @@ public class BlockEntityBehaviorRoamingBees(BlockEntity blockEntity) : BlockEnti
|
|
|
|
public const string TARGET_BEE_PARTICLE_COUNT_ATTRIBUTE = "roamingbees_targetBeeParticleCount";
|
|
|
|
public const string TARGET_BEE_PARTICLE_COUNT_ATTRIBUTE = "roamingbees_targetBeeParticleCount";
|
|
|
|
public const string RADIUS_ATTRIBUTE = "roamingbees_radius";
|
|
|
|
public const string RADIUS_ATTRIBUTE = "roamingbees_radius";
|
|
|
|
public const string NETWORK_CHANNEL_NAME = "bee particle spawns";
|
|
|
|
public const string NETWORK_CHANNEL_NAME = "bee particle spawns";
|
|
|
|
public const int SERVER_TICK_FREQUENCY_DECREASE = 50;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public int ActiveBeesCount => activeBees.Count;
|
|
|
|
public int ActiveBeesCount => activeBees.Count;
|
|
|
|
public IEnumerable<BeeSpawnPacket> ActiveBeesPackets => activeBees.Select(x => x.SpawnPacket);
|
|
|
|
public IEnumerable<BeeSpawnPacket> ActiveBeesPackets => activeBees.Select(x => x.SpawnPacket);
|
|
|
|
@@ -85,10 +89,25 @@ public class BlockEntityBehaviorRoamingBees(BlockEntity blockEntity) : BlockEnti
|
|
|
|
plantPositionRegistry?.RegisterBeehive(Blockentity.Pos, radius);
|
|
|
|
plantPositionRegistry?.RegisterBeehive(Blockentity.Pos, radius);
|
|
|
|
|
|
|
|
|
|
|
|
var updateFrequency = 20;
|
|
|
|
var updateFrequency = 20;
|
|
|
|
if (api.Side == EnumAppSide.Server)
|
|
|
|
|
|
|
|
updateFrequency *= SERVER_TICK_FREQUENCY_DECREASE;
|
|
|
|
|
|
|
|
Blockentity.RegisterGameTickListener(OnParticleTick, updateFrequency);
|
|
|
|
Blockentity.RegisterGameTickListener(OnParticleTick, updateFrequency);
|
|
|
|
Blockentity.RegisterGameTickListener(UpdateClimateInfo, 10000);
|
|
|
|
Blockentity.RegisterGameTickListener(UpdateClimateInfo, 10000);
|
|
|
|
|
|
|
|
Blockentity.RegisterGameTickListener(DecreaseStopwatchCounts, 60000);
|
|
|
|
|
|
|
|
if (api.Side.IsServer())
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
Blockentity.RegisterGameTickListener(OnSpawnTick, 500);
|
|
|
|
|
|
|
|
Blockentity.RegisterGameTickListener(OnUpdatePlantInfoTick, 5000);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void DecreaseStopwatchCounts(float dt)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (spawnStopwatchTriggerCount > 10)
|
|
|
|
|
|
|
|
modSystem?.Mod.Logger.Warning($"{nameof(spawnStopwatchTriggerCount)} is {spawnStopwatchTriggerCount}");
|
|
|
|
|
|
|
|
spawnStopwatchTriggerCount = Math.Max(0, spawnStopwatchTriggerCount - 1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (onParticleTickStopwatchTriggerCount > 10)
|
|
|
|
|
|
|
|
modSystem?.Mod.Logger.Warning($"{nameof(onParticleTickStopwatchTriggerCount)} is {onParticleTickStopwatchTriggerCount}");
|
|
|
|
|
|
|
|
onParticleTickStopwatchTriggerCount = Math.Max(0, onParticleTickStopwatchTriggerCount - 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void UpdateClimateInfo(float dt)
|
|
|
|
private void UpdateClimateInfo(float dt)
|
|
|
|
@@ -150,7 +169,7 @@ public class BlockEntityBehaviorRoamingBees(BlockEntity blockEntity) : BlockEnti
|
|
|
|
|
|
|
|
|
|
|
|
public void HandleBeeParticleSpawn(BeeSpawnPacket packet, bool catchup = false)
|
|
|
|
public void HandleBeeParticleSpawn(BeeSpawnPacket packet, bool catchup = false)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
stopwatch.Restart();
|
|
|
|
handleSpawnStopwatch.Restart();
|
|
|
|
if (Blockentity.Pos != packet.HivePosition)
|
|
|
|
if (Blockentity.Pos != packet.HivePosition)
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
@@ -189,7 +208,7 @@ public class BlockEntityBehaviorRoamingBees(BlockEntity blockEntity) : BlockEnti
|
|
|
|
for (var i = 0; i < totalDelta / 0.1f; i++)
|
|
|
|
for (var i = 0; i < totalDelta / 0.1f; i++)
|
|
|
|
bee.Step(0.1f, 0.1f); // todo
|
|
|
|
bee.Step(0.1f, 0.1f); // todo
|
|
|
|
}
|
|
|
|
}
|
|
|
|
stopwatch.StopAndLogTime(this, 0.05);
|
|
|
|
handleSpawnStopwatch.StopAndLogTime(this, 0.05);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void Clear()
|
|
|
|
public void Clear()
|
|
|
|
@@ -204,12 +223,22 @@ public class BlockEntityBehaviorRoamingBees(BlockEntity blockEntity) : BlockEnti
|
|
|
|
activeBees.Clear();
|
|
|
|
activeBees.Clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void OnParticleTick(float dt)
|
|
|
|
private void OnUpdatePlantInfoTick(float dt)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (Block is BlockSkep && !Config.Instance.EnableOnVanillaSkeps)
|
|
|
|
if (!ShouldTick())
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
stopwatch.Restart();
|
|
|
|
plantInfoStopwatch.Restart();
|
|
|
|
|
|
|
|
UpdatePlantInfo();
|
|
|
|
|
|
|
|
var note = $"global bees: {modSystem?.GlobalActiveBees}, registered hives: {modSystem?.BeeSpawnPacketDistributor?.SpawnHandlersCount}, radius: {Config.Instance.BeeRoamingRadius}";
|
|
|
|
|
|
|
|
plantInfoStopwatch.StopAndLogTime(this, 0.1, note);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private bool ShouldTick()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (Block is BlockSkep && !Config.Instance.EnableOnVanillaSkeps)
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
var isFgc = Block?.Code?.Domain == "fromgoldencombs";
|
|
|
|
var isFgc = Block?.Code?.Domain == "fromgoldencombs";
|
|
|
|
var path = Block?.Code?.Path ?? string.Empty;
|
|
|
|
var path = Block?.Code?.Path ?? string.Empty;
|
|
|
|
var isFgcLangstroth = isFgc && path.Contains("langstrothstack", StringComparison.OrdinalIgnoreCase);
|
|
|
|
var isFgcLangstroth = isFgc && path.Contains("langstrothstack", StringComparison.OrdinalIgnoreCase);
|
|
|
|
@@ -218,22 +247,37 @@ public class BlockEntityBehaviorRoamingBees(BlockEntity blockEntity) : BlockEnti
|
|
|
|
if (isFgcLangstroth)
|
|
|
|
if (isFgcLangstroth)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (!Config.Instance.EnableOnFgcLangstroth)
|
|
|
|
if (!Config.Instance.EnableOnFgcLangstroth)
|
|
|
|
return;
|
|
|
|
return false;
|
|
|
|
if (!HasRequiredLangstrothBase())
|
|
|
|
if (!HasRequiredLangstrothBase())
|
|
|
|
return;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (isFgcCeramic && !Config.Instance.EnableOnFgcCeramic)
|
|
|
|
if (isFgcCeramic && !Config.Instance.EnableOnFgcCeramic)
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void OnParticleTick(float dt)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (!ShouldTick())
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var isFgc = Block?.Code?.Domain == "fromgoldencombs";
|
|
|
|
|
|
|
|
var path = Block?.Code?.Path ?? string.Empty;
|
|
|
|
|
|
|
|
var isFgcLangstroth = isFgc && path.Contains("langstrothstack", StringComparison.OrdinalIgnoreCase);
|
|
|
|
|
|
|
|
var isFgcCeramic = isFgc && path.Contains("ceramicbroodpot", StringComparison.OrdinalIgnoreCase);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
particleStopwatch.Restart();
|
|
|
|
|
|
|
|
|
|
|
|
entityAttributeSnapshot.Clear();
|
|
|
|
entityAttributeSnapshot.Clear();
|
|
|
|
Blockentity.ToTreeAttributes(entityAttributeSnapshot);
|
|
|
|
Blockentity.ToTreeAttributes(entityAttributeSnapshot);
|
|
|
|
|
|
|
|
|
|
|
|
var targetBeeParticleCount = GetTargetBeeParticleCountFromBlockEntity();
|
|
|
|
var targetBeeParticleCount = GetTargetBeeParticleCountFromBlockEntity();
|
|
|
|
if (targetBeeParticleCount <= 0)
|
|
|
|
TargetParticleCount = Math.Max(0, targetBeeParticleCount);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (TargetParticleCount <= 0)
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
TargetParticleCount = Math.Max(0, targetBeeParticleCount);
|
|
|
|
|
|
|
|
if (Block is BlockSkep)
|
|
|
|
if (Block is BlockSkep)
|
|
|
|
TargetParticleCount = Config.Instance.RoamingBeesPerVanillaSkep;
|
|
|
|
TargetParticleCount = Config.Instance.RoamingBeesPerVanillaSkep;
|
|
|
|
if (isFgcLangstroth)
|
|
|
|
if (isFgcLangstroth)
|
|
|
|
@@ -241,14 +285,9 @@ public class BlockEntityBehaviorRoamingBees(BlockEntity blockEntity) : BlockEnti
|
|
|
|
if (isFgcCeramic)
|
|
|
|
if (isFgcCeramic)
|
|
|
|
TargetParticleCount = Config.Instance.RoamingBeesPerFgcCeramic;
|
|
|
|
TargetParticleCount = Config.Instance.RoamingBeesPerFgcCeramic;
|
|
|
|
|
|
|
|
|
|
|
|
if (Api.Side == EnumAppSide.Server)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
UpdatePlantInfo();
|
|
|
|
|
|
|
|
stopwatch.LogTime(this, 0.05, "after UpdatePlantInfo");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Update(dt);
|
|
|
|
Update(dt);
|
|
|
|
stopwatch.StopAndLogTime(this, 0.05);
|
|
|
|
if (particleStopwatch.StopAndLogTime(this, 0.1, note: $"global bees: {modSystem?.GlobalActiveBees}, registered hives: {modSystem?.BeeSpawnPacketDistributor?.SpawnHandlersCount}"))
|
|
|
|
|
|
|
|
onParticleTickStopwatchTriggerCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void Update(float dt)
|
|
|
|
private void Update(float dt)
|
|
|
|
@@ -265,7 +304,10 @@ public class BlockEntityBehaviorRoamingBees(BlockEntity blockEntity) : BlockEnti
|
|
|
|
temperature = climate?.Temperature ?? 20f;
|
|
|
|
temperature = climate?.Temperature ?? 20f;
|
|
|
|
|
|
|
|
|
|
|
|
// iterate from end to easily remove from list
|
|
|
|
// iterate from end to easily remove from list
|
|
|
|
for (int i = activeBees.Count - 1; i >= 0; i--)
|
|
|
|
var end = activeBees.Count - 1;
|
|
|
|
|
|
|
|
end -= onParticleTickStopwatchTriggerCount * 10;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = end; i >= 0; i--)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
var bee = activeBees[i];
|
|
|
|
var bee = activeBees[i];
|
|
|
|
|
|
|
|
|
|
|
|
@@ -276,10 +318,7 @@ public class BlockEntityBehaviorRoamingBees(BlockEntity blockEntity) : BlockEnti
|
|
|
|
BeeVisualParticleRenderer.Spawn(clientWorld, Blockentity.Pos, bee);
|
|
|
|
BeeVisualParticleRenderer.Spawn(clientWorld, Blockentity.Pos, bee);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (Api.Side == EnumAppSide.Server)
|
|
|
|
if (Api.Side == EnumAppSide.Server)
|
|
|
|
{
|
|
|
|
bee.Step(dt, windSpeed);
|
|
|
|
for (var j = 0; j < SERVER_TICK_FREQUENCY_DECREASE; j++)
|
|
|
|
|
|
|
|
bee.Step(dt / SERVER_TICK_FREQUENCY_DECREASE, windSpeed);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (bee.ShouldBeDespawned && modSystem != null)
|
|
|
|
if (bee.ShouldBeDespawned && modSystem != null)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
@@ -289,12 +328,28 @@ public class BlockEntityBehaviorRoamingBees(BlockEntity blockEntity) : BlockEnti
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TimeSinceLastSpawn += dt;
|
|
|
|
TimeSinceLastSpawn += dt;
|
|
|
|
if (Api.Side == EnumAppSide.Server)
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void OnSpawnTick(float dt)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (!ShouldTick())
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (climate is null || windVec is null)
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
serverSpawnStopwatch.Restart();
|
|
|
|
TrySpawnNewBee(TargetParticleCount);
|
|
|
|
TrySpawnNewBee(TargetParticleCount);
|
|
|
|
|
|
|
|
if (serverSpawnStopwatch.StopAndLogTime(this, 0.1))
|
|
|
|
|
|
|
|
spawnStopwatchTriggerCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void TrySpawnNewBee(int targetParticleCount)
|
|
|
|
private void TrySpawnNewBee(int targetParticleCount)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
int desiredParticleCount = targetParticleCount;
|
|
|
|
|
|
|
|
if (activeBees.Count >= desiredParticleCount)
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
if (TimeSinceLastSpawn < spawn_cooldown_seconds)
|
|
|
|
if (TimeSinceLastSpawn < spawn_cooldown_seconds)
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
@@ -305,7 +360,7 @@ public class BlockEntityBehaviorRoamingBees(BlockEntity blockEntity) : BlockEnti
|
|
|
|
|
|
|
|
|
|
|
|
var sunPos = Api.World.Calendar.GetSunPosition(new Vec3d(Blockentity.Pos.X, Blockentity.Pos.Y, Blockentity.Pos.Z), Api.World.Calendar.TotalDays);
|
|
|
|
var sunPos = Api.World.Calendar.GetSunPosition(new Vec3d(Blockentity.Pos.X, Blockentity.Pos.Y, Blockentity.Pos.Z), Api.World.Calendar.TotalDays);
|
|
|
|
float sunAltitudeDegrees = MathF.Asin(sunPos.Y) * 180f / GameMath.PI;
|
|
|
|
float sunAltitudeDegrees = MathF.Asin(sunPos.Y) * 180f / GameMath.PI;
|
|
|
|
if (sunPos.Y <= cfg.SunAltitudeMinDegrees)
|
|
|
|
if (sunAltitudeDegrees <= cfg.SunAltitudeMinDegrees)
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
if (rainfall >= cfg.RainfallSpawnStopThreshold)
|
|
|
|
if (rainfall >= cfg.RainfallSpawnStopThreshold)
|
|
|
|
@@ -318,10 +373,6 @@ public class BlockEntityBehaviorRoamingBees(BlockEntity blockEntity) : BlockEnti
|
|
|
|
if (modSystem.GlobalActiveBees >= maxGlobal)
|
|
|
|
if (modSystem.GlobalActiveBees >= maxGlobal)
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
int desiredParticleCount = targetParticleCount;
|
|
|
|
|
|
|
|
if (activeBees.Count >= desiredParticleCount)
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
float sunAltitudeModifier = 1 - Math.Clamp((sunAltitudeDegrees - cfg.SunAltitudeMinDegrees) / cfg.SunAltitudeRangeDegrees, 0f, 1f);
|
|
|
|
float sunAltitudeModifier = 1 - Math.Clamp((sunAltitudeDegrees - cfg.SunAltitudeMinDegrees) / cfg.SunAltitudeRangeDegrees, 0f, 1f);
|
|
|
|
float sunAltitudeCooldownPenalty = sunAltitudeModifier * cfg.MaxSunAltitudeCooldownPenalty;
|
|
|
|
float sunAltitudeCooldownPenalty = sunAltitudeModifier * cfg.MaxSunAltitudeCooldownPenalty;
|
|
|
|
|
|
|
|
|
|
|
|
|