Skip to content

Instantly share code, notes, and snippets.

@Kanin
Last active August 27, 2022 02:10
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Kanin/eca27f515a8f4fc41886782e07a14d79 to your computer and use it in GitHub Desktop.
Save Kanin/eca27f515a8f4fc41886782e07a14d79 to your computer and use it in GitHub Desktop.
__author__ = "Kanin (https://github.com/Kanin)"
__copyright__ = "Copyright (C) 2022 Kanin"
__license__ = "Public Domain"
__version__ = "1.0"
import os
from pathlib import Path
import discord
from PIL import Image
from discord.ext import commands
from discord import app_commands
from discord.ext.tasks import loop
from discord.ui import View, Button
from bot import Bot
from pyboy import PyBoy, WindowEvent
from io import BytesIO
rom_folder = os.path.join(Path(__file__).parent.parent.parent, "utils/assets/ROMs/")
game_name = "Pokemon-Yellow"
current_game = os.path.join(rom_folder, game_name)
game_type = "gbc"
rom_path = os.path.join(current_game, f"{game_name}.{game_type}")
class BBPlays(commands.Cog):
def __init__(self, bot):
self.bot: Bot = bot
self.buttons = {
"up": (WindowEvent.PRESS_ARROW_UP, WindowEvent.RELEASE_ARROW_UP),
"down": (WindowEvent.PRESS_ARROW_DOWN, WindowEvent.RELEASE_ARROW_DOWN),
"left": (WindowEvent.PRESS_ARROW_LEFT, WindowEvent.RELEASE_ARROW_LEFT),
"right": (WindowEvent.PRESS_ARROW_RIGHT, WindowEvent.RELEASE_ARROW_RIGHT),
"b": (WindowEvent.PRESS_BUTTON_B, WindowEvent.RELEASE_BUTTON_B),
"a": (WindowEvent.PRESS_BUTTON_A, WindowEvent.RELEASE_BUTTON_A),
"select": (WindowEvent.PRESS_BUTTON_SELECT, WindowEvent.RELEASE_BUTTON_SELECT),
"start": (WindowEvent.PRESS_BUTTON_START, WindowEvent.RELEASE_BUTTON_START)
}
self.game = None
self.inputs = {"up": 0, "down": 0, "left": 0, "right": 0, "select": 0, "start": 0, "b": 0, "a": 0}
self.multipliers = {2: 0, 3: 0, 4: 0, 5: 0, 6: 0}
self.input_users = []
self.multiplier_users = []
self.loaded = False
def skip_frames(self, frames: int):
frames = frames * 60
x = 0
while x < frames:
self.game.tick()
x += 1
async def cog_load(self):
if not self.loaded:
game = PyBoy(os.path.join(rom_path), window_type="headless")
self.game = game
if os.path.exists(os.path.join(current_game, "Pokemon-Yellow.state")):
self.game.load_state(open(os.path.join(current_game, "Pokemon-Yellow.state"), "rb"))
self.game_loop.start()
self.loaded = True
async def cog_unload(self):
self.game_loop.cancel()
self.game.stop()
self.loaded = False
@app_commands.command()
async def send_gameboy(self, interaction: discord.Interaction, channel: discord.TextChannel):
lbumper = Button(emoji="<:LBumper:1009706435124416574>", disabled=True, style=discord.ButtonStyle.blurple)
rbumper = Button(emoji="<:RBumper:1009706434361040957>", disabled=True, style=discord.ButtonStyle.blurple)
up = Button(emoji="<:Up:1009706432523939850>", style=discord.ButtonStyle.blurple)
down = Button(emoji="<:Down:1009706433421508688>", style=discord.ButtonStyle.blurple)
left = Button(emoji="<:Left:1009706429671800832>", style=discord.ButtonStyle.blurple)
right = Button(emoji="<:Right:1009706431148204043>", style=discord.ButtonStyle.blurple)
a = Button(emoji="<:AButton:1009706436936355842>", style=discord.ButtonStyle.blurple)
b = Button(emoji="<:BButton:1009706436265250856>", style=discord.ButtonStyle.blurple)
select = Button(emoji="<:Select:1009706428740665394>", style=discord.ButtonStyle.blurple)
start = Button(emoji="<:Start:1009706430691033098>", style=discord.ButtonStyle.blurple)
m2 = Button(emoji="2️⃣", style=discord.ButtonStyle.blurple)
m3 = Button(emoji="3️⃣", style=discord.ButtonStyle.blurple)
m4 = Button(emoji="4️⃣", style=discord.ButtonStyle.blurple)
m5 = Button(emoji="5️⃣", style=discord.ButtonStyle.blurple)
m6 = Button(emoji="6️⃣", style=discord.ButtonStyle.blurple)
view = View()
view.add_item(lbumper)
view.add_item(up)
view.add_item(Button(label=" ", disabled=True, style=discord.ButtonStyle.blurple))
view.add_item(Button(label=" ", disabled=True, style=discord.ButtonStyle.blurple))
view.add_item(rbumper)
view.add_item(left)
view.add_item(
Button(emoji="<a:PikaDance:1009707955412807701>", disabled=True, style=discord.ButtonStyle.blurple))
view.add_item(right)
view.add_item(Button(label=" ", disabled=True, style=discord.ButtonStyle.blurple))
view.add_item(a)
view.add_item(Button(label=" ", disabled=True, style=discord.ButtonStyle.blurple))
view.add_item(down)
view.add_item(Button(label=" ", disabled=True, style=discord.ButtonStyle.blurple))
view.add_item(b)
view.add_item(Button(label=" ", disabled=True, style=discord.ButtonStyle.blurple))
view.add_item(m2)
view.add_item(m3)
view.add_item(m4)
view.add_item(m5)
view.add_item(m6)
view.add_item(Button(label=" ", disabled=True, style=discord.ButtonStyle.blurple))
view.add_item(select)
view.add_item(Button(label=" ", disabled=True, style=discord.ButtonStyle.blurple))
view.add_item(start)
view.add_item(Button(label=" ", disabled=True, style=discord.ButtonStyle.blurple))
message = await channel.send(view=view)
em = discord.Embed(title="Gameboy info:", description=message.id)
em.add_field(name="Left Bumper:", value=lbumper.custom_id)
em.add_field(name="Right Bumper:", value=rbumper.custom_id)
em.add_field(name="Up:", value=up.custom_id)
em.add_field(name="Down:", value=down.custom_id)
em.add_field(name="Left:", value=left.custom_id)
em.add_field(name="Right:", value=right.custom_id)
em.add_field(name="A:", value=a.custom_id)
em.add_field(name="B:", value=b.custom_id)
em.add_field(name="Select:", value=select.custom_id)
em.add_field(name="Start:", value=start.custom_id)
em.add_field(name="2x:", value=m2.custom_id)
em.add_field(name="3x:", value=m3.custom_id)
em.add_field(name="4x:", value=m4.custom_id)
em.add_field(name="5x:", value=m5.custom_id)
em.add_field(name="6x:", value=m6.custom_id)
await interaction.user.send(embed=em)
await interaction.response.send_message("I have sent you the button IDs!")
def press_button(self, button: str, multiplier: int = 1):
self.game.send_input(self.buttons[button][0])
for _ in range(15 * multiplier):
self.game.tick()
self.game.send_input(self.buttons[button][1])
@loop(seconds=7)
async def game_loop(self):
choice = max(self.inputs, key=self.inputs.get)
multiplier = max(self.multipliers, key=self.multipliers.get)
if self.inputs[choice] > 0:
if self.multipliers[multiplier] > 0:
self.press_button(choice, multiplier)
else:
multiplier = 1
self.press_button(choice)
else:
choice = "none"
if self.multipliers[multiplier] == 0:
multiplier = 1
self.inputs = {"up": 0, "down": 0, "left": 0, "right": 0, "select": 0, "start": 0, "b": 0, "a": 0}
self.input_users = []
self.multipliers = {2: 0, 3: 0, 4: 0, 5: 0, 6: 0}
self.multiplier_users = []
if choice == "none":
self.skip_frames(5 * int(multiplier))
else:
self.skip_frames(5)
blank = Image.new("RGB", (500, 426), (0, 0, 0))
frame: Image = self.game.screen_image()
frame = frame.resize((426, 426))
blank.paste(frame, (37, 0))
temp = BytesIO()
blank.save(temp, "png")
temp.seek(0)
guild = self.bot.get_guild()
chan = guild.get_channel()
message = await chan.fetch_message()
await message.edit(content=f"Last selection was: {choice}*{multiplier}", attachments=[discord.File(fp=temp, filename="Screen.png")])
self.game.save_state(open(os.path.join(current_game, f"{game_name}.state"), "wb"))
@commands.Cog.listener()
async def on_interaction(self, interaction: discord.Interaction):
data = interaction.data
if data and "component_type" in data and data["component_type"] == 2:
bid = data["custom_id"]
user = interaction.user
if bid in [
"", # Up
"", # Left
"", # Right
"", # Down
"", # A
"", # B
"", # Select
"" # Start
]:
if user.id not in self.input_users:
if bid == "":
self.inputs["up"] += 1
elif bid == "":
self.inputs["left"] += 1
elif bid == "":
self.inputs["right"] += 1
elif bid == "":
self.inputs["down"] += 1
elif bid == "":
self.inputs["a"] += 1
elif bid == "":
self.inputs["b"] += 1
elif bid == "":
self.inputs["select"] += 1
else:
self.inputs["start"] += 1
self.input_users.append(user.id)
return await interaction.response.defer()
await interaction.response.send_message("You've already made a selection!", ephemeral=True)
if bid in [
"", # 2
"", # 3
"", # 4
"", # 5
"" # 6
]:
if user.id not in self.multiplier_users:
if bid == "":
self.multipliers[2] += 1
elif bid == "":
self.multipliers[3] += 1
elif bid == "":
self.multipliers[4] += 1
elif bid == "":
self.multipliers[5] += 1
else:
self.multipliers[6] += 1
self.multiplier_users.append(user.id)
return await interaction.response.defer()
await interaction.response.send_message("You've already made a multiplier selection!", ephemeral=True)
async def setup(bot):
await bot.add_cog(BBPlays(bot))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment