diff --git a/.timetracker b/.timetracker index 09984e6..a8c1ff1 100644 --- a/.timetracker +++ b/.timetracker @@ -1,5 +1,5 @@ { - "total": 592730, + "total": 602351, "sessions": [ { "begin": "2026-01-09T17:26:02+01:00", @@ -1355,6 +1355,11 @@ "begin": "2026-03-21T01:18:07+01:00", "end": "2026-03-21T01:43:24+01:00", "duration": 1517 + }, + { + "begin": "2026-03-21T01:43:25+01:00", + "end": "2026-03-21T04:23:47+01:00", + "duration": 9621 } ] } \ No newline at end of file diff --git a/OrekiWoofsBees.Common/IPlantPositionRegistry.cs b/OrekiWoofsBees.Common/IPlantPositionRegistry.cs index 3fff757..4f9621a 100644 --- a/OrekiWoofsBees.Common/IPlantPositionRegistry.cs +++ b/OrekiWoofsBees.Common/IPlantPositionRegistry.cs @@ -24,13 +24,7 @@ public interface IPlantPositionRegistry ) GetPlantCountsNearPosition(BlockPos hivePos, int radius); - ( - IEnumerable Flowers, - IEnumerable Crops, - float InitialScanProgress, - float RescanProgress - ) - GetPlantsNearPosition(BlockPos hivePos, int radius); + (float InitialScanProgress, float RescanProgress) GetPlantsNearPosition(BlockPos hivePos, int radius, List flowerPositionsBuffer, List cropPositionsBuffer); void RegisterBeehive(BlockPos pos, int radius); diff --git a/OrekiWoofsBees.Common/PlantPositionRegistryModSystem2.cs b/OrekiWoofsBees.Common/PlantPositionRegistryModSystem2.cs index 6a4d53c..5dee948 100644 --- a/OrekiWoofsBees.Common/PlantPositionRegistryModSystem2.cs +++ b/OrekiWoofsBees.Common/PlantPositionRegistryModSystem2.cs @@ -81,26 +81,33 @@ public class PlantPositionRegistryModSystem2 : ModSystem, IPlantPositionRegistry } public ( - IEnumerable Flowers, - IEnumerable Crops, float InitialScanProgress, float RescanProgress - ) GetPlantsNearPosition(BlockPos hivePos, int radius) + ) GetPlantsNearPosition(BlockPos hivePos, int radius, List flowerPositionsBuffer, List cropPositionsBuffer) { + flowerPositionsBuffer.Clear(); + cropPositionsBuffer.Clear(); + var key = StructVec3i.FromBlockPos(hivePos); - var flowers = flowerPositions - .Where(p => Overlaps.IsWithinSphericalRadius(hivePos, p, radius)) - .Select(p => new BlockPos(p.X, p.Y, p.Z, hivePos.dimension)); + foreach (var flowerPos in flowerPositions) + { + if (!Overlaps.IsWithinSphericalRadius(hivePos, flowerPos, radius)) + continue; + flowerPositionsBuffer.Add(flowerPos); + } - var crops = cropPositions - .Where(p => Overlaps.IsWithinSphericalRadius(hivePos, p, radius)) - .Select(p => new BlockPos(p.X, p.Y, p.Z, hivePos.dimension)); + foreach (var cropPos in cropPositions) + { + if (!Overlaps.IsWithinSphericalRadius(hivePos, cropPos, radius)) + continue; + cropPositionsBuffer.Add(cropPos); + } float initialProgress = 1.0f; float rescanProgress = 0.0f; if (!beehives.TryGetValue(key, out var cursor)) - return (flowers, crops, initialProgress, rescanProgress); + return (initialProgress, rescanProgress); var table = offsetTables[cursor.Radius]; if (table.Count > 0) @@ -109,13 +116,24 @@ public class PlantPositionRegistryModSystem2 : ModSystem, IPlantPositionRegistry rescanProgress = cursor.GetRescanProgress(offsetTables); } - return (flowers, crops, initialProgress, rescanProgress); + return (initialProgress, rescanProgress); } public (int FlowerCount, int CropCount, float InitialScanProgress, float RescanProgress) GetPlantCountsNearPosition(BlockPos hivePos, int radius) { - int flowers = flowerPositions.Count(p => Overlaps.IsWithinSphericalRadius(hivePos, p, radius)); - int crops = cropPositions.Count(p => Overlaps.IsWithinSphericalRadius(hivePos, p, radius)); + int flowers = 0; + foreach (var flowerPos in flowerPositions) + { + if (Overlaps.IsWithinSphericalRadius(hivePos, flowerPos, radius)) + flowers++; + } + + int crops = 0; + foreach (var cropPos in cropPositions) + { + if (Overlaps.IsWithinSphericalRadius(hivePos, cropPos, radius)) + crops++; + } float initialProgress = 0.0f; float rescanProgress = 0.0f; diff --git a/RoamingBees/RoamingBees/Behaviors/BlockEntityBehaviorRoamingBees.cs b/RoamingBees/RoamingBees/Behaviors/BlockEntityBehaviorRoamingBees.cs index 16acb6d..d1a9a7b 100644 --- a/RoamingBees/RoamingBees/Behaviors/BlockEntityBehaviorRoamingBees.cs +++ b/RoamingBees/RoamingBees/Behaviors/BlockEntityBehaviorRoamingBees.cs @@ -36,6 +36,11 @@ public class BlockEntityBehaviorRoamingBees(BlockEntity blockEntity) : BlockEnti private float rainfall; private float temperature; private bool initialized; + + private readonly List flowerPositions = []; + private readonly List cropPositions = []; + private readonly List relativePlantPositions = []; + public const string TARGET_BEE_PARTICLE_COUNT_ATTRIBUTE = "roamingbees_targetBeeParticleCount"; public const string RADIUS_ATTRIBUTE = "roamingbees_radius"; public const string NETWORK_CHANNEL_NAME = "bee particle spawns"; @@ -214,14 +219,14 @@ public class BlockEntityBehaviorRoamingBees(BlockEntity blockEntity) : BlockEnti TargetParticleCount = Config.Instance.RoamingBeesPerFgcLangstroth; if (isFgcCeramic) TargetParticleCount = Config.Instance.RoamingBeesPerFgcCeramic; - var nearbyPlantPositions = Api.Side == EnumAppSide.Server - ? GetNearbyPlantPositions() - : []; - Update(dt, nearbyPlantPositions); + if (Api.Side == EnumAppSide.Server) + UpdatePlantInfo(); + + Update(dt); } - private void Update(float dt, IEnumerable nearbyPlantPositions) + private void Update(float dt) { if (dt > 10f) return; @@ -259,15 +264,15 @@ public class BlockEntityBehaviorRoamingBees(BlockEntity blockEntity) : BlockEnti TimeSinceLastSpawn += dt; if (Api.Side == EnumAppSide.Server) - TrySpawnNewBee(TargetParticleCount, nearbyPlantPositions); + TrySpawnNewBee(TargetParticleCount); } - private void TrySpawnNewBee(int targetParticleCount, IEnumerable nearbyPlantPositions) + private void TrySpawnNewBee(int targetParticleCount) { if (TimeSinceLastSpawn < spawn_cooldown_seconds) return; - if (!nearbyPlantPositions.Any()) + if (relativePlantPositions.Count == 0) return; var cfg = Config.Instance; @@ -312,7 +317,7 @@ public class BlockEntityBehaviorRoamingBees(BlockEntity blockEntity) : BlockEnti var facing = GetFacing(); var entrancePos = GetEntrancePosition(facing); var frontDirection = GetFrontDirection(facing); - var path = BeePathGeneration.GeneratePath(Api.World.BlockAccessor, Blockentity.Pos, entrancePos, frontDirection, nearbyPlantPositions); + var path = BeePathGeneration.GeneratePath(Api.World.BlockAccessor, Blockentity.Pos, entrancePos, frontDirection, relativePlantPositions); if (path is null || path.Length == 0) return; @@ -364,37 +369,35 @@ public class BlockEntityBehaviorRoamingBees(BlockEntity blockEntity) : BlockEnti }; } - private Vector3[] GetNearbyPlantPositions() + private void UpdatePlantInfo() { + relativePlantPositions.Clear(); + int radius = Config.Instance.BeeRoamingRadius; if (radius <= 0) { radius = entityAttributeSnapshot.GetInt(RADIUS_ATTRIBUTE, 10); if (radius <= 0) - return []; + return; } - var plantPositions = new List(); var plantRegistry = Api.GetPlantPositionRegistry(); if (plantRegistry is null) - return []; + return; - var (flowerCount, cropCount, initialScanProgress, rescanProgress) = plantRegistry.GetPlantCountsNearPosition(Blockentity.Pos, radius); - FlowerCount = flowerCount; - CropCount = cropCount; + var (initialScanProgress, rescanProgress) = plantRegistry.GetPlantsNearPosition(Blockentity.Pos, radius, flowerPositions, cropPositions); + FlowerCount = flowerPositions.Count; + CropCount = cropPositions.Count; InitialScanProgress = initialScanProgress; RescanProgress = rescanProgress; - var (flowers, crops, _, _) = plantRegistry.GetPlantsNearPosition(Blockentity.Pos, radius); - foreach (var pos in flowers.Concat(crops)) + foreach (var pos in flowerPositions.Concat(cropPositions)) { float relX = pos.X - Blockentity.Pos.X + 0.5f; float relY = pos.Y - Blockentity.Pos.Y + 0.5f; float relZ = pos.Z - Blockentity.Pos.Z + 0.5f; - plantPositions.Add(new Vector3(relX, relY, relZ)); + relativePlantPositions.Add(new Vector3(relX, relY, relZ)); } - - return [.. plantPositions]; } private Vector3 GetFrontDirection(string facing) diff --git a/RoamingBees/RoamingBees/Particles/BeePathGeneration.cs b/RoamingBees/RoamingBees/Particles/BeePathGeneration.cs index 98696ab..34960c9 100644 --- a/RoamingBees/RoamingBees/Particles/BeePathGeneration.cs +++ b/RoamingBees/RoamingBees/Particles/BeePathGeneration.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Numerics; using Vintagestory.API.Common; using Vintagestory.API.Datastructures; @@ -58,7 +57,7 @@ public static class BeePathGeneration BlockPos hiveWorldPos, Vector3 beehiveEntrancePosition, Vector3 frontDirection, - IEnumerable plantPositions) + List plantPositions) { temp_list.Clear(); temp_plants.Clear(); @@ -71,15 +70,13 @@ public static class BeePathGeneration for (var i = 0; i < plant_count; i++) { var lastPosition = temp_list.Count > 0 ? temp_list[^1].Position : GetFrontOfEntrance(beehiveEntrancePosition, frontDirection); - foreach (var plantPathPoint in PickTargetAndGeneratePathPoints(blockAccessor, hiveWorldPos, lastPosition)) - temp_list.Add(plantPathPoint); + PickTargetAndGeneratePathPoints(blockAccessor, hiveWorldPos, lastPosition); } if (temp_list.Count == 0) return []; - foreach (var returnPathPoint in GetReturnPath(blockAccessor, hiveWorldPos, temp_list.Last().Position, beehiveEntrancePosition, frontDirection)) - temp_list.Add(new BeePlannedPathPoint(returnPathPoint, true, false)); + GetReturnPath(blockAccessor, hiveWorldPos, temp_list[^1].Position, beehiveEntrancePosition, frontDirection); temp_list[^1] = temp_list[^1] with { IsSlowdown = true }; temp_list.Add(new BeePlannedPathPoint(beehiveEntrancePosition, false, true)); @@ -155,7 +152,7 @@ public static class BeePathGeneration if (containerSelectionBoxes.Length == 0) return false; - Cuboidf containerSelectionBox = containerSelectionBoxes.First(); + Cuboidf containerSelectionBox = containerSelectionBoxes[0]; var fillHeight = attributes["fillHeight"]?.AsFloat(0.5f) ?? 0.5f; var sitHeight = attributes["sitHeight"]?.AsFloat(Math.Min(0.9f, fillHeight + 0.2f)) ?? Math.Min(0.9f, fillHeight + 0.2f); @@ -189,7 +186,7 @@ public static class BeePathGeneration if (selectionBoxes.Length == 0) return false; - Cuboidf selectionBox = selectionBoxes.First(); + Cuboidf selectionBox = selectionBoxes[0]; var height = blockPlant.drawnHeight / 32f; var sitHeightAttr = attributes["sitHeight"]; if (sitHeightAttr != null) @@ -203,13 +200,13 @@ public static class BeePathGeneration return true; } - private static IEnumerable PickTargetAndGeneratePathPoints(IBlockAccessor blockAccessor, BlockPos hiveWorldPos, Vector3 lastPosition) + private static void PickTargetAndGeneratePathPoints(IBlockAccessor blockAccessor, BlockPos hiveWorldPos, Vector3 lastPosition) { for (var i = 0; i < 2; i++) { var nearby_only = i == 1; if (!TryPickPlantPosition(lastPosition, nearby_only, out var blockCenter)) - yield break; + return; var (plantOffset, plantSize) = GetPlantOffsetAndSize(blockAccessor, blockCenter, hiveWorldPos); if (plantSize is not null && plantOffset is not null) @@ -220,10 +217,9 @@ public static class BeePathGeneration { used_plants.Add(blockCenter); if (waypoint is not null) - yield return new BeePlannedPathPoint(waypoint.Value, true, false); - foreach (var plantTarget in GetPlantTargets(blockCenter, size, target)) - yield return new BeePlannedPathPoint(plantTarget, false, false); - yield break; + temp_list.Add(new BeePlannedPathPoint(waypoint.Value, true, false)); + GetPlantTargets(blockCenter, size, target); + return; } } } @@ -250,13 +246,13 @@ public static class BeePathGeneration return valid_count > 0; } - private static IEnumerable GetPlantTargets(Vector3 blockCenter, Vector3 plantSize, Vector3 firstTarget) + private static void GetPlantTargets(Vector3 blockCenter, Vector3 plantSize, Vector3 firstTarget) { - yield return firstTarget; + temp_list.Add(new BeePlannedPathPoint(firstTarget, false, false)); var total_targets = random.Next(3, 10); for (var i = 1; i < total_targets; i++) - yield return GetRandomPointInPlantBlock(blockCenter, plantSize); + temp_list.Add(new BeePlannedPathPoint(GetRandomPointInPlantBlock(blockCenter, plantSize), false, false)); } private static bool TryPickPlantTarget(IBlockAccessor blockAccessor, BlockPos hiveWorldPos, Vector3 lastPosition, Vector3 blockCenter, Vector3 plantSize, out Vector3 target, out Vector3? waypoint, bool biasUpwards = false) @@ -402,27 +398,27 @@ public static class BeePathGeneration return block.CollisionBoxes != null && block.CollisionBoxes.Length > 0; } - private static IEnumerable GetReturnPath(IBlockAccessor blockAccessor, BlockPos hiveWorldPos, Vector3 lastPosition, Vector3 beehiveEntrancePosition, Vector3 frontDirection) + private static void GetReturnPath(IBlockAccessor blockAccessor, BlockPos hiveWorldPos, Vector3 lastPosition, Vector3 beehiveEntrancePosition, Vector3 frontDirection) { var frontOfEntrance = GetFrontOfEntrance(beehiveEntrancePosition, frontDirection); var targetPos = frontOfEntrance; if (HasLineOfSight(blockAccessor, hiveWorldPos, lastPosition, targetPos)) { - yield return targetPos; - yield break; + temp_list.Add(new BeePlannedPathPoint(targetPos, true, false)); + return; } if (TryFindWaypoint(blockAccessor, hiveWorldPos, lastPosition, targetPos, out var waypoint)) { - yield return waypoint; - yield return targetPos; - yield break; + temp_list.Add(new BeePlannedPathPoint(waypoint, true, false)); + temp_list.Add(new BeePlannedPathPoint(targetPos, true, false)); + return; } - foreach (var pathPoint in temp_list.Reverse()) - yield return pathPoint.Position; + for (var i = temp_list.Count - 1; i >= 0; i--) + temp_list.Add(new BeePlannedPathPoint(temp_list[i].Position, true, false)); - yield return frontOfEntrance; + temp_list.Add(new BeePlannedPathPoint(frontOfEntrance, true, false)); } internal static Vector3 GetFrontOfEntrance(Vector3 beehiveEntrancePosition, Vector3 frontDirection)