Пример #1
0
 def __recv_msg(self):
     header = MessageBuf(self.__recv_bytes(2))
     data_len = header.get_uint16(be=True)
     msg = MessageBuf(self.__recv_bytes(data_len))
     if self.verbose:
         self.info('< ' + str(msg))
     return msg
Пример #2
0
 def on_msg_rel(self, msg):
     seq = msg.get_uint16()
     while not msg.eom():
         rel_type = msg.get_uint8()
         if (rel_type & 0x80) != 0:
             rel_type &= 0x7F
             rel_len = msg.get_uint16()
             rmsg = MessageBuf(msg.get_bytes(rel_len))
         else:
             rmsg = MessageBuf(msg.get_remaining())
         if seq == self.rseq:
             if rel_type == RelMessageType.RMSG_NEWWDG:
                 self.on_rmsg_newwdg(rmsg)
             elif rel_type == RelMessageType.RMSG_WDGMSG:
                 self.on_rmsg_wdgmsg(rmsg)
             elif rel_type == RelMessageType.RMSG_DSTWDG:
                 self.on_rmsg_dstwdg(rmsg)
             elif rel_type == RelMessageType.RMSG_GLOBLOB:
                 self.on_rmsg_globlob(rmsg)
             elif rel_type == RelMessageType.RMSG_RESID:
                 self.on_rmsg_resid(rmsg)
             elif rel_type == RelMessageType.RMSG_PARTY:
                 self.on_rmsg_party(rmsg)
             elif rel_type == RelMessageType.RMSG_CATTR:
                 self.on_rmsg_cattr(rmsg)
             else:
                 pass
             self.gc.ack(seq)
             self.rseq = (self.rseq + 1) % 65536
         seq += 1
Пример #3
0
    def handle_wiact_message(self, data):
        if self.get_gs() != GameState.PLAY:
            # TODO: Send response back to the client
            return

        item_id = data['iid']

        msg = MessageBuf()
        msg.add_uint8(RelMessageType.RMSG_WDGMSG)
        msg.add_uint16(item_id)
        msg.add_string('take')
        msg.add_list([Coords.Z, Coords.Z])
        self.queue_rmsg(msg)

        wound_id = int(data['wid'])

        msg = MessageBuf()
        msg.add_uint8(RelMessageType.RMSG_WDGMSG)
        msg.add_uint16(self.chr_wdg_id)
        msg.add_string('wiact')
        msg.add_list([
            wound_id,
            0  # modflags
        ])
        self.queue_rmsg(msg)
Пример #4
0
    def queue_rmsg(self, rmsg):
        msg = MessageBuf()
        msg.add_uint8(MessageType.MSG_REL)
        msg.add_uint16(self.wseq)
        msg.add_bytes(rmsg.buf)

        msg.seq = self.wseq
        with self.rmsgs_lock:
            self.rmsgs.append(msg)
        self.wseq = (self.wseq + 1) % 65536
Пример #5
0
 def start_session(self, username, cookie):
     msg = MessageBuf()
     msg.add_uint8(MessageType.MSG_SESS)
     msg.add_uint16(2)  # Magic number
     msg.add_string('Hafen')
     msg.add_uint16(9)  # Protocol version
     msg.add_string(username)
     msg.add_uint16(len(cookie))
     msg.add_bytes(cookie)
     self.send_msg(msg)
Пример #6
0
    def handle_closepmchat_message(self, data):
        if self.get_gs() != GameState.PLAY:
            # TODO: Send response back to the client
            return

        chat_id = data['id']

        msg = MessageBuf()
        msg.add_uint8(RelMessageType.RMSG_WDGMSG)
        msg.add_uint16(chat_id)
        msg.add_string('close')
        self.queue_rmsg(msg)
Пример #7
0
    def get_cookie(self):
        msg = MessageBuf()
        msg.add_string('cookie')
        self.__send_msg(msg)

        rpl = self.__recv_msg()
        status = rpl.get_string()
        if status == 'ok':
            cookie = rpl.get_bytes(32)
            return cookie
        else:
            raise AuthException('Unexpected reply: "' + status + '"')
Пример #8
0
    def handle_play_message(self, data):
        if self.charlist_wdg_id == -1:
            return

        char_name = data['char_name']

        msg = MessageBuf()
        msg.add_uint8(RelMessageType.RMSG_WDGMSG)
        msg.add_uint16(self.charlist_wdg_id)
        msg.add_string('play')
        msg.add_list([char_name])
        self.queue_rmsg(msg)
