Pre 1.2 Terraria GameLauncher - A way to load multiple mods through Steam

Discussion in 'Released Mods' started by plaYer2k, Sep 13, 2011.

Thread Status:
Not open for further replies.
  1. plaYer2k Mouse

    Good news everyone! (Random Futurama quote)

    This application allows you to start multiple Terraria Mods through your Steam account.
    No more you have to rename/move files just to change between mods and the original game.

    ---
    Eikester content from here
    ---
    Eikester who made the CustomContentLoader and the nice Sonic texture pack also made a GUI version for this program now, but see youself:

    Download
    ---
    original post from here
    ---

    It is even easy to install. You would have a hard time trying to mess that up ;-)

    This is how it looks like right now:
    [IMG]
    Enter the number of the "Game" you want to play and press enter.
    Then it starts your game and you can enjoy it. Simple isnt it ?
    (You still have to install the mods through their own routine, usually a DiffPatch)

    Modders Info: (open)

    To use the Launcher you simply have to provide all essential files like executable(not Terraria.exe), textures, sounds etc.
    In addition the GameLauncher is looking for files with a .gli extension to load the required informations.

    A gli-file contains two lines of text right now, Display Name and Hash.
    To get the Hash for your executable simply put the "GameLauncher Installer.exe" or its modified Terraria.exe (both have a size of ~9,5kb) into your mod directory and run GameLauncher executable with the parameter -genhash and you get a txt-file containing all Files with their Hash.
    (i.e. GameLauncher Installer.exe -gethash)
    The hash is used to accurately identify your mod and no other file.

    Example gli-file:
    TerrariaOriginal_1061.gli
    Code:
    Terraria 1.0.6.1
    A5774195387F3AB230BDA08BBDF38DF32B4D3AE5C79425D5D04C8288C01D6570
    
    So you can name your executable what ever you want as long as its a valid windows name.
    Your mod is choosen by its hash only.
    Do NOT replace Terraria.exe



    The reason i made this program is quiet obvious.
    Many people are using Surfpops Config Mod, i want to release my Cmod and other modders are doing the same. Its also easier to change between just one mod and vanilla Terraria.
    Using this tool i hope we can find a unified platform to launch all mods through steam.

    So what are your benefits as user?
    - easy to use
    - works through steam

    What it cant?
    - you can not run Wrapper through this app since they try to access Terraria.exe which is the launcher now

    Download:
    Filebeam.com URL Removed
    Mediafire.com URL Removed

    source (open)

    Code:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.IO;
    using System.Diagnostics;
    using System.Security.Cryptography;
    
    namespace Terraria
    {
        class Program
        {
            private static string startExe = "";
            private static string tHash;
            private static SHA256 sHA = new SHA256Managed();
            private static string curDir;
            private static string[] configs;
            private static string[] executables;
            private static string[] gameName;
            private static string[] gameHash;
            private const string version = "release 2";
            private const string patcherHash = "32A4664E367A5C6BC7316D2213E60086D2813C21DB3D407350E4ACA61C1B16A1";
            private const string curTerrariaReleaseHash = "A5774195387F3AB230BDA08BBDF38DF32B4D3AE5C79425D5D04C8288C01D6570";
            private static int gliCount = 0;
            private static string defTerrariaPath = "";
            private static string defTerrariaBackupPath = "";
            private static string originalTerrariaPath = "";
    
            static void Main(string[] args)
            {
                curDir = Directory.GetCurrentDirectory();
                configs = Directory.GetFiles(curDir, "*.gli");
                executables = Directory.GetFiles(curDir, "*.exe");
                gameName = new String[configs.Length];
                gameHash = new String[configs.Length];
                defTerrariaPath = Path.Combine(curDir, "Terraria.exe");
                defTerrariaBackupPath = Path.Combine(curDir, "TerrariaOriginalBackup.exe");
                originalTerrariaPath = getExeForHash(curTerrariaReleaseHash);
    
                //check all arguments for this application
                for (int i = 0; i < args.Length; i++)
                {
                    //check if we shall create the hashValues for all executables within the current directory
                    if (args[i].ToLower() == "-genhash")
                    {
                        string hashTextFile = "hashKeys.txt";
                        string[] infos = new String[2];
                        using (StreamWriter hashFile = new StreamWriter(hashTextFile))
                        {
                            for (int j = 0; j < executables.Length; j++)
                            {
                                try
                                {
                                    infos[0] = executables[j];
                                    infos[1] = genHash(executables[j]);
                                    hashFile.WriteLine(infos[0]);
                                    hashFile.WriteLine(infos[1]);
                                }
                                catch
                                {
    
                                }
                            }
                        }
                        Console.WriteLine("Hashes generates, please open " + hashTextFile);
                        Console.WriteLine("press enter to exit");
                        Console.ReadLine();
                        return;
                    }
                    ////currently WIP
                    //if (false && args[i].ToLower() == "-patch")
                    //{
                    //    string patchPath = "";
                    //    string destFile = "";
                    //    try
                    //    {
                    //        patchPath = args[i + 1];
                    //        destFile = args[i + 2];
                    //    }
                    //    catch
                    //    {
                    //        Console.WriteLine("Error: unable to fetch arguments");
                    //        Console.ReadLine();
                    //        return;
                    //    }
                    //    bool error = false;
                    //    string patcherPath = getExeForHash(patcherHash);
                    //    if (!File.Exists(patcherPath))
                    //    {
                    //        Console.WriteLine("Error: bspatcher.exe not found or unknown version");
                    //        error = true;
                    //    }
                    //    if(!File.Exists(Path.Combine(curDir,patcherPath)))
                    //    {
                    //        Console.WriteLine("Error: did not find the patchfile (" + patchPath + ")");
                    //        Console.WriteLine("please contact the mod author to get this problem solved");
                    //        error = true;
                    //    }
                    //    if (error)
                    //    {
                    //        Console.WriteLine("patching aborded");
                    //        Console.ReadLine();
                    //        return;
                    //    }
                    //    string destFilePathFull = Path.Combine(curDir, destFile);
                    //    if (File.Exists(destFilePathFull))
                    //    {
                    //        try
                    //        {
                    //            File.Delete(destFilePathFull);
                    //        }
                    //        catch (Exception)
                    //        {
                    //            Console.WriteLine("Unable to delete");
                    //        }
                    //    }
                    //    else
                    //    {
                    //        try
                    //        {
                    //            //  Currently this is bugged, Running a .bat file from your windows explorer as administrator
                    //            //  does NOT grant this programm the sufficient admin rights to perform that action
                    //            //  but running the .bat through a cmd promt which got admin rights, it works.
                    //            //  This may be a windows 7 "security" problem.
                    //            //  -> adding patches through this file is halted for now.
                    //            Console.WriteLine("patching");
                    //            String patcherArgument = Path.GetFileName(getExeForHash(curTerrariaReleaseHash)) + " " + destFile + " " + patchPath;
                    //            Process patch = new Process();
                    //            patch.StartInfo.FileName = patcherPath;
                    //            patch.StartInfo.UseShellExecute = true;
                    //            patch.StartInfo.RedirectStandardOutput = true;
                    //            patch.StartInfo.WorkingDirectory = Directory.GetCurrentDirectory();
                    //            patch.StartInfo.Arguments = patcherArgument;
                    //            patch.Start();
                    //            patch.WaitForExit();
                    //        }
                    //        catch (Exception)
                    //        {
                    //            Console.WriteLine("Error: Run with administrator rights.");
                    //        }
                    //        if (File.Exists(Path.Combine(curDir, destFile)))
                    //            Console.WriteLine("Patch applied");
                    //        else
                    //            Console.WriteLine("Error: Patch failed");
                    //    }
                    //    Console.ReadLine();
                    //    return;
                    //}
                }
    
                //install the GameLauncher by itself if its not named Terraria
                string myProcessName = Process.GetCurrentProcess().ProcessName + ".exe";
                if (myProcessName != "Terraria.exe")
                {
                    Console.WriteLine("Installing GameLauncher " + version + " ...");
                    string myPath = Path.Combine(curDir, myProcessName);
                    if (!File.Exists(originalTerrariaPath))
                    {
                        Console.WriteLine("Error: Could not locate your original Terraria build\nMay you use a newer version? Check updates.\nAlso make sure you run this file from within your terraria directory '...\\Steam\\SteamApps\\common\\terraria\\'");
                        Console.WriteLine((File.Exists(defTerrariaPath) ? "found: " : "missing: ") + defTerrariaPath);
                        Console.WriteLine((File.Exists(defTerrariaBackupPath) ? "found: " : "missing: ") + defTerrariaBackupPath);
                        Console.WriteLine((File.Exists(originalTerrariaPath) ? "found: " : "missing: ") + originalTerrariaPath);
                        Console.WriteLine("press enter to exit");
                        Console.ReadLine();
                        return;
                    }
                    if (defTerrariaBackupPath != originalTerrariaPath)
                    {
                        try
                        {
                            File.Move(originalTerrariaPath, defTerrariaBackupPath);
                        }
                        catch
                        {
                            Console.WriteLine("Error: Could not backup your " + Path.GetFileName(originalTerrariaPath) + " to " + Path.GetFileName(defTerrariaBackupPath));
                            Console.WriteLine((File.Exists(defTerrariaPath) ? "found: " : "missing: ") + defTerrariaPath);
                            Console.WriteLine((File.Exists(defTerrariaBackupPath) ? "found: " : "missing: ") + defTerrariaBackupPath);
                            Console.WriteLine((File.Exists(originalTerrariaPath) ? "found: " : "missing: ") + originalTerrariaPath);
                            Console.WriteLine("press enter to exit");
                            Console.ReadLine();
                            return;
    
                        }
                        originalTerrariaPath = getExeForHash(curTerrariaReleaseHash);
                        if (!File.Exists(originalTerrariaPath))
                        {
                            Console.WriteLine("Wooops!!! Something went terrible wrong!");
                            Console.WriteLine("If you see this, please report your case to the forumthread");
                            Console.WriteLine("Please restore your terraria backup from 'TerrariaOriginalBackup.exe'");
                            Console.WriteLine((File.Exists(defTerrariaPath)?"found: ":"missing: ") + defTerrariaPath);
                            Console.WriteLine((File.Exists(defTerrariaBackupPath) ? "found: " : "missing: ") + defTerrariaBackupPath);
                            Console.WriteLine((File.Exists(originalTerrariaPath) ? "found: " : "missing: ") + originalTerrariaPath);
                            Console.WriteLine("press enter to exit");
                            Console.ReadLine();
                            return;
                        }
                    }
                    try
                    {
                        if(File.Exists(defTerrariaPath))
                            File.Delete(defTerrariaPath);
                        File.Copy(myPath, defTerrariaPath);
                    }
                    catch
                    {
                        Console.WriteLine("Error: could not write " + Path.GetFileName(defTerrariaPath));
                        Console.WriteLine((File.Exists(defTerrariaPath) ? "found: " : "missing: ") + defTerrariaPath);
                        Console.WriteLine((File.Exists(defTerrariaBackupPath) ? "found: " : "missing: ") + defTerrariaBackupPath);
                        Console.WriteLine((File.Exists(originalTerrariaPath) ? "found: " : "missing: ") + originalTerrariaPath);
                        Console.WriteLine("press enter to exit");
                        Console.ReadLine();
                    }
                    if (File.Exists(defTerrariaPath))
                        Console.WriteLine("Gamelauncher installation Complete\nenjoy");
                    else
                    {
                        Console.WriteLine("Error: GameLauncher could not find writen Terraria.exe");
                        Console.WriteLine((File.Exists(defTerrariaPath) ? "found: " : "missing: ") + defTerrariaPath);
                        Console.WriteLine((File.Exists(defTerrariaBackupPath) ? "found: " : "missing: ") + defTerrariaBackupPath);
                        Console.WriteLine((File.Exists(originalTerrariaPath) ? "found: " : "missing: ") + originalTerrariaPath);
                    }
                    Console.WriteLine("press enter to exit");
                    Console.ReadLine();
                    return;
                }
                //File.WriteAllBytes(Path.Combine(curDir, "TerrariaOriginal.gli"), );// ARGG how to get this testline to work ._.
                //Read all info Files
                for(int i = 0; i < configs.Length;i++)
                {
                    try
                    {
                        StreamReader curConfigStream = new StreamReader(configs[i]);
                        gameName[i] = curConfigStream.ReadLine();
                        gameHash[i] = curConfigStream.ReadLine();
                        gliCount++;
                    }
                    catch
                    {
                        Console.WriteLine("Error in file: " + configs[i]);
                    }
                }
    
                //catch the case that no gli-file was found
                if (gliCount <= 0)
                {
                    Console.WriteLine("No compatible game found");
                    Console.WriteLine("press enter to exit");
                    Console.ReadLine();
                    return;
                }
    
                bool valideInput = false;
                while (!valideInput)
                {
                    Console.WriteLine("Welcome to the GameLoader " + version + "\n");
                    Console.WriteLine("Please choose one of the following games to run\nby entering the number in front of it\n");
                    for (int i = 0; i < configs.Length; i++)
                    {
                        if (gameName[i].Length > 0)
                        {
                            Console.WriteLine((i+1) + " - " + gameName[i]);
                        }
                    }
                    string textInput = Console.ReadLine();
                    try
                    {
                        int intInput = Convert.ToInt32(textInput) - 1;
                        if (intInput >= 0 && intInput < configs.Length)
                        {
                            tHash = gameHash[intInput];
                            valideInput = true;
                        }
                    }
                    catch
                    {
                    }
                    try
                    {
                        Console.Clear();
                    }
                    catch
                    {
                    }
                }
    
                //get the corresponding executable for your hash
                startExe = getExeForHash(tHash);
    
                //run the executable once the file is present
                if (File.Exists(startExe))
                {
                    Console.WriteLine("Starting: " + Path.GetFileName(startExe));
                    Process process = new Process();
                    process.StartInfo.FileName = startExe;
                    process.StartInfo.UseShellExecute = false;
                    process.StartInfo.RedirectStandardOutput = true;
                    process.StartInfo.WorkingDirectory = Directory.GetCurrentDirectory();
                    process.Start();
                    StreamReader outputStream = process.StandardOutput;
                    while (!process.HasExited)
                        Console.WriteLine(outputStream.ReadLine());
                }
                else
                {
                    //error output
                    Console.WriteLine("Game not found");
                    Console.WriteLine("press enter to exit");
                    Console.ReadLine();
                }
            }
    
            private static string genHash(String file)
            {
                if (!File.Exists(file))
                    return "";
                byte[] buffer;
                byte[] hashArray;
                buffer = File.ReadAllBytes(file);
                hashArray = sHA.ComputeHash(buffer);
                return string.Concat(Array.ConvertAll<byte, string>(hashArray, (byte x) => x.ToString("X2")));
            }
    
            private static string getExeForHash(String hash)
            {
                executables = Directory.GetFiles(curDir, "*.exe");
                string path = "";
                for (int i = 0; i < executables.Length; i++)
                {
                    if (File.Exists(executables[i]) && hash == genHash(executables[i]))
                    {
                        path = executables[i];
                        break;
                    }
                }
                return path;
            }
        }
    }
    

    Changelog
    • Release 2
      • Added Console.WriteLine support for games.
      • Changed the way how the launcher "installs" itself
      • Added a more details to error messages
    • Release 1
      • Initial release
      • Added support to load multiple games through .gli files
      • Added a selfinstaller to replace Terraria.exe
    And a single warning, its my ONLY warning i give here.
    No discussions about modding, how you like or dislike it.
    No "but the devs dont support modding yet".
    I will send out infraction requests once it goes too offtopic.

    Thanks to Surfpup for the idea and codesegments to use Hash values to identify executables.
    Thanks to Berserker66 for the console output keyword (stdin/stdout).

    Edit
    Roddy, sldad, Omnir and 1 other person like this.
  2. Surfpup Arapaima

    I'll be adding support for this when I get the chance. By the way, what's this mod that you're working on about?
    Omnir likes this.
  3. Zamixus Doctor Bones

    Great idea, nice work!
  4. Berserker66 Umbrella Slime

    I wont use it, as I rarely use steam. But I can see it beeing useful for other people.

    If you can get multiple mods to work by applying multiple binary difference patches, then it would be a lot more awesome ;)
  5. plaYer2k Mouse

    I hope that this will improve usability for "common users" since some dont like to "move and rename" files themself. :)
    quick copy&paste from my test PM (open)


    As for the new content:
    - around 100 new recipes
    - around 120 new items, some of them are for testing purposes only
    - a few new projectiles and buffs
    - the Pipesystem to transport water
    - the shooters that shoot projectiles like water (currently only used for water with "fishy frog fountains")
    - leech system (health and mana)
    - gravity (mostly used for Pigged Out Debuff and Astro Suit)
    - rain
    - food system
    [IMG]

    just stuff


    Heh i were just lucky to have some timing. Also a big part of that goes to Surfpop for his hashing implementation of his mod since i used parts of his code as well as the idea in general to identify Mods. (OH grose i just now realized that i didnt mention it ... *shame on me* and i were sure i did write that)

    Well multiple mods work, at least for what i tested. What does NOT work, are wrapper since they try to access Terraria.exe usually which is now the Launcher only :-P
    And if you use a altered steam_api.dll then it will run too :)
    But i dont do that with my Launcher.

    Anyway iam going to add a new release soon with a few minor fixes.

    And for modders, either assume the original Terraria.exe to be named TerraroaOriginalBackup.exe which the user could change or scramble through the code and see how to make a patcher youself. I might add a patching method through the GameLauncher Installer.exe so you can apply patches with a bat-file and the line "GameLauncher Installer.exe -patch MyMod_Patch" and it looks for the original Terraria exe itself since the user could have moved it, iam not sure yet.

    The method how mods are loaded should not be changed so anyone who is interested can test to add his mod on his own pc and then tell me if there are problems.
  6. Surfpup Arapaima

    I've added support for this in tConfig. I was wondering, since there's a lovely command prompt still on the screen, is it possible to somehow print messages to it from my mod? It would be a great use for it, to have all my debug messages appear on there.
  7. Berserker66 Umbrella Slime

    A typical method is to just write debug to file and have another program write that into its console.
    Yes, I know its more work and a direct print would be much nicer. This is just an alternative I offer ;)
  8. plaYer2k Mouse

    Ok sorry everyone, i accidentally locked the wrong file.
    Then i unlocked it, but somehow (may be it a bug or just my slow connection) it did not unlock the file again.

    But now its UNLOCKED again and working.
    Sorry for the trouble.

    EDIT:
    @Console Output

    The current method to call the subsequent executables is really simple. Start a new process and wait untill its finished. This is really linear and does not allow communication between the "parent" and the "child" right now.
    I currently dont know much about an easy and fast way for program communication so Berserkers approach might be the one to try.

    Right now i would advice to create a console within your own mod to enable such a feature.
  9. Xemgoa Dark Caster

    This Mod looks superb but...it cannot detect my terraria on my comp, even though i have it installed, through steam ^_^;
  10. Berserker66 Umbrella Slime

    If you open a process from your program, the other programs console output should be avaiable in your stdin, or you have a special interface for it, depending on language. If you made the launcher with python I could tell you how to read & write to other consoles, but I assume you didnt use that language :p
  11. plaYer2k Mouse

    Well you have to put the "GameLauncher Installer.exe" into your Terraria directory next to your original Terraria.exe.
    ...\Steam\SteamApps\common\terraria\

    what it does then and 'why' (open)

    It requires a certain checksum for this "terraria.exe" and goes through all .exe files within its own folder to find it and therefor does not work with modified versions or when you dont have a backuped .exe

    I did it for a single and really important reason, force consistency!
    The "current method" to deliver mods are diffPatches or deltaPatches anyway so they require such a file inside the folder.
    As well as it requires that file to start terraria 1.0.6.1 since its the original file :)

    In case that does still not work, please post the error message in here :)
    Otherwise an easy bugfix is usually to verify your gamefiles.
  12. plaYer2k Mouse

    Program Update -> Release 2

    Added Console.WriteLine support.
    Now you can use the command to pass messages to the GameLauncher and display them there. No need for any internal developer console =)
    Thanks for the tip Berserker66.

    Also added details for a few error messages so they give more informations to the user and me once something happens. (just a quickjob yet)

    Some minor "fixes" and changes.

    *sorry for the doublepost but updates are important -_-*
  13. Rare Green Slime

    Download wont work for me. D=
  14. Berserker66 Umbrella Slime

    Anytime, mate ;)
  15. LNeone Slimed Zombie

    Challenge accepted, being the person who messes up everything, I will find a way to fail
  16. plaYer2k Mouse

    And how "does it not work" for you?
    What is the message you get or see once you click on the download button [IMG] ?
  17. TheMobott Doctor Bones

    Wait, does this work with the TexturePack exe? If so, *high fives*
  18. Surfpup Arapaima

    I forgot to mention this to you earlier, but if you download through filebeam on Google Chrome, it will state that the file is malicious. I recommend you use a different website for hosting your files - namely Dropbox.
  19. Rare Green Slime

    It comes up with this.
    [IMG]
  20. plaYer2k Mouse

    Iam using Chrome too and got no problem at all with that page. Strange.
    Well dropbox got a traffic limit (which i sure not break with a 6kb file) and this usually is reason enough to not use it. Also i got my folders and counter there. Well iam looking into alternatives or just a mirror.

    No wrapper are not supported since they start "Terraria.exe" which is the launcher now and NOT the actual game.
    I might find a workaround for it, but i think its more likely to just use an altered Wrapper that accesses the "TerrariaOriginalBackup.exe" instead of "Terraria.exe", and then you just need the .gli file to link it.

    Edit:
    Ok added a Mediafire mirror http://www.mediafire.com/?5t72l5kstzugkjf
Thread Status:
Not open for further replies.

Share This Page