Is your server trash because it is exactly like everybody else's? Are you desperately looking for anything unique to differentiate your server from the competition? Well, look no further.
Introducing Python scripts! Think about the level of prestige, status and elitism that comes with being the only public live server that uses Python for its scripts. You can put that feature on your gtop listing and draw in hundreds of new players.
Alright so let's get started on implementing this bad boy. I did this implementation on the masterrace source Solaxia but since Odin's scripting engine hasn't really been touched since the Vietnam war, this should work on every source.
In ServerConstants, add this:
PHP Code:
//Scripting Configuration
public static final String SCRIPTING_ENGINE = "javascript";
public static final String SCRIPT_EXTENSION = ".js";
This helps modularize the language used for scripts in your source so you can painlessly change it back to Javascript should you choose to, or perhaps even use another language entirely.
The following changes are going to be pretty repetitive but I will still list out all. In EventScriptManager, replace
PHP Code:
Invocable iv = getInvocable("event/" + script + ".js", null);
with
PHP Code:
Invocable iv = getInvocable("event/" + script + ServerConstants.SCRIPT_EXTENSION, null);
In ItemScriptManager, replace
PHP Code:
File scriptFile = new File("scripts/item/" + scriptName + ".js");
File scriptFile = new File("scripts/item/" + scriptName + ".js");
sef = sem.getEngineByName("javascript").getFactory();
with
PHP Code:
File scriptFile = new File("scripts/item/" + scriptName + ServerConstants.SCRIPT_EXTENSION);
File scriptFile = new File("scripts/item/" + scriptName + ServerConstants.SCRIPT_EXTENSION);
sef = sem.getEngineByName(ServerConstants.SCRIPTING_ENGINE).getFactory();
In MapScriptManager, replace
PHP Code:
sef = sem.getEngineByName("javascript").getFactory();
File scriptFile = new File("scripts/map/" + (firstUser ? "onFirstUserEnter/" : "onUserEnter/") + scriptName + ".js");
File scriptFile = new File("scripts/map/" + type + scriptName + ".js");
with
PHP Code:
sef = sem.getEngineByName(ServerConstants.SCRIPTING_ENGINE).getFactory();
File scriptFile = new File("scripts/map/" + (firstUser ? "onFirstUserEnter/" : "onUserEnter/") + scriptName + ServerConstants.SCRIPT_EXTENSION);
File scriptFile = new File("scripts/map/" + type + scriptName + ServerConstants.SCRIPT_EXTENSION);
Invocable iv = getInvocable("reactor/" + reactor.getId() + ".js", c);
Invocable iv = getInvocable("reactor/" + reactor.getId() + ".js", c);
with
PHP Code:
Invocable iv = getInvocable("reactor/" + reactor.getId() + ServerConstants.SCRIPT_EXTENSION, c);
Invocable iv = getInvocable("reactor/" + reactor.getId() + ServerConstants.SCRIPT_EXTENSION, c);
Finally, in your AbstractScriptManager, replace
PHP Code:
engine = sem.getEngineByName("javascript");
if (ServerConstants.JAVA_8){
engine.eval("load('nashorn:mozilla_compat.js');");
}
with
PHP Code:
engine = sem.getEngineByName(ServerConstants.SCRIPTING_ENGINE);
if (ServerConstants.JAVA_8 && ServerConstants.SCRIPTING_ENGINE.equals("javascript")){
engine.eval("load('nashorn:mozilla_compat.js');");
}
And there you have it, the implementation is that easy. This could obviously be accomplished with a simple IDE search + replace, but I listed out all the steps anyways. Now that you can switch your source's scripting language, let's switch it to Python boyssssssssssssss.
PHP Code:
//Scripting Configuration
public static final String SCRIPTING_ENGINE = "python";
public static final String SCRIPT_EXTENSION = ".py";
We will need a dependency for this to actually work, and for this we will use Jython. Grab yourself a copy by clicking here. I used Jython 2.5.4rc1 so I recommend you also use that. I cannot vouch for Jython 2.7.0 or any other version since I did not personally test it on those. Once you have your standalone jar, put in your dist folder and add it as an external jar like you would when originally setting up any source. Once you have done this, your source is fully ready to read and evaluate python scripts!
Being Christmas and all, I have decided to release a carbon-copy conversion of a random Javascript NPC script into Python, just to show how relatively easy it actually is to switch over entirely.
Below is a basic NPC script in Javascript written by RageZone's greatest member ever, Moogra, and then followed by my carbon-copy version in Python.
PHP Code:
/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
Matthias Butz <matze@odinms.de>
Jan Christian Meyer <vimes@odinms.de>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* NPC: Thomas Swift
* Maps: 100000000, 680000000
* Author: Moogra
* Purpose: Amoria warper.
*/
status = -1;
function start() {
if (cm.getPlayer().getMapId() == 100000000)
cm.sendYesNo("I can take you to the Amoria Village. Are you ready to go?");
else
cm.sendYesNo("I can take you back to Henesys. Are you ready to go?");
}
function action(mode, type, selection) {
status++;
if (mode != 1) {
if (mode == 0)
cm.sendOk("Ok, feel free to hang around until you're ready to go!");
cm.dispose();
return;
}
if (status == 0)
cm.sendNext("I hope you had a great time! See you around!");
else if (status == 1) {
if (cm.getPlayer().getMapId() == 100000000)
cm.warp(680000000, 0);
else
cm.warp(100000000, 5);
cm.dispose();
}
}
and now my version in Python
PHP Code:
'''
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
Matthias Butz <matze@odinms.de>
Jan Christian Meyer <vimes@odinms.de>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
'''
''' NPC: Thomas Swift
Maps: 100000000, 680000000
Author: Moogra
Purpose: Amoria warper.
'''
status = -1;
def start():
if (cm.getPlayer().getMapId() == 100000000):
cm.sendYesNo("I can take you to the Amoria Village. Are you ready to go?")
else:
cm.sendYesNo("I can take you back to Henesys. Are you ready to go?")
def action(mode, type, selection):
global status
status += 1
if (mode != 1):
if (mode == 0):
cm.sendOk("Ok, feel free to hang around until you're ready to go!")
cm.dispose()
return
if (status == 0):
cm.sendNext("I hope you had a great time! See you around!")
elif (status == 1):
if (cm.getPlayer().getMapId() == 100000000):
cm.warp(680000000, 0)
else:
cm.warp(100000000, 5)
cm.dispose()
As you can see, it practically takes no effort at all to convert. There are virtually no real differences between those two above scripts. As a general overview, you simply add a colon where an opening brace would be, delete all closing braces and semicolons, use Python's comment syntax instead of Javascript's, and you're already like literally 90% of the way done converting. The remaining 10% will simply be resolving any little quirks unique to Python like
PHP Code:
global status
Without going into too much detail since this obviously isn't a Python tutorial thread, without that line, Python would read the variable "status"
PHP Code:
status += 1
as a new local variable instead of the externally defined one. The global keyword tells Python that you are referring to the "status" variable defined outside of action's scope, and thus it now works exactly as you would expect it to, like the Javascript version.
Frequently Asked Questions
Spoiler:
1) Okay that's cool but all my scripts are in Javascript...?
Spoiler:
lol tru
2) So basically you want me to rewrite all my scripts to Python?
Spoiler:
lol yea tbh
3) So is there any practical use for this release?
Spoiler:
In all seriousness, it's cool to do things differently and while it probably isn't worth the effort to convert all your scripts over, I'm like 85% confident I could simply write a tool to translate all OdinMS Javascript scripts to Python in such a way that you could realistically be fully converted in just a few hours of work from start to finish. A couple hours of work for a pretty unique feature like this with little to no side effect (at least none I can think of right now) could be worth it depending on how you view things. So to ultimately answer this question, it is legitimately practical if you actually want to put in a bit of effort to make the switch entirely. Otherwise, then no, this release isn't all that practical for you. I just needed something memey af to release for Christmas and this was perfect.
4) So are you also releasing that conversion tool?
Spoiler:
If by some miracle there is legitimate interest in Python scripts, then yeah, I actually would write and release a conversion tool. But obviously not if nobody would use it.
Shameless Plug
Spoiler:
If you're not part of the MapleStory development discord by now, you should certainly join it by clicking here. You can dick around with the greatest memers around including the likes of Zygon, Eric, PacketBakery and many others.
This idea is actually very interesting (though I don't need your code, lol).
I will consider using Python as the scripting engine for my C++ source.
I have never thought of this before, thank you.
I honestly do not think that Python will attract new players, but thank you for the release.
Clearly you have never run a popular server in your life. Python DOES attract new players.
Originally Posted by Fraysa
de_memes...?
@op ty for rls, i actually use python as well =)
masterrace!
Nice, at least they aren't hardcoded.
Originally Posted by Buya
This idea is actually very interesting (though I don't need your code, lol).
I will consider using Python as the scripting engine for my C++ source.
I have never thought of this before, thank you.
Let's launch the Python revolution and take down the Javascript empire.