def newCity(self, peer, info): '''Checks to make sure city location is valid. If so we establish city! ''' for x in range(0, 64): for y in range(0,64): tile = self.getTile(info.positionx+x, info.positiony+y) if tile.cityid: container = proto.Container() container.newCityResponse.type = 0 container.newCityResponse.message = "A city already claims tile " + str((info.positionx+x, info.positiony+y)) messenger.send("sendData", [peer, container]) return # Grab next free id. If we are at region city limit then no build! cityids = self.cities.keys() cityid = 1 for n in range(1, self.city_limit): if n not in cityids: cityid = n break else: container = proto.Container() container.newCityResponse.type = 0 container.newCityResponse.message = "This region has reached its max limit of " + str(self.city_limit) + " cities." messenger.send("sendData", [peer, container]) return # Passed the test! Time to found! user = users.getNameFromPeer(peer) newcity = city.City(info.name, cityid, mayor = user) self.cities[cityid] = newcity updated_tiles = [] for y in range(0, 64): for x in range(0, 64): tile = self.getTile(info.positionx+x, info.positiony+y) tile.cityid = cityid updated_tiles.append(tile) container = proto.Container() container.newCityResponse.type = 1 #messenger.send("sendData", [peer, container]) print info.name, "founded with", newcity.funds #container = proto.Container() container.newCity.id = cityid container.newCity.name = info.name container.newCity.mayor = user container.newCity.population = newcity.population container.newCity.funds = newcity.funds #messenger.send("broadcastData", [container]) #container = proto.Container() for tile in updated_tiles: self.updateTile(container, tile) messenger.send("broadcastData", [container])
def sendGameState(self, peer=None): '''Sends game state. Requires full simulation pause while in progress. In this region package tiles are sent by changes in city id. No other data needs to be sent until a city is activated. ''' messenger.send("setServerState", [1]) container = proto.Container() container.gameState.name = self.name container.gameState.heightmap = base64.b64encode(self.heightmap) # Used to check for change tilecityid = -1 for tile in self.tiles: if tile.cityid != tilecityid: tilecityid = tile.cityid t = container.gameState.tiles.add() t.id = tile.id t.positionx = tile.coords[0] t.positiony = tile.coords[1] t.cityid = tile.cityid for ident, city in self.cities.items(): c = container.gameState.cities.add() c.id = ident c.name = city.name c.mayor = city.mayor c.population = city.population c.funds = city.funds if peer: messenger.send("sendData", [peer, container]) else: messenger.send("broadcastData", [container])
def unfoundCity(self, peer, ident): '''Checks permissions and, if all good, unfounds city.''' # Can't unfound the region or a city that doesn't exist logging.debug("Requesting to unfound city %s by %s" %(ident, peer)) container = proto.Container() if not ident or ident not in self.cities: container.response = "Can not unfound imaginary city." messenger.send("sendData", [peer, container]) return user = users.getNameFromPeer(peer) access = users.getType(user) if access > 1 or self.cities[ident].mayor == user: for tile in self.tiles: if tile.cityid is ident: tile.cityid = 0 self.updateTile(container, tile) del self.cities[ident] container.unfoundCity = ident messenger.send("broadcastData", [container]) else: container.response = "Lack permissions for unfounding this city." messenger.send("sendData", [peer, container]) logging.info("City %s unfounded. New city db: %s" %(ident, self.cities))
def generateRegion(self, mapName, regionName="TestRegion"): """ Generates new region filesystem """ x = True n = 1 version = "" # We spin through a versioning number system to emulate how sc4 did regions with the same name # This prevents an accedental overwrite # Information is then copied to the region in the home directory while x: if regionName + version in os.listdir(self.home + "/CityMania/Regions"): version = "[" + str(n) + "]" n += 1 else: self.regionPath = self.home + "/CityMania/Regions/" + regionName + version + "/" os.makedirs(self.regionPath) x = False try: shutil.copyfile("Maps/" + mapName + "/heightmap.png", self.regionPath + "heightmap.png") except: print "TODO: Add error message for missing map" contrainer = proto.Container() container.mapSelectError.message = "No such map name" messenger.send("broadcastData", [container]) return heightMapFile = open(self.regionPath + "heightmap.png") heightMap = heightMapFile.read() heightMapFile.close() messenger.send("generateRegion", [regionName, heightMap])
def login(name, password, peer): '''Adds new user to db. Does not auto logon. Returns 0 if not in db, 1 if password does not match, 2 if success''' if password != userdb[name].password: container = proto.Container() container.disconnect = "Incorrect password." messenger.send("logout", [peer]) return 0 userdb[name].loggedin = True if userdb[name].peer: # This user is already logged in, so we need to log out the old ip oldpeer = userdb[name].peer container = proto.Container() container.disconnect = "Another client signed in with this user name and password. If this is in error please contact the server administrator." messenger.send("sendData", [oldpeer, container]) messenger.send("logout", [userdb[name].peer]) logger.info( "User %s signing in with peer %s. Killing old connection %s" % (name, peer, oldpeer)) userdb[name].peer = peer peers[peer] = name return 1
def checkEnterCity(self, peer, ident): '''Checks if user can enter city and if so, what permissions.''' # TODO: Check if city is active, if not send tiles to be simulated # TODO: Flag city as active userName = users.getNameFromPeer(peer) city = self.cities[ident] container = proto.Container() if users.isAdmin(userName) or userName == city.mayor: container.enterCity = ident elif users.canUser(userName, ident, 'viewCity'): container.enterCity = ident else: container.response = "You lack permission to enter city." messenger.send("sendData", [peer, container])
def processData(self, peer, data): """ processes serialized network event object into internal message system """ container = proto.Container() container.ParseFromString(data) logger.debug("Data from: %s\nData: %s" % (peer, container)) # Parsing chain! # Great care will need to be taken on when to use if, else, and elif # If the profile for this process takes too long if container.HasField("login"): self.login(peer, container.login) # If the player is not logged in we will not process any other message if peer not in users.peers: print "Unauthorized message from", peer, ". Skipping." return if container.HasField("chat"): messenger.send("onChat", [peer, container.chat]) if container.HasField("requestServerState"): messenger.send("requestServerState", [peer]) elif container.HasField("requestMaps"): messenger.send("requestMaps", [peer]) elif container.HasField("mapRequest"): # Make sure user is admin! name = users.getNameFromPeer(peer) if users.isAdmin(name): messenger.send("mapRequest", [container.mapRequest]) elif container.HasField("newCityRequest"): messenger.send("newCityRequest", [peer, container.newCityRequest]) elif container.HasField("requestGameState"): if not container.requestGameState: messenger.send("sendGameState", [peer]) elif container.HasField("requestUnfoundCity"): messenger.send("requestUnfoundCity", [peer, container.requestUnfoundCity]) elif container.HasField("requestEnterCity"): messenger.send("requestEnterCity", [peer, container.requestEnterCity]) elif container.HasField('requestExitCity'): messenger.send('requestExitCity', [ peer, ])
def sendMaps(self, peer): """ Usually called when a client requests a game state with no region loaded Or wishes to generate a new region. maps = {"Mapname": (heightmap, citybitmap)} """ maps = {} #os.chdir("Maps/") for directory in os.listdir("Maps/"): heightMap = open("Maps/" + directory + "/heightmap.png") # Convert to base64 for transmission over wire maps[directory] = base64.b64encode(heightMap.read()) heightMap.close() # Now for a good question, how to send over wire with pb? container = proto.Container() for mapName in maps: mapContainer = container.maps.add() mapContainer.name = mapName mapContainer.heightmap = maps[mapName] messenger.send("sendData", [peer, container])
def login(self, peer, login): """ Logs in player to the server """ self.lock.acquire() container = proto.Container() container.loginResponse.type = 1 if login.regionPassword != self.password: container.loginResponse.type = 0 container.loginResponse.message = "Region password incorrect" if login.name not in users.userdb: users.addUser(login.name, login.password) loginType = users.login(login.name, login.password, peer) if not loginType: container.loginResponse.type = 0 container.loginResponse.message = "Player password incorrect" if container.loginResponse.type: container.loginResponse.usertype = users.getType(login.name) container.loginResponse.username = login.name messenger.send("loggedIn", [peer, login.name]) logger.info("Logged in: %s %s" % (login.name, peer)) messenger.send("sendData", [peer, container]) self.lock.release()
def sendChat(self, peer, chat): container = proto.Container() container.chat.to = chat.to container.chat.sender = chat.sender container.chat.message = chat.message messenger.post("sendData", [peer, container])
def getServerState(self, peer): container = proto.Container() container.serverState = self.serverState messenger.send("sendData", [peer, container])