请在Discord机器人中注册Minecraft的坐标,并创建一个传送命令
前提這篇文章是一篇關於使用 Discord 機器人來掃描 Minecraft 伺服器的聖誕日曆文章。
-
WSL, Ubuntu 22.04.1
- WSL, Ubuntu 22.04.1
-
- discord.py 2.1.0
- Python 3.10.6
我正在这样的环境中进行。
我想做的事情当在Minecraft中发现海底神殿等地点时,我想制作一个能够通过命令将坐标整理到Discord机器人并发送到另一个频道的工具。
而且,仅此还不够有趣,所以我还想复制tp命令以便能够暂时传送到那个地点。
所以让我们来做吧。
实施首先,让我们创建一个命令来输入并显示坐标。
创建命令
import os
import discord
from discord import app_commands, Client, Intents, Interaction
from discord.ui import View, Button
from discord.app_commands import CommandTree
from dotenv import load_dotenv
load_dotenv()
class MyClient(Client):
def __init__(self, intents: Intents) -> None:
super().__init__(intents=intents)
self.tree = CommandTree(self)
async def setup_hook(self) -> None:
await self.tree.sync()
async def on_ready(self):
print(f"login: {self.user.name} [{self.user.id}]")
intents = Intents.default()
client = MyClient(intents=intents)
@client.tree.command()
@app_commands.describe(what="what you found?")
async def set_locate(
interaction: Interaction,
what: str,
x: int,
y: int,
z: int,
):
message = f"{what} is located: x:{x}, y:{y}, z:{z}"
await interaction.response.send_message(message)
client.run(os.getenv("TOKEN"))
import os
import discord
from discord import app_commands, Client, Intents, Interaction
from discord.ui import View, Button
from discord.app_commands import CommandTree
from dotenv import load_dotenv
load_dotenv()
class MyClient(Client):
def __init__(self, intents: Intents) -> None:
super().__init__(intents=intents)
self.tree = CommandTree(self)
async def setup_hook(self) -> None:
await self.tree.sync()
async def on_ready(self):
print(f"login: {self.user.name} [{self.user.id}]")
intents = Intents.default()
client = MyClient(intents=intents)
@client.tree.command()
@app_commands.describe(what="what you found?")
async def set_locate(
interaction: Interaction,
what: str,
x: int,
y: int,
z: int,
):
message = f"{what} is located: x:{x}, y:{y}, z:{z}"
await interaction.response.send_message(message)
client.run(os.getenv("TOKEN"))
试一下就知道了,目前看起来应该没有问题。
次にやることは,このメッセージを別のチャンネルに送ることです.チャンネルのIDからGuildChannelを取得します.そのチャンネルに対してメッセージをsendメソッドで送ります.
请发送到其他频道。
import os
import discord
from discord import app_commands, Client, Intents, Interaction
from discord.ui import View, Button
from discord.app_commands import CommandTree
from dotenv import load_dotenv
load_dotenv()
class MyClient(Client):
def __init__(self, intents: Intents) -> None:
super().__init__(intents=intents)
self.tree = CommandTree(self)
async def setup_hook(self) -> None:
await self.tree.sync()
async def on_ready(self):
print(f"login: {self.user.name} [{self.user.id}]")
intents = Intents.default()
client = MyClient(intents=intents)
@client.tree.command()
@app_commands.describe(what="what you found?")
async def set_locate(
interaction: Interaction,
what: str,
x: int,
y: int,
z: int,
):
message = f"{what} is located: x:{x}, y:{y}, z:{z}"
+ log_channel = client.get_channel(1052926772607463456)
+ await log_channel.send(message)
- await interaction.response.send_message(message)
+ await interaction.response.send_message("add location!")
client.run(os.getenv("TOKEN"))
別のチャンネルに送れました.
では続いて,別チャンネルに送信したメッセージにtpコマンドのコピーができるボタンを作ります.とりあえずコピーのところは置いておいて,ボタンを作りましょう.
Viewを継承したサブクラスに,discord.ui.button()デコレータを使用しサブクラスにボタンを追加します.この下に書いた処理がcallbackとして扱われます.
注意点として,スーパークラスのコンストラクタの呼び出しを忘れないようにしましょう.1時間溶かすことになります(1敗).
import os
import discord
from discord import app_commands, Client, Intents, Interaction
from discord.ui import View, Button
from discord.app_commands import CommandTree
from dotenv import load_dotenv
load_dotenv()
+ class TpCommandView(View):
+ def __init__(self):
+ super().__init__()
+
+ @discord.ui.button(label="get tp command")
+ async def getTpCmddButton(self, interaction: Interaction, button: Button):
+ await interaction.response.send_message(
+ "copy to your clipboard!", ephemeral=True
+ )
class MyClient(Client):
def __init__(self, intents: Intents) -> None:
super().__init__(intents=intents)
self.tree = CommandTree(self)
async def setup_hook(self) -> None:
await self.tree.sync()
async def on_ready(self):
print(f"login: {self.user.name} [{self.user.id}]")
intents = Intents.default()
client = MyClient(intents=intents)
@client.tree.command()
@app_commands.describe(what="what you found?")
async def set_locate(
interaction: Interaction,
what: str,
x: int,
y: int,
z: int,
):
message = f"{what} is located: x:{x}, y:{y}, z:{z}"
+ tp_cmd_view = TpCommandView()
log_channel = client.get_channel(1052926772607463456)
- await log_channel.send(message)
+ await log_channel.send(message, view=tp_cmd_view)
await interaction.response.send_message("add location!")
client.run(os.getenv("TOKEN"))
当我试运行时,按钮显示的是下面的图像,点击按钮后,消息被发送了出去。

