Hello everyone,
In this tutorial, I want to share some experiences I made when planning all the (for most people) invisible steps that a plugin developer usually has to do when distributing their plugins on, e.g., itch.io.
We will discuss mainly:
- providing a small game project for your customers that works with both MV and MZ
- maintaining a free trial and a full version
- automating tasks
- obfuscating
- packaging
- publishing
All those topics will probably require a
few hours until you have a deep understanding; however, I made the experience that those things are massive time savers and make Plugin distribution much easier.
> Making your Plugin compatible with both MV and MZ
As the core codes from MV and MZ are similar, it's usually worth the effort to make your Plugin(s) compatible with both engines instead of publishing an MV and an MZ version. In case you need to distinguish inside your code, you can do this:
Spoiler: Example Code
Code:
function requestAnimation (target, animationId) { if (!target || !animationId || !$dataAnimations[animationId]) return; // silently don't show an animation if (Utils.RPGMAKER_NAME == 'MZ') { $gameTemp.requestAnimation([target], animationId); } if (Utils.RPGMAKER_NAME == 'MV') { target.startAnimation(animationId); } }
> Making a free Trial and a paywalled Full Version
Providing a free trial and a full version is something really useful for your customers.
I found out there are two frequently used approaches:
1. Publish 2 Plugins, one free version with limited features and one full version. While that's easy to understand, you must maintain 2 Plugins. On the other hand, you may obfuscate your free version while sharing your code when the customer purchases - as you wish.
2. Publish 1 Plugin and one paywalled Plugin that acts as a key.
This is a little bit more complex, but just a little. I realized I wanted to allow 95% of my features in the free trial, making option 1 obsolete. I also didn't want to maintain 2 Plugins, so I tried out a different approach.
I have one Main Plugin that includes all the features, but it runs only in RPG Maker's test play until the game dev includes another Plugin into his game - This Plugin is paywalled and acts as a key. The Main Plugin checks on starting the game whether the "key" Plugin is included and, if not, aborts the game.
Include this into your Main Plugin (example):
Spoiler: Code
Code:
var Imported = Imported || { }; (function() { const hasKey = () => Imported.MY_PLUGIN_SECRET_KEY == '123456789'; const isTestPlay = () => Utils.isNwjs() && (Utils.isOptionValid("test") || Utils.isOptionValid("btest") || Utils.isOptionValid("etest")); const alias = Scene_Boot.prototype.start; Scene_Boot.prototype.start = function() { alias.call(this); if (!hasKey() && isTestPlay()) { console.warn("Using free trial version - Game will not launch when exported."); console.warn("If you purchased the Full Version, please add YOUR_KEY_PLUGIN_NAME to unlock this Plugin."); } if (!hasKey() && !isTestPlay()) { alert("Free Trial only usable in PLAYTEST\n\n" + "If you purchased the Full Version, please add YOUR_KEY_PLUGIN_NAME to unlock this Plugin."); SceneManager.exit(); } } })();
Your Key Plugin would look like this (example):
Code:
var Imported = Imported || { }; Imported.MY_PLUGIN_SECRET_KEY = '123456789';
Important! Obfuscate your Plugins using e.g.,
https://obfuscator.io/
We will also automate this step later.
Important! Obfuscating your code is never a 100% bullet-proof solution. Anyone who wants to invest effort can revert-engineer your protection and crack it.
> Making Sample Game Projects that are compatible with both MV and MZ
As soon as your Plugin becomes bigger and more flexible, you probably think about making a Sample project that you deliver together with your Plugins. As we have learned that we can write Plugins compatible with both MV and MZ versions, it becomes obvious that we need to make and deliver two Sample projects. Or even more because you want to deliver a free and a paywalled version.
Some people would publish one or multiple large game projects, one for the MV and one for the MZ engine, and maybe, even more, when providing a free trial and a full version. Furthermore, all those game projects would contain all the RTP assets, including graphics and audio, requiring a large amount of space on your web server or cloud.
While I don't know about a suitable way to combine a free with a full version, we can save much time and effort regarding the other issues.
I worked on a small program (".bat" file) that allows uploading only the custom files (i.e., Maps, Plugins, Switches & Variables, Common Events, ...) while the program will copy-paste the RTP assets automatically on the client's device. Your customers can choose if they want to build your project's MV or MZ version. We successfully hit two birds with one stone, as you will upload only one small zip file that works for both MV and MZ.
You find the batch file here:
https://forums.rpgmakerweb.com/inde...ect-and-skip-all-the-rtp-assets-mv-mz.148956/
Note: Some default graphics (e.g., Titles) and audios (e.g., cursor SE) are available in only one engine's RTP. Use graphics and SEs available in both engines' RTP, or add those files manually into your zip files.
> Automate Obfuscating and Zipping your Files
I recommend using JavaScript here, as you already know about it, and because JavaScript can take over the task of obfuscating for us. Python could also be a handy alternative if you don't want to obfuscate your code.
Your script will
- copy-paste all your custom files as described in the previous step
- obfuscate your plugins (optional)
- build one or two (free version and full version) Zip files that contain your custom files, the batch file from the step above, and maybe some ReadMe files.
I will not share code snippets for this task because there are multiple libraries you can use to copy and zip files, and it's a reasonably simple yet individual flow for you as a developer.
But I share one more tip about obfuscating:
You want to use this npm package:
https://www.npmjs.com/package/javascript-obfuscator
The obfuscator would wipe all the comments, including Plugin Parameters and Commands, by default. To mitigate this, I add a tag in my code, e.g., "//@obfuscate." My script scans the code for this tag, and if it finds it, it will obfuscate only the part below this tag.
Spoiler: Example Code
Code:
async function obfuscatePlugin(file) { const content = await readFile(file, 'utf-8'); return obfuscate(content); } function obfuscate(content) { const splitted = content.split('//@obfuscate'); let toReturn; if (splitted[1]) { const obfuscated = '' + JavaScriptObfuscator.obfuscate(splitted[1]); toReturn = splitted[0] + '\n\n' + obfuscated; } else { toReturn = content; } return toReturn; }
> Test your ZIP Files
From here, you definitely should test if the ZIP files that your scripts produce work properly.
> Automate uploading your ZIP Files
When you want to use itch-io to upload your files, you have probably realized that you need to manually remove and re-upload your files using the web interface whenever you want to publish a new patch. We can do it better!
This tip requires some
web space. Maybe you already have a website to show your Plugin with some instructions; then check out if your provider also offers some web space for you that you can connect to with an
FTP client.
When you want to earn money with your Plugins, investing some into a website and web space is probably worth it.
When having a place to upload your files, you can easily write a new Python or JS script to upload your files to your web space. I recommend
not to append this script into the packaging script from the step above because you want to test your ZIP files first before uploading them; hence, you will have (at least) two scripts.
Important! When publishing paywalled Plugins, ensure your web server or website has
path traversal disabled! We will upload your files into a directory with a long and hard-to-guess name (as seen in the script below), so ensure there's no way to see your site's folder structure for people not being you or not being part of your team.
This is my Python script that you may copy-paste:
Spoiler: Python Script
Code:
# Your provider will give you the credentials host = "your.site.com" port = 22 user = "username" pw = "pw" secret_directory = "jutnxyolstg243850sjfklafa" FREE_VERSION = "C:/Users/XY/Documents/RPG/Free_Version.zip" FULL_VERSION = "C:/Users/XY/Documents/RPG/Full_Version.zip" import pysftp cnopts = pysftp.CnOpts() cnopts.hostkeys = None with pysftp.Connection(host = host, port = port, username = user, password = pw, cnopts = cnopts) as sftp: with sftp.cd('trials'): print("Uploading Free Version...") sftp.put(FREE_VERSION) with sftp.cd(secret_directory): print("Uploading Full Version...") sftp.put(FULL_VERSION) print("Done")
Your files are available online at "your.site.com/trials/Free_Version.zip" and "your.site.com/jutnxyolsötg243850sjfklafa/Full_Version.zip".
On Itch io, you can now add your files as external files where you add the URLs.
From now on, you can easily upload your files with your script and don't need to go to the Itch io site again (except for writing a new devlog).
本贴来自国际rpgmaker官方论坛作者:Aerosys处,因国际论坛即将永久关站,为了存档多年珍贵资料,署名转载到本论坛存档,由于官方帖子为英文原帖,需要中文翻译请点击论坛顶部切换语言为中文就可以将帖子翻译成中文浏览,方便大家随时查看,原文地址:
https://forums.rpgmakerweb.com/threads/advanced-plugin-distribution-tutorial-automating-tasks-free-paid-version-mv-mz-etc.155778/