mirror of
https://github.com/solero/houdini.git
synced 2024-11-21 21:17:21 +00:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
923c31fbd1
@ -1,9 +1,9 @@
|
|||||||
|
import argparse
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
import argparse
|
|
||||||
|
|
||||||
|
from houdini.constants import ClientType, ConflictResolution, Language
|
||||||
from houdini.houdini import Houdini
|
from houdini.houdini import Houdini
|
||||||
from houdini.constants import Language, ConflictResolution, ClientType
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
logger = logging.getLogger('houdini')
|
logger = logging.getLogger('houdini')
|
||||||
|
14002
houdini.sql
14002
houdini.sql
File diff suppressed because it is too large
Load Diff
@ -1,11 +1,10 @@
|
|||||||
|
import asyncio
|
||||||
|
import importlib
|
||||||
|
import logging
|
||||||
|
import pkgutil
|
||||||
|
from abc import ABC, abstractmethod
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from types import FunctionType
|
from types import FunctionType
|
||||||
from abc import abstractmethod
|
|
||||||
|
|
||||||
import asyncio
|
|
||||||
import logging
|
|
||||||
import importlib
|
|
||||||
import pkgutil
|
|
||||||
|
|
||||||
|
|
||||||
def get_package_modules(package):
|
def get_package_modules(package):
|
||||||
@ -37,6 +36,56 @@ class _AbstractManager(dict):
|
|||||||
"""Loads entries from module"""
|
"""Loads entries from module"""
|
||||||
|
|
||||||
|
|
||||||
|
class ITable(ABC):
|
||||||
|
"""
|
||||||
|
All table game logic classes must implement this interface.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def make_move(self, *args):
|
||||||
|
"""Tells logic a move has been made."""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def is_valid_move(self, *args):
|
||||||
|
"""Returns true if the move is valid."""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def get_string(self):
|
||||||
|
"""Returns string representation of the game."""
|
||||||
|
|
||||||
|
|
||||||
|
class IWaddle(ABC):
|
||||||
|
"""
|
||||||
|
All waddle game logic classes must implement this interface.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def room_id(self):
|
||||||
|
"""External ID of waddle game room."""
|
||||||
|
|
||||||
|
def __init__(self, waddle):
|
||||||
|
self.penguins = list(waddle.penguins)
|
||||||
|
self.seats = waddle.seats
|
||||||
|
|
||||||
|
async def start(self):
|
||||||
|
room_id = type(self).room_id
|
||||||
|
for penguin in self.penguins:
|
||||||
|
penguin.waddle = self
|
||||||
|
await penguin.join_room(penguin.server.rooms[room_id])
|
||||||
|
|
||||||
|
async def remove_penguin(self, p):
|
||||||
|
self.penguins.remove(p)
|
||||||
|
p.waddle = None
|
||||||
|
|
||||||
|
async def send_xt(self, *data):
|
||||||
|
for penguin in self.penguins:
|
||||||
|
await penguin.send_xt(*data)
|
||||||
|
|
||||||
|
def get_seat_id(self, p):
|
||||||
|
return self.penguins.index(p)
|
||||||
|
|
||||||
|
|
||||||
class PenguinStringCompiler(OrderedDict):
|
class PenguinStringCompiler(OrderedDict):
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
import inspect
|
import inspect
|
||||||
|
|
||||||
from houdini import handlers
|
from houdini import _AbstractManager, handlers, plugins
|
||||||
from houdini import plugins
|
|
||||||
from houdini import _AbstractManager
|
|
||||||
from houdini.constants import ConflictResolution
|
from houdini.constants import ConflictResolution
|
||||||
|
|
||||||
from houdini.converters import _ArgumentDeserializer, _listener
|
from houdini.converters import _ArgumentDeserializer, _listener
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,18 +1,15 @@
|
|||||||
from abc import ABC
|
|
||||||
from abc import abstractmethod
|
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import itertools
|
|
||||||
import inspect
|
|
||||||
import collections
|
import collections
|
||||||
|
import inspect
|
||||||
|
import itertools
|
||||||
|
from abc import ABC, abstractmethod
|
||||||
|
|
||||||
from houdini.cooldown import CooldownError
|
from houdini.cooldown import CooldownError
|
||||||
|
from houdini.data.igloo import Flooring, Furniture, Igloo, Location
|
||||||
from houdini.data.room import Room
|
|
||||||
from houdini.data.item import Item
|
from houdini.data.item import Item
|
||||||
from houdini.data.igloo import Igloo, Furniture, Flooring, Location
|
from houdini.data.pet import PenguinPuffle, Puffle
|
||||||
|
from houdini.data.room import Room
|
||||||
from houdini.data.stamp import Stamp
|
from houdini.data.stamp import Stamp
|
||||||
from houdini.data.pet import Puffle, PenguinPuffle
|
|
||||||
|
|
||||||
|
|
||||||
class ChecklistError(Exception):
|
class ChecklistError(Exception):
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
from gino import Gino
|
|
||||||
from collections.abc import Mapping
|
from collections.abc import Mapping
|
||||||
|
|
||||||
|
from gino import Gino
|
||||||
|
|
||||||
db = Gino()
|
db = Gino()
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
from houdini.data import db, AbstractDataCollection
|
from houdini.data import AbstractDataCollection, db
|
||||||
|
|
||||||
|
|
||||||
class BuddyList(db.Model):
|
class BuddyList(db.Model):
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
from houdini.data import db, AbstractDataCollection
|
from houdini.data import AbstractDataCollection, db
|
||||||
|
|
||||||
|
|
||||||
class DanceSong(db.Model):
|
class DanceSong(db.Model):
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
from houdini.data import db, AbstractDataCollection
|
from houdini.data import AbstractDataCollection, db
|
||||||
from functools import cached_property
|
from functools import cached_property
|
||||||
|
|
||||||
class Flooring(db.Model):
|
class Flooring(db.Model):
|
||||||
@ -8,6 +8,8 @@ class Flooring(db.Model):
|
|||||||
name = db.Column(db.String(50))
|
name = db.Column(db.String(50))
|
||||||
cost = db.Column(db.Integer, nullable=False, server_default=db.text("0"))
|
cost = db.Column(db.Integer, nullable=False, server_default=db.text("0"))
|
||||||
patched = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
|
patched = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
|
||||||
|
legacy_inventory = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
|
||||||
|
vanilla_inventory = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
|
||||||
|
|
||||||
|
|
||||||
class Furniture(db.Model):
|
class Furniture(db.Model):
|
||||||
@ -20,6 +22,8 @@ class Furniture(db.Model):
|
|||||||
cost = db.Column(db.Integer, nullable=False, server_default=db.text("0"))
|
cost = db.Column(db.Integer, nullable=False, server_default=db.text("0"))
|
||||||
member = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
|
member = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
|
||||||
patched = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
|
patched = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
|
||||||
|
legacy_inventory = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
|
||||||
|
vanilla_inventory = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
|
||||||
bait = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
|
bait = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
|
||||||
max_quantity = db.Column(db.SmallInteger, nullable=False, server_default=db.text("100"))
|
max_quantity = db.Column(db.SmallInteger, nullable=False, server_default=db.text("100"))
|
||||||
innocent = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
|
innocent = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
|
||||||
@ -33,6 +37,8 @@ class Igloo(db.Model):
|
|||||||
name = db.Column(db.String(50), nullable=False)
|
name = db.Column(db.String(50), nullable=False)
|
||||||
cost = db.Column(db.SmallInteger, nullable=False, server_default=db.text("0"))
|
cost = db.Column(db.SmallInteger, nullable=False, server_default=db.text("0"))
|
||||||
patched = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
|
patched = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
|
||||||
|
legacy_inventory = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
|
||||||
|
vanilla_inventory = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
|
||||||
|
|
||||||
|
|
||||||
class IglooFurniture(db.Model):
|
class IglooFurniture(db.Model):
|
||||||
@ -66,6 +72,8 @@ class Location(db.Model):
|
|||||||
name = db.Column(db.String(50), nullable=False)
|
name = db.Column(db.String(50), nullable=False)
|
||||||
cost = db.Column(db.Integer, nullable=False, server_default=db.text("0"))
|
cost = db.Column(db.Integer, nullable=False, server_default=db.text("0"))
|
||||||
patched = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
|
patched = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
|
||||||
|
legacy_inventory = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
|
||||||
|
vanilla_inventory = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
|
||||||
|
|
||||||
|
|
||||||
class PenguinIgloo(db.Model):
|
class PenguinIgloo(db.Model):
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
from houdini.data import db, AbstractDataCollection
|
from houdini.data import db, AbstractDataCollection
|
||||||
from functools import cached_property
|
from functools import cached_property
|
||||||
|
|
||||||
|
|
||||||
class Item(db.Model):
|
class Item(db.Model):
|
||||||
__tablename__ = 'item'
|
__tablename__ = 'item'
|
||||||
|
|
||||||
@ -10,6 +12,8 @@ class Item(db.Model):
|
|||||||
member = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
|
member = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
|
||||||
bait = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
|
bait = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
|
||||||
patched = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
|
patched = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
|
||||||
|
legacy_inventory = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
|
||||||
|
vanilla_inventory = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
|
||||||
epf = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
|
epf = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
|
||||||
tour = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
|
tour = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
|
||||||
release_date = db.Column(db.Date, nullable=False, server_default=db.text("now()"))
|
release_date = db.Column(db.Date, nullable=False, server_default=db.text("now()"))
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
from houdini.data import db, AbstractDataCollection
|
from houdini.data import AbstractDataCollection, db
|
||||||
|
|
||||||
|
|
||||||
class Postcard(db.Model):
|
class Postcard(db.Model):
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
from houdini.data import db, AbstractDataCollection
|
from houdini.data import AbstractDataCollection, db
|
||||||
|
|
||||||
|
|
||||||
class Ban(db.Model):
|
class Ban(db.Model):
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
from houdini.data import db, AbstractDataCollection
|
from houdini.data import AbstractDataCollection, db
|
||||||
|
|
||||||
|
|
||||||
class Card(db.Model):
|
class Card(db.Model):
|
||||||
@ -14,6 +14,16 @@ class Card(db.Model):
|
|||||||
description = db.Column(db.String(255), nullable=False, server_default=db.text("''::character varying"))
|
description = db.Column(db.String(255), nullable=False, server_default=db.text("''::character varying"))
|
||||||
|
|
||||||
|
|
||||||
|
class CardStarterDeck(db.Model):
|
||||||
|
__tablename__ = 'card_starter_deck'
|
||||||
|
|
||||||
|
item_id = db.Column(db.ForeignKey('item.id', ondelete='CASCADE', onupdate='CASCADE'), primary_key=True,
|
||||||
|
nullable=False, index=True)
|
||||||
|
card_id = db.Column(db.ForeignKey('card.id', ondelete='CASCADE', onupdate='CASCADE'), primary_key=True,
|
||||||
|
nullable=False)
|
||||||
|
quantity = db.Column(db.SmallInteger, nullable=False, server_default=db.text("1"))
|
||||||
|
|
||||||
|
|
||||||
class PenguinCard(db.Model):
|
class PenguinCard(db.Model):
|
||||||
__tablename__ = 'penguin_card'
|
__tablename__ = 'penguin_card'
|
||||||
|
|
||||||
@ -30,6 +40,21 @@ class CardCollection(AbstractDataCollection):
|
|||||||
__indexby__ = 'id'
|
__indexby__ = 'id'
|
||||||
__filterby__ = 'id'
|
__filterby__ = 'id'
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
self.starter_decks = {}
|
||||||
|
|
||||||
|
def set_starter_decks(self, starter_deck_cards):
|
||||||
|
for card in starter_deck_cards:
|
||||||
|
starter_deck = self.starter_decks.get(card.item_id, [])
|
||||||
|
starter_deck.append((self.get(card.card_id), card.quantity))
|
||||||
|
self.starter_decks[card.item_id] = starter_deck
|
||||||
|
|
||||||
|
@property
|
||||||
|
def power_cards(self):
|
||||||
|
return [card for card in self.values() if card.power_id > 0]
|
||||||
|
|
||||||
|
|
||||||
class PenguinCardCollection(AbstractDataCollection):
|
class PenguinCardCollection(AbstractDataCollection):
|
||||||
__model__ = PenguinCard
|
__model__ = PenguinCard
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from functools import lru_cache
|
||||||
|
|
||||||
from houdini.data import db
|
from houdini.data import db
|
||||||
|
|
||||||
from functools import lru_cache
|
|
||||||
|
|
||||||
|
|
||||||
class Penguin(db.Model):
|
class Penguin(db.Model):
|
||||||
__tablename__ = 'penguin'
|
__tablename__ = 'penguin'
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
from houdini.data import db, AbstractDataCollection
|
from houdini.data import AbstractDataCollection, db
|
||||||
|
|
||||||
|
|
||||||
class Permission(db.Model):
|
class Permission(db.Model):
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
from houdini.data import db, AbstractDataCollection
|
from houdini.data import AbstractDataCollection, db
|
||||||
|
|
||||||
|
|
||||||
class Puffle(db.Model):
|
class Puffle(db.Model):
|
||||||
|
@ -1,9 +1,4 @@
|
|||||||
from houdini.games.sled import SledRacingLogic
|
from houdini.data import AbstractDataCollection, db
|
||||||
from houdini.games.four import ConnectFourLogic
|
|
||||||
from houdini.games.mancala import MancalaLogic
|
|
||||||
from houdini.games.treasure import TreasureHuntLogic
|
|
||||||
|
|
||||||
from houdini.data import db, AbstractDataCollection
|
|
||||||
|
|
||||||
|
|
||||||
def stealth_mod_filter(stealth_mod_id):
|
def stealth_mod_filter(stealth_mod_id):
|
||||||
@ -199,12 +194,6 @@ class RoomTable(db.Model):
|
|||||||
nullable=False)
|
nullable=False)
|
||||||
game = db.Column(db.String(20), nullable=False)
|
game = db.Column(db.String(20), nullable=False)
|
||||||
|
|
||||||
GameClassMapping = {
|
|
||||||
'four': ConnectFourLogic,
|
|
||||||
'mancala': MancalaLogic,
|
|
||||||
'treasure': TreasureHuntLogic
|
|
||||||
}
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.penguins = []
|
self.penguins = []
|
||||||
@ -272,14 +261,13 @@ class RoomWaddle(db.Model):
|
|||||||
seats = db.Column(db.SmallInteger, nullable=False, server_default=db.text("2"))
|
seats = db.Column(db.SmallInteger, nullable=False, server_default=db.text("2"))
|
||||||
game = db.Column(db.String(20), nullable=False)
|
game = db.Column(db.String(20), nullable=False)
|
||||||
|
|
||||||
GameClassMapping = {
|
|
||||||
'sled': SledRacingLogic
|
|
||||||
}
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
self.temporary = kwargs.pop('temporary', False)
|
||||||
|
|
||||||
self.penguins = []
|
self.penguins = []
|
||||||
|
self.logic = None
|
||||||
|
self.room = None
|
||||||
|
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
async def add_penguin(self, p):
|
async def add_penguin(self, p):
|
||||||
if not self.penguins:
|
if not self.penguins:
|
||||||
@ -287,29 +275,35 @@ class RoomWaddle(db.Model):
|
|||||||
|
|
||||||
seat_id = self.penguins.index(None)
|
seat_id = self.penguins.index(None)
|
||||||
self.penguins[seat_id] = p
|
self.penguins[seat_id] = p
|
||||||
await p.send_xt("jw", seat_id)
|
await p.send_xt('jw', seat_id)
|
||||||
await p.room.send_xt("uw", self.id, seat_id, p.safe_name)
|
await p.room.send_xt('uw', self.id, seat_id, p.safe_name)
|
||||||
|
|
||||||
p.waddle = self
|
p.waddle = self
|
||||||
|
|
||||||
if self.penguins.count(None) == 0:
|
if self.penguins.count(None) == 0:
|
||||||
game_instance = RoomWaddle.GameClassMapping[self.game](self)
|
game_instance = self.logic(self)
|
||||||
await game_instance.start()
|
await game_instance.start()
|
||||||
|
|
||||||
await self.reset()
|
await self.reset()
|
||||||
|
|
||||||
|
if self.temporary:
|
||||||
|
del p.server.rooms[self.room_id].waddles[self.id]
|
||||||
|
|
||||||
async def remove_penguin(self, p):
|
async def remove_penguin(self, p):
|
||||||
seat_id = self.get_seat_id(p)
|
seat_id = self.get_seat_id(p)
|
||||||
self.penguins[seat_id] = None
|
self.penguins[seat_id] = None
|
||||||
await p.room.send_xt("uw", self.id, seat_id)
|
await p.room.send_xt('uw', self.id, seat_id)
|
||||||
|
|
||||||
p.waddle = None
|
p.waddle = None
|
||||||
|
|
||||||
|
if self.temporary and self.penguins.count(None) == self.seats:
|
||||||
|
del p.server.rooms[self.room_id].waddles[self.id]
|
||||||
|
|
||||||
async def reset(self):
|
async def reset(self):
|
||||||
for seat_id, penguin in enumerate(self.penguins):
|
for seat_id, penguin in enumerate(self.penguins):
|
||||||
if penguin:
|
if penguin:
|
||||||
self.penguins[seat_id] = None
|
self.penguins[seat_id] = None
|
||||||
await penguin.room.send_xt("uw", self.id, seat_id)
|
await penguin.room.send_xt('uw', self.id, seat_id)
|
||||||
|
|
||||||
def get_seat_id(self, p):
|
def get_seat_id(self, p):
|
||||||
return self.penguins.index(p)
|
return self.penguins.index(p)
|
||||||
@ -329,16 +323,3 @@ class RoomCollection(AbstractDataCollection):
|
|||||||
@property
|
@property
|
||||||
def spawn_rooms(self):
|
def spawn_rooms(self):
|
||||||
return [room for room in self.values() if room.spawn]
|
return [room for room in self.values() if room.spawn]
|
||||||
|
|
||||||
async def setup_tables(self):
|
|
||||||
async with db.transaction():
|
|
||||||
async for table in RoomTable.query.gino.iterate():
|
|
||||||
self[table.room_id].tables[table.id] = table
|
|
||||||
table.room = self[table.room_id]
|
|
||||||
table.logic = RoomTable.GameClassMapping[table.game]()
|
|
||||||
|
|
||||||
async def setup_waddles(self):
|
|
||||||
async with db.transaction():
|
|
||||||
async for waddle in RoomWaddle.query.gino.iterate():
|
|
||||||
self[waddle.room_id].waddles[waddle.id] = waddle
|
|
||||||
waddle.room = self[waddle.room_id]
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
from houdini.data import db, AbstractDataCollection
|
from houdini.data import AbstractDataCollection, db
|
||||||
|
|
||||||
|
|
||||||
class Stamp(db.Model):
|
class Stamp(db.Model):
|
||||||
|
@ -1,49 +0,0 @@
|
|||||||
from abc import ABC
|
|
||||||
from abc import abstractmethod
|
|
||||||
|
|
||||||
|
|
||||||
class ITable(ABC):
|
|
||||||
"""
|
|
||||||
All table game logic classes must implement this interface.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def make_move(self, *args):
|
|
||||||
"""Tells logic a move has been made."""
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def is_valid_move(self, *args):
|
|
||||||
"""Returns true if the move is valid."""
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def get_string(self):
|
|
||||||
"""Returns string representation of the game."""
|
|
||||||
|
|
||||||
|
|
||||||
class IWaddle(ABC):
|
|
||||||
"""
|
|
||||||
All waddle game logic classes must implement this interface.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@property
|
|
||||||
@abstractmethod
|
|
||||||
def __room_id__(self):
|
|
||||||
"""External ID of waddle game room."""
|
|
||||||
|
|
||||||
def __init__(self, waddle):
|
|
||||||
self.penguins = list(waddle.penguins)
|
|
||||||
self.seats = waddle.seats
|
|
||||||
|
|
||||||
async def start(self):
|
|
||||||
room_id = type(self).__room_id__
|
|
||||||
for penguin in self.penguins:
|
|
||||||
penguin.waddle = self
|
|
||||||
await penguin.join_room(penguin.server.rooms[room_id])
|
|
||||||
|
|
||||||
async def remove_penguin(self, p):
|
|
||||||
self.penguins.remove(p)
|
|
||||||
p.waddle = None
|
|
||||||
|
|
||||||
async def send_xt(self, *data):
|
|
||||||
for penguin in self.penguins:
|
|
||||||
await penguin.send_xt(*data)
|
|
@ -1,45 +0,0 @@
|
|||||||
from houdini.games import ITable
|
|
||||||
|
|
||||||
|
|
||||||
class ConnectFourLogic(ITable):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.current_player = 1
|
|
||||||
self.board = [[0 for _ in range(6)] for _ in range(7)]
|
|
||||||
|
|
||||||
def make_move(self, col, row):
|
|
||||||
self.board[col][row] = self.current_player
|
|
||||||
|
|
||||||
def is_valid_move(self, col, row):
|
|
||||||
if 0 <= row <= 5 and 0 <= col <= 6:
|
|
||||||
if row == 5 or (self.board[col][row] == 0 and self.board[col][row + 1]):
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def get_string(self):
|
|
||||||
return ','.join(str(item) for row in self.board for item in row)
|
|
||||||
|
|
||||||
def is_position_win(self, col, row):
|
|
||||||
for delta_row, delta_col in [(1, 0), (0, 1), (1, 1), (1, -1)]:
|
|
||||||
streak = 1
|
|
||||||
for delta in (1, -1):
|
|
||||||
delta_row *= delta
|
|
||||||
delta_col *= delta
|
|
||||||
next_row = row + delta_row
|
|
||||||
next_col = col + delta_col
|
|
||||||
while 0 <= next_row < 6 and 0 <= next_col < 7:
|
|
||||||
if self.board[next_col][next_row] == self.current_player:
|
|
||||||
streak += 1
|
|
||||||
else:
|
|
||||||
break
|
|
||||||
if streak == 4:
|
|
||||||
return True
|
|
||||||
next_row += delta_row
|
|
||||||
next_col += delta_col
|
|
||||||
return False
|
|
||||||
|
|
||||||
def is_board_full(self):
|
|
||||||
for col in self.board:
|
|
||||||
if not col[0]:
|
|
||||||
return False
|
|
||||||
return True
|
|
@ -1,63 +0,0 @@
|
|||||||
from houdini.games import ITable
|
|
||||||
|
|
||||||
|
|
||||||
class MancalaLogic(ITable):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.current_player = 1
|
|
||||||
self.board = [
|
|
||||||
4, 4, 4, 4, 4, 4, 0,
|
|
||||||
4, 4, 4, 4, 4, 4, 0
|
|
||||||
]
|
|
||||||
|
|
||||||
def make_move(self, hollow):
|
|
||||||
capture = False
|
|
||||||
hand = self.board[hollow]
|
|
||||||
self.board[hollow] = 0
|
|
||||||
|
|
||||||
while hand > 0:
|
|
||||||
hollow = (hollow + 1) % len(self.board)
|
|
||||||
my_mancala, opponent_mancala = (6, 13) if self.current_player == 1 else (13, 6)
|
|
||||||
|
|
||||||
if hollow == opponent_mancala:
|
|
||||||
continue
|
|
||||||
opposite_hollow = 12 - hollow
|
|
||||||
|
|
||||||
if hand == 1 and self.board[hollow] == 0:
|
|
||||||
if (self.current_player == 1 and hollow in range(0, 6)) or (self.current_player == 2 and hollow in range(7, 13)):
|
|
||||||
self.board[my_mancala] += self.board[opposite_hollow] + 1
|
|
||||||
self.board[opposite_hollow] = 0
|
|
||||||
capture = True
|
|
||||||
break
|
|
||||||
|
|
||||||
self.board[hollow] += 1
|
|
||||||
hand -= 1
|
|
||||||
|
|
||||||
if (self.current_player == 1 and hollow != 6) or (self.current_player == 2 and hollow != 13):
|
|
||||||
return 'c' if capture else str()
|
|
||||||
else:
|
|
||||||
self.current_player = 2 if self.current_player == 1 else 1
|
|
||||||
return 'f'
|
|
||||||
|
|
||||||
def is_valid_move(self, hollow):
|
|
||||||
if self.current_player == 1 and hollow not in range(0, 6):
|
|
||||||
return False
|
|
||||||
elif self.current_player == 2 and hollow not in range(7, 13):
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
def get_string(self):
|
|
||||||
return ','.join(map(str, self.board))
|
|
||||||
|
|
||||||
def is_position_win(self):
|
|
||||||
if sum(self.board[0:6]) == 0 or sum(self.board[7:-1]) == 0:
|
|
||||||
if sum(self.board[0:6]) > sum(self.board[7:-1]):
|
|
||||||
return self.current_player == 1
|
|
||||||
return self.current_player == 2
|
|
||||||
return False
|
|
||||||
|
|
||||||
def is_position_tie(self):
|
|
||||||
if sum(self.board[0:6]) == 0 or sum(self.board[7:-1]) == 0:
|
|
||||||
if sum(self.board[0:6]) == sum(self.board[7:-1]):
|
|
||||||
return True
|
|
||||||
return False
|
|
@ -1,19 +0,0 @@
|
|||||||
from houdini.games import IWaddle
|
|
||||||
|
|
||||||
|
|
||||||
class SledRacingLogic(IWaddle):
|
|
||||||
|
|
||||||
__room_id__ = 999
|
|
||||||
|
|
||||||
def __init__(self, waddle):
|
|
||||||
super().__init__(waddle)
|
|
||||||
|
|
||||||
self.payouts = [20, 10, 5, 5]
|
|
||||||
|
|
||||||
async def remove_penguin(self, p):
|
|
||||||
await super().remove_penguin(p)
|
|
||||||
await self.send_xt('uz', self.seats, *(f'{penguin.safe_name}|{penguin.color}|'
|
|
||||||
f'{penguin.hand}|{penguin.safe_name}' for penguin in self.penguins))
|
|
||||||
|
|
||||||
def get_payout(self):
|
|
||||||
return self.payouts.pop(0)
|
|
@ -1,129 +0,0 @@
|
|||||||
from houdini.games import ITable
|
|
||||||
|
|
||||||
import random
|
|
||||||
|
|
||||||
|
|
||||||
class TreasureHuntLogic(ITable):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.map_width = 10
|
|
||||||
self.map_height = 10
|
|
||||||
self.coins_hidden = 0
|
|
||||||
self.gems_hidden = 0
|
|
||||||
self.turns = 12
|
|
||||||
self.gem_value = 25
|
|
||||||
self.coin_value = 1
|
|
||||||
self.gem_locations = []
|
|
||||||
self.treasure_map = []
|
|
||||||
self.coins_found = 0
|
|
||||||
self.gems_found = 0
|
|
||||||
self.emerald_found = 0
|
|
||||||
self.dig_record_names = []
|
|
||||||
self.dig_record_directions = []
|
|
||||||
self.dig_record_numbers = []
|
|
||||||
self.emerald = 0
|
|
||||||
self.current_player = 1
|
|
||||||
self.generate_map()
|
|
||||||
|
|
||||||
def make_move(self, movie, direction, spade):
|
|
||||||
if direction == 'right':
|
|
||||||
row = self.treasure_map[spade]
|
|
||||||
for column, tiles in enumerate(row):
|
|
||||||
self.dig(spade, column)
|
|
||||||
elif direction == 'down':
|
|
||||||
for row, columns in enumerate(self.treasure_map):
|
|
||||||
self.dig(row, spade)
|
|
||||||
self.turns -= 1
|
|
||||||
self.dig_record_names.append(movie)
|
|
||||||
self.dig_record_directions.append(direction)
|
|
||||||
self.dig_record_numbers.append(spade)
|
|
||||||
|
|
||||||
def is_valid_move(self, movie, direction, spade):
|
|
||||||
test_movie = direction + 'button' + str(spade) + '_mc'
|
|
||||||
if test_movie == movie and direction in ['down', 'right'] and 0 <= spade <= 9:
|
|
||||||
if direction == 'right':
|
|
||||||
row = self.treasure_map[spade]
|
|
||||||
for column, tiles in enumerate(row):
|
|
||||||
treasure, digs = self.treasure_map[spade][column]
|
|
||||||
if digs == 2:
|
|
||||||
return False
|
|
||||||
elif direction == 'down':
|
|
||||||
for row, columns in enumerate(self.treasure_map):
|
|
||||||
treasure, digs = self.treasure_map[row][spade]
|
|
||||||
if digs == 2:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def get_string(self):
|
|
||||||
treasure_map = ','.join(str(item) for row in self.treasure_map for item, digs in row)
|
|
||||||
gem_locations = ','.join(self.gem_locations)
|
|
||||||
game_array = [self.map_width, self.map_height, self.coins_hidden, self.gems_hidden, self.turns,
|
|
||||||
self.gem_value, self.coin_value, gem_locations, treasure_map]
|
|
||||||
if self.dig_record_numbers:
|
|
||||||
game_array += [self.coins_found, self.gems_found, self.emerald_found]
|
|
||||||
game_array += [','.join(self.dig_record_names), ','.join(self.dig_record_directions),
|
|
||||||
','.join(map(str, self.dig_record_numbers))]
|
|
||||||
return '%'.join(map(str, game_array))
|
|
||||||
|
|
||||||
def generate_map(self):
|
|
||||||
for row in range(self.map_height):
|
|
||||||
self.treasure_map.append([])
|
|
||||||
for column in range(self.map_width):
|
|
||||||
self.treasure_map[row].append([self.generate_treasure(row, column), 0])
|
|
||||||
|
|
||||||
def generate_treasure(self, row, column):
|
|
||||||
treasure_type = [('None', 0), ('Coin', 1), ('Gem', 2), ('Emerald', 4)]
|
|
||||||
if self.get_gem_by_piece(row, column):
|
|
||||||
return 3
|
|
||||||
if row + 1 == self.map_height or column + 1 == self.map_width:
|
|
||||||
treasure_type = treasure_type[:2]
|
|
||||||
name, value = random.choices(treasure_type, weights=[60, 40, 1, 0.5][:len(treasure_type)])[0]
|
|
||||||
self.coins_hidden += 1 if value == 1 else self.coins_hidden
|
|
||||||
if value > 1:
|
|
||||||
self.gems_hidden += 1
|
|
||||||
self.gem_locations.append(str(row) + ',' + str(column))
|
|
||||||
if self.emerald:
|
|
||||||
return 2
|
|
||||||
if value == 4 and not self.emerald:
|
|
||||||
self.emerald = 1
|
|
||||||
return value
|
|
||||||
|
|
||||||
def get_gem_by_piece(self, row, column):
|
|
||||||
for delta_row, delta_col in [(0, -1), (-1, -1), (-1, 0)]:
|
|
||||||
if row > 0 and column > 0:
|
|
||||||
treasure, digs = self.treasure_map[row + delta_row][column + delta_col]
|
|
||||||
if treasure == 2 or treasure == 4:
|
|
||||||
return row + delta_row, column + delta_col
|
|
||||||
return False
|
|
||||||
|
|
||||||
def is_gem_uncovered(self, row, column):
|
|
||||||
for delta_row, delta_col in [(0, 1), (1, 1), (1, 0)]:
|
|
||||||
treasure, digs = self.treasure_map[row + delta_row][column + delta_col]
|
|
||||||
if digs != 2:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
def dig(self, row, column):
|
|
||||||
self.treasure_map[row][column][1] += 1
|
|
||||||
treasure, digs = self.treasure_map[row][column]
|
|
||||||
if digs == 2:
|
|
||||||
if treasure == 1:
|
|
||||||
self.coins_found += 1
|
|
||||||
elif treasure == 2 or treasure == 4:
|
|
||||||
if not self.is_gem_uncovered(row, column):
|
|
||||||
return
|
|
||||||
self.gems_found += 1
|
|
||||||
elif treasure == 3:
|
|
||||||
treasure_row, treasure_col = self.get_gem_by_piece(row, column)
|
|
||||||
if not self.is_gem_uncovered(treasure_row, treasure_col):
|
|
||||||
return
|
|
||||||
self.gems_found += 1
|
|
||||||
if treasure == 4:
|
|
||||||
self.emerald_found = 1
|
|
||||||
|
|
||||||
def determine_winnings(self):
|
|
||||||
total = self.coins_found * self.coin_value
|
|
||||||
total += self.gems_found * self.gem_value
|
|
||||||
total += self.emerald_found * self.gem_value * 3
|
|
||||||
return total
|
|
@ -1,12 +1,12 @@
|
|||||||
import inspect
|
|
||||||
import enum
|
import enum
|
||||||
|
import inspect
|
||||||
import itertools
|
import itertools
|
||||||
from types import FunctionType
|
from types import FunctionType
|
||||||
|
|
||||||
from houdini.converters import _listener, _ArgumentDeserializer, get_converter, \
|
from houdini import _AbstractManager, get_package_modules, plugins
|
||||||
do_conversion, _ConverterContext, ChecklistError
|
from houdini.converters import ChecklistError, _ArgumentDeserializer, _ConverterContext, _listener, do_conversion, \
|
||||||
from houdini.cooldown import _Cooldown, _CooldownMapping, BucketType, CooldownError
|
get_converter
|
||||||
from houdini import plugins, _AbstractManager, get_package_modules
|
from houdini.cooldown import BucketType, CooldownError, _Cooldown, _CooldownMapping
|
||||||
|
|
||||||
|
|
||||||
class AuthorityError(Exception):
|
class AuthorityError(Exception):
|
||||||
@ -258,3 +258,19 @@ def player_in_room(*room_ids):
|
|||||||
def check_room_id(_, p):
|
def check_room_id(_, p):
|
||||||
return p.room is not None and p.room.id in room_ids
|
return p.room is not None and p.room.id in room_ids
|
||||||
return check(check_room_id)
|
return check(check_room_id)
|
||||||
|
|
||||||
|
|
||||||
|
def table(*logic):
|
||||||
|
def check_table_game(_, p):
|
||||||
|
if p.table is not None and type(p.table.logic) in logic:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
return check(check_table_game)
|
||||||
|
|
||||||
|
|
||||||
|
def waddle(*waddle):
|
||||||
|
def check_waddle_game(_, p):
|
||||||
|
if p.waddle is not None and type(p.waddle) in waddle:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
return check(check_waddle_game)
|
||||||
|
@ -1,17 +1,16 @@
|
|||||||
from houdini import handlers
|
import random
|
||||||
from houdini.handlers import XTPacket
|
import time
|
||||||
from houdini.converters import OptionalConverter
|
|
||||||
from houdini.constants import ClientType
|
|
||||||
from houdini.handlers.play.navigation import handle_join_room
|
|
||||||
from houdini.handlers.play.moderation import cheat_ban
|
|
||||||
from houdini.data.room import Room
|
|
||||||
from houdini.data.game import PenguinGameData
|
|
||||||
|
|
||||||
from sqlalchemy.dialects.postgresql import insert
|
from sqlalchemy.dialects.postgresql import insert
|
||||||
|
|
||||||
import time
|
from houdini import handlers
|
||||||
import random
|
from houdini.constants import ClientType
|
||||||
|
from houdini.converters import OptionalConverter
|
||||||
|
from houdini.data.game import PenguinGameData
|
||||||
|
from houdini.data.room import Room
|
||||||
|
from houdini.handlers import XTPacket
|
||||||
|
from houdini.handlers.play.moderation import cheat_ban
|
||||||
|
from houdini.handlers.play.navigation import handle_join_room
|
||||||
|
|
||||||
default_score_games = {904, 905, 906, 912, 916, 917, 918, 919, 950, 952}
|
default_score_games = {904, 905, 906, 912, 916, 917, 918, 919, 950, 952}
|
||||||
|
|
||||||
|
@ -1,15 +1,14 @@
|
|||||||
from houdini import handlers
|
|
||||||
from houdini.handlers import XTPacket
|
|
||||||
from houdini.data.dance import DanceSongCollection
|
|
||||||
from houdini.penguin import Penguin
|
|
||||||
|
|
||||||
import random
|
|
||||||
import time
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import itertools
|
import itertools
|
||||||
|
import random
|
||||||
|
import time
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
from houdini import handlers
|
||||||
|
from houdini.data.dance import DanceSongCollection
|
||||||
|
from houdini.handlers import XTPacket
|
||||||
|
from houdini.penguin import Penguin
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Dancer:
|
class Dancer:
|
||||||
@ -56,6 +55,11 @@ class DanceFloor:
|
|||||||
self._dancers.pop(p.id)
|
self._dancers.pop(p.id)
|
||||||
await self.send_xt('zm', self.get_string())
|
await self.send_xt('zm', self.get_string())
|
||||||
|
|
||||||
|
async def start(self):
|
||||||
|
while True:
|
||||||
|
await self.next_round()
|
||||||
|
await asyncio.sleep(self._current_track.song_length_millis // 1000)
|
||||||
|
|
||||||
async def next_round(self):
|
async def next_round(self):
|
||||||
self._current_track = self._queued_track
|
self._current_track = self._queued_track
|
||||||
|
|
||||||
@ -84,9 +88,6 @@ class DanceFloor:
|
|||||||
self._queued_track = next(self._tracks)
|
self._queued_track = next(self._tracks)
|
||||||
self._next_song_timestamp = int(round(time.time() * 1000)) + self._current_track.song_length_millis
|
self._next_song_timestamp = int(round(time.time() * 1000)) + self._current_track.song_length_millis
|
||||||
|
|
||||||
await asyncio.sleep(self._current_track.song_length_millis // 1000)
|
|
||||||
await self.next_round()
|
|
||||||
|
|
||||||
async def send_xt(self, *data):
|
async def send_xt(self, *data):
|
||||||
for dancer in self._dancers.values():
|
for dancer in self._dancers.values():
|
||||||
await dancer.penguin.send_xt(*data)
|
await dancer.penguin.send_xt(*data)
|
||||||
@ -147,7 +148,7 @@ async def songs_load(server):
|
|||||||
server.logger.info(f'Loaded {len(server.dance_songs)} dance tracks')
|
server.logger.info(f'Loaded {len(server.dance_songs)} dance tracks')
|
||||||
|
|
||||||
server.dance_floor = DanceFloor(server)
|
server.dance_floor = DanceFloor(server)
|
||||||
asyncio.create_task(server.dance_floor.next_round())
|
asyncio.create_task(server.dance_floor.start())
|
||||||
|
|
||||||
|
|
||||||
@handlers.handler(XTPacket('gz', ext='z'))
|
@handlers.handler(XTPacket('gz', ext='z'))
|
||||||
|
@ -1,17 +1,59 @@
|
|||||||
from houdini import handlers
|
from houdini import ITable, handlers
|
||||||
from houdini.handlers import XTPacket
|
from houdini.handlers import XTPacket
|
||||||
from houdini.handlers.games.table import table_handler
|
|
||||||
from houdini.games.four import ConnectFourLogic
|
|
||||||
|
class ConnectFourLogic(ITable):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.current_player = 1
|
||||||
|
self.board = [[0 for _ in range(6)] for _ in range(7)]
|
||||||
|
|
||||||
|
def make_move(self, col, row):
|
||||||
|
self.board[col][row] = self.current_player
|
||||||
|
|
||||||
|
def is_valid_move(self, col, row):
|
||||||
|
if 0 <= row <= 5 and 0 <= col <= 6:
|
||||||
|
if row == 5 or (self.board[col][row] == 0 and self.board[col][row + 1]):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_string(self):
|
||||||
|
return ','.join(str(item) for row in self.board for item in row)
|
||||||
|
|
||||||
|
def is_position_win(self, col, row):
|
||||||
|
for delta_row, delta_col in [(1, 0), (0, 1), (1, 1), (1, -1)]:
|
||||||
|
streak = 1
|
||||||
|
for delta in (1, -1):
|
||||||
|
delta_row *= delta
|
||||||
|
delta_col *= delta
|
||||||
|
next_row = row + delta_row
|
||||||
|
next_col = col + delta_col
|
||||||
|
while 0 <= next_row < 6 and 0 <= next_col < 7:
|
||||||
|
if self.board[next_col][next_row] == self.current_player:
|
||||||
|
streak += 1
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
if streak == 4:
|
||||||
|
return True
|
||||||
|
next_row += delta_row
|
||||||
|
next_col += delta_col
|
||||||
|
return False
|
||||||
|
|
||||||
|
def is_board_full(self):
|
||||||
|
for col in self.board:
|
||||||
|
if not col[0]:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
@handlers.handler(XTPacket('gz', ext='z'))
|
@handlers.handler(XTPacket('gz', ext='z'))
|
||||||
@table_handler(ConnectFourLogic)
|
@handlers.table(ConnectFourLogic)
|
||||||
async def handle_get_game(p):
|
async def handle_get_game(p):
|
||||||
await p.send_xt('gz', p.table.get_string())
|
await p.send_xt('gz', p.table.get_string())
|
||||||
|
|
||||||
|
|
||||||
@handlers.handler(XTPacket('jz', ext='z'))
|
@handlers.handler(XTPacket('jz', ext='z'))
|
||||||
@table_handler(ConnectFourLogic)
|
@handlers.table(ConnectFourLogic)
|
||||||
async def handle_join_game(p):
|
async def handle_join_game(p):
|
||||||
game_full = len(p.table.penguins) > 2
|
game_full = len(p.table.penguins) > 2
|
||||||
if not game_full:
|
if not game_full:
|
||||||
@ -24,7 +66,7 @@ async def handle_join_game(p):
|
|||||||
|
|
||||||
|
|
||||||
@handlers.handler(XTPacket('zm', ext='z'))
|
@handlers.handler(XTPacket('zm', ext='z'))
|
||||||
@table_handler(ConnectFourLogic)
|
@handlers.table(ConnectFourLogic)
|
||||||
async def handle_send_move(p, col: int, row: int):
|
async def handle_send_move(p, col: int, row: int):
|
||||||
try:
|
try:
|
||||||
seat_id = p.table.get_seat_id(p)
|
seat_id = p.table.get_seat_id(p)
|
||||||
|
@ -1,17 +1,77 @@
|
|||||||
from houdini import handlers
|
from houdini import ITable, handlers
|
||||||
from houdini.handlers import XTPacket
|
from houdini.handlers import XTPacket
|
||||||
from houdini.handlers.games.table import table_handler
|
|
||||||
from houdini.games.mancala import MancalaLogic
|
|
||||||
|
class MancalaLogic(ITable):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.current_player = 1
|
||||||
|
self.board = [
|
||||||
|
4, 4, 4, 4, 4, 4, 0,
|
||||||
|
4, 4, 4, 4, 4, 4, 0
|
||||||
|
]
|
||||||
|
|
||||||
|
def make_move(self, hollow):
|
||||||
|
capture = False
|
||||||
|
hand = self.board[hollow]
|
||||||
|
self.board[hollow] = 0
|
||||||
|
|
||||||
|
while hand > 0:
|
||||||
|
hollow = (hollow + 1) % len(self.board)
|
||||||
|
my_mancala, opponent_mancala = (6, 13) if self.current_player == 1 else (13, 6)
|
||||||
|
|
||||||
|
if hollow == opponent_mancala:
|
||||||
|
continue
|
||||||
|
opposite_hollow = 12 - hollow
|
||||||
|
|
||||||
|
if hand == 1 and self.board[hollow] == 0:
|
||||||
|
if (self.current_player == 1 and hollow in range(0, 6)) or (self.current_player == 2 and hollow in range(7, 13)):
|
||||||
|
self.board[my_mancala] += self.board[opposite_hollow] + 1
|
||||||
|
self.board[opposite_hollow] = 0
|
||||||
|
capture = True
|
||||||
|
break
|
||||||
|
|
||||||
|
self.board[hollow] += 1
|
||||||
|
hand -= 1
|
||||||
|
|
||||||
|
if (self.current_player == 1 and hollow != 6) or (self.current_player == 2 and hollow != 13):
|
||||||
|
return 'c' if capture else str()
|
||||||
|
else:
|
||||||
|
self.current_player = 2 if self.current_player == 1 else 1
|
||||||
|
return 'f'
|
||||||
|
|
||||||
|
def is_valid_move(self, hollow):
|
||||||
|
if self.current_player == 1 and hollow not in range(0, 6):
|
||||||
|
return False
|
||||||
|
elif self.current_player == 2 and hollow not in range(7, 13):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def get_string(self):
|
||||||
|
return ','.join(map(str, self.board))
|
||||||
|
|
||||||
|
def is_position_win(self):
|
||||||
|
if sum(self.board[0:6]) == 0 or sum(self.board[7:-1]) == 0:
|
||||||
|
if sum(self.board[0:6]) > sum(self.board[7:-1]):
|
||||||
|
return self.current_player == 1
|
||||||
|
return self.current_player == 2
|
||||||
|
return False
|
||||||
|
|
||||||
|
def is_position_tie(self):
|
||||||
|
if sum(self.board[0:6]) == 0 or sum(self.board[7:-1]) == 0:
|
||||||
|
if sum(self.board[0:6]) == sum(self.board[7:-1]):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
@handlers.handler(XTPacket('gz', ext='z'))
|
@handlers.handler(XTPacket('gz', ext='z'))
|
||||||
@table_handler(MancalaLogic)
|
@handlers.table(MancalaLogic)
|
||||||
async def handle_get_game(p):
|
async def handle_get_game(p):
|
||||||
await p.send_xt('gz', p.table.get_string())
|
await p.send_xt('gz', p.table.get_string())
|
||||||
|
|
||||||
|
|
||||||
@handlers.handler(XTPacket('jz', ext='z'))
|
@handlers.handler(XTPacket('jz', ext='z'))
|
||||||
@table_handler(MancalaLogic)
|
@handlers.table(MancalaLogic)
|
||||||
async def handle_join_game(p):
|
async def handle_join_game(p):
|
||||||
game_full = len(p.table.penguins) > 2
|
game_full = len(p.table.penguins) > 2
|
||||||
if not game_full:
|
if not game_full:
|
||||||
@ -24,7 +84,7 @@ async def handle_join_game(p):
|
|||||||
|
|
||||||
|
|
||||||
@handlers.handler(XTPacket('zm', ext='z'))
|
@handlers.handler(XTPacket('zm', ext='z'))
|
||||||
@table_handler(MancalaLogic)
|
@handlers.table(MancalaLogic)
|
||||||
async def handle_send_move(p, hollow: int):
|
async def handle_send_move(p, hollow: int):
|
||||||
try:
|
try:
|
||||||
seat_id = p.table.get_seat_id(p)
|
seat_id = p.table.get_seat_id(p)
|
||||||
|
@ -0,0 +1,187 @@
|
|||||||
|
import asyncio
|
||||||
|
import operator
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
from houdini import handlers
|
||||||
|
from houdini.data.room import RoomWaddle
|
||||||
|
from houdini.handlers import XTPacket
|
||||||
|
from houdini.handlers.games.ninja.card import CardJitsuLogic
|
||||||
|
from houdini.handlers.games.ninja.fire import CardJitsuFireLogic
|
||||||
|
from houdini.handlers.games.ninja.water import CardJitsuWaterLogic
|
||||||
|
from houdini.penguin import Penguin
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class MatchMaker:
|
||||||
|
penguin: Penguin
|
||||||
|
tick: int
|
||||||
|
|
||||||
|
|
||||||
|
class MatchMaking:
|
||||||
|
SenseiRoom = 951
|
||||||
|
SenseiFireRoom = 953
|
||||||
|
SenseiWaterRoom = 954
|
||||||
|
|
||||||
|
def __init__(self, server, on_tick, on_matched, match_by, max_players=2, match_every=10):
|
||||||
|
self.server = server
|
||||||
|
self._on_tick = on_tick
|
||||||
|
self._on_matched = on_matched
|
||||||
|
|
||||||
|
self._match_by = match_by
|
||||||
|
self._max_players = max_players
|
||||||
|
self._match_every = match_every
|
||||||
|
|
||||||
|
self._penguins = []
|
||||||
|
self._matched_penguins = {}
|
||||||
|
|
||||||
|
async def start(self):
|
||||||
|
while True:
|
||||||
|
await self.tick()
|
||||||
|
await asyncio.sleep(1)
|
||||||
|
|
||||||
|
async def tick(self):
|
||||||
|
for i in range(0, len(self._penguins) - len(self._penguins) % 2, self._max_players):
|
||||||
|
matched = self._penguins[i:i+self._max_players]
|
||||||
|
if any(mm.tick == 0 for mm in matched):
|
||||||
|
matched_penguins = [mm.penguin for mm in matched]
|
||||||
|
self._matched_penguins.update({
|
||||||
|
mm.penguin.id: matched_penguins
|
||||||
|
for mm in matched})
|
||||||
|
self._penguins = [mm for mm in self._penguins if mm not in matched]
|
||||||
|
|
||||||
|
await self._on_matched(matched)
|
||||||
|
else:
|
||||||
|
await self._on_tick(matched)
|
||||||
|
for mm in matched:
|
||||||
|
mm.tick -= 1
|
||||||
|
|
||||||
|
def add_penguin(self, p):
|
||||||
|
mm = MatchMaker(penguin=p, tick=self._match_every)
|
||||||
|
self._penguins.append(mm)
|
||||||
|
self._penguins.sort(key=operator.attrgetter('penguin.' + self._match_by))
|
||||||
|
|
||||||
|
def remove_penguin(self, p):
|
||||||
|
self._penguins = [mm for mm in self._penguins if mm.penguin != p]
|
||||||
|
if p.id in self._matched_penguins:
|
||||||
|
matched = self._matched_penguins[p.id]
|
||||||
|
matched.remove(p)
|
||||||
|
|
||||||
|
del self._matched_penguins[p.id]
|
||||||
|
self._penguins.sort(key=operator.attrgetter('penguin.' + self._match_by))
|
||||||
|
|
||||||
|
def matched_with(self, p):
|
||||||
|
if p.id in self._matched_penguins:
|
||||||
|
return self._matched_penguins[p.id]
|
||||||
|
|
||||||
|
def has_matched(self, p):
|
||||||
|
return p.id in self._matched_penguins
|
||||||
|
|
||||||
|
|
||||||
|
async def card_tick(matched):
|
||||||
|
nicknames = [mm.penguin.safe_name for mm in matched]
|
||||||
|
for mm in matched:
|
||||||
|
await mm.penguin.send_xt('tmm', mm.tick, *nicknames)
|
||||||
|
|
||||||
|
|
||||||
|
async def card_color_tick(matched):
|
||||||
|
nicknames = [f'{mm.penguin.safe_name}|{mm.penguin.color}' for mm in matched]
|
||||||
|
for mm in matched:
|
||||||
|
await mm.penguin.send_xt('tmm', len(matched), mm.tick, *nicknames)
|
||||||
|
|
||||||
|
|
||||||
|
def card_match(waddle_room_id, waddle_game):
|
||||||
|
async def match(matched):
|
||||||
|
nicknames = [f'{mm.penguin.safe_name}|{mm.penguin.color}' for mm in matched]
|
||||||
|
host = matched[0].penguin
|
||||||
|
|
||||||
|
waddle_room = host.server.rooms[waddle_room_id]
|
||||||
|
rw = RoomWaddle(id=host.id, room_id=waddle_room.id, seats=len(matched), game=waddle_game, temporary=True)
|
||||||
|
waddle_room.waddles[rw.id] = rw
|
||||||
|
|
||||||
|
for mm in matched:
|
||||||
|
await mm.penguin.send_xt('scard', waddle_room.id, rw.id, len(matched), mm.tick, *nicknames)
|
||||||
|
return match
|
||||||
|
|
||||||
|
|
||||||
|
card_matched = card_match(CardJitsuLogic.room_id, 'card')
|
||||||
|
card_fire_matched = card_match(CardJitsuFireLogic.room_id, 'fire')
|
||||||
|
card_water_matched = card_match(CardJitsuWaterLogic.room_id, 'water')
|
||||||
|
|
||||||
|
|
||||||
|
@handlers.boot
|
||||||
|
async def match_load(server):
|
||||||
|
server.match_making = MatchMaking(server, card_tick, card_matched, match_by='ninja_rank')
|
||||||
|
server.fire_match_making = MatchMaking(server, card_color_tick, card_fire_matched,
|
||||||
|
match_by='fire_ninja_rank', max_players=4)
|
||||||
|
server.water_match_making = MatchMaking(server, card_color_tick, card_water_matched,
|
||||||
|
match_by='water_ninja_rank', max_players=4)
|
||||||
|
|
||||||
|
asyncio.create_task(server.match_making.start())
|
||||||
|
asyncio.create_task(server.fire_match_making.start())
|
||||||
|
asyncio.create_task(server.water_match_making.start())
|
||||||
|
|
||||||
|
|
||||||
|
@handlers.handler(XTPacket('jmm', ext='z'))
|
||||||
|
@handlers.player_in_room(MatchMaking.SenseiRoom)
|
||||||
|
async def handle_join_match_making(p):
|
||||||
|
p.server.match_making.add_penguin(p)
|
||||||
|
await p.send_xt('jmm', p.safe_name)
|
||||||
|
|
||||||
|
|
||||||
|
@handlers.handler(XTPacket('jmm', ext='z'))
|
||||||
|
@handlers.player_in_room(MatchMaking.SenseiFireRoom)
|
||||||
|
async def handle_join_fire_match_making(p):
|
||||||
|
p.server.fire_match_making.add_penguin(p)
|
||||||
|
await p.send_xt('jmm', p.safe_name)
|
||||||
|
|
||||||
|
|
||||||
|
@handlers.handler(XTPacket('jmm', ext='z'))
|
||||||
|
@handlers.player_in_room(MatchMaking.SenseiWaterRoom)
|
||||||
|
async def handle_join_water_match_making(p):
|
||||||
|
p.server.water_match_making.add_penguin(p)
|
||||||
|
await p.send_xt('jmm', p.safe_name)
|
||||||
|
|
||||||
|
|
||||||
|
@handlers.handler(XTPacket('jsen', ext='z'))
|
||||||
|
@handlers.player_in_room(MatchMaking.SenseiRoom)
|
||||||
|
async def handle_join_sensei_match(p):
|
||||||
|
waddle_room = p.server.rooms[CardJitsuLogic.__room_id__]
|
||||||
|
rw = RoomWaddle(id=p.id, room_id=waddle_room.id, seats=1, game='sensei', temporary=True)
|
||||||
|
waddle_room.waddles[rw.id] = rw
|
||||||
|
|
||||||
|
await p.send_xt('scard', waddle_room.id, rw.id, 1, 0, f'{p.safe_name}|{p.color}')
|
||||||
|
|
||||||
|
|
||||||
|
@handlers.handler(XTPacket('jsen', ext='z'))
|
||||||
|
@handlers.player_in_room(MatchMaking.SenseiFireRoom)
|
||||||
|
async def handle_join_fire_sensei_match(p):
|
||||||
|
waddle_room = p.server.rooms[CardJitsuFireLogic.__room_id__]
|
||||||
|
rw = RoomWaddle(id=p.id, room_id=waddle_room.id, seats=1, game='firesensei', temporary=True)
|
||||||
|
waddle_room.waddles[rw.id] = rw
|
||||||
|
|
||||||
|
await p.send_xt('scard', waddle_room.id, rw.id, 1, 0, f'{p.safe_name}|{p.color}')
|
||||||
|
|
||||||
|
|
||||||
|
@handlers.handler(XTPacket('jsen', ext='z'))
|
||||||
|
@handlers.player_in_room(MatchMaking.SenseiWaterRoom)
|
||||||
|
async def handle_join_water_sensei_match(p):
|
||||||
|
waddle_room = p.server.rooms[CardJitsuWaterLogic.__room_id__]
|
||||||
|
rw = RoomWaddle(id=p.id, room_id=waddle_room.id, seats=1, game='watersensei', temporary=True)
|
||||||
|
waddle_room.waddles[rw.id] = rw
|
||||||
|
|
||||||
|
await p.send_xt('scard', waddle_room.id, rw.id, 1, 0, f'{p.safe_name}|{p.color}')
|
||||||
|
|
||||||
|
|
||||||
|
@handlers.handler(XTPacket('lmm', ext='z'))
|
||||||
|
async def handle_leave_match_making(p):
|
||||||
|
p.server.match_making.remove_penguin(p)
|
||||||
|
p.server.water_match_making.remove_penguin(p)
|
||||||
|
p.server.fire_match_making.remove_penguin(p)
|
||||||
|
|
||||||
|
|
||||||
|
@handlers.disconnected
|
||||||
|
@handlers.player_attribute(joined_world=True)
|
||||||
|
async def handle_disconnect_match_making(p):
|
||||||
|
p.server.match_making.remove_penguin(p)
|
||||||
|
p.server.water_match_making.remove_penguin(p)
|
||||||
|
p.server.fire_match_making.remove_penguin(p)
|
@ -0,0 +1,201 @@
|
|||||||
|
import itertools
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from typing import Dict, List, Union
|
||||||
|
|
||||||
|
from houdini import IWaddle
|
||||||
|
from houdini.data.ninja import Card
|
||||||
|
from houdini.penguin import Penguin
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Played:
|
||||||
|
id: int
|
||||||
|
card: Card
|
||||||
|
player: int
|
||||||
|
opponent: int
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Ninja:
|
||||||
|
penguin: Penguin
|
||||||
|
deck: Dict[int, Card]
|
||||||
|
bank: Dict[str, List[Played]]
|
||||||
|
chosen: Union[Played, None]
|
||||||
|
|
||||||
|
|
||||||
|
class CardJitsuLogic(IWaddle):
|
||||||
|
room_id = 998
|
||||||
|
rule_set = {'f': 's', 'w': 'f', 's': 'w'}
|
||||||
|
discard_elements = {4: 's', 5: 'w', 6: 'f'}
|
||||||
|
discard_colors = {7: 'r', 8: 'b', 9: 'g', 10: 'y', 11: 'o', 12: 'p'}
|
||||||
|
replacements = {16: ['w', 'f'], 17: ['s', 'w'], 18: ['f', 's']}
|
||||||
|
rank_speed = 1
|
||||||
|
|
||||||
|
def __init__(self, waddle):
|
||||||
|
super().__init__(waddle)
|
||||||
|
|
||||||
|
self.ninjas = [
|
||||||
|
Ninja(
|
||||||
|
penguin=p,
|
||||||
|
deck={},
|
||||||
|
bank={'f': [], 'w': [], 's': []},
|
||||||
|
chosen=None
|
||||||
|
) for p in waddle.penguins]
|
||||||
|
|
||||||
|
self.card_id = 1
|
||||||
|
self.powers = {}
|
||||||
|
self.discards = []
|
||||||
|
|
||||||
|
def get_winning_cards(self, seat_id):
|
||||||
|
player_cards = self.ninjas[seat_id].bank
|
||||||
|
for element, cards in player_cards.items():
|
||||||
|
color_cards, colors = [], []
|
||||||
|
for card in cards:
|
||||||
|
if card.card.color not in colors:
|
||||||
|
color_cards.append(card)
|
||||||
|
colors.append(card.card.color)
|
||||||
|
if len(color_cards) == 3:
|
||||||
|
return color_cards, 0
|
||||||
|
elements = player_cards.values()
|
||||||
|
for combo in itertools.product(*elements):
|
||||||
|
colors = {card.card.color for card in combo}
|
||||||
|
if len(colors) == 3:
|
||||||
|
return combo, 1
|
||||||
|
return False, -1
|
||||||
|
|
||||||
|
def has_cards_to_play(self, seat_id):
|
||||||
|
power_limiters = {13: 's', 14: 'f', 15: 'w'}
|
||||||
|
for power_id, element in power_limiters.items():
|
||||||
|
if power_id in self.powers:
|
||||||
|
power_card = self.powers[power_id]
|
||||||
|
if power_card.opponent == seat_id:
|
||||||
|
opponent_deck = self.ninjas[power_card.opponent].deck
|
||||||
|
for card_id, card in opponent_deck.items():
|
||||||
|
if card.element != element:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def discard_opponent_card(self, power_id, opponent_seat_id):
|
||||||
|
opponent_cards = self.ninjas[opponent_seat_id].bank
|
||||||
|
if power_id in self.discard_elements:
|
||||||
|
element_to_discard = self.discard_elements[power_id]
|
||||||
|
if len(opponent_cards[element_to_discard]) > 0:
|
||||||
|
card_to_discard = self.ninjas[opponent_seat_id].bank[element_to_discard][-1]
|
||||||
|
self.discards.append(card_to_discard.id)
|
||||||
|
del self.ninjas[opponent_seat_id].bank[element_to_discard][-1]
|
||||||
|
return True
|
||||||
|
if power_id in self.discard_colors:
|
||||||
|
color_to_discard = self.discard_colors[power_id]
|
||||||
|
for element, cards in opponent_cards.items():
|
||||||
|
for index, card in enumerate(cards):
|
||||||
|
if card.card.color == color_to_discard:
|
||||||
|
card_to_discard = self.ninjas[opponent_seat_id].bank[element][index]
|
||||||
|
self.discards.append(card_to_discard.id)
|
||||||
|
del self.ninjas[opponent_seat_id].bank[element][index]
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def adjust_card_values(self, first_card, second_card):
|
||||||
|
for power_id, power_card in self.powers.items():
|
||||||
|
if power_card.card.power_id == 1 and first_card.card.element == second_card.card.element:
|
||||||
|
first_card.card.value = 1
|
||||||
|
second_card.card.value = 1
|
||||||
|
if power_card.card.power_id == 2:
|
||||||
|
if power_card.player == 0:
|
||||||
|
first_card.card.value += 2
|
||||||
|
else:
|
||||||
|
second_card.card.value += 2
|
||||||
|
if power_card.card.power_id == 3:
|
||||||
|
if power_card.player == 0:
|
||||||
|
second_card.card.value -= 2
|
||||||
|
else:
|
||||||
|
first_card.card.value -= 2
|
||||||
|
|
||||||
|
def get_round_winner(self):
|
||||||
|
first_card, second_card = self.ninjas[0].chosen, self.ninjas[1].chosen
|
||||||
|
winner_seat_id = self.get_winner_seat_id(first_card, second_card)
|
||||||
|
self.adjust_card_values(first_card, second_card)
|
||||||
|
|
||||||
|
for ninja_seat_id, ninja in enumerate(self.ninjas):
|
||||||
|
played_card = ninja.chosen
|
||||||
|
power_id = played_card.card.power_id
|
||||||
|
if not power_id:
|
||||||
|
continue
|
||||||
|
|
||||||
|
opponent_seat_id = 1 if ninja_seat_id == 0 else 0
|
||||||
|
|
||||||
|
on_played = power_id in {1, 16, 17, 18}
|
||||||
|
on_scored = not on_played
|
||||||
|
current_round = power_id in {4, 5, 6, 7, 8, 9, 10, 11, 12, 16, 17, 18}
|
||||||
|
next_round = not current_round
|
||||||
|
|
||||||
|
if on_played and next_round:
|
||||||
|
self.powers[power_id] = played_card
|
||||||
|
if on_scored and ninja_seat_id == winner_seat_id:
|
||||||
|
if next_round:
|
||||||
|
self.powers[power_id] = played_card
|
||||||
|
if current_round:
|
||||||
|
self.discard_opponent_card(power_id, opponent_seat_id)
|
||||||
|
if on_played and current_round:
|
||||||
|
self.replace_opponent_card(power_id, first_card, second_card, played_card.player)
|
||||||
|
winner_seat_id = self.get_winner_seat_id(first_card, second_card)
|
||||||
|
|
||||||
|
self.ninjas[0].chosen = None
|
||||||
|
self.ninjas[1].chosen = None
|
||||||
|
return winner_seat_id
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def replace_opponent_card(cls, power_id, first_card, second_card, seat_id):
|
||||||
|
for replace_power_id, replacement in cls.replacements.items():
|
||||||
|
if power_id == replace_power_id:
|
||||||
|
original, replace = replacement
|
||||||
|
if seat_id == 1 and first_card.card.element == original:
|
||||||
|
first_card.card.element = replace
|
||||||
|
if seat_id == 0 and second_card.card.element == original:
|
||||||
|
second_card.card.element = replace
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_winner_seat_id(cls, first_card, second_card):
|
||||||
|
if first_card.card.element != second_card.card.element:
|
||||||
|
return 0 if cls.rule_set[first_card.card.element] == second_card.card.element else 1
|
||||||
|
elif first_card.card.value > second_card.card.value:
|
||||||
|
return 0
|
||||||
|
elif second_card.card.value > first_card.card.value:
|
||||||
|
return 1
|
||||||
|
return -1
|
||||||
|
|
||||||
|
|
||||||
|
class CardJitsuMatLogic(CardJitsuLogic):
|
||||||
|
rank_speed = 0.5
|
||||||
|
|
||||||
|
|
||||||
|
class SenseiLogic(CardJitsuLogic):
|
||||||
|
|
||||||
|
def __init__(self, waddle):
|
||||||
|
super().__init__(waddle)
|
||||||
|
|
||||||
|
self.ninja = Ninja(
|
||||||
|
penguin=waddle.penguins[0],
|
||||||
|
deck={},
|
||||||
|
bank={'f': [], 'w': [], 's': []},
|
||||||
|
chosen=None
|
||||||
|
)
|
||||||
|
|
||||||
|
self.sensei_move = {}
|
||||||
|
self.colors = []
|
||||||
|
|
||||||
|
def get_win_card(self, card):
|
||||||
|
self.colors = [] if len(self.colors) >= 6 else self.colors
|
||||||
|
for card_check in self.ninja.penguin.server.cards.values():
|
||||||
|
if self.beats_card(card_check, card) and card_check.color not in self.colors:
|
||||||
|
self.colors.append(card_check.color)
|
||||||
|
return card_check
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def beats_card(cls, card_check, card_play):
|
||||||
|
if card_check.card.element != card_play.card.element:
|
||||||
|
return True if cls.rule_set[card_check.card.element] == card_play.card.element else False
|
||||||
|
elif card_check.card.value > card_play.card.value:
|
||||||
|
return True
|
||||||
|
return False
|
@ -0,0 +1,15 @@
|
|||||||
|
from houdini import IWaddle
|
||||||
|
|
||||||
|
|
||||||
|
class CardJitsuFireLogic(IWaddle):
|
||||||
|
|
||||||
|
room_id = 997
|
||||||
|
|
||||||
|
def __init__(self, waddle):
|
||||||
|
super().__init__(waddle)
|
||||||
|
|
||||||
|
|
||||||
|
class FireSenseiLogic(CardJitsuFireLogic):
|
||||||
|
|
||||||
|
def __init__(self, waddle):
|
||||||
|
super().__init__(waddle)
|
@ -0,0 +1,15 @@
|
|||||||
|
from houdini import IWaddle
|
||||||
|
|
||||||
|
|
||||||
|
class CardJitsuWaterLogic(IWaddle):
|
||||||
|
|
||||||
|
room_id = 995
|
||||||
|
|
||||||
|
def __init__(self, waddle):
|
||||||
|
super().__init__(waddle)
|
||||||
|
|
||||||
|
|
||||||
|
class WaterSenseiLogic(CardJitsuWaterLogic):
|
||||||
|
|
||||||
|
def __init__(self, waddle):
|
||||||
|
super().__init__(waddle)
|
@ -1,24 +1,40 @@
|
|||||||
from houdini import handlers
|
from houdini import IWaddle, handlers
|
||||||
from houdini.handlers import XTPacket
|
from houdini.handlers import XTPacket
|
||||||
from houdini.handlers.games.waddle import waddle_handler
|
|
||||||
from houdini.games.sled import SledRacingLogic
|
|
||||||
|
class SledRacingLogic(IWaddle):
|
||||||
|
|
||||||
|
room_id = 999
|
||||||
|
|
||||||
|
def __init__(self, waddle):
|
||||||
|
super().__init__(waddle)
|
||||||
|
|
||||||
|
self.payouts = [20, 10, 5, 5]
|
||||||
|
|
||||||
|
async def remove_penguin(self, p):
|
||||||
|
await super().remove_penguin(p)
|
||||||
|
await self.send_xt('uz', self.seats, *(f'{penguin.safe_name}|{penguin.color}|'
|
||||||
|
f'{penguin.hand}|{penguin.safe_name}' for penguin in self.penguins))
|
||||||
|
|
||||||
|
def get_payout(self):
|
||||||
|
return self.payouts.pop(0)
|
||||||
|
|
||||||
|
|
||||||
@handlers.handler(XTPacket('jz', ext='z'))
|
@handlers.handler(XTPacket('jz', ext='z'))
|
||||||
@waddle_handler(SledRacingLogic)
|
@handlers.waddle(SledRacingLogic)
|
||||||
async def handle_join_game(p):
|
async def handle_join_game(p):
|
||||||
await p.send_xt('uz', p.waddle.seats, *(f'{penguin.safe_name}|{penguin.color}|'
|
await p.send_xt('uz', p.waddle.seats, *(f'{penguin.safe_name}|{penguin.color}|'
|
||||||
f'{penguin.hand or 0}|{penguin.nickname}' for penguin in p.waddle.penguins))
|
f'{penguin.hand or 0}|{penguin.nickname}' for penguin in p.waddle.penguins))
|
||||||
|
|
||||||
|
|
||||||
@handlers.handler(XTPacket('zm', ext='z'))
|
@handlers.handler(XTPacket('zm', ext='z'))
|
||||||
@waddle_handler(SledRacingLogic)
|
@handlers.waddle(SledRacingLogic)
|
||||||
async def handle_send_move(p, player_id: int, x: float, y: float, time: float):
|
async def handle_send_move(p, player_id: int, x: float, y: float, time: float):
|
||||||
await p.waddle.send_xt('zm', player_id, x, y, time)
|
await p.waddle.send_xt('zm', player_id, x, y, time)
|
||||||
|
|
||||||
|
|
||||||
@handlers.handler(XTPacket('zo', ext='z'))
|
@handlers.handler(XTPacket('zo', ext='z'))
|
||||||
@waddle_handler(SledRacingLogic)
|
@handlers.waddle(SledRacingLogic)
|
||||||
async def handle_game_over(p):
|
async def handle_game_over(p):
|
||||||
coins = p.waddle.get_payout()
|
coins = p.waddle.get_payout()
|
||||||
await p.add_coins(coins)
|
await p.add_coins(coins)
|
||||||
|
@ -1,14 +1,6 @@
|
|||||||
from houdini import handlers
|
from houdini import handlers
|
||||||
from houdini.handlers import XTPacket, check
|
from houdini.handlers import XTPacket
|
||||||
from houdini.handlers.play.navigation import handle_join_room, handle_join_player_room
|
from houdini.handlers.play.navigation import handle_join_player_room, handle_join_room
|
||||||
|
|
||||||
|
|
||||||
def table_handler(logic):
|
|
||||||
def check_table_game(_, p):
|
|
||||||
if p.table is not None and type(p.table.logic) == logic:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
return check(check_table_game)
|
|
||||||
|
|
||||||
|
|
||||||
@handlers.handler(XTPacket('a', 'gt'))
|
@handlers.handler(XTPacket('a', 'gt'))
|
||||||
|
@ -1,11 +1,137 @@
|
|||||||
from houdini import handlers
|
import random
|
||||||
|
|
||||||
|
from houdini import ITable, handlers
|
||||||
from houdini.handlers import XTPacket
|
from houdini.handlers import XTPacket
|
||||||
from houdini.handlers.games.table import table_handler
|
|
||||||
from houdini.games.treasure import TreasureHuntLogic
|
|
||||||
|
class TreasureHuntLogic(ITable):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.map_width = 10
|
||||||
|
self.map_height = 10
|
||||||
|
self.coins_hidden = 0
|
||||||
|
self.gems_hidden = 0
|
||||||
|
self.turns = 12
|
||||||
|
self.gem_value = 25
|
||||||
|
self.coin_value = 1
|
||||||
|
self.gem_locations = []
|
||||||
|
self.treasure_map = []
|
||||||
|
self.coins_found = 0
|
||||||
|
self.gems_found = 0
|
||||||
|
self.emerald_found = 0
|
||||||
|
self.dig_record_names = []
|
||||||
|
self.dig_record_directions = []
|
||||||
|
self.dig_record_numbers = []
|
||||||
|
self.emerald = 0
|
||||||
|
self.current_player = 1
|
||||||
|
self.generate_map()
|
||||||
|
|
||||||
|
def make_move(self, movie, direction, spade):
|
||||||
|
if direction == 'right':
|
||||||
|
row = self.treasure_map[spade]
|
||||||
|
for column, tiles in enumerate(row):
|
||||||
|
self.dig(spade, column)
|
||||||
|
elif direction == 'down':
|
||||||
|
for row, columns in enumerate(self.treasure_map):
|
||||||
|
self.dig(row, spade)
|
||||||
|
self.turns -= 1
|
||||||
|
self.dig_record_names.append(movie)
|
||||||
|
self.dig_record_directions.append(direction)
|
||||||
|
self.dig_record_numbers.append(spade)
|
||||||
|
|
||||||
|
def is_valid_move(self, movie, direction, spade):
|
||||||
|
test_movie = direction + 'button' + str(spade) + '_mc'
|
||||||
|
if test_movie == movie and direction in ['down', 'right'] and 0 <= spade <= 9:
|
||||||
|
if direction == 'right':
|
||||||
|
row = self.treasure_map[spade]
|
||||||
|
for column, tiles in enumerate(row):
|
||||||
|
treasure, digs = self.treasure_map[spade][column]
|
||||||
|
if digs == 2:
|
||||||
|
return False
|
||||||
|
elif direction == 'down':
|
||||||
|
for row, columns in enumerate(self.treasure_map):
|
||||||
|
treasure, digs = self.treasure_map[row][spade]
|
||||||
|
if digs == 2:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_string(self):
|
||||||
|
treasure_map = ','.join(str(item) for row in self.treasure_map for item, digs in row)
|
||||||
|
gem_locations = ','.join(self.gem_locations)
|
||||||
|
game_array = [self.map_width, self.map_height, self.coins_hidden, self.gems_hidden, self.turns,
|
||||||
|
self.gem_value, self.coin_value, gem_locations, treasure_map]
|
||||||
|
if self.dig_record_numbers:
|
||||||
|
game_array += [self.coins_found, self.gems_found, self.emerald_found]
|
||||||
|
game_array += [','.join(self.dig_record_names), ','.join(self.dig_record_directions),
|
||||||
|
','.join(map(str, self.dig_record_numbers))]
|
||||||
|
return '%'.join(map(str, game_array))
|
||||||
|
|
||||||
|
def generate_map(self):
|
||||||
|
for row in range(self.map_height):
|
||||||
|
self.treasure_map.append([])
|
||||||
|
for column in range(self.map_width):
|
||||||
|
self.treasure_map[row].append([self.generate_treasure(row, column), 0])
|
||||||
|
|
||||||
|
def generate_treasure(self, row, column):
|
||||||
|
treasure_type = [('None', 0), ('Coin', 1), ('Gem', 2), ('Emerald', 4)]
|
||||||
|
if self.get_gem_by_piece(row, column):
|
||||||
|
return 3
|
||||||
|
if row + 1 == self.map_height or column + 1 == self.map_width:
|
||||||
|
treasure_type = treasure_type[:2]
|
||||||
|
name, value = random.choices(treasure_type, weights=[60, 40, 1, 0.5][:len(treasure_type)])[0]
|
||||||
|
self.coins_hidden += 1 if value == 1 else self.coins_hidden
|
||||||
|
if value > 1:
|
||||||
|
self.gems_hidden += 1
|
||||||
|
self.gem_locations.append(str(row) + ',' + str(column))
|
||||||
|
if self.emerald:
|
||||||
|
return 2
|
||||||
|
if value == 4 and not self.emerald:
|
||||||
|
self.emerald = 1
|
||||||
|
return value
|
||||||
|
|
||||||
|
def get_gem_by_piece(self, row, column):
|
||||||
|
for delta_row, delta_col in [(0, -1), (-1, -1), (-1, 0)]:
|
||||||
|
if row > 0 and column > 0:
|
||||||
|
treasure, digs = self.treasure_map[row + delta_row][column + delta_col]
|
||||||
|
if treasure == 2 or treasure == 4:
|
||||||
|
return row + delta_row, column + delta_col
|
||||||
|
return False
|
||||||
|
|
||||||
|
def is_gem_uncovered(self, row, column):
|
||||||
|
for delta_row, delta_col in [(0, 1), (1, 1), (1, 0)]:
|
||||||
|
treasure, digs = self.treasure_map[row + delta_row][column + delta_col]
|
||||||
|
if digs != 2:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def dig(self, row, column):
|
||||||
|
self.treasure_map[row][column][1] += 1
|
||||||
|
treasure, digs = self.treasure_map[row][column]
|
||||||
|
if digs == 2:
|
||||||
|
if treasure == 1:
|
||||||
|
self.coins_found += 1
|
||||||
|
elif treasure == 2 or treasure == 4:
|
||||||
|
if not self.is_gem_uncovered(row, column):
|
||||||
|
return
|
||||||
|
self.gems_found += 1
|
||||||
|
elif treasure == 3:
|
||||||
|
treasure_row, treasure_col = self.get_gem_by_piece(row, column)
|
||||||
|
if not self.is_gem_uncovered(treasure_row, treasure_col):
|
||||||
|
return
|
||||||
|
self.gems_found += 1
|
||||||
|
if treasure == 4:
|
||||||
|
self.emerald_found = 1
|
||||||
|
|
||||||
|
def determine_winnings(self):
|
||||||
|
total = self.coins_found * self.coin_value
|
||||||
|
total += self.gems_found * self.gem_value
|
||||||
|
total += self.emerald_found * self.gem_value * 3
|
||||||
|
return total
|
||||||
|
|
||||||
|
|
||||||
@handlers.handler(XTPacket('gz', ext='z'))
|
@handlers.handler(XTPacket('gz', ext='z'))
|
||||||
@table_handler(TreasureHuntLogic)
|
@handlers.table(TreasureHuntLogic)
|
||||||
async def handle_get_game(p):
|
async def handle_get_game(p):
|
||||||
if len(p.table.penguins) == 2:
|
if len(p.table.penguins) == 2:
|
||||||
player_one = p.table.penguins[0]
|
player_one = p.table.penguins[0]
|
||||||
@ -15,7 +141,7 @@ async def handle_get_game(p):
|
|||||||
|
|
||||||
|
|
||||||
@handlers.handler(XTPacket('jz', ext='z'))
|
@handlers.handler(XTPacket('jz', ext='z'))
|
||||||
@table_handler(TreasureHuntLogic)
|
@handlers.table(TreasureHuntLogic)
|
||||||
async def handle_join_game(p):
|
async def handle_join_game(p):
|
||||||
game_full = len(p.table.penguins) > 2
|
game_full = len(p.table.penguins) > 2
|
||||||
if not game_full:
|
if not game_full:
|
||||||
@ -27,7 +153,7 @@ async def handle_join_game(p):
|
|||||||
|
|
||||||
|
|
||||||
@handlers.handler(XTPacket('zm', ext='z'))
|
@handlers.handler(XTPacket('zm', ext='z'))
|
||||||
@table_handler(TreasureHuntLogic)
|
@handlers.table(TreasureHuntLogic)
|
||||||
async def handle_send_move(p, movie: str, direction: str, spade: int):
|
async def handle_send_move(p, movie: str, direction: str, spade: int):
|
||||||
try:
|
try:
|
||||||
seat_id = p.table.get_seat_id(p)
|
seat_id = p.table.get_seat_id(p)
|
||||||
|
@ -1,14 +1,7 @@
|
|||||||
from houdini import handlers
|
from houdini import handlers
|
||||||
from houdini.handlers import XTPacket, check
|
from houdini.data.room import Room
|
||||||
from houdini.handlers.play.navigation import handle_join_room, handle_join_player_room
|
from houdini.handlers import XTPacket
|
||||||
|
from houdini.handlers.play.navigation import handle_join_player_room, handle_join_room
|
||||||
|
|
||||||
def waddle_handler(waddle):
|
|
||||||
def check_waddle_game(_, p):
|
|
||||||
if p.waddle is not None and type(p.waddle) == waddle:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
return check(check_waddle_game)
|
|
||||||
|
|
||||||
|
|
||||||
@handlers.handler(XTPacket('gw', ext='z'))
|
@handlers.handler(XTPacket('gw', ext='z'))
|
||||||
@ -32,6 +25,11 @@ async def handle_leave_waddle(p):
|
|||||||
await p.waddle.remove_penguin(p)
|
await p.waddle.remove_penguin(p)
|
||||||
|
|
||||||
|
|
||||||
|
@handlers.handler(XTPacket('w', 'jx'))
|
||||||
|
async def handle_start_waddle(p, room: Room, waddle: int):
|
||||||
|
await room.waddles[waddle].add_penguin(p)
|
||||||
|
|
||||||
|
|
||||||
@handlers.handler(XTPacket('j', 'jr'), after=handle_join_room)
|
@handlers.handler(XTPacket('j', 'jr'), after=handle_join_room)
|
||||||
async def handle_join_room_waddle(p):
|
async def handle_join_room_waddle(p):
|
||||||
if p.waddle:
|
if p.waddle:
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
from houdini import handlers
|
from houdini import handlers
|
||||||
from houdini.handlers import XMLPacket
|
|
||||||
from houdini.converters import VersionChkConverter
|
|
||||||
from houdini.constants import ClientType
|
from houdini.constants import ClientType
|
||||||
|
from houdini.converters import VersionChkConverter
|
||||||
from houdini.data.buddy import BuddyList
|
from houdini.data.buddy import BuddyList
|
||||||
|
from houdini.handlers import XMLPacket
|
||||||
|
|
||||||
|
|
||||||
@handlers.handler(XMLPacket('verChk'))
|
@handlers.handler(XMLPacket('verChk'))
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
|
import asyncio
|
||||||
|
import os
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
|
import bcrypt
|
||||||
|
|
||||||
from houdini import handlers
|
from houdini import handlers
|
||||||
|
from houdini.constants import ClientType
|
||||||
|
from houdini.converters import Credentials
|
||||||
|
from houdini.crypto import Crypto
|
||||||
|
from houdini.data.moderator import Ban
|
||||||
|
from houdini.data.penguin import Penguin
|
||||||
from houdini.handlers import XMLPacket
|
from houdini.handlers import XMLPacket
|
||||||
from houdini.handlers.login import get_server_presence
|
from houdini.handlers.login import get_server_presence
|
||||||
from houdini.handlers.play.navigation import get_minutes_played_today
|
from houdini.handlers.play.navigation import get_minutes_played_today
|
||||||
from houdini.converters import Credentials
|
|
||||||
from houdini.data.penguin import Penguin
|
|
||||||
from houdini.data.moderator import Ban
|
|
||||||
from houdini.crypto import Crypto
|
|
||||||
from houdini.constants import ClientType
|
|
||||||
|
|
||||||
import asyncio
|
|
||||||
import bcrypt
|
|
||||||
import os
|
|
||||||
|
|
||||||
from datetime import datetime, timedelta
|
|
||||||
|
|
||||||
|
|
||||||
@handlers.handler(XMLPacket('login'))
|
@handlers.handler(XMLPacket('login'))
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
from houdini import handlers
|
|
||||||
from houdini.handlers import XMLPacket, login
|
|
||||||
from houdini.converters import WorldCredentials, Credentials
|
|
||||||
from houdini.data.penguin import Penguin
|
|
||||||
from houdini.data.moderator import Ban
|
|
||||||
from houdini.crypto import Crypto
|
|
||||||
from houdini.constants import ClientType
|
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
|
from houdini import handlers
|
||||||
|
from houdini.constants import ClientType
|
||||||
|
from houdini.converters import Credentials, WorldCredentials
|
||||||
|
from houdini.crypto import Crypto
|
||||||
|
from houdini.data.moderator import Ban
|
||||||
|
from houdini.data.penguin import Penguin
|
||||||
|
from houdini.handlers import XMLPacket, login
|
||||||
|
|
||||||
handle_version_check = login.handle_version_check
|
handle_version_check = login.handle_version_check
|
||||||
handle_random_key = login.handle_random_key
|
handle_random_key = login.handle_random_key
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
from houdini import handlers
|
from houdini import handlers
|
||||||
from houdini.handlers import XTPacket
|
|
||||||
from houdini.constants import ClientType
|
from houdini.constants import ClientType
|
||||||
|
from houdini.handlers import XTPacket
|
||||||
|
|
||||||
|
|
||||||
@handlers.handler(XTPacket('pt', 'spts'), client=ClientType.Vanilla)
|
@handlers.handler(XTPacket('pt', 'spts'), client=ClientType.Vanilla)
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
from houdini import handlers
|
from houdini import handlers
|
||||||
from houdini.handlers import XMLPacket, XTPacket
|
|
||||||
from houdini.handlers.play.navigation import handle_join_room
|
|
||||||
from houdini.handlers import Priority
|
|
||||||
|
|
||||||
from houdini.data.penguin import Penguin
|
|
||||||
from houdini.data.buddy import BuddyList, BuddyRequest, BuddyListCollection, \
|
|
||||||
BuddyRequestCollection, CharacterBuddyCollection, CharacterCollection
|
|
||||||
from houdini.constants import ClientType
|
from houdini.constants import ClientType
|
||||||
|
from houdini.data.buddy import BuddyList, BuddyListCollection, BuddyRequest, BuddyRequestCollection, \
|
||||||
|
CharacterBuddyCollection, CharacterCollection
|
||||||
|
from houdini.data.penguin import Penguin
|
||||||
|
from houdini.handlers import Priority, XMLPacket, XTPacket
|
||||||
|
from houdini.handlers.play.navigation import handle_join_room
|
||||||
|
|
||||||
|
|
||||||
async def update_player_presence(p):
|
async def update_player_presence(p):
|
||||||
|
52
houdini/handlers/play/card.py
Normal file
52
houdini/handlers/play/card.py
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import random
|
||||||
|
|
||||||
|
from houdini import handlers
|
||||||
|
from houdini.data.ninja import CardCollection, CardStarterDeck, PenguinCardCollection
|
||||||
|
from houdini.handlers import Priority, XMLPacket, XTPacket
|
||||||
|
|
||||||
|
|
||||||
|
@handlers.boot
|
||||||
|
async def cards_load(server):
|
||||||
|
server.cards = await CardCollection.get_collection()
|
||||||
|
server.logger.info(f'Loaded {len(server.cards)} ninja cards')
|
||||||
|
|
||||||
|
starter_deck_cards = await CardStarterDeck.query.gino.all()
|
||||||
|
server.cards.set_starter_decks(starter_deck_cards)
|
||||||
|
server.logger.info(f'Loaded {len(server.cards.starter_decks)} starter decks')
|
||||||
|
|
||||||
|
|
||||||
|
@handlers.handler(XMLPacket('login'), priority=Priority.Low)
|
||||||
|
@handlers.allow_once
|
||||||
|
async def load_card_inventory(p):
|
||||||
|
p.cards = await PenguinCardCollection.get_collection(p.id)
|
||||||
|
|
||||||
|
|
||||||
|
@handlers.handler(XTPacket('i', 'ai'))
|
||||||
|
async def handle_buy_starter_deck(p, deck_id: int):
|
||||||
|
if deck_id in p.server.cards.starter_decks:
|
||||||
|
starter_deck = p.server.cards.starter_decks[deck_id]
|
||||||
|
power_cards = [card for card, qty in starter_deck if card.power_id > 0]
|
||||||
|
for card, qty in starter_deck:
|
||||||
|
if card.power_id == 0:
|
||||||
|
await p.add_card(card, quantity=qty)
|
||||||
|
power_card = random.choice(power_cards)
|
||||||
|
await p.add_card(power_card, quantity=1)
|
||||||
|
|
||||||
|
|
||||||
|
@handlers.handler(XTPacket('cd', 'gcd'))
|
||||||
|
async def handle_get_card_data(p):
|
||||||
|
await p.send_xt('gcd', '|'.join(f'{card.card_id},{card.quantity},{card.member_quantity}'
|
||||||
|
for card in p.cards.values()))
|
||||||
|
|
||||||
|
|
||||||
|
@handlers.handler(XTPacket('cd', 'bpc'))
|
||||||
|
async def handle_buy_power_cards(p):
|
||||||
|
if p.coins >= 1500:
|
||||||
|
power_cards = random.sample(p.server.cards.power_cards, 3)
|
||||||
|
for card in power_cards:
|
||||||
|
await p.add_card(card, member_quantity=1)
|
||||||
|
|
||||||
|
await p.update(coins=p.coins - 1500).apply()
|
||||||
|
await p.send_xt('bpc', ','.join([str(card.id) for card in power_cards]), p.coins)
|
||||||
|
else:
|
||||||
|
await p.send_xt('bpc', 401)
|
@ -1,17 +1,16 @@
|
|||||||
from houdini import handlers
|
import datetime
|
||||||
from houdini.handlers import XTPacket
|
import random
|
||||||
from houdini.handlers.play.mail import handle_start_mail_engine
|
import time
|
||||||
|
|
||||||
|
from aiocache import cached
|
||||||
|
|
||||||
|
from houdini import handlers
|
||||||
|
from houdini.constants import ClientType
|
||||||
from houdini.data.item import Item
|
from houdini.data.item import Item
|
||||||
from houdini.data.mail import PenguinPostcard
|
from houdini.data.mail import PenguinPostcard
|
||||||
from houdini.data.penguin import EpfComMessage
|
from houdini.data.penguin import EpfComMessage
|
||||||
from houdini.constants import ClientType
|
from houdini.handlers import XTPacket
|
||||||
|
from houdini.handlers.play.mail import handle_start_mail_engine
|
||||||
import datetime
|
|
||||||
import time
|
|
||||||
import random
|
|
||||||
|
|
||||||
from aiocache import cached
|
|
||||||
|
|
||||||
|
|
||||||
@cached(alias='default', key='com_messages')
|
@cached(alias='default', key='com_messages')
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
from houdini import handlers
|
|
||||||
from houdini.handlers import XTPacket
|
|
||||||
from houdini.handlers.play.navigation import handle_join_server, handle_join_room, handle_join_player_room
|
|
||||||
|
|
||||||
from houdini.data import db
|
|
||||||
from houdini.data.quest import Quest, QuestAwardItem, QuestAwardFurniture, QuestAwardPuffleItem, QuestTask
|
|
||||||
from houdini.data.quest import PenguinQuestTask
|
|
||||||
|
|
||||||
import ujson
|
import ujson
|
||||||
from aiocache import cached
|
from aiocache import cached
|
||||||
|
|
||||||
|
from houdini import handlers
|
||||||
|
from houdini.data import db
|
||||||
|
from houdini.data.quest import PenguinQuestTask, Quest, QuestAwardFurniture, QuestAwardItem, QuestAwardPuffleItem, \
|
||||||
|
QuestTask
|
||||||
|
from houdini.handlers import XTPacket
|
||||||
|
from houdini.handlers.play.navigation import handle_join_player_room, handle_join_room, handle_join_server
|
||||||
|
|
||||||
|
|
||||||
def get_status_key(_, p):
|
def get_status_key(_, p):
|
||||||
return f'quest.status.{p.id}'
|
return f'quest.status.{p.id}'
|
||||||
|
@ -1,28 +1,23 @@
|
|||||||
import itertools
|
import itertools
|
||||||
import ujson
|
|
||||||
import time
|
import time
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
from houdini import handlers
|
import ujson
|
||||||
from houdini.handlers import XMLPacket, XTPacket, Priority
|
from aiocache import cached
|
||||||
from houdini.converters import SeparatorConverter
|
|
||||||
from houdini.constants import ClientType, StatusField
|
|
||||||
from houdini.handlers.play.navigation import handle_join_server
|
|
||||||
|
|
||||||
from houdini.data import db
|
|
||||||
from houdini.data.penguin import Penguin
|
|
||||||
from houdini.data.room import PenguinIglooRoom
|
|
||||||
from houdini.data.igloo import IglooFurniture, IglooLike, Igloo, Furniture, Flooring, Location, \
|
|
||||||
IglooCollection, FurnitureCollection, \
|
|
||||||
FlooringCollection, LocationCollection,\
|
|
||||||
PenguinIglooCollection, PenguinFurnitureCollection, \
|
|
||||||
PenguinFlooringCollection, PenguinLocationCollection
|
|
||||||
from houdini.data.room import PenguinIglooRoomCollection
|
|
||||||
from houdini.data.game import PenguinGameData
|
|
||||||
|
|
||||||
from sqlalchemy.dialects.postgresql import insert
|
from sqlalchemy.dialects.postgresql import insert
|
||||||
|
|
||||||
from aiocache import cached
|
from houdini import handlers
|
||||||
|
from houdini.constants import ClientType, StatusField
|
||||||
|
from houdini.converters import SeparatorConverter
|
||||||
|
from houdini.data import db
|
||||||
|
from houdini.data.game import PenguinGameData
|
||||||
|
from houdini.data.igloo import Flooring, FlooringCollection, Furniture, FurnitureCollection, Igloo, IglooCollection, \
|
||||||
|
IglooFurniture, IglooLike, Location, LocationCollection, PenguinFlooringCollection, PenguinFurnitureCollection, \
|
||||||
|
PenguinIglooCollection, PenguinLocationCollection
|
||||||
|
from houdini.data.penguin import Penguin
|
||||||
|
from houdini.data.room import PenguinIglooRoom, PenguinIglooRoomCollection
|
||||||
|
from houdini.handlers import Priority, XMLPacket, XTPacket
|
||||||
|
from houdini.handlers.play.navigation import handle_join_server
|
||||||
|
|
||||||
|
|
||||||
def get_layout_furniture_key(_, p, igloo_id):
|
def get_layout_furniture_key(_, p, igloo_id):
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
from houdini import handlers
|
from houdini import handlers
|
||||||
from houdini.handlers import XMLPacket, XTPacket, Priority
|
|
||||||
|
|
||||||
from houdini.data.penguin import Penguin
|
|
||||||
from houdini.data.buddy import IgnoreList, IgnoreListCollection
|
from houdini.data.buddy import IgnoreList, IgnoreListCollection
|
||||||
|
from houdini.data.penguin import Penguin
|
||||||
|
from houdini.handlers import Priority, XMLPacket, XTPacket
|
||||||
|
|
||||||
|
|
||||||
@handlers.handler(XMLPacket('login'), priority=Priority.Low)
|
@handlers.handler(XMLPacket('login'), priority=Priority.Low)
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
|
import operator
|
||||||
|
import time
|
||||||
|
|
||||||
|
from aiocache import cached
|
||||||
|
|
||||||
from houdini import handlers
|
from houdini import handlers
|
||||||
from houdini.handlers import XMLPacket, XTPacket, Priority
|
|
||||||
from houdini.data.item import Item, ItemCollection, PenguinItemCollection
|
from houdini.data.item import Item, ItemCollection, PenguinItemCollection
|
||||||
from houdini.data.permission import PenguinPermissionCollection
|
from houdini.data.permission import PenguinPermissionCollection
|
||||||
|
from houdini.handlers import Priority, XMLPacket, XTPacket
|
||||||
import time
|
|
||||||
from aiocache import cached
|
|
||||||
import operator
|
|
||||||
|
|
||||||
|
|
||||||
def get_pin_string_key(_, p, player_id):
|
def get_pin_string_key(_, p, player_id):
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
from houdini import handlers
|
import time
|
||||||
from houdini.handlers import XTPacket
|
|
||||||
|
|
||||||
|
from houdini import handlers
|
||||||
from houdini.data import db
|
from houdini.data import db
|
||||||
from houdini.data.penguin import Penguin
|
|
||||||
from houdini.data.buddy import IgnoreList
|
from houdini.data.buddy import IgnoreList
|
||||||
from houdini.data.mail import PenguinPostcard, PostcardCollection
|
from houdini.data.mail import PenguinPostcard, PostcardCollection
|
||||||
|
from houdini.data.penguin import Penguin
|
||||||
import time
|
from houdini.handlers import XTPacket
|
||||||
|
|
||||||
|
|
||||||
@handlers.boot
|
@handlers.boot
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
from houdini import handlers
|
from houdini import handlers
|
||||||
|
from houdini.commands import has_command_prefix, invoke_command_string
|
||||||
|
from houdini.data.moderator import ChatFilterRuleCollection
|
||||||
from houdini.handlers import XTPacket
|
from houdini.handlers import XTPacket
|
||||||
from houdini.handlers.play.moderation import moderator_ban
|
from houdini.handlers.play.moderation import moderator_ban
|
||||||
|
|
||||||
from houdini.commands import invoke_command_string, has_command_prefix
|
|
||||||
|
|
||||||
from houdini.data.moderator import ChatFilterRuleCollection
|
|
||||||
|
|
||||||
|
|
||||||
@handlers.boot
|
@handlers.boot
|
||||||
async def filter_load(server):
|
async def filter_load(server):
|
||||||
@ -25,16 +23,17 @@ async def handle_send_message(p, penguin_id: int, message: str):
|
|||||||
await penguin.send_xt("mm", message, penguin_id)
|
await penguin.send_xt("mm", message, penguin_id)
|
||||||
return
|
return
|
||||||
|
|
||||||
tokens = message.lower().split()
|
if p.server.chat_filter_words:
|
||||||
|
tokens = message.lower().split()
|
||||||
|
|
||||||
word, consequence = next(((w, c) for w, c in p.server.chat_filter_words.items() if w in tokens))
|
word, consequence = next(((w, c) for w, c in p.server.chat_filter_words.items() if w in tokens))
|
||||||
|
|
||||||
if consequence.ban:
|
if consequence.ban:
|
||||||
return await moderator_ban(p, p.id, comment='Inappropriate language', message=message)
|
return await moderator_ban(p, p.id, comment='Inappropriate language', message=message)
|
||||||
elif consequence.warn:
|
elif consequence.warn:
|
||||||
return
|
return
|
||||||
elif consequence.filter:
|
elif consequence.filter:
|
||||||
return
|
return
|
||||||
|
|
||||||
if has_command_prefix(p.server.config.command_prefix, message):
|
if has_command_prefix(p.server.config.command_prefix, message):
|
||||||
await invoke_command_string(p.server.commands, p, message)
|
await invoke_command_string(p.server.commands, p, message)
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
from houdini import handlers
|
|
||||||
from houdini.data import db
|
|
||||||
from houdini.handlers import XTPacket
|
|
||||||
from houdini.data.moderator import Ban, Warning, Report
|
|
||||||
from houdini.data.penguin import Penguin
|
|
||||||
from houdini.constants import ClientType
|
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
|
from houdini import handlers
|
||||||
|
from houdini.constants import ClientType
|
||||||
|
from houdini.data import db
|
||||||
|
from houdini.data.moderator import Ban, Report, Warning
|
||||||
|
from houdini.data.penguin import Penguin
|
||||||
|
from houdini.handlers import XTPacket
|
||||||
|
|
||||||
|
|
||||||
@handlers.handler(XTPacket('o', 'k'))
|
@handlers.handler(XTPacket('o', 'k'))
|
||||||
async def handle_kick_player(p, penguin_id: int):
|
async def handle_kick_player(p, penguin_id: int):
|
||||||
|
@ -1,16 +1,15 @@
|
|||||||
from houdini import handlers
|
import asyncio
|
||||||
from houdini.handlers import XTPacket
|
import re
|
||||||
|
from datetime import date, datetime
|
||||||
from houdini.data import db
|
|
||||||
from houdini.data.music import PenguinTrack, TrackLike
|
|
||||||
from houdini.constants import ClientType
|
|
||||||
from houdini.crypto import Crypto
|
|
||||||
|
|
||||||
from gino.loader import ColumnLoader
|
from gino.loader import ColumnLoader
|
||||||
|
|
||||||
from datetime import datetime, date
|
from houdini import handlers
|
||||||
import asyncio
|
from houdini.constants import ClientType
|
||||||
import re
|
from houdini.crypto import Crypto
|
||||||
|
from houdini.data import db
|
||||||
|
from houdini.data.music import PenguinTrack, TrackLike
|
||||||
|
from houdini.handlers import XTPacket
|
||||||
|
|
||||||
|
|
||||||
class SoundStudio:
|
class SoundStudio:
|
||||||
|
@ -1,23 +1,66 @@
|
|||||||
from houdini import handlers
|
import hashlib
|
||||||
from houdini.handlers import XTPacket
|
|
||||||
from houdini.data import db
|
|
||||||
from houdini.data.room import Room
|
|
||||||
from houdini.data.penguin import Penguin, Login
|
|
||||||
from houdini.data.room import PenguinIglooRoom, PenguinBackyardRoom, RoomCollection
|
|
||||||
from houdini.constants import ClientType, StatusField
|
|
||||||
|
|
||||||
import random
|
import random
|
||||||
import time
|
import time
|
||||||
import pytz
|
|
||||||
import hashlib
|
|
||||||
from datetime import date, datetime
|
from datetime import date, datetime
|
||||||
|
|
||||||
|
import pytz
|
||||||
|
|
||||||
|
from houdini import handlers
|
||||||
|
from houdini.constants import ClientType, StatusField
|
||||||
|
from houdini.data import db
|
||||||
|
from houdini.data.penguin import Login, Penguin
|
||||||
|
from houdini.data.room import PenguinBackyardRoom, PenguinIglooRoom, Room, RoomCollection, RoomTable, RoomWaddle
|
||||||
|
from houdini.handlers import XTPacket
|
||||||
|
from houdini.handlers.games.four import ConnectFourLogic
|
||||||
|
from houdini.handlers.games.mancala import MancalaLogic
|
||||||
|
from houdini.handlers.games.ninja.card import CardJitsuLogic, SenseiLogic
|
||||||
|
from houdini.handlers.games.ninja.fire import CardJitsuFireLogic, FireSenseiLogic
|
||||||
|
from houdini.handlers.games.ninja.water import CardJitsuWaterLogic, WaterSenseiLogic
|
||||||
|
from houdini.handlers.games.sled import SledRacingLogic
|
||||||
|
from houdini.handlers.games.treasure import TreasureHuntLogic
|
||||||
|
|
||||||
|
TableLogicMapping = {
|
||||||
|
'four': ConnectFourLogic,
|
||||||
|
'mancala': MancalaLogic,
|
||||||
|
'treasure': TreasureHuntLogic
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WaddleLogicMapping = {
|
||||||
|
'sled': SledRacingLogic,
|
||||||
|
|
||||||
|
'card': CardJitsuLogic,
|
||||||
|
'sensei': SenseiLogic,
|
||||||
|
|
||||||
|
'water': CardJitsuWaterLogic,
|
||||||
|
'watersensei': WaterSenseiLogic,
|
||||||
|
|
||||||
|
'fire': CardJitsuFireLogic,
|
||||||
|
'firesensei': FireSenseiLogic
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async def setup_tables(room_collection):
|
||||||
|
async with db.transaction():
|
||||||
|
async for table in RoomTable.query.gino.iterate():
|
||||||
|
room_collection[table.room_id].tables[table.id] = table
|
||||||
|
table.room = room_collection[table.room_id]
|
||||||
|
table.logic = TableLogicMapping[table.game]()
|
||||||
|
|
||||||
|
|
||||||
|
async def setup_waddles(room_collection):
|
||||||
|
async with db.transaction():
|
||||||
|
async for waddle in RoomWaddle.query.gino.iterate():
|
||||||
|
room_collection[waddle.room_id].waddles[waddle.id] = waddle
|
||||||
|
waddle.room = room_collection[waddle.room_id]
|
||||||
|
waddle.logic = WaddleLogicMapping[waddle.game]
|
||||||
|
|
||||||
|
|
||||||
@handlers.boot
|
@handlers.boot
|
||||||
async def rooms_load(server):
|
async def rooms_load(server):
|
||||||
server.rooms = await RoomCollection.get_collection()
|
server.rooms = await RoomCollection.get_collection()
|
||||||
await server.rooms.setup_tables()
|
await setup_tables(server.rooms)
|
||||||
await server.rooms.setup_waddles()
|
await setup_waddles(server.rooms)
|
||||||
server.logger.info(f'Loaded {len(server.rooms)} rooms ({len(server.rooms.spawn_rooms)} spawn)')
|
server.logger.info(f'Loaded {len(server.rooms)} rooms ({len(server.rooms.spawn_rooms)} spawn)')
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,18 +1,5 @@
|
|||||||
from houdini import handlers
|
from houdini import handlers
|
||||||
from houdini.handlers import XMLPacket, XTPacket, Priority
|
from houdini.handlers import XTPacket
|
||||||
from houdini.data.ninja import PenguinCardCollection, CardCollection
|
|
||||||
|
|
||||||
|
|
||||||
@handlers.boot
|
|
||||||
async def cards_load(server):
|
|
||||||
server.cards = await CardCollection.get_collection()
|
|
||||||
server.logger.info(f'Loaded {len(server.cards)} ninja cards')
|
|
||||||
|
|
||||||
|
|
||||||
@handlers.handler(XMLPacket('login'), priority=Priority.Low)
|
|
||||||
@handlers.allow_once
|
|
||||||
async def load_ninja_inventory(p):
|
|
||||||
p.cards = await PenguinCardCollection.get_collection(p.id)
|
|
||||||
|
|
||||||
|
|
||||||
@handlers.handler(XTPacket('ni', 'gnr'))
|
@handlers.handler(XTPacket('ni', 'gnr'))
|
||||||
@ -40,7 +27,7 @@ async def handle_get_snow_level(p):
|
|||||||
await p.send_xt('gsl', 0, 0)
|
await p.send_xt('gsl', 0, 0)
|
||||||
|
|
||||||
|
|
||||||
@handlers.handler(XTPacket('cd', 'gcd'))
|
@handlers.handler(XTPacket('ni', 'gcd'))
|
||||||
async def handle_get_card_data(p):
|
async def handle_get_card_data(p):
|
||||||
await p.send_xt('gcd', '|'.join(f'{card.card_id},{card.quantity},{card.member_quantity}'
|
await p.send_xt('gcd', '|'.join(f'{card.card_id},{card.quantity},{card.member_quantity}'
|
||||||
for card in p.cards.values()))
|
for card in p.cards.values()))
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
from houdini import handlers
|
|
||||||
from houdini.handlers import XTPacket
|
|
||||||
|
|
||||||
|
|
||||||
import ujson
|
import ujson
|
||||||
|
|
||||||
|
from houdini import handlers
|
||||||
|
from houdini.handlers import XTPacket
|
||||||
|
|
||||||
DefaultPartyCookie = {
|
DefaultPartyCookie = {
|
||||||
'msgViewedArray': [0] * 10,
|
'msgViewedArray': [0] * 10,
|
||||||
|
@ -1,21 +1,16 @@
|
|||||||
from houdini import handlers
|
|
||||||
from houdini.handlers import XMLPacket, XTPacket, Priority
|
|
||||||
from houdini.constants import ClientType, StatusField
|
|
||||||
|
|
||||||
from houdini.data.pet import PenguinPuffleCollection, PenguinPuffleItemCollection, PenguinPuffle, \
|
|
||||||
PuffleCollection, PuffleItemCollection, \
|
|
||||||
PuffleTreasureFurniture, PuffleTreasureItem, \
|
|
||||||
PuffleTreasurePuffleItem
|
|
||||||
from houdini.data.room import PenguinBackyardRoom, PenguinIglooRoom
|
|
||||||
from houdini.data.mail import PenguinPostcard
|
|
||||||
|
|
||||||
from datetime import datetime, timedelta
|
|
||||||
|
|
||||||
import time
|
|
||||||
import random
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import operator
|
import operator
|
||||||
|
import random
|
||||||
|
import time
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
|
from houdini import handlers
|
||||||
|
from houdini.constants import ClientType, StatusField
|
||||||
|
from houdini.data.mail import PenguinPostcard
|
||||||
|
from houdini.data.pet import PenguinPuffle, PenguinPuffleCollection, PenguinPuffleItemCollection, PuffleCollection, \
|
||||||
|
PuffleItemCollection, PuffleTreasureFurniture, PuffleTreasureItem, PuffleTreasurePuffleItem
|
||||||
|
from houdini.data.room import PenguinBackyardRoom, PenguinIglooRoom
|
||||||
|
from houdini.handlers import Priority, XMLPacket, XTPacket
|
||||||
|
|
||||||
PuffleKillerInterval = 600
|
PuffleKillerInterval = 600
|
||||||
LegacyPuffleIds = [0, 1, 2, 3, 4, 5, 6, 7, 8]
|
LegacyPuffleIds = [0, 1, 2, 3, 4, 5, 6, 7, 8]
|
||||||
@ -450,6 +445,7 @@ async def handle_wear_puffle(p, item_id: int):
|
|||||||
|
|
||||||
@handlers.disconnected
|
@handlers.disconnected
|
||||||
@handlers.player_attribute(client_type=ClientType.Legacy)
|
@handlers.player_attribute(client_type=ClientType.Legacy)
|
||||||
|
@handlers.player_attribute(joined_world=True)
|
||||||
async def handle_stop_walking(p):
|
async def handle_stop_walking(p):
|
||||||
if p.joined_world:
|
if p.joined_world:
|
||||||
if p.walking:
|
if p.walking:
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
from houdini import handlers
|
import asyncio
|
||||||
from houdini.converters import SeparatorConverter
|
import random
|
||||||
from houdini.handlers import XTPacket, XMLPacket, Priority
|
import time
|
||||||
from houdini.data import db
|
from datetime import datetime, timedelta
|
||||||
from houdini.data.penguin import Penguin, PenguinMembership
|
|
||||||
from houdini.data.mail import PenguinPostcard
|
|
||||||
from houdini.constants import ClientType
|
|
||||||
|
|
||||||
from aiocache import cached
|
from aiocache import cached
|
||||||
from datetime import datetime, timedelta
|
|
||||||
import random
|
from houdini import handlers
|
||||||
import asyncio
|
from houdini.constants import ClientType
|
||||||
import time
|
from houdini.converters import SeparatorConverter
|
||||||
|
from houdini.data import db
|
||||||
|
from houdini.data.mail import PenguinPostcard
|
||||||
|
from houdini.data.penguin import Penguin, PenguinMembership
|
||||||
|
from houdini.handlers import Priority, XMLPacket, XTPacket
|
||||||
|
|
||||||
|
|
||||||
def get_player_string_key(_, p, player_id):
|
def get_player_string_key(_, p, player_id):
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
from houdini import handlers
|
import time
|
||||||
from houdini.handlers import XTPacket
|
|
||||||
from houdini.constants import ClientType
|
|
||||||
|
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
import ujson
|
import ujson
|
||||||
import time
|
|
||||||
|
|
||||||
|
from houdini import handlers
|
||||||
|
from houdini.constants import ClientType
|
||||||
|
from houdini.handlers import XTPacket
|
||||||
|
|
||||||
RainbowQuestRewards = [6158, 4809, 1560, 3159]
|
RainbowQuestRewards = [6158, 4809, 1560, 3159]
|
||||||
RainbowBonusReward = 5220
|
RainbowBonusReward = 5220
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
from houdini import handlers
|
|
||||||
from houdini.handlers import XTPacket
|
|
||||||
from houdini.data.penguin import Penguin
|
|
||||||
|
|
||||||
import random
|
import random
|
||||||
|
|
||||||
|
from houdini import handlers
|
||||||
|
from houdini.data.penguin import Penguin
|
||||||
|
from houdini.handlers import XTPacket
|
||||||
|
|
||||||
|
|
||||||
@handlers.handler(XTPacket('r', 'cdu'))
|
@handlers.handler(XTPacket('r', 'cdu'))
|
||||||
@handlers.cooldown(1)
|
@handlers.cooldown(1)
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
from houdini import handlers
|
from houdini import handlers
|
||||||
from houdini.handlers import XTPacket
|
|
||||||
|
|
||||||
from houdini.data.item import Item
|
from houdini.data.item import Item
|
||||||
|
from houdini.handlers import XTPacket
|
||||||
|
|
||||||
|
|
||||||
@handlers.handler(XTPacket('s', 'upc'))
|
@handlers.handler(XTPacket('s', 'upc'))
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
from houdini import handlers
|
|
||||||
from houdini.handlers import XMLPacket, XTPacket, Priority
|
|
||||||
from houdini.handlers.play.navigation import handle_join_server, handle_join_room
|
|
||||||
from houdini.data.stamp import Stamp, CoverStamp, CoverItem, PenguinStampCollection, StampCollection
|
|
||||||
from houdini.data.penguin import Penguin
|
|
||||||
|
|
||||||
from aiocache import cached
|
from aiocache import cached
|
||||||
|
|
||||||
|
from houdini import handlers
|
||||||
|
from houdini.data.penguin import Penguin
|
||||||
|
from houdini.data.stamp import CoverItem, CoverStamp, PenguinStampCollection, Stamp, StampCollection
|
||||||
|
from houdini.handlers import Priority, XMLPacket, XTPacket
|
||||||
|
from houdini.handlers.play.navigation import handle_join_room, handle_join_server
|
||||||
|
|
||||||
|
|
||||||
def get_book_cover_key(_, p, player_id):
|
def get_book_cover_key(_, p, player_id):
|
||||||
return f'book.{player_id}'
|
return f'book.{player_id}'
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
from houdini import handlers
|
from houdini import handlers
|
||||||
from houdini.handlers import XTPacket
|
|
||||||
from houdini.constants import ClientType
|
from houdini.constants import ClientType
|
||||||
|
from houdini.handlers import XTPacket
|
||||||
|
|
||||||
|
|
||||||
@handlers.handler(XTPacket('t', 'at'))
|
@handlers.handler(XTPacket('t', 'at'))
|
||||||
|
@ -1,17 +1,18 @@
|
|||||||
|
from datetime import datetime
|
||||||
|
|
||||||
from houdini import handlers
|
from houdini import handlers
|
||||||
from houdini.handlers import XTPacket
|
|
||||||
from houdini.constants import ClientType
|
from houdini.constants import ClientType
|
||||||
from houdini.data.item import Item
|
from houdini.data.item import Item
|
||||||
from houdini.data.igloo import Furniture, Igloo
|
from houdini.data.igloo import Furniture, Igloo
|
||||||
from houdini.data import db
|
from houdini.data import db
|
||||||
from houdini.data.redemption import RedemptionCode, RedemptionAwardCard, RedemptionAwardFlooring, \
|
from houdini.data.redemption import PenguinRedemptionBook, PenguinRedemptionCode, RedemptionAwardCard, \
|
||||||
RedemptionAwardFurniture, RedemptionAwardIgloo, RedemptionAwardItem, RedemptionAwardLocation,\
|
RedemptionAwardFlooring, RedemptionAwardFurniture, RedemptionAwardIgloo, RedemptionAwardItem, \
|
||||||
RedemptionAwardPuffle, RedemptionAwardPuffleItem, PenguinRedemptionBook, PenguinRedemptionCode
|
RedemptionAwardLocation, RedemptionAwardPuffle, RedemptionAwardPuffleItem, RedemptionCode
|
||||||
|
from houdini.handlers import XTPacket
|
||||||
|
|
||||||
import random
|
import random
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
@handlers.handler(XTPacket('rjs', ext='red'), pre_login=True, client=ClientType.Vanilla)
|
@handlers.handler(XTPacket('rjs', ext='red'), pre_login=True, client=ClientType.Vanilla)
|
||||||
@handlers.allow_once
|
@handlers.allow_once
|
||||||
async def handle_join_redemption_server_vanilla(p, credentials: str, confirmation_hash: str, lang: str):
|
async def handle_join_redemption_server_vanilla(p, credentials: str, confirmation_hash: str, lang: str):
|
||||||
@ -172,9 +173,6 @@ async def handle_golden_choice(p, redemption_code: str, choice: int):
|
|||||||
if penguin_redeemed:
|
if penguin_redeemed:
|
||||||
return await p.close()
|
return await p.close()
|
||||||
|
|
||||||
if choice == 1:
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,19 +1,17 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from houdini.spheniscidae import Spheniscidae
|
|
||||||
from houdini.penguin import Penguin
|
|
||||||
from houdini import PenguinStringCompiler
|
|
||||||
|
|
||||||
import logging
|
|
||||||
from logging.handlers import RotatingFileHandler
|
from logging.handlers import RotatingFileHandler
|
||||||
|
|
||||||
import aioredis
|
import aioredis
|
||||||
from aiocache import SimpleMemoryCache, caches
|
from aiocache import SimpleMemoryCache, caches
|
||||||
|
|
||||||
|
from houdini import PenguinStringCompiler
|
||||||
from houdini.data import db
|
from houdini.data import db
|
||||||
from houdini.data.permission import PermissionCollection
|
from houdini.data.permission import PermissionCollection
|
||||||
|
from houdini.penguin import Penguin
|
||||||
|
from houdini.spheniscidae import Spheniscidae
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import uvloop
|
import uvloop
|
||||||
@ -32,7 +30,6 @@ from houdini.handlers.play.player import server_heartbeat, server_egg_timer
|
|||||||
from houdini.handlers.play.pet import decrease_stats
|
from houdini.handlers.play.pet import decrease_stats
|
||||||
|
|
||||||
from houdini.handlers.play.music import SoundStudio
|
from houdini.handlers.play.music import SoundStudio
|
||||||
from houdini.handlers.games.dance import DanceFloor
|
|
||||||
|
|
||||||
|
|
||||||
class Houdini:
|
class Houdini:
|
||||||
@ -90,6 +87,9 @@ class Houdini:
|
|||||||
|
|
||||||
self.music = None
|
self.music = None
|
||||||
self.dance_floor = None
|
self.dance_floor = None
|
||||||
|
self.match_making = None
|
||||||
|
self.water_match_making = None
|
||||||
|
self.fire_match_making = None
|
||||||
|
|
||||||
self.puck = (0, 0)
|
self.puck = (0, 0)
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import time
|
import time
|
||||||
|
|
||||||
from houdini.spheniscidae import Spheniscidae
|
|
||||||
from houdini.data import penguin
|
from houdini.data import penguin
|
||||||
from houdini.data.mail import PenguinPostcard
|
from houdini.data.mail import PenguinPostcard
|
||||||
from houdini.handlers.play.pet import get_my_player_walking_puffle
|
from houdini.handlers.play.pet import get_my_player_walking_puffle
|
||||||
|
from houdini.spheniscidae import Spheniscidae
|
||||||
|
|
||||||
|
|
||||||
class Penguin(Spheniscidae, penguin.Penguin):
|
class Penguin(Spheniscidae, penguin.Penguin):
|
||||||
@ -193,15 +193,15 @@ class Penguin(Spheniscidae, penguin.Penguin):
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
async def add_card(self, card, quantity=1, member_quantity=0):
|
async def add_card(self, card, quantity=0, member_quantity=0):
|
||||||
if card.id in self.cards:
|
if card.id in self.cards:
|
||||||
penguin_card = self.cards[card.id]
|
penguin_card = self.cards[card.id]
|
||||||
|
|
||||||
await penguin_card.update(
|
await penguin_card.update(
|
||||||
quantity=penguin_card.quantity + quantity,
|
quantity=penguin_card.quantity + quantity,
|
||||||
member_quantity=member_quantity).apply()
|
member_quantity=penguin_card.member_quantity + member_quantity).apply()
|
||||||
else:
|
else:
|
||||||
await self.cards.insert(card_id=card.id)
|
await self.cards.insert(card_id=card.id, quantity=quantity, member_quantity=member_quantity)
|
||||||
|
|
||||||
self.logger.info(f'{self.username} added \'{card.name}\' to their ninja deck')
|
self.logger.info(f'{self.username} added \'{card.name}\' to their ninja deck')
|
||||||
|
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
from abc import ABC
|
|
||||||
from abc import abstractmethod
|
|
||||||
|
|
||||||
import inspect
|
import inspect
|
||||||
|
from abc import ABC, abstractmethod
|
||||||
|
|
||||||
from houdini import _AbstractManager, get_package_modules
|
from houdini import _AbstractManager, get_package_modules
|
||||||
|
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
from houdini.handlers import XMLPacket, XTPacket
|
from asyncio import CancelledError, IncompleteReadError
|
||||||
|
|
||||||
from asyncio import IncompleteReadError, CancelledError
|
|
||||||
|
|
||||||
import defusedxml.cElementTree as Et
|
|
||||||
from xml.etree.cElementTree import Element, SubElement, tostring
|
from xml.etree.cElementTree import Element, SubElement, tostring
|
||||||
|
|
||||||
|
import defusedxml.cElementTree as Et
|
||||||
|
|
||||||
from houdini.constants import ClientType
|
from houdini.constants import ClientType
|
||||||
from houdini.handlers import AuthorityError
|
from houdini.handlers import AuthorityError, XMLPacket, XTPacket
|
||||||
|
|
||||||
|
|
||||||
class Spheniscidae:
|
class Spheniscidae:
|
||||||
|
Loading…
Reference in New Issue
Block a user