因此,讓我們確保實際上進行複製。
复制tp命令コピーされるというのは,ボタンを押した後Ctr+Vでコマンドが貼り付けられる,という意味です.自分でドラッグしてコピーは面倒なのでそうします.
そのためにはクリップボードに対して操作をしないといけません.どうやらPythonではpyperclipを使うとそれができるみたいです.公式ドキュメントを見てみると,copy()でコピーさせることができるみたいです.
在使用pyperclip之前,需要进行安装。虽然在文档中没有提到,但在pypi上有相关说明。
$ pip install pyperclip
如果安装成功,那就立即试用一下吧。我们将对TpCommandView输入的坐标进行更改,创建一个tp命令,并将其复制过去。顺便提一下,tp命令是通过/tp x y z来让自己传送到指定坐标的。虽然可以选择目标进行传送,但是考虑到用户选择可能会麻烦,我们先不做。
import os
import discord
from discord import app_commands, Client, Intents, Interaction
from discord.ui import View, Button
from discord.app_commands import CommandTree
+ import pyperclip
from dotenv import load_dotenv
load_dotenv()
class TpCommandView(View):
- def __init__(self):
+ def __init__(self, locate: list):
super().__init__()
+ self.locate = locate
@discord.ui.button(label="get tp command")
async def getTpCmddButton(self, interaction: Interaction, button: Button):
+ tp_cmd = f"tp {self.locate[0]} {self.locate[1]} {self.locate[2]}"
+ pyperclip.copy(tp_cmd)
await interaction.response.send_message(
"copy to your clipboard!", ephemeral=True
)
class MyClient(Client):
def __init__(self, intents: Intents) -> None:
super().__init__(intents=intents)
self.tree = CommandTree(self)
async def setup_hook(self) -> None:
await self.tree.sync()
async def on_ready(self):
print(f"login: {self.user.name} [{self.user.id}]")
intents = Intents.default()
client = MyClient(intents=intents)
@client.tree.command()
@app_commands.describe(what="what you found?")
async def set_locate(
interaction: Interaction,
what: str,
x: int,
y: int,
z: int,
):
message = f"{what} is located: x:{x}, y:{y}, z:{z}"
- tp_cmd_view = TpCommandView()
+ tp_cmd_view = TpCommandView([x, y, z])
log_channel = client.get_channel(1052926772607463456)
await log_channel.send(message, view=tp_cmd_view)
await interaction.response.send_message("add location!")
client.run(os.getenv("TOKEN"))
因为写三个参数很麻烦,所以我尝试用数组来接收它们。嗯,当建造通往下界的道路时,需要将数值缩小为1/8,所以使用数组也是一个妥协吧。