Пример #9
0
    def handle_pmchat_message(self, data):
        if self.get_gs() != GameState.PLAY or self.buddy_wdg_id == -1:
            # TODO: Send response back to the client
            return

        kin_id = data['id']

        msg = MessageBuf()
        msg.add_uint8(RelMessageType.RMSG_WDGMSG)
        msg.add_uint16(self.buddy_wdg_id)
        msg.add_string('chat')
        msg.add_list([kin_id])
        self.queue_rmsg(msg)
Пример #10
0
    def handle_transfer_message(self, data):
        if self.get_gs() != GameState.PLAY:
            # TODO: Send response back to the client
            return

        item_id = data['id']

        msg = MessageBuf()
        msg.add_uint8(RelMessageType.RMSG_WDGMSG)
        msg.add_uint16(item_id)
        msg.add_string('transfer')
        msg.add_list([Coords.Z])  # Ignored
        self.queue_rmsg(msg)
Пример #11
0
    def handle_drop_message(self, data):
        if self.get_gs() != GameState.PLAY:
            # TODO: Send response back to the client
            return

        coords = data['coords']

        msg = MessageBuf()
        msg.add_uint8(RelMessageType.RMSG_WDGMSG)
        msg.add_uint16(self.inv_wdg_id)
        msg.add_string('drop')
        msg.add_list([Coord(coords['x'], coords['y'])])
        self.queue_rmsg(msg)
Пример #12
0
    def login(self, username, password):
        msg = MessageBuf()
        msg.add_string('pw')
        msg.add_string(username)
        msg.add_bytes(password.decode('hex'))
        self.__send_msg(msg)

        rpl = self.__recv_msg()
        status = rpl.get_string()
        if status == 'ok':
            acc = rpl.get_string(
            )  # This is normally the same thing as `username`
            return
        elif status == 'no':
            err = rpl.get_string()
            raise AuthException(err)
        else:
            raise AuthException('Unexpected reply: "' + status + '"')
Пример #13
0
    def handle_cl_message(self, data):
        if self.get_gs() != GameState.PLAY or self.flowermenu_wdg_id == -1:
            # TODO: Send response back to the client
            return

        option = data['option']

        msg = MessageBuf()
        msg.add_uint8(RelMessageType.RMSG_WDGMSG)
        msg.add_uint16(self.flowermenu_wdg_id)
        msg.add_string('cl')
        if option == -1:
            msg.add_list([option])
        else:
            msg.add_list([
                option,
                0  # modflags
            ])
        self.queue_rmsg(msg)

        self.flowermenu_wdg_id = -1  # TODO: Handle it on DSTWDG message or smth like that
Пример #14
0
    def __init__(self, resname, resver, rawinfo):
        self.resname = resname
        self.resver = resver

        buf = MessageBuf(rawinfo)

        canon_sig = 'Haven Resource 1'
        sig = buf.get_bytes(len(canon_sig))
        if sig != canon_sig:
            raise ResException('Wrong signature')

        ver = buf.get_uint16()
        if ver != self.resver:
            raise ResException('Wrong version')

        self.layers = []
        while not buf.eom():
            layer_type = buf.get_string()
            layer_len = buf.get_int32()
            layer_data = buf.get_bytes(layer_len)
            self.layers.append(ResLayer(layer_type, layer_data))
Пример #15
0
    def handle_transfer_message(self, data):
        if self.get_gs() != GameState.PLAY:
            # TODO: Send response back to the client
            return

        item_id = data['id']

        coords = None
        with self.items_lock:
            for item in self.items:
                if item.wdg_id == item_id:
                    coords = copy.copy(item.coords)
        if coords is None:
            # TODO: Send response back to the client
            return

        msg = MessageBuf()
        msg.add_uint8(RelMessageType.RMSG_WDGMSG)
        msg.add_uint16(item_id)
        msg.add_string('transfer')
        msg.add_list([coords])
        self.queue_rmsg(msg)
Пример #16
0
    def rworker(self):
        while True:
            try:
                msg = self.gc.recv_msg(
                )  # TODO: Make it non-blocking to check the game state
                msg_type = msg.get_uint8()
                data = MessageBuf(msg.get_remaining())
                if msg_type == MessageType.MSG_SESS:
                    self.on_msg_sess(data)
                elif msg_type == MessageType.MSG_REL:
                    self.on_msg_rel(data)
                elif msg_type == MessageType.MSG_ACK:
                    self.on_msg_ack(data)
                elif msg_type == MessageType.MSG_OBJDATA:
                    self.on_msg_objdata(data)
                elif msg_type == MessageType.MSG_CLOSE:
                    self.on_msg_close()
                else:
                    pass

                if self.get_gs() == GameState.CLOSE:
                    return
            except GameException as e:
                self.error('Game session error: ' + str(e))
