def changeOwner(self, tran, obj, ownerID, force = 0): oldOwnerID = obj.owner if obj.owner == ownerID: # the owner is the same return elif obj.owner != OID_NONE and force == 0: # this planet is already owned! # TODO resolve conflict (based on player relations) raise GameException('Planet is already owned by another commander.') elif obj.owner != OID_NONE and force == 1: # remove planet from old owner try: oldOwner = tran.db[obj.owner] oldOwner.planets.remove(obj.oid) if tran.db.has_key(obj.owner): Utils.sendMessage(tran, obj, MSG_LOST_PLANET, obj.oid, None) except Exception: log.warning("Cannot remove planet from owner", obj.oid, obj.owner) oldOwnerID = OID_NONE # reset timer obj.ownerSince = tran.db[OID_UNIVERSE].turn # add planet to new owner's empire if ownerID != OID_NONE: newOwner = tran.db[ownerID] newOwner.planets.append(obj.oid) # reset some attributes obj.owner = ownerID obj.revoltLen = 0 # no revolt obj.prodQueue = [] # clear production queue if ownerID != OID_NONE: # notify player Utils.sendMessage(tran, obj, MSG_GAINED_PLANET, obj.oid, None)
def _checkValidity(ship, tech, installations, equipCounter, raiseExs): if not raiseExs: return # check min hull req elif tech.minHull > ship.combatClass: log.warning("Cannot add tech", tech.id, tech.name) raise GameException("Minimum hull requirement not satisfied.") # check max hull req elif tech.maxHull < ship.combatClass: log.warning("Cannot add tech", tech.id, tech.name) raise GameException("Maximum hull requirement not satisfied.") # check maximum installations elif tech.maxInstallations and installations[ tech.id] > tech.maxInstallations: raise GameException( "Maximum number of equipment installations exceeded.") #check maximum type installations elif tech.subtype == "seq_mod" and tech.equipType in Rules.maxEquipType: try: equipCounter[tech.equipType] += 1 except KeyError: equipCounter[tech.equipType] = 1 if equipCounter[tech.equipType] > Rules.maxEquipType[tech.equipType]: raise GameException( "Maximum number of restricted type equipment installations exceeded: %s." % tech.equipType)
def getMessages(): # construct list of mailboxes mailboxes = [] mailboxes.append((db.playerID, getMessagesLastID(db.playerID))) for galaxyID in getPlayer().galaxies: mailboxes.append((galaxyID, getMessagesLastID(galaxyID))) mailboxes.append((OID_UNIVERSE, getMessagesLastID(OID_UNIVERSE))) # get data data = cmdProxy.multiGetMsgs(OID_UNIVERSE, mailboxes) # process new = 0 now = time.time() for objID, messages in data: obj = get(objID) # add new for message in messages: #@log.debug("Got message ID", message["id"]) if message["id"] not in obj._messages: if message["forum"] != "OUTBOX": message["readed"] = 0 message["replied"] = 0 else: message["readed"] = 1 message["replied"] = 0 obj._messagesLastID = max(message["id"], obj._messagesLastID) obj._messages[message["id"]] = message new += 1 else: log.warning("Got duplicated message", message) if new > 0: callbackObj.onNewMessages(new) return new
def getMsgText(msgID, data): msg, transform, severity = msgData.get(msgID, (None, None, None)) # create default messages if not msg: return _('ERROR\nMissing text for msg %d: %s') % (msgID, repr(data)) # there is message text -> create message # force unicode msg = _(msg) if data == None: return msg try: # tranform data newData = {} if not (type(data) == types.ListType or type(data) == types.TupleType): data = (data,) if transform: index = 1 for tranFunc in transform: newData[str(index)] = tranFunc(data[index - 1]) index += 1 else: index = 1 for item in data: newData[str(index)] = item index += 1 text = msg % newData except Exception, e: # wrong arguments -> default message log.warning("Error while formating message") return _('ERROR\nWrong format for msg %d: %s\nException: %s: %s\nFormat: %s') % (msgID, repr(data), str(e.__class__), str(e), msg)
def update(self, tran, obj): if obj.impactDelay > Rules.asteroidImpactDelay: # delete me self.cmd(obj).disbandFleet(tran, obj) return # closest system if not hasattr(obj, "closeSystem") or not tran.db.has_key(obj.closeSystem): if obj.orbiting == OID_NONE: log.warning("No close system for asteroid", obj.oid) # select any system systemID = tran.db[tran.db[OID_UNIVERSE].galaxies[0]].systems[0] obj.closeSystem = systemID else: obj.closeSystem = obj.orbiting system = tran.db[obj.closeSystem] if system.type == T_SYSTEM: if obj.oid not in system.closeFleets: system.closeFleets.append(obj.oid) else: log.debug("IAsteroid - invalid orbiting", obj.orbiting) self.cmd(obj).disbandFleet(tran, obj) return # verify close system if tran.db.has_key(obj.closeSystem): system = tran.db[obj.closeSystem] if system.type == T_SYSTEM: if obj.oid not in system.closeFleets: #@log.debug("Adding fleet", obj.oid, "into closeFleets", system.oid) system.closeFleets.append(obj.oid) else: obj.closeSystem = OID_NONE else: obj.closeSystem = OID_NONE
def getMsgText(msgID, data): msg, transform, severity = msgData.get(msgID, (None, None, None)) # create default messages if not msg: return _('ERROR\nMissing text for msg %d: %s') % (msgID, repr(data)) # there is message text -> create message # force unicode msg = _(msg) if data == None: return msg try: # tranform data newData = {} if not (type(data) == types.ListType or type(data) == types.TupleType): data = (data, ) if transform: index = 1 for tranFunc in transform: newData[str(index)] = tranFunc(data[index - 1]) index += 1 else: index = 1 for item in data: newData[str(index)] = item index += 1 text = msg % newData except Exception, e: # wrong arguments -> default message log.warning("Erorr while formating message") return _( 'ERROR\nWrong format for msg %d: %s\nException: %s: %s\nFormat: %s' ) % (msgID, repr(data), str(e.__class__), str(e), msg)
def recordScanLevel(self, tran, obj, scanPwr, player, contactType): if obj.owner == player.oid: log.warning("Scan on own asteroid!", obj.oid) return if scanPwr >= Rules.level1InfoScanPwr: self.cmd(player).addObjectToMap(tran, player, obj, scanPwr, Const.CONTACT_NONE)
def playMusic(): if musicEnabled: try: if pygame.mixer.music.get_busy() == False: pygame.mixer.music.play(-1) except pygame.error: log.warning("Cannot play music")
def __call__(self, *args): if self.client.msgHandler: self.client.msgHandler(MSG_CMD_BEGIN, None) # retry 'turn in progress' and server restart situations retries = 10 ok = 0 while retries > 0: try: result = self.processCall(args) ok = 1 break except ServerStatusException as e: log.warning("Cannot complete request - retrying...") retries -= 1 time.sleep(1) # this was commented out except Exception as e: log.warning("Cannot complete request") if self.client.msgHandler: self.client.msgHandler(MSG_CMD_END, None) raise e if self.client.msgHandler: self.client.msgHandler(MSG_CMD_END, None) if ok: return result else: raise IClientException('Cannot send request to the server')
def update(self, tran, obj): if obj.impactDelay > Rules.asteroidImpactDelay: # delete me self.cmd(obj).disbandFleet(tran, obj) return # closest system if not hasattr(obj, "closeSystem") or not tran.db.has_key( obj.closeSystem): if obj.orbiting == Const.OID_NONE: log.warning("No close system for asteroid", obj.oid) # select any system systemID = tran.db[tran.db[ Const.OID_UNIVERSE].galaxies[0]].systems[0] obj.closeSystem = systemID else: obj.closeSystem = obj.orbiting system = tran.db[obj.closeSystem] if system.type == Const.T_SYSTEM: if obj.oid not in system.closeFleets: system.closeFleets.append(obj.oid) else: log.debug("IAsteroid - invalid orbiting", obj.orbiting) self.cmd(obj).disbandFleet(tran, obj) return # verify close system if tran.db.has_key(obj.closeSystem): system = tran.db[obj.closeSystem] if system.type == Const.T_SYSTEM: if obj.oid not in system.closeFleets: #@log.debug("Adding fleet", obj.oid, "into closeFleets", system.oid) system.closeFleets.append(obj.oid) else: obj.closeSystem = Const.OID_NONE else: obj.closeSystem = Const.OID_NONE
def processINITPhase(self, tran, obj, data): try: ## find active/inactive pacts # set all active/on pacts to active for playerID in obj.players: #@log.debug("Processing player", playerID) player = tran.db[playerID] for partyID in player.diplomacyRels: #@log.debug("Processing party", partyID) dipl = player.diplomacyRels[partyID] for pactID in dipl.pacts.keys(): if pactID not in Rules.pactDescrs: # this is invalid pactID log.debug(playerID, "Deleting invalid pact with", partyID, "pact", pactID) del dipl.pacts[pactID] continue if dipl.pacts[pactID][0] > PACT_OFF: dipl.pacts[pactID][0] = PACT_ACTIVE # inactivate all pact that does not satisfy conditions changed = 1 defaultPact = [PACT_OFF] while changed: changed = 0 log.debug("Inactivate pacts iteration starting...") for playerID in obj.players: #@log.debug("Processing player", playerID) player = tran.db[playerID] # all parties of a player for partyID in player.diplomacyRels: #@log.debug("Processing party", partyID) party = tran.db[partyID] partyDipl = party.diplomacyRels.get(playerID, None) if not partyDipl: continue dipl = player.diplomacyRels[partyID] # correct relations dipl.relation = min(dipl.relation, partyDipl.relation) # all pacts with party for pactID in dipl.pacts: # check validity interval pactSpec = Rules.pactDescrs[pactID] if (dipl.relation < pactSpec.validityInterval[0] or \ dipl.relation > pactSpec.validityInterval[1]) and \ dipl.pacts[pactID][0] == PACT_ACTIVE: #@log.debug("Inactivating pact (validity interval)", playerID, pactID) dipl.pacts[pactID][0] = PACT_INACTIVE changed = 1 # check conditions for the pact if pact is active if dipl.pacts[pactID][0] == PACT_ACTIVE: for condPactID in dipl.pacts[pactID][1:]: #@log.debug("Checking", playerID, pactID, "against", partyID, condPactID) if partyDipl and partyDipl.pacts.get(condPactID, defaultPact)[0] != PACT_ACTIVE: dipl.pacts[pactID][0] = PACT_INACTIVE changed = 1 except Exception: log.warning("Cannot process diplomacy initialization") # TODO - send notifications if pacts are changed # remove old messages self.cmd(obj).deleteOldMsgs(tran, obj) return obj.players[:] + [OID_NATURE]
def moveToWormhole(self, tran, obj, targetID): origin = tran.db[targetID] if not (obj.x==origin.x and obj.y==origin.y): if not self.cmd(obj).moveToTarget(tran, obj, targetID): return 0 #ship hasn't arrived # enter wormhole if origin.type == T_WORMHOLE: #is wormhole, now enter it! destinationWormHole = tran.db[origin.destinationOid] if destinationWormHole.oid == targetID: return 1 if obj.oid not in destinationWormHole.fleets: destinationWormHole.fleets.append(obj.oid) if obj.oid not in destinationWormHole.closeFleets: destinationWormHole.closeFleets.append(obj.oid) if obj.oid in origin.fleets: origin.fleets.remove(obj.oid) if obj.oid in origin.closeFleets: origin.closeFleets.remove(obj.oid) obj.closeSystem = destinationWormHole.oid log.debug('IFleet', 'Entering Wormhole - destination ', destinationWormHole.oid) obj.orbiting = destinationWormHole.oid obj.x = destinationWormHole.x obj.y = destinationWormHole.y destinationWormHole.scannerPwrs[obj.owner] = max(obj.scannerPwr, destinationWormHole.scannerPwrs.get(obj.owner, 0)) Utils.sendMessage(tran, obj, MSG_ENTERED_WORMHOLE, destinationWormHole.oid , (origin.name,destinationWormHole.name)) arrived = 1 else: #is not wormhole...how'd you ever execute this command? Or is there some weird "terraform wormhole" technology we never forsaw? log.warning('IFleet', 'Cannot enter non-existant wormhole at location ', origin.oid) #Utils.sendMessage(tran, obj, MSG_ENTERED_WORMHOLE, destinationWormHole.oid , (origin.name,destinationWormHole.name)) arrived = 1 #since the move part was successful, just ignore this problem for the player return arrived
def stopMusic(): try: if pygame.mixer.music.get_busy() == True: pygame.mixer.music.fadeout(1000) except pygame.error: log.warning("Cannot stop music") except error: pass
def verifyPassword(self, login, password): """Called by Authentication module, returns 0 if password is valid""" try: return self.rpc.ospace.verify_user(login, password) except xmlrpclib.Fault, f: if f.faultString == "Bad login/pass combination.": return False log.warning("Cannot complete Wordpress XML-RPC call")
def getObjectsInSpace(self, tran, obj): inSpace = obj.closeFleets[:] for fleetID in obj.fleets: try: inSpace.remove(fleetID) except ValueError: log.warning(obj.oid, "Cannot remove fleet from closeFleets", fleetID, obj.fleets, obj.closeFleets) return inSpace
def onUpdateFinished(): global progressDlg log.debug("onUpdateFinished") try: progressDlg.Close() progressDlg.Destroy() progressDlg = None except: log.warning("Cannot close ProgressDialog window")
def onUpdateFinished(): global progressDlg log.debug("onUpdateFinished") try: progressDlg.hide() except: log.warning("Cannot delete progressDlg window") for dialog in gdata.updateDlgs: dialog.update()
def setMusicVolume(volume): global musicVolume global musicEnabled musicVolume = volume try: if musicEnabled : pygame.mixer.music.set_volume(volume) except: log.warning("Cannot set music volume")
def updateDatabase(clearDB=0): try: return updateDatabaseUnsafe(clearDB) except: log.warning("Cannot update database") # again with clear callbackObj.onUpdateFinished() messageEnable(SMESSAGE_NEWTURN) messageEnable(SMESSAGE_NEWMESSAGE) return updateDatabaseUnsafe(clearDB=1, force=1)
def playSound(style): if soundEnabled and style in sounds: try: if sounds[style]["sound"] == None: filename = sounds[style]["fname"] sounds[style]["sound"] = pygame.mixer.Sound(filename) sounds[style]["sound"].set_volume(soundVolume) sounds[style]["sound"].play() except pygame.error: log.warning("Cannot play sound", style)
def updateDatabase(clearDB = 0): try: return updateDatabaseUnsafe(clearDB) except: log.warning("Cannot update database") # again with clear callbackObj.onUpdateFinished() messageEnable(Const.SMESSAGE_NEWTURN) messageEnable(Const.SMESSAGE_NEWMESSAGE) return updateDatabaseUnsafe(clearDB = 1, force = 1)
def removePlayer(self, playerID): log.debug('removePlayer', playerID) player = self.db[playerID] # unregister player self.unregisterPlayer(player) # remove player from universe universe = self.db[OID_UNIVERSE] try: universe.players.remove(playerID) except ValueError: log.warning("Cannot remove player", playerID)
def update(self, tran, obj): # clean up negative build queues and fix missing demolishStruct keys loopAgain = True while loopAgain: deletedKey = False for key in range(0,len(obj.prodQueue)): item = obj.prodQueue[key] if not hasattr(item, "demolishStruct"): item.demolishStruct = OID_NONE if item.quantity < 0: log.warning("Deleting negative item queue on", obj.oid,"for player",obj.owner) if item.isShip: tech = player.shipDesigns[item.techID] else: tech = Rules.techs[item.techID] player = tran.db[obj.owner] for sr in tech.buildSRes: player.stratRes[sr] = player.stratRes.get(sr, 0) + item.quantity #quantity negative, so subtracting strat resources # del the bad item. Since this changes indicies, start the check over again on remaining items deletedKey = True del obj.prodQueue[key] break # no more bad entries found; break the while loop if not deletedKey: loopAgain = False # TODO: remove in 0.5.34 for struct in obj.slots: if len(struct) < 4: # add oper status struct.append(100) # change owner to OID_NONE when owner is invalid if obj.owner != OID_NONE: player = tran.db.get(obj.owner, None) if not player or player.type not in PLAYER_TYPES or obj.oid not in player.planets: # TODO this can be a probem - this planet cannot be attacked! log.warning("Changing owner to OID_NONE - invalid owner", obj) self.cmd(obj).changeOwner(tran, obj, OID_NONE, force = 1) # kill all population obj.storPop = 0 return # TODO: remove in 0.5.65 obj.storBio = int(obj.storBio) obj.storEn = int(obj.storEn) # TODO: remove in 0.5.69 if not hasattr(obj, "globalQueue"): obj.globalQueue = 0 # check compOf if not tran.db.has_key(obj.compOf) or tran.db[obj.compOf].type != T_SYSTEM: log.debug("CONSISTENCY invalid compOf for planet", obj.oid) # fix signature obj.signature = 75 if not hasattr(obj, 'moraleModifiers'): obj.moraleModifiers = [ 0.0 , 0.0 , 0.0 , 0.0 ]
def removePlayer(self, playerID): log.debug('removePlayer', playerID) player = self.db[playerID] # unregister player self.unregisterPlayer(player) # remove player from universe universe = self.db[Const.OID_UNIVERSE] try: universe.players.remove(playerID) except ValueError: log.warning("Cannot remove player", playerID)
def login(self, gameID, login, password): self.gameID = gameID.encode("ascii") # hash password with challenge passwd = ige.Authentication.encode(password, self.challenge) #@log.debug(login, password, passwd) try: IProxy('login', None, self)(login, passwd, self.hostID) except: log.warning('login failed') return 0 log.debug('login succeeded') self.logged = 1 return 1
def createSounds(section, option): global sounds name = "%s-%s" % (section[:-4], option[6:]) filename = os.path.join(skinDir, config.get(section, option)) try: sounds[name] = {} sounds[name]["fname"] = filename if soundEnabled: sounds[name]["sound"] = pygame.mixer.Sound(filename) else: sounds[name]["sound"] = None except pygame.error: log.warning("Cannot create sound", name, filename)
def login(self, gameID, login, password): self.gameID = gameID.encode("ascii") # hash password with challenge passwd = md5.new(password + self.challenge).hexdigest() #@log.debug(login, password, passwd) try: apply(IProxy('login', None, self), (login, passwd, self.hostID)) except: log.warning('login failed') return 0 log.debug('login succeeded') self.logged = 1 return 1
def performDownload(self, updateDirectory): """Download zip with new version""" log.debug('Downloading new version') self.setProgress('Preparing download...', 0, 1) # setup proxies proxies = {} if gdata.config.proxy.http != None: proxies['http'] = gdata.config.proxy.http log.debug('Using proxies', proxies) # get file try: # open URL opener = urllib.build_opener(urllib.ProxyHandler(proxies)) # it unfortunately is not completely reliable for i in range(1, 5): try: ifh = opener.open(self.url) log.debug("Retrieving URL", ifh.geturl()) # download file total = int(ifh.info()["content-length"]) basename = re.search( '(?<=filename=).*', ifh.info()["content-disposition"]).group(0) break except KeyError: pygame.time.wait(1) if not basename: log.message("URL is not a file") self.reportFailure(_("Error: URL does not point to a file.")) return filename = os.path.join(updateDirectory, basename) log.debug("Downloading file %s of size %d" % (filename, total)) ofh = open(filename, "wb") # download and report progress downloaded = 0 while True: data = ifh.read(100000) if not data: break ofh.write(data) downloaded += len(data) log.debug("Download progress", downloaded, total) self.setProgress("Downloading update...", downloaded, total) ifh.close() ofh.close() return filename except urllib.error.URLError as e: log.warning("Cannot download file") self.reportFailure( _("Cannot finish download: %(s)") % str(e.reason)) return None
def delete(self, tran, obj): log.debug("Deleting player", obj.oid) # delete relations for playerID in tran.db[OID_UNIVERSE].players: player = tran.db[playerID] self.cmd(player).deleteDiplomacyWith(tran, player, obj.oid) # delete fleets for fleetID in obj.fleets: fleet = tran.db[fleetID] self.cmd(fleet).disbandFleet(tran, fleet) try: tran.gameMngr.removePlayer(obj.oid) except Exception: log.warning("Cannot remove player")
def main(): log.message("Starting IGE - Outer Space Messager Client version", Ver.versionString) log.debug("sys.path =", sys.path) log.debug("os.name =", os.name) # create required directories if not os.path.exists('var'): os.mkdir('var') # parse configuration gdata.config = Config('var/osci.ini') # default configuration if gdata.config.game.server == None: gdata.config.game.server = 'www.ospace.net:9080' # prepare internationalization if gdata.config.client.language == None: gdata.config.client.language = 'en' language = gdata.config.client.language import gettext try: tran = gettext.translation('OSPACE', 'res', languages=[language]) except IOError: log.warning('OSCI', 'Cannot find catalog for', language) log.message('OSCI', 'Installing null translations') tran = gettext.NullTranslations() tran.install(unicode=1) log.message('OSCI', 'Translations installed for %s languaage' % language) # client from igeclient.IClient import IClientException client.initialize(gdata.config.game.server, handler) app = App(False) app.MainLoop() # write configuration log.debug("Saving configuration.") gdata.config.save('var/osci.ini') # logout client.logout() log.debug("Shut down")
def login(self, gameID, login, password): self.gameID = gameID.encode("ascii") # hash password with challenge passwd = hashlib.sha512( hashlib.sha512(password).hexdigest() + self.challenge).hexdigest() #@log.debug(login, password, passwd) try: apply(IProxy('login', None, self), (login, passwd, self.hostID)) except: log.warning('login failed') return 0 log.debug('login succeeded') self.logged = 1 return 1
def processFINALPhase(self, tran, obj, data): if not Rules.Tech.PIRATEBREWERY in obj.techs: log.warning('Adding new pirate structures to human pirate player.') self.cmd(obj).update(tran, obj) #grant the techs because something screwed up obj.govPwr = Rules.pirateGovPwr IPlayer.processFINALPhase(self, tran, obj, data) # get fame every 1:00 turns if tran.db[Const.OID_UNIVERSE].turn % Rules.turnsPerDay == 0: Utils.sendMessage(tran, obj, Const.MSG_GAINED_FAME, obj.oid, Rules.pirateSurvivalFame) obj.pirateFame += Rules.pirateSurvivalFame # fix goverment power obj.govPwrCtrlRange = 10000 # bonus for gained fame obj.prodEff += obj.pirateFame / 100.0
def loadMusic(file): if musicEnabled and pygame.mixer.music.get_busy() == False: global themeMusic if file != None: musicFile = "res.ext/music/" + file elif themeMusic != None: musicFile = "res.ext/music/" + themeMusic else: musicFile = "res.ext/music/riddleofsteel.ogg" if os.path.exists(musicFile): try: pygame.mixer.music.load(musicFile) except pygame.error: log.warning("Cannot load music ",musicFile)
def connect(self, login): # to enable sending commands self.connected = 1 # create connection log.debug('Connecting to the server', self.server) # send hello message log.debug('Sending hello') try: self.sid, self.challenge = self.hello(login, self.clientIdent) except: log.warning('Cannot connect to the server.') self.connected = 0 raise IClientException('Cannot connect to the server.') log.debug(self.sid, self.challenge)
def connect(self): # to enable sending commands self.connected = 1 # create connection log.debug('Connecting to the server', self.server) # send hello message log.debug('Sending hello') try: self.sid, self.challenge = self.hello(self.clientIdent) except: log.warning('Cannot connect to the server.') self.connected = 0 raise IClientException('Cannot connect to the server.') log.debug(self.sid, self.challenge)
def disbandFleet(self, tran, obj): log.debug('IFleet', 'disbanding fleet', obj.oid, 'of player', obj.owner) # remove from player's fleets try: if obj.owner != OID_NONE: tran.db[obj.owner].fleets.remove(obj.oid) except Exception: log.warning('IFleet', 'disbandFleet: cannot remove fleet from owner\'s fleet') pass # remove from orbit # remove from index if necessary if obj.orbiting != OID_NONE: try: if tran.db.has_key(obj.orbiting): tran.db[obj.orbiting].fleets.remove(obj.oid) except Exception: log.warning('IFleet', 'disbandFleet: cannot remove fleet from system.') pass # remove from close fleets if obj.closeSystem != OID_NONE: try: if tran.db.has_key(obj.closeSystem): tran.db[obj.closeSystem].closeFleets.remove(obj.oid) except Exception: log.warning("IFleet", "disbandFleet: cannot remove fleet from the close system.") # delete from database try: tran.db.delete(obj.oid) except KeyError: log.warning('IFleet', 'disbandFleet: cannot remove fleet from database.')
def main(): log.message("Starting IGE - Outer Space Messager Client version", Ver.versionString) log.debug("sys.path =", sys.path) log.debug("os.name =", os.name) # create required directories if not os.path.exists('var'): os.mkdir('var') # parse configuration gdata.config = Config('var/osci.ini') # default configuration if gdata.config.game.server == None: gdata.config.game.server = 'www.ospace.net:9080' # prepare internationalization if gdata.config.client.language == None: gdata.config.client.language = 'en' language = gdata.config.client.language import gettext try: tran = gettext.translation('OSPACE', 'res', languages = [language]) except IOError: log.warning('OSCI', 'Cannot find catalog for', language) log.message('OSCI', 'Installing null translations') tran = gettext.NullTranslations() tran.install(unicode = 1) log.message('OSCI', 'Translations installed for %s languaage' % language) # client from igeclient.IClient import IClientException client.initialize(gdata.config.game.server, handler) app = App(False) app.MainLoop() # write configuration log.debug("Saving configuration.") gdata.config.save('var/osci.ini') # logout client.logout() log.debug("Shut down")
def performDownload(self, updateDirectory): """Download zip with new version""" log.debug('Downloading new version') self.setProgress('Preparing download...', 0, 1) # setup proxies proxies = {} if gdata.config.proxy.http != None: proxies['http'] = gdata.config.proxy.http log.debug('Using proxies', proxies) # get file try: # open URL opener = urllib2.build_opener(urllib2.ProxyHandler(proxies)) # it unfortunately is not completely reliable for i in xrange(1,5): try: ifh = opener.open(self.url) log.debug("Retrieving URL", ifh.geturl()) # download file total = int(ifh.info()["content-length"]) basename = re.search('(?<=filename=).*', ifh.info()["content-disposition"]).group(0) break except KeyError: pygame.time.wait(1) if not basename: log.message("URL is not a file") self.reportFailure(_("Error: URL does not point to a file.")) return filename = os.path.join(updateDirectory, basename) log.debug("Downloading file %s of size %d" % (filename, total) ) ofh = open(filename, "wb") # download and report progress downloaded = 0 while True: data = ifh.read(100000) if not data: break ofh.write(data) downloaded += len(data) log.debug("Download progress", downloaded, total) self.setProgress("Downloading update...", downloaded, total) ifh.close() ofh.close() return filename except urllib2.URLError, e: log.warning("Cannot download file") self.reportFailure(_("Cannot finish download: %(s)") % str(e.reason)) return None
def processFINALPhase(self, tran, obj, data): if not Rules.Tech.PIRATEBREWERY in obj.techs: log.warning('Adding new pirate structures to human pirate player.') self.cmd(obj).update( tran, obj) #grant the techs because something screwed up obj.govPwr = Rules.pirateGovPwr IPlayer.processFINALPhase(self, tran, obj, data) # get fame every 1:00 turns if tran.db[Const.OID_UNIVERSE].turn % Rules.turnsPerDay == 0: Utils.sendMessage(tran, obj, Const.MSG_GAINED_FAME, obj.oid, Rules.pirateSurvivalFame) obj.pirateFame += Rules.pirateSurvivalFame # fix goverment power obj.govPwrCtrlRange = 10000 # bonus for gained fame obj.prodEff += obj.pirateFame / 100.0
def setDefaults(gdata, options): if gdata.config.client.language == None: gdata.config.client.language = 'en' if gdata.config.defaults.minfleetsymbolsize == None: gdata.config.defaults.minfleetsymbolsize = 4 if gdata.config.defaults.minplanetsymbolsize == None: gdata.config.defaults.minplanetsymbolsize = 5 if gdata.config.defaults.maxfleetsymbolsize == None: gdata.config.defaults.maxfleetsymbolsize = 0 if gdata.config.defaults.maxplanetsymbolsize == None: gdata.config.defaults.maxplanetsymbolsize = 0 if gdata.config.game.screenshot_dir is None: gdata.config.game.screenshot_dir = os.path.join( options.configDir, 'screenshots') try: os.makedirs(gdata.config.game.screenshot_dir) except OSError: pass # read Highlights if gdata.config.defaults.colors != None: for coldef in gdata.config.defaults.colors.split(' '): m = re.match('(\d+):(0[xX].*?),(0[xX].*?),(0[xX].*)', coldef) if m != None: id = int(m.group(1)) red = min(int(m.group(2), 16), 255) green = min(int(m.group(3), 16), 255) blue = min(int(m.group(4), 16), 255) gdata.playersHighlightColors[id] = (red, green, blue) else: log.warning('OSCI', 'Unrecognized highlight definition :', coldef) # read Object Keys if gdata.config.defaults.objectkeys != None: for objectkey in gdata.config.defaults.objectkeys.split(' '): m = re.match('(\d+):(\d+)', objectkey) if m != None: key = int(m.group(1)) objid = int(m.group(2)) gdata.objectFocus[key] = objid else: log.warning('OSCI', 'Unrecognized object key definition :', objectkey)
def delete(self, tran, obj): # check whether it is AI or normal player if obj.type in AI_PLAYER_TYPES: # remove AI account from the game, and record in the AI list log.debug("Removing AI account from the AI list", obj.oid) tran.gameMngr.clientMngr.removeAiAccount(obj.login) aiList = AIList(tran.gameMngr.configDir) aiList.remove(obj.login) log.debug("Deleting player", obj.oid) # delete relations for playerID in tran.db[OID_UNIVERSE].players: player = tran.db[playerID] self.cmd(player).deleteDiplomacyWith(tran, player, obj.oid) # delete fleets for fleetID in obj.fleets: fleet = tran.db[fleetID] self.cmd(fleet).disbandFleet(tran, fleet) try: tran.gameMngr.removePlayer(obj.oid) except Exception: log.warning("Cannot remove player")
def __call__(self, *args): if self.client.msgHandler: apply(self.client.msgHandler, (MSG_CMD_BEGIN, None)) # retry 'turn in progress' and server restart situations retries = 10 ok = 0 while retries > 0: try: result = self.processCall(args) ok = 1 break except ServerStatusException, e: log.warning("Cannot complete request - retrying...") retries -= 1 time.sleep(1) # this was commented out except Exception, e: log.warning("Cannot complete request") if self.client.msgHandler: apply(self.client.msgHandler, (MSG_CMD_END, None)) raise e
def onDownloadAndInstall(self, widget, action, data): """Download and run installer of the new version""" self.setProgress('Preparing download...', 0, 1) # setup proxies proxies = {} if gdata.config.proxy.http != None: proxies['http'] = gdata.config.proxy.http log.debug('Using proxies', proxies) # get file try: # open URL opener = urllib2.build_opener(urllib2.ProxyHandler(proxies)) ifh = opener.open(self.url) log.debug("Retrieving URL", ifh.geturl()) # download file total = int(ifh.info()["Content-Length"]) basename = os.path.basename(ifh.geturl()) if not basename: log.message("URL is not a file") self.reportFailure(_("Error: URL does not point to a file.")) return filename = os.path.join(self.options.configDir, basename) log.debug("Downloading file %s of size %d" % (filename, total) ) ofh = open(filename, "wb") # download and report progress downloaded = 0 while True: data = ifh.read(100000) if not data: break ofh.write(data) downloaded += len(data) log.debug("Download progress", downloaded, total) self.setProgress("Downloading update...", downloaded, total) ifh.close() ofh.close() except urllib2.URLError, e: log.warning("Cannot download file") self.reportFailure(_("Cannot finish download: %(s)") % str(e.reason)) return
def getMessages(): # construct list of mailboxes mailboxes = [] mailboxes.append((db.playerID, getMessagesLastID(db.playerID))) galaxyID = getPlayer().galaxy if galaxyID: mailboxes.append((galaxyID, getMessagesLastID(galaxyID))) mailboxes.append( (Const.OID_UNIVERSE, getMessagesLastID(Const.OID_UNIVERSE))) # get data data = cmdProxy.multiGetMsgs(Const.OID_UNIVERSE, mailboxes) # process new = 0 now = time.time() for objID, messages in data: obj = get(objID) # delete old messages TODO leave this to the user #for messageID in obj._messages.keys(): # message = obj._messages[messageID] # if message["time"] + Rules.messageTimeout < now: # del obj._messages[messageID] # add new for message in messages: #@log.debug("Got message ID", message["id"]) if message["id"] not in obj._messages: if message["forum"] != "OUTBOX": message["readed"] = 0 message["replied"] = 0 else: message["readed"] = 1 message["replied"] = 0 obj._messagesLastID = max(message["id"], obj._messagesLastID) obj._messages[message["id"]] = message new += 1 else: log.warning("Got duplicated message", message) if new > 0: callbackObj.onNewMessages(new) return new
def processINITPhase(self, tran, obj, data): for galaxyID in obj.galaxies: galaxy = tran.db[galaxyID] self.cmd(galaxy).enableTime(tran, galaxy) try: ## find active/inactive pacts # set all active/on pacts to active for playerID in obj.players: #@log.debug("Processing player", playerID) player = tran.db[playerID] for partyID in player.diplomacyRels: #@log.debug("Processing party", partyID) dipl = player.diplomacyRels[partyID] for pactID in dipl.pacts.keys(): if pactID not in Rules.pactDescrs: # this is invalid pactID log.debug(playerID, "Deleting invalid pact with", partyID, "pact", pactID) del dipl.pacts[pactID] continue if dipl.pacts[pactID][0] > Const.PACT_OFF: dipl.pacts[pactID][0] = Const.PACT_ACTIVE # inactivate all pact that does not satisfy conditions changed = 1 defaultPact = [Const.PACT_OFF] while changed: changed = 0 log.debug("Inactivate pacts iteration starting...") for playerID in obj.players: #@log.debug("Processing player", playerID) player = tran.db[playerID] # all parties of a player for partyID in player.diplomacyRels: #@log.debug("Processing party", partyID) party = tran.db[partyID] partyDipl = party.diplomacyRels.get(playerID, None) if not partyDipl: continue dipl = player.diplomacyRels[partyID] # correct relations dipl.relation = min(dipl.relation, partyDipl.relation) # all pacts with party for pactID in dipl.pacts: # check validity interval pactSpec = Rules.pactDescrs[pactID] if (dipl.relation < pactSpec.validityInterval[0] or \ dipl.relation > pactSpec.validityInterval[1]) and \ dipl.pacts[pactID][0] == Const.PACT_ACTIVE: #@log.debug("Inactivating pact (validity interval)", playerID, pactID) dipl.pacts[pactID][0] = Const.PACT_INACTIVE changed = 1 # check conditions for the pact if pact is active if dipl.pacts[pactID][0] == Const.PACT_ACTIVE: for condPactID in dipl.pacts[pactID][1:]: #@log.debug("Checking", playerID, pactID, "against", partyID, condPactID) if partyDipl and partyDipl.pacts.get(condPactID, defaultPact)[0] != Const.PACT_ACTIVE: dipl.pacts[pactID][0] = Const.PACT_INACTIVE changed = 1 except Exception: log.warning("Cannot process diplomacy initialization") # TODO - send notifications if pacts are changed # remove old messages self.cmd(obj).deleteOldMsgs(tran, obj) return obj.players[:] + [Const.OID_NATURE]
def runClient(options): # log initialization log.message("Starting Outer Space Client", ige.version.versionString) log.debug("sys.path =", sys.path) log.debug("os.name =", os.name) log.debug("sys.platform =", sys.platform) log.debug("os.getcwd() =", os.getcwd()) log.debug("sys.frozen =", getattr(sys, "frozen", None)) # create required directories if not os.path.exists(options.configDir): os.makedirs(options.configDir) log.debug("options.configDir =", options.configDir) running = 1 first = True #while running: if not first: reload(osci) # parse configuration if first: import osci.gdata as gdata else: reload(gdata) gdata.config = Config( os.path.join(options.configDir, options.configFilename)) gdata.config.game.server = options.server setDefaults(gdata, options) language = gdata.config.client.language import gettext log.debug('OSCI', 'Installing translation for:', language) if language == 'en': log.debug('OSCI', 'English is native - installing null translations') tran = gettext.NullTranslations() else: try: tran = gettext.translation('OSPACE', resources.get('translations'), languages=[language]) except IOError: log.warning('OSCI', 'Cannot find catalog for', language) log.message('OSCI', 'Installing null translations') tran = gettext.NullTranslations() tran.install(unicode=1) #initialize pygame and prepare screen if (gdata.config.defaults.sound == "yes") or (gdata.config.defaults.music == "yes"): pygame.mixer.pre_init(44100, -16, 2, 4096) os.environ['SDL_VIDEO_ALLOW_SCREENSAVER'] = '1' os.environ['SDL_DEBUG'] = '1' pygame.init() flags = pygame.SWSURFACE DEFAULT_SCRN_SIZE = (800, 600) gdata.scrnSize = DEFAULT_SCRN_SIZE if gdata.config.display.resolution == "FULLSCREEN": gdata.scrnSize = (0, 0) flags |= pygame.FULLSCREEN elif gdata.config.display.resolution is not None: width, height = gdata.config.display.resolution.split('x') gdata.scrnSize = (int(width), int(height)) if gdata.config.display.depth == None: # guess best depth bestdepth = pygame.display.mode_ok(gdata.scrnSize, flags) else: bestdepth = int(gdata.config.display.depth) # initialize screen try: screen = pygame.display.set_mode(gdata.scrnSize, flags, bestdepth) # gdata.scrnSize is used everywhere to setup windows gdata.scrnSize = screen.get_size() except pygame.error: # for example if fullscreen is selected with resolution bigger than display # TODO: as of now, fullscreen has automatic resolution gdata.scrnSize = DEFAULT_SCRN_SIZE screen = pygame.display.set_mode(gdata.scrnSize, flags, bestdepth) gdata.screen = screen log.debug('OSCI', 'Driver:', pygame.display.get_driver()) log.debug('OSCI', 'Using depth:', bestdepth) log.debug('OSCI', 'Display info:', pygame.display.Info()) pygame.mouse.set_visible(1) pygame.display.set_caption(_('Outer Space %s') % ige.version.versionString) # set icon pygame.display.set_icon( pygame.image.load(resources.get('icon48.png')).convert_alpha()) # UI stuff if first: import pygameui as ui else: reload(ui) setSkinTheme(gdata, ui) app = ui.Application(update, theme=ui.SkinableTheme) app.background = defineBackground() app.draw(gdata.screen) app.windowSurfaceFlags = pygame.SWSURFACE | pygame.SRCALPHA gdata.app = app pygame.event.clear() # resources import osci.res osci.res.initialize() # load resources import osci.dialog dlg = osci.dialog.ProgressDlg(gdata.app) osci.res.loadResources(dlg) dlg.hide() osci.res.prepareUIIcons(ui.SkinableTheme.themeIcons) while running: if first: import osci.client, osci.handler from igeclient.IClient import IClientException else: reload(osci.client) reload(osci.handler) osci.client.initialize(gdata.config.game.server, osci.handler, options) # create initial dialogs if first: import osci.dialog else: reload(osci.dialog) gdata.savePassword = gdata.config.game.lastpasswordcrypted != None if options.login and options.password: gdata.config.game.lastlogin = options.login gdata.config.game.lastpassword = options.password gdata.config.game.lastpasswordcrypted = binascii.b2a_base64( options.password).strip() gdata.config.game.autologin = '******' gdata.savePassword = '******' loginDlg = osci.dialog.LoginDlg(gdata.app) updateDlg = osci.dialog.UpdateDlg(gdata.app) # event loop update() lastSave = time.clock() # set counter to -1 to trigger Update dialog (see "if" below) counter = -1 needsRefresh = False session = 1 first = False while running and session: try: counter += 1 if counter == 0: # display initial dialog in the very first cycle updateDlg.display(caller=loginDlg, options=options) # process as many events as possible before updating evt = pygame.event.wait() evts = pygame.event.get() evts.insert(0, evt) forceKeepAlive = False saveDB = False for evt in evts: if evt.type == pygame.QUIT: running = 0 break if evt.type == ( ui.USEREVENT) and evt.action == "localExit": session = False break if evt.type == pygame.ACTIVEEVENT: if evt.gain == 1 and evt.state == 6: # pygame desktop window focus event needsRefresh = True if evt.type == pygame.KEYUP and evt.key == pygame.K_F12: if not pygame.key.get_mods() & pygame.KMOD_CTRL: running = 0 break if evt.type == pygame.KEYUP and evt.key == pygame.K_F9: forceKeepAlive = True evt = gdata.app.processEvent(evt) if gdata.app.needsUpdate() or needsRefresh: needsRefresh = False update() # keep alive connection osci.client.keepAlive(forceKeepAlive) # save DB every 4 hours in case of a computer crash # using "counter" to limit calls to time.clock() to approximately every 10-15 minutes if counter > 5000: # set this to zero so we don't display Update dialog counter = 0 if time.clock() - lastSave > 14400: saveDB = True if saveDB: osci.client.saveDB() lastSave = time.clock() except IClientException, e: osci.client.reinitialize() gdata.app.setStatus(e.args[0]) loginDlg.display(message=e.args[0]) except Exception, e: log.warning('OSCI', 'Exception in event loop') if not isinstance(e, SystemExit) and not isinstance( e, KeyboardInterrupt): log.debug("Processing exception") # handle exception import traceback, StringIO fh = StringIO.StringIO() exctype, value, tb = sys.exc_info() funcs = [entry[2] for entry in traceback.extract_tb(tb)] faultID = "%06d-%03d" % ( hash("/".join(funcs)) % 1000000, traceback.extract_tb(tb)[-1][1] % 1000, ) del tb # high level info print >> fh, "Exception ID:", faultID print >> fh print >> fh, "%s: %s" % (exctype, value) print >> fh print >> fh, "--- EXCEPTION DATA ---" # dump exception traceback.print_exc(file=fh) excDlg = osci.dialog.ExceptionDlg(gdata.app) excDlg.display(faultID, fh.getvalue()) del excDlg # reference to the dialog holds app's intance fh.close() del fh else: break