我已将其正确地复制到剪贴板了。由于Discord正在Windows上运行,所以我不太清楚在其他操作系统上会发生什么情况。
但是我认为总体上是一样的,应该没问题的。
现在可以复制tp命令,这样在Minecraft中就可以方便地使用命令了。嗯,虽然在生存模式下无法输入命令。
总之,我成功地在Discord机器人中注册了Minecraft的坐标并得到了tp指令。辛苦了。
import os
import discord
from discord import app_commands, Client, Intents, Interaction
from discord.ui import View, Button
from discord.app_commands import CommandTree
from dotenv import load_dotenv
load_dotenv()
class MyClient(Client):
def __init__(self, intents: Intents) -> None:
super().__init__(intents=intents)
self.tree = CommandTree(self)
async def setup_hook(self) -> None:
await self.tree.sync()
async def on_ready(self):
print(f"login: {self.user.name} [{self.user.id}]")
intents = Intents.default()
client = MyClient(intents=intents)
@client.tree.command()
@app_commands.describe(what="what you found?")
async def set_locate(
interaction: Interaction,
what: str,
x: int,
y: int,
z: int,
):
message = f"{what} is located: x:{x}, y:{y}, z:{z}"
+ log_channel = client.get_channel(1052926772607463456)
+ await log_channel.send(message)
- await interaction.response.send_message(message)
+ await interaction.response.send_message("add location!")
client.run(os.getenv("TOKEN"))
別のチャンネルに送れました.
では続いて,別チャンネルに送信したメッセージにtpコマンドのコピーができるボタンを作ります.とりあえずコピーのところは置いておいて,ボタンを作りましょう.
Viewを継承したサブクラスに,discord.ui.button()デコレータを使用しサブクラスにボタンを追加します.この下に書いた処理がcallbackとして扱われます.
注意点として,スーパークラスのコンストラクタの呼び出しを忘れないようにしましょう.1時間溶かすことになります(1敗).
import os
import discord
from discord import app_commands, Client, Intents, Interaction
from discord.ui import View, Button
from discord.app_commands import CommandTree
from dotenv import load_dotenv
load_dotenv()
+ class TpCommandView(View):
+ def __init__(self):
+ super().__init__()
+
+ @discord.ui.button(label="get tp command")
+ async def getTpCmddButton(self, interaction: Interaction, button: Button):
+ await interaction.response.send_message(
+ "copy to your clipboard!", ephemeral=True
+ )
class MyClient(Client):
def __init__(self, intents: Intents) -> None:
super().__init__(intents=intents)
self.tree = CommandTree(self)
async def setup_hook(self) -> None:
await self.tree.sync()
async def on_ready(self):
print(f"login: {self.user.name} [{self.user.id}]")
intents = Intents.default()
client = MyClient(intents=intents)
@client.tree.command()
@app_commands.describe(what="what you found?")
async def set_locate(
interaction: Interaction,
what: str,
x: int,
y: int,
z: int,
):
message = f"{what} is located: x:{x}, y:{y}, z:{z}"
+ tp_cmd_view = TpCommandView()
log_channel = client.get_channel(1052926772607463456)
- await log_channel.send(message)
+ await log_channel.send(message, view=tp_cmd_view)
await interaction.response.send_message("add location!")
client.run(os.getenv("TOKEN"))
当我试运行时,按钮显示的是下面的图像,点击按钮后,消息被发送了出去。

因此,讓我們確保實際上進行複製。
复制tp命令コピーされるというのは,ボタンを押した後Ctr+Vでコマンドが貼り付けられる,という意味です.自分でドラッグしてコピーは面倒なのでそうします.
そのためにはクリップボードに対して操作をしないといけません.どうやらPythonではpyperclipを使うとそれができるみたいです.公式ドキュメントを見てみると,copy()でコピーさせることができるみたいです.
在使用pyperclip之前,需要进行安装。虽然在文档中没有提到,但在pypi上有相关说明。
$ pip install pyperclip
如果安装成功,那就立即试用一下吧。我们将对TpCommandView输入的坐标进行更改,创建一个tp命令,并将其复制过去。顺便提一下,tp命令是通过/tp x y z来让自己传送到指定坐标的。虽然可以选择目标进行传送,但是考虑到用户选择可能会麻烦,我们先不做。
import os
import discord
from discord import app_commands, Client, Intents, Interaction
from discord.ui import View, Button
from discord.app_commands import CommandTree
+ import pyperclip
from dotenv import load_dotenv
load_dotenv()
class TpCommandView(View):
- def __init__(self):
+ def __init__(self, locate: list):
super().__init__()
+ self.locate = locate
@discord.ui.button(label="get tp command")
async def getTpCmddButton(self, interaction: Interaction, button: Button):
+ tp_cmd = f"tp {self.locate[0]} {self.locate[1]} {self.locate[2]}"
+ pyperclip.copy(tp_cmd)
await interaction.response.send_message(
"copy to your clipboard!", ephemeral=True
)
class MyClient(Client):
def __init__(self, intents: Intents) -> None:
super().__init__(intents=intents)
self.tree = CommandTree(self)
async def setup_hook(self) -> None:
await self.tree.sync()
async def on_ready(self):
print(f"login: {self.user.name} [{self.user.id}]")
intents = Intents.default()
client = MyClient(intents=intents)
@client.tree.command()
@app_commands.describe(what="what you found?")
async def set_locate(
interaction: Interaction,
what: str,
x: int,
y: int,
z: int,
):
message = f"{what} is located: x:{x}, y:{y}, z:{z}"
- tp_cmd_view = TpCommandView()
+ tp_cmd_view = TpCommandView([x, y, z])
log_channel = client.get_channel(1052926772607463456)
await log_channel.send(message, view=tp_cmd_view)
await interaction.response.send_message("add location!")
client.run(os.getenv("TOKEN"))
因为写三个参数很麻烦,所以我尝试用数组来接收它们。嗯,当建造通往下界的道路时,需要将数值缩小为1/8,所以使用数组也是一个妥协吧。

我已将其正确地复制到剪贴板了。由于Discord正在Windows上运行,所以我不太清楚在其他操作系统上会发生什么情况。
但是我认为总体上是一样的,应该没问题的。
现在可以复制tp命令,这样在Minecraft中就可以方便地使用命令了。嗯,虽然在生存模式下无法输入命令。
总之,我成功地在Discord机器人中注册了Minecraft的坐标并得到了tp指令。辛苦了。