Search code examples
python-2.7twisted

How do I call a specific protocol using Twisted


So I'm trying to make a very basic MUD and I may be going about it the wrong way but I just need some coding help. This code includes twisted that I've tweaked for testing means to try and understand it, however I have run into a road block.

from twisted.internet.protocol import Factory
from twisted.protocols.basic import LineReceiver
from twisted.internet import reactor
import time


class Chat(LineReceiver):

    def __init__(self, users):
        self.users = users
        self.name = None
        self.health = 10
        self.state = "GETNAME"

    def connectionMade(self):
        self.sendLine("What's your name?")

    def connectionLost(self, reason):
        if self.users.has_key(self.name):
            print self.name, "has disconnected"
            del self.users[self.name]

    def lineReceived(self, line):
        if self.state == "GETNAME":
            self.handle_GETNAME(line)
        else:
            if self.state == "CHAT":
                self.handle_CHAT(line)
            else:
                if self.state == "ATTACK":
                    self.handle_ATTACK(line)

    def handle_GETNAME(self, name):
        if self.users.has_key(name):
            self.sendLine("Name taken, please choose another.")
            return
        self.sendLine("Welcome, %s!" % (name,))
        print name, "has connected"
        self.sendLine("You currently have %s health..." % (self.health))
        self.name = name
        self.users[name] = self
        for name, protocol in self.users.iteritems():
            if protocol != self:
                message = "%s has joined" % (self.name,)
                protocol.sendLine(message)
        self.state = "CHAT"

    def handle_CHAT(self, message):
        if(message[0:3] == 'say'):
            try:
                message = message[4:]
                message = "<%s> %s" % (self.name, message)
                print message
                for name, protocol in self.users.iteritems():
                    if protocol != self:
                        protocol.sendLine(message)
            except:
                print "Chat failed"
        if(message == 'test'):
            try:
                self.handle_TEST()
            except:
                print "Testing Failed"
        if(message == 'attack'):
            try:
                self.handle_ATTACKINIT()
            except:
                print "Attack Failed"

    def handle_ATTACKINIT(self):
        self.sendLine("Who are you attacking?")
        self.state = "ATTACK"

    def handle_ATTACK(self, target):
        for target, protocol in self.users.iteritems():
            if protocol == target:
                target.sendLine("You have been attacked!")
                protocol.sendLine("You now have %s health remaining..." % (self.health,))
            else:
                self.sendLine("No target with that name")

    def handle_TEST(self):
        print name, "is Testing"
        self.sendLine("This is a test")
        self.state = "CHAT"


class ChatFactory(Factory):

    def __init__(self):
        self.users = {}  # maps user names to Chat instances

    def buildProtocol(self, addr):
        return Chat(self.users)


reactor.listenTCP(8123, ChatFactory())
reactor.run()

The main function I need help with is this function...

    def handle_ATTACK(self, target):
        for target, protocol in self.users.iteritems():
            if protocol == target:
                target.sendLine("You have been attacked!")
                protocol.sendLine("You now have %s health remaining..." % (self.health,))
            else:
                self.sendLine("No target with that name")

I need to find the 'target's' protocol to send it a message and deal damage to it.

I figured out that it is saving the Name/Protocol match in the list self.users, and I'm guessing I look for "target's" protocol in the set self.users.iteritems() but I'm having trouble accessing a specific protocol and utilizing it.

Any help for the beginning novice that is messing with twisted?


Solution

  • You've shadowed your target parameter with a loop variable:

    def handle_ATTACK(self, target):
        for target, protocol in self.users.iteritems():
            if protocol == target:
    

    Before the loop starts, target identifies the user to attack. After the loop starts, it identifies one of the keys in the self.users dictionary.

    Then, you compare that key to protocol - which is one of the values of the self.users dictionary. This probably isn't what you intended.

    Try comparing the target parameter to keys from self.users and then using the corresponding value as the protocol to use to send data.