PoC Life
-
Автор темы
- #1
Перед прочтением основного контента ниже, пожалуйста, обратите внимание на обновление внутри секции Майна на нашем форуме. У нас появились:
- бесплатные читы для Майнкрафт — любое использование на свой страх и риск;
- маркетплейс Майнкрафт — абсолютно любая коммерция, связанная с игрой, за исключением продажи читов (аккаунты, предоставления услуг, поиск кодеров читов и так далее);
- приватные читы для Minecraft — в этом разделе только платные хаки для игры, покупайте группу "Продавец" и выставляйте на продажу свой софт;
- обсуждения и гайды — всё тот же раздел с вопросами, но теперь модернизированный: поиск нужных хаков, пати с игроками-читерами и другая полезная информация.
Спасибо!
Список:
1. Создаём главный класс + снимаем ограничения - https://yougame.biz/threads/325113
2. Автобус евентов - https://yougame.biz/threads/325114
3. OpenGL + Шейдеры + Рендер - https://yougame.biz/threads/325115
4. Аим - https://yougame.biz/threads/325188
5. GlowESP aka OpenGL Framebuffer - https://yougame.biz/threads/325211/
6. Текст, шрифты, атлас - https://yougame.biz/threads/325292
Теория
Сейчас расскажу про систему евентов и её полезность. Представим есть функция рендера:
Чтобы не писать такой грязный код:
Вы можете просто вызвать евент. Евент - это просто класс, который содержит в себе полезные данные, чтобы вы в дальнейшем использовали их в listener'е. Listener (дословно слушатель) - это класс, который обрабатывает один или несколько евентов. Когда вызывается евент, он собирает все зарегистрированные listener'ы и вызывает обработку евента в них.
Практика
Можно приступать к написанию кода.
Сделаем интерфейс listener'а:
Автобус евентов прям так и назовём:
В нём будет список listener'ов:
| Изучаем библиотеки
| Майнкрафт использует библиотеку guava, в которой есть удобные классы для работы с коллекциями: Lists, Sets, Maps
Интерфейс евента:
А также вызов евента:
Не забываем, что существует другой тип евентов, которые можно отменять. Для этого создадим новый класс для отменяемых евентов:
Ну теперь всё, для проверки создадим тестовый event, listener и попробуем вызвать:
Ставим бряк на onTest и проверяем:
Поздравляю, всё работает. Но НО есть одно НО, если я захочу написать вот так:
То евент вызовется два раза, потому что в первый раз его вызовет onTest, а второй раз его вызовет автобус, т.к. он также имеет TestEvent в аргументах. Поэтому я предлагаю помечать методы по аннотации:
В автобусе для stream'а добавим ещё один фильтр:
Теперь проверяем, ставим бряк на handleTest и при срабатывании нажимаем на кнопку продолжить, если далее ничего не произошло и начался запускаться майнкрафт, то handler (наш метод) вызвался один раз и вы всё сделали правильно.
Теперь, чтобы удобно обращаться к автобусу евентов определим его в нашем клиенте:
1. Создаём главный класс + снимаем ограничения - https://yougame.biz/threads/325113
2. Автобус евентов - https://yougame.biz/threads/325114
3. OpenGL + Шейдеры + Рендер - https://yougame.biz/threads/325115
4. Аим - https://yougame.biz/threads/325188
5. GlowESP aka OpenGL Framebuffer - https://yougame.biz/threads/325211/
6. Текст, шрифты, атлас - https://yougame.biz/threads/325292
Теория
Сейчас расскажу про систему евентов и её полезность. Представим есть функция рендера:
Java:
public void render() {
// Do render
}
Java:
public void render() {
watermark.render();
staffalert.render();
}
Практика
Можно приступать к написанию кода.
Сделаем интерфейс listener'а:
interface Listener {}
Автобус евентов прям так и назовём:
class EventBus {}
В нём будет список listener'ов:
Java:
class EventBus {
// Зарегистрированные listener'ы
private final Set<Listener> listeners;
public EventBus() {
this.listeners = Sets.newLinkedSet();
}
/*
Регистрация listener'а
*/
public void registerListener(Listener listener) {
this.listeners.add(listener);
}
}
| Майнкрафт использует библиотеку guava, в которой есть удобные классы для работы с коллекциями: Lists, Sets, Maps
Интерфейс евента:
interface Event {}
А также вызов евента:
Java:
ublic void callEvent(Event event) {
this.listeners.stream()
.flatMap(listener -> Stream.of(listener.getClass().getDeclaredMethods()) // Собриаем все методы
.map(method -> Map.entry(listener, method)) // И преобразуем в Entry<Listener, Method>, т.к. экземпляр listener'а нам понадобится, чтобы вызвать метод
)
.filter(entry -> entry.getValue().getParameterCount() == 1) // Проверяем имеет ли метод ровно 1 параметр
.filter(entry -> entry.getValue().getParameterTypes()[0].equals(event.getClass())) // Проверяем совпадает ли класс данного параметра с нашим евентом
.forEach(entry -> {
try {
entry.getValue().invoke(entry.getKey(), event); // Пытаемся вызвать евент
} catch (IllegalAccessException | InvocationTargetException exception) {
exception.printStackTrace(); // В случае ошибки выводим её
}
});
}
Java:
class CancellableEvent implements Event {
private boolean cancelled;
public boolean isCancelled() {
return this.cancelled;
}
public void cancel() {
this.cancelled = true;
}
}
Java:
public class TestEvent implements Event {}
public class TestListener implements Listener {
public void onTest(TestEvent event) {
}
}
...
eventBus.registerListener(new TestListener());
eventBus.callEvent(new TestEvent());
Поздравляю, всё работает. Но НО есть одно НО, если я захочу написать вот так:
То евент вызовется два раза, потому что в первый раз его вызовет onTest, а второй раз его вызовет автобус, т.к. он также имеет TestEvent в аргументах. Поэтому я предлагаю помечать методы по аннотации:
Java:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface EventHandler {}
@EventHandler
public void onTest(TestEvent event) {
handleTest(event);
}
.filter(entry -> entry.getValue().isAnnotationPresent(EventHandler.class))
Теперь проверяем, ставим бряк на handleTest и при срабатывании нажимаем на кнопку продолжить, если далее ничего не произошло и начался запускаться майнкрафт, то handler (наш метод) вызвался один раз и вы всё сделали правильно.
Теперь, чтобы удобно обращаться к автобусу евентов определим его в нашем клиенте:
Java:
private final EventBus eventBus;
public LearnClient() {
this.eventBus = new EventBus();
}
Последнее редактирование: