diff --git a/Sources/Sandbox.Common/ModAPI/Ingame/IMyOreDetector.cs b/Sources/Sandbox.Common/ModAPI/Ingame/IMyOreDetector.cs
index 84b88e931..07e501b94 100644
--- a/Sources/Sandbox.Common/ModAPI/Ingame/IMyOreDetector.cs
+++ b/Sources/Sandbox.Common/ModAPI/Ingame/IMyOreDetector.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using VRageMath;
namespace Sandbox.ModAPI.Ingame
{
@@ -9,5 +10,22 @@ public interface IMyOreDetector : IMyFunctionalBlock
{
float Range {get;}
bool BroadcastUsingAntennas {get;}
+
+ ///
+ ///Returns your own List filled with visible ore markers.
+ ///
+ void GetOreMarkers (List outputList);
+ }
+
+ public struct MyOreMarker
+ {
+ public readonly string ElementName;
+ public readonly Vector3D Location;
+
+ public MyOreMarker (string inputElement, Vector3D inputCoords)
+ {
+ this.ElementName = inputElement;
+ this.Location = inputCoords;
+ }
}
}
diff --git a/Sources/Sandbox.Game/Game/Entities/Blocks/MyOreDetector.cs b/Sources/Sandbox.Game/Game/Entities/Blocks/MyOreDetector.cs
index ab3bd438d..81cf9db72 100644
--- a/Sources/Sandbox.Game/Game/Entities/Blocks/MyOreDetector.cs
+++ b/Sources/Sandbox.Game/Game/Entities/Blocks/MyOreDetector.cs
@@ -1,10 +1,13 @@
#region Using
+using System.Collections.Generic;
+
using Sandbox.Common.ObjectBuilders;
using Sandbox.Definitions;
using Sandbox.Game.Gui;
using Sandbox.Game.Multiplayer;
using System.Text;
+using System.Diagnostics;
using Sandbox.Game.EntityComponents;
using VRageMath;
using Sandbox.ModAPI;
@@ -24,13 +27,17 @@ namespace Sandbox.Game.Entities.Cube
public class MyOreDetector : MyFunctionalBlock, IMyComponentOwner, IMyOreDetector
{
private MyOreDetectorDefinition m_definition;
+ private Dictionary m_closestEachElement = new Dictionary (); //I use the same collection to reduce heap allocations.
- MyOreDetectorComponent m_oreDetectorComponent = new MyOreDetectorComponent();
+ private MyOreDetectorComponent m_oreDetectorComponent = new MyOreDetectorComponent();
+ bool getOreRateLimited;
Sync m_broadcastUsingAntennas;
public MyOreDetector()
{
+ getOreRateLimited = true;
+
#if XB1 // XB1_SYNC_NOREFLECTION
m_broadcastUsingAntennas = SyncType.CreateAndAddProp();
#endif // XB1
@@ -151,11 +158,14 @@ public override void OnUnregisteredFromGridSystems()
public override void UpdateBeforeSimulation100()
{
+ getOreRateLimited = true;
+
base.UpdateBeforeSimulation100();
if (HasLocalPlayerAccess())
{
- m_oreDetectorComponent.Update(PositionComp.GetPosition());
+ m_oreDetectorComponent.Update (PositionComp.GetPosition());
}
+
else
{
m_oreDetectorComponent.Clear();
@@ -180,8 +190,7 @@ public float Range
{
m_oreDetectorComponent.DetectionRadius = (value / 100f) * m_definition.MaximumRange;
RaisePropertiesChanged();
- }
-
+ }
}
}
@@ -203,5 +212,51 @@ public bool BroadcastUsingAntennas
bool ModAPI.Ingame.IMyOreDetector.BroadcastUsingAntennas { get { return m_oreDetectorComponent.BroadcastUsingAntennas; } }
float ModAPI.Ingame.IMyOreDetector.Range { get { return Range; } }
+
+ public void GetOreMarkers (List userList) //Imprinting on the reference parameter is cheaper than a return List due to heap allocations.
+ {
+ if (getOreRateLimited)
+ {
+ getOreRateLimited = false;
+ userList.Clear();
+ Vector3D blockCoordinates = new Vector3D (base.PositionComp.GetPosition());
+ m_oreDetectorComponent.Update (blockCoordinates, false);
+
+ foreach (MyEntityOreDeposit deposit in m_oreDetectorComponent.DetectedDeposits)
+ {
+ for (int i = 0; i < deposit.Materials.Count; i++)
+ {
+ MyEntityOreDeposit.Data depositData = deposit.Materials[i];
+ Vector3D cachesPosition = new Vector3D();
+ depositData.ComputeWorldPosition (deposit.VoxelMap, out cachesPosition);
+ string cachesElement = deposit.Materials[i].Material.MinedOre;
+
+ if (m_closestEachElement.ContainsKey (cachesElement) == false)
+ {
+ m_closestEachElement.Add (cachesElement, cachesPosition); //I decided Dictionary was the best way to group nearest markers since all I need is two variables.
+ }
+
+ else
+ {
+ Vector3D difference = blockCoordinates - cachesPosition;
+ Vector3D previousDifference = m_closestEachElement[cachesElement] - cachesPosition;
+ float distanceToCache = (float) difference.LengthSquared(); //explicitly converted in order to estimate the actual hud markers as close as possible.
+ float previousDistance = (float) previousDifference.LengthSquared();
+
+ if (distanceToCache < previousDistance)
+ {
+ m_closestEachElement[cachesElement] = cachesPosition; //I only want the nearest of each element.
+ }
+ }
+ }
+ }
+
+ foreach (KeyValuePair marker in m_closestEachElement)
+ {
+ userList.Add (new ModAPI.Ingame.MyOreMarker (marker.Key, marker.Value));
+ }
+ m_closestEachElement.Clear();
+ }
+ }
}
}
diff --git a/Sources/Sandbox.Game/Game/Entities/Blocks/MyOreDetectorComponent.cs b/Sources/Sandbox.Game/Game/Entities/Blocks/MyOreDetectorComponent.cs
index 9e60c98df..9b6d166c5 100644
--- a/Sources/Sandbox.Game/Game/Entities/Blocks/MyOreDetectorComponent.cs
+++ b/Sources/Sandbox.Game/Game/Entities/Blocks/MyOreDetectorComponent.cs
@@ -180,6 +180,8 @@ class MyOreDetectorComponent
private static readonly List m_inRangeCache = new List();
private static readonly List m_notInRangeCache = new List();
+ public HashSet DetectedDeposits { get; private set; }
+
public delegate bool CheckControlDelegate();
public float DetectionRadius { get; set; }
@@ -194,34 +196,41 @@ public MyOreDetectorComponent()
DetectionRadius = 50;
SetRelayedRequest = false;
BroadcastUsingAntennas = false;
+ DetectedDeposits = new HashSet ();
}
public bool SetRelayedRequest { get; set; }
- public void Update(Vector3D position, bool checkControl = true)
- {
- Clear();
-
- if (!SetRelayedRequest && checkControl && !OnCheckControl())
+ public void Update (Vector3D position, bool checkControl = true)
+ {
+ if (checkControl == true)
{
- m_depositGroupsByEntity.Clear();
- return;
+ Clear();
+
+ if (!SetRelayedRequest && !OnCheckControl())
+ {
+ //m_depositGroupsByEntity.Clear(); I commented this out because it, in some states, causes DetectedDeposits to ouput incorrectly as empty. m_depositGroupsByEntity seems to take more than one run to fully load.
+ return;
+ }
+ SetRelayedRequest = false;
}
- SetRelayedRequest = false;
-
- var sphere = new BoundingSphereD(position, DetectionRadius);
- MyGamePruningStructure.GetAllVoxelMapsInSphere(ref sphere, m_inRangeCache);
+ else
+ {
+ DetectedDeposits.Clear(); //Deposits needs to remove duplicates but also leave the HUD unchanged.
+ }
+ var sphere = new BoundingSphereD (position, DetectionRadius);
+ MyGamePruningStructure.GetAllVoxelMapsInSphere (ref sphere, m_inRangeCache);
{ // Find voxel maps which went out of range and then remove them.
foreach (var voxelMap in m_depositGroupsByEntity.Keys)
{
- if (!m_inRangeCache.Contains(voxelMap))
- m_notInRangeCache.Add(voxelMap);
+ if (!m_inRangeCache.Contains (voxelMap))
+ m_notInRangeCache.Add (voxelMap);
}
foreach (var notInRange in m_notInRangeCache)
{
- m_depositGroupsByEntity.Remove(notInRange);
+ m_depositGroupsByEntity.Remove (notInRange);
}
m_notInRangeCache.Clear();
}
@@ -229,8 +238,8 @@ public void Update(Vector3D position, bool checkControl = true)
{ // Add voxel maps which came into range.
foreach (var voxelMap in m_inRangeCache)
{
- if (!m_depositGroupsByEntity.ContainsKey(voxelMap))
- m_depositGroupsByEntity.Add(voxelMap, new MyOreDepositGroup(voxelMap));
+ if (!m_depositGroupsByEntity.ContainsKey (voxelMap))
+ m_depositGroupsByEntity.Add (voxelMap, new MyOreDepositGroup (voxelMap));
}
m_inRangeCache.Clear();
}
@@ -240,18 +249,26 @@ public void Update(Vector3D position, bool checkControl = true)
{
var voxelMap = entry.Key;
var group = entry.Value;
- group.UpdateDeposits(ref sphere);
+ group.UpdateDeposits (ref sphere);
foreach (var deposit in group.Deposits)
{
if (deposit != null)
- {
- MyHud.OreMarkers.RegisterMarker(deposit);
+ {
+ switch (checkControl) //the method has been divided into these two choices because previously, oremarkers could not be fetched without a radio antenna.
+ {
+ case true:
+ MyHud.OreMarkers.RegisterMarker (deposit);
+ break;
+
+ case false:
+ DetectedDeposits.Add (deposit);
+ break;
+ }
}
}
- }
-
- m_inRangeCache.Clear();
+ }
+ m_inRangeCache.Clear();
}
public void Clear()
@@ -261,11 +278,13 @@ public void Clear()
foreach (var deposit in group.Deposits)
{
if (deposit != null)
- MyHud.OreMarkers.UnregisterMarker(deposit);
+ {
+ MyHud.OreMarkers.UnregisterMarker (deposit);
+ }
}
- }
+ }
+ DetectedDeposits.Clear();
}
-
}
///
diff --git a/Sources/Sandbox.Game/Game/Entities/Blocks/MyRadioAntenna.cs b/Sources/Sandbox.Game/Game/Entities/Blocks/MyRadioAntenna.cs
index fca2e9404..daa92f557 100644
--- a/Sources/Sandbox.Game/Game/Entities/Blocks/MyRadioAntenna.cs
+++ b/Sources/Sandbox.Game/Game/Entities/Blocks/MyRadioAntenna.cs
@@ -350,7 +350,7 @@ public override List GetHudParams(bool allowBlink)
MyOreDetectorComponent oreDetector;
if (oreDetectorOwner.GetComponent(out oreDetector) && oreDetector.BroadcastUsingAntennas)
{
- oreDetector.Update(terminalBlock.PositionComp.GetPosition(), false);
+ oreDetector.Update (terminalBlock.PositionComp.GetPosition(), false);
oreDetector.SetRelayedRequest = true;
}
}
diff --git a/Sources/Sandbox.Game/Game/Weapons/Guns/MyHandDrill.cs b/Sources/Sandbox.Game/Game/Weapons/Guns/MyHandDrill.cs
index b8fcfdbf4..6599253d5 100644
--- a/Sources/Sandbox.Game/Game/Weapons/Guns/MyHandDrill.cs
+++ b/Sources/Sandbox.Game/Game/Weapons/Guns/MyHandDrill.cs
@@ -391,7 +391,7 @@ public override void UpdateBeforeSimulation100()
{
base.UpdateBeforeSimulation100();
m_drillBase.UpdateSoundEmitter();
- m_oreDetectorBase.Update(PositionComp.GetPosition());
+ m_oreDetectorBase.Update (PositionComp.GetPosition());
}
public void UpdateSoundEmitter()