def writeServerEvent(self, logtype, *args, **kwargs):
        """
        Write an event to the central Event Logger, if one is configured.

        The purpose of the Event Logger is to keep a game-wide record of all
        interesting in-game events that take place. Therefore, this function
        should be used whenever such an interesting in-game event occurs.
        """

        if self.eventSocket is None:
            return # No event logger configured!

        log = collections.OrderedDict()
        log['type'] = logtype
        log['sender'] = self.eventLogId

        for i,v in enumerate(args):
            # +1 because the logtype was _0, so we start at _1
            log['_%d' % (i+1)] = v

        log.update(kwargs)

        dg = PyDatagram()
        msgpack_encode(dg, log)
        self.eventSocket.Send(dg.getMessage())
Example #2
0
 def sendSetLocation(self, doId, parentId, zoneId):
     datagram = PyDatagram()
     datagram.addUint16(CLIENT_OBJECT_LOCATION)
     datagram.addUint32(doId)
     datagram.addUint32(parentId)
     datagram.addUint32(zoneId)
     self.send(datagram)
    def writeServerEvent(self, logtype, *args, **kwargs):
        """
        Write an event to the central Event Logger, if one is configured.

        The purpose of the Event Logger is to keep a game-wide record of all
        interesting in-game events that take place. Therefore, this function
        should be used whenever such an interesting in-game event occurs.
        """

        if self.eventSocket is None:
            return  # No event logger configured!

        log = collections.OrderedDict()
        log['type'] = logtype
        log['sender'] = self.eventLogId

        for i, v in enumerate(args):
            # +1 because the logtype was _0, so we start at _1
            log['_%d' % (i + 1)] = v

        log.update(kwargs)

        dg = PyDatagram()
        msgpack_encode(dg, log)
        self.eventSocket.Send(dg.getMessage())
Example #4
0
 def sendDisconnect(self):
     if self.isConnected():
         datagram = PyDatagram()
         datagram.addUint16(CLIENT_DISCONNECT_CMU)
         self.send(datagram)
         self.notify.info('Sent disconnect message to server')
         self.disconnect()
     self.stopHeartbeat()
    def sendDeleteMsg(self, doId):
        # This method is only used in conjunction with the CMU LAN
        # server.

        datagram = PyDatagram()
        datagram.addUint16(CLIENT_OBJECT_DELETE)
        datagram.addUint32(doId)
        self.send(datagram)
 def sendSetShardMsg(self, shardId):
     datagram = PyDatagram()
     # Add message type
     datagram.addUint16(CLIENT_SET_SHARD)
     # Add shard id
     datagram.addUint32(shardId)
     # send the message
     self.send(datagram)
    def setAI(self, doId, aiChannel):
        """
        Sets the AI of the specified DistributedObjectAI to be the specified channel.
        Generally, you should not call this method, and instead call DistributedObjectAI.setAI.
        """

        dg = PyDatagram()
        dg.addServerHeader(doId, aiChannel, STATESERVER_OBJECT_SET_AI)
        dg.add_uint64(aiChannel)
        self.send(dg)
    def setClientState(self, clientChannel, state):
        """
        Sets the state of the client on the CA.
        Useful for logging in and logging out, and for little else.
        """

        dg = PyDatagram()
        dg.addServerHeader(clientChannel, self.ourChannel, CLIENTAGENT_SET_STATE)
        dg.add_uint16(state)
        self.send(dg)
    def setOwner(self, doId, newOwner):
        """
        Sets the owner of a DistributedObject. This will enable the new owner to send "ownsend" fields,
        and will generate an OwnerView.
        """

        dg = PyDatagram()
        dg.addServerHeader(doId, self.ourChannel, STATESERVER_OBJECT_SET_OWNER)
        dg.add_uint64(newOwner)
        self.send(dg)
Example #10
0
 def sendHeartbeat(self):
     datagram = PyDatagram()
     # Add message type
     datagram.addUint16(CLIENT_HEARTBEAT)
     # Send it!
     self.send(datagram)
     self.lastHeartbeat = globalClock.getRealTime()
     # This is important enough to consider flushing immediately
     # (particularly if we haven't run readerPollTask recently).
     self.considerFlush()
Example #11
0
 def sendHeartbeat(self):
     datagram = PyDatagram()
     # Add message type
     datagram.addUint16(CLIENT_HEARTBEAT)
     # Send it!
     self.send(datagram)
     self.lastHeartbeat = globalClock.getRealTime()
     # This is important enough to consider flushing immediately
     # (particularly if we haven't run readerPollTask recently).
     self.considerFlush()
 def sendSetLocation(self, doId, parentId, zoneId):
     datagram = PyDatagram()
     datagram.addUint16(CLIENT_OBJECT_LOCATION)
     datagram.addUint32(doId)
     datagram.addUint32(parentId)
     datagram.addUint32(zoneId)
     self.send(datagram)
Example #13
0
 def sendDisconnect(self):
     if self.isConnected():
         # Tell the game server that we're going:
         datagram = PyDatagram()
         # Add message type
         datagram.addUint16(CLIENT_DISCONNECT)
         # Send the message
         self.send(datagram)
         self.notify.info("Sent disconnect message to server")
         self.disconnect()
     self.stopHeartbeat()
    def requestDelete(self, do):
        """
        Request the deletion of an object that already exists on the State Server.

        You should probably use do.requestDelete() instead.
        """

        dg = PyDatagram()
        dg.addServerHeader(do.doId, self.ourChannel, STATESERVER_OBJECT_DELETE_RAM)
        dg.addUint32(do.doId)
        self.send(dg)
Example #15
0
 def sendDisconnect(self):
     if self.isConnected():
         # Tell the game server that we're going:
         datagram = PyDatagram()
         # Add message type
         datagram.addUint16(CLIENT_DISCONNECT)
         # Send the message
         self.send(datagram)
         self.notify.info("Sent disconnect message to server")
         self.disconnect()
     self.stopHeartbeat()
    def clientAddSessionObject(self, clientChannel, doId):
        """
        Declares the specified DistributedObject to be a "session object",
        meaning that it is destroyed when the client disconnects.
        Generally used for avatars owned by the client.
        """

        dg = PyDatagram()
        dg.addServerHeader(clientChannel, self.ourChannel, CLIENTAGENT_ADD_SESSION_OBJECT)
        dg.add_uint32(doId)
        self.send(dg)
Example #17
0
    def clearPostRemove(self):
        """
        Clear all datagrams registered with addPostRemove.

        This is useful if the Panda3D process is performing a clean exit. It may
        clear the "emergency clean-up" post-remove messages and perform a normal
        exit-time clean-up instead, depending on the specific design of the game.
        """

        dg = PyDatagram()
        dg.addServerControlHeader(CONTROL_CLEAR_POST_REMOVE)
        self.send(dg)
    def requestDelete(self, do):
        """
        Request the deletion of an object that already exists on the State Server.

        You should use do.requestDelete() instead. This is not meant to be
        called directly unless you really know what you are doing.
        """

        dg = PyDatagram()
        dg.addServerHeader(do.doId, self.ourChannel, STATESERVER_OBJECT_DELETE_RAM)
        dg.addUint32(do.doId)
        self.send(dg)
    def clearPostRemove(self):
        """
        Clear all datagrams registered with addPostRemove.

        This is useful if the Panda3D process is performing a clean exit. It may
        clear the "emergency clean-up" post-remove messages and perform a normal
        exit-time clean-up instead, depending on the specific design of the game.
        """

        dg = PyDatagram()
        dg.addServerControlHeader(CONTROL_CLEAR_POST_REMOVE)
        self.send(dg)
 def _sendRemoveInterest(self, contextId):
     """
     contextId is a client-side created number that refers to
             a set of interests.  The same contextId number doesn't
             necessarily have any relationship to the same contextId
             on another client.
     """
     assert self.notify.debugCall()
     datagram = PyDatagram()
     # Add message type
     datagram.addUint16(CLIENT_REMOVE_INTEREST)
     datagram.addUint16(contextId)
     self.send(datagram)
Example #21
0
 def _sendRemoveInterest(self, handle, contextId):
     datagram = PyDatagram()
     datagram.addUint16(CLIENT_REMOVE_INTEREST)
     datagram.addUint16(handle)
     if contextId != 0:
         datagram.addUint32(contextId)
     self.send(datagram)
Example #22
0
    def setInterestZones(self, interestZoneIds):
        """ Changes the set of zones that this particular client is
        interested in hearing about. """

        datagram = PyDatagram()
        # Add message type
        datagram.addUint16(CLIENT_SET_INTEREST_CMU)

        for zoneId in interestZoneIds:
            datagram.addUint32(zoneId)

        # send the message
        self.send(datagram)
        self.interestZones = interestZoneIds[:]
 def sendSetLocation(self, do, parentId, zoneId):
     dg = PyDatagram()
     dg.addServerHeader(do.doId, self.ourChannel,
                        STATESERVER_OBJECT_SET_LOCATION)
     dg.addUint32(parentId)
     dg.addUint32(zoneId)
     self.send(dg)
    def unregisterForChannel(self, channel):
        """
        Unregister a channel subscription on the Message Director. The Message
        Director will cease to relay messages to this AIR sent on the channel.
        """

        if channel not in self._registeredChannels:
            return
        self._registeredChannels.remove(channel)

        dg = PyDatagram()
        dg.addServerControlHeader(CONTROL_REMOVE_CHANNEL)
        dg.addChannel(channel)
        self.send(dg)
    def addPostRemove(self, dg):
        """
        Register a datagram with the Message Director that gets sent out if the
        connection is ever lost.

        This is useful for registering cleanup messages: If the Panda3D process
        ever crashes unexpectedly, the Message Director will detect the socket
        close and automatically process any post-remove datagrams.
        """

        dg2 = PyDatagram()
        dg2.addServerControlHeader(CONTROL_ADD_POST_REMOVE)
        dg2.addString(dg.getMessage())
        self.send(dg2)
    def clientAddInterest(self, clientChannel, interestId, parentId, zoneId):
        """
        Opens an interest on the behalf of the client. This, used in conjunction
        with add_interest: visible (or preferably, disabled altogether), will mitigate
        possible security risks.
        """

        dg = PyDatagram()
        dg.addServerHeader(clientChannel, self.ourChannel,
                           CLIENTAGENT_ADD_INTEREST)
        dg.add_uint16(interestId)
        dg.add_uint32(parentId)
        dg.add_uint32(zoneId)
        self.send(dg)
    def registerForChannel(self, channel):
        """
        Register for messages on a specific Message Director channel.

        If the channel is already open by this AIR, nothing will happen.
        """

        if channel in self._registeredChannels:
            return
        self._registeredChannels.add(channel)

        dg = PyDatagram()
        dg.addServerControlHeader(CONTROL_ADD_CHANNEL)
        dg.addChannel(channel)
        self.send(dg)
        def _sendAddInterest(self, contextId, parentId, zoneId):
            """
            Part of the new otp-server code.

            contextId is a client-side created number that refers to
                    a set of interests.  The same contextId number doesn't
                    necessarily have any relationship to the same contextId
                    on another client.
            """
            datagram = PyDatagram()
            # Add message type
            datagram.addUint16(CLIENT_ADD_INTEREST)
            datagram.addUint16(contextId)
            datagram.addUint32(parentId)
            datagram.addUint32(zoneId)
            self.send(datagram)
    def getNetworkAddress(self, clientId, callback):
        """
        Get the endpoints of a client connection.

        You should already be sure the client actually exists, otherwise the
        callback will never be called.

        Callback is called as: callback(remoteIp, remotePort, localIp, localPort)
        """

        ctx = self.getContext()
        self.__callbacks[ctx] = callback
        dg = PyDatagram()
        dg.addServerHeader(clientId, self.ourChannel, CLIENTAGENT_GET_NETWORK_ADDRESS)
        dg.addUint32(ctx)
        self.send(dg)
    def getLocation(self, doId, callback):
        """
        Ask a DistributedObject where it is.

        You should already be sure the object actually exists, otherwise the
        callback will never be called.

        Callback is called as: callback(doId, parentId, zoneId)
        """

        ctx = self.getContext()
        self.__callbacks[ctx] = callback
        dg = PyDatagram()
        dg.addServerHeader(doId, self.ourChannel, STATESERVER_OBJECT_GET_LOCATION)
        dg.addUint32(ctx)
        self.send(dg)
    def getActivated(self, doId, callback):
        ctx = self.getContext()
        self.__callbacks[ctx] = callback

        dg = PyDatagram()
        dg.addServerHeader(doId, self.ourChannel, DBSS_OBJECT_GET_ACTIVATED)
        dg.addUint32(ctx)
        dg.addUint32(doId)
        self.send(dg)
