What's new
  • Visit Rebornbuddy
  • Visit Panda Profiles
  • Visit LLamamMagic
  • Visit Resources
  • Visit Downloads
  • Visit Portal

Overview of the new upcoming 3rd party content loading system

pushedx

Well-Known Member
Joined
Sep 24, 2013
Messages
4,252
Reaction score
290
Outdated - The new system makes use of a single 3rdparty.json file. Please see this post for the new tool, but the concepts talked about in this thread are still relevant: https://www.thebuddyforum.com/threads/exilebuddy-3-0-reference-thread.406684/#post-2523724

[About]


As Exilebuddy continues to grow and evolve, we're always looking for better ways to do things so life is easier for everyone. One area that has been in need of improvement is how 3rd party code is distributed by users and loaded by the bot. Right now, users must download compressed files, extract them in a specific location, ensure the folder name is correct for the assembly, and then manage keeping things up-to-date. This works, but is the cause for a lot of inconvenience on both the users and devs, which results in more support issues we have to handle.

This thread will go over a new system we've been working on to greatly simplify the way things are. I should start out by mentioning the current system in place will continue to work as-is and will not change, as we do not want to force this new setup on everyone, but rather let them transition to it at their own pace. However, barring unforeseen side-effects, we'd expect everyone to adopt this system because it will make life easier all around, and requires little extra work for devs to make work.

[Devs]

Please keep in mind the current BosslandGmbH Forum Rules & Guidelines still apply!

There's two main things devs need to do to make use of this new system. First, they need to create a text file, "3rdparty.txt" in their root content folder. The contents of this file simply need to be the exact assembly name of their content, as the bot uses this to create the folder and compile the code.

For example: The current MapRunner plugin is distributed as "MapRunner1.6.2.zip". If you open this file, you'll see a subfolder, "MapRunner". "3rdparty.txt" would go inside the "MapRunner" sub-folder, as the root folder is where all the main content is. The contents of "3rdparty.txt" would simply be "MapRunner".

Another example: The current AIF plugin is distributed as "AdvancedItemFilter 1.0.2.3.zip". If you open this file, you'll see the main content, so "3rdparty.txt" would go into the zip itself and not any other folders. The contents of "3rdparty.txt" would simply be "AdvancedItemFilter".

For any 3rd party content that does not make use of external non-code files, such as images, or data files, their zips would now be compatible and ready to use with the system. 3rd party content which make use of external non-code files will need to update how they reference said files.

To simplify this process, the new ThirdPartyLoader exposes an API function, GetInstance, that allows users to get a ThirdPartyInstance object that stores all the relevant information they will need need. The ThirdPartyInstance object exposes the Name of the instance, the ContentPath and CompiledPath, as well as instances for the various types: BotInstances, PluginInstances, RoutineInstances.

For example, the current AIF code for loading images, works as follows:
Code:
var imageFolderUrl = new Uri(AppDomain.CurrentDomain.BaseDirectory + "Plugins/AdvancedItemFilter/Images", UriKind.RelativeOrAbsolute);

This code works in the current setup, because plugins go into the Plugins folder, and the AIF folder should be named, AdvancedItemFilter, so the path should exist if the user extracted correctly. In the new system, this code would not work because the paths are different. This is how the code would look if it were to be compatible with the new system:
Code:
var instance = ThirdPartyLoader.GetInstance("AdvancedItemFilter");
var imageFolderUrl = new Uri(Path.Combine(instance.ContentPath, "Images"), UriKind.RelativeOrAbsolute);

In that code, the AIF instance is loaded from the ThirdPartyLoader. Devs should obviously check for null in case their code is not being used from the ThirdPartyLoader. Once the instance is obtained, the ContentPath provides the new root content folder for the assembly, so any data files can be referenced from that.

Those are the only two changes required to make things work. Some plugins might need a few more changes, because there's no post detailing best practices for 3rd party code, but I'll work on making such guides in the near future. The biggest difference is that there's no specific load order for Bots/Plugins/Routines, so if your Routine or Plugin assumed there was a bot already loaded and selected, that would no longer be the case. The solution for that is to defer such logic so it only executes in Start, where the current bot will be valid.

Support has now been added for loading content via folders. This means you can load 3rd party content from folders the same way as the current Bots/Plugins/Routines layout does, without having to make a zip file. The folder layout has to mirror the zip layout; you need a "3rdparty.txt" file in your content folder's root, so the files get copied into the locations they should be.

[End-Users]

End users will simply have to open up the "3rdParty" folder Exilebuddy creates, and copy over compatible zip files of the 3rd party content they want to use. That's it! It's best to start with a clean bot installation, to avoid having old copies of 3rd party content in the Bots/Plugins/Routines folder though. Non-compatible zips (those that do not contain a "3rdparty.txt" file) will simply be ignored.

