class Server(object):
	"""Server object.
	"""
	
	def __init__(self):
		
		# Maak socket aan en luister.
		self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
		self.sock.setblocking(0)
		self.sock.bind((HOSTNAME, PORT))
		
		print "Server listening at '%s:%i'" % (HOSTNAME, PORT)
		
		# Game state.
		self.gameState = GameState()
		
		# Lijst met alle connections.
		self.connections = {}
		
	def handleRequest(self, data, address):
		"""Handel een request af.
		"""
		id = int(data.split(" ")[0])
		command = data.split(" ")[1]
		args = " ".join(data.split(" ")[2:])
		
		# Connecten.
		if command == "connect":
			
			# Informatie ophalen uit packet.
			name = args
			id = getNextId()

			# Check of de speler met die naam al bestaat.			
			if self.gameState.containsPlayerWithName(name) == False:
				# Hij bestaat nog niet - toevoegen.
				
				# Connectie opslaan.
				self.connections[id] = address
				print "Player connected: %s (ID:%i)" % (name, id)
	
				# Player toevoegen aan game.
				self.gameState.addPlayer(name)
				
				# Welcome command terugsturen naar client.
				welcomeString = "0 welcome %s %i" % (name, id)
				self.sock.sendto(welcomeString, address)
	
			else:
				# Hij bestaat al - niet toestaan.
				
				# Stuur denied command terug naar de client.
				print "Player denied: %s (name in use)" % name
				deniedString = "0 denied %s player name in use" % name
				self.sock.sendto(deniedString, address)

		# Disconnecten.
		elif command == "disconnect":
			name = args
			print "Player disconnected: %s (ID:%i)" % (name, id)
			self.gameState.removePlayer(name)
			del(self.connections[id])

		# Moven.
		elif command == "move":
			name = args.split(" ")[0]
			velX = int(args.split(" ")[1])
			velY = int(args.split(" ")[2])
			#print "Moving player %s to %i %i" % (name, velX, velY)
			self.gameState.movePlayer(name, velX, velY)

		# Onbekend request.
		else:
			print "Unknown network command: %s" % data
		
	def run(self):
		"""Run de main loop van de server.
		"""

		# Eeuwig blijven draaien.
		while True:

			# Lees de socket uit tot er niks meer beschikbaar is deze tick.
			empty = False
			while not empty:
				
				# Haal gegevens op.
				try:
					data, address = self.sock.recvfrom( 1024 )
					
				# Except voor als er niks meer is.
				except socket.error:
					empty = True
				
				# Else voor als er wel wat is.
				else:
					#print "Received message:", data
					self.handleRequest(data, address)
			
			# Verstuur naar iedereen de nieuwe posities.
			for id, connection in self.connections.items():
				positionString = "%i %s" % (id, self.gameState.toString())
				self.sock.sendto(positionString, connection)
			
			# Wachten.
			pygame.time.wait(50)
