Skip to content
This repository has been archived by the owner on Jan 6, 2022. It is now read-only.

Get Ore Markers in the Programmable Block #567

Open
wants to merge 26 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
2463505
finished the pull request
Oct 12, 2016
507bea4
Refined a couple names.
Oct 12, 2016
2a6f511
refined a couple names.
Oct 12, 2016
27334a6
refined a couple names.
Oct 12, 2016
79ef9a8
changed struct name in order to follow the code design rules.
Oct 12, 2016
1edb274
refined some names.
Oct 12, 2016
d424eb2
Refactored slightly to maximize performance.
Oct 12, 2016
10e04ad
Checks for null and does its job anyway.
Oct 12, 2016
95ec518
Added more information to struct MyOreMarker and added more informati…
Oct 12, 2016
855aa1d
no message
Oct 12, 2016
fd1bfde
no message
Oct 12, 2016
288ccee
no message
Oct 12, 2016
fb0c938
exposed subtypeID due to request.
Oct 13, 2016
c45256a
Deposit unpacking method now matches the visible ore markers.
Oct 19, 2016
3cbf20e
fixed a small compilation error.
Oct 22, 2016
4fb7a9c
fixed a null exception in my code.
Oct 22, 2016
cf6d8b3
Finished, Polished, Tested.
Oct 22, 2016
2ef491c
Realised I dont need to prevent access of an ore detector with no owner.
Oct 22, 2016
ffebf73
minor text change
Oct 23, 2016
75ac63c
ref makes it clear to the user how exactly they will get their ore ma…
Oct 26, 2016
16f9340
GetOreMarkers() now prevents excessively fast runs. Removed duplicate…
Dec 4, 2016
86cd578
tweaked MyOreDetectorComponent.Update() to perform exactly the same a…
Dec 4, 2016
84e8841
Made the rate the method can run at in line with simulation updates.
Dec 8, 2016
d92c5bf
Removed unnecessary ref
Pharap Mar 1, 2017
a1feff6
Removed unnecessary ref
Pharap Mar 1, 2017
c51dfcb
Merge pull request #1 from Pharap/GetOreMarkersInPB
Mar 2, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions Sources/Sandbox.Common/ModAPI/Ingame/IMyOreDetector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,30 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using VRageMath;

namespace Sandbox.ModAPI.Ingame
{
public interface IMyOreDetector : IMyFunctionalBlock
{
float Range {get;}
bool BroadcastUsingAntennas {get;}

/// <summary>
///Returns your own List filled with visible ore markers.
/// </summary>
void GetOreMarkers (ref List <MyOreMarker> outputList);
}

public struct MyOreMarker
{
public readonly string ElementName;
public readonly Vector3D Location;

public MyOreMarker (string inputElement, Vector3D inputCoords)
{
this.ElementName = inputElement;
this.Location = inputCoords;
}
}
}
64 changes: 60 additions & 4 deletions Sources/Sandbox.Game/Game/Entities/Blocks/MyOreDetector.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -24,8 +27,10 @@ namespace Sandbox.Game.Entities.Cube
public class MyOreDetector : MyFunctionalBlock, IMyComponentOwner<MyOreDetectorComponent>, IMyOreDetector
{
private MyOreDetectorDefinition m_definition;
private Dictionary <string, Vector3D> m_closestEachElement = new Dictionary <string, Vector3D>(); //I use the same collection to reduce heap allocations.

MyOreDetectorComponent m_oreDetectorComponent = new MyOreDetectorComponent();
private MyOreDetectorComponent m_oreDetectorComponent = new MyOreDetectorComponent();
int MethodCallRateCounter = 0;

Sync<bool> m_broadcastUsingAntennas;

Expand Down Expand Up @@ -154,12 +159,18 @@ public override void UpdateBeforeSimulation100()
base.UpdateBeforeSimulation100();
if (HasLocalPlayerAccess())
{
m_oreDetectorComponent.Update(PositionComp.GetPosition());
m_oreDetectorComponent.Update (PositionComp.GetPosition());
}

else
{
m_oreDetectorComponent.Clear();
}

if (MethodCallRateCounter < Stopwatch.Frequency)
{
MethodCallRateCounter++;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wouldn't ++MethodCallRateCounter be better?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Increment before viewing the number? why does it matter?

Copy link

@Pingger Pingger Dec 9, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because than no duplicate of the variable is created which would be returned at this point.

Like this:
varType incrementBeforeReturn() { var = var +1; return var; }

varType incrementAfterReturn() { varType prev = var; var = var +1; return prev; }

incrementing before before return therefore reduces memory consumption and runtime

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The compiler does this automaticly, no need to worry

}
}

bool OnCheckControl()
Expand All @@ -180,8 +191,7 @@ public float Range
{
m_oreDetectorComponent.DetectionRadius = (value / 100f) * m_definition.MaximumRange;
RaisePropertiesChanged();
}

}
}
}

Expand All @@ -203,5 +213,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 (ref List <ModAPI.Ingame.MyOreMarker> usersList) //Imprinting on the reference parameter is cheaper than a return List<T> due to heap allocations.
{
if (MethodCallRateCounter == Stopwatch.Frequency) //counter will stop so it can wait forever.
{
MethodCallRateCounter = 0;
usersList.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 <string, Vector3D> marker in m_closestEachElement)
{
usersList.Add (new ModAPI.Ingame.MyOreMarker (marker.Key, marker.Value));
}
m_closestEachElement.Clear();
}
}
}
}
69 changes: 44 additions & 25 deletions Sources/Sandbox.Game/Game/Entities/Blocks/MyOreDetectorComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,8 @@ class MyOreDetectorComponent
private static readonly List<MyVoxelBase> m_inRangeCache = new List<MyVoxelBase>();
private static readonly List<MyVoxelBase> m_notInRangeCache = new List<MyVoxelBase>();

public HashSet <MyEntityOreDeposit> DetectedDeposits { get; private set; }

public delegate bool CheckControlDelegate();

public float DetectionRadius { get; set; }
Expand All @@ -194,43 +196,50 @@ public MyOreDetectorComponent()
DetectionRadius = 50;
SetRelayedRequest = false;
BroadcastUsingAntennas = false;
DetectedDeposits = new HashSet <MyEntityOreDeposit>();
}

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();
}

{ // 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();
}
Expand All @@ -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()
Expand All @@ -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();
}

}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ public override List<MyHudEntityParams> 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;
}
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/Sandbox.Game/Game/Weapons/Guns/MyHandDrill.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down