To update 3rd party content, users will just need to delete the old zip file, then copy over the new one. The bot will take care of cleaning up the old content and extracting the new.

There are no more Bots/Plugins/Routines folders for users to deal with. Content will be auto-extracted to a base path of "3rdParty/ConfigurationName/AssemblyName". A "Content" folder will hold all of the extracted content. A "Compiled" folder will hold the compiled artifacts the bot generates and loads.

This structure is used so people can continue to use multiple bots from the same folder, and it solves the issue of simultaneously running bots at the same time, as each bot will need it's own configuration name regardless. Furthermore, only the active configuration's folder contents will be affected, avoiding an issue where in the current setup, all folders are deleted and any files in use are simply ignored.

Users that wish to make changes to 3rd party source code still can, with a few caveats. First, they must run the bot to have the content extracted. The "Content" folder is deleted and replaced when the 3rd party content zip changes. This is tracked by a file placed in each "Content" directory, "do_not_delete.txt". This text file contains the MD5 hash of the zip file, so when it does not match, the current "Content" folder is deleted, and the new zip archive will be extracted in place of it. If a user deletes the "do_not_delete.txt" file, then the bot will delete the "Content" folder, and re-extract the zip contents for them, making a new "do_not_delete.txt" file with the current content zip hash.

Users that want to use folders instead of zips can now as well. The process is the same, except content from a folder always overwrites existing content for the current configuration. To update content, it's best to delete the old folder, and copy over the new content to avoid any issues with your source folder mixing old and new files that were deleted or renamed. Please keep in mind, you cannot load the same content from a zip and a folder at the same time, since the assembly names would overlap! For any specific 3rd party content, you need to use the zip or the folder.

That's all there is to it.

[Misc]

The standard Windows Zip format needs to be used. Most programs are capable of providing compatible zips, but things like WinZip might allow incompatible formats with some options, likewise with 7-zip if you try to mess with compression. Please test your zips with the built-in windows unzipping feature to see if it'll work. ThirdPartyLoader uses System.IO.Compression's ZipArchive class to handle things.

GuiSettings.Instance.ContentOrder is used to specify the content processing order. The actual loading of content is done in a multithreaded approach to help speed up EB, and cannot be controlled. However, support for loading specific content in order exists again. To do this, content developers simply need to add an empty text file named "3rdparty-required.txt" alongside "3rdparty.txt" and the bot will load that content first synchronously. This is for base library content commonly used by other plugins, such as EXtensions or CommunityLib.

Support has been added to let content developers specify which files are loaded and compiled. This feature was added to help content providers that have a lot of files, which some might be deleted over time and are no longer needed. While using the zip system avoids this issue altogether, the issue can exist when the folder system is used. Content developers simply need to add a text file, "3rdparty-files.txt", alongside their "3rdparty.txt". The contents of this file should be relative paths of the content to include from the root folder. Any files with "3rdparty" in them do not need to be added.

This image provides an example.
FdNhwq6.png

Alternatively, here's the source to ThirdPartyFileGenerator, which can be ran from a ready to deploy content distribution that will generate the "3rdparty-files.txt" file for you:
Code:
using System;
using System.IO;
using System.Text;

namespace ThirdPartyFileGenerator
{
    class Program
    {
        static void Main(string[] args)
        {
            var sb = new StringBuilder();
            var baseDir = AppDomain.CurrentDomain.BaseDirectory;
            foreach (var file in Directory.GetFiles(baseDir, "*.*", SearchOption.AllDirectories))
            {
                if (file.ToLowerInvariant().Contains("3rdparty"))
                    continue;

                var ext = Path.GetExtension(file).ToLowerInvariant();
                if (ext.Equals(".dll") || ext.Equals(".exe"))
                    continue;

                sb.Append(file.Replace(baseDir, ""));
                sb.AppendLine();
            }
            File.WriteAllText("3rdparty-files.txt", sb.ToString());
        }
    }
}

This system is now officially in use, and the old system has been removed.
 
Last edited:
This thread is now open for discussion! I'll put any summary changes or Q/A in this post. A Beta build containing this system will be built soon TM.
 
STAP BREAKING THE BOT DREW!


no rly, thanks for making me work more then I have to to get cool features, to fix my issues. Thanks... ;P.
 
Must be missing something here, but I don't see how this makes things any easier? For my plugins I just right click and create a .zip, tell people which folder to extract it into, and everything works. To update, they just delete the old version and install the new one. I don't see how the new system really streamlines the process at all, except that I don't need to tell them which folder to extract into.
 
