Inactive [DEV] PythonLoader v0.3.1 - Load Plugins written in Python [1.1-R6]

Discussion in 'Inactive/Unsupported Plugins' started by masteroftime, Aug 8, 2011.

  1. Offline

    masteroftime

    PythonLoader 0.3
    This plugin allows developers to code bukkit plugins in the python programming language. The plugins in python can either use a thin wrapper to the standard Bukkit API, or the newer decorator API. For more detailed instructions for installing this plugin and how to code plugins, take a look into the Readme on Github.

    Features:
    • Load bukkit plugins written in python.
    Installation:
    Put PythonLoader.jar into plugins directory and jython.jar into lib directory (within bukkit folder not plugins folder).

    PythonLoader
    Jython (By downloading and using Jython you accept the Jython License)
    Source Code

    I have to give special credits to @lahwran who created the whole decorator API and corrected many of my mistakes. :)

    Changelog: Version 0.3.1

    Version 0.3.1
    • Updated to CB 1.1-R6
    Version 0.3
    • Updated to CB 1.1-R1
    • Changed to new EventHandling System
    Version 0.2
    • Added decorator API
    • Invalid plugin exceptions are thrown when an invalid python plugin is loaded
    • Seperate Python Interpreter for each plugin
    • JavaPlugin's event executor creation is now directly used
    Version 0.1.1
    • Changed plugin.yaml to plugin.yml
    • Removed some debug output
    Version 0.1
    • First official release.
     
  2. Offline

    masteroftime

    It doesn't work for you? I tested it with 1.0.1-R1 and it worked for me. Please send me what errors you get.
     
    jsalles likes this.
  3. Offline

    jsalles

    Confirmed, running on CraftBukkit 1.0.1-R1-39-g60409d1-b1717jnks for MC 1.1 and everything is running smooth.
     
  4. Offline

    dwarmia

    omg, now i dont have to learn Java....... Thank you !!

    is it going to be updated ?
     
    jsalles likes this.
  5. Offline

    SpaceManiac

    Hey there, I'm using the latest RB (1.1-R1) and PythonLoader refuses to load my python plugin - no error message of any sort, and PythonLoader itself seems to be loading fine. I'm reasonably certain the python script doesn't contain any errors, but I can post it if need be.
     
  6. Offline

    masteroftime

    SpaceManiac This is beacause of Bukkit 1.1 and the new Event-Handling System the Plugin Loading changed quite a bit and the old code therefore doesn't work any more because plugins would have to register the new loader even before they are loaded themselves.

    I am currently updating to 1.1 and I've uploaded a snapshot to BukkitDev. Just note that you have to specify the event type in a new format - <subpackage>.<event_class> (e.g. player.PlayerChatEvent). If you do it in the old way (player_chat) the event will not fire.

    ps I'm already trying to get the old system to work again so pls don't complain about it

    *edit* here's a link to the download
     
  7. Offline

    SpaceManiac

    That's fine, I'm not using events, just hook.command - works swimmingly with the snapshot, thank you!
     
  8. Offline

    Clem

    Just a question, how do I install a plugin on my server. It's not explained very well, at least I'm not sure how you do it. Thanks masteroftime for the plugin :). P.S. Any word on if you will update for 1.1?
     
  9. Offline

    masteroftime

    Yup, the update is already in the making. A snapshot is already available to download here.

    Just note that you have to specify the event type in a new format - <subpackage>.<event_class> (e.g. player.PlayerChatEvent). If you do it in the old way (player_chat) the event will not fire. Also the event priorities are broken, every registered event has normal priority even if you specify another priority.

    Now events using the old annotations and priorities are working again.

    Btw. did you guys already make some plugins using python? I'm just curious and I also want to be able to feature some cool plugins using python :p

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 18, 2016
  10. Offline

    gallexme

    Could u Explain how to use Config files or is it Possible to use python functions like Read and write ?

    Well im Publish now my simpel Plugins

    and thank u MasterofTime

    so My Plugin :

    it s an not Working login / Register Script + Creeper and Enderman Protection with .ini Config Files:

    main.py:

    Code:
    from org.bukkit.entity import CreatureType
     
    import sys
     
    import ConfigParser
     
    config = ConfigParser.ConfigParser()
     
    playerloginned = False
     
    cprotect = False
     
    eprotect = False
     
    class malcolmjunk():
     
        def spammer(self, sender, myrange):
     
     
     
            player = sender
     
            try:
     
                creature = CreatureType.fromName(str(myrange[0]))
     
                player.getWorld().spawnCreature(player.getLocation(), creature)
     
                sender.sendMessage("[Spammer] %s" + str(myrange[0]) )
     
            except:
     
                sender.sendMessage("[SpawnMob] Erster Buchstabe muss Gros geschrieben sein vom Monster")
     
    junk =malcolmjunk()
     
    [AD]hook.enable
     
    def onEnable():
     
        print "Creeper Schutz aktiviert"
     
        auslesenCreeper()
     
    def auslesenCreeper():
     
        print "Protect.ini wird ausgelsen ...."
     
        global cprotect
     
        config.read(sys.path[0] + "/protect.ini" )
     
        auslesenEnderman()
     
        if config.getboolean('Creeper', 'CreeperProtect') == True:
     
            print "Creeper Bumm Deaktiviert"
     
            cprotect = True
     
        else:
     
            cprotect = False
     
            print "Creeper Bumm Aktiviert"
     
    def auslesenEnderman():
     
        global eprotect
     
        config.read(sys.path[0] + "/protect.ini" )
     
        if config.getboolean('Enderman', 'EndermanProtect') == True:
     
            print "Ender Protect Deaktiviert"
     
            eprotect = True
     
        else:
     
            eprotect = False
     
            print "Ender Protect Aktiviert"
     
    [AD]hook.disable
     
    def onDisable():
     
        print "Creeper Schutz Deaktiviert"
     
    [AD]hook.command("Spawnmob", usage="/<command>",
     
                    desc="Spawn a Mob")
     
    def spamme(sender,command,label,args):
     
        if len(args) != 0:
     
            #print "The player typed something as a argument"
     
            player = sender
     
            bob = args
     
            junk.spammer(sender,bob)
     
        else:
     
            # This doesn't really work, I never implemented a "check for number" function.
     
            #print "The player did not type a number as an argument"
     
            print "nothing"
     
        return True
     
    [AD]hook.event("entity.EntityExplodeEvent", "high")
     
    def Creeperprotect(event):
     
        if cprotect == True:
     
            event.setCancelled(True)
     
        else:
     
            return
     
    [AD]hook.event("entity.EndermanPickupEvent", "high")
     
    def endermanprotect(event):
     
        if eprotect == True:
     
            event.setCancelled(True)
     
        else:
     
            return
     
    [AD]hook.event("player.PlayerJoinEvent", "high")
     
    def login(event):
     
        event.getPlayer().sendMessage("Creeper und Enderman Schutz Aktiviert von Nanostray")
     
    [AD]hook.event("player.PlayerMoveEvent", "high")
     
    def protect(event):
     
        if playerloginned:
     
            return
     
        else:
     
            event.setCancelled(True)
     
    [AD]hook.command("register", usage="/<command>",
     
                    desc="registers u")
     
    def register(sender,command,label,args):
     
        import string
     
        if len(args) != 0:
     
            #print "The player typed something as a argument"
     
            player = sender
     
            bob = string.join(args, " ")
     
            text_file = open(sys.path[0] + "/" + str(player) +".txt", "w")
     
            text_file.write(str(bob))
     
            text_file.close()
     
     
     
        else:
     
            # This doesn't really work, I never implemented a "check for number" function.
     
            #print "The player did not type a number as an argument"
     
            print "nothing"
     
        return True
     
    [AD]hook.command("login", usage="/<command>",
     
                    desc="registers u")
     
    def login(sender,command,label,args):
     
        import string
     
        if len(args) != 0:
     
            #print "The player typed something as a argument"
     
            player = sender
     
            bob = string.join(args, " ")
     
            fin = open(sys.path[0] + "/" + str(player) +".txt", "r")
     
            str3 = fin.read()
     
            fin.close()
     
            print bob
     
            print str3
     
            if bob == str3:
     
                print "Willkommen " + str(player) + " auf Fabis Survival Server"
     
                global playerloginned
     
                playerloginned = True
     
            else:
     
                print "Fail"
     
     
     
        else:
     
            # This doesn't really work, I never implemented a "check for number" function.
     
            #print "The player did not type a number as an argument"
     
            print "nothing"
     
        return True
     
    [AD]hook.command("enderprotect", usage="/<command>",
     
                    desc="Toggle EnderProtect")
     
    def ToggleEnderman(sender,command,label,args):
     
        global eprotect
     
        if eprotect == True:
     
            eprotect = False
     
        else:
     
            eprotect = True
     
    [AD]hook.command("creeperprotect", usage="/<command>",
     
                    desc="Toggle CreeperProtect")
     
    def ToggleCreeper(sender,command,label,args):
     
        global cprotect
     
        if cprotect == True:
     
            cprotect = False
     
        else:
     
            cprotect = True
     
    
    protect.ini:

    Code:
    [Creeper]
     
    CreeperProtect: True
     
    [Enderman]
     
    EndermanProtect: True
    How to do Spoilers?

    mfg gallexme

    hate the tag funktion replace the [AD] with @

    Edit:

    TimberPlugin:

    # U Can chop an Tree with only destroy 1 Log Block while holding an Iron_Axe und can chop single log blocks while u crouching

    Code:
    #Timber Plugin:
     
    [USER=16971]Hook[/USER].enable
     
    def onEnable():
     
        print "Timber mod Activated"
     
    [USER=16971]Hook[/USER].disable
     
    def onDisable():
     
        print "Timber mod Disactivated"
     
    [USER=16971]Hook[/USER].event("block.BlockBreakEvent", "high")
     
    def onPlayerBreakLog(event):
     
        if str(event.getBlock().getType()) == "LOG":
     
            itemstack = event.getPlayer().getItemInHand()
     
            itemstackstring = str(itemstack)
     
            if "IRON_AXE" in itemstackstring:
     
                location = event.getBlock().getLocation()
     
                world = location.getWorld()
     
                i = 0
     
                if event.getPlayer().isSneaking():
     
                    return
     
                else:
     
                    while i <15:
     
                        location.setY(location.getY() +1)
     
                        blockeabove = world.getBlockAt(location)
     
                        if str(blockeabove.getType()) == "LOG":
     
                            blockeabove.breakNaturally()
     
                        else:
     
                            return
     
                        i = i + 1
     
            else:
     
                return
    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 18, 2016
  11. Offline

    Clem

    I'm alright with Bukkit's API and Python, but what I don't get is how I install the plugin into my own server. Is anyone here willing to enlighten me :)? gallexme
     
  12. Offline

    gallexme

    the plugins.py should be in the /plugins folder
    :)
     
  13. Offline

    Clem

    gallexme I little more detail. Where do I put the config files :3

    Sorry for the confusion I think I was confusing the two Methods of write and the yml files, with the decorator api it seems I just need 1 file. That's right correct? But if I use the old API I have to use a yml and where would it go?
     
  14. Offline

    gallexme

    if u use the decorate api u need only 1 file thats right
    Where do I put the config files:
    My config files ? these goese to lib\Lib

    and with the old api i dont know sorry
    best regards gallexme
     
  15. Offline

    masteroftime

    Clem if you use the old api you can either create a folder which name ends with .py.dir or _py_dir if you os hates dots xD or you can put the files in a zip file with the extension .py.zip or .pyp
    the files you need are plugin.yml (the config file) and plugin.py (the main python file). I hope this answers your question
     
    Clem likes this.
  16. Offline

    gallexme

    Masteroftime ur PythonLoader is so FreaKin Awesome but it its really needs more documentation :D
     
    Clem likes this.
  17. Offline

    Clem

    gallexme Yes, I think so too. It is really great but using it is a bit vague. masteroftime maybe when you get 0.3 out perhaps you could spend some dev time on improving the documentation :D? Anyways thanks for the answer that was what I was working for :). I'll try to get a cool plugin that you can show as well. You need more attention :p

    -Clem
     
  18. Offline

    b1naryth1ef

    To toggle a bool, you can do this:
    Code:
    x = not x
     
  19. Offline

    gallexme

    the event listener doestn work with r4 or ?
    im getting this error :
    Code:
    12:39:44 [SCHWERWIEGEND] Error occurred (in the plugin loader) while enabling ti
    mberplugin vdev (Is it up to date?): org.bukkit.plugin.RegisteredListener.<init>
    (Lorg/bukkit/event/Listener;Lorg/bukkit/plugin/EventExecutor;Lorg/bukkit/event/E
    ventPriority;Lorg/bukkit/plugin/Plugin;)V
    java.lang.NoSuchMethodError: org.bukkit.plugin.RegisteredListener.<init>(Lorg/bu
    kkit/event/Listener;Lorg/bukkit/plugin/EventExecutor;Lorg/bukkit/event/EventPrio
    rity;Lorg/bukkit/plugin/Plugin;)V
            at net.lahwran.bukkit.jython.PythonPluginLoader.createRegisteredListener
    s(PythonPluginLoader.java:427)
            at org.bukkit.plugin.SimplePluginManager.registerEvents(SimplePluginMana
    ger.java:539)
            at net.lahwran.bukkit.jython.PythonPluginLoader.enablePlugin(PythonPlugi
    nLoader.java:389)
            at org.bukkit.plugin.SimplePluginManager.enablePlugin(SimplePluginManage
    r.java:380)
            at org.bukkit.craftbukkit.CraftServer.loadPlugin(CraftServer.java:199)
            at org.bukkit.craftbukkit.CraftServer.enablePlugins(CraftServer.java:182
    )
            at net.minecraft.server.MinecraftServer.t(MinecraftServer.java:357)
            at net.minecraft.server.MinecraftServer.a(MinecraftServer.java:344)
            at net.minecraft.server.MinecraftServer.init(MinecraftServer.java:175)
            at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:408)
            at net.minecraft.server.ThreadServerApplication.run(SourceFile:465)
     
  20. Offline

    SpaceManiac

    Hey there! It looks like your plugin hasn't been updated to R5. Could you do so? For reference, here's a list of all the bad references, though it may or may not be actually any use.

    Code:
    net.lahwran.bukkit.jython.PythonEventHandler has 3 bad references:
        class org.bukkit.event.Event$Type
        class org.bukkit.event.Event$Priority
        method void registerEvent(org.bukkit.event.Event$Type, org.bukkit.event.Listener, org.bukkit.event.Event$Priority, org.bukkit.plugin.Plugin) in org.bukkit.plugin.PluginManager
    net.lahwran.bukkit.jython.PythonHooks$1 has 2 bad references:
        class org.bukkit.event.Event$Type
        class org.bukkit.event.Event$Priority
    net.lahwran.bukkit.jython.PythonHooks has 3 bad references:
        class org.bukkit.event.Event$Type
        class org.bukkit.event.Event$Priority
        method java.lang.Object getCommands() in org.bukkit.plugin.PluginDescriptionFile
    net.lahwran.bukkit.jython.PythonListener has 2 bad references:
        class org.bukkit.event.Event$Type
        method org.bukkit.event.Event$Type getType() in org.bukkit.event.Event
    net.lahwran.bukkit.jython.PythonPlugin has 1 bad references:
        class org.bukkit.util.config.Configuration
    net.lahwran.bukkit.jython.PythonPluginLoader$1 has 1 bad references:
        class org.bukkit.event.Event$Type
    net.lahwran.bukkit.jython.PythonPluginLoader has 5 bad references:
        class org.bukkit.plugin.UnknownSoftDependencyException
        class org.bukkit.event.Event$Type
        method java.lang.Object getDepend() in org.bukkit.plugin.PluginDescriptionFile
        method java.lang.Object getSoftDepend() in org.bukkit.plugin.PluginDescriptionFile
        method org.bukkit.plugin.EventExecutor createExecutor(org.bukkit.event.Event$Type, org.bukkit.event.Listener) in org.bukkit.plugin.java.JavaPluginLoader
    org.bukkit.plugin.python.PythonPlugin has 1 bad references:
        class org.bukkit.plugin.python.PythonPlugin
    
    If you're busy I could look into it myself. Guess while I'm at it, I'll ask - Did you pick up the plugin from lahwran, and how are you getting around the jar sealing to put a class in org.bukkit? :p
     
  21. Offline

    masteroftime

    Yep I know that it wasn't updated, the update was already in process.

    SpaceManiac what? org.bukkit is sealed? I didn't even notice that :p But the class in org.bukkit is not really necessary for the plugin anyway I might soon throw it out.
     
  22. Offline

    zaph34r

    Holy crap :confused: this plugin is made of win and awesome :D Why didn't i see this before?
    If it works and doesn't cost too much performance in any way, i will so rewrite my whole plugin in python and ditch my feeble attempts at doing things the java way :)

    Are there any limitations as of now compared to plugins written in java? Like, it being impossible to talk to other plugins, or only a limited part of the API being wrapped or something?
     
    Clem likes this.
  23. Offline

    masteroftime

    The loader does not work in 1.2.3-R2 when you want to load plugins without a plugin.yml file. I have no way of fixing this myself, however it will be fixed in 1.2.3-R3 so you either have to temporarily use a zip file or directory, or you use the 1.2.3-R3 Developement Build

    Note:
    You plugin can go to either a single .py file a directory ending with .py.dir or _py_dir or a zip file ending with .py.zip or .pyp. When using a directory your main file should be named main.py and you can add a plugin.yml file. For information about the plugin.yml file refer to the Bukkit docs.
     
  24. Offline

    zaph34r

    ah, so if i use a plugin.yml instead of the __plugin_version__ etc. it works? I would not have anticipated that, and of course i only tried it without the .yml :D Thanks a lot :)
     
  25. Offline

    seanth

    Would you be willing to post your posts so people could have an example to look at? That way they could follow the tutorials and compare the java to your python.

    For those of us that learn by example, that would definitely speed up the # of python plugins appearing. There are a number of dead bukkit plugins I'd love to port to python.

     
  26. Offline

    zaph34r

    If there is interest in python versions of specific examples or other small plugins, feel free to PM me and i will try to translate it and post it (or a link to it) here. I also tried to make the source to my first small python plugin (CopyMap at github) relatively neat and well commented, maybe it's of use to someone (although it doesn't contain a lot more than the example at the PythonLoader github page)
     
  27. Offline

    zaph34r

    I have a few questions regarding events:
    - With the new event system and the generic annotation @EventHandler, the listeners are auto-registered by argument type, is there any way to get that in pythonloader?
    - Any chance that the event decorators can support registering the same event multiple times with different priorities?
    - Would it be possible to extend the hook decorators to be usable with static methods/class methods/instance methods? At the moment it cannot coerce the types to PyFunction, and fails.
     
  28. Offline

    masteroftime

    I thought about that but since python uses dynamic typing I couldn't think of a way to get the type of the argument


    Should be possible, I'll look into it.
     
  29. Offline

    zaph34r

    thanks a lot :)
    if the last 2 points are in, the one line more for the decorator over auto-registration is a small price to pay for the added flexibility :D

    Something else came to mind: Importing and using java stuff from jython works all fine and dandy, but how would one go about the reverse in case i would want to expose an API for other plugins? From what i understand, its possible to compile a jython program to .class, and then use it from java like a native java package if the objects and functions to be exposed are properly treated to be recognizable by java, but is there any option of letting java plugins access a jython plugin without compilation ? Custom events would work too i guess, but could get a little bit complicated in some cases. Due to static typing/visibility something like .getPluginManager().getPlugin("something").someRandomMethod() would not compile, am i right? Been a while since i did something in java :confused:
     
    Clem likes this.
  30. Offline

    Clem

    I have a question... Using the decorator API can I define the functions outside of the Hook.command and then call it again? Also is there a way I can program my plugins in Eclipse (my main dev tool) without it having a hissy-fit. E.G. Import everything so it understands what I'm trying to do... (Using Jython2.5.2 interpreter and python2.5 dialect)
     
  31. Offline

    Clem

    Yes... 3.x support would be great! I mainly develop in 3.2 and using Jython is a pain because I have to start using deprecated functions :'(
     

Share This Page