Example #1
0
 def promotion(self, npc, player):
     npc.sayTo(player, "Do you want me to promote you?")
     word = yield
     word = word.title()
     if word in accept:
         if player.data["vocation"] < 4 and player.data["level"] > 20:
             if player.removeMoney(20000):
                 sql.runOperation(
                     "UPDATE `players` SET `vocation` = %s WHERE `id` = %s",
                     (player.data["vocation"] + 4, player.data["id"]))
                 player.data["vocation"] += 4
                 npc.sayTo(player, "Congratulations! You are now promoted.")
             else:
                 npc.sayTo(player, "You do not have enough money!")
         elif player.data["level"] < 20:
             npc.sayTo(
                 player,
                 "I am sorry, but I can only promote you once you have reached level"
             )
         else:
             npc.sayTo(player, "You are already promoted!")
Example #2
0
            def firstPacketLoginChar(self, packet):
                characterName = packet.string()

                if (not self.username and not config.anyAccountWillDo) or not characterName:
                    self.exitWithError("Could not get your account name, or character name")
                    return

                packet.pos += 6 # I don't know what this is

                # Our funny way of doing async SQL
                account = yield sql.runQuery("SELECT `id`,`language` FROM `accounts` WHERE `name` = %s AND `password` = SHA1(CONCAT(`salt`, %s))", self.username, self.password)

                if not account:
                    account = game.scriptsystem.get("loginAccountFailed").run(client=self, username=username, password=self.password)
                    if not account or account == True:
                        self.exitWithError("Invalid username or password")
                        return

                account = account[0]

                # Ban check.
                if game.ban.accountIsBanned(account['id']):
                    self.exitWithError("Your account is banned.\n %s" % game.ban.banAccounts[account['id']].message())
                    return

                if not len(account) >= 2 or not account['language']:
                    language = config.defaultLanguage
                else:
                    language = account['language']

                character = yield sql.runQuery("SELECT p.`id`,p.`name`,p.`world_id`,p.`group_id`,p.`account_id`,p.`vocation`,p.`health`,p.`mana`,p.`soul`,p.`manaspent`,p.`experience`,p.`posx`,p.`posy`,p.`posz`,p.`instanceId`,p.`sex`,p.`looktype`,p.`lookhead`,p.`lookbody`,p.`looklegs`,p.`lookfeet`,p.`lookaddons`,p.`lookmount`,p.`town_id`,p.`skull`,p.`stamina`, p.`storage`, p.`inventory`, p.`depot`, p.`conditions`, s.`fist`,s.`fist_tries`,s.`sword`,s.`sword_tries`,s.`club`,s.`club_tries`,s.`axe`,s.`axe_tries`,s.`distance`,s.`distance_tries`,s.`shield`,s.`shield_tries`,s.`fishing`, s.`fishing_tries`, g.`guild_id`, g.`guild_rank`, p.`balance` FROM `players` AS `p` LEFT JOIN player_skills AS `s` ON p.`id` = s.`player_id` LEFT JOIN player_guild AS `g` ON p.`id` = g.`player_id` WHERE p.account_id = %s AND p.`name` = %s AND p.`world_id` = %s", account['id'], characterName, config.worldId)

                if not character:
                    character = game.scriptsystem.get("loginCharacterFailed").run(client=self, account=account, name=characterName)
                    if not character or character == True:
                        self.exitWithError("Character can't be loaded")
                        return

                character = character[0]

                # Ban check.
                if isinstance(character, game.player.Player):
                    if game.ban.playerIsBanned(character):
                        self.exitWithError("Your player is banned.\n %s" % game.ban.banAccounts[character.data["id"]].message())
                        return
                elif game.ban.playerIsBanned(character['id']):
                    self.exitWithError("Your player is banned.\n %s" % game.ban.banAccounts[character['id']].message())
                    return

                # If we "made" a new character in a script, character = the player.
                player = None
                if isinstance(character, game.player.Player):
                    player = character
                    game.player.allPlayers[player.name()] = player
                elif character['name'] in game.player.allPlayers:
                    player = game.player.allPlayers[character['name']]
                    if player.client:
                        self.exitWithError("This character is already logged in!")
                        return
                if player:
                    self.player = player
                    if self.player.data["health"] <= 0:
                        self.player.onSpawn()
                    self.player.client = self
                    tile = getTile(self.player.position)
                    tile.placeCreature(self.player)
                    # Send update tile to refresh all players. We use refresh because it fixes the order of things as well.
                    updateTile(self.player.position, tile)

                else:
                    # Load deathlist.
                    yield deathlist.loadDeathList(character['id'])
                    character["language"] = language
                    game.player.allPlayers[character['name']] = game.player.Player(self, character)
                    self.player = game.player.allPlayers[character['name']]
                    if self.player.data["health"] <= 0:
                        self.player.onSpawn()

                    try:
                        tile = getTile(self.player.position)
                        tile.placeCreature(self.player)
                        # Send update tile to refresh all players. We use refresh because it fixes the order of things as well.
                        updateTile(self.player.position, tile)

                    except AttributeError:
                        self.player.position = Position(*game.map.mapInfo.towns[1][1])
                        tile = getTile(self.player.position)
                        tile.placeCreature(self.player)
                        # Send update tile to refresh all players. We use refresh because it fixes the order of things as well.
                        updateTile(self.player.position, tile)

                # Update last login
                sql.runOperation("UPDATE `players` SET `lastlogin` = %s WHERE `id` = %s", int(time.time()), character['id'])

                self.packet = self.player.packet
                self.player.sendFirstPacket()
                self.ready = True # We can now accept other packages

                # Call the login script
                game.scriptsystem.get("login").run(creature=self.player)
Example #3
0
    def onFirstPacket(self, packet):
        packetType = packet.uint8()
        IN_TEST = False

        if packetType == 0xFF:
            # Special case for tests.
            IN_TEST = True
            
        if packetType == 0x0A and not self.ready:
            packet.pos += 2 # OS 0x00 and 0x01
            #packet.uint16() 
            version = packet.uint16() # Version int
            
            if version >= 972:
                version = packet.uint32()
                packet.uint8() # Client type.

            self.protocol = game.protocol.getProtocol(version)
            self.version = version
            print "Client protocol version %d" % version

            if not self.protocol:
                log.msg("Trying to load a invalid protocol")
                self.transport.loseConnection()
                return

            if not IN_TEST:
                if (len(packet.data) - packet.pos) == 128: # RSA 1024 is always 128
                    packet.data = otcrypto.decryptRSA(packet.getData()) # NOTICE: Should we do it in a seperate thread?
                    packet.pos = 0 # Reset position

                else:
                    log.msg("RSA, length != 128 (it's %d)" % (packet.length - packet.pos))
                    self.transport.loseConnection()
                    return

                if not packet.data or packet.uint8(): # RSA needs to decrypt just fine, so we get the data, and the first byte should be 0
                    log.msg("RSA, first char != 0")
                    self.transport.loseConnection()
                    return

                # Set the XTEA key
                k = (packet.uint32(), packet.uint32(), packet.uint32(), packet.uint32())
                sum = 0
                self.xtea = {}
                for x in xrange(32):
                    self.xtea[x] = sum + k[sum & 3] & 0xffffffff
                    sum = (sum + 0x9E3779B9) & 0xffffffff
                    self.xtea[32 + x] = sum + k[sum>>11 & 3] & 0xffffffff
                    

            ip = self.transport.getPeer().host
            
            # Ban check.
            if game.ban.ipIsBanned(ip):
                self.exitWithError("Your ip is banned.\n %s" % game.ban.banIps[ip].message())
                return 
        
            if config.gameMaxConnections <= (self.connections + len(waitingListIps)):
                if ip in waitingListIps:
                    i = waitingListIps.index(ip) + 1
                    lastChecks[ip] = time.time()
                    # Note: Everyone below this threshhold might connect. So even if your #1 on the list and there is two free slots, you can be unlucky and don't get them.
                    if i + self.connections > config.gameMaxConnections:
                        self.exitWaitingList("Too many players online. You are at place %d on the waiting list." % i, i) 
                        return
                else:
                    waitingListIps.append(ip)
                    lastChecks[ip] = time.time()
                    self.exitWaitingList("Too many players online. You are at place %d on the waiting list." % len(waitingListIps), len(waitingListIps)) 
                    return
            self.connections += 1
            try:
                waitingListIps.remove(ip)
                del lastChecks[ip]
            except:
                pass
            
            # "Gamemaster" mode?
            gamemaster = packet.uint8()

            # Check if version is correct
            if version > config.versionMax or version < config.versionMin:
                self.exitWithError(config.versionError)
                return

            # Some weird thing with 9.7.
            try:
                # Check if there is a username (and a password)
                username = packet.string()

                characterName = packet.string()

                password = packet.string()
            except:
                self.exitWithError("Try again.")
                return

            if (not username and not config.anyAccountWillDo) or not characterName:
                self.exitWithError("Could not get your account name, or character name")
                return

            packet.pos += 6 # I don't know what this is

            # Our funny way of doing async SQL
            account = yield sql.conn.runQuery("SELECT `id`,`language` FROM `accounts` WHERE `name` = %s AND `password` = SHA1(CONCAT(`salt`, %s))", (username, password))

            if not account:
                account = game.scriptsystem.get("loginAccountFailed").runSync(None, client=self, username=username, password=password)
                if not account or account == True:
                    self.exitWithError("Invalid username or password")
                    return

            account = account[0]
            
            # Ban check.
            if game.ban.accountIsBanned(account['id']):
                self.exitWithError("Your account is banned.\n %s" % game.ban.banAccounts[account['id']].message())
                return 
            
            if not len(account) >= 2 or not account['language']:
                language = config.defaultLanguage
            else:
                language = account['language']
                
            character = yield sql.conn.runQuery("SELECT p.`id`,p.`name`,p.`world_id`,p.`group_id`,p.`account_id`,p.`vocation`,p.`health`,p.`mana`,p.`soul`,p.`manaspent`,p.`experience`,p.`posx`,p.`posy`,p.`posz`,p.`instanceId`,p.`sex`,p.`looktype`,p.`lookhead`,p.`lookbody`,p.`looklegs`,p.`lookfeet`,p.`lookaddons`,p.`lookmount`,p.`town_id`,p.`skull`,p.`stamina`, p.`storage`, p.`inventory`, p.`depot`, p.`conditions`, s.`fist`,s.`fist_tries`,s.`sword`,s.`sword_tries`,s.`club`,s.`club_tries`,s.`axe`,s.`axe_tries`,s.`distance`,s.`distance_tries`,s.`shield`,s.`shield_tries`,s.`fishing`, s.`fishing_tries`, g.`guild_id`, g.`guild_rank`, p.`balance` FROM `players` AS `p` LEFT JOIN player_skills AS `s` ON p.`id` = s.`player_id` LEFT JOIN player_guild AS `g` ON p.`id` = g.`player_id` WHERE p.account_id = %s AND p.`name` = %s AND p.`world_id` = %s", (account['id'], characterName, config.worldId))

            if not character:
                character = game.scriptsystem.get("loginCharacterFailed").runSync(None, client=self, account=account, name=characterName)
                if not character or character == True:
                    self.exitWithError("Character can't be loaded")
                    return
                
            character = character[0]
            if gamemaster and character['group_id'] < 3:
                self.exitWithError("You are not gamemaster! Turn off gamemaster mode in your IP changer.")
                return

            # Ban check.
            if isinstance(character, game.player.Player):
                if game.ban.playerIsBanned(character):
                    self.exitWithError("Your player is banned.\n %s" % game.ban.banAccounts[character.data["id"]].message())
                    return 
            elif game.ban.playerIsBanned(character['id']):
                self.exitWithError("Your player is banned.\n %s" % game.ban.banAccounts[character['id']].message())
                return 
            
            # If we "made" a new character in a script, character = the player.
            player = None
            if isinstance(character, game.player.Player):
                player = character
                game.player.allPlayers[player.name()] = player
            elif character['name'] in game.player.allPlayers:
                player = game.player.allPlayers[character['name']]
                if player.client:
                    self.exitWithError("This character is already logged in!")
                    return
                sql.runOperation("UPDATE `players` SET `lastlogin` = %s, `online` = 1 WHERE `id` = %s", (int(time.time()), character['id']))
            if player:    
                self.player = player
                if self.player.data["health"] <= 0:
                    self.player.onSpawn()
                self.player.client = self
                tile = getTile(self.player.position)
                tile.placeCreature(self.player)
                # Send update tile to refresh all players. We use refresh because it fixes the order of things as well.
                updateTile(self.player.position, tile)
                
            else:
                # Bulld the dict since we disabled automaticly doing this. Here we cast Decimal objects to int aswell (no longer automaticly either)
                yield deathlist.loadDeathList(character['id'])
                character["language"] = language
                game.player.allPlayers[character['name']] = game.player.Player(self, character)
                self.player = game.player.allPlayers[character['name']]
                if self.player.data["health"] <= 0:
                    self.player.onSpawn()

                try:
                    tile = getTile(self.player.position)
                    tile.placeCreature(self.player)
                    # Send update tile to refresh all players. We use refresh because it fixes the order of things as well.
                    updateTile(self.player.position, tile)
                        
                except AttributeError:
                    self.player.position = Position(*game.map.mapInfo.towns[1][1])
                    tile = getTile(self.player.position)
                    tile.placeCreature(self.player)
                    # Send update tile to refresh all players. We use refresh because it fixes the order of things as well.
                    updateTile(self.player.position, tile)
                        
                # Update last login
                sql.runOperation("UPDATE `players` SET `lastlogin` = %s WHERE `id` = %s", (int(time.time()), character['id']))

            self.packet = self.player.packet
            self.player.sendFirstPacket()
            self.ready = True # We can now accept other packages

            # Call the login script
            game.scriptsystem.get("login").runSync(self.player)
            
            # If we got a waiting list, now is a good time to verify the list
            if lastChecks:
                checkTime = time.time()
                for entry in lastChecks:
                    if checkTime - lastChecks[entry] > 3600:
                        waitingListIps.remove(entry)
                        del lastChecks[entry]
                        
        elif packetType == 0x00 and self.transport.getPeer().host in config.executeProtocolIps:
            self.gotFirst = False
            t = TibiaPacket()
            if not config.executeProtocolAuthKeys:
                self.ready = 2
            try:
                while True:
                    op = packet.string()
                    print op
                    if op == "CALL" and self.ready == 2:
                        print "do this"
                        result = yield game.functions.executeCode(packet.string())
                        
                        t.string(result)
                    elif op == "AUTH":
                        print "auth"
                        result = packet.string() in config.executeProtocolAuthKeys
                        if result:
                            t.string("True")
                            self.ready = 2
                        else:
                            t.string("False")
            except struct.error:
                pass # End of the line
            t.send(self)
Example #4
0
    def onFirstPacket(self, packet):
        packetType = packet.uint8()
        IN_TEST = False

        if packetType == 0xFF:
            # Special case for tests.
            IN_TEST = True

        if packetType == 0x0A and not self.ready:
            packet.pos += 2  # OS 0x00 and 0x01
            #packet.uint16()
            version = packet.uint16()  # Version int

            if version >= 972:
                version = packet.uint32()
                packet.uint8()  # Client type.

            self.protocol = game.protocol.getProtocol(version)
            self.version = version
            print "Client protocol version %d" % version

            if not self.protocol:
                log.msg("Trying to load a invalid protocol")
                self.transport.loseConnection()
                return

            if not IN_TEST:
                if (len(packet.data) -
                        packet.pos) == 128:  # RSA 1024 is always 128
                    packet.data = otcrypto.decryptRSA(packet.getData(
                    ))  # NOTICE: Should we do it in a seperate thread?
                    packet.pos = 0  # Reset position

                else:
                    log.msg("RSA, length != 128 (it's %d)" %
                            (packet.length - packet.pos))
                    self.transport.loseConnection()
                    return

                if not packet.data or packet.uint8(
                ):  # RSA needs to decrypt just fine, so we get the data, and the first byte should be 0
                    log.msg("RSA, first char != 0")
                    self.transport.loseConnection()
                    return

                # Set the XTEA key
                k = (packet.uint32(), packet.uint32(), packet.uint32(),
                     packet.uint32())
                sum = 0
                self.xtea = {}
                for x in xrange(32):
                    self.xtea[x] = sum + k[sum & 3] & 0xffffffff
                    sum = (sum + 0x9E3779B9) & 0xffffffff
                    self.xtea[32 + x] = sum + k[sum >> 11 & 3] & 0xffffffff

            ip = self.transport.getPeer().host

            # Ban check.
            if game.ban.ipIsBanned(ip):
                self.exitWithError("Your ip is banned.\n %s" %
                                   game.ban.banIps[ip].message())
                return

            if config.gameMaxConnections <= (self.connections +
                                             len(waitingListIps)):
                if ip in waitingListIps:
                    i = waitingListIps.index(ip) + 1
                    lastChecks[ip] = time.time()
                    # Note: Everyone below this threshhold might connect. So even if your #1 on the list and there is two free slots, you can be unlucky and don't get them.
                    if i + self.connections > config.gameMaxConnections:
                        self.exitWaitingList(
                            "Too many players online. You are at place %d on the waiting list."
                            % i, i)
                        return
                else:
                    waitingListIps.append(ip)
                    lastChecks[ip] = time.time()
                    self.exitWaitingList(
                        "Too many players online. You are at place %d on the waiting list."
                        % len(waitingListIps), len(waitingListIps))
                    return
            self.connections += 1
            try:
                waitingListIps.remove(ip)
                del lastChecks[ip]
            except:
                pass

            # "Gamemaster" mode?
            gamemaster = packet.uint8()

            # Check if version is correct
            if version > config.versionMax or version < config.versionMin:
                self.exitWithError(config.versionError)
                return

            # Some weird thing with 9.7.
            try:
                # Check if there is a username (and a password)
                username = packet.string()

                characterName = packet.string()

                password = packet.string()
            except:
                self.exitWithError("Try again.")
                return

            if (not username
                    and not config.anyAccountWillDo) or not characterName:
                self.exitWithError(
                    "Could not get your account name, or character name")
                return

            packet.pos += 6  # I don't know what this is

            # Our funny way of doing async SQL
            account = yield sql.conn.runQuery(
                "SELECT `id`,`language` FROM `accounts` WHERE `name` = %s AND `password` = SHA1(CONCAT(`salt`, %s))",
                (username, password))

            if not account:
                account = game.scriptsystem.get("loginAccountFailed").runSync(
                    None, client=self, username=username, password=password)
                if not account or account == True:
                    self.exitWithError("Invalid username or password")
                    return

            account = account[0]

            # Ban check.
            if game.ban.accountIsBanned(account['id']):
                self.exitWithError(
                    "Your account is banned.\n %s" %
                    game.ban.banAccounts[account['id']].message())
                return

            if not len(account) >= 2 or not account['language']:
                language = config.defaultLanguage
            else:
                language = account['language']

            character = yield sql.conn.runQuery(
                "SELECT p.`id`,p.`name`,p.`world_id`,p.`group_id`,p.`account_id`,p.`vocation`,p.`health`,p.`mana`,p.`soul`,p.`manaspent`,p.`experience`,p.`posx`,p.`posy`,p.`posz`,p.`instanceId`,p.`sex`,p.`looktype`,p.`lookhead`,p.`lookbody`,p.`looklegs`,p.`lookfeet`,p.`lookaddons`,p.`lookmount`,p.`town_id`,p.`skull`,p.`stamina`, p.`storage`, p.`inventory`, p.`depot`, p.`conditions`, s.`fist`,s.`fist_tries`,s.`sword`,s.`sword_tries`,s.`club`,s.`club_tries`,s.`axe`,s.`axe_tries`,s.`distance`,s.`distance_tries`,s.`shield`,s.`shield_tries`,s.`fishing`, s.`fishing_tries`, g.`guild_id`, g.`guild_rank`, p.`balance` FROM `players` AS `p` LEFT JOIN player_skills AS `s` ON p.`id` = s.`player_id` LEFT JOIN player_guild AS `g` ON p.`id` = g.`player_id` WHERE p.account_id = %s AND p.`name` = %s AND p.`world_id` = %s",
                (account['id'], characterName, config.worldId))

            if not character:
                character = game.scriptsystem.get(
                    "loginCharacterFailed").runSync(None,
                                                    client=self,
                                                    account=account,
                                                    name=characterName)
                if not character or character == True:
                    self.exitWithError("Character can't be loaded")
                    return

            character = character[0]
            if gamemaster and character['group_id'] < 3:
                self.exitWithError(
                    "You are not gamemaster! Turn off gamemaster mode in your IP changer."
                )
                return

            # Ban check.
            if isinstance(character, game.player.Player):
                if game.ban.playerIsBanned(character):
                    self.exitWithError(
                        "Your player is banned.\n %s" %
                        game.ban.banAccounts[character.data["id"]].message())
                    return
            elif game.ban.playerIsBanned(character['id']):
                self.exitWithError(
                    "Your player is banned.\n %s" %
                    game.ban.banAccounts[character['id']].message())
                return

            # If we "made" a new character in a script, character = the player.
            player = None
            if isinstance(character, game.player.Player):
                player = character
                game.player.allPlayers[player.name()] = player
            elif character['name'] in game.player.allPlayers:
                player = game.player.allPlayers[character['name']]
                if player.client:
                    self.exitWithError("This character is already logged in!")
                    return
                sql.runOperation(
                    "UPDATE `players` SET `lastlogin` = %s, `online` = 1 WHERE `id` = %s",
                    (int(time.time()), character['id']))
            if player:
                self.player = player
                if self.player.data["health"] <= 0:
                    self.player.onSpawn()
                self.player.client = self
                tile = getTile(self.player.position)
                tile.placeCreature(self.player)
                # Send update tile to refresh all players. We use refresh because it fixes the order of things as well.
                updateTile(self.player.position, tile)

            else:
                # Bulld the dict since we disabled automaticly doing this. Here we cast Decimal objects to int aswell (no longer automaticly either)
                yield deathlist.loadDeathList(character['id'])
                character["language"] = language
                game.player.allPlayers[character['name']] = game.player.Player(
                    self, character)
                self.player = game.player.allPlayers[character['name']]
                if self.player.data["health"] <= 0:
                    self.player.onSpawn()

                try:
                    tile = getTile(self.player.position)
                    tile.placeCreature(self.player)
                    # Send update tile to refresh all players. We use refresh because it fixes the order of things as well.
                    updateTile(self.player.position, tile)

                except AttributeError:
                    self.player.position = Position(
                        *game.map.mapInfo.towns[1][1])
                    tile = getTile(self.player.position)
                    tile.placeCreature(self.player)
                    # Send update tile to refresh all players. We use refresh because it fixes the order of things as well.
                    updateTile(self.player.position, tile)

                # Update last login
                sql.runOperation(
                    "UPDATE `players` SET `lastlogin` = %s WHERE `id` = %s",
                    (int(time.time()), character['id']))

            self.packet = self.player.packet
            self.player.sendFirstPacket()
            self.ready = True  # We can now accept other packages

            # Call the login script
            game.scriptsystem.get("login").runSync(self.player)

            # If we got a waiting list, now is a good time to verify the list
            if lastChecks:
                checkTime = time.time()
                for entry in lastChecks:
                    if checkTime - lastChecks[entry] > 3600:
                        waitingListIps.remove(entry)
                        del lastChecks[entry]

        elif packetType == 0x00 and self.transport.getPeer(
        ).host in config.executeProtocolIps:
            self.gotFirst = False
            t = TibiaPacket()
            if not config.executeProtocolAuthKeys:
                self.ready = 2
            try:
                while True:
                    op = packet.string()
                    print op
                    if op == "CALL" and self.ready == 2:
                        print "do this"
                        result = yield game.functions.executeCode(
                            packet.string())

                        t.string(result)
                    elif op == "AUTH":
                        print "auth"
                        result = packet.string(
                        ) in config.executeProtocolAuthKeys
                        if result:
                            t.string("True")
                            self.ready = 2
                        else:
                            t.string("False")
            except struct.error:
                pass  # End of the line
            t.send(self)
Example #5
0
def saveAll(force=False):
    """ Save everything, players, houses, global storage etc. """
    commited = False

    t = time.time()
    for player in game.player.allPlayers.values():
        result = player._saveQuery(force)
        if result:
            sql.runOperation(*result)
            commited = True

    # Global storage
    if saveGlobalStorage or force:
        for field in globalStorage:
            type = ""
            if field in jsonFields:
                data = otjson.dumps(globalStorage[field])
                type = "json"
            elif field in pickleFields:
                data = fastPickler(globalStorage[field])
                type = "pickle"
            else:
                data = globalStorage[field]

            sql.runOperation(
                "INSERT INTO `globals` (`key`, `data`, `type`) VALUES(%s, %s, %s) ON DUPLICATE KEY UPDATE `data` = %s",
                (field, data, type, data))
            commited = True

    # Houses
    if game.map.houseTiles:
        for houseId, house in game.house.houseData.iteritems():
            # House is loaded?
            if houseId in game.map.houseTiles:
                try:
                    items = house.data["items"].copy()
                except:
                    log.msg("House id %d have broken items!" % houseId)
                    items = {}  # Broken items

                for tile in game.map.houseTiles[houseId]:
                    _items = []
                    lastItem = None
                    for item in tile.bottomItems():
                        ic = item.count
                        if not item.fromMap and (ic == None or ic > 0):
                            if lastItem and lastItem.itemId == item.itemId and lastItem.stackable and lastItem.count < 100:
                                # Stack.
                                lCount = lastItem.count
                                lastItem.count = min(100, lCount + ic)
                                ic -= lastItem.count - lCount
                                item.count = ic
                            if ic or ic == None:
                                _items.append(item)
                                lastItem = item
                    _items.reverse()
                    items[tile.position] = _items

                if items != house.data["items"]:
                    house.data["items"] = items
                    house.save = True  # Force save
                if house.save:
                    log.msg("Saving house ", houseId)
                    sql.runOperation(
                        "UPDATE `houses` SET `owner` = %s,`guild` = %s,`paid` = %s, `data` = %s WHERE `id` = %s",
                        (house.owner, house.guild, house.paid,
                         fastPickler(house.data) if house.data else '',
                         houseId))
                    house.save = False
                    commited = True
                else:
                    log.msg("Not saving house", houseId)

    if force:
        log.msg("Full (forced) save took: %f" % (time.time() - t))

    elif commited:
        log.msg("Full save took: %f" % (time.time() - t))