Must be missing something here, but I don't see how this makes things any easier? For my plugins I just right click and create a .zip, tell people which folder to extract it into, and everything works. To update, they just delete the old version and install the new one. I don't see how the new system really streamlines the process at all, except that I don't need to tell them which folder to extract into.

they put the zip file into a folder, and the bot do the rest. it also involves the possibility for EB to support dynamic reloading, which means easier debugging/dev for us

less hassle for the users & devs, sounds right to me.
 
they put the zip file into a folder, and the bot do the rest. it also involves the possibility for EB to support dynamic reloading, which means easier debugging/dev for us

less hassle for the users & devs, sounds right to me.
So it literally saves them right clicking, choosing 'extract' and picking the right folder (three clicks), and instead we have to add a .txt and change our code for loading images/data. It also means they have to do a bunch of messing around to alter the source code of plugins if there's a minor tweak they want to make. Dynamic reloading just means we won't have to close EB and reopen it, a process that takes two clicks. Again, this seems totally pointless and if anything more annoying in some ways, unless I'm not understanding something.
 
So it literally saves them right clicking, choosing 'extract' and picking the right folder (three clicks), and instead we have to add a .txt and change our code for loading images/data. It also means they have to do a bunch of messing around to alter the source code of plugins if there's a minor tweak they want to make. Dynamic reloading just means we won't have to close EB and reopen it, a process that takes two clicks. Again, this seems totally pointless and if anything more annoying in some ways, unless I'm not understanding something.
You are mis-understanding something, because you do not heavily dev.

1 - This means, those who use SVN, will not have to worry about threads poping up with the same error ( Ie, QuestPlugin is the correct name, SVN zip names it questplugin, which throws an error)
with a zip, users just replace the old zip with the new one.

2 - You are a dev, more work is how devs, well dev.

3 - They do not have to do any messing around, if they choose to alter the source, it is of their own violation, and any errors, is also a fault of theirs. Devs do not have to constantly reply to the same issues. Devs should make their code flexible, so the end user does not need to do any "minor tweaks". Settings that effect the behaviour of plugins/bots, should be able to be altered from the GUI, not through the source code.

4 - A process that " a process that takes two clicks" and 10+ seconds for the bot to load, if you have more plugins, more seconds. This affirms you do not do much deving, as this is a constant issue for us, therefore a reloading of plugins/recompiling of code is godsend.
 
You are mis-understanding something, because you do not heavily dev.

1 - This means, those who use SVN, will not have to worry about threads poping up with the same error ( Ie, QuestPlugin is the correct name, SVN zip names it questplugin, which throws an error)
with a zip, users just replace the old zip with the new one.

2 - You are a dev, more work is how devs, well dev.

3 - They do not have to do any messing around, if they choose to alter the source, it is of their own violation, and any errors, is also a fault of theirs. Devs do not have to constantly reply to the same issues. Devs should make their code flexible, so the end user does not need to do any "minor tweaks". Settings that effect the behaviour of plugins/bots, should be able to be altered from the GUI, not through the source code.

4 - A process that " a process that takes two clicks" and 10+ seconds for the bot to load, if you have more plugins, more seconds. This affirms you do not do much deving, as this is a constant issue for us, therefore a reloading of plugins/recompiling of code is godsend.

2dd.jpg


On a serious note, "Settings that effect the behavior of plugins/bots, should be able to be altered from the GUI, not through the source code" is a good idea since majority of people can't code or follow simple directions! I'm all for it!
 
Last edited:
You are mis-understanding something, because you do not heavily dev.

1 - This means, those who use SVN, will not have to worry about threads poping up with the same error ( Ie, QuestPlugin is the correct name, SVN zip names it questplugin, which throws an error)
with a zip, users just replace the old zip with the new one.

2 - You are a dev, more work is how devs, well dev.

3 - They do not have to do any messing around, if they choose to alter the source, it is of their own violation, and any errors, is also a fault of theirs. Devs do not have to constantly reply to the same issues. Devs should make their code flexible, so the end user does not need to do any "minor tweaks". Settings that effect the behaviour of plugins/bots, should be able to be altered from the GUI, not through the source code.

4 - A process that " a process that takes two clicks" and 10+ seconds for the bot to load, if you have more plugins, more seconds. This affirms you do not do much deving, as this is a constant issue for us, therefore a reloading of plugins/recompiling of code is godsend.
Fair enough, I guess if you're doing a lot it might be more useful. Never personally had a problem with any of those things but the new system is optional so it's all good.

-snip-

On a serious note, "Settings that effect the behavior of plugins/bots, should be able to be altered from the GUI, not through the source code" is a good idea since majority of people can't code or follow simple directions! I'm all for it!
Agreed, but that's not always the case. My Ouroboros routine started out by allowing the AOE radius of 20 which was hardcoded into OldRoutine to be changed.
 