Пример #17
0
    def handle_clicknearest_message(self, data):
        if self.get_gs() != GameState.PLAY:
            # TODO: Send response back to the client
            return

        if self.mapview_wdg_id == -1:
            self.sendMessage(
                unicode(
                    json.dumps({
                        'action': 'clicknearest',
                        'success': False,
                        'reason': 'Map has not been constructed yet'
                    })))
            return

        obj_name = data['name']
        if obj_name != 'table':
            self.sendMessage(
                unicode(
                    json.dumps({
                        'action': 'clicknearest',
                        'success': False,
                        'reason': 'Unsupported object name'
                    })))
            return

        with self.gobs_lock:
            tables = []
            pl = None
            for gob_id, gob in self.gobs.iteritems():
                if gob.c is None:
                    continue
                if gob.is_table():
                    tables.append(gob)
                elif gob_id == self.pgob_id:
                    pl = gob
            if len(tables) == 0:
                self.sendMessage(
                    unicode(
                        json.dumps({
                            'action':
                            'clicknearest',
                            'success':
                            False,
                            'reason':
                            'No tables found (try again later)'
                        })))
                return
            if pl is None:
                self.sendMessage(
                    unicode(
                        json.dumps({
                            'action':
                            'clicknearest',
                            'success':
                            False,
                            'reason':
                            'Player object has not been received yet'
                        })))
                return

            nearest = None
            nearestc = None
            for table in tables:
                d = Coord.diff(pl.c, table.c)
                if nearest is None or d.x + d.y < nearestc:
                    nearest = table
                    nearestc = d.x + d.y

            msg = MessageBuf()
            msg.add_uint8(RelMessageType.RMSG_WDGMSG)
            msg.add_uint16(self.mapview_wdg_id)
            msg.add_string('click')
            msg.add_list([
                Coords.Z,  # pc (not used)
                Coords.Z,  # mc (not used)
                3,  # RMB
                0,  # modflags (no Alt / Ctrl / etc)
                0,  # no overlay
                nearest.gob_id,
                Coord.floor(nearest.c, Coords.POSRES),
                0,  # overlay ID
                -1  # click ID
            ])
            self.queue_rmsg(msg)

            self.sendMessage(
                unicode(json.dumps({
                    'action': 'clicknearest',
                    'success': True
                })))
Пример #18
0
 def __prepend_header(self, msg):
     tmp = MessageBuf()
     tmp.add_uint16(len(msg.buf), be=True)
     tmp.add_bytes(msg.buf)
     return tmp
Пример #19
0
 def ack(self, seq):
     msg = MessageBuf()
     msg.add_uint8(MessageType.MSG_ACK)
     msg.add_uint16(seq)
     self.send_msg(msg)
Пример #20
0
 def beat(self):
     msg = MessageBuf()
     msg.add_uint8(MessageType.MSG_BEAT)
     self.send_msg(msg)
