tModPorter has now been added to tModLoader as an official module on 1.4 preview. It will see more updates over the next while, but it is now at a reasonable release point.
tModPorter itself is a custom software that helps mod developers transition away from 1.3 by automatically handling several of the breaking changes that we’ve introduced.
However, it is not perfect - some work will still be needed, but it is hoped it will carry the brunt of the manual labor.
Associated launcher files are included in the tModPorter folder in the Install Folder for tModLoader, as well as a button in-game to shortcut to that.
Note that this is tModLoader’s first update with it - so if you encounter bugs, please let us know.
Additionally, please note that many more automatic ports will be added to tModPorter in the next few days. You can help Chicken-Bones prioritize by posting things you'd most like to see automatically ported in the tModPorter Discord thread.
• After 9 years in development, hopefully it will be worth the wait.
• ModSound and SoundLoader have both been removed. As well as the Mod.SoundAutoloadingEnabled property.
• LegacySoundStyle and CustomSoundStyle were removed. SoundStyle is now a struct (record), which contains everything a sound playing enthusiast would need: AssetRepository-based paths; Volume, pitch and looping control; Numbered suffix variants with even weighted random supported; Sound instance limits and their behavior; And etc., etc.
• All sound playback is now done through one method - SlotId SoundEngine.PlaySound(SoundStyle style, Vector2? position = null).
All legacy (int type, int style) overloads have been removed from the API.
• I went through the pains of entirety converting all SoundID entries to the new SoundStyles, which means that you can now not only replicate vanilla sound playbacks, but also modify their copies with ease. I suggest getting familiar with the x with { A = B } syntax, it’s great here.
• A few improvements may follow later, but they’re unlikely to be breaking changes.
Basically, this cleans up a long standing set of TML bugs resulting from an attempted fix for a vanilla issue (#1437) with unpredictable item usage frames relative to their animations that was preventing modders from implementing their ideas.
• By demand of mod developers, a design change that was part of the OnSpawn Pull Request has been reverted, and CloneNewInstances from 1.3 is back, again set to false by default, like in 1.3. This revert may be temporary in case the team comes up with superior designs in the later months.
• TML tries to make sure that all ModItem and instanced GlobalItem derivatives return true from IsCloneable, logging warnings otherwise.
• If the default IsCloneable implementation returns false, but your item is cloneable via MemberwiseClone (because you have reference fields which don't change once the item is spawned/loaded) - you can do 'override IsCloneable => true'.
• Added [CloneByReference] attribute for fields that are safe to share between clones (because they’re shared, or not modified after Load/SetDefaults)
• This re-adds the ModTrees, ModPalmTrees, ModCactus support from 1.3 as they were. Consider this a bug fix PR, not a feature rework/API cleanup
• This does not add 1.4 content unless it was specifically required for these to work
• This is NOT the final PR, and we do expect future breaking changes as outlined in / in support of Issue #1347.
All mods will now be Just-In-Time compiled on load. This will detect mods that silently break as tModLoader changes and disable them instead of allowing them to silently cause errors. A side effect of this is that weak referenced Types will cause the mod to fail to load, so mod developers weakly referencing other mods will need to utilize the [JitWhenModsEnabled] attribute to annotate classes, methods, or properties using those Types to bypass this checking. See the details in the Pull Request for more information on this and more advanced situations.
Additionally, we now support inheriting from base classes in weakly referenced mods. Such classes need to be annotated with the [ExtendsFromMod] attribute to inform tModLoader not to attempt to autoload the class. A side effect of this capability is that mods should no longer call Assembly.GetTypes() on other mod assemblies, as this could fail now. They should now use AssemblyManager.GetLoadableTypes(Assembly) to retrieve all Types that should be considered from other mods.
Mod.AddEquipTexture(...) got turned into EquipLoader.AddEquipTexture(...), and it can now be used to register equipment textures through an internal name instead of being locked into using the name of their associated item as an internal name. This also allows mods to register equip textures without needing an item reference, and most importantly, allows them to register multiple equip textures of the same type for the same item.
HJSON localization improvements:
• Periods can now be used in keys;
It's now possible to write Mods.YourMod: { } in place of Mods: { YourMod: { } }.
• Arrays item paths are now properly handled as well;
Every array item will now have a period-separated key: AnArray.42.SomethingInsideArrayItem.
• Ammo damage modifiers are selected based on the DamageClass of the ammo
• Added Mod/GlobalItem.CanChooseAmmo hooks.
• PickAmmo hook now has a StatModifier damage parameter.
• Added AmmoID.Sets IsArrow, IsBullet and IsRocket.
Adds bool Global/ModItem.NeedsAmmo() hook, allowing for weapons which can shoot their default projectile without ammo under certain conditions (like if you had a free ammo buff.)
• Adds NPC.ShowNameOnHover defaulting to true. Can be changed in SetDefaults or AI to hide the hover mouse text
• Adds Mod/GlobalNPC.ModifyHoverBoundingBox(ref Rectangle boundingBox) for custom hover text rect control.
• Adds CatchingTool and LavaproofCatchingTool Item Sets for creating new bug net type items
• Greatly enhances the hooks for CatchNPC
• A few changes to existing Catch related hooks to be wary of
• Read more in the PR.
• void SendExtraAI(Projectile projectile, BitWriter bitWriter, BinaryWriter binaryWriter)
• void ReceiveExtraAI(Projectile projectile, BitReader bitReader, BinaryReader binaryReader)
• Added methods to allow control of ordering for recipes, for example keeping modded wood with vanilla wood.
• All mods that call Recipe.Register() or RemoveRecipes will need to be updated and/or rebuilt.
• Does what it says on the can.
• CloneDefaults will fully now initialize the item/npc/projectile as another type, and then restore the mod-x and global-x from the original item type.
• You’re only really meant to call this from ModX.SetDefaults.
Fellow code injection abusers and users of mods from them will love to hear this:
We've updated to a dev build of MonoMod (the code injection library we use to allow mod developers to more freely modify the game) to get a fix for a process freeze that could super rarely occur during injections, and discovered that specifically that same fix (tied to an unforeseen change the .NET 6 runtime) has also sped up code injections by over ten times.
Thanks and much love to 0x0ade for making MonoMod and collaborating with us!
We've added a notification window when you launch to see which subscribed mods have updated since the last time you played. This will help you track when your favorite mods update so you can check them out for new features. This will also help you if a mod is broken and you want to remember to re-enable it when it updates.
Mods will now automatically reload when exiting the Mods menu. This has caused some confusion in the past as users did not know they needed to reload mods. This change will help simplify the new user experience.