Example #32
0
 def __getBarrierData(self):
     # Returns the barrier data formatted as a blob for sending to
     # the clients.  This lists all of the current outstanding
     # barriers and the avIds waiting for them.
     dg = PyDatagram()
     for context, barrier in self.__barriers.items():
         toons = barrier.pendingToons
         if toons:
             dg.addUint16(context)
             dg.addUint16(len(toons))
             for avId in toons:
                 dg.addUint32(avId)
     return dg.getMessage()
    def clientAddInterest(self, clientChannel, interestId, parentId, zoneId):
        """
        Opens an interest on the behalf of the client. This, used in conjunction
        with add_interest: visible (or preferably, disabled altogether), will mitigate
        possible security risks.
        """

        dg = PyDatagram()
        dg.addServerHeader(clientChannel, self.ourChannel, CLIENTAGENT_ADD_INTEREST)
        dg.add_uint16(interestId)
        dg.add_uint32(parentId)
        dg.add_uint32(zoneId)
        self.send(dg)
    def __connected(self):
        self.notify.info('Connected successfully.')

        # Listen to our channel...
        self.registerForChannel(self.ourChannel)

        # If we're configured with a State Server, register a post-remove to
        # clean up whatever objects we own on this server should we unexpectedly
        # fall over and die.
        if self.serverId:
            dg = PyDatagram()
            dg.addServerHeader(self.serverId, self.ourChannel, STATESERVER_DELETE_AI_OBJECTS)
            dg.addChannel(self.ourChannel)
            self.addPostRemove(dg)

        messenger.send('airConnected')
        self.handleConnected()
    def eject(self, clientChannel, reasonCode, reason):
        """
        Kicks the client residing at the specified clientChannel, using the specifed reasoning.
        """

        dg = PyDatagram()
        dg.addServerHeader(clientChannel, self.ourChannel, CLIENTAGENT_EJECT)
        dg.add_uint16(reasonCode)
        dg.addString(reason)
        self.send(dg)
 def _sendRemoveInterest(self, handle, contextId):
     datagram = PyDatagram()
     datagram.addUint16(CLIENT_REMOVE_INTEREST)
     datagram.addUint16(handle)
     if contextId != 0:
         datagram.addUint32(contextId)
     self.send(datagram)
Example #37
0
    def setAllowClientSend(self, avId, dObj, fieldNameList=[]):
        """
        Overrides the security of a field(s) specified, allows an owner of a DistributedObject to send
        the field(s) regardless if its marked ownsend/clsend.
        """

        dg = PyDatagram()
        dg.addServerHeader(dObj.GetPuppetConnectionChannel(avId),
                           self.ourChannel, CLIENTAGENT_SET_FIELDS_SENDABLE)
        fieldIds = []
        for fieldName in fieldNameList:
            field = dObj.dclass.getFieldByName(fieldName)
            if field:
                fieldIds.append(field.getNumber())
        dg.addUint32(dObj.getDoId())
        dg.addUint16(len(fieldIds))
        for fieldId in fieldIds:
            dg.addUint16(fieldId)
        self.send(dg)
Example #38
0
        def _sendAddInterest(self, contextId, parentId, zoneId):
            """
            Part of the new otp-server code.

            contextId is a client-side created number that refers to
                    a set of interests.  The same contextId number doesn't
                    necessarily have any relationship to the same contextId
                    on another client.
            """
            datagram = PyDatagram()
            # Add message type
            datagram.addUint16(CLIENT_ADD_INTEREST)
            datagram.addUint16(contextId)
            datagram.addUint32(parentId)
            datagram.addUint32(zoneId)
            self.send(datagram)
    def getActivated(self, doId, callback):
        ctx = self.getContext()
        self.__callbacks[ctx] = callback

        dg = PyDatagram()
        dg.addServerHeader(doId, self.ourChannel, DBSS_OBJECT_GET_ACTIVATED)
        dg.addUint32(ctx)
        dg.addUint32(doId)
        self.send(dg)
    def eject(self, clientChannel, reasonCode, reason):
        """
        Kicks the client residing at the specified clientChannel, using the specifed reasoning.
        """

        dg = PyDatagram()
        dg.addServerHeader(clientChannel, self.ourChannel, CLIENTAGENT_EJECT)
        dg.add_uint16(reasonCode)
        dg.addString(reason)
        self.send(dg)
