Priority update for listeners
This commit is contained in:
parent
06af229a62
commit
a2eaf55515
@ -9,10 +9,10 @@ import discord
|
||||
from redbot.core import commands
|
||||
from redbot.core.bot import Red
|
||||
|
||||
from .builder import parse_code
|
||||
from .player import Player
|
||||
from .role import Role
|
||||
from .votegroup import VoteGroup
|
||||
from werewolf.builder import parse_code
|
||||
from werewolf.player import Player
|
||||
from werewolf.role import Role
|
||||
from werewolf.votegroup import VoteGroup
|
||||
|
||||
log = logging.getLogger("red.fox_v3.werewolf.game")
|
||||
|
||||
@ -480,7 +480,7 @@ class Game:
|
||||
async def _notify(self, event, **kwargs):
|
||||
for i in range(1, 7): # action guide 1-6 (0 is no action)
|
||||
tasks = []
|
||||
for event in self.listeners.get(event, []):
|
||||
for event in self.listeners.get(event, {}).get(i, []):
|
||||
tasks.append(asyncio.ensure_future(event(**kwargs), loop=self.loop))
|
||||
await asyncio.gather(*tasks)
|
||||
|
||||
@ -912,26 +912,19 @@ class Game:
|
||||
|
||||
# Optional dynamic channels/categories
|
||||
|
||||
def add_listener(self, func, name=None):
|
||||
"""The non decorator alternative to :meth:`.listen`.
|
||||
def add_ww_listener(self, func, priority=0, name=None):
|
||||
"""Adds a listener from the pool of listeners.
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
func: :ref:`coroutine <coroutine>`
|
||||
The function to call.
|
||||
priority: Optional[:class:`int`]
|
||||
Priority of the listener. Defaults to 0 (no-action)
|
||||
name: Optional[:class:`str`]
|
||||
The name of the event to listen for. Defaults to ``func.__name__``.
|
||||
|
||||
Example
|
||||
--------
|
||||
|
||||
.. code-block:: python3
|
||||
|
||||
async def on_ready(): pass
|
||||
async def my_message(message): pass
|
||||
|
||||
bot.add_listener(on_ready)
|
||||
bot.add_listener(my_message, 'on_message')
|
||||
do_sort: Optional[:class:`bool`]
|
||||
Whether or not to sort listeners after. Skip sorting during mass appending
|
||||
|
||||
"""
|
||||
name = func.__name__ if name is None else name
|
||||
@ -940,26 +933,32 @@ class Game:
|
||||
raise TypeError('Listeners must be coroutines')
|
||||
|
||||
if name in self.listeners:
|
||||
self.listeners[name].append(func)
|
||||
if priority in self.listeners[name]:
|
||||
self.listeners[name][priority].append(func)
|
||||
else:
|
||||
self.listeners[name][priority] = [func]
|
||||
else:
|
||||
self.listeners[name] = [func]
|
||||
self.listeners[name] = {priority: [func]}
|
||||
|
||||
def remove_listener(self, func, name=None):
|
||||
"""Removes a listener from the pool of listeners.
|
||||
# self.listeners[name].sort(reverse=True)
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
func
|
||||
The function that was used as a listener to remove.
|
||||
name: :class:`str`
|
||||
The name of the event we want to remove. Defaults to
|
||||
``func.__name__``.
|
||||
"""
|
||||
|
||||
name = func.__name__ if name is None else name
|
||||
|
||||
if name in self.listeners:
|
||||
try:
|
||||
self.listeners[name].remove(func)
|
||||
except ValueError:
|
||||
pass
|
||||
# def remove_wolf_listener(self, func, name=None):
|
||||
# """Removes a listener from the pool of listeners.
|
||||
#
|
||||
# Parameters
|
||||
# -----------
|
||||
# func
|
||||
# The function that was used as a listener to remove.
|
||||
# name: :class:`str`
|
||||
# The name of the event we want to remove. Defaults to
|
||||
# ``func.__name__``.
|
||||
# """
|
||||
#
|
||||
# name = func.__name__ if name is None else name
|
||||
#
|
||||
# if name in self.listeners:
|
||||
# try:
|
||||
# self.listeners[name].remove(func)
|
||||
# except ValueError:
|
||||
# pass
|
||||
|
@ -1,7 +1,7 @@
|
||||
import inspect
|
||||
|
||||
|
||||
def wolflistener(name=None):
|
||||
def wolflistener(name=None, priority=0):
|
||||
"""A decorator that marks a function as a listener.
|
||||
|
||||
This is the werewolf.Game equivalent of :meth:`.Cog.listener`.
|
||||
@ -11,6 +11,22 @@ def wolflistener(name=None):
|
||||
name: :class:`str`
|
||||
The name of the event being listened to. If not provided, it
|
||||
defaults to the function's name.
|
||||
priority: :class:`int`
|
||||
The priority of the listener.
|
||||
Priority guide as follows:
|
||||
_at_night_start
|
||||
0. No Action
|
||||
1. Detain actions (Jailer/Kidnapper)
|
||||
2. Group discussions and choose targets
|
||||
|
||||
_at_night_end
|
||||
0. No Action
|
||||
1. Self actions (Veteran)
|
||||
2. Target switching and role blocks (bus driver, witch, escort)
|
||||
3. Protection / Preempt actions (bodyguard/framer)
|
||||
4. Non-disruptive actions (seer/silencer)
|
||||
5. Disruptive actions (Killing)
|
||||
6. Role altering actions (Cult / Mason / Shifter)
|
||||
|
||||
Raises
|
||||
--------
|
||||
@ -32,12 +48,12 @@ def wolflistener(name=None):
|
||||
actual = actual.__func__
|
||||
if not inspect.iscoroutinefunction(actual):
|
||||
raise TypeError("Listener function must be a coroutine function.")
|
||||
actual.__wolf_listener__ = True
|
||||
actual.__wolf_listener__ = priority
|
||||
to_assign = name or actual.__name__
|
||||
try:
|
||||
actual.__wolf_listener_names__.append(to_assign)
|
||||
actual.__wolf_listener_names__.append((priority, to_assign))
|
||||
except AttributeError:
|
||||
actual.__wolf_listener_names__ = [to_assign]
|
||||
actual.__wolf_listener_names__ = [(priority, to_assign)]
|
||||
# we have to return `func` instead of `actual` because
|
||||
# we need the type to be `staticmethod` for the metaclass
|
||||
# to pick it up but the metaclass unfurls the function and
|
||||
@ -51,7 +67,6 @@ class WolfListenerMeta(type):
|
||||
def __new__(mcs, cls, *args, **kwargs):
|
||||
name, bases = args
|
||||
|
||||
commands = {}
|
||||
listeners = {}
|
||||
need_at_msg = "Listeners must start with at_ (in method {0.__name__}.{1})"
|
||||
|
||||
@ -76,10 +91,10 @@ class WolfListenerMeta(type):
|
||||
|
||||
listeners_as_list = []
|
||||
for listener in listeners.values():
|
||||
for listener_name in listener.__wolf_listener_names__:
|
||||
for priority, listener_name in listener.__wolf_listener_names__:
|
||||
# I use __name__ instead of just storing the value so I can inject
|
||||
# the self attribute when the time comes to add them to the bot
|
||||
listeners_as_list.append((listener_name, listener.__name__))
|
||||
listeners_as_list.append((priority, listener_name, listener.__name__))
|
||||
|
||||
new_cls.__wolf_listeners__ = listeners_as_list
|
||||
return new_cls
|
||||
@ -87,5 +102,5 @@ class WolfListenerMeta(type):
|
||||
|
||||
class WolfListener(metaclass=WolfListenerMeta):
|
||||
def __init__(self, game):
|
||||
for name, method_name in self.__wolf_listeners__:
|
||||
game.add_listener(getattr(self, method_name), name)
|
||||
for priority, name, method_name in self.__wolf_listeners__:
|
||||
game.add_ww_listener(getattr(self, method_name), priority, name)
|
||||
|
@ -1,6 +1,6 @@
|
||||
import logging
|
||||
|
||||
from .role import Role
|
||||
from werewolf.role import Role
|
||||
|
||||
log = logging.getLogger("red.fox_v3.werewolf.night_powers")
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
from ..listener import wolflistener
|
||||
from ..night_powers import pick_target
|
||||
from ..role import Role
|
||||
from werewolf.listener import wolflistener
|
||||
from werewolf.night_powers import pick_target
|
||||
from werewolf.role import Role
|
||||
|
||||
|
||||
class Seer(Role):
|
||||
@ -27,17 +27,17 @@ class Seer(Role):
|
||||
# self.blocked = False
|
||||
# self.properties = {} # Extra data for other roles (i.e. arsonist)
|
||||
self.see_target = None
|
||||
self.action_list = [
|
||||
(self._at_game_start, 1), # (Action, Priority)
|
||||
(self._at_day_start, 0),
|
||||
(self._at_voted, 0),
|
||||
(self._at_kill, 0),
|
||||
(self._at_hang, 0),
|
||||
(self._at_day_end, 0),
|
||||
(self._at_night_start, 2),
|
||||
(self._at_night_end, 4),
|
||||
(self._at_visit, 0),
|
||||
]
|
||||
# self.action_list = [
|
||||
# (self._at_game_start, 1), # (Action, Priority)
|
||||
# (self._at_day_start, 0),
|
||||
# (self._at_voted, 0),
|
||||
# (self._at_kill, 0),
|
||||
# (self._at_hang, 0),
|
||||
# (self._at_day_end, 0),
|
||||
# (self._at_night_start, 2),
|
||||
# (self._at_night_end, 4),
|
||||
# (self._at_visit, 0),
|
||||
# ]
|
||||
|
||||
async def see_alignment(self, source=None):
|
||||
"""
|
||||
@ -60,7 +60,7 @@ class Seer(Role):
|
||||
"""
|
||||
return "Villager"
|
||||
|
||||
@wolflistener("at_night_start")
|
||||
@wolflistener("at_night_start", priority=2)
|
||||
async def _at_night_start(self, data=None):
|
||||
if not self.player.alive:
|
||||
return
|
||||
@ -68,7 +68,7 @@ class Seer(Role):
|
||||
await self.game.generate_targets(self.player.member)
|
||||
await self.player.send_dm("**Pick a target to see tonight**")
|
||||
|
||||
@wolflistener("at_night_end")
|
||||
@wolflistener("at_night_end", priority=4)
|
||||
async def _at_night_end(self, data=None):
|
||||
if self.see_target is None:
|
||||
if self.player.alive:
|
||||
|
@ -1,7 +1,6 @@
|
||||
from ..listener import wolflistener
|
||||
from ..role import Role
|
||||
|
||||
from ..votegroups.wolfvote import WolfVote
|
||||
from werewolf.listener import wolflistener
|
||||
from werewolf.role import Role
|
||||
from werewolf.votegroups.wolfvote import WolfVote
|
||||
|
||||
|
||||
class VanillaWerewolf(Role):
|
||||
|
@ -1,4 +1,4 @@
|
||||
from ..role import Role
|
||||
from werewolf.role import Role
|
||||
|
||||
|
||||
class Villager(Role):
|
||||
|
1
werewolf/votegroups/__init__.py
Normal file
1
werewolf/votegroups/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from .wolfvote import WolfVote
|
@ -1,6 +1,6 @@
|
||||
import random
|
||||
|
||||
from ..votegroup import VoteGroup
|
||||
from werewolf.votegroup import VoteGroup
|
||||
|
||||
|
||||
class WolfVote(VoteGroup):
|
||||
|
@ -6,14 +6,14 @@ from redbot.core.bot import Red
|
||||
from redbot.core.commands import Cog
|
||||
from redbot.core.utils.menus import DEFAULT_CONTROLS, menu
|
||||
|
||||
from .builder import (
|
||||
from werewolf.builder import (
|
||||
GameBuilder,
|
||||
role_from_alignment,
|
||||
role_from_category,
|
||||
role_from_id,
|
||||
role_from_name,
|
||||
)
|
||||
from .game import Game
|
||||
from werewolf.game import Game
|
||||
|
||||
log = logging.getLogger("red.fox_v3.werewolf")
|
||||
|
||||
@ -81,8 +81,8 @@ class Werewolf(Cog):
|
||||
"""
|
||||
Lists current guild settings
|
||||
"""
|
||||
success, role, category, channel, log_channel = await self._get_settings(ctx)
|
||||
if not success:
|
||||
valid, role, category, channel, log_channel = await self._get_settings(ctx)
|
||||
if not valid:
|
||||
await ctx.send("Failed to get settings")
|
||||
return None
|
||||
|
||||
@ -362,13 +362,15 @@ class Werewolf(Cog):
|
||||
return None
|
||||
if guild.id not in self.games or self.games[guild.id].game_over:
|
||||
await ctx.send("Starting a new game...")
|
||||
success, role, category, channel, log_channel = await self._get_settings(ctx)
|
||||
valid, role, category, channel, log_channel = await self._get_settings(ctx)
|
||||
|
||||
if not success:
|
||||
if not valid:
|
||||
await ctx.send("Cannot start a new game")
|
||||
return None
|
||||
|
||||
self.games[guild.id] = Game(self.bot, guild, role, category, channel, log_channel, game_code)
|
||||
self.games[guild.id] = Game(
|
||||
self.bot, guild, role, category, channel, log_channel, game_code
|
||||
)
|
||||
|
||||
return self.games[guild.id]
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user