Skip to content

Instantly share code, notes, and snippets.

@celestefox
Last active December 22, 2015 04:38
Show Gist options
  • Save celestefox/6417953 to your computer and use it in GitHub Desktop.
Save celestefox/6417953 to your computer and use it in GitHub Desktop.
Python in Javascript in Minecraft oh my!
//Start python script engine integration
var __system__;
var __file__;
var __pathJoiner__;
var engineManager;
var engine;
var execPyString;
var execPyStream;
var execPyFile;
/**
* Sets up the python script engine.
* Might need Java 7+
* Currently depends on both Jython (probably needs 2.7, has to be standalone) and guava being in the classpath.
* If you are using Forge/FML, guava is already suplied from at least 1.4 on.
* To get a working jython.jar is a bit harder.
* Download http://search.maven.org/remotecontent?filepath=org/python/jython-installer/2.7-b1/jython-installer-2.7-b1.jar
* (for 2.7) and run it. Select english, agree to the agreement.
* MAKE SURE TO SELECT STANDALONE INSTALLATION. Set the location to say a empty folder on your desktop.
* Leave the java home alone, unless you know you are running MC with a different JRE than default (hint you probably are not)
* Say next on the confirmation screen, wait, say next until it exits. Fin the directory you told it to install to, copy the jython.jar in there
* to your mods folder (not coremods, not libs, etc). This SHOULD make FML insert it into your classpath, probably with MC1.4+, but I'm not sure about 1.6
*
* After this block, you should be able to do whatever with the Python Script engine fairly easily with execPyString, execPyStream, and execPyFile
* Pass any string to execPyString to execute it in the python script engine
* execPyStream is more of a helper function for execPyFile, you probably will only use it if you HAVE to have some python file out of the "msePy" directory
* execPyFile takes an arbitrary filename and executes the file, assuming it is in config/msePy, a folder that is set as set as the python "home",
* prepended to the python path, and had a basic registry file for jython added to it. The python "home" setting makes Jython look for that registry file there.
*/
(function ()
{
__system__ = Packages.java.lang.System;
__file__ = Packages.java.io.File;
__pathJoiner__ = Packages.com.google.common.base.Joiner.on(__file__.pathSeparator).skipNulls();
__file__(__api.__getConfigDir(), "msePy").mkdirs();
if (!__file__(__file__(__api.__getConfigDir(), "msePy"), "registry").isFile())
{
//Registry file does not exist, first run
var __regfile__ = __file__(__file__(__api.__getConfigDir(), "msePy"), "registry");
__regfile__.createNewFile();
var __regwriter__ = java.io.FileWriter(__regfile__, false);
__regwriter__.write("python.security.respectJavaAccessibility = false" + __system__.lineSeparator + "python.options.caseok = false");
__regwriter__.flush();
__regwriter__.close();
}
/** I need to override this to get several things working. */
__system__.setProperty("python.home", __file__(__api.__getConfigDir(), "msePy").toString());
var __pythonPath__ = __system__.getProperty("python.path");
if (!isEmpty(__pythonPath__))//I use this because typeof on null returns "object" but trying to iterate it throws so yay reuse!
{
//Pythonpath already has some entries somehow, prepend our msePy directory.
var __pythonPathEntries__ = java.util.ArrayList(java.util.Arrays.asList(__pythonPath__.split(__file__.pathSeparator)));
__pythonPathEntries__.add(0, __file__(__api.__getConfigDir(), "msePy").toString());
__pythonPath__ = __pathJoiner__.join(__pythonPathEntries__);
} else {
__pythonPath__ = __file__(__api.__getConfigDir(), "msePy").toString();
}
__system__.setProperty("python.path", __pythonPath__);
engineManager = new Packages.javax.script.ScriptEngineManager();
engine = engineManager.getEngineByName("python");
engine.put("__api__", __api);
execPyString = function execPyString (str)//Exec's any old string, with the filename set to "UNKNOWN" to represent this.
{
engine.put(Packages.javax.script.ScriptEngine.FILENAME, "UNKNOWN");
engine.exec(stream);
engine.put(Packages.javax.script.ScriptEngine.FILENAME, null);
};
/**
* Takes a class implementing Reader and executes it inside the Jython script engine.
* @param stream the class implementing Reader
* @param filename the name of the file that goes with the Stream or a placeholder
* @return undefined Returns nothing, logs on error instead of throwing
*/
execPyStream = function execPyStream (stream, filename)
{
try
{
engine.put(Packages.javax.script.ScriptEngine.FILENAME, filename.toString());
engine.exec(stream);
} catch (e) {log("Python stream execution failed with filename:" + ((typeof filename != "null")&&(typeof filename != "undefined")?filename.toString():"undefined"), logLevel.error)} finally {
engine.put(Packages.javax.script.ScriptEngine.FILENAME, null);
}
};
execPyFile = function execPyFile (filename)//Reads and execs a file in MSEConfigDir/msePy(or lower), which is usually .minecraft/config/msePy
{
var file = new __file__(__file__(__api.__getConfigDir(), "msePy"), filename);
var reader = new Packages.java.io.InputStreamReader(new Packages.java.io.FileInputStream(file), "UTF-8");
execPyStream(reader, file.toString());
reader.close();
};
}) ();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment