gooby Posted July 19, 2021 Share Posted July 19, 2021 IMPORTANT! You must build your apps from the most recent upstream/development branch in order to have all the fixes and usages shown in this guide so it runs properly. You must also follow all the nuances or else your plugin may not work, so I highly suggest you use the In-Depth guides first. Introduction Spoiler This guide is made to help you get acquainted with the plugin system. I'll show you how to create, compile, and install plugins for your game. Although this is mostly a client-focused plugin walkthrough, it basically applies to the server, with the exception of it missing some callbacks (see Plugin Capabilities section below). Plugins are made in the form of DLLs and go into the respective client or server resources/plugins folder (the folder may not exist, so just create it). You may also see the Examples folder in the main directory of the development and prerelease branches for Panda's plugin examples. Ideally, you should separate your Client and Server plugin scripts to avoid errors. This also prevents others from decompiling your Client plugin DLL's and seeing your Server plugin code. It's also unnecessary to try running Client plugin code on your Server. You may also need a third project that acts as the "Core" project with classes both the client and server need access to, such as packets (not handlers!). For example, if you only want to make a client based plugin (like a main menu Discord button), you only need one project for the client. Same goes for a server only plugin, like a custom post-hook packet handler. However, if you want to add custom packets and handlers to communicate between client and server, you will need three new projects (for Core, Client, and Server DLLs). FAQs Spoiler Q: How do I compile the example plugin? A: I don't know, I couldn't get it to compile either... Plugin Capabilities Spoiler What it CAN do Spoiler Can draw a Discord button and other custom GUI Add custom network packets and handlers Can capture custom inputs See the Sample Plugins section for more... What it CAN'T do Spoiler Server does not have a GameUpdate callback Cannot draw any non-GUI sprites or text on client Custom inputs are not easily customizable like they are in the options menu. Plugin Overrides and Callbacks Spoiler Plugin Overrides Spoiler The base callbacks are OnBootstrap, OnStart, and OnStop and are available on both the client and server. See the script template below for more info as it is well-commented and provides some example code. OnBootstrap Spoiler This method is called during application bootstrapping, before OnStart is called. This method is ideally used for registering custom packets and handlers. OnStart Spoiler This method is called after basic initialization of the client. This is where you should assign any of your necessary variables, such as loading custom assets (explained later in the guide), and subscribe to Lifecycle callbacks. OnStop Spoiler This method is called when the app is shutting down. I have yet to find a use for this. Client Lifecycle Spoiler The Client lifecycle consists of several stages: Intro - during the start of the application before the menu is loaded Menu - when at the main menu Loading - the time when loading into the game, and when exiting the game and loading the menu InGame - when in the game Error - internal use, we don't need this Interface Spoiler Returns a reference to the currently loaded interface. This can be either the menu UI or the game UI. Later, I'll show you how to use this to draw your own GUI. Drawing GUI Spoiler Drawing GUI requires you to add Gwen Controls to the current interface. You can add Gwen Controls to the current interface using context.Lifecycle.Interface.Create<Control>(). You can find a full list of base controls in the other project: "Intersect.Client.Framework/Gwen/Control". The Create<> method will sometimes require parameters. This depends on the control you are creating and their constructor. You can ignore the first parameter of the constructor, which is always Base parent. The rest of the parameters are what you have to add. For example, Button's constructor is public Button(Base parent, string name = ""), so you must pass a string for its name like so: context.Lifecycle.Interface.Create<Button>("ButtonName"). For controls like RadioButton, the constructor contains no extra parameters besides the (Base parent), so nothing needs to be passed. Note that the interface will be null in OnStart. It can only be called when the main menu or the game is loaded, which ensures their respective interface has been created. Use the context.Lifecycle.LifecycleChangeState callback for that, then create your control. The interface might still be null when you try to add a control to the main menu. For some reason unknown to me, the Menu ChangeState event gets called twice. The first time it's called, the interface will be null. So before adding your control, check: if (context.Lifecycle.Interface == null) return; See the Drawing GUI section in detailed guide below for more information. There are a few callbacks to subscribe to in OnStart to get more information about GameState changes and updates: LifecycleChangeState Spoiler Invoked once whenever the GameState changes. For example, if you only want to draw something in the menu (like a Discord button), you would call the method to show the button if the args.State is GameStates.Menu. GameUpdate Spoiler Invoked once per frame in any state. This callback is useful for getting inputs, keeping track of time, etc. It should be more useful in the future as more capabilities are added to the plugins. Capturing inputs Spoiler This is a bit more complicated and tedious than I'd like, but still totally doable. In OnStart, you need to subscribe to the Intersect.Client.Core.Input events with two methods (one to handle key/mouse pressed and the other to handle key/mouse released) where both have only a Intersect.Client.Framework.GenericClasses.Keys parameter. You will also need to keep track of the keys changed that frame when the events are invoked. I used a Dictionary<Keys, bool> in the example below that is indexed by the Key pressed and if it was pressed (false) or released (true) in that frame. Optional: You may make your own KeyStates enum or add a reference to Microsoft.Xna.Framework.Input to get that enum. Then in the LifecycleUpdate callback, you just need to check if the dictionary has the key you want and if it was up or down using YourDictionary.TryGetValue. Don't forget to clear your dictionary at the end of the Update! You may go further and only allow key inputs in a certain game stage, i.e. only in game to show custom in-game menus. Here is an example script: Spoiler https://pastebin.com/Ch6YUbTs Server Lifecycle Spoiler coming later (Currently contains nothing of use.) Client Plugin Script Template Spoiler Here is a Client plugin template I created if you want to get started quickly. You will just need to change your namespace and the class name, or just copy the contents of the class to yours. (A server script will look very similar, you just wouldn't have the lifecycle callbacks.) Spoiler https://pastebin.com/xu1u7CFh Last updated: 18 July 2021 Client Plugin Guide w/ Discord Example Spoiler TL;DR: Spoiler Create a new branch from the latest upstream/development branch. Create a class library (DLL) project in the solution. Make sure to keep your client and server plugin projects separate. Create an appropriately named class in the folder that inherits from ClientPluginEntry or ServerPluginEntry. (Optionally, do this in a new folder in your plugin project.) Create another class for your Manifest. Copy and paste the example manifest (https://pastebin.com/KuhUQgND) and change the namespace and author information accordingly. Create another class for your Configuration that inherits from PluginConfiguration. Implement as many exposed properties as you wish. The app will automatically generate a JSON file when running your plugin. You can reference your config using: context.GetTypedConfiguration<YourConfig>()?.YourProperty. (Client plugin only) Subscribe to both context.Lifecycle events in OnStart. Add your custom images and other assets to your project, preferably in a separate folder. Make sure to set the "Properties > Build Option" to "Embedded Resource". You can reference them using: context.ContentManager.LoadEmbedded. Drawing GUI requires you to add Gwen Controls to the current interface. You can add Gwen Controls to the current interface using: context.Lifecycle.Interface.Create<Base>("ControlName"). (You can find a full list of base controls in: Intersect.Client.Framework/Gwen/Control.) Compile the plugin by cleaning then building your project/solution. Copy your DLL to your respective client or server's resources/plugins folder. If it doesn't exist, then make it. The project won't automatically create it. You must create another folder in this directory that has the exact same name as your DLL. Then, paste your DLL in the folder with the same name. Finally, run your application. It should automatically detect your plugin(s) and run them! In-Depth Discord Button Example This section is targeted more to beginners, but each step has a TL;DR that might be useful to follow for more informed users. Spoiler Creating a new DLL Project TL;DR: Create a new project in VS2019 using the class library (DLL) template targeting the current project framework (currently .NET Framework 4.6.2). Spoiler Open Visual Studio 2019 and create a new project. Spoiler Search 'dll' for the class library (DLL) template, select it, and press 'Next'. Spoiler Name your project. Set your save path. Make sure the 'Framework' field is set to whatever Intersect's current target framework is (currently .NET Framework 4.6.2), then click 'Create'. Installing Intersect's NuGet Packages TL;DR: Add the client or server framework package via NuGet to automatically add all the dependencies you'll need. Just press 'OK' if the 'Preview Changes' window pops up. Spoiler After your project is created and opened, the first you'll want to do is install Intersect's framework dependencies. There are two options according to what plugin you want to make: server or client. (You can always make another project in this solution for the other one.) Right-click your project and select 'Manage NuGet packages...' Spoiler Search for 'intersect' and the packages should show up. (If it doesn't, make sure your package source is 'nuget.org'.) Then, double-click and install the framework according to your plugin. We will use the Client framework for this guide. It should take a few minutes. If the 'Preview Changes' window pops up, just press 'OK'. Spoiler Setting the Build Target Spoiler The last bit of setup we need to do requires you to make a file so your plugin solution will build using the given dependency. Navigate to your computer's home directory (on Windows: "C:\Users\<name>", Mac: "/Users/<name>", Linux: "/home/<name>"). Create a new text file and rename it, including the extension, with "intersect.developer.targets". Spoiler Open the file with a text editor and copy-paste these contents into it: Spoiler <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <IntersectDeveloperTargetsImported>true</IntersectDeveloperTargetsImported> <IntersectRepoPath Condition="$(OS) != 'Windows_NT'">$(HOME)/intersect/network-optimizations</IntersectRepoPath> <IntersectRepoPath Condition="$(OS) == 'Windows_NT'">$(USERPROFILE)\intersect\network-optimizations</IntersectRepoPath> </PropertyGroup> <Target Name="BeforeBuild"> <Message Importance="High" Text="INTERSECT_REPO_PATH=$(INTERSECT_REPO_PATH)" /> <Message Importance="High" Text="INTERSECT_PATH=$(INTERSECT_PATH)" /> <Message Importance="High" Text="IntersectRepoPath=$(IntersectRepoPath)" /> <Message Importance="High" Text="IntersectPath=$(IntersectPath)" /> </Target> </Project> Change the corresponding path under 'PropertyGroup' (if Windows, change the one that says "OS == Windows", else change the other one) and the 'INTERSECT_REPO_PATH' to your Intersect repo's directory. Then, make sure to restart Visual Studio. Here's mine for comparison: Spoiler <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <IntersectDeveloperTargetsImported>true</IntersectDeveloperTargetsImported> <IntersectRepoPath Condition="$(OS) != 'Windows_NT'">$(HOME)/intersect/network-optimizations</IntersectRepoPath> <IntersectRepoPath Condition="$(OS) == 'Windows_NT'">D:\GitHub\Intersect-Engine</IntersectRepoPath> </PropertyGroup> <Target Name="BeforeBuild"> <Message Importance="High" Text="INTERSECT_REPO_PATH=$(D:\GitHub\Intersect-Engine)" /> <Message Importance="High" Text="INTERSECT_PATH=$(INTERSECT_PATH)" /> <Message Importance="High" Text="IntersectRepoPath=$(IntersectRepoPath)" /> <Message Importance="High" Text="IntersectPath=$(IntersectPath)" /> </Target> </Project> Note: If you still have issues building the plugin later on, try deleting the '.vs' folder in your plugin project's directory. Organizing the DLL project TL;DR: Create a new folder in your plugin project with a descriptive name. Create an appropriately named class in the folder that inherits from ClientPluginEntry. Spoiler Organization is important in getting the DLL to work. (Optional: You may delete the Class1.cs file that's already in your project if you want.) Create a folder in your project and name it whatever you want, preferably to reflect what plugin you're making. I'll name mine "DiscordButton". If you have multiple plugins, folders are important. Spoiler In that folder you can create a new class, preferably the same name as the folder. I'll name mine "DiscordButton.cs". Spoiler Creating your custom plugin class Spoiler Your custom class must inherit from 'ClientPluginEntry'. Spoiler 'ClientPluginEntry' will be underlined in red. All you need to do is add the using Intersect.Client.Plugins; statement at the top. Spoiler Now the base class name should be underlined in red. This is because we need to implement the base abstract class. To do this, select the class name, and click the little lightbulb icon on the left or press 'Alt + Enter' to bring up the 'Potential Fixes' menu. Then, select 'Implement abstract class'. It will automatically generate the methods you need: OnStart and OnStop. Spoiler You should also remove the exceptions to leave the methods empty so the process doesn't get stopped when running the DLL. Your class should now look like this: Spoiler Defining a Manifest TL;DR: Create another class adjacent to your custom plugin entry. Copy and paste the example manifest in this section and change the author information accordingly. Spoiler Another thing the plugins require is a manifest. The manifest is defined as another C# class with the author's information. Create another class in your custom plugin folder so it's alongside your plugin entry class and name it something appropriate. Mine will be 'DiscordButtonManifest'. Spoiler Admittedly, I copied the code from the example and changed it to fit my needs. Here's Panda's original example manifest: Spoiler https://pastebin.com/KuhUQgND Do not change the struct name just yet! You'll notice many errors in the document. Adding these using statements at the top should fix it: Spoiler using Intersect.Plugins.Interfaces; using Intersect.Plugins.Manifests.Types; using Intersect.Utilities; using Semver; (Optional) Finally, if you want to change the name, select the struct name and press 'Ctrl + R + R'. This will bring up the renaming menu for you to change. Also, make sure to change the 'Author' and 'Homepage' field information to your own profile/website. Here is this example's manifest script for comparison: Spoiler https://pastebin.com/E9Jg2fBd Creating a Configuration File TL;DR: Make another appropriately named class for your config that inherits from PluginConfiguration. Implement as many exposed properties as you wish. The app will automatically generate a JSON file when running your plugin. Spoiler Now, you can make a plugin with just the manifest and it'll work. It will generate an empty config file for you. So, you can skip this step if you don't want to do it right now, but I highly recommend coming back and adding properties to your config for modularity; so you don't always need to change the code in order to change the plugin values. Instead you would change your property values via a JSON file in your plugin's directory, like you'd do with the GUI layouts, for example. That being said, make a new class in the same subfolder as your other scripts and call it something appropriate. I'll name mine 'DiscordButtonConfig'. Spoiler Your class must inherit from 'PluginConfiguration', which requires the 'using Intersect.Plugins;' using statement at the top. Spoiler That's it for the config setup! Now, you just need to add properties you want to read from your plugin entry class. For this discord button example, I'm just going to add a string to the invite URL. Spoiler Referencing your config file You can reference your config file and its properties from your plugin entry script as such: var propertyRef = context.GetTypedConfiguration<YourConfig>()?.YourProperty; where the 'context' is a reference to the client context (provided by the callback methods), 'YourConfig' is the name of your config script, and 'YourProperty' is the property or field you want to reference. See the provided example or keep reading for more details. Using the Client Lifecycle TL;DR: Subscribe to both context.Lifecycle events in OnStart. Spoiler Please see the Client Plugin Overrides and Callbacks section or the script template for more info about the lifecycle. You can get access to the Lifecycle from the context parameter. Make sure to include the "using Intersect.Client.General;" using statement at the top. Spoiler You can open a switch statement for the args.State for both callback method to specify the GameState. Make sure to include the "using Intersect.Client.General;" to get access to the GameStates enum. Spoiler Adding custom assets TL;DR: Add your custom images and other assets to your project, preferably in a separate folder. Make sure to set the 'Properties > Build Option' to 'Embedded Resource'. You can reference them using context.ContentManager.LoadEmbedded. Spoiler The plugin system is able to load embedded assets to be used in your plugin. For example, for a Discord button, you'll probably need an image that says "Join our Discord!" or something. Make another subfolder in your plugin folder where all the scripts are, and call it "Assets" (you can name this whatever you want). Spoiler You can then right-click the folder, hit 'Add > Existing item' and choose the image, or just drag and drop it on the folder. (I'm stealing this from Panda's example as well. ) Spoiler This part is crucial for loading the asset. Right click the file you added and select 'Properties'. Then change its "Build Action" to "Embedded Resource". Spoiler Referencing the asset You can use the built-in Content Manager to load embedded resources in your DLL. Just make sure your subdirectory is correct. Here would be the example reference: context.ContentManager.LoadEmbedded<GameTexture>( context, ContentTypes.Interface, "DiscordButton/Assets/join-our-discord.png" ); Drawing GUI TL;DR: You can add Gwen Controls to the current interface using context.Lifecycle.Interface.Create<Base>("ControlName"). You can find a full list of controls in the other project: "Intersect.Client.Framework/Gwen/Control". Spoiler The current Interface can be accessed from context.Lifecycle. You need to use this interface to add controls by using its Create function. You can create any Gwen base control, such as Button, ImagePanel, Label, etc. There is a full list of controls in Intersect.Client.Framework/Gwen/Control folder. These will require a "using Intersect.Client.Framework.Gwen.Control;" statement. Creating a control also requires exactly ONE argument, which is the control's name. You can name this whatever you want. For example, the discord button will be created as such: var button = context.Lifecycle.Interface.Create<Button>("DiscordButton"); From here on you can change the settings of these controls like you normally would. (If you wanted more info about how to use these controls, well... it's out of the scope of this tutorial. You can see the full example script in the next step to get an idea, but Gwen controls are a different tutorial for a different day.) Coding the actual plugin TL;DR: This section is not that long dude. Spoiler After all the setup, we can finally program the plugin! This will depend on what you are doing. For this example, we will draw the GUI button in the bottom right corner of the main menu. The script looks like this: Spoiler https://pastebin.com/eQyTJHp1 Compiling and Installing the Plugin TL;DR: Compile the plugin by cleaning then building your project/solution. Copy your DLL to your respective client or server's resources/plugins folder. If the directory doesn't exist, then make it. The project won't automatically create it. You must create another folder in this directory that has the exact same name as your DLL. Then, paste your DLL in the folder with the same name. Spoiler To compile the plugin, simply right click your project and select "Clean", then right-click again and select "Build". (If you are having issues building, go back to the "Setting the Build Target" section.) Spoiler The plugin will be created in your default directory in a folder under the same name. Spoiler Go into your folder and navigate to bin/debug/YourPluginName.dll. This will be the file you copy and paste into your client plugins folder. Spoiler Go into your client (or server) folder, then navigate to resources/plugins. If the folder doesn't exist, create one. Spoiler This is an important step: you must create another folder that has the same name as your DLL. Mine would be "Client.Plugins". Then paste your DLL into that folder. Spoiler And that's it! If you built your client with the proper development version, and everything went well, your plugin should now work! Spoiler Adding Custom Packets and Handlers Spoiler Note: You will need all three (Core, Client, and Server) plugin projects to make custom packets. See TL;DR above if you don't understand what this means. However, this section assumes you already went through the detailed example guide and know how to add references on your own (basically hit Alt+Enter on any errors and add the reference). Setting up the Packet class Spoiler Packet classes must go into your Core project because both the Client and Server plugins will need to reference them. Create a new class that inherits from IntersectPacket in your Core project. Your Core plugin project will need to reference Intersect's Core project because it needs the MessagePack namespace. MessagePack requires you to use the [MessagePackObject] attribute on your class. Each one of your declared fields (if any) must also have the [Key(#)] attribute, where # indicated a number. They need to be numbered in order starting from 0. (MessagePack might also require a parameterless constructor to work. I've got it to work without one, but not always... so, if you create a constructor with parameters, I'd also create an empty one just to be safe. Needs confirmation.) Example packet class: Spoiler using Intersect.Network; using MessagePack; namespace Core { [MessagePackObject] public class ClientTestPacket : IntersectPacket { [Key(0)] public string Message; } } Setting up the PacketHandler class Spoiler Packet handler classes go into your respective Client or Server projects. Create a new class in the project that inherits from IPacketHandler<YourPacket>. This will require a project reference to your Core Plugins project. You will then need to implement the abstract class which will create two different Handle methods, both with two parameters. The one with the generic "IPacket packet" parameter (likely the second one) just needs to call the other Handle method. Most of the time, it'll look like this: Spoiler public bool Handle(IPacketSender packetSender, IPacket packet) { return Handle(packetSender, packet as YourPacket); } The other method just needs to handle the packet as you wish. Spoiler public bool Handle(IPacketSender packetSender, YourPacket packet) { // Your packet handling logic here return true; } For this section's ongoing example, it'll just print the message sent and the class would look like this: Spoiler using System; using Core; using Intersect.Network; namespace Server { public class ClientTestPacketHandler : IPacketHandler<ClientTestPacket> { public bool Handle(IPacketSender packetSender, ClientTestPacket packet) { Console.WriteLine("Received client msg:" + packet.Message); return true; } public bool Handle(IPacketSender packetSender, IPacket packet) { return Handle(packetSender, packet as ClientTestPacket); } } } Registering Packets and Handlers Spoiler Registering packets and handlers is done in OnBootstrap because you need its context. You must register all of your custom packets that you will handle or send. Below is a simple example; ideally you should also log errors and close the app if the registry fails. Spoiler public override void OnBootstrap(IPluginBootstrapContext context) { RegisterPackets(context); RegisterPacketHandlers(context); } void RegisterPackets(IPluginBootstrapContext context) { context.Packet.TryRegisterPacketType<ClientTestPacket>(); context.Packet.TryRegisterPacketType<ServerTestPacket>(); } private void RegisterPacketHandlers(IPluginBootstrapContext context) { context.Packet.TryRegisterPacketHandler<ServerTestPacketHandler, ServerTestPacket>(out _); } Sending packets Spoiler On the client: The PacketSender can be referenced using the ClientContext provided by OnStart and Update methods. For example: Spoiler context.Network.PacketSender.Send(new ClientTestPacket { Message = "Hello server, I'm client" }); On the server: Currently, the PacketSender is only available via packet handlers. For example, if we use the code above to send a message from the client to the server, the server can then send a message back in its ClientTestPacketHandler method: Spoiler public class ClientTestPacketHandler : IPacketHandler<ClientTestPacket> { public bool Handle(IPacketSender packetSender, ClientTestPacket packet) { Console.WriteLine("\nReceived important Client msg:\n" + packet.Message +"\n"); packetSender.Send(new ServerTestPacket { Message = "Hello client, am serv" }); return true; } public bool Handle(IPacketSender packetSender, IPacket packet) { return Handle(packetSender, packet as ClientTestPacket); } } Conclusion Spoiler This guide should have helped you compile, create, and install your plugins successfully. You have a working Discord button plugin for your client at the very least. While this plugin system has lots of potential as it is, it still needs work, and it is still being worked on time to time. If you have any questions or comments about plugins or how to improve this guide, please leave them below! Arufonsu, HelenaToDev, nvh and 1 other 3 1 Link to comment Share on other sites More sharing options...
nvh Posted July 19, 2021 Share Posted July 19, 2021 Goob job ✊🏻 Lancelot and gooby 2 Link to comment Share on other sites More sharing options...
Arufonsu Posted July 20, 2021 Share Posted July 20, 2021 this is amazing, way more convenient than work and release niche/game specific mods in .patch files (for the non-programmer users, may be as easy to drag n' drop the compiled plugins ! ) -> in the other hand, wouldn't it open the risk of sus/infected plugins being distributed in the future? convenience may often come with few cons, yet this is amazing, thanks for this guide! Link to comment Share on other sites More sharing options...
gooby Posted July 20, 2021 Author Share Posted July 20, 2021 8 hours ago, Arufonsu said: this is amazing, way more convenient than work and release niche/game specific mods in .patch files (for the non-programmer users, may be as easy to drag n' drop the compiled plugins ! ) -> in the other hand, wouldn't it open the risk of sus/infected plugins being distributed in the future? convenience may often come with few cons, yet this is amazing, thanks for this guide! Yeah i suppose youre right... so dont download and install DLLs from strangers! Link to comment Share on other sites More sharing options...
Weylon Santana Posted July 20, 2021 Share Posted July 20, 2021 Dude you explained everything about plugins and explained how to create plugins and detailed how the discord button plugin works as if you were talking to monkeys and that was EXACTLY what I needed. Thank you so much for taking the time to create something so (not so anymore) complex. I'm learning C# (when I have time) so as soon as possible I'll follow your tutorial and get back to you if everything went well. gooby 1 Link to comment Share on other sites More sharing options...
panda Posted July 20, 2021 Share Posted July 20, 2021 9 hours ago, Arufonsu said: this is amazing, way more convenient than work and release niche/game specific mods in .patch files (for the non-programmer users, may be as easy to drag n' drop the compiled plugins ! ) -> in the other hand, wouldn't it open the risk of sus/infected plugins being distributed in the future? convenience may often come with few cons, yet this is amazing, thanks for this guide! I mean all of you downloaded Intersect for years before it was open source. If anything, the plugin system could open up an easier avenue for people to make cheats for games. gooby 1 Link to comment Share on other sites More sharing options...
Arufonsu Posted July 21, 2021 Share Posted July 21, 2021 On 7/20/2021 at 8:09 AM, panda said: I mean all of you downloaded Intersect for years before it was open source. Guess i joined in the party sort of late, it was already Open Source when i first found about you guys The security risks are always going to be there anyway, not something we should ignore and simply let anyone release any .dll around forums without double checking that everything is safe! Anyway, that was just a small offtopic that people tend to forget about , didn't meant to bring down the party to anyone and i think myself that this right here is a big step into the moon for this game engine cheers u guys, and once again, thanks for this guide @gooby ! gooby 1 Link to comment Share on other sites More sharing options...
Weylon Santana Posted July 22, 2021 Share Posted July 22, 2021 @gooby I finished reading and writing your tutorial today, I loved it, I'm not a programmer and I barely know how to program, I only know very basic concepts and the way you explained I understood everything perfectly well, I could even put the button inside the game (if (lifecycleChangeStateArgs.State == GameStates.Menu || lifecycleChangeStateArgs.State == GameStates.InGame)) ( just to test if it would work and it did). Thanks for your time in doing this. I would like to know (in case you want to add it in your tutorial in the future as an optional thing), how to generate those json files that are generated in the gui so we could change the position of the button through the json file, how does it work for the rest of the interface? It would be possible? gooby 1 Link to comment Share on other sites More sharing options...
jcsnider Posted July 22, 2021 Share Posted July 22, 2021 8 minutes ago, Weylon Santana said: I would like to know (in case you want to add it in your tutorial in the future as an optional thing), how to generate those json files that are generated in the gui so we could change the position of the button through the json file, how does it work for the rest of the interface? It would be possible? Somewhere in the code for that button there will be a line to load the ui from json. If that json file is not found, it will be created with default/empty values automatically in which you can then modify. (So you don't need to worry about manually creating the json file) Link to comment Share on other sites More sharing options...
Weylon Santana Posted July 22, 2021 Share Posted July 22, 2021 1 minute ago, jcsnider said: Somewhere in the code for that button there will be a line to load the ui from json. If that json file is not found, it will be created with default/empty values automatically in which you can then modify. (So you don't need to worry about manually creating the json file) Are you referring to this plugin code? https://pastebin.com/eQyTJHp1(At the end of the tutorial this is what the main script looks like) or to the official intersect plugin that panda made? Link to comment Share on other sites More sharing options...
jcsnider Posted July 22, 2021 Share Posted July 22, 2021 20 minutes ago, Weylon Santana said: Are you referring to this plugin code? https://pastebin.com/eQyTJHp1(At the end of the tutorial this is what the main script looks like) or to the official intersect plugin that panda made? Ignore me. The example plugin does not load from a dedicated json file. Weylon Santana 1 Link to comment Share on other sites More sharing options...
panda Posted July 22, 2021 Share Posted July 22, 2021 24 minutes ago, jcsnider said: Ignore me. The example plugin does not load from a dedicated json file. Correct, it does not load UI position from the JSON file. It only loads the URL. Weylon Santana 1 Link to comment Share on other sites More sharing options...
gooby Posted July 22, 2021 Author Share Posted July 22, 2021 3 hours ago, Weylon Santana said: I would like to know (in case you want to add it in your tutorial in the future as an optional thing), how to generate those json files that are generated in the gui so we could change the position of the button through the json file, how does it work for the rest of the interface? It would be possible? yeah what they said ^ you could also add those values to your config script and then people could just modify them through the JSON it generates. then, just load those values before drawing your button in the plugin script Weylon Santana 1 Link to comment Share on other sites More sharing options...
Weylon Santana Posted July 22, 2021 Share Posted July 22, 2021 4 hours ago, gooby said: yeah what they said ^ you could also add those values to your config script and then people could just modify them through the JSON it generates. then, just load those values before drawing your button in the plugin script I like it, this is a good alternative, I will try to look at how the url property value is obtained and I will try to replicate for position and size, I will do that soon, can I call you in discord if I have any questions, if doesn't bother you? Link to comment Share on other sites More sharing options...
gooby Posted July 22, 2021 Author Share Posted July 22, 2021 Updated the guide to use NuGet package dependencies instead of making a new branch off the upstream/development repo. If you were having issues, try it out now Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now