马上登录/注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
简介
这是一个Spigot插件,其能够使用库的形式将Bukkit API开放给Python使用。
与其他插件不同,它并没有将几个指令硬生生的硬编码进插件中。
解释器
插件的解释器基于Jython。这的好处是完整的Python解释器系统在JVM内部运行,但缺点是它只支持Python 2。
指令
您可以通过telnet服务器、websocket服务器和聊天指令(/py、/pyload和/pyrestart)与Jython解释器交互。
/py <代码> 在Jython解释器上运行一行Python代码(每个玩家都有自己的解释器实例)。
在需要提供带有空格的缩进时,可以使用<代码>行开头的.(点)(Minecraft服务器通常忽略空格)。
/pyrestart 用于重新启动Jython解释器。
/pyload <文件> 取本地Python文件(在服务器上)并在Jython解释器中执行。
内置的Python模块mcapi.py提供了一些预定义的方便命令,可以在远程解释器中导入。
将.py文件放在python-plugins目录中时,这些文件在启动插件时会作为“插件”运行。
此解释器继续运行,可用于设置全局监听器。在一段时间的闲置后,解释器会被删除。
关于Python3
Jython目前只支持Python 2,而且似乎它会持续很长一段时间。
有各种Python 3 <-> JVM互操作项目可用,尽管这些项目似乎都没有像Jython那样在JVM实现上提供完整的Python的易用性。
Py4j很接近,早期的提交确实提供了一种使用此库与Minecraft交互的方法。
然而,Py4J实现严重依赖Python和JVM之间的回调,这些回调通过网络发送。
将此与许多线程杂耍和Spigt的内部线程模型相结合是令人生畏的。
该实现有效,但在尝试在Spigot服务器上执行大量操作时非常不稳定,所以我最终暂时将其从代码库中删除。
我(原作者)稍后可能会把这个重新添加到一个单独的分支中。
开始
从最新版本到最新版本,该插件的安装与任何其他Spigot插件一样。你至少需要Java 8。
在引导时,lib-common和python目录将自动创建。如果您想访问Python脚本中的其他Minecraft插件,他们的JAR文件可以复制到lib自定义目录。
例子 # Import some modules
from mcapi import *
from time import sleep
from random import randint
MY_NAME = "Macuyiko"
# Note: all code runs asynchronously by default. If you want to make world edits, Spigot
# forces you to execute these on a synchronised task. Most of the methods included in mcapi
# will take care of this automatically
# Set the time to sundawn
time(0)
# Zap the point where I'm looking at
bolt(lookingat(player(MY_NAME)))
# A small explosion instead
explosion(lookingat(player(MY_NAME)), power=2)
# Generate a tree (only works if there is room)
tree(lookingat(player(MY_NAME)))
# Spawn some particles
particle(lookingat(player(MY_NAME)))
# Spawn an entity (chicken by default)
spawn(lookingat(player(MY_NAME)))
# Fireworks
fireworks(lookingat(player(MY_NAME)))
# Let's create an exploding chicken spell
def exploding_chicken(player_name):
yell("Creating an exploding chicken")
chicken = spawn(lookingat(player(player_name)))
for i in range(5,0,-1):
yell("%s second(s) left..." % i)
sleep(1)
explosion(location(chicken), power=2)
# Try it!
exploding_chicken(MY_NAME)
# Now let's define a command for this spell
# Command functions take a special form func(caller, params)
@asynchronous()
def cmd_explode_spell(caller, params):
exploding_chicken(caller.getName())
# Commands are executed synchronously by Spigot
# This means that all actions in exploding_chicken would use the state of the
# world as it was at the current server tick when executing the command,
# hence, we use the @asynchronous() decorator to force this function to be
# ran asynchronously, only synchronising every time a synchronous command is called
add_command('chickenspell', cmd_explode_spell)
# Try typing `/chickenspell` in Minecraft chat window
# Commands can be unregistered using
remove_command('chickenspell')
# Let's register another command to show of the asynchronous workings
@asynchronous()
def cmd_growme(caller, params):
beginning = lookingat(player(caller.getName()))
position = [beginning.x, beginning.y, beginning.z]
for i in range(100):
setblock(position) # <- will be synchronised
position[randint(0,2)] += randint(-1,1)
position[1] += +1
sleep(0.05)
add_command('growme', cmd_growme)
# Now let's register an event
# These need a func(event) definition
from org.bukkit.event.block import BlockDamageEvent
# Almost all events execute synchronised, so again we force them to be asynchronous
@asynchronous()
def damage_evt(e):
player = e.getPlayer()
position = location(player)
yell("I'll count to ten, get out!")
for i in range(10):
yell(str(i))
sleep(1.0)
explosion(position)
# A block will explode if the player damages it
listener = add_event_listener(BlockDamageEvent, damage_evt)
# Remove specific event hook
remove_event_listener(listener)
# Or all hooks
remove_event_listeners()
from mcapi import *
from time import sleep
from random import randint
from org.bukkit.event.player import PlayerJoinEvent
@asynchronous()
def join_event(e):
player = e.getPlayer()
player_location = location(player)
player_location.y += 20
yell("A chickeny hello to player %s" % (player.getName(),))
for i in range(10):
spawn(player_location)
listener = add_event_listener(PlayerJoinEvent, join_event)
|