2017-07-14 7 views
0

クラスを使用するのが始まりです。私はいつも別の方法を見つけました。昨日、私は必要なコードを正確に見つけましたが、それは素敵なクラスに入っていて、アクセスする方法を理解できません。私はここですべてのチュートリアルや同様のソリューションを読みました。私はちょうどそれの周りに私の頭を包むことはできません。私が書いた唯一の部分は、動作しない部分であるmain()です。私は主な数十の方法を書き直しました、そして、私は彼らが働くことを期待している方法で働いていません。Pythonエラー「最初の引数としてインスタンスを使用してバインドされていないメソッドを呼び出す必要があります」

ありがとうございました。

すべてのクレジットはネイサン・アダムスに行く - dinnerbone

import socket 
import struct 

class MinecraftQuery: 
    MAGIC_PREFIX = '\xFE\xFD' 
    PACKET_TYPE_CHALLENGE = 9 
    PACKET_TYPE_QUERY = 0 
    HUMAN_READABLE_NAMES = dict(
     game_id  = "Game Name", 
     gametype = "Game Type", 
     motd  = "Message of the Day", 
     hostname = "Server Address", 
     hostport = "Server Port", 
     map   = "Main World Name", 
     maxplayers = "Maximum Players", 
     numplayers = "Players Online", 
     players  = "List of Players", 
     plugins  = "List of Plugins", 
     raw_plugins = "Raw Plugin Info", 
     software = "Server Software", 
     version  = "Game Version", 
    ) 

    def __init__(self, host, port, timeout=10, id=0, retries=2): 
     self.addr = (host, port) 
     self.id = id 
     self.id_packed = struct.pack('>l', id) 
     self.challenge_packed = struct.pack('>l', 0) 
     self.retries = 0 
     self.max_retries = retries 

     self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
     self.socket.settimeout(timeout) 

    def send_raw(self, data): 
     self.socket.sendto(self.MAGIC_PREFIX + data, self.addr) 

    def send_packet(self, type, data=''): 
     self.send_raw(struct.pack('>B', type) + self.id_packed + self.challenge_packed + data) 

    def read_packet(self): 
     buff = self.socket.recvfrom(1460)[0] 
     type = struct.unpack('>B', buff[0])[0] 
     id = struct.unpack('>l', buff[1:5])[0] 
     return type, id, buff[5:] 

    def handshake(self, bypass_retries=False): 
     self.send_packet(self.PACKET_TYPE_CHALLENGE) 

     try: 
      type, id, buff = self.read_packet() 
     except: 
      if not bypass_retries: 
       self.retries += 1 

      if self.retries < self.max_retries: 
       self.handshake(bypass_retries=bypass_retries) 
       return 
      else: 
       raise 

     self.challenge = int(buff[:-1]) 
     self.challenge_packed = struct.pack('>l', self.challenge) 

    def get_status(self): 
     if not hasattr(self, 'challenge'): 
      self.handshake() 

     self.send_packet(self.PACKET_TYPE_QUERY) 

     try: 
      type, id, buff = self.read_packet() 
     except: 
      self.handshake() 
      return self.get_status() 

     data = {} 

     data['motd'], data['gametype'], data['map'], data['numplayers'], data['maxplayers'], buff = buff.split('\x00', 5) 
     data['hostport'] = struct.unpack('<h', buff[:2])[0] 
     buff = buff[2:] 
     data['hostname'] = buff[:-1] 

     for key in ('numplayers', 'maxplayers'): 
      try: 
       data[key] = int(data[key]) 
      except: 
       pass 

     return data 

    def get_rules(self): 
     if not hasattr(self, 'challenge'): 
      self.handshake() 

     self.send_packet(self.PACKET_TYPE_QUERY, self.id_packed) 

     try: 
      type, id, buff = self.read_packet() 
     except: 
      self.retries += 1 
      if self.retries < self.max_retries: 
       self.handshake(bypass_retries=True) 
       return self.get_rules() 
      else: 
       raise 

     data = {} 

     buff = buff[11:] # splitnum + 2 ints 
     items, players = buff.split('\x00\x00\x01player_\x00\x00') # Shamefully stole from https://github.com/barneygale/MCQuery 

     if items[:8] == 'hostname': 
      items = 'motd' + items[8:] 

     items = items.split('\x00') 
     data = dict(zip(items[::2], items[1::2])) 

     players = players[:-2] 

     if players: 
      data['players'] = players.split('\x00') 
     else: 
      data['players'] = [] 

     for key in ('numplayers', 'maxplayers', 'hostport'): 
      try: 
       data[key] = int(data[key]) 
      except: 
       pass 

     data['raw_plugins'] = data['plugins'] 
     data['software'], data['plugins'] = self.parse_plugins(data['raw_plugins']) 

     return data 

    def parse_plugins(self, raw): 
     parts = raw.split(':', 1) 
     server = parts[0].strip() 
     plugins = [] 

     if len(parts) == 2: 
      plugins = parts[1].split(';') 
      plugins = map(lambda s: s.strip(), plugins) 

     return server, plugins 

def main(): 
    check = MinecraftQuery.get_status('10.0.10.8',25565) 
    print check 

main() 
+0

クラスをインスタンス化してからメソッドを呼び出す必要があります。まず、MinecraftQuery(host、port)を使用して新しいインスタンスを作成します。ここで、hostとportは明らかにホスト名とポート名です。その後、その状態を呼び出します。 –

答えて

0

私は次のようになるはずです。それが動作するか試してみてください。

def main(): 
    check = MinecraftQuery('10.0.10.8', 25565) 
    # It calls the __init__() method and constructs an object/instance of the class named 'MinecraftQuery' 
    # using the given arguments and associate it with the given identifier 'check' 
    check.get_status() 
    # Now, this invokes the get_status() method of the instance named 'check'. 
    print check 
+1

はい!私はもはやmain()でエラーを取得しません。今、私はパケットを待っているタイムアウトエラーがあります。私はminecraftの別のバージョンのためにこれを微調整する必要があります。ありがとうございました! –

0

別名結合していないメソッドは、クラスのインスタンスで呼び出されていないものです。エラーは、インスタンスではなくクラスでメソッドを呼び出すことを意味します。そのため、まずクラスのインスタンスを作成してからメソッドを呼び出す必要があります。

関連する問題

 関連する問題