Feature: *Safe* Self-Repeatable Programmable Block (Run Queue)#365
Feature: *Safe* Self-Repeatable Programmable Block (Run Queue)#365malware-dev wants to merge 5 commits intoKeenSoftwareHouse:masterfrom malware-dev:feature-self-repeatable-programmable-block
Conversation
|
What happens if you have a single PB enqueue itself every tick and then try to run it manually? Will it run twice in a single tick or will one of the run commands be ignored? Also, how will it behave after a reload? |
|
The same thing that happens if you run the same programmable block with two timers - it's run twice within the same tick, yes. As to state management, that is still left to you. That's beyond the scope of this PR. |
|
I find the idea intriguing, I'm not sure your second example would work. But, I'd think I prefer a timer class and call delegates from that, so you can assign the time and callback instead. |
|
Can you Enqueue with a parameter? (IE, Run command) |
|
The answer is yes. I just checked, ignore me. ;) |
|
@Spartan322 Hehe no the second example won't work because I'm an idiot! There should be no while loop there. Editing the example. This one does work. As to a timer class - this is a bare-bones feature. However, you can create a timer class for yourself with this. Just let the program always enqueue itself, and use ElapsedTime to calculate how much time has elapsed since whatever starting point you want - and run whatever method you like at the given time. You still work within the required safety area, and you have a per-tick sensitive timer. There are limits as to what we are allowed to open up for the programmable block. "Real" timers, like multithreaded things, would never be merged. @joemorin73 Yes you can. |
|
I'm not talking about multi-threaded stuff, but something like Gmod's timer system would probably be fine, if you create limits for it like only so many calls per second or so. |
|
I know nothing about GMod. However here's a very simple timer example using this feature. This runs the Tick command every 3 seconds (made in about 5 minutes so don't expect perfection 😉) Timer _timer;
public int count;
void Main(string argument) {
if (_timer == null) {
_timer = new Timer(this, TimeSpan.FromSeconds(3));
_timer.Tick = () => {
Echo("TICK" + count);
count++;
};
}
_timer.Update();
}
public class Timer {
Program _program;
TimeSpan _delay;
TimeSpan _currentTime;
public Timer(Program program, TimeSpan delay) {
_program = program;
_delay = delay;
}
public Action Tick;
public void Update() {
_currentTime += _program.ElapsedTime;
if (_currentTime > _delay) {
if (Tick != null) Tick();
_currentTime = new TimeSpan();
}
_program.Me.EnqueueRun();
}
} |
|
That's a very nice feature to have. A couple of possible issues:
This script will make queue to grow limitless, which is not very nice. It'll help to have a reasonable queue size limit, like 100 items or so.
|
|
Yes, you're right. I'll add a maximum queue size. The queue must be processed every frame however, that is the entire purpose of this. However only one item in the queue is processed per frame. So if you were to enqueue 100 runs, it would take 100 frames before it is complete. I.e. still safe - it won't affect the framerate any more than if you set a timer to trigger itself now and run a PB. Or actually, less so because there is less overhead, and less synchronization messages. All this feature does is eliminate the need for the timer block. Besides, if you need more exact timing, you can easily do this using the ElapsedTime property. |
|
Take a look at my example above. |
|
@kapitanov I'm guessing you got the comment via email or something. The comment was updated several times. |
|
I have to say first, I love this option. This does open up the possibility of tasks that require more intensive operations. (IE Drones.) My only concern would be bad scripts that are improperly written and therefore too intense. They could start congesting the system since the PB is on the same thread as the game. |
|
@joemorin73 @lord-devious Yes, i have the same tougths on this PR, i love the feature but a wrong script could slow your game (unintended). and thats a power on the PB that should not exist in first place, I sugest to have a max time runing or somehing that avoids infine loops (but that not makes any sense because it is what this feature is all about). |
|
@joemorin73 yes, but this feature does not add to that. You can do exactly the same right now with a timer set to trigger itself now and running a PB. The feature introduced here will actually lessen the impact by removing the timer overhead and the synchronization messages it sends. |
|
Back in the day when i first started messing with the timerB+prog.B, it was too easy for me to break my game without knowing "why did my sim speed droped to 0.3?". I thing your PR is perfect, there is no diference betwen a TB+PB and this PB in the sense that you CAN congest your system if miss-used. That being said, and because @lord-devious has a hi.knwloge base of the guts of the PB, is there a way we can counter this behavior? Limit Runtimes per tick? Limit Run per Run? Limit Run on Sim.speed? Just some tougths. |
|
@FavioGalvis It's true. The Timer+PB can do the same effect. Not to cloud this PR with this side topic, perhaps we can open a separate issue in regards to removing the risk of the PB in the game. |
|
Is there a way to clear the queue outside the programming block? Maybe a reset queue button? |
|
Recompile the script ;) |
|
That works for me! |
|
Nice one. Now we only need a way to effectively communicate between grids and my defender drones for my mothership are a go. |
…gineers into feature-self-repeatable-programmable-block
|
To be readded later |
This is a small change with very powerful consequences. You can now have the programmable block repeat itself as you will. Even better, your state machines can enqueue themselves for repeat run only as long as they need to. This feature relies on the actions already available for the programmable block to function, but hidden.
As suggested by @kapitanov, I added a maximum queue size of 100 items. This should be more than enough I think.
Incidentally, this feature also add a Run method to hide the complicated ApplyAction way to run programmable blocks from code.
See also #367 for a related pull request.
Examples: