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.

Memory Block

Discussion in 'Programming Questions and Suggestions' started by spacedMatt, Jan 4, 2015.

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

    Messages:
    421
    A block to store variables like int,float,string,var...

    At the moment if you want to have memory you could use a blocks custom name to store a reference to the data in side of your code.

    The problem with this is that you see the reference in the control panel, plus having to sacrifice block names and you need to put the data in all of your scrips that use it.

    I think it would be good to have a place data is stored like a block with lots of custom names but more like sub names that you could store all types of data. Also the data would be hidden from the main control panel and your scripts.

    This would make it a lot easier for scripts to share data.
    I may be getting this wrong so if there is already a way to do this please say.
     
  2. pipakin Apprentice Engineer

    Messages:
    182
    I built a script to handle this. It stores the data in a chosen block's name.

    See: http://forums.keenswh.com/post/data-storage-script-7227320
     
  3. spacedMatt Apprentice Engineer

    Messages:
    421
    Thanks But I've already done this, I'm saying it would be better to save it in a place you can't see it, like inside of a blocks 'sum name' and not the one shown in the control panel.

    Also so you don't have to keep converting the string to an int but have that data as you saved and want it, being int, float, bool, string...
     
    Last edited by a moderator: Jan 4, 2015
  4. pipakin Apprentice Engineer

    Messages:
    182
    The script I provided uses whatever type you want. Example:

    Code:
    int intValue = DataStorage_Get<int>("intValue");
    
    It can even store/load lists.
     
  5. spacedMatt Apprentice Engineer

    Messages:
    421
    But you can still see it in your control panel and you only get one variable per block name.
     
    Last edited by a moderator: Jan 4, 2015
  6. pipakin Apprentice Engineer

    Messages:
    182
    Fair point, you can see it. Nothing to be done about that.

    BUT You can store as many variables as you want in one block. I've tested it with 200 variables, including several lists, and it worked just fine.

    Essentially, you init it with a block name:

    Code:
    DataStorage_InitStorage("Block Name Here", "Your data prefix here");
    
    Then load or store as many variables as you want with:

    Code:
    var variable = DataStorage_Get<T>("variable name");
    DataStorage_Set<T>("variable name", value);
    
    var listOfT = DataStorage_GetList<T>("list name");
    DataStorage_SetList<T>("list name", listOfT);
    
     
    Last edited by a moderator: Jan 4, 2015
  7. spacedMatt Apprentice Engineer

    Messages:
    421
    Interesting, I guess you could always save the start of the block name as something like
    'Memory Block.........:'
    So you couldn't see the variables attached and you know what it is in the control panel.
     
    Last edited by a moderator: Jan 4, 2015
  8. pipakin Apprentice Engineer

    Messages:
    182
    Also, I just fixed a major bug where it didn't work with blocks not named "Data Storage". lol

    I'm toying with adding newlines and seeing how that works. I'll get back to you.
     
  9. pipakin Apprentice Engineer

    Messages:
    182
    Ok, newlines was a bust, but just adding a bunch of whitespace made it not visible. Weee!

    Pre-release of version 2.0 which should have "hidden" values.

    [​IMG]
    You can still see them if you scroll to the end of the block name.

    [​IMG]

    Code:
    //Example script for storing arbitrary data in a block's name.  Will later use something less dumb,  
    //but as this is the only method available right now, that's what we got.  
    //  
    //This data will get persisted across save/load boundaries! :)  
      
    void Main()  
    {  
        //Make sure to call this once. In the future, any data-migration will end up here.  
        //Also, this sets the name of the block to use for storing your data.  
        //note: if you use the prefix argument and it doesn't match your data before the prefix   
        //existed, it won't be migrated, you gotta do that yourself.  
        DataStorage_InitStorage("Data Storage", "DSTest_");  
      
        //Add some data!  
        DataStorage_Set("Hello", "World!");  
        DataStorage_Set("foo", 1);  
        DataStorage_Set("bar", 0.13563);  
        DataStorage_Set("awesome", true);  
          
        //add a list!  
        DataStorage_SetList("omgLists", new List<int>{ 10, 42, 32, 100 });  
      
        //Get the data back!  
        var hello = DataStorage_Get<string>("Hello");  
        var foo = DataStorage_Get<int>("foo");  
        var bar = DataStorage_Get<double>("bar");  
        var awesome = DataStorage_Get<bool>("awesome");  
          
        //get the list!  
        var omgLists = DataStorage_GetList<int>("omgLists");  
          
        //test it by adding the 3rd value back (32)  
        DataStorage_Set("testList", omgLists[2]);  
          
        //remove foo  
        DataStorage_Remove("foo");  
    }  
      
    //Copy everything below this line into a script that you want to use data storage in  
    string DataStorage_BlockName = null;  
    string DataStorage_Prefix = "";  
    int DataStorage_DataOffset = 0;  
    void DataStorage_InitStorage(string blockName, string prefix = "")  
    {  
        DataStorage_Prefix = "";  
        var block = GridTerminalSystem.GetBlockWithName(blockName);   
      
        DataStorage_BlockName = blockName + "                                                                                                                                                                  ";   
        DataStorage_DataOffset = DataStorage_BlockName.Length;  
       
        if(block.CustomName == blockName)   
        {   
            block.SetCustomName(DataStorage_BlockName);    
       
            DataStorage_Set("DS_InitDate", DateTime.Now.ToString("yyyy-MM-dd"));   
            DataStorage_Set("DS_Version", 2.0);  
        }  
      
        //Upgrades... Versions before 2.0 were visible on the control panel.
        //So we have to update them.
        if(block.CustomName.StartsWith(blockName + " - "))  
        {  
            //add newlines to data 
     
            var oldName = block.CustomName; 
            block.SetCustomName(oldName.Replace(blockName + " - ", DataStorage_BlockName)); 
     
            //set the new version 
            DataStorage_Set("DS_Version", 2.0);  
        }  
          
        DataStorage_Prefix = prefix;  
    }  
      
    public void DataStorage_SetList<T>(string name, List<T> value)  
    {  
        var stringVal = "";  
        for(int i=0;i<value.Count;i++)  
        {  
            stringVal += value[i].ToString() + "~";  
        }  
        DataStorage_SetString(name, stringVal);  
    }  
      
    public List<T> DataStorage_GetList<T>(string name)  
    {  
        var testStringVal = DataStorage_GetString(name);  
        var list = new List<T>();  
        if(testStringVal == null)  
            return list;  
        var stringVal = testStringVal.Split('~');  
        for(int i=0;i<stringVal.Length - 1;i++)  
        {  
            try{  
                list.Add((T)Convert.ChangeType(stringVal[i], typeof(T)));  
            } catch {  
                list.Add(default(T));  
            }  
        }  
        return list;  
    }  
      
    public void DataStorage_Set<T>(string name, T value)  
    {  
        DataStorage_SetString(name, value.ToString());  
    }  
      
    public T DataStorage_Get<T>(string name)  
    {  
        var val = DataStorage_GetString(name);  
        try{  
            return (T)Convert.ChangeType(val, typeof(T));  
        } catch {  
            return default(T);  
        }  
    } 
     
    List<string> GetVariableLines(IMyTerminalBlock block) 
    { 
        return new List<string>(block 
                            .CustomName 
                            .Substring(DataStorage_DataOffset) 
                            .Split(new string[]{ ";" }, StringSplitOptions.None)); 
    } 
      
    void DataStorage_SetString(string name, string value)  
    {  
        var block = GridTerminalSystem.GetBlockWithName(DataStorage_BlockName);    
        var groups = GetVariableLines(block); 
        var found = false;  
          
        var fullName = DataStorage_Prefix + name;  
        
        for(int i=0;i<groups.Count;i++)   
        {   
            var keyval = groups[i].Split('=');   
            if(keyval[0] == fullName || groups[i] == "")  
            {  
                groups[i] = fullName + "=" + value;  
                found = true;  
            }  
        }   
        if(!found)  
        {  
            groups.Add(fullName + "=" + value);  
        }  
      
        block.SetCustomName(DataStorage_BlockName + string.Join(";", groups));  
    }  
      
    string DataStorage_GetString(string name)  
    {  
        var block = GridTerminalSystem.GetBlockWithName(DataStorage_BlockName);   
        var groups = GetVariableLines(block); 
          
        var fullName = DataStorage_Prefix + name;  
       
        for(int i=0;i<groups.Count;i++)  
        {  
            var keyval = groups[i].Split('=');  
            if(keyval[0] == fullName) return keyval[1];  
        }  
        return null;  
    }  
      
    void DataStorage_Remove(string name)  
    {  
        var block = GridTerminalSystem.GetBlockWithName(DataStorage_BlockName);    
        var groups = GetVariableLines(block); 
          
        var fullName = DataStorage_Prefix + name;  
        
        for(int i=0;i<groups.Count;i++)   
        {   
            var keyval = groups[i].Split('=');   
            if(keyval[0] == fullName || groups[i] == "")  
            {  
                groups.RemoveAt(i);  
                break;  
            }  
        }   
      
        block.SetCustomName(DataStorage_BlockName + string.Join(";", groups));  
    }
    
     
  10. spacedMatt Apprentice Engineer

    Messages:
    421
    Nice one! It looks really good I'll give it a go now.

    This will really help with my own code thanks :thumb::comp:
     
  11. A2K Trainee Engineer

    Messages:
    18
    I have proposed similar idea in other thread, then I saw this. Yes, it would be great to have a real memory block!
    Modifying other block names for this purpose is not a very elegant solution because those names are supposed to be human-readable in game UI.
     
Thread Status:
This last post in this thread was made more than 31 days old.