def handleAddItem(client, item): item = client.engine.itemCrumbs[item] if item is None: return client.send('e', 402) if item.is_bait and not client['moderator']: # Ban the player? client.log('warn', '[Exploit detected] Player trying to add a bait item :', item.id) return client.send('e', 410) if item in client['inventory']: return client.send('e', 400) if item.is_member and not client['member']: return client.send('e', 999) if item.is_epf and not client['epf']: #Suspecious? return client.send('e', 410) if client.addItem(item): client.send('ai', item, client['coins']) GeneralEvent.call('add-item:{}'.format(item))
def handleAddItem(client, item): item = client.engine.itemCrumbs[item] if item is None: returnValue(client.send('e', 402)) if item.is_bait and not client['moderator']: # Ban the player? client.log('warn', '[Exploit detected] Player trying to add a bait item :', item.id) returnValue(client.send('e', 410)) if client['RefreshHandler'].inInventory(int(item)): returnValue(client.send('e', 400)) if item.is_member and not client['member']: returnValue(client.send('e', 999)) if item.is_epf and not client['epf']: #Suspecious? returnValue(client.send('e', 410)) added = yield client.addItem(item) if added: client['RefreshHandler'].forceRefresh() GeneralEvent.call('add-item:{}'.format(item), client)
def broadcastMusic(self, nextMusic = False): if self.broadcasting and not nextMusic: return 0 if self.currentMusic is not None: self.currentMusic.shared = False self.shareQueue.remove(self.currentMusic) if len(self.shareQueue) < 1: # try once self.currentMusic = None self.broadcasting = False GeneralEvent('music:broadcast', self, None) self.redis.server.set('music:broadcasting', None) return 0 # No more queue self.broadcasting = True self.currentMusic = self.shareQueue[0] self.redis.server.hmset('music:sharing', {self.currentMusic.id : int(0)}) t = ceil(self.currentMusic.length / 1000) self.redis.server.set('music:broadcasting', int(self.currentMusic)) GeneralEvent('music:broadcast', self, self.currentMusic) self.logger.info('Broadcasting "%s" by %s, %i seconds until next music!', self.currentMusic.name, self.currentMusic.pengNick, t) self.broadcastDefer = reactor.callLater(t, self.broadcastMusic, True) self.refresh()
def append(self, client): self.deChequeReferences() if not isinstance(client, self.roomHandler.engine.protocol): return if client in self: return #client.send('e', 200) if len(self) + 1 > self.max: return client.send('e', 210) if self.member and not client['member']: return client.send('e', 999) if self.requiredItem is not None: if not self.requiredItem in client['inventory']: return client.send('e', 212) super(Room, self).append(client) client.penguin.room = self client.engine.redis.server.hmset( "online:{}".format(client.penguin.id), {'place': self.ext_id if not client['stealth_mode'] else None}) GeneralEvent.call('joined-room', client, self.id) GeneralEvent.call('joined-room-{}'.format(self.ext_id), client, self.ext_id) self.onAdd(client)
def handleJoinServer(client, _id, passd, lang): if _id != client.penguin.id or passd != client.penguin.password: client.send('e', 101) returnValue(client.disconnect()) # User logged in! yield client.engine.redis.server.hincrby('server:{}'.format(client.engine.id), 'population', 1) yield client.engine.redis.server.hmset("online:{}".format(client.penguin.id), {'joined' : 1, 'world': client.engine.id}) yield client.engine.redis.server.sadd("users:{}".format(client.engine.id), client['swid']) client.initialize() yield client['RefreshHandler'].CacheInitializedDefer GeneralEvent.call("penguin-logged", client.ref) # 47 -> all lang except russian, 111 -> all incl russian; russian lang is deprecated and no longer exists # to get support for any lang, use bitmask = LANG1_BITMASK ^ LANG2_BITMASK ^ ... client.penguin.lang_allowed = bool(lang & client['data'].avatar.language) client.penguin.language = client['data'].avatar.language if not client['moderator'] else 47 # todo: epf client.send('js', *(map(int, [0, client['RefreshHandler'].inInventory(428), client['moderator']]))) client.send('gps', client['id'], '|'.join([str(k.stamp) for k in client['data'].stamps])) client.canRecvPacket = True # Start receiving XT Packets member = client['member'].mrem if client.Protocol == AS3_PROTOCOL: client.send('lp', client, client['coins'], 0, 1440, int(time() * 1000), client['age'], 0, int(client['age'])-1, member or '', '', client['cache'].playerWidget, client['cache'].mapCategory, client['cache'].igloo) elif client.Protocol == AS2_PROTOCOL: # #user_str%coins%issafe%egg%time%age%banned%minplay%memdays client.send('lp', client, client['coins'], 0, 1440, int(time() * 1000), client['age'], 0, int(client['age'])/60, member, 0) client.engine.roomHandler.joinRoom(client, 'town', 'name') # TODO Check for max-users limit
def handleJoinServer(client, _id, passd, lang): if _id != client.penguin.id or passd != client.penguin.password: client.send('e', 101) returnValue(client.disconnect()) # User logged in! GeneralEvent.call("penguin-logged", client.selfRefer) yield client.engine.redis.server.hincrby( 'server:{}'.format(client.engine.id), 'population', 1) yield client.engine.redis.server.hmset( "online:{}".format(client.penguin.id), {'joined': 1}) client.initialize() client.send( 'js', *(map(int, [client['member'] > 0, client['moderator'], client['epf']]))) client.send('gps', client['id'], client['stampHandler']) client.canRecvPacket = True # Start receiving XT Packets member = int(client['member']) if int(client['member']) > 0 else 0 client.send('lp', client, client['coins'], 0, 1024, int(time() * 1000), client['age'], 0, client['age'], member, '', client['cache'].playerWidget, client['cache'].mapCategory, client['cache'].igloo) client.engine.roomHandler.joinRoom( client, 'dojofire', 'name') # TODO Check for max-users limit
def handleStartMail(client, data): if client['mail'] is None: return client.send('mst', -1, -1) GeneralEvent.call('mail-start', client) unread = len([k for k in client['mail'] if k.opened < 1]) client.send('mst', unread, len(client['mail']))
def handleKickPlayer(client, _id): if not client['moderator']: client.engine.log('warn', '%s tried to kick %s. %s is not a moderator.', client['nickname'], _id) return GeneralEvent('ban-player', client, 0, 'Hacking or Manipulating server. Unauthorized kick {}, while not a moderator.'.format(_id), 1, 3) _kickable = GetPenguin(client.engine, _id) if _kickable['moderator']: return client.send('e', 800) GeneralEvent('kick-player', _kickable, '{} kicked {} on {}'.format(client['nickname'], _kickable['nickname'], client.engine))
def setupCommands(self): CommandsPlugin = self.dependencies[0] if self.Call_AI_Command not in CommandsPlugin.__commands__: CommandsPlugin.__commands__.append(self.Call_AI_Command) GeneralEvent.on('command={}'.format(self.Call_AI_Command.lower()), self.Play4) self.logger.debug("FindFour AI Call Command set. Command : %s", self.Call_AI_Command)
def __init__(self): super(Commands, self).__init__() self.logger = logging.getLogger(TIMELINE_LOGGER) GeneralEvent.on('before-message', self) GeneralEvent.on('after-message-muted', self.deMute) self.setup() self.logger.debug("Player Commands Active!")
def __init__(self): super(FindFourAI, self).__init__() self.logger = logging.getLogger(TIMELINE_LOGGER) self.Bots = {} self.AICreatedDefer = self.setupAI() self.setupCommands() self.logger.debug("FindFour AI Active!") self.logger.debug("Please ensure you have dassets.swf active!") GeneralEvent.on('onEngine', self.attachBotToServer)
def Play4(self, client, params): if client['room'].ext_id is not 220: return engine = client.engine if engine not in self.Bots: return client.send('sm', client['id'], "Sorry, bot is not available in this server!") AI = self.Bots[engine]['bot'] if self.Bots[engine]['playing'] is not None: return client.send( 'sm', AI['id'], "Sorry, am currently playing with {}".format( self.Bots[engine]['playing']['nickname'])) try: difficulty = int(params[0]) except: difficulty = 2 # default if difficulty > self.Bots[engine]['difficulty'] or difficulty < 1: difficulty = self.Bots[engine]['difficulty'] # maximum client.send( 'sm', AI['id'], "Let's play! Difficulty level set to {}".format(difficulty)) sleep(3) client.send('sm', AI['id'], "Finding a board to play...") AvailableBoard = self.getFourBoard(engine) if AvailableBoard is None: return client.send('sm', AI['id'], "Sorry, no boards are available to play! :(") self.Bots[engine]['playing'] = client AI.penguin.difficulty = difficulty GeneralEvent.on( 'Table-Left-{}-{}'.format(client['id'], AvailableBoard.table), self.ClientLeft) client.send('zaf', AvailableBoard.table) # make sure you have dote's assets Event.call('JoinTable-{}'.format(AvailableBoard.table), AI, AvailableBoard.table) AI['room'].send( 'sm', AI['id'], "FindFour: {} V/S {}, difficulty: {}, started!".format( AI['nickname'], client['nickname'], difficulty)) AI['game'].joinGame(AI)
def handleMutePlayer(client, _id): if not client['moderator']: client.engine.log('warn', '%s tried to (un)mute %s. %s is not a moderator.', client['nickname'], _id) return GeneralEvent( 'ban-player', client, 0, 'Hacking or Manipulating server. Unauthorized (un)muting {}, while not a moderator.' .format(_id), 1, 3) _mutable = GetPenguin(client.engine, _id) GeneralEvent( 'mute-player', _mutable, '{} (un)muted {} on {}'.format(client['nickname'], _mutable['nickname'], client.engine))
def ClientLeft(self, client, FourGame): GeneralEvent.removeListener( 'Table-Left-{}-{}'.format(client['id'], FourGame.table), self.ClientLeft) if client.engine not in self.Bots: return FourGame.remove(self.Bots[client.engine]['bot']) self.Bots[client.engine]['playing'] = None AI = self.Bots[client.engine]['bot'] AI['room'].send( 'sm', AI['id'], "I've completed my game with {}. Ready for next round!".format( client['nickname']))
def initialize(self): self.penguin.nickname = Nickname(self.dbpenguin.nickname, self.ref) self.penguin.swid = self.dbpenguin.swid #TODO: figure out why the hell EPF even exists. self.penguin.epf = EPFAgent(self.dbpenguin.agent, str(self.dbpenguin.epf), self.ref) self.penguin.RefreshHandler = Refresh(self.ref) self.penguin.moderator = int(self.dbpenguin.moderator) self.penguin.stealth_mode = self['moderator'] == 2 self.penguin.mascot_mode = self['moderator'] == 3 self.penguin.x = self.penguin.y = self.penguin.frame = 0 self.penguin.age = Age(self.dbpenguin.create, self.ref) self.penguin.muted = False self.penguin.cache = Cache(self.ref) self.penguin.ninjaHandler = NinjaHandler(self.ref) self.penguin.currencyHandler = CurrencyHandler(self.ref) self.engine.musicHandler.init(self.ref) GeneralEvent('onBuildClient', self.ref)
def connectionLost(self, reason): super(Penguin, self).connectionLost(reason) if self.id in self.users: del self.users[self.id] self.penguin.connectionLost = True # decentralize and make disconnection more flexible if self.engine.type == WORLD_SERVER and self.penguin.id != None: # sending self just to make sure it doesn't throw weak-reference error if self['RefreshHandler'] is not None: self['RefreshHandler'].RefreshManagerLoop.stop( ) if self['RefreshHandler'].RefreshManagerLoop.running else 0 yield self.engine.redis.server.srem( "users:{}".format(self.engine.id), self['swid']) yield GeneralEvent('onClientDisconnect', self.ref) if self['RefreshHandler'] is not None: del self.penguin.RefreshHandler yield self.engine.redis.server.delete("online:{}".format(self['id'])) yield self.engine.disconnect(self) self.cleanConnectionLost.callback(True)
def __init__(self, protocol, _type, _id, name="World Server 1", _max=300, server_protocol = AS3_PROTOCOL): self.protocol = protocol self.server_protocol = server_protocol self.type = _type self.id = _id self.logger = logging.getLogger(TIMELINE_LOGGER) self.name = name self.users = deque() # Thread safe self.dbDetails = dict() self.maximum = _max - 1 self._listening = False self._portListener = None self.proxyReference = weakref.proxy(self) self.redis = Redis(self) self.log("info", "Timeline Factory Started!") self.log("info", "Running:", self.name) self.log("info", "Maximum users:", self.maximum) if self.type == WORLD_SERVER: self.initializeWorld() self.redis.redisConnectionDefer.addCallback(lambda *x: GeneralEvent('onEngine', self))
def __call__(self, client, message): if not message.startswith('!') or client['muted']: return msg_packets = message[1:].split(' ') command = msg_packets[0].lower() params = msg_packets[1:] __commands__ = [str(k).lower() for k in self.__commands__] if command in __commands__: client.penguin.muted = True client.penguin.muted_for_command = True if client['muted_for_command'] is None \ else client['muted_for_command'] GeneralEvent('command={}'.format(command), client, params) GeneralEvent('command[{}]={}'.format(client.Protocol, command), client, params)
def onCommand(command, protocol=AS3_PROTOCOL, function=None): command_ext = 'command[{}]={}'.format(protocol, command) commandPlugin = [i for i in PLUGIN_OBJECTS if isinstance(i, Commands)][-1] commandPlugin.__commands__.append( command) if command not in commandPlugin.__commands__ else None return GeneralEvent.on(command_ext, function=function)
def checkForMascotPresence(self): mascots = set(m['nickname'] for m in self if m['mascot_mode']) penguins = [p for p in self if not p['mascot_mode']] [ GeneralEvent("mascot-joined-room", self, mascot, penguins) for mascot in mascots ] self.roomHandler.engine.log("info", "Mascot presence found in room: ", self.name)
def onRemove(self, client): try: super(TableGame, self).onRemove(client) except: pass GeneralEvent('Table-Left-{}-{}'.format(client['id'], self.table), client, self) GeneralEvent('Table-Left-{}'.format(client['id']), client, self) GeneralEvent('Table-Left-{}'.format(self.table), client, self) client.penguin.playing = client.penguin.waddling = False client.penguin.game = None self.room.append(self) client.penguin.room = self.room # must client.engine.redis.server.hmset("online:{}".format(client.penguin.id), {'place' : self.room.ext_id}) self.updateTable()
def disconnect(self, client): GeneralEvent('onClientRemove', client.ref) if client in self.users: self.users.remove(client) yield self.redis.server.hmset("server:{}".format(self.id), {'population':len(self.users)}) returnValue(True) returnValue(False)
def _refresh(self, forced=False): if self.DEBUG: self.logger.info( 'Penguin ASync-Refresh-ing : Penguin - {}, Forced - {}'.format( self.penguin['nickname'], forced)) if self.penguin['connectionLost']: returnValue(0) if self.firstTimeCall: yield self._setupCache() self.firstTimeCall = False returnValue(1) # coins update self.penguin.penguin.coins = (yield Registry.getConfig(). \ execute("SELECT SUM(transaction) FROM coins where penguin_id = %s" % self.penguin['id']))[0][0] if self.penguin['coins'] is None: yield Coin(penguin_id=self.penguin['id'], transaction=100, comment="Player went bankrupt. " "Giving them +100").save() self.penguin.penguin.coins = 100 self.penguin.penguin.coins = int(self.penguin['coins']) self.penguin.send('gtc', self.penguin['coins']) for item in self.REFRESH_ITEMS: if not hasattr(self.penguin.dbpenguin, item): continue relation = getattr(self.penguin.dbpenguin, item) items_o = set(self.cache[item]) items_ = yield relation.get() items_updated = set(items_) items_added = items_updated - items_o items_removed = items_o - items_updated reactor.callFromThread(self.cacheHandlers[item], items_added, items_removed, items_o) reactor.callFromThread(self.cacheHandlers['igloos']) GeneralEvent( 'Refresh-Cache', self) # Refresh cache data for things other than those in here if forced: reactor.callFromThread( self.RefreshManagerLoop.stop ) if self.RefreshManagerLoop.running else None reactor.callFromThread(self.RefreshManagerLoop.start, self.REFRESH_INTERVAL, False) if \ not self.penguin['connectionLost'] else None
def connectionLost(self, reason): del self.PacketHandler.penguin super(Penguin, self).connectionLost(reason) # decentralize and make disconnection more flexible if self.engine.type == WORLD_SERVER and self.penguin.id != None: self.engine.roomHandler.removeFromAnyRoom(self.selfRefer) yield GeneralEvent('onClientDisconnect', self.selfRefer) yield self.engine.disconnect(self) self.cleanConnectionLost.callback(True)
def handleGameOver(client, data): score = int(data[2][0]) coins = round(score / 10.0) client.penguin.playing = False current_game = client['room'] if coins > 10000: client.engine.log('warn', "Potential coins manipulation,", current_game, ':', score) return if not isinstance(current_game, Game) or isinstance( current_game, Multiplayer): try: current_game.gameOver(client=client) except: client.engine.log('warn', "Game exploitation,", current_game.name, ':', score) return stamps = map(int, client['recentStamps']) g_stamps = map( int, client.engine.stampCrumbs.getStampsByGroup(current_game.stamp_id)) e_stamps = list( set(map(lambda x: int(x.stamp), client['data'].stamps)).intersection(g_stamps)) stamps = list(set(stamps).intersection(g_stamps)) earned = len(e_stamps) total = len(g_stamps) if total == earned and total != 0: coins *= 2 client.send('zo', client['coins'] + coins, '|'.join(map(str, stamps)), earned, total, total) client['coins'] += coins Coin(penguin_id=client['id'], transaction=coins, comment="Coins earned by playing game. Game: {}".format( current_game.name)).save() GeneralEvent("Game-Over", client, score, current_game) client['room'].remove(client) for room in client['prevRooms'][::-1]: if isinstance(room, Place): room.append(client) return
def onAdd(self, client): super(Place, self).onAdd(client) client.send('jr', self.ext_id, *((self, ) if len(str(self)) > 0 else [])) self.send('ap', client) if not client['stealth_mode'] else client.send( 'ap', client) if client['mascot_mode']: GeneralEvent("mascot:{}-joined-room".format(client['nickname']), self) self.checkForMascotPresence()
def handleSendMessage(client, _id, message): if not client['id'] == _id: return message = message.strip(' ').replace('|', '\\|') GeneralEvent.call('before-message', client, message) if client['muted']: GeneralEvent.call('after-message-muted', client, message) return if client['stealth_mode'] or client['mascot_mode']: return toxic = Toxicity(message) if toxic > 60: # wow toxic... if toxic > 90: # he's a racist, ban him GeneralEvent('ban-player', client, 0, 'Rude. Toxicity [{}] message: {}'.format( toxic, message), type=3, ban_type=610) elif toxic > 80: # Kick'em GeneralEvent( 'kick-player', client, 'Rude. Toxicity [{}] message: {}'.format(toxic, message)) else: GeneralEvent( 'mute-player', client, 'Rude. Toxicity [{}] message: {}'.format(toxic, message)) return client['room'].send('sm', _id, message) GeneralEvent.call('after-message', client, message)
def connectionLost(self, reason): super(Penguin, self).connectionLost(reason) # decentralize and make disconnection more flexible if self.engine.type == WORLD_SERVER and self.penguin.id != None: #self.engine.roomHandler.removeFromAnyRoom(self.selfRefer) # needs some fix b4 further usage on-disconnect self.engine.roomHandler.removeFromAnyRoom(self.selfRefer, self) # experimental # sending self just to make sure it doesn't throw weak-reference error yield self.engine.redis.server.delete("online:{}".format( self['id'])) yield GeneralEvent('onClientDisconnect', self.selfRefer) yield self.engine.disconnect(self) self.cleanConnectionLost.callback(True)
def initialize(self): self.penguin.nickname = Nickname(self.dbpenguin.nickname, self.selfRefer) self.penguin.swid = self.dbpenguin.swid self.penguin.inventory = Inventory(self.selfRefer) self.penguin.inventory.parseFromString(self.dbpenguin.inventory) self.penguin.member = Membership(self.dbpenguin.membership, self.selfRefer) self.penguin.moderator = int(self.dbpenguin.moderator) self.penguin.stealth_mode = self['moderator'] == 2 self.penguin.mascot_mode = self['moderator'] == 3 self.penguin.x = self.penguin.y = self.penguin.frame = self.penguin.avatar = 0 self.penguin.coins = Coins(self.dbpenguin.coins, self.selfRefer) self.penguin.age = Age(self.dbpenguin.create, self.selfRefer) self.penguin.cache = Cache(self.selfRefer) self.penguin.muted = False self.penguin.epf = EPFAgent(self.dbpenguin.agent, str(self.dbpenguin.epf), self.selfRefer) clothing = [Color, Head, Face, Neck, Body, Hand, Feet, Pin, Photo] for cloth in clothing: name = cloth.__name__.lower() self.penguin[name] = cloth(0, 0, name + " item", False, False, False) self.penguin.mail = MailHandler(self.selfRefer) self.penguin.iglooHandler = PenguinIglooHandler(self.selfRefer) self.penguin.puffleHandler = PuffleHandler(self.selfRefer) self.penguin.stampHandler = StampHandler(self.selfRefer) self.penguin.ninjaHandler = NinjaHandler(self.selfRefer) self.penguin.currencyHandler = CurrencyHandler(self.selfRefer) self.penguin.friendsHandler = FriendsHandler(self.selfRefer) self.engine.musicHandler.init(self.selfRefer) self.loadClothing() GeneralEvent('onBuildClient', self.selfRefer)
def __init__(self, protocol, _type, _id, name="World Server 1", _max=300): self.protocol = protocol self.type = _type self.id = _id self.logger = logging.getLogger(TIMELINE_LOGGER) self.name = name self.users = deque() # Thread safe self.dbDetails = dict() self.maximum = _max - 1 self.redis = Redis(self) self.log("info", "Timeline Factory Started!") self.log("info", "Running:", self.name) self.log("info", "Maximum users:", self.maximum) if self.type == WORLD_SERVER: self.initializeWorld() GeneralEvent('onEngine', self)