Tutorial request: memory updates

I would like to know which good methods do we have to update measurement. I’m writing my code outside of your interface, so I would like to see “native” names for the methods and classes, not parsed for scripts.

To create s “starting point”, I will give two examples:

1). I want to warp to a bookmark. I emulate mouseRightClick on space and need to wait while menu appears. Because I’m doing all that under virtual machine, sometimes it lags and menu appearsnot immeniatly, but only a second ot two after the click. What’s the best way to update measurement for such a changes?

2). I’m getting #Measurement#.ShipUi.SpeedLabel.Text to decide whether we are in a warp or not. I manually click “warp …” in game and want my code to wait until warp ends (e.g. wait until #Measurement#.ShipUi.SpeedLabel.Text equals to “(Warping)” and then wait until it doesn’t). What’s the best way (speaking of CPU load) to do so?

I would like to know which good methods do we have to update measurement.

The only good method to update so far is to call “Sanderling.InvalidateMeasurement”.

I’m writing my code outside of your interface, so I would like to see “native” names for the methods and classes, not parsed for scripts.

So far, there are not native names at all. As for the parsing, the names don’t get parsed for scripts, they are the same in the scripts.

To create s “starting point”, I will give two examples:

1). I want to warp to a bookmark. I emulate mouseRightClick on space and need to wait while menu appears. Because I’m doing all that under virtual machine, sometimes it lags and menu appearsnot immeniatly, but only a second ot two after the click. What’s the best way to update measurement for such a changes?

The best way that came to mind so far is to define a function which takes a delegate defining the condition to end the waiting and a timeout. You could use this as simple as that:

 WaitForWithTimeout(measurement => 0 < measurement?.Menu?.Length, 2000);

So this code above means wait until there is at least one menu or the two seconds have passed.

So far it is only a draft of the implementation, I have not tested it and it might need some refining:

void WaitForWithTimeout(Func<Parse.IMemoryMeasurement, bool> condition, int timeoutMilli){     var    waitStartTime = Host.GetTimeContinuousMilli();     while(!condition(Sanderling.MemoryMeasurementParsed?.Value))     {         var    waitDuration = Host.GetTimeContinuousMilli() - waitStartTime;          if(timeoutMilli < waitDuration)             break;          Sanderling.InvalidateMeasurement();     }}

The only good method to update so far is to call “Sanderling.InvalidateMeasurement”.

Should I also call sensorServerDispatcher?.InterfaceAppManager?.MeasurementTakeRequest?

The best way that came to mind so far is to define a function…

Thanks for your example! I’m wondering - how should I initialize Sanderling’s Host in me code?

Should I also call sensorServerDispatcher?.InterfaceAppManager?.MeasurementTakeRequest?

Thanks for your example! I’m wondering - how should I initialize Sanderling’s Host in me code?

Now with the last post I gained some understanding. Before I thought that you have an object implementing “Sanderling.Script.IHostToScript”

But since you mention “MeasurementTakeRequest” I now assume that you work with an instance of “BotEngine.Interface.InterfaceAppManager”.

This works different because this does not have the amenities to simplify scripting. Here you can just call “MeasurementTakeRequest” and and supply the process id and return value of “Bib3.Glob.StopwatchZaitMiliSictInt” just as shown in the sample code at https://github.com/Arcitectus/Sanderling/blob/0b73a9704c66ac14b73a0221e3b1d6caf7038b9c/src/sample/Sanderling.Sample.Read/Program.cs#L69-L71

This way you will get a new measurement with every call.

Not sure how much experience you have with the coding, so in case you are not aware you can package this call like this:

FromProcessMeasurement<IMemoryMeasurement> GetMeasurement() => GetInterfaceAppManager()?.MeasurementTake(GetProcessId(), Bib3.Glob.StopwatchZaitMiliSictInt());

And then the WaitForWithTimeout function would look more like this:

void WaitForWithTimeout(Func<IMemoryMeasurement, bool> condition, int timeoutMilli) { var waitStartTime = Bib3.Glob.StopwatchZaitMiliSictInt(); while (!condition(GetMeasurement()?.Value)) { var waitDuration = Bib3.Glob.StopwatchZaitMiliSictInt() - waitStartTime; if (timeoutMilli < waitDuration) break; } }

I’m doing it in this manner:

Mem = new Sanderling.Parse.MemoryMeasurement(sensorServerDispatcher?.InterfaceAppManager?.MeasurementTakeRequest( cfg.EveOnlineClientProcessId, Bib3.Glob.StopwatchZaitMiliSictInt())?.MemoryMeasurement?.Value);

It works fine, but very CPU-consuming.Tried to find a better way. The reason is simple: I don’t need this whole chunk of data every time. Is there any way to update precisely one object? ChatWindow, for example. I believe it shouldn’t get so much processor time to update some kilobytes of data. But I don’t know inner structure =(

I’m doing it in this manner:

Mem = new Sanderling.Parse.MemoryMeasurement(sensorServerDispatcher?.InterfaceAppManager?.MeasurementTakeRequest( cfg.EveOnlineClientProcessId, Bib3.Glob.StopwatchZaitMiliSictInt())?.MemoryMeasurement?.Value);

It works fine, but very CPU-consuming.Tried to find a better way. The reason is simple: I don’t need this whole chunk of data every time. Is there any way to update precisely one object? ChatWindow, for example. I believe it shouldn’t get so much processor time to update some kilobytes of data.

There are multiple ways to approach the CPU load problem:

This also might be the time to explain some background about the design. This was designed when I created a mission running bot. This bot almost always considers more data then just precisely one object as you describe it because it executes several tasks in parallel and adjusts priorities to react to changes in the UI. Just as an example, it always monitors whether an UI element it tries to interact with just became occluded to react to that (for example by minimizing or closing a window before continuing with another task). So for that (first) bot it would not have made that much of a difference.

Another reason for this design was to make it cheap to inspect a session report. You can navigate to point in time in the past and you will be shown a screenshot and the measurement taken at the time. This makes understanding problems way easier because you can look at the measurement object graph and see the exact data which was available to the bot at the time.

That said, it is still possible to combine this model of an interface which offers a full measurement with restricting reading to portions which are needed. Those would then probably more coarse grained like for example a complete window at a time. This would allow to have both short reading time and the benefits described above. But this surely would cost me more than 100 hours.

But I don’t know inner structure =(

Alright, you are in for some serious fun: They store primitives like int, float or bool in their own objects (as far as I can tell similar to typical CPython memory structure). An object which has such members stores named references to those members in a dictionary. So the memory reading code follows maybe a dozen pointers to read for example a single textlabel in the UI. So it works a bit different then most games. You will see this when you try the demo I mentioned above.

1 Like