2016-06-17 3 views
-1

Это исходный код сервера Minecraft, также называемый API Minecraft Bukkit, теперь вы знаете столько, сколько я.Как создается этот интерфейс?

Существует интерфейс называется Сервер:

public interface Server extends PluginMessegeRecipient { 
    public String getVersion(); 
} 

PluginMessageRecipient представляет собой интерфейс также.

Существует класс называется Bukkit, который конкретизирует сервер:

public final class Bukkit { 
    private static Server server; 

} 

Внутренние методы в классе Bucket они вызывают методы объекта-сервера. Например:

server.getVersion(); 

Дело в том, что нет кода для getVersion в интерфейсе сервера, это всего лишь подпись метода. Также нет кода в интерфейсе PluginMessageRecipient и не распространяется ни на что.

Я прочитал все вопросы и ответы на SO, которые говорят, что мне нужен анонимный класс или внутренний класс, и это, похоже, не подходит для этих решений.

+1

Я подозреваю, что 'server' идет экземпляр к реализующему классу' интерфейса Server' в каком-то момент. Например: 'Bucket.server = new VersionFiveServer()' и 'VersionFiveServer реализует сервер'. – CollinD

+1

Сервер - это интерфейс, поэтому он не будет иметь код. У него будет только подпись метода. Вот что такое интерфейс. Некоторые другие классы реализуют этот интерфейс и содержат код. – ManoDestra

+0

Связанный: http://stackoverflow.com/questions/383947/what-does-it-mean-to-program-to-an-interface –

ответ

1

Существует класс называется Bucket, что конкретизирует сервер:

Bucket На самом деле не создает экземпляр Server. Класс Bucket содержит ссылку на Server. Вы не показали, как это было установлено, поэтому мы не знаем настоящего класса.

Однако, это гарантирует, что является присвоен этой ссылке (Bucket.server), при условии, что это не null, является объектом какого-либо конкретного класса, который реализует Server. Этот класс обеспечит реализацию getVersion(), и это то, что вызывается.

+0

«Класс Bucket содержит ссылку на сервер. Вы не показали, как это установлено, поэтому мы не знаем фактического класса». - Нет. Я не могу показать это. Это мой вопрос. – nicomp

+0

Он был установлен где-то, так что «Не существует» - это ложь на лице. Вы говорите, что это API, поэтому, несомненно, был где-то звонок или файл конфигурации (XML, JSON, свойства, ...) где-то или вариант командной строки где-то, в сочетании с каким-то кодом инициализации где-то, реализующий класс. Вы его еще не нашли. Вы пробовали документацию по API? –

0

Bukkit - это просто модификатор API. Если вы хотите реализовать Bukkit, вам нужно создать такой экземпляр самостоятельно и передать его там.

Возьмем, например, модульные тесты, которые Bukkit включает в себя: https://github.com/Bukkit/Bukkit/blob/f210234e59275330f83b994e199c76f6abd41ee7/src/test/java/org/bukkit/TestServer.java#L77

Реальная реализация, которая позволяет запускать сервер Bukkit является Spigot.

0

Если я правильно помню, конкретный конкретный класс, который выбирается, определяется во время выполнения через отражение. Поскольку Minecraft не является открытым исходным кодом, все разработчики являются обфускамированными скомпилированными файлами классов для работы.

Код выполняет поиск по каждому файлу класса внутри фрейма minecraft, ищет класс, соответствующий определенным условиям, а затем, используя библиотеку байт-кода, заставляет этот класс реализовать этот интерфейс.

Например, допустим, что следующий (затемненный) класс был реальногоServer класса в коде Minecraft

class a { 

    String x_x317() { 
     return q_q98; 
    } 

    static a a_a1; 
    static String q_q98 = "1.9.4"; 
} 

В этом случае метод x_x317 возвращает строку версии. Инструмент, который позволяет им тоже вклиниться в этот класс может сделать это на основе следующих условий:

  1. класс имеет доступ по умолчанию
  2. класс имеет только один по умолчанию доступ статическую ссылку на себя
  3. класс имеет только одно статическое поле String по умолчанию.
  4. Класс имеет единственный метод, который имеет доступ по умолчанию, который возвращает String, а возвращаемое значение является FieldRef найдено в 3.

Это обычно возвращает только один класс. В случае возвращения нескольких (обычно в фазе dev новой версии Bukkit) они становятся более конкретными с их условиями, чтобы гарантировать, что они вернут правильный класс. Они делают это для каждого поля, класса и метода, которые они должны идентифицировать.

Поскольку теперь они знают, какой именно класс является классом Server, они могут идти дальше и вносить в него изменения. Во-первых, они должны были бы реализовать интерфейс

class a implements org.bukkit.Server 

А затем реализовать метод

class a implements org.bukkit.Server { 

    String x_x317() { 
     return q_q98; 
    } 

    public String getVersionNumber() { 
     return x_x317(); 
    } 

    static a a_a1; 
    static String q_q98 = "1.9.4"; 
} 

Теперь у нас есть класс, который соответствует API Bukkit.

Когда им нужно создать экземпляр этого класса, они просто делают что-то вдоль линий

Server server = findAndTransformServerClassFromMinecraftJar(); 

// ... 

Server findAndTransformServerClassFromMinecraftJar() { 
    // load classes from jar 
    // map them to the appropriate interfaces 
    // transform and hook the required classes and methods 

    Class<?> serverClass = doTheFirstThreeSteps(); 

    return (Server) serverClass.newInstance(); 
} 
+0

На самом деле, bukkit работает с уже деформированной банкой (и имеет конкретную реализацию «CraftServer», которая является обычаем, хотя другие части CraftBukkit ссылаются на код ванили) – Pokechu22

Смежные вопросы