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.

Using Block Position To Find Another Block

Discussion in 'Programming (In-game)' started by Bullet_Force, Feb 18, 2016.

Thread Status:
This last post in this thread was made more than 31 days old.
  1. Bullet_Force Apprentice Engineer

    Messages:
    357
    Hi is it possible to do the following in Space Engineers using Block Position?

    Say I have a Merge Block and then I go 2 block positions along the X axis and turn whatever block that is on without knowing its name or type?

    Has anyone got a similar script or an example of anything like this.
     
  2. Phoera Senior Engineer

    Messages:
    1,713
    i cannot give you a practice code, but can give theory.

    you can take block from grid position.
    by using block.Position to know grid position.
    and block.CubeGrid to take grid.
    then grid.GetCubeBlock(position to check) to take block from that grid.(you will get slim block)
    slim.FatBlock will give you a terminal block of that cube.
    also you can use simple grid.CubeExists if you need to only know if block exists.(it will return true also for not terminal blocks)
     
  3. Malware Master Engineer

    Messages:
    9,663
    The following is an exerpt of the code I use to get blocks by position, taking block orientation into account (meaning the position is always relative to the block, not the grid). You will need to tweek it to get it to work for your own purposes.
    Code:
    _matrix = new MatrixI(_baseBlock.Orientation);
     
      // Negate the X and Z to have the vectors equate the world system
      // -x left +x right
      // -y down +y up
      // -z forward +z backwards
     
    var pos = new Vector3I(-position.X, position.Y, -position.Z);
    Vector3I transformed;
    Vector3I.Transform(ref pos, ref _matrix, out transformed);
    transformed += _baseBlock.Position;
    var slim = _baseBlock.CubeGrid.GetCubeBlock(transformed);
    return slim == null ? null : slim.FatBlock as IMyTerminalBlock;
    
     
  4. Bullet_Force Apprentice Engineer

    Messages:
    357
    Hi can you explain this line the syntax doesn't make sense to me:
    Code:
    var targetBlock = slim == null ? null : slim.FatBlock as IMyTerminalBlock;
     
  5. Malware Master Engineer

    Messages:
    9,663
    My apologies :) It is shorthand. It means the same as this:

    Code:
    	IMyTerminalBlock targetBlock;
    	if (slim == null) {
    		targetBlock = null;
    	} else {
    		targetBlock = slim.FatBlock as IMyTerminalBlock;
    	}
    
     
  6. plaYer2k Master Engineer

    Messages:
    3,160
    Are you sure that is needed? I always though the grid coordinates are the same like the world coordinates.
     
  7. Malware Master Engineer

    Messages:
    9,663
    Of course I'm sure, I'm using this code :p

    It has to do with the matrix multiplication, I think. Remember, I'm working relative to the block, not the grid. I haven't bothered rooting out the main reason, because it works.
     
    • Like Like x 1
  8. plaYer2k Master Engineer

    Messages:
    3,160
    Well it still looks odd somehow :D

    I am using the following code with great success
    Code:
    void Main(string arg)
    {
    Vector3I dir;
    if(!Vector3I.TryParseFromString(arg, out dir))
    {
    Echo("Unable to parse to Vector3I: " + arg);
    return;
    }
    string output = "";
    IMyTerminalBlock block = GetRelativeBlock(Me, dir);
    if(block != null)
    Echo(string.Format("Found Block: {0}", block.CustomName));
    else
    Echo("Unable to find block with input direction: " + dir.ToString());
    Echo(output);
    }
     
    public static IMyTerminalBlock GetRelativeBlock(IMyTerminalBlock reference, Vector3I direction)
    {
    Matrix mat;
    reference.Orientation.GetMatrix(out mat);
    mat.Translation = reference.Position;
    Vector3I.Transform(ref direction, ref mat, out direction);
    IMySlimBlock sb = reference.CubeGrid.GetCubeBlock(direction);
    return sb == null ? null : sb.FatBlock as IMyTerminalBlock;
    }
    and as you can see there is no prior manipulation of the direction.

    I have a simple world setup with programmable blocks and other terminal blocks and always get the correct block related to the programmable block.
    Programmable blocks also got their access in backwards direction so maybe that was the cause? Rotating 180° around the Y axis inverts X and Z.

    Edit:
    Using other blocks like for example the Remote Control also makes the blocks actual orientation more obvious i guess. For them the forward, right and up direction is pretty clear.
    I have a reactor directly in front of the remote control, a programmable block (PB1) on top of that reactor and another programmable block (PB2) on the left of the reactor.

    With the following inputs i get the following blocks:
    [0;0;0] > Remote Control
    [0;0;-1] > Reactor
    [-1;0;-1] > Programmable Block 2
    [0;1;-1] > Programmable Block 1
    any other input > no block found
     
    Last edited: Feb 18, 2016
  9. Malware Master Engineer

    Messages:
    9,663
    That may very well be the cause, yes. I always use the programmable blocks as origin and for some reason assumed the access was in front, although when I actually think about it that doesn't actually make sense :p

    Off topic, I hate that forward is negative. I'm used to Lightwave 3D. Forward is positive. Makes more sense to me... To go forward I ADD to my coordinate.
     
  10. Michael Viktor Starberg Trainee Engineer

    Messages:
    18
    @Malware: This was exactly what I was I was looking for! Very hard to Google a proper solution for just getting a block relative to another block. Here is a C#6 version for you:

    Code:
            private T GetBlock<T>(IMyTerminalBlock reference, int x, int y, int z)
            {
                var direction = new Vector3I(x, y, z);
    
                var matrix = default(Matrix);
                reference.Orientation.GetMatrix(out matrix);
    
                matrix.Translation = reference.Position;
                Vector3I.Transform(ref direction, ref matrix, out direction);
    
                var slimBlock = reference.CubeGrid.GetCubeBlock(direction);
                var fatBlock = (T)slimBlock?.FatBlock;
    
                return fatBlock;
            }
    
    
    Usage:

    Code:
            IMyTimerBlock timer;
            IMyAirVent airVent;
            IMyGasTank oxygenTank;
            // etc..
            public Program()
            {
                timer = GetBlock<IMyTimerBlock>(Me, 0, -1, 0);
                airVent = GetBlock<IMyAirVent>(Me, 1, 0, -1);
                oxygenTank = GetBlock<IMyGasTank>(Me, 2, 0, 0);
    	    //etc..
    
    
    Would be cool if there was an easier way to get a FatBlock relative to another block directly from the API. But this is the best I have found. And thanks again @Malware for the solution.
     
    Last edited: Aug 28, 2017
Thread Status:
This last post in this thread was made more than 31 days old.