Example #6
0
def saveAll(force=False):
    """ Save everything, players, houses, global storage etc. """
    commited = False
    
    t = time.time()
    for player in game.player.allPlayers.values():
        result = player._saveQuery(force)
        if result:
            sql.runOperation(*result)
            commited = True

    # Global storage
    if saveGlobalStorage or force:
        for field in globalStorage:
            type = ""
            if field in jsonFields:
                data = otjson.dumps(globalStorage[field])
                type = "json"
            elif field in pickleFields:
                data = fastPickler(globalStorage[field])
                type = "pickle"
            else:
                data = globalStorage[field]
                
            sql.runOperation("INSERT INTO `globals` (`key`, `data`, `type`) VALUES(%s, %s, %s) ON DUPLICATE KEY UPDATE `data` = %s", (field, data, type, data))
            commited = True
            
    # Houses
    if game.map.houseTiles:
        for houseId, house in game.house.houseData.iteritems():
            # House is loaded?
            if houseId in game.map.houseTiles:
                try:
                    items = house.data["items"].copy()
                except:
                    log.msg("House id %d have broken items!" % houseId)
                    items = {} # Broken items
                    
                for tile in game.map.houseTiles[houseId]:
                    _items = []
                    lastItem = None
                    for item in tile.bottomItems():
                        ic = item.count
                        if not item.fromMap and (ic == None or ic > 0):
                            if lastItem and lastItem.itemId == item.itemId and lastItem.stackable and lastItem.count < 100:
                                    # Stack.
                                    lCount = lastItem.count
                                    lastItem.count = min(100, lCount + ic)
                                    ic -= lastItem.count - lCount
                                    item.count = ic
                            if ic or ic == None:
                                _items.append(item)
                                lastItem = item
                    _items.reverse()                    
                    items[tile.position] = _items

                if items != house.data["items"]:
                    house.data["items"] = items
                    house.save = True # Force save
                if house.save:
                    log.msg("Saving house ", houseId)
                    sql.runOperation("UPDATE `houses` SET `owner` = %s,`guild` = %s,`paid` = %s, `data` = %s WHERE `id` = %s", (house.owner, house.guild, house.paid, fastPickler(house.data) if house.data else '', houseId))
                    house.save = False
                    commited = True
                else:
                    log.msg("Not saving house", houseId)
        
    if force:        
        log.msg("Full (forced) save took: %f" % (time.time() - t))

    elif commited:       
        log.msg("Full save took: %f" % (time.time() - t))