1. Этот сайт использует файлы cookie. Продолжая пользоваться данным сайтом, Вы соглашаетесь на использование нами Ваших файлов cookie. Узнать больше.
  2. Вы находитесь в сообществе Rubukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на различные языки плагины наших коллег из других стран.
    Скрыть объявление
Скрыть объявление
В преддверии глобального обновления, мы проводим исследования, которые помогут нам сделать опыт пользования форумом ещё удобнее. Помогите нам, примите участие!

Как написать мониторинг майнкарфт сервера на Delphi?

Тема в разделе "Управление сервером Bukkit", создана пользователем MrZipner, 26 июн 2015.

  1. Автор темы
    MrZipner

    MrZipner Активный участник Пользователь

    Баллы:
    78
    Как написать мониторинг майнкарфт сервера на Delphi? Знания есть, но не глубокие. Помогите пожалуйста.
     
  2. Автор темы
    MrZipner

    MrZipner Активный участник Пользователь

    Баллы:
    78
  3. Firkys

    Firkys Активный участник Пользователь

    Баллы:
    88
    Skype:
    Firkys
    Имя в Minecraft:
    Firkys
    В каких целях?
     
  4. Автор темы
    MrZipner

    MrZipner Активный участник Пользователь

    Баллы:
    78
    Для своего лаунчера.
     
  5. Firkys

    Firkys Активный участник Пользователь

    Баллы:
    88
    Skype:
    Firkys
    Имя в Minecraft:
    Firkys
    Гугли про сокет
     
  6. Автор темы
    MrZipner

    MrZipner Активный участник Пользователь

    Баллы:
    78
    Я полный нуб...
     
  7. HoShiMin

    HoShiMin Старожил Пользователь

    Баллы:
    173
    Окей, Хош, как написать мониторинг?
    А вот так:
    Код:
    unit ServerQuery;
    
    interface
    
    uses
      Windows, SysUtils, WinSock2, CodepageAPI;
    
    type
      TServerInfo = record
        IsActive: Boolean;
        MOTD: string;
        MaxPlayers: string;
        CurrentPlayers: string;
      end;
    
    function GetServerInfo(IP: AnsiString; Port: Word; out ServerInfo: TServerInfo; Timeout: Word = 0): Boolean;
    
    
    implementation
    
    function DNStoIP(Host: PAnsiChar): PAnsiChar;
    var
      HostEnt: PHostEnt;
    begin
      HostEnt := GetHostByName(Host);
      Result := inet_ntoa(PInAddr(HostEnt^.h_addr_list^)^);
    end;
    
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    
    function GetServerInfo(IP: AnsiString; Port: Word; out ServerInfo: TServerInfo; Timeout: Word = 0): Boolean;
    var
      Socket: TSocket;
      SockAddr: TSockAddrIn;
    
      FDSetW: TFDSet;
      FDSetE: TFDSet;
      TimeVal: TTimeVal;
      NonBlockingMode: Cardinal;
    
      ConnectionStatus: Boolean;
    
      RequestPackage: Word;
      Size: Integer;
      Buffer: Pointer;
    
      Response: string;
    
      StringLen: LongWord;
      Position: LongWord;
    
      I: Integer;
    const
      BufferSize: LongWord = 1024;
    
    begin
      Result := False;
      FillChar(ServerInfo, SizeOf(ServerInfo), #0);
    
      // Пытаемся установить соединение:
      Socket := WinSock2.socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
      if Socket = INVALID_SOCKET then
      begin
        Shutdown(Socket, SD_BOTH);
        CloseSocket(Socket);
        Exit;
      end;
    
      IP := DNStoIP(PAnsiChar(IP));
    
      FillChar(SockAddr, SizeOf(SockAddr), #0);
      SockAddr.sin_family := AF_INET;
      SockAddr.sin_port := htons(Port);
      SockAddr.sin_addr.S_addr := inet_addr(PAnsiChar(IP));
    
      // Подключаемся:
      ConnectionStatus := False;
      if Timeout > 0 then
      begin
        NonBlockingMode := 1;
        IoCtlSocket(Socket, Integer(FIONBIO), NonBlockingMode);
        if WinSock2.connect(Socket, TSockAddr(SockAddr), SizeOf(TSockAddr)) <> 0 then
        begin
          FD_ZERO(FDSetW);
          FD_ZERO(FDSetE);
          _FD_SET(Socket, FDSetW);
          _FD_SET(Socket, FDSetE);
          TimeVal.tv_sec  := Timeout div 1000;
          TimeVal.tv_usec := (Timeout mod 1000) * 1000;
          select(0, nil, @FDSetW, @FDSetE, @TimeVal);
          ConnectionStatus := FD_ISSET(Socket, FDSetW);
        end;
        NonBlockingMode := 0;
        IoCtlSocket(Socket, Integer(FIONBIO), NonBlockingMode);
      end
      else
      begin
        ConnectionStatus := WinSock2.connect(Socket, TSockAddr(SockAddr), SizeOf(TSockAddr)) = 0;
      end;
    
      if not ConnectionStatus then Exit;
    
      // Посылаем данные:
      RequestPackage := $01FE;
      Send(Socket, RequestPackage, 2, 0);
    
      // Ждём ответ:
      GetMem(Buffer, BufferSize);
      FillChar(Buffer^, BufferSize, #0);
    
      Size := Recv(Socket, Buffer^, BufferSize, 0);
    
      // Закрываем соединение:
      Shutdown(Socket, SD_BOTH);
      CloseSocket(Socket);
    
      if (Size = SOCKET_ERROR) or (Size = 0) then
      begin
        FreeMem(Buffer);
        Exit;
      end;
    
      // Блок получили, можно парсить:
      Result := True;
      ServerInfo.IsActive := True;
    
    // Для начала переведём наш блок в ANSI:
    
      // Нуль-терминаторы переведём в $A7 (аналог запроса $FE):
      I := 0;
      while I < Size do
      begin
        if Word(Pointer((NativeInt(Buffer) + I))^) = 0 then
          Word(Pointer((NativeInt(Buffer) + I))^) := Word(Pointer((NativeInt(Buffer) + I))^) or $00A7;
        Inc(I, 2);
      end;
    
      Response := PChar(Buffer);
      FreeMem(Buffer);
    
    // Выделяем нужные блоки:
    
      // Получаем максимальное количество игроков:
      StringLen := Length(Response);
      Position := LastDelimiter(#$A7, Response);
      ServerInfo.MaxPlayers := Copy(Response, Position + 1, StringLen - Position);
    
      // Удаляем скопированную строку:
      Response := Copy(Response, 1, Position - 1);
    
      // Получаем количество игроков на сервере в данный момент:
      StringLen := Length(Response);
      Position := LastDelimiter(#$A7, Response);
      ServerInfo.CurrentPlayers := Copy(Response, Position + 1, StringLen - Position);
    
      // Удаляем скопированную строку:
      Response := Copy(Response, 1, Position - 1);
    
      // Получаем MOTD:
      StringLen := Length(Response);
      ServerInfo.MOTD := Copy(Response, 3, StringLen - 2);
    end;
    
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    
    function InitWinSock: Integer;
    var
      WSAData: TWSAData;
    begin
      Result := WSAStartup($202, WSAData);
    end;
    
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    
    initialization
    begin
      InitWinSock;
    end;
    
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    
    finalization
    begin
      WSACleanup;
    end;
    
    end.
    
    
     
  8. Автор темы
    MrZipner

    MrZipner Активный участник Пользователь

    Баллы:
    78
    Таак.... Чёт малость подозрительно.
     
  9. HoShiMin

    HoShiMin Старожил Пользователь

    Баллы:
    173
    Подозрительно? Подозрительно то, что ты просишь модуль с мониторингом. Куда же ты его навешивать-то собрался?
    Что-то здесь не сходится, на какой же лаунчер?.. Хммммм...
     
  10. CraftChel

    CraftChel Новичок Пользователь

    Баллы:
    21
    Имя в Minecraft:
    CraftChel
    Ты хочешь сделать обычную полосу онлайна?
     

Поделиться этой страницей