Difference between revisions of "User:FallenAvatar/Code Based Mod"

From wiki
Jump to: navigation, search
m (fixing image)
m
Line 10: Line 10:
  
 
To create a new Code Based Mod:
 
To create a new Code Based Mod:
 +
[[File:code-based-mod_new-project.png|thumb|x150px|Your New Project dialog may not look exactly like this.]]
 
* '''Open''' Visual Studio
 
* '''Open''' Visual Studio
 
* '''Create''' a New Project (File > New > Project)
 
* '''Create''' a New Project (File > New > Project)
Line 18: Line 19:
 
* Pick where you want your mod saved
 
* Pick where you want your mod saved
 
* Click '''Ok'''
 
* Click '''Ok'''
 
[[File:code-based-mod_new-project.png|New Project]]
 
'' Your New Project dialog may not look exactly like this.''
 
  
 
== Setting Up The Project ==
 
== Setting Up The Project ==
Now the project needs to be setup to recognize Staxel's code and directories.
+
Now the project needs to be setup to recognize Staxel's code and build itself correctly for debugging.
* '''Add a Reference
+
[[File:code-based-mod_add-reference.png|thumb|x150px|Add References]]
 +
* '''Add a Reference''' by Right-Clicking the Project and selecting Add > Reference
 +
** Click Browse at the bottom right and navigate to where Staxel is installed, and open the bin folder.
 +
*** For Staxel on Steam on Windows, this is likely "C:\Program Files (x86)\Steam\steamapps\common\Staxel\bin"
 +
** Hold Ctrl (Control) and select:
 +
*** Plukit.Base.dll
 +
*** Staxel.dll
 +
** Click Add
 +
** Click Ok
  
This sets it so that it builds in a manner that Staxel will be able to access. After this, let it create the solution.
+
''The project is now able to be built and loaded as a Mod, of course it doesn't do much at the moment''
 
+
After this file is set up, it's time to add references to Staxel's .dll files. Right-Click on the project (not the solution) in the Solution explorer then go to "Add" and then "Reference..."
+
 
+
When the window opens, click on Browse at the bottom of the window, then navigate to where Staxel stores its files. When there, head to the "bin" folder and select both "Staxel.dll" and "Plukit.Base.dll", as both of these are needed for the code below. Other .dll files may be needed at a later time.
+
 
+
You are now setup for creating a mod.
+
 
+
 
+
= Helpful Tips =
+
 
+
'''Note:''' If possible, use a refactor service to implement shell versions of a given interface. Visual Studio 2015 has this by default. Third-party add-ons, like JetBrains ReSharper, can also do this alongside other features that make development considerably easier. It can be obtained at https://www.jetbrains.com/resharper/.
+
 
+
 
+
= Contents of a mod =
+
 
+
For the most part, contents of code is left up to the user. However, you must implement certain interfaces in order for Staxel to run your program's code.
+
 
+
A good starting place would be to implement this interface made for modding:
+
  
 +
* Add a new Text File and name it StaxelMod.mod
 +
** Replace StaxelMod with what you named your project
 +
** Simply add "{}" without the quotation marks to the file and save it.
 +
*** This file is a config file. However nothing is supported in it yet. In the future, this ''might'' change.
 +
* Rename the Class1 class to Mod and allow Visual Studio to rename all references to it.
 +
* Open Mod.cs and replace its content with:
 
<pre>
 
<pre>
using System;
 
 
using Plukit.Base;
 
using Plukit.Base;
 
using Staxel.Items;
 
using Staxel.Items;
Line 53: Line 46:
 
using Staxel.Tiles;
 
using Staxel.Tiles;
  
namespace ClassLibrary1
+
namespace StaxelMod {
{
+
public class Mod : Staxel.Modding.IModHookV2 {
    public class Class1 : Staxel.Modding.IModHookV2 {
+
#region Loading
        public bool CanPlaceTile(Entity entity, Vector3I location, Tile tile, TileAccessFlags accessFlags) {
+
public void GameContextInitializeInit() {}
            throw new NotImplementedException();
+
public void ClientContextInitializeInit() {}
        }
+
public void ClientContextInitializeBefore() {}
 +
public void GameContextInitializeBefore() {}
 +
public void GameContextInitializeAfter() {}
 +
public void ClientContextInitializeAfter() {}
 +
#endregion
  
        public bool CanRemoveTile(Entity entity, Vector3I location, TileAccessFlags accessFlags) {
+
#region Running
            throw new NotImplementedException();
+
#region Every From
        }
+
public void UniverseUpdateAfter() {}
 +
public void UniverseUpdateBefore( Universe universe, Timestep step ) {}
 +
#endregion
  
        public bool CanReplaceTile(Entity entity, Vector3I location, Tile tile, TileAccessFlags accessFlags) {
+
public bool CanPlaceTile( Entity entity, Vector3I location, Tile tile, TileAccessFlags accessFlags ) {
            throw new NotImplementedException();
+
return true;
        }
+
}
  
        public void Dispose() {
+
public bool CanRemoveTile( Entity entity, Vector3I location, TileAccessFlags accessFlags ) {
            throw new NotImplementedException();
+
return true;
        }
+
}
  
        public void GameContextDeinitialize() {
+
public bool CanReplaceTile( Entity entity, Vector3I location, Tile tile, TileAccessFlags accessFlags ) {
            throw new NotImplementedException();
+
return true;
        }
+
}
 +
#endregion
  
        public void GameContextInitializeAfter() {
+
#region Closing
            throw new NotImplementedException();
+
public void CleanupOldSession() { }
        }
+
public void GameContextDeinitialize() { }
 +
public void ClientContextDeinitialize() { }
 +
public void Dispose() { }
 +
#endregion
  
        public void GameContextInitializeBefore() {
+
#region Reloading
            throw new NotImplementedException();
+
public void ClientContextReloadBefore() { }
        }
+
public void GameContextReloadBefore() { }
 +
public void GameContextReloadAfter() { }
 +
public void ClientContextReloadAfter() { }
 +
#endregion
 +
}
 +
}
  
        public void GameContextInitializeInit() {
 
            throw new NotImplementedException();
 
        }
 
 
        public void GameContextReloadAfter() {
 
            throw new NotImplementedException();
 
        }
 
 
        public void GameContextReloadBefore() {
 
            throw new NotImplementedException();
 
        }
 
 
        public void UniverseUpdateAfter() {
 
            throw new NotImplementedException();
 
        }
 
 
        public void UniverseUpdateBefore(Universe universe, Timestep step) {
 
            throw new NotImplementedException();
 
        }
 
 
        public void ClientContextInitializeInit() {
 
            throw new NotImplementedException();
 
        }
 
 
public void ClientContextInitializeBefore() {
 
            throw new NotImplementedException();
 
        }
 
 
public void ClientContextInitializeAfter() {
 
            throw new NotImplementedException();
 
        }
 
 
public void ClientContextDeinitialize() {
 
            throw new NotImplementedException();
 
        }
 
 
public void ClientContextReloadBefore() {
 
            throw new NotImplementedException();
 
        }
 
 
public void ClientContextReloadAfter() {
 
            throw new NotImplementedException();
 
        }
 
 
public void CleanupOldSession() {
 
            throw new NotImplementedException();
 
        }
 
    }
 
}
 
 
</pre>
 
</pre>
 
+
** Again, replace "StaxelMod" as necessary.
You can look around for other types of interfaces within Staxel's code/dll and as an added bonus, Visual Studio will offer to help you implement these interfaces when you find them, with the appropriate methods and "usings".
+
** '' '''Note''': Currently ClientContextDeinitialize is called during initialization intead of ClientContextInitializeInit
 
+
*
A list of some of these Interfaces you can implement are:
+
 
+
<code>
+
IAchievementComponentBuilder, IBiomeBuilder, ICommandBuilder, IComponentBuilder, IEffectBuilder, IEntityAction, IEntityLogicBuilder, IEntityPainterBuilder, IFarmAnimalEntityBehaviourBuilder, IItemBuilder, IItemComponentBuilder, IModHook, INotificationBuilder, IPlayerExtendedCommand, IScript, ISubProcessHandler, ITileComponentBuilder, ITileConfigurationBuilder, ITileStateBuilder ITileStateBuilder, IVillagerEntityCommand, IVillagerEntityInstinct, IWeatherComponentBuilder
+
</code>
+
 
+
 
+
Past this point it's up to you to look around and find out what you can. One recommendation is to find out how to decompile Staxel.dll, as it is not obfuscated, and have a look at the actual code. Tools with which to do so include ILSpy, and JetBrains dotPeek.
+
 
+
'''Be aware: Exceptions will cause the game to crash. Try to avoid leaving NotImplementExceptions in unused methods.'''
+
 
+
= Loading A Mod Into Staxel =
+
 
+
After you have written your code, be sure to build your file. You can then navigate to your solution's bin folder. In that folder will be a bunch of files - select the ones you have made, then copy and paste them into the bin folder in Staxel's directory. (That is, copy and paste those files into "pathToStaxel/bin")
+
 
+
Once this copy is done, make a new text file and name it the same as your .dll file, except replace .dll with .mod. Inside of this .mod file, simply add {} and save. This may eventually include more information, but for now it is empty.
+
 
+
If all goes well, your mod will now be loaded into Staxel. Have fun coding!
+
 
+
  
 
= Interface Documentation =
 
= Interface Documentation =

Revision as of 21:51, 2 February 2018

[[Category:Modding]] Staxel also supports adding in your own code which can attach itself to interfaces within Staxel's code. This attachment is fairly rudimentary, and isn't tested as much as the other features. However, if you've ever wanted to add new features to Staxel, this is the way to do it.


Creating The Project

This page assumes that you are running Visual Studio 2017. If you run other versions of Visual Studio, locations of things may have changed. Other IDE's will definitely have different methods for some actions.

You should not need any external dependencies to develop Mods for Staxel. However, complex changes to the game may need XNA. In that case you can find what you need here: MXA

To create a new Code Based Mod:

Your New Project dialog may not look exactly like this.
  • Open Visual Studio
  • Create a New Project (File > New > Project)
  • Select a Class Library (Installed > Visual C# > Windows Classic Desktop > Class Library (.NET Framework))
    • Note You should be able to use your .Net Language of choice, but all sample code is in C#.
    • You may name it how you like, and use the newest version of the framework.
      • Tested with up to 4.7.1
  • Pick where you want your mod saved
  • Click Ok

Setting Up The Project

Now the project needs to be setup to recognize Staxel's code and build itself correctly for debugging.

Add References
  • Add a Reference by Right-Clicking the Project and selecting Add > Reference
    • Click Browse at the bottom right and navigate to where Staxel is installed, and open the bin folder.
      • For Staxel on Steam on Windows, this is likely "C:\Program Files (x86)\Steam\steamapps\common\Staxel\bin"
    • Hold Ctrl (Control) and select:
      • Plukit.Base.dll
      • Staxel.dll
    • Click Add
    • Click Ok

The project is now able to be built and loaded as a Mod, of course it doesn't do much at the moment

  • Add a new Text File and name it StaxelMod.mod
    • Replace StaxelMod with what you named your project
    • Simply add "{}" without the quotation marks to the file and save it.
      • This file is a config file. However nothing is supported in it yet. In the future, this might change.
  • Rename the Class1 class to Mod and allow Visual Studio to rename all references to it.
  • Open Mod.cs and replace its content with:
using Plukit.Base;
using Staxel.Items;
using Staxel.Logic;
using Staxel.Tiles;

namespace StaxelMod {
	public class Mod : Staxel.Modding.IModHookV2 {
#region Loading
		public void GameContextInitializeInit() {}
		public void ClientContextInitializeInit() {}
		public void ClientContextInitializeBefore() {}
		public void GameContextInitializeBefore() {}
		public void GameContextInitializeAfter() {}
		public void ClientContextInitializeAfter() {}
#endregion

#region Running
	#region Every From
		public void UniverseUpdateAfter() {}
		public void UniverseUpdateBefore( Universe universe, Timestep step ) {}
	#endregion

		public bool CanPlaceTile( Entity entity, Vector3I location, Tile tile, TileAccessFlags accessFlags ) {
			return true;
		}

		public bool CanRemoveTile( Entity entity, Vector3I location, TileAccessFlags accessFlags ) {
			return true;
		}

		public bool CanReplaceTile( Entity entity, Vector3I location, Tile tile, TileAccessFlags accessFlags ) {
			return true;
		}
#endregion

#region Closing
		public void CleanupOldSession() { }
		public void GameContextDeinitialize() { }
		public void ClientContextDeinitialize() { }
		public void Dispose() { }
#endregion

#region Reloading
		public void ClientContextReloadBefore() { }
		public void GameContextReloadBefore() { }
		public void GameContextReloadAfter() { }
		public void ClientContextReloadAfter() { }
#endregion
	}
}

    • Again, replace "StaxelMod" as necessary.
    • Note: Currently ClientContextDeinitialize is called during initialization intead of ClientContextInitializeInit

Interface Documentation