Modding Tutorials

Discuss modding questions and implementation details.
User avatar
TheLacus
Posts: 693
Joined: Wed Sep 14, 2016 6:22 pm
Contact:

Re: Modding Tutorials

Post by TheLacus » Mon Apr 30, 2018 3:40 pm

A few words on how to use the IHasModSaveData interface recently introduced to allow mods to store and retrieve save data.

First of all we must define a class to hold the data that needs to be saved. SaveLoadManager sends and requests the mod an instance of this class, which is automatically serialized in a file specific to the mod.
In the worst case this file can be deleted but it may be not a bad idea to make use of the versioning system for a smoother upgrade.

Code: Select all

[FullSerializer.fsObject("v1")]
public class MyModSaveData
{
	public string Text;
	public List<int> Items;
}
When the mod is started we have to link the interface to the Mod instance given by InitParams. We can do this in Init, Start or another method used to retrieve the singleton.

Code: Select all

mod.SaveDataInterface = instance;
The inteface requires one property and three methods to be implemented.
  • SaveDataType
    This is the type of the data class, used for deserialization.

    Code: Select all

    public Type SaveDataType
    {
    	get { return typeof(MyModSaveData); }
    }
    
  • NewSaveData()
    This is called when the mod is installed for the first time or the serialized file is missing for any reason.

    Code: Select all

    public object NewSaveData()
    {
    	return new MyModSaveData
    	{
    		Text = "Default text",
    		Items =  new List<int>();
    	};
    }
    
  • GetSaveData()
    This method asks the data to serialize when a new save is created.
    If the return value is null the file is not created.

    Code: Select all

    public object GetSaveData()
    {
    	return new MyModSaveData
    	{
    		Text = text,
    		Items =  items;
    	};
    }
    
  • RestoreSaveData()
    Give us the data deserialized (or result of NewSaveData()) to be applied in the running instance. Be sure to set all values to avoid leftovers from the previously running save.

    Code: Select all

    public void RestoreSaveData(object saveData)
    {
    	var myModSaveData = (MyModSaveData)saveData;
    	text = myModSaveData.Text;
    	items = myModSaveData.Items;
    }
    
If you are interested in creating mods for Daggerfall Unity you can find the documentation here.

User avatar
Nystul
Posts: 1198
Joined: Mon Mar 23, 2015 8:31 am

Re: Modding Tutorials

Post by Nystul » Wed Jun 27, 2018 8:41 am

I am posting this here since it looks like a bug in the modding system...

I am currently trying to build a standalone mod of Lypyl's Enhanced Sky mod (from the last known source before he ported stuff to the mod system).
I am having issues with the prefabs used in the Enhanced Sky mod.

I can load them from the mod's asset resource folders, I can instantiate them (so the gameobjects are created and present in the scene) but as soon as I want to get an attached script from the gameobject that was created from the prefab, the returned script is always null. So I can't get any working script references via code.
to be more clear, this line fails and always returns null for any attached script (for a script that is present on the gameobject when you can see it attached to the gamobject in the unity hierarchy):

Code: Select all

	AScript script = gameObject.GetComponent<AScript>();
Since Enhanced Sky does this or similar stuff by itself things are broken.

So the question from my side is: Did someone else experience problems with prefabs and attached scripts in mods? Or differently said: did someone succesfully used prefabs together with script referencing?

I wounder if these issues also affected Lypyl and if this was the reason he did not upload the ported code in the first place. Maybe he did some workarounds he was not too happy about and wanted to solve them first but never had the chance to do it. But this is just guesswork.

User avatar
TheLacus
Posts: 693
Joined: Wed Sep 14, 2016 6:22 pm
Contact:

Re: Modding Tutorials

Post by TheLacus » Wed Jun 27, 2018 9:36 am

You can't attach a script defined in a mod because type is not yet known during deserialization. You can attach only scripts which are already in the assembly (unity api + core).
I believe Lypyl was using an helper in ModManager to serialize prefab on mod build, then add the components at run time after instantiation and manually deserialize.
If you are interested in creating mods for Daggerfall Unity you can find the documentation here.

User avatar
Nystul
Posts: 1198
Joined: Mon Mar 23, 2015 8:31 am

Re: Modding Tutorials

Post by Nystul » Wed Jun 27, 2018 4:13 pm

ah ok, so this is a known issue then.
well this is a non-trivial limitation of the mod system :(

I will try to build all gameobjects and attached scripts from code then

User avatar
Nystul
Posts: 1198
Joined: Mon Mar 23, 2015 8:31 am

Re: Modding Tutorials

Post by Nystul » Sat Jun 30, 2018 9:21 pm

I found some more code that will result in a crash by the mod system when used:

Code: Select all

public struct AStruct
{
	private int value;

	private AStruct(int value)
	{
		this.value = value;
	}

	public static implicit operator AStruct(int value)
	{
		return new AStruct(value);
	}

	public static implicit operator int(AStruct record)
	{
		return record.value;
	}
}
any idea what might cause the crash? maybe the implicit operator overloading?

User avatar
TheLacus
Posts: 693
Joined: Wed Sep 14, 2016 6:22 pm
Contact:

Re: Modding Tutorials

Post by TheLacus » Sat Jun 30, 2018 10:03 pm

My first suggestion is to try make it a class. I also had occasional crashes with structs without apparent reason...
If you are interested in creating mods for Daggerfall Unity you can find the documentation here.

User avatar
Nystul
Posts: 1198
Joined: Mon Mar 23, 2015 8:31 am

Re: Modding Tutorials

Post by Nystul » Sat Jun 30, 2018 11:27 pm

will try this ;) thanks for the suggestion

Post Reply