Welcome to Keen Software House Forums! Log in or Sign up to interact with the KSH community.
  1. You are currently browsing our forum as a guest. Create your own forum account to access all forum functionality.

Space Engineers New! PB Scripting Guide: How To Use Self-Updating

Discussion in 'Programming (In-game)' started by rexxar, Nov 17, 2017.

Thread Status:
This last post in this thread was made more than 31 days old.
  1. Michael Viktor Starberg Trainee Engineer

    Messages:
    17
    @rexxar (@Malware )

    Thanks to MDK-SE I finally took the time to do some major surgery to my scripts.
    I used to have two timers for all my grids. One for 'pulse' and one for 'callback'.
    That pesky state-machine was ugly and tricky.

    Now I use Update10 for pulse and Update100 for waiting. Pulsing oir Waiting.
    Peew. Not easy to code and even trickier to abstract. I'm getting there.

    Also removes a timer block on my airlock. Makes it one large block shorter in height and no need to build a roof over it. So thanks.

    Thanks!

    ps.
    Update1000 would be nice for waiting...

    pps. Adding my non abstracted version. It's good enough.

    Code:
    			
    			public void ProcessMessage(string args, UpdateType updateType)
    			{
    				if (waiter.Waiting && updateType != UpdateType.Update100)
    				{
    					// We are waiting and another kind of message came in. Store it so we can run it later.
    					var message = new Message(args, updateType);
    					waiter.Messages.Add(message);
    					return;
    				}
    
    				var now = DateTime.Now;
    				if (updateType == UpdateType.Update10)
    				{
    					if ((now - waiter.LastPulse) > TimeSpans.TwoSeconds)
    					{
    						// Normal pulse. But before we process this message we must check to see others are not waiting
    						if(waiter.Messages.Count > 0)
    						{
    							// A message was waiting. we set that as the current message and fall out to handle it
    							var dequeueMessage = waiter.Messages.Pop();
    							args = dequeueMessage.Args;
    							updateType = dequeueMessage.UpdateType;
    						}
    						else
    						{
    							// Normal message. We are good.
    							program.grid.UpdateState();
    							waiter.LastPulse = DateTime.Now;
    							return;
    						}
    					}
    				}
    
    				if (updateType == UpdateType.Update100)
    				{
    					if (now > waiter.WaitUntil)
    					{
    						// TODO This is one part that should be abstracted. Action<Enum>
    						switch(waiter.WaitFor)
    						{
    							case WaitState.Docking:
    								program.OnDocked(done: true);
    								break;
    
    						}
    						waiter.Waiting = false;
    						waiter.WaitFor = WaitState.Idle;
    						Pulse();
    						return;
    					}
    				}
    
    				program.grid.UpdateState();
    
    				// TODO This part should be abstracted into Action<string>.
    				switch (args)
    				{
    					case "pulse":
    						Pulse();
    						break;
    					case "nopulse":
    						Nopulse();
    						break;
    					case "sensorEnter":
    						program.OnSensor(leaving: false);
    						break;
    					case "sensorLeave":
    						program.OnSensor(leaving: true);
    						break;
    					case "docking":
    						program.OnDocking();
    						break;
    					case "docked":
    						program.OnDocked(done: false);
    						break;
    					case "rename":
    						program.renamer.RenameBlocks();
    						break;
    					case "testwait":
    						WaitFor(WaitState.Idle, TimeSpans.FiveSeconds);
    						break;
    				}
    			}
    
     
  2. Pie Apprentice Engineer

    Messages:
    107
    Maybe this should go in Bug Reports however I suspect it would be very low priority so I'm wondering if anyone here has a workaround!

    On a local game setting Runtime.UpdateFrequency = None works fine. On DS it seems to get ignored. As an example, create a new world locally. Create a grid with power, a programmable block, an LCD panel with public text turned on called "HangarDebug" (sorry, wanted to make it work on my existing DS rather than just find the first panel).

    Stick this in a Programmable Block and compile:

    Code:
    IMyTextPanel output;
    int tick;
    
    public Program()
    
    {
    	// Find the first lcd
    	tick=0;
    	List<IMyTerminalBlock> allBlocks = new List<IMyTerminalBlock>();
    	GridTerminalSystem.SearchBlocksOfName("HangarDebug", allBlocks);
    	if (allBlocks.Count > 0) { output=allBlocks[0] as IMyTextPanel; output.WritePublicText("Test...\n"); }
    	
    	// Set Update Frequency to 10
    	Runtime.UpdateFrequency = UpdateFrequency.Update10;
    }
    
    public void Main(string argument, UpdateType updateSource)
    {
    	// Increase the tick...
    	tick=tick+1;
    	if (output != null) { output.WritePublicText("Tick: "+tick+"\n", true); }
    	if (tick > 5)
    	{
    		output.WritePublicText("Tick greater than 5 - stopping execution...", true);
    		Runtime.UpdateFrequency = UpdateFrequency.None;
    	}
    }
    
    Works fine - you'll get 5 ticks then it will stop.

    Do the same on a DS - it runs forever.
     
  3. Malware Master Engineer

    Messages:
    9,031
    @Pie Well if you don't post it in bug reports it might not get fixed at all, so don't do the either/or thing here ;)
     
  4. rexxar Senior Engineer

    Messages:
    1,530
    I have risen from the dead.

    There is a bug which causes the program constructor to run on clients. This in turn can start the script self-update manager running on clients, which inadvertently sends run requests up to the server.

    Kind of a chain reaction thing that can't be stopped.

    When/if I get a break from work I'll patch it and send it to Keen. It looks like it was my mistake, I added a default parameter out of laziness and I didn't examine the consequences fully.
     
  5. EnjoyCoke Trainee Engineer

    Messages:
    71
    Is it possible to loop the pb using default argument over no argument?
     
  6. Malware Master Engineer

    Messages:
    9,031
    @EnjoyCoke No. The looping system has no argument and the so-called "default" argument is really the manual run argument. However you can get that argument through Me.TerminalRunArgument.
     
  7. Bullet_Force Apprentice Engineer

    Messages:
    275
    Hi has this bug been fixed?
    --- Automerge ---
    Hi with this is there a way to run a script longer then once every 100 ticks? I want my script to run once say every 20 seconds which would be around 1200 ticks (if 60 per second).
     
Thread Status:
This last post in this thread was made more than 31 days old.