Пример #21
0
    def on_msg_objdata(self, msg):
        # NOTE: We don't really need to handle all of these messages,
        # we just want to get rid of most of them by sending the corresponding MSG_OBJACK messages
        while not msg.eom():
            fl = msg.get_uint8()
            id = msg.get_uint32()
            frame = msg.get_int32()

            while True:
                data_type = msg.get_uint8()
                if data_type == ObjDataType.OD_REM:
                    with self.gobs_lock:
                        del self.gobs[id]
                    self.sendMessage(
                        unicode(json.dumps({
                            'action': 'gobrem',
                            'id': id
                        })))
                elif data_type == ObjDataType.OD_MOVE:
                    msg.get_int32()
                    msg.get_int32()
                    ia = msg.get_uint16()
                elif data_type == ObjDataType.OD_RES:
                    resid = msg.get_uint16()
                    if (resid & 0x8000) != 0:
                        resid &= ~0x8000
                        sdt_len = msg.get_uint8()
                        sdt = MessageBuf(msg.get_bytes(sdt_len))
                elif data_type == ObjDataType.OD_LINBEG:
                    msg.get_int32()
                    msg.get_int32()

                    msg.get_int32()
                    msg.get_int32()
                elif data_type == ObjDataType.OD_LINSTEP:
                    w = msg.get_int32()
                    if w == -1:
                        pass
                    elif (w & 0x80000000) == 0:
                        pass
                    else:
                        w = msg.get_int32()
                elif data_type == ObjDataType.OD_SPEECH:
                    zo = msg.get_int16() / 100.0
                    text = msg.get_string()
                elif data_type == ObjDataType.OD_COMPOSE:
                    resid = msg.get_uint16()
                    with self.gobs_lock:
                        gob = self.gobs.get(id, Gob(id))
                        gob.compose(resid)
                        self.gobs[id] = gob
                elif data_type == ObjDataType.OD_CMPPOSE:
                    pfl = msg.get_uint8()
                    seq = msg.get_uint8()

                    if (pfl & 2) != 0:
                        while True:
                            resid = msg.get_uint16()
                            if resid == 65535:
                                break
                            if (resid & 0x8000) != 0:
                                resid &= ~0x8000
                                sdt_len = msg.get_uint8()
                                sdt = MessageBuf(msg.get_bytes(sdt_len))

                    if (pfl & 4) != 0:
                        while True:
                            resid = msg.get_uint16()
                            if resid == 65535:
                                break
                            if (resid & 0x8000) != 0:
                                resid &= ~0x8000
                                sdt_len = msg.get_uint8()
                                sdt = MessageBuf(msg.get_bytes(sdt_len))
                        ttime = msg.get_uint8() / 10.0
                elif data_type == ObjDataType.OD_CMPMOD:
                    while True:
                        modid = msg.get_uint16()
                        if modid == 65535:
                            break
                        while True:
                            resid = msg.get_uint16()
                            if resid == 65535:
                                break
                            if (resid & 0x8000) != 0:
                                resid &= ~0x8000
                                sdt_len = msg.get_uint8()
                                sdt = MessageBuf(msg.get_bytes(sdt_len))
                elif data_type == ObjDataType.OD_CMPEQU:
                    while True:
                        h = msg.get_uint8()
                        if h == 255:
                            break
                        ef = h & 0x80
                        et = h & 0x7f
                        at = msg.get_string()
                        resid = msg.get_uint16()
                        if (resid & 0x8000) != 0:
                            resid &= ~0x8000
                            sdt_len = msg.get_uint8()
                            sdt = MessageBuf(msg.get_bytes(sdt_len))
                        if (ef & 128) != 0:
                            x = msg.get_int16()
                            y = msg.get_int16()
                            z = msg.get_int16()
                elif data_type == ObjDataType.OD_ZOFF:
                    off = msg.get_int16() / 100.0
                elif data_type == ObjDataType.OD_LUMIN:
                    msg.get_int32()
                    msg.get_int32()

                    sz = msg.get_uint16()
                    sstr = msg.get_uint8()
                elif data_type == ObjDataType.OD_AVATAR:
                    while True:
                        layer = msg.get_uint16()
                        if layer == 65535:
                            break
                elif data_type == ObjDataType.OD_FOLLOW:
                    oid = msg.get_uint32()
                    if oid != 0xffffffffl:
                        xfres = msg.get_uint16()  # getres
                        xfname = msg.get_string()
                elif data_type == ObjDataType.OD_HOMING:
                    oid = msg.get_uint32()
                    if oid != 0xffffffffl:
                        pass
                    else:
                        msg.get_int32()
                        msg.get_int32()

                        msg.get_int32(
                        )  # double v = msg.int32() * 0x1p-10 * 11;
                elif data_type == ObjDataType.OD_OVERLAY:
                    oid = msg.get_int32()
                    resid = msg.get_uint16()
                    if resid == 65535:
                        pass
                    else:
                        if (resid & 0x8000) != 0:
                            resid &= ~0x8000
                            sdt_len = msg.get_uint8()
                            sdt = MessageBuf(msg.get_bytes(sdt_len))
                elif data_type == ObjDataType.OD_HEALTH:
                    hp = msg.get_uint8()
                elif data_type == ObjDataType.OD_BUDDY:
                    name = msg.get_string()
                    if len(name) > 0:
                        group = msg.get_uint8()
                        btype = msg.get_uint8()
                    with self.gobs_lock:
                        gob = self.gobs.get(id, Gob(id))
                        gob.buddy(name)
                        self.gobs[id] = gob
                    self.sendMessage(
                        unicode(
                            json.dumps({
                                'action': 'buddy',
                                'id': id,
                                'name': name
                            })))
                elif data_type == ObjDataType.OD_ICON:
                    resid = msg.get_uint16()
                    if resid == 65535:
                        pass
                    else:
                        ifl = msg.get_uint8()
                elif data_type == ObjDataType.OD_RESATTR:
                    resid = msg.get_uint16()
                    dat_len = msg.get_uint8()
                    if dat_len > 0:
                        dat = MessageBuf(msg.get_bytes(dat_len))
                elif data_type == ObjDataType.OD_END:
                    break

            msg = MessageBuf()
            msg.add_uint8(MessageType.MSG_OBJACK)
            msg.add_uint32(id)
            msg.add_int32(frame)
            self.gc.send_msg(msg)
Пример #22
0
 def recv_msg(self):
     data, addr = self.s.recvfrom(65535)
     msg = MessageBuf(data)
     if self.verbose:
         self.info('< ' + str(msg))
     return msg