Example #41
0
    def writeServerEvent(self, logtype, *args):
        """
        Write an event to the central Event Logger, if one is configured.

        The purpose of the Event Logger is to keep a game-wide record of all
        interesting in-game events that take place. Therefore, this function
        should be used whenever such an interesting in-game event occurs.
        """

        if self.eventSocket is None:
            return  # No event logger configured!

        dg = PyDatagram()
        dg.addString(self.eventLogId)
        dg.addString(logtype)
        for arg in args:
            dg.addString(str(arg))
        self.eventSocket.Send(dg.getMessage())
    def sendDeleteMsg(self, doId):
        # This method is only used in conjunction with the CMU LAN
        # server.

        datagram = PyDatagram()
        datagram.addUint16(CLIENT_OBJECT_DELETE)
        datagram.addUint32(doId)
        self.send(datagram)
    def addPostRemove(self, dg):
        """
        Register a datagram with the Message Director that gets sent out if the
        connection is ever lost.

        This is useful for registering cleanup messages: If the Panda3D process
        ever crashes unexpectedly, the Message Director will detect the socket
        close and automatically process any post-remove datagrams.
        """

        dg2 = PyDatagram()
        dg2.addServerControlHeader(CONTROL_ADD_POST_REMOVE)
        dg2.addUint64(self.ourChannel)
        dg2.addString(dg.getMessage())
        self.send(dg2)
Example #44
0
    def setInterestZones(self, interestZoneIds):
        datagram = PyDatagram()
        datagram.addUint16(CLIENT_SET_INTEREST_CMU)
        for zoneId in interestZoneIds:
            datagram.addUint32(zoneId)

        self.send(datagram)
        self.interestZones = interestZoneIds[:]
 def sendSetShardMsg(self, shardId):
     datagram = PyDatagram()
     # Add message type
     datagram.addUint16(CLIENT_SET_SHARD)
     # Add shard id
     datagram.addUint32(shardId)
     # send the message
     self.send(datagram)
Example #46
0
 def sendUpdateToChannel(self, distObj, channelId, fieldName, args):
     datagram = distObj.dclass.clientFormatUpdate(fieldName, distObj.doId, args)
     dgi = PyDatagramIterator(datagram)
     dgi.getUint16()
     dg = PyDatagram()
     dg.addUint16(CLIENT_OBJECT_UPDATE_FIELD_TARGETED_CMU)
     dg.addUint32(channelId & 4294967295L)
     dg.appendData(dgi.getRemainingBytes())
     self.send(dg)
        def sendSetZoneMsg(self, zoneId, visibleZoneList=None):
            datagram = PyDatagram()
            # Add message type
            datagram.addUint16(CLIENT_SET_ZONE)
            # Add zone id
            datagram.addUint32(zoneId)

            # if we have an explicit list of visible zones, add them
            if visibleZoneList is not None:
                vzl = list(visibleZoneList)
                vzl.sort()
                assert PythonUtil.uniqueElements(vzl)
                for zone in vzl:
                    datagram.addUint32(zone)

            # send the message
            self.send(datagram)
Example #48
0
    def getObject(self, doId, callback):
        """
        Get the entire state of an object.

        You should already be sure the object actually exists, otherwise the
        callback will never be called.

        Callback is called as: callback(doId, parentId, zoneId, dclass, fields)
        """

        ctx = self.getContext()
        self.__callbacks[ctx] = callback
        dg = PyDatagram()
        dg.addServerHeader(doId, self.ourChannel, STATESERVER_OBJECT_GET_ALL)
        dg.addUint32(ctx)
        dg.addUint32(doId)
        self.send(dg)
    def setAI(self, doId, aiChannel):
        """
        Sets the AI of the specified DistributedObjectAI to be the specified channel.
        Generally, you should not call this method, and instead call DistributedObjectAI.setAI.
        """

        dg = PyDatagram()
        dg.addServerHeader(doId, aiChannel, STATESERVER_OBJECT_SET_AI)
        dg.add_uint64(aiChannel)
        self.send(dg)