Must be missing something here, but I don't see how this makes things any easier? For my plugins I just right click and create a .zip, tell people which folder to extract it into, and everything works. To update, they just delete the old version and install the new one. I don't see how the new system really streamlines the process at all, except that I don't need to tell them which folder to extract into.

The new system is optional now, but will replace the old one in the near future as support for folders currently exists. The only extra work people will have to do, is adding the text file with their assembly name, and fixing external paths to the new system.

In terms of dev benefits, think about it this way: a new standardized way of referencing your content's source/compiled folder has been added. The limitations of the current system in requiring partially hard-coded paths is bad design, and leads to all of the user problems that you see with renamed folders, different cases, and users not being sure how to "install content" correctly (yes, people have tried running plugins from bots/routine folders).

With the new system, with very little actual work, devs can simply give users a zip, say put it in this folder, and they are good to go. This is a huge difference, even though it might not seem like it at first glance. It's fair to ask why is this needed, but it's more apt to ask, why don't we support it? The inspiration for this system was actually the way mods work in Minecraft. You download content, drop it in a folder, then run the game and you're good to go 99% of the time. Sometimes, you do need to edit settings, but the content should load and generate the default settings you need to edit after you run it the first time.

With folder support, the problem of renamed/deleted files is eliminated with the destination folders being refreshed each run. In addition, the configuration design avoids the current system's issue when trying to load multiple bots at the same time. You won't be forced to use zips though, so you won't be inconvenienced if you need to make minor source edits, as you simply apply them to the root folder contents. If you need to make different separate edits to code in different configurations, then the code itself needs a design update to avoid that. Furthermore, the new standardized way to referencing your content/compiled folder also applies, so everything is on the same page.

The talks of the code reloading were from other discussions I've had with wanting to support other things, but the primary reason for this system is to address usability issues, which we're almost seeing at least 1 post daily about. Sure, we can always tell devs to fix their distributions, but we haven't had any official guidelines or systems in place for it. The core issue results from the way .Net works with baml, so it's unavoidable. While this system isn't going to revolutionize anything, it's a good step in terms of progress and QoL improvements EB has had a reputation of lacking in the past.

Hopefully that sheds some more light on my mindset for this topic. :)
 
and since this required pushedx do do the hardest part of the job, and i love to consider this a little fair community, pls let all together trow a sane:

Tnx YOU pushedx for this.
 
On a practical note, for the end users. If I'm updating the bot and want to jump on board, I need to load any zip files that have the text file into the 3rdParty folder, leave them be. For those that do not, do we load them into the 3rdParty folder as well or into the destination folder like we used to (StashBuddy for example)?

Say if I want to modify a file (always end up modifying routines for the most part) that is contained in a zip, should I modify the file in the zip, or only modify the file once it has been extracted (ie once the bot has been run once)?

Also, what is going to happen with older plugins that still work for the most part but their dev is no longer active (StrongboxCrafter or MinionSupportPlugin)?
 
Last edited:
On a practical note, for the end users. If I'm updating the bot and want to jump on board, I need to load any zip files that have the text file into the 3rdParty folder, leave them be. For those that do not, do we load them into the 3rdParty folder as well or into the destination folder like we used to (StashBuddy for example)?

Say if I want to modify a file (always end up modifying routines for the most part) that is contained in a zip, should I modify the file in the zip, or only modify the file once it has been extracted (ie once the bot has been run once)?

Also, what is going to happen with older plugins that still work for the most part but their dev is no longer active (StrongboxCrafter or MinionSupportPlugin)?

Basically, all your 3rd party content simply goes into the 3rdparty root folder, zip or folder. You never want to copy into _CONFIGS_ because the bot will only load content based on the root 3rdparty folder itself. I forgot to mention it, but this was done to address the issue of wanting to not load a bot/plugin/routine at all, but in the current system, you have to delete the folder entirely. Now, you can just delete/rename the 3rdparty.txt file (or the zip) and loading will be skipped.

For your example, you'd most likely want to just extract the zip into the root content folder, delete the zip, then make your changes. As long as it had the correct layout with the 3rdparty.txt file, it'll get copied into your configs folder with any changes you made. The zip processing is just a convenience shortcut for your average user who wants to download and go with 3rdparty content that doesn't require source modifications.

When the system eventually changes (there's no rush honestly), someone will simply need to make the changes listed for compatibility, that's it. If it's just a matter of adding a file to a zip, I'm sure someone can manage that easily. If the plugin uses hard-coded paths, then the code will need more updates, but it shouldn't be too hard for someone to do. That's in the future though, and it's more likely that API breaking changes break such code before this system does. :)
 
This system is now officially in place, and the old loading methods will no longer work.
 
Back
Top