Example #2
0
class Client(QObject):
    sendReady = pyqtSignal(int, list)
    readyToConnect = pyqtSignal()

    def __init__(self, host, port, name = "", parent = None):
        QObject.__init__(self, parent)
        self.game = GameState()
        self.host = host
        self.port = port
        self.name = name
        self.connection = Connection(client=True)
        self.connection.messageReceived.connect(self.handleMessage)
        self.connection.error.connect(self.handleError)
        self.sendReady.connect(self.connection.sendMessage)
        self.connection.connectToHost(self.host, self.port)
        while not self.connection.waitForConnected(10000):
            if not QMessageBox.Retry == QMessageBox.critical(None, "Connection Failed", "Failed to connect to %s on port %d" % (self.host, self.port), QMessageBox.Retry | QMessageBox.Cancel):
                sys.exit()
        self.send(Message.Join)
        QApplication.setQuitOnLastWindowClosed(False)

    def send(self, msg, args = []):
        self.sendReady.emit(msg, args)

    def handleError(self, err):
        log.error(self.connection.errorString())
        QMessageBox.critical(None, "Network Error", self.connection.errorString())
        QApplication.quit()

    def handleMessage(self, msg, args):
        if msg == Message.Ping:
            self.send(Message.Pong)

        elif msg == Message.StateChanged:
            self.handleStateChange(*args)

        elif msg == Message.ReceiveChat:
            (sender, text, timestamp) = args
            p = self.game.getPlayer(sender)
            if not p:
                color = (128, 128, 128)
            else:
                color = p.color
            self.mainWindow.chat.addLine(Line(Line.Chat, sender=sender, text=text, playerColor=color, timestamp = timestamp))

        elif msg == Message.ReceiveWhisper:
            (sender, target, text, timestamp) = args
            p = self.game.getPlayer(sender)
            self.mainWindow.chat.addLine(Line(Line.Whisper, sender=sender, target=target, text=text, playerColor=p.color, timestamp = timestamp))

        elif msg == Message.WhisperError:
            self.mainWindow.chat.addLine("No such player.")

        elif msg == Message.JoinSuccess:
            name = self.name
            while not name:
                (name, ok) = QInputDialog.getText(None, "Username", "Name")
                if not ok:
                    QApplication.quit()
                    break
            self.send(Message.RequestName, [name])
        
        elif msg == Message.NameTaken:
            name = ""
            while not name:
                (name, ok) = QInputDialog.getText(None, "Name Taken", "New name")
                if not ok:
                    QApplication.quit()
                    break
            self.send(Message.RequestName, [name])
        
        elif msg == Message.NameAccepted:
            (self.clientPlayerName, self.password) = args
            self.send(Message.RequestPlayerList)

        elif msg == Message.PlayerJoined:
            name = args[0]
            color = args[1:]
            player = self.game.addPlayer(name)
            player.color = color
            self.mainWindow.chat.addLine(Line(Line.PlayerJoined, target=name))
            self.mainWindow.playerInfo.addPlayer(player)

        elif msg == Message.GameInProgress:
            password = ""
            while not password:
                (password, ok) = QInputDialog.getText(None, "Game Already Inprogress", "Password")
                if not ok:
                    QApplication.quit()
                    break
            self.send(Message.Rejoin, [str(password)])

        elif msg == Message.IncorrectPassword:
            password = ""
            while not password:
                (password, ok) = QInputDialog.getText(None, "Incorrect Password", "Password")
                if not ok:
                    QApplication.quit()
                    break
            self.send(Message.Rejoin, [str(password)])

        elif msg == Message.RejoinSuccess:
            name = args[0]
            self.clientPlayerName = name
            self.send(Message.RequestPlayerList)

        elif msg == Message.PlayerRejoined:
            name = args[0]
            self.mainWindow.chat.addLine(Line(Line.PlayerRejoined, target=name))

        elif msg == Message.BeginPlayerList:
            pass

        elif msg == Message.PlayerInfo:
            name = args[0]
            cardCount = args[1]
            color = args[2:]
            player = self.game.addPlayer(name)
            player.color = color
            player.cards = [Card() for i in range(cardCount)]

        elif msg == Message.EndPlayerList:
            self.send(Message.RequestBoardName)

        elif msg == Message.LoadBoard:
            boardName = args[0]
            board = loadBoard(boardName)
            if not board:
                QMessageBox.critical(None, "Board Missing", "You do not have the board \"%s\" required for this game." % (boardName), QMessageBox.Close)
                QApplication.quit()
            self.game.board = board
            self.game.clientPlayer = self.game.getPlayer(self.clientPlayerName)
            del self.clientPlayerName
            self.mainWindow = MainWindow(self.game)
            self.game.changed.connect(self.mainWindow.boardWidget.update)
            self.mainWindow.boardWidget.territoryClaimed.connect(self.sendClaimTerritory)
            self.mainWindow.boardWidget.drafted.connect(self.sendDraft)
            self.mainWindow.boardWidget.attacked.connect(self.sendAttack)
            self.mainWindow.boardWidget.fortified.connect(self.sendFortify)
            self.mainWindow.setWindowTitle("Empyre %s:%d" % (self.host, self.port))
            self.mainWindow.chat.lineEntered.connect(self.sendChat)
            self.mainWindow.colorChanged.connect(self.sendColorChange)
            self.mainWindow.nameChanged.connect(self.sendNameChange)
            self.mainWindow.cardsSelected.connect(self.sendExchangeCards)
            self.mainWindow.endAttackReleased.connect(self.sendEndAttack)
            self.mainWindow.endTurnReleased.connect(self.sendEndTurn)
            for p in self.game.players:
                self.mainWindow.playerInfo.addPlayer(p)
            self.mainWindow.show()
            try:
                _ = self.password
                self.mainWindow.chat.addLine("Welcome to the game!")
                self.mainWindow.chat.addLine("Your password is \"%s\"." % self.password)
                self.mainWindow.chat.addLine("Use this password to rejoin the game once it has started.")
                del self.password
                self.send(Message.ReadyToPlay)
            except AttributeError:
                self.mainWindow.chat.addLine("Welcome back to the game!")
                self.mainWindow.boardWidget.setEnabled(True)
                self.send(Message.RequestOwnershipList)
                self.send(Message.RequestCardList)
                self.send(Message.RequestCurrentPlayer)
                self.send(Message.RequestState)
                self.send(Message.RequestRemainingTroops)
            QApplication.setQuitOnLastWindowClosed(True)
            self.send(Message.RequestChatHistory)

        elif msg == Message.CurrentState:
            self.handleStateChange(State.Lobby, args[0])

        elif msg == Message.BeginOwnershipList:
            self.mainWindow.boardWidget.setUpdatesEnabled(False)

        elif msg == Message.Ownership:
            (t, player, count) = args
            t = self.game.board.getTerritory(t)
            t.owner = self.game.getPlayer(player)
            t.troopCount = count
            if t.owner:
                self.mainWindow.boardWidget.updateTerritoryOwner(t.name, t.owner.name)
                self.mainWindow.boardWidget.updateTerritoryTroopCount(t.name, count)

        elif msg == Message.EndOwnershipList:
            self.mainWindow.boardWidget.setUpdatesEnabled(True)
            self.mainWindow.playerInfo.updateStatistics()

        elif msg == Message.BeginCardList:
            pass

        elif msg == Message.Card:
            self.game.clientPlayer.cards.append(Card(*args))
        
        elif msg == Message.EndCardList:
            self.mainWindow.updateStatistics()

        elif msg == Message.PlayerLeft:
            name = args[0]
            self.game.removePlayer(name)
            self.mainWindow.chat.addLine(Line(Line.PlayerLeft, target=name))
            self.mainWindow.playerInfo.removePlayer(name)

        elif msg == Message.PlayerLeftDuringGame:
            name = args[0]
            self.mainWindow.chat.addLine(Line(Line.PlayerLeft, target=name))

        elif msg == Message.ColorChanged:
            name = args[0]
            color = args[1:]
            self.game.setPlayerColor(name, color)
            self.mainWindow.chat.changePlayerColor(name, color)
            self.mainWindow.chat.addLine("%s has changed their color." % (name))
            self.mainWindow.playerInfo.changePlayerColor(name, color)

        elif msg == Message.NameChangeTaken:
            self.mainWindow.chat.addLine("That name is already taken.")

        elif msg == Message.NameChangeSuccess:
            name = args[0]
            self.game.setPlayerName(self.game.clientPlayer.name, name)

        elif msg == Message.NameChanged:
            before = args[0]
            after = args[1]
            self.game.setPlayerName(before, after)
            self.mainWindow.chat.changePlayerName(before, after)
            self.mainWindow.chat.addLine("%s changed their name to %s" % (before, after))
            self.mainWindow.playerInfo.changePlayerName(before, after)

        elif msg == Message.TurnChanged or msg == Message.CurrentPlayer:
            name = args[0]
            self.game.setCurrentPlayer(name)
            if self.game.yourTurn():
                self.mainWindow.activateWindow()
            self.mainWindow.playerInfo.changeCurrentPlayer(name)

        elif msg == Message.TerritoryUpdated:
            (name, owner, count) = args
            t = self.game.board.getTerritory(name)
            previousOwner = t.owner
            previousTroopCount = t.troopCount
            t.owner = self.game.getPlayer(owner)
            t.troopCount = count
            if t.owner != previousOwner:
                self.mainWindow.boardWidget.updateTerritoryOwner(name, owner)
            if t.troopCount != previousTroopCount:
                self.mainWindow.boardWidget.updateTerritoryTroopCount(name, count)
            self.mainWindow.playerInfo.updateStatistics()
            self.game.changed.emit()

        elif msg == Message.RemainingTroopsChanged:
            troops = args[0]
            self.game.remainingTroops = troops

        elif msg == Message.MustExchangeCards:
            self.mainWindow.chat.addLine("You must trade in your cards.")

        elif msg == Message.CardsExchanged:
            name = args[0]
            indexes = args[1:]
            player = self.game.getPlayer(name)
            if player == self.game.clientPlayer:
                player.cards = [c for i, c in enumerate(player.cards) if not i in indexes]
            self.mainWindow.player.updateStatistics()

        elif msg == Message.Attacked:
            (attacker, source, target) = args
            self.mainWindow.boardWidget.attack(*args)

        elif msg == Message.ReceiveCard:
            (t, u) = args
            self.game.clientPlayer.cards.append(Card(t, u))
            self.game.changed.emit()

        elif msg == Message.CardAwarded:
            name = args[0]
            player = self.game.getPlayer(name)
            if player != self.game.clientPlayer:
                player.cards.append(Card())
            count = len(player.cards)
            self.mainWindow.playerInfo.updateStatistics()

        elif msg == Message.PlayerEliminated:
            name = args[0]
            self.mainWindow.chat.addLine("%s has been eliminated!" % name)

    def handleStateChange(self, old, new):
        self.mainWindow.cashCards.setEnabled(False)
        self.mainWindow.endAttack.setEnabled(False)
        self.mainWindow.endTurn.setEnabled(False)
        if old == State.Lobby:
            self.mainWindow.chat.addLine("The game has started!")
            self.mainWindow.boardWidget.setEnabled(True)
            self.mainWindow.changeName.setEnabled(False)
            self.mainWindow.changeColor.setEnabled(False)
        if self.game.yourTurn():
            if new == State.Draft:
                self.mainWindow.cashCards.setEnabled(True)
            elif new == State.Attack:
                self.mainWindow.endAttack.setEnabled(True)
                self.mainWindow.endTurn.setEnabled(True)
            elif new == State.Fortify:
                self.mainWindow.endTurn.setEnabled(True)
        self.mainWindow.boardWidget.stateChange(old, new)
        self.game.state = new

    def sendChat(self, text):
        if not text:
            return
        parts = text.split(" ")
        if parts[0] == "/to":
            if len(parts) < 3:
                self.mainWindow.chat.addLine("Invalid command.")
                return
            target = parts[1]
            text = " ".join(parts[2:])
            self.send(Message.SendWhisper, [target, text])
        else:
            self.send(Message.SendChat, [text])

    def sendColorChange(self, color):
        self.send(Message.ChangeColor, color)

    def sendNameChange(self, name):
        self.send(Message.ChangeName, [name])

    def sendClaimTerritory(self, name):
        self.send(Message.ClaimTerritory, [name])

    def sendExchangeCards(self, cards):
        self.send(Message.ExchangeCards, cards)
        
    def sendDraft(self, name, count):
        self.send(Message.Draft, [name, count])

    def sendAttack(self, source, target, n):
        self.send(Message.Attack, [source, target, n])

    def sendEndAttack(self):
        self.send(Message.EndAttack)

    def sendFortify(self, source, target, n):
        self.send(Message.Fortify, [source, target, n])

    def sendEndTurn(self):
        self.send(Message.EndTurn)