Example #50
0
 def _sendRemoveAIInterest(self, handle):
     """
     handle is a bare int, NOT an InterestHandle.  Use this to
     close an AI opened interest.
     """
     datagram = PyDatagram()
     # Add message type
     datagram.addUint16(CLIENT_REMOVE_INTEREST)
     datagram.addUint16((1<<15) + handle)
     self.send(datagram)
    def setOwner(self, doId, newOwner):
        """
        Sets the owner of a DistributedObject. This will enable the new owner to send "ownsend" fields,
        and will generate an OwnerView.
        """

        dg = PyDatagram()
        dg.addServerHeader(doId, self.ourChannel, STATESERVER_OBJECT_SET_OWNER)
        dg.add_uint64(newOwner)
        self.send(dg)
    def sendRemoveZoneMsg(self, zoneId, visibleZoneList=None):
        # This method is only used in conjunction with the CMU LAN
        # server.

        datagram = PyDatagram()
        datagram.addUint16(CLIENT_REMOVE_ZONE)
        datagram.addUint32(zoneId)

        # if we have an explicit list of visible zones, add them
        if visibleZoneList is not None:
            vzl = list(visibleZoneList)
            vzl.sort()
            assert PythonUtil.uniqueElements(vzl)
            for zone in vzl:
                datagram.addUint32(zone)

        # send the message
        self.send(datagram)
    def writeServerEvent(self, logtype, *args):
        """
        Write an event to the central Event Logger, if one is configured.

        The purpose of the Event Logger is to keep a game-wide record of all
        interesting in-game events that take place. Therefore, this function
        should be used whenever such an interesting in-game event occurs.
        """

        if self.eventSocket is None:
            return # No event logger configured!

        dg = PyDatagram()
        dg.addString(self.eventLogId)
        dg.addString(logtype)
        for arg in args:
            dg.addString(str(arg))
        self.eventSocket.Send(dg.getMessage())
    def setClientState(self, clientChannel, state):
        """
        Sets the state of the client on the CA.
        Useful for logging in and logging out, and for little else.
        """

        dg = PyDatagram()
        dg.addServerHeader(clientChannel, self.ourChannel,
                           CLIENTAGENT_SET_STATE)
        dg.add_uint16(state)
        self.send(dg)
    def clientAddSessionObject(self, clientChannel, doId):
        """
        Declares the specified DistributedObject to be a "session object",
        meaning that it is destroyed when the client disconnects.
        Generally used for avatars owned by the client.
        """

        dg = PyDatagram()
        dg.addServerHeader(clientChannel, self.ourChannel,
                           CLIENTAGENT_ADD_SESSION_OBJECT)
        dg.add_uint32(doId)
        self.send(dg)
Example #56
0
    def requestDelete(self, do):
        """
        Request the deletion of an object that already exists on the State Server.

        You should probably use do.requestDelete() instead.
        """

        dg = PyDatagram()
        dg.addServerHeader(do.doId, self.ourChannel,
                           STATESERVER_OBJECT_DELETE_RAM)
        dg.addUint32(do.doId)
        self.send(dg)
    def sendWorldPos(self, x, y):
        # The server will need to know the world
        # offset of our current render node path
        # and adjust the x, y accordingly.  At one
        # point I considered adding the world offset
        # here, but that would just use extra bits.

        onScreenDebug.add("worldPos", "%-4d, %-4d" % (x, y))
        return  #*#

        datagram = PyDatagram()
        # Add message type
        datagram.addUint16(CLIENT_SET_WORLD_POS)
        # Add x
        datagram.addInt16(x)
        # Add y
        datagram.addSint16(y)
        # send the message
        self.send(datagram)
Example #58
0
        def sendSetZoneMsg(self, zoneId, visibleZoneList=None):
            datagram = PyDatagram()
            # Add message type
            datagram.addUint16(CLIENT_SET_ZONE)       
            # Add zone id
            datagram.addUint32(zoneId)
    
            # if we have an explicit list of visible zones, add them
            if visibleZoneList is not None:
                vzl = list(visibleZoneList)
                vzl.sort()
                assert PythonUtil.uniqueElements(vzl)
                for zone in vzl:
                    datagram.addUint32(zone)

            # send the message
            self.send(datagram)