Гайд Своя $$$база Forge 1.16.5

Forge Api ;-;
Начинающий
Статус
Оффлайн
Регистрация
3 Май 2023
Сообщения
776
Реакции[?]
18
Поинты[?]
13K

Перед прочтением основного контента ниже, пожалуйста, обратите внимание на обновление внутри секции Майна на нашем форуме. У нас появились:

  • бесплатные читы для Майнкрафт — любое использование на свой страх и риск;
  • маркетплейс Майнкрафт — абсолютно любая коммерция, связанная с игрой, за исключением продажи читов (аккаунты, предоставления услуг, поиск кодеров читов и так далее);
  • приватные читы для Minecraft — в этом разделе только платные хаки для игры, покупайте группу "Продавец" и выставляйте на продажу свой софт;
  • обсуждения и гайды — всё тот же раздел с вопросами, но теперь модернизированный: поиск нужных хаков, пати с игроками-читерами и другая полезная информация.

Спасибо!

Для начала устанавливаем плагин Minecraft Development

Далее создаем новый проект
1730737689774.png
Заходим в главный класс мода и оставляем для себя только

Java:
@Mod("bigbrain")
public class ClientEntry {
  
    public ClientEntry() {
        init();
    }

    public void init() {
        MinecraftForge.EVENT_BUS.register(this);
    }
}
Далее мы берём ноги в зубы и идем плотно пастить утилки с гитхаба (
Пожалуйста, авторизуйтесь для просмотра ссылки.
|
Пожалуйста, авторизуйтесь для просмотра ссылки.
)

После успешного пастинга едем реализовывать наши функции.
Создаем класс Module и ModuleCategory
Java:
public abstract class Module {
    public String name;
    public ModuleCategory category;
    public String description;
    public int key;
    public boolean included;
    public List<Setting> settings = new ArrayList<>();
  
    public Module(String name, ModuleCategory category, String description) {
        this.name = name;
        this.category = category;
        this.description = description;
    }
  
     public Module(String name, ModuleCategory category, String description, int key) {
        this.name = name;
        this.category = category;
        this.key = key;
        this.description = description;
    }
  
    public void onEnable() {
        included = true;
        MinecraftForge.EVENT_BUS.register(this);
    }
  
    public void onDisable() {
        included = false;
        MinecraftForge.EVENT_BUS.unregister(this);
    }
  
    public void toggle() {
        if (included) {
            onDisable();
        } else {
            onEnable();
        }
    }
  
    public boolean isEnabled() {
        return included;
    }
  
    public ModuleCategory getCategory() {
        return category;
    }
}
Java:
public enum ModuleCategory {
    Combat,
    Movement,
    Player,
    Visuals
}
Так-же нам нужно создать менеджер для наших будущих функций
Java:
public class ModulesManager {
    public static ArrayList<Feature> modules = new ArrayList<>();

    public static void addModules() {
        try {
                // modules.add(new Class());
            new Thread(() -> {
                try {
                    Thread.sleep(5000);
                } catch (Exception ignored) {
                }
            }).start();
        } catch (Exception ignored) {
        }
    }

    public static boolean moduleIncluded(Class<?> featureClass) {
        for (Feature feature : features) {
            if (feature.included && feature.getClass() == featureClass) {
                return true;
            }
        }
        return false;
    }
}
В ините нашего мейн класса вызываем
Java:
ModuleManager.addModules();
Так-же добавляем в наш главный класс обработку нажатий на кнопки биндов

Java:
@SubscribeEvent
public void onKeyInput(InputEvent.KeyInputEvent keyInputEvent) {
    for (Module module : ModuleManager.modules) {
        if (Minecraft.getInstance().screen == null && keyInputEvent.getKey() == module.key && keyInputEvent.getAction() == 1) {
            module.toggle();
        }
    }
}
Уже сейчас мы можем для примера написать какую нибудь простенькую функцию

Java:
public class TestModule extends Module {
    public TestModule() {
        super("test module", ModuleCategory.Movement, "jumping$", GLFW.GLFW_KEY_X);
    }
  
    // логика нашего $elfcod'a
    @Override
    public void onEnable() {
        Minecraft.getInstance().player.jumpFromGround();
        super.onDisable();
    }
}
Не забываем зарегистрировать функцию с помощью ModuleManager'a

Чисто для нашего удобства создадит класс ClientUtil
Java:
public class ClientUtil {
    public static Minecraft mc = Minecraft.getInstance();
    public static MainWindow mw = mc.getWindow();
  
    // добавляем сюда все, что используем часто
}
Пришло время создать максимально простенькое нечто, напоминающее клик гуи

Java:
public class ClickUi extends Screen {
    private final List<Module> modules;
    private ModuleCategory selected;
    private int offset;

    public ClickUi() {
        super(new StringTextComponent("gui"));
        this.modules = ModuleManager.modules;
        this.selected = ModuleCategory.Combat;
        this.offset = 0;
    }

    @Override
    protected void init() {
        int y = this.height / 2 - 75;
        for (ModuleCategory category : ModuleCategory.values()) {
            this.addButton(new Buttons(this.width / 2 - 105, y, 75, 20, category.name(), (btn) -> {
                selected = category;
            }));
            y += 25;
        }
    }

    @Override
    public void render(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {
        this.renderBackground(matrixStack);
        int x = this.width / 2;
        int Ypos = this.height / 2;

        DrawHelper.drawRoundedRect(x - 110, Ypos + 80, 225, 160, 5, new Color(8, 10, 12).brighter());
        DrawHelper.drawRoundedRect(x - 20, Ypos + 75, 130, 150, 5, new Color(8, 10, 12));

        RenderSystem.enableScissor((x - 20) * this.minecraft.getWindow().getWidth() / this.width,
                (Ypos - 74) * this.minecraft.getWindow().getHeight() / this.height,
                130 * this.minecraft.getWindow().getWidth() / this.width,
                150 * this.minecraft.getWindow().getHeight() / this.height);

        int y = Ypos - 70 + offset;
        for (Module module : modules) {
            if (module.getCategory() == selected) {
                StyledFontRenderer.drawString(matrixStack, ClientEntry.big, module.name, x - 15, y + ClientEntry.big.getFontHeight(), module.isEnabled() ? new Color(56, 78, 126) : new Color(255, 255, 255));
                y += 15;
            }
        }

        RenderSystem.disableScissor();

        super.render(matrixStack, mouseX, mouseY, partialTicks);
    }

    @Override
    public boolean mouseClicked(double mouseX, double mouseY, int button) {
        if (button == 0) {
            int x = this.width / 2;
            int Ypos = this.height / 2;
            int y = Ypos - 70 + offset;
            for (Module module : modules) {
                if (module.getCategory() == selected) {
                    if (mouseX >= x - 15 && mouseX <= x + 85 && mouseY >= y && mouseY <= y + 15) {
                        module.toggle();
                        return true;
                    }
                    y += 15;
                }
            }
        }
        return super.mouseClicked(mouseX, mouseY, button);
    }

    @Override
    public boolean mouseScrolled(double mouseX, double mouseY, double value) {
        offset += value * 10;
        offset = Math.max(Math.min(offset, 0), -getMaxScroll());
        return true;
    }

    private int getMaxScroll() {
        int count = 0;
        for (Module module : modules) {
            if (module.getCategory() == selected) {
                count++;
            }
        }
        return Math.max(0, count * 15 - 125);
    }

    private static class Buttons extends Button {
        public Buttons(int x, int y, int width, int height, String text, IPressable onPress) {
            super(x, y, width, height, new StringTextComponent(text), onPress);
        }

        @Override
        public void renderButton(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {
            Color color = this.isHovered() ? new Color(56, 78, 126) : new Color(17, 24, 39);
            DrawHelper.drawRoundedRect(this.x, this.y + this.height, this.width, this.height, 3, color);
            StyledFontRenderer.drawCenteredXString(matrixStack, ClientEntry.big, this.getMessage().getString(), this.x + this.width / 2, this.y + (this.height / 2) + 4, Color.WHITE);
        }
    }
}
На выходе получаем микро вариант cs gui
1730743800330.png
Визуально ее изменить думаю осилит каждый (если конечно iq чуть выше 15)

Но мы же блатные, поэтому надо сделать сеттинги

Создаем класс Setting

Java:
public class Setting {
    public String name;
    public boolean isVisible = true;

    public Setting(String name) {this.name = name;}

    public boolean isVisible() {return isVisible;}

    public String getName() {return name;}
}
Далее к нему уже создаем классы FloatSetting, BooleanSetting, ModeSetting
Java:
public class FloatSetting extends Setting {
    private double min, max, inc;
    public double value;
    double defaultvalue;

    public void setInc(double inc) {
        this.inc = inc;
    }

    public double getDefaultvalue() {
        return defaultvalue;
    }

    public void setDefaultvalue(double defaultvalue) {
        this.defaultvalue = defaultvalue;
    }

    public FloatSetting(String name, double min, double max, double defaultvalue, double inc) {
        super(name);
        this.max = max;
        this.min = min;
        this.defaultvalue = defaultvalue;
        this.inc = inc;
        this.value = clamp((float) defaultvalue, (float) min, (float) max);
    }

    public double getValue() {
        return (value != 0) ? value : defaultvalue;
    }

    public double getValueFloat() {
        return (float) value;
    }

    public void setValDouble(double in) {
        this.value = in;
    }

    public void setValue(double value) {
        value = Math.round(value / inc) * inc;
        this.value = clamp(value, min, max);
    }

    public static double clamp(double num, double min, double max) {
        return Math.max(min, Math.min(max, num));
    }

    public void reset() {
        setValue(defaultvalue);
    }

    public double getMin() {
        return min;
    }

    public void setMin(double min) {
        this.min = min;
    }

    public double getMax() {
        return max;
    }

    public void setMax(double max) {
        this.max = max;
    }

    public double getInc() {
        return inc;
    }

    public static float clamp(float num, float min, float max) {
        return num < min ? min : num > max ? max : num;
    }

    public int getValueInt() {
        return (int) value;
    }

    public void inc(boolean isPositive) {
        if (isPositive) setValue(getValue() + getInc());
        else setValue(getValue() - getInc());
    }
}
Java:
public class BooleanSetting extends Setting {
    public boolean value;

    public BooleanSetting(String name, boolean defaultVal) {
        super(name);
        this.value = defaultVal;
    }

    public void toggle() {
        this.value = !this.value;
    }

    public boolean isEnabled() {
        return value;
    }

    public void setEnabled() {
        this.value = value;
    }

    public boolean getValue() {
        return this.value;
    }
}
Java:
public class ModeSetting extends Setting {
    private List<String> modes;
    private int index;
    public String mode;
    public Animation animation;
    public String previousMode;
    private int previousIndex;

    public List<String> getModes() {
        return modes;
    }

    public void setModes(List<String> modes) {
        this.modes = modes;
    }

    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
        this.mode = modes.get(index);
    }

    public String getMode() {
        return mode;
    }


    public ModeSetting(String name, String... modes) {
        super(name);
        this.modes = Arrays.asList(modes);
        this.mode = this.modes.get(0);
        this.index = 0;
        this.animation = new Animation(1, 1, 0.1f);
        this.previousMode = null;
        this.previousIndex = 0;
    }

    public void cycle() {
        this.previousMode = this.mode;
        this.previousIndex = this.index;
        if (index < modes.size() - 1) {
            index++;
        } else {
            index = 0;
        }
        this.mode = modes.get(index);
        this.animation.setAnim(0);
    }

    public void setMode(String mode) {
        if (!this.mode.equals(mode)) {
            this.previousMode = this.mode;
            this.previousIndex = this.index;
            this.mode = mode;
            this.index = modes.indexOf(mode);
            this.animation.setAnim(0);
        }
    }

    public int getPreviousIndex() {
        return previousIndex;
    }

    public boolean isMode(String mode) {
        return Objects.equals(this.mode, mode);
    }

    public String getValue() {
        return this.mode;
    }
}
Сеттинги в гуи добавите сами, мне впадлу слишком <3

Пример использованию наших сеттингов


Java:
public class TestModule() {
  
    BooleanSetting booleanSetting = new BooleanSetting("Bool Setting", true);
  
    public TestModule() {
        super("module", ModuleCategory.Visuals, "test");
        addSettings(booleanSetting);
    }
  
    @SubscribeEvent
    public void onTick(TickEvent event) {
        if (booleanSetting.isEnabled()) {
            /* ... */
        }
    }
}
Так-же для возможности открыть нашу гуи создаем класс

Java:
public class ClickGUI extends Module {

    public ClickGUI() {
        super("gui", ModuleCategory.Visuals, "yougame gui", GLFW.GLFW_KEY_RIGHT_SHIFT);
    }

    @Override
    public void onEnable() {
        mc.setScreen(new ClickUi());
    }
}
И регистрируем его в ModuleManager'e
По итогу мы имеем достаточно простенькую, но какую никакую собственную базу.
Спасибо за уделенное время!

Нужно ли вообще делать тутор на хуки/миксины?
 
Последнее редактирование:
Начинающий
Статус
Оффлайн
Регистрация
26 Дек 2023
Сообщения
471
Реакции[?]
2
Поинты[?]
1K
Для начала устанавливаем плагин Minecraft Development

Далее создаем новый проект
Посмотреть вложение 289600
Заходим в главный класс мода и оставляем для себя только

Java:
@Mod("bigbrain")
public class ClientEntry {
   
    public ClientEntry() {
        init();
    }

    public void init() {
        MinecraftForge.EVENT_BUS.register(this);
    }
}
Далее мы берём ноги в зубы и идем плотно пастить утилки с гитхаба (
Пожалуйста, авторизуйтесь для просмотра ссылки.
|
Пожалуйста, авторизуйтесь для просмотра ссылки.
)

После успешного пастинга едем реализовывать наши функции.
Создаем класс Module и ModuleCategory
Java:
public abstract class Module {
    public String name;
    public FeatureCategory category;
    public String description;
    public int key;
    public boolean included;
    public List<Setting> settings = new ArrayList<>();
   
    public Module(String name, ModuleCategory category, String description) {
        this.name = name;
        this.category = category;
        this.description = description;
    }
   
     public Module(String name, ModuleCategory category, String description, int key) {
        this.name = name;
        this.category = category;
        this.key = key;
        this.description = description;
    }
   
    public void onEnable() {
        MinecraftForge.EVENT_BUS.register(this);
    }
   
    public void onDisable() {
        MinecraftForge.EVENT_BUS.unregister(this);
    }
   
    public void toggle() {
        if (included) {
            onDisable();
        } else {
            onEnable();
        }
    }
   
    public boolean isEnabled() {
        return included;
    }
   
    public ModuleCategory getCategory() {
        return category;
    }
}
Java:
public enum ModuleCategory {
    Combat,
    Movement,
    Player,
    Visuals
}
Так-же нам нужно создать менеджер для наших будущих функций
Java:
public class ModulesManager {
    public static ArrayList<Feature> modules = new ArrayList<>();

    public static void addModules() {
        try {
                // modules.add(new Class());
            new Thread(() -> {
                try {
                    Thread.sleep(5000);
                } catch (Exception ignored) {
                }
            }).start();
        } catch (Exception ignored) {
        }
    }

    public static boolean moduleIncluded(Class<?> featureClass) {
        for (Feature feature : features) {
            if (feature.included && feature.getClass() == featureClass) {
                return true;
            }
        }
        return false;
    }
}
В ините нашего мейн класса вызываем
Java:
ModuleManager.addModules();
Так-же добавляем в наш главный класс обработку нажатий на кнопки биндов

Java:
@SubscribeEvent
public void onKeyInput(InputEvent.KeyInputEvent keyInputEvent) {
    for (Module module : ModuleManager.modules) {
        if (Minecraft.getInstance().screen == null && keyInputEvent.getKey() == module.key && keyInputEvent.getAction() == 1) {
            module.toggle();
        }
    }
}
Уже сейчас мы можем для примера написать какую нибудь простенькую функцию

Java:
public class TestModule extends Module {
    public TestModule() {
        super("test module", ModuleCategory.Movement, "jumping$", GLFW.GLFW_KEY_X);
    }
   
    // логика нашего $elfcod'a
    @Override
    public void onEnable() {
        Minecraft.getInstance().player.jumpFromGround();
        super.onDisable();
    }
}
Не забываем зарегистрировать функцию с помощью ModuleManager'a

Чисто для нашего удобства создадит класс ClientUtil
Java:
public class ClientUtil {
    public static Minecraft mc = Minecraft.getInstance();
    public static MainWindow mw = mc.getWindow();
   
    // добавляем сюда все, что используем часто
}
Пришло время создать максимально простенькое нечто, напоминающее клик гуи

Java:
public class ClickUi extends Screen {
    private final List<Module> modules;
    private ModuleCategory selected;
    private int offset;

    public ClickUi() {
        super(new StringTextComponent("gui"));
        this.modules = ModuleManager.modules;
        this.selected = ModuleCategory.Combat;
        this.offset = 0;
    }

    @Override
    protected void init() {
        int y = this.height / 2 - 75;
        for (ModuleCategory category : ModuleCategory.values()) {
            this.addButton(new Buttons(this.width / 2 - 105, y, 75, 20, category.name(), (btn) -> {
                selected = category;
            }));
            y += 25;
        }
    }

    @Override
    public void render(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {
        this.renderBackground(matrixStack);
        int x = this.width / 2;
        int Ypos = this.height / 2;

        DrawHelper.drawRoundedRect(x - 110, Ypos + 80, 225, 160, 5, new Color(8, 10, 12).brighter());
        DrawHelper.drawRoundedRect(x - 20, Ypos + 75, 130, 150, 5, new Color(8, 10, 12));

        RenderSystem.enableScissor((x - 20) * this.minecraft.getWindow().getWidth() / this.width,
                (Ypos - 74) * this.minecraft.getWindow().getHeight() / this.height,
                130 * this.minecraft.getWindow().getWidth() / this.width,
                150 * this.minecraft.getWindow().getHeight() / this.height);

        int y = Ypos - 70 + offset;
        for (Module module : modules) {
            if (module.getCategory() == selected) {
                StyledFontRenderer.drawString(matrixStack, ClientEntry.big, module.name, x - 15, y + ClientEntry.big.getFontHeight(), module.isEnabled() ? new Color(56, 78, 126) : new Color(255, 255, 255));
                y += 15;
            }
        }

        RenderSystem.disableScissor();

        super.render(matrixStack, mouseX, mouseY, partialTicks);
    }

    @Override
    public boolean mouseClicked(double mouseX, double mouseY, int button) {
        if (button == 0) {
            int x = this.width / 2;
            int Ypos = this.height / 2;
            int y = Ypos - 70 + offset;
            for (Module module : modules) {
                if (module.getCategory() == selected) {
                    if (mouseX >= x - 15 && mouseX <= x + 85 && mouseY >= y && mouseY <= y + 15) {
                        module.toggle();
                        return true;
                    }
                    y += 15;
                }
            }
        }
        return super.mouseClicked(mouseX, mouseY, button);
    }

    @Override
    public boolean mouseScrolled(double mouseX, double mouseY, double value) {
        offset += value * 10;
        offset = Math.max(Math.min(offset, 0), -getMaxScroll());
        return true;
    }

    private int getMaxScroll() {
        int count = 0;
        for (Module module : modules) {
            if (module.getCategory() == selected) {
                count++;
            }
        }
        return Math.max(0, count * 15 - 125);
    }

    private static class Buttons extends Button {
        public Buttons(int x, int y, int width, int height, String text, IPressable onPress) {
            super(x, y, width, height, new StringTextComponent(text), onPress);
        }

        @Override
        public void renderButton(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {
            Color color = this.isHovered() ? new Color(56, 78, 126) : new Color(17, 24, 39);
            DrawHelper.drawRoundedRect(this.x, this.y + this.height, this.width, this.height, 3, color);
            StyledFontRenderer.drawCenteredXString(matrixStack, ClientEntry.big, this.getMessage().getString(), this.x + this.width / 2, this.y + (this.height / 2) + 4, Color.WHITE);
        }
    }
}
На выходе получаем микро вариант cs gui
Посмотреть вложение 289608
Визуально ее изменить думаю осилит каждый (если конечно iq чуть выше 15)

Но мы же блатные, поэтому надо сделать сеттинги

Создаем класс Setting

Java:
public class Setting {
    public String name;
    public boolean isVisible = true;

    public Setting(String name) {this.name = name;}

    public boolean isVisible() {return isVisible;}

    public String getName() {return name;}
}
Далее к нему уже создаем классы FloatSetting, BooleanSetting, ModeSetting
Java:
public class FloatSetting extends Setting {
    private double min, max, inc;
    public double value;
    double defaultvalue;

    public void setInc(double inc) {
        this.inc = inc;
    }

    public double getDefaultvalue() {
        return defaultvalue;
    }

    public void setDefaultvalue(double defaultvalue) {
        this.defaultvalue = defaultvalue;
    }

    public FloatSetting(String name, double min, double max, double defaultvalue, double inc) {
        super(name);
        this.max = max;
        this.min = min;
        this.defaultvalue = defaultvalue;
        this.inc = inc;
        this.value = clamp((float) defaultvalue, (float) min, (float) max);
    }

    public double getValue() {
        return (value != 0) ? value : defaultvalue;
    }

    public double getValueFloat() {
        return (float) value;
    }

    public void setValDouble(double in) {
        this.value = in;
    }

    public void setValue(double value) {
        value = Math.round(value / inc) * inc;
        this.value = clamp(value, min, max);
    }

    public static double clamp(double num, double min, double max) {
        return Math.max(min, Math.min(max, num));
    }

    public void reset() {
        setValue(defaultvalue);
    }

    public double getMin() {
        return min;
    }

    public void setMin(double min) {
        this.min = min;
    }

    public double getMax() {
        return max;
    }

    public void setMax(double max) {
        this.max = max;
    }

    public double getInc() {
        return inc;
    }

    public static float clamp(float num, float min, float max) {
        return num < min ? min : num > max ? max : num;
    }

    public int getValueInt() {
        return (int) value;
    }

    public void inc(boolean isPositive) {
        if (isPositive) setValue(getValue() + getInc());
        else setValue(getValue() - getInc());
    }
}
Java:
public class BooleanSetting extends Setting {
    public boolean value;

    public BooleanSetting(String name, boolean defaultVal) {
        super(name);
        this.value = defaultVal;
    }

    public void toggle() {
        this.value = !this.value;
    }

    public boolean isEnabled() {
        return value;
    }

    public void setEnabled() {
        this.value = value;
    }

    public boolean getValue() {
        return this.value;
    }
}
Java:
public class ModeSetting extends Setting {
    private List<String> modes;
    private int index;
    public String mode;
    public Animation animation;
    public String previousMode;
    private int previousIndex;

    public List<String> getModes() {
        return modes;
    }

    public void setModes(List<String> modes) {
        this.modes = modes;
    }

    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
        this.mode = modes.get(index);
    }

    public String getMode() {
        return mode;
    }


    public ModeSetting(String name, String... modes) {
        super(name);
        this.modes = Arrays.asList(modes);
        this.mode = this.modes.get(0);
        this.index = 0;
        this.animation = new Animation(1, 1, 0.1f);
        this.previousMode = null;
        this.previousIndex = 0;
    }

    public void cycle() {
        this.previousMode = this.mode;
        this.previousIndex = this.index;
        if (index < modes.size() - 1) {
            index++;
        } else {
            index = 0;
        }
        this.mode = modes.get(index);
        this.animation.setAnim(0);
    }

    public void setMode(String mode) {
        if (!this.mode.equals(mode)) {
            this.previousMode = this.mode;
            this.previousIndex = this.index;
            this.mode = mode;
            this.index = modes.indexOf(mode);
            this.animation.setAnim(0);
        }
    }

    public int getPreviousIndex() {
        return previousIndex;
    }

    public boolean isMode(String mode) {
        return Objects.equals(this.mode, mode);
    }

    public String getValue() {
        return this.mode;
    }
}
Сеттинги в гуи добавите сами, мне впадлу слишком <3

Пример использованию наших сеттингов


Java:
public class TestModule() {
   
    BooleanSetting booleanSetting = new BooleanSetting("Bool Setting", true);
   
    public TestModule() {
        super("module", ModuleCategory.Visuals, "test");
        addSettings(booleanSetting);
    }
   
    @SubscribeEvent
    public void onTick(TickEvent event) {
        if (booleanSetting.isEnabled()) {
            /* ... */
        }
    }
}
Так-же для возможности открыть нашу гуи создаем класс

Java:
public class ClickGUI extends Module {

    public ClickGUI() {
        super("gui", ModuleCategory.Visuals, "yougame gui", GLFW.GLFW_KEY_RIGHT_SHIFT);
    }

    @Override
    public void onEnable() {
        mc.setScreen(new ClickUi());
    }
}
И регистрируем его в ModuleManager'e
По итогу мы имеем достаточно простенькую, но какую никакую собственную базу.
Спасибо за уделенное время!

Нужно ли вообще делать тутор на хуки/миксины?
годно, продолжай в том же духе
 
Начинающий
Статус
Онлайн
Регистрация
27 Окт 2024
Сообщения
67
Реакции[?]
0
Поинты[?]
0
Для начала устанавливаем плагин Minecraft Development

Далее создаем новый проект
Посмотреть вложение 289600
Заходим в главный класс мода и оставляем для себя только

Java:
@Mod("bigbrain")
public class ClientEntry {
   
    public ClientEntry() {
        init();
    }

    public void init() {
        MinecraftForge.EVENT_BUS.register(this);
    }
}
Далее мы берём ноги в зубы и идем плотно пастить утилки с гитхаба (
Пожалуйста, авторизуйтесь для просмотра ссылки.
|
Пожалуйста, авторизуйтесь для просмотра ссылки.
)

После успешного пастинга едем реализовывать наши функции.
Создаем класс Module и ModuleCategory
Java:
public abstract class Module {
    public String name;
    public FeatureCategory category;
    public String description;
    public int key;
    public boolean included;
    public List<Setting> settings = new ArrayList<>();
   
    public Module(String name, ModuleCategory category, String description) {
        this.name = name;
        this.category = category;
        this.description = description;
    }
   
     public Module(String name, ModuleCategory category, String description, int key) {
        this.name = name;
        this.category = category;
        this.key = key;
        this.description = description;
    }
   
    public void onEnable() {
        MinecraftForge.EVENT_BUS.register(this);
    }
   
    public void onDisable() {
        MinecraftForge.EVENT_BUS.unregister(this);
    }
   
    public void toggle() {
        if (included) {
            onDisable();
        } else {
            onEnable();
        }
    }
   
    public boolean isEnabled() {
        return included;
    }
   
    public ModuleCategory getCategory() {
        return category;
    }
}
Java:
public enum ModuleCategory {
    Combat,
    Movement,
    Player,
    Visuals
}
Так-же нам нужно создать менеджер для наших будущих функций
Java:
public class ModulesManager {
    public static ArrayList<Feature> modules = new ArrayList<>();

    public static void addModules() {
        try {
                // modules.add(new Class());
            new Thread(() -> {
                try {
                    Thread.sleep(5000);
                } catch (Exception ignored) {
                }
            }).start();
        } catch (Exception ignored) {
        }
    }

    public static boolean moduleIncluded(Class<?> featureClass) {
        for (Feature feature : features) {
            if (feature.included && feature.getClass() == featureClass) {
                return true;
            }
        }
        return false;
    }
}
В ините нашего мейн класса вызываем
Java:
ModuleManager.addModules();
Так-же добавляем в наш главный класс обработку нажатий на кнопки биндов

Java:
@SubscribeEvent
public void onKeyInput(InputEvent.KeyInputEvent keyInputEvent) {
    for (Module module : ModuleManager.modules) {
        if (Minecraft.getInstance().screen == null && keyInputEvent.getKey() == module.key && keyInputEvent.getAction() == 1) {
            module.toggle();
        }
    }
}
Уже сейчас мы можем для примера написать какую нибудь простенькую функцию

Java:
public class TestModule extends Module {
    public TestModule() {
        super("test module", ModuleCategory.Movement, "jumping$", GLFW.GLFW_KEY_X);
    }
   
    // логика нашего $elfcod'a
    @Override
    public void onEnable() {
        Minecraft.getInstance().player.jumpFromGround();
        super.onDisable();
    }
}
Не забываем зарегистрировать функцию с помощью ModuleManager'a

Чисто для нашего удобства создадит класс ClientUtil
Java:
public class ClientUtil {
    public static Minecraft mc = Minecraft.getInstance();
    public static MainWindow mw = mc.getWindow();
   
    // добавляем сюда все, что используем часто
}
Пришло время создать максимально простенькое нечто, напоминающее клик гуи

Java:
public class ClickUi extends Screen {
    private final List<Module> modules;
    private ModuleCategory selected;
    private int offset;

    public ClickUi() {
        super(new StringTextComponent("gui"));
        this.modules = ModuleManager.modules;
        this.selected = ModuleCategory.Combat;
        this.offset = 0;
    }

    @Override
    protected void init() {
        int y = this.height / 2 - 75;
        for (ModuleCategory category : ModuleCategory.values()) {
            this.addButton(new Buttons(this.width / 2 - 105, y, 75, 20, category.name(), (btn) -> {
                selected = category;
            }));
            y += 25;
        }
    }

    @Override
    public void render(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {
        this.renderBackground(matrixStack);
        int x = this.width / 2;
        int Ypos = this.height / 2;

        DrawHelper.drawRoundedRect(x - 110, Ypos + 80, 225, 160, 5, new Color(8, 10, 12).brighter());
        DrawHelper.drawRoundedRect(x - 20, Ypos + 75, 130, 150, 5, new Color(8, 10, 12));

        RenderSystem.enableScissor((x - 20) * this.minecraft.getWindow().getWidth() / this.width,
                (Ypos - 74) * this.minecraft.getWindow().getHeight() / this.height,
                130 * this.minecraft.getWindow().getWidth() / this.width,
                150 * this.minecraft.getWindow().getHeight() / this.height);

        int y = Ypos - 70 + offset;
        for (Module module : modules) {
            if (module.getCategory() == selected) {
                StyledFontRenderer.drawString(matrixStack, ClientEntry.big, module.name, x - 15, y + ClientEntry.big.getFontHeight(), module.isEnabled() ? new Color(56, 78, 126) : new Color(255, 255, 255));
                y += 15;
            }
        }

        RenderSystem.disableScissor();

        super.render(matrixStack, mouseX, mouseY, partialTicks);
    }

    @Override
    public boolean mouseClicked(double mouseX, double mouseY, int button) {
        if (button == 0) {
            int x = this.width / 2;
            int Ypos = this.height / 2;
            int y = Ypos - 70 + offset;
            for (Module module : modules) {
                if (module.getCategory() == selected) {
                    if (mouseX >= x - 15 && mouseX <= x + 85 && mouseY >= y && mouseY <= y + 15) {
                        module.toggle();
                        return true;
                    }
                    y += 15;
                }
            }
        }
        return super.mouseClicked(mouseX, mouseY, button);
    }

    @Override
    public boolean mouseScrolled(double mouseX, double mouseY, double value) {
        offset += value * 10;
        offset = Math.max(Math.min(offset, 0), -getMaxScroll());
        return true;
    }

    private int getMaxScroll() {
        int count = 0;
        for (Module module : modules) {
            if (module.getCategory() == selected) {
                count++;
            }
        }
        return Math.max(0, count * 15 - 125);
    }

    private static class Buttons extends Button {
        public Buttons(int x, int y, int width, int height, String text, IPressable onPress) {
            super(x, y, width, height, new StringTextComponent(text), onPress);
        }

        @Override
        public void renderButton(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {
            Color color = this.isHovered() ? new Color(56, 78, 126) : new Color(17, 24, 39);
            DrawHelper.drawRoundedRect(this.x, this.y + this.height, this.width, this.height, 3, color);
            StyledFontRenderer.drawCenteredXString(matrixStack, ClientEntry.big, this.getMessage().getString(), this.x + this.width / 2, this.y + (this.height / 2) + 4, Color.WHITE);
        }
    }
}
На выходе получаем микро вариант cs gui
Посмотреть вложение 289608
Визуально ее изменить думаю осилит каждый (если конечно iq чуть выше 15)

Но мы же блатные, поэтому надо сделать сеттинги

Создаем класс Setting

Java:
public class Setting {
    public String name;
    public boolean isVisible = true;

    public Setting(String name) {this.name = name;}

    public boolean isVisible() {return isVisible;}

    public String getName() {return name;}
}
Далее к нему уже создаем классы FloatSetting, BooleanSetting, ModeSetting
Java:
public class FloatSetting extends Setting {
    private double min, max, inc;
    public double value;
    double defaultvalue;

    public void setInc(double inc) {
        this.inc = inc;
    }

    public double getDefaultvalue() {
        return defaultvalue;
    }

    public void setDefaultvalue(double defaultvalue) {
        this.defaultvalue = defaultvalue;
    }

    public FloatSetting(String name, double min, double max, double defaultvalue, double inc) {
        super(name);
        this.max = max;
        this.min = min;
        this.defaultvalue = defaultvalue;
        this.inc = inc;
        this.value = clamp((float) defaultvalue, (float) min, (float) max);
    }

    public double getValue() {
        return (value != 0) ? value : defaultvalue;
    }

    public double getValueFloat() {
        return (float) value;
    }

    public void setValDouble(double in) {
        this.value = in;
    }

    public void setValue(double value) {
        value = Math.round(value / inc) * inc;
        this.value = clamp(value, min, max);
    }

    public static double clamp(double num, double min, double max) {
        return Math.max(min, Math.min(max, num));
    }

    public void reset() {
        setValue(defaultvalue);
    }

    public double getMin() {
        return min;
    }

    public void setMin(double min) {
        this.min = min;
    }

    public double getMax() {
        return max;
    }

    public void setMax(double max) {
        this.max = max;
    }

    public double getInc() {
        return inc;
    }

    public static float clamp(float num, float min, float max) {
        return num < min ? min : num > max ? max : num;
    }

    public int getValueInt() {
        return (int) value;
    }

    public void inc(boolean isPositive) {
        if (isPositive) setValue(getValue() + getInc());
        else setValue(getValue() - getInc());
    }
}
Java:
public class BooleanSetting extends Setting {
    public boolean value;

    public BooleanSetting(String name, boolean defaultVal) {
        super(name);
        this.value = defaultVal;
    }

    public void toggle() {
        this.value = !this.value;
    }

    public boolean isEnabled() {
        return value;
    }

    public void setEnabled() {
        this.value = value;
    }

    public boolean getValue() {
        return this.value;
    }
}
Java:
public class ModeSetting extends Setting {
    private List<String> modes;
    private int index;
    public String mode;
    public Animation animation;
    public String previousMode;
    private int previousIndex;

    public List<String> getModes() {
        return modes;
    }

    public void setModes(List<String> modes) {
        this.modes = modes;
    }

    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
        this.mode = modes.get(index);
    }

    public String getMode() {
        return mode;
    }


    public ModeSetting(String name, String... modes) {
        super(name);
        this.modes = Arrays.asList(modes);
        this.mode = this.modes.get(0);
        this.index = 0;
        this.animation = new Animation(1, 1, 0.1f);
        this.previousMode = null;
        this.previousIndex = 0;
    }

    public void cycle() {
        this.previousMode = this.mode;
        this.previousIndex = this.index;
        if (index < modes.size() - 1) {
            index++;
        } else {
            index = 0;
        }
        this.mode = modes.get(index);
        this.animation.setAnim(0);
    }

    public void setMode(String mode) {
        if (!this.mode.equals(mode)) {
            this.previousMode = this.mode;
            this.previousIndex = this.index;
            this.mode = mode;
            this.index = modes.indexOf(mode);
            this.animation.setAnim(0);
        }
    }

    public int getPreviousIndex() {
        return previousIndex;
    }

    public boolean isMode(String mode) {
        return Objects.equals(this.mode, mode);
    }

    public String getValue() {
        return this.mode;
    }
}
Сеттинги в гуи добавите сами, мне впадлу слишком <3

Пример использованию наших сеттингов


Java:
public class TestModule() {
   
    BooleanSetting booleanSetting = new BooleanSetting("Bool Setting", true);
   
    public TestModule() {
        super("module", ModuleCategory.Visuals, "test");
        addSettings(booleanSetting);
    }
   
    @SubscribeEvent
    public void onTick(TickEvent event) {
        if (booleanSetting.isEnabled()) {
            /* ... */
        }
    }
}
Так-же для возможности открыть нашу гуи создаем класс

Java:
public class ClickGUI extends Module {

    public ClickGUI() {
        super("gui", ModuleCategory.Visuals, "yougame gui", GLFW.GLFW_KEY_RIGHT_SHIFT);
    }

    @Override
    public void onEnable() {
        mc.setScreen(new ClickUi());
    }
}
И регистрируем его в ModuleManager'e
По итогу мы имеем достаточно простенькую, но какую никакую собственную базу.
Спасибо за уделенное время!

Нужно ли вообще делать тутор на хуки/миксины?
да, нужно
 
PoC Life
Пользователь
Статус
Онлайн
Регистрация
22 Авг 2022
Сообщения
335
Реакции[?]
47
Поинты[?]
37K
Для начала устанавливаем плагин Minecraft Development

Далее создаем новый проект
Посмотреть вложение 289600
Заходим в главный класс мода и оставляем для себя только

Java:
@Mod("bigbrain")
public class ClientEntry {
   
    public ClientEntry() {
        init();
    }

    public void init() {
        MinecraftForge.EVENT_BUS.register(this);
    }
}
Далее мы берём ноги в зубы и идем плотно пастить утилки с гитхаба (
Пожалуйста, авторизуйтесь для просмотра ссылки.
|
Пожалуйста, авторизуйтесь для просмотра ссылки.
)

После успешного пастинга едем реализовывать наши функции.
Создаем класс Module и ModuleCategory
Java:
public abstract class Module {
    public String name;
    public FeatureCategory category;
    public String description;
    public int key;
    public boolean included;
    public List<Setting> settings = new ArrayList<>();
   
    public Module(String name, ModuleCategory category, String description) {
        this.name = name;
        this.category = category;
        this.description = description;
    }
   
     public Module(String name, ModuleCategory category, String description, int key) {
        this.name = name;
        this.category = category;
        this.key = key;
        this.description = description;
    }
   
    public void onEnable() {
        MinecraftForge.EVENT_BUS.register(this);
    }
   
    public void onDisable() {
        MinecraftForge.EVENT_BUS.unregister(this);
    }
   
    public void toggle() {
        if (included) {
            onDisable();
        } else {
            onEnable();
        }
    }
   
    public boolean isEnabled() {
        return included;
    }
   
    public ModuleCategory getCategory() {
        return category;
    }
}
Java:
public enum ModuleCategory {
    Combat,
    Movement,
    Player,
    Visuals
}
Так-же нам нужно создать менеджер для наших будущих функций
Java:
public class ModulesManager {
    public static ArrayList<Feature> modules = new ArrayList<>();

    public static void addModules() {
        try {
                // modules.add(new Class());
            new Thread(() -> {
                try {
                    Thread.sleep(5000);
                } catch (Exception ignored) {
                }
            }).start();
        } catch (Exception ignored) {
        }
    }

    public static boolean moduleIncluded(Class<?> featureClass) {
        for (Feature feature : features) {
            if (feature.included && feature.getClass() == featureClass) {
                return true;
            }
        }
        return false;
    }
}
В ините нашего мейн класса вызываем
Java:
ModuleManager.addModules();
Так-же добавляем в наш главный класс обработку нажатий на кнопки биндов

Java:
@SubscribeEvent
public void onKeyInput(InputEvent.KeyInputEvent keyInputEvent) {
    for (Module module : ModuleManager.modules) {
        if (Minecraft.getInstance().screen == null && keyInputEvent.getKey() == module.key && keyInputEvent.getAction() == 1) {
            module.toggle();
        }
    }
}
Уже сейчас мы можем для примера написать какую нибудь простенькую функцию

Java:
public class TestModule extends Module {
    public TestModule() {
        super("test module", ModuleCategory.Movement, "jumping$", GLFW.GLFW_KEY_X);
    }
   
    // логика нашего $elfcod'a
    @Override
    public void onEnable() {
        Minecraft.getInstance().player.jumpFromGround();
        super.onDisable();
    }
}
Не забываем зарегистрировать функцию с помощью ModuleManager'a

Чисто для нашего удобства создадит класс ClientUtil
Java:
public class ClientUtil {
    public static Minecraft mc = Minecraft.getInstance();
    public static MainWindow mw = mc.getWindow();
   
    // добавляем сюда все, что используем часто
}
Пришло время создать максимально простенькое нечто, напоминающее клик гуи

Java:
public class ClickUi extends Screen {
    private final List<Module> modules;
    private ModuleCategory selected;
    private int offset;

    public ClickUi() {
        super(new StringTextComponent("gui"));
        this.modules = ModuleManager.modules;
        this.selected = ModuleCategory.Combat;
        this.offset = 0;
    }

    @Override
    protected void init() {
        int y = this.height / 2 - 75;
        for (ModuleCategory category : ModuleCategory.values()) {
            this.addButton(new Buttons(this.width / 2 - 105, y, 75, 20, category.name(), (btn) -> {
                selected = category;
            }));
            y += 25;
        }
    }

    @Override
    public void render(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {
        this.renderBackground(matrixStack);
        int x = this.width / 2;
        int Ypos = this.height / 2;

        DrawHelper.drawRoundedRect(x - 110, Ypos + 80, 225, 160, 5, new Color(8, 10, 12).brighter());
        DrawHelper.drawRoundedRect(x - 20, Ypos + 75, 130, 150, 5, new Color(8, 10, 12));

        RenderSystem.enableScissor((x - 20) * this.minecraft.getWindow().getWidth() / this.width,
                (Ypos - 74) * this.minecraft.getWindow().getHeight() / this.height,
                130 * this.minecraft.getWindow().getWidth() / this.width,
                150 * this.minecraft.getWindow().getHeight() / this.height);

        int y = Ypos - 70 + offset;
        for (Module module : modules) {
            if (module.getCategory() == selected) {
                StyledFontRenderer.drawString(matrixStack, ClientEntry.big, module.name, x - 15, y + ClientEntry.big.getFontHeight(), module.isEnabled() ? new Color(56, 78, 126) : new Color(255, 255, 255));
                y += 15;
            }
        }

        RenderSystem.disableScissor();

        super.render(matrixStack, mouseX, mouseY, partialTicks);
    }

    @Override
    public boolean mouseClicked(double mouseX, double mouseY, int button) {
        if (button == 0) {
            int x = this.width / 2;
            int Ypos = this.height / 2;
            int y = Ypos - 70 + offset;
            for (Module module : modules) {
                if (module.getCategory() == selected) {
                    if (mouseX >= x - 15 && mouseX <= x + 85 && mouseY >= y && mouseY <= y + 15) {
                        module.toggle();
                        return true;
                    }
                    y += 15;
                }
            }
        }
        return super.mouseClicked(mouseX, mouseY, button);
    }

    @Override
    public boolean mouseScrolled(double mouseX, double mouseY, double value) {
        offset += value * 10;
        offset = Math.max(Math.min(offset, 0), -getMaxScroll());
        return true;
    }

    private int getMaxScroll() {
        int count = 0;
        for (Module module : modules) {
            if (module.getCategory() == selected) {
                count++;
            }
        }
        return Math.max(0, count * 15 - 125);
    }

    private static class Buttons extends Button {
        public Buttons(int x, int y, int width, int height, String text, IPressable onPress) {
            super(x, y, width, height, new StringTextComponent(text), onPress);
        }

        @Override
        public void renderButton(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {
            Color color = this.isHovered() ? new Color(56, 78, 126) : new Color(17, 24, 39);
            DrawHelper.drawRoundedRect(this.x, this.y + this.height, this.width, this.height, 3, color);
            StyledFontRenderer.drawCenteredXString(matrixStack, ClientEntry.big, this.getMessage().getString(), this.x + this.width / 2, this.y + (this.height / 2) + 4, Color.WHITE);
        }
    }
}
На выходе получаем микро вариант cs gui
Посмотреть вложение 289608
Визуально ее изменить думаю осилит каждый (если конечно iq чуть выше 15)

Но мы же блатные, поэтому надо сделать сеттинги

Создаем класс Setting

Java:
public class Setting {
    public String name;
    public boolean isVisible = true;

    public Setting(String name) {this.name = name;}

    public boolean isVisible() {return isVisible;}

    public String getName() {return name;}
}
Далее к нему уже создаем классы FloatSetting, BooleanSetting, ModeSetting
Java:
public class FloatSetting extends Setting {
    private double min, max, inc;
    public double value;
    double defaultvalue;

    public void setInc(double inc) {
        this.inc = inc;
    }

    public double getDefaultvalue() {
        return defaultvalue;
    }

    public void setDefaultvalue(double defaultvalue) {
        this.defaultvalue = defaultvalue;
    }

    public FloatSetting(String name, double min, double max, double defaultvalue, double inc) {
        super(name);
        this.max = max;
        this.min = min;
        this.defaultvalue = defaultvalue;
        this.inc = inc;
        this.value = clamp((float) defaultvalue, (float) min, (float) max);
    }

    public double getValue() {
        return (value != 0) ? value : defaultvalue;
    }

    public double getValueFloat() {
        return (float) value;
    }

    public void setValDouble(double in) {
        this.value = in;
    }

    public void setValue(double value) {
        value = Math.round(value / inc) * inc;
        this.value = clamp(value, min, max);
    }

    public static double clamp(double num, double min, double max) {
        return Math.max(min, Math.min(max, num));
    }

    public void reset() {
        setValue(defaultvalue);
    }

    public double getMin() {
        return min;
    }

    public void setMin(double min) {
        this.min = min;
    }

    public double getMax() {
        return max;
    }

    public void setMax(double max) {
        this.max = max;
    }

    public double getInc() {
        return inc;
    }

    public static float clamp(float num, float min, float max) {
        return num < min ? min : num > max ? max : num;
    }

    public int getValueInt() {
        return (int) value;
    }

    public void inc(boolean isPositive) {
        if (isPositive) setValue(getValue() + getInc());
        else setValue(getValue() - getInc());
    }
}
Java:
public class BooleanSetting extends Setting {
    public boolean value;

    public BooleanSetting(String name, boolean defaultVal) {
        super(name);
        this.value = defaultVal;
    }

    public void toggle() {
        this.value = !this.value;
    }

    public boolean isEnabled() {
        return value;
    }

    public void setEnabled() {
        this.value = value;
    }

    public boolean getValue() {
        return this.value;
    }
}
Java:
public class ModeSetting extends Setting {
    private List<String> modes;
    private int index;
    public String mode;
    public Animation animation;
    public String previousMode;
    private int previousIndex;

    public List<String> getModes() {
        return modes;
    }

    public void setModes(List<String> modes) {
        this.modes = modes;
    }

    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
        this.mode = modes.get(index);
    }

    public String getMode() {
        return mode;
    }


    public ModeSetting(String name, String... modes) {
        super(name);
        this.modes = Arrays.asList(modes);
        this.mode = this.modes.get(0);
        this.index = 0;
        this.animation = new Animation(1, 1, 0.1f);
        this.previousMode = null;
        this.previousIndex = 0;
    }

    public void cycle() {
        this.previousMode = this.mode;
        this.previousIndex = this.index;
        if (index < modes.size() - 1) {
            index++;
        } else {
            index = 0;
        }
        this.mode = modes.get(index);
        this.animation.setAnim(0);
    }

    public void setMode(String mode) {
        if (!this.mode.equals(mode)) {
            this.previousMode = this.mode;
            this.previousIndex = this.index;
            this.mode = mode;
            this.index = modes.indexOf(mode);
            this.animation.setAnim(0);
        }
    }

    public int getPreviousIndex() {
        return previousIndex;
    }

    public boolean isMode(String mode) {
        return Objects.equals(this.mode, mode);
    }

    public String getValue() {
        return this.mode;
    }
}
Сеттинги в гуи добавите сами, мне впадлу слишком <3

Пример использованию наших сеттингов


Java:
public class TestModule() {
   
    BooleanSetting booleanSetting = new BooleanSetting("Bool Setting", true);
   
    public TestModule() {
        super("module", ModuleCategory.Visuals, "test");
        addSettings(booleanSetting);
    }
   
    @SubscribeEvent
    public void onTick(TickEvent event) {
        if (booleanSetting.isEnabled()) {
            /* ... */
        }
    }
}
Так-же для возможности открыть нашу гуи создаем класс

Java:
public class ClickGUI extends Module {

    public ClickGUI() {
        super("gui", ModuleCategory.Visuals, "yougame gui", GLFW.GLFW_KEY_RIGHT_SHIFT);
    }

    @Override
    public void onEnable() {
        mc.setScreen(new ClickUi());
    }
}
И регистрируем его в ModuleManager'e
По итогу мы имеем достаточно простенькую, но какую никакую собственную базу.
Спасибо за уделенное время!

Нужно ли вообще делать тутор на хуки/миксины?
1730745339966.png
так это уже не своя база
а вот это с объяснениями уже своя
 
Forge Api ;-;
Начинающий
Статус
Оффлайн
Регистрация
3 Май 2023
Сообщения
776
Реакции[?]
18
Поинты[?]
13K
Посмотреть вложение 289612
так это уже не своя база
а вот это с объяснениями уже своя
бля ну это да, но ты же понимаешь что в этом разделе человека 3 от силы будут свой рендер писать
 
PoC Life
Пользователь
Статус
Онлайн
Регистрация
22 Авг 2022
Сообщения
335
Реакции[?]
47
Поинты[?]
37K
бля ну это да, но ты же понимаешь что в этом разделе человека 3 от силы будут свой рендер писать
а твою ебейшую базу никто. объективно: если человек сам захочет обучаться - он сюда и в жизни не зайдёт
 
Начинающий
Статус
Оффлайн
Регистрация
29 Апр 2023
Сообщения
786
Реакции[?]
4
Поинты[?]
5K
Для начала устанавливаем плагин Minecraft Development

Далее создаем новый проект
Посмотреть вложение 289600
Заходим в главный класс мода и оставляем для себя только

Java:
@Mod("bigbrain")
public class ClientEntry {
   
    public ClientEntry() {
        init();
    }

    public void init() {
        MinecraftForge.EVENT_BUS.register(this);
    }
}
Далее мы берём ноги в зубы и идем плотно пастить утилки с гитхаба (
Пожалуйста, авторизуйтесь для просмотра ссылки.
|
Пожалуйста, авторизуйтесь для просмотра ссылки.
)

После успешного пастинга едем реализовывать наши функции.
Создаем класс Module и ModuleCategory
Java:
public abstract class Module {
    public String name;
    public FeatureCategory category;
    public String description;
    public int key;
    public boolean included;
    public List<Setting> settings = new ArrayList<>();
   
    public Module(String name, ModuleCategory category, String description) {
        this.name = name;
        this.category = category;
        this.description = description;
    }
   
     public Module(String name, ModuleCategory category, String description, int key) {
        this.name = name;
        this.category = category;
        this.key = key;
        this.description = description;
    }
   
    public void onEnable() {
        MinecraftForge.EVENT_BUS.register(this);
    }
   
    public void onDisable() {
        MinecraftForge.EVENT_BUS.unregister(this);
    }
   
    public void toggle() {
        if (included) {
            onDisable();
        } else {
            onEnable();
        }
    }
   
    public boolean isEnabled() {
        return included;
    }
   
    public ModuleCategory getCategory() {
        return category;
    }
}
Java:
public enum ModuleCategory {
    Combat,
    Movement,
    Player,
    Visuals
}
Так-же нам нужно создать менеджер для наших будущих функций
Java:
public class ModulesManager {
    public static ArrayList<Feature> modules = new ArrayList<>();

    public static void addModules() {
        try {
                // modules.add(new Class());
            new Thread(() -> {
                try {
                    Thread.sleep(5000);
                } catch (Exception ignored) {
                }
            }).start();
        } catch (Exception ignored) {
        }
    }

    public static boolean moduleIncluded(Class<?> featureClass) {
        for (Feature feature : features) {
            if (feature.included && feature.getClass() == featureClass) {
                return true;
            }
        }
        return false;
    }
}
В ините нашего мейн класса вызываем
Java:
ModuleManager.addModules();
Так-же добавляем в наш главный класс обработку нажатий на кнопки биндов

Java:
@SubscribeEvent
public void onKeyInput(InputEvent.KeyInputEvent keyInputEvent) {
    for (Module module : ModuleManager.modules) {
        if (Minecraft.getInstance().screen == null && keyInputEvent.getKey() == module.key && keyInputEvent.getAction() == 1) {
            module.toggle();
        }
    }
}
Уже сейчас мы можем для примера написать какую нибудь простенькую функцию

Java:
public class TestModule extends Module {
    public TestModule() {
        super("test module", ModuleCategory.Movement, "jumping$", GLFW.GLFW_KEY_X);
    }
   
    // логика нашего $elfcod'a
    @Override
    public void onEnable() {
        Minecraft.getInstance().player.jumpFromGround();
        super.onDisable();
    }
}
Не забываем зарегистрировать функцию с помощью ModuleManager'a

Чисто для нашего удобства создадит класс ClientUtil
Java:
public class ClientUtil {
    public static Minecraft mc = Minecraft.getInstance();
    public static MainWindow mw = mc.getWindow();
   
    // добавляем сюда все, что используем часто
}
Пришло время создать максимально простенькое нечто, напоминающее клик гуи

Java:
public class ClickUi extends Screen {
    private final List<Module> modules;
    private ModuleCategory selected;
    private int offset;

    public ClickUi() {
        super(new StringTextComponent("gui"));
        this.modules = ModuleManager.modules;
        this.selected = ModuleCategory.Combat;
        this.offset = 0;
    }

    @Override
    protected void init() {
        int y = this.height / 2 - 75;
        for (ModuleCategory category : ModuleCategory.values()) {
            this.addButton(new Buttons(this.width / 2 - 105, y, 75, 20, category.name(), (btn) -> {
                selected = category;
            }));
            y += 25;
        }
    }

    @Override
    public void render(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {
        this.renderBackground(matrixStack);
        int x = this.width / 2;
        int Ypos = this.height / 2;

        DrawHelper.drawRoundedRect(x - 110, Ypos + 80, 225, 160, 5, new Color(8, 10, 12).brighter());
        DrawHelper.drawRoundedRect(x - 20, Ypos + 75, 130, 150, 5, new Color(8, 10, 12));

        RenderSystem.enableScissor((x - 20) * this.minecraft.getWindow().getWidth() / this.width,
                (Ypos - 74) * this.minecraft.getWindow().getHeight() / this.height,
                130 * this.minecraft.getWindow().getWidth() / this.width,
                150 * this.minecraft.getWindow().getHeight() / this.height);

        int y = Ypos - 70 + offset;
        for (Module module : modules) {
            if (module.getCategory() == selected) {
                StyledFontRenderer.drawString(matrixStack, ClientEntry.big, module.name, x - 15, y + ClientEntry.big.getFontHeight(), module.isEnabled() ? new Color(56, 78, 126) : new Color(255, 255, 255));
                y += 15;
            }
        }

        RenderSystem.disableScissor();

        super.render(matrixStack, mouseX, mouseY, partialTicks);
    }

    @Override
    public boolean mouseClicked(double mouseX, double mouseY, int button) {
        if (button == 0) {
            int x = this.width / 2;
            int Ypos = this.height / 2;
            int y = Ypos - 70 + offset;
            for (Module module : modules) {
                if (module.getCategory() == selected) {
                    if (mouseX >= x - 15 && mouseX <= x + 85 && mouseY >= y && mouseY <= y + 15) {
                        module.toggle();
                        return true;
                    }
                    y += 15;
                }
            }
        }
        return super.mouseClicked(mouseX, mouseY, button);
    }

    @Override
    public boolean mouseScrolled(double mouseX, double mouseY, double value) {
        offset += value * 10;
        offset = Math.max(Math.min(offset, 0), -getMaxScroll());
        return true;
    }

    private int getMaxScroll() {
        int count = 0;
        for (Module module : modules) {
            if (module.getCategory() == selected) {
                count++;
            }
        }
        return Math.max(0, count * 15 - 125);
    }

    private static class Buttons extends Button {
        public Buttons(int x, int y, int width, int height, String text, IPressable onPress) {
            super(x, y, width, height, new StringTextComponent(text), onPress);
        }

        @Override
        public void renderButton(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {
            Color color = this.isHovered() ? new Color(56, 78, 126) : new Color(17, 24, 39);
            DrawHelper.drawRoundedRect(this.x, this.y + this.height, this.width, this.height, 3, color);
            StyledFontRenderer.drawCenteredXString(matrixStack, ClientEntry.big, this.getMessage().getString(), this.x + this.width / 2, this.y + (this.height / 2) + 4, Color.WHITE);
        }
    }
}
На выходе получаем микро вариант cs gui
Посмотреть вложение 289608
Визуально ее изменить думаю осилит каждый (если конечно iq чуть выше 15)

Но мы же блатные, поэтому надо сделать сеттинги

Создаем класс Setting

Java:
public class Setting {
    public String name;
    public boolean isVisible = true;

    public Setting(String name) {this.name = name;}

    public boolean isVisible() {return isVisible;}

    public String getName() {return name;}
}
Далее к нему уже создаем классы FloatSetting, BooleanSetting, ModeSetting
Java:
public class FloatSetting extends Setting {
    private double min, max, inc;
    public double value;
    double defaultvalue;

    public void setInc(double inc) {
        this.inc = inc;
    }

    public double getDefaultvalue() {
        return defaultvalue;
    }

    public void setDefaultvalue(double defaultvalue) {
        this.defaultvalue = defaultvalue;
    }

    public FloatSetting(String name, double min, double max, double defaultvalue, double inc) {
        super(name);
        this.max = max;
        this.min = min;
        this.defaultvalue = defaultvalue;
        this.inc = inc;
        this.value = clamp((float) defaultvalue, (float) min, (float) max);
    }

    public double getValue() {
        return (value != 0) ? value : defaultvalue;
    }

    public double getValueFloat() {
        return (float) value;
    }

    public void setValDouble(double in) {
        this.value = in;
    }

    public void setValue(double value) {
        value = Math.round(value / inc) * inc;
        this.value = clamp(value, min, max);
    }

    public static double clamp(double num, double min, double max) {
        return Math.max(min, Math.min(max, num));
    }

    public void reset() {
        setValue(defaultvalue);
    }

    public double getMin() {
        return min;
    }

    public void setMin(double min) {
        this.min = min;
    }

    public double getMax() {
        return max;
    }

    public void setMax(double max) {
        this.max = max;
    }

    public double getInc() {
        return inc;
    }

    public static float clamp(float num, float min, float max) {
        return num < min ? min : num > max ? max : num;
    }

    public int getValueInt() {
        return (int) value;
    }

    public void inc(boolean isPositive) {
        if (isPositive) setValue(getValue() + getInc());
        else setValue(getValue() - getInc());
    }
}
Java:
public class BooleanSetting extends Setting {
    public boolean value;

    public BooleanSetting(String name, boolean defaultVal) {
        super(name);
        this.value = defaultVal;
    }

    public void toggle() {
        this.value = !this.value;
    }

    public boolean isEnabled() {
        return value;
    }

    public void setEnabled() {
        this.value = value;
    }

    public boolean getValue() {
        return this.value;
    }
}
Java:
public class ModeSetting extends Setting {
    private List<String> modes;
    private int index;
    public String mode;
    public Animation animation;
    public String previousMode;
    private int previousIndex;

    public List<String> getModes() {
        return modes;
    }

    public void setModes(List<String> modes) {
        this.modes = modes;
    }

    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
        this.mode = modes.get(index);
    }

    public String getMode() {
        return mode;
    }


    public ModeSetting(String name, String... modes) {
        super(name);
        this.modes = Arrays.asList(modes);
        this.mode = this.modes.get(0);
        this.index = 0;
        this.animation = new Animation(1, 1, 0.1f);
        this.previousMode = null;
        this.previousIndex = 0;
    }

    public void cycle() {
        this.previousMode = this.mode;
        this.previousIndex = this.index;
        if (index < modes.size() - 1) {
            index++;
        } else {
            index = 0;
        }
        this.mode = modes.get(index);
        this.animation.setAnim(0);
    }

    public void setMode(String mode) {
        if (!this.mode.equals(mode)) {
            this.previousMode = this.mode;
            this.previousIndex = this.index;
            this.mode = mode;
            this.index = modes.indexOf(mode);
            this.animation.setAnim(0);
        }
    }

    public int getPreviousIndex() {
        return previousIndex;
    }

    public boolean isMode(String mode) {
        return Objects.equals(this.mode, mode);
    }

    public String getValue() {
        return this.mode;
    }
}
Сеттинги в гуи добавите сами, мне впадлу слишком <3

Пример использованию наших сеттингов


Java:
public class TestModule() {
   
    BooleanSetting booleanSetting = new BooleanSetting("Bool Setting", true);
   
    public TestModule() {
        super("module", ModuleCategory.Visuals, "test");
        addSettings(booleanSetting);
    }
   
    @SubscribeEvent
    public void onTick(TickEvent event) {
        if (booleanSetting.isEnabled()) {
            /* ... */
        }
    }
}
Так-же для возможности открыть нашу гуи создаем класс

Java:
public class ClickGUI extends Module {

    public ClickGUI() {
        super("gui", ModuleCategory.Visuals, "yougame gui", GLFW.GLFW_KEY_RIGHT_SHIFT);
    }

    @Override
    public void onEnable() {
        mc.setScreen(new ClickUi());
    }
}
И регистрируем его в ModuleManager'e
По итогу мы имеем достаточно простенькую, но какую никакую собственную базу.
Спасибо за уделенное время!

Нужно ли вообще делать тутор на хуки/миксины?
+rep
 
Начинающий
Статус
Оффлайн
Регистрация
8 Апр 2023
Сообщения
219
Реакции[?]
20
Поинты[?]
23K
Java:
public abstract class Module {
    public FeatureCategory category;
    public boolean included;

    public boolean isEnabled() {
        return included;
    }
 
    public ModuleCategory getCategory() {
        return category;
    }

}
после этой хуйни я не стал дальше смотреть, но уверен там такого будет больше.
 
Начинающий
Статус
Оффлайн
Регистрация
28 Мар 2024
Сообщения
319
Реакции[?]
0
Поинты[?]
0
Для начала устанавливаем плагин Minecraft Development

Далее создаем новый проект
Посмотреть вложение 289600
Заходим в главный класс мода и оставляем для себя только

Java:
@Mod("bigbrain")
public class ClientEntry {
 
    public ClientEntry() {
        init();
    }

    public void init() {
        MinecraftForge.EVENT_BUS.register(this);
    }
}
Далее мы берём ноги в зубы и идем плотно пастить утилки с гитхаба (
Пожалуйста, авторизуйтесь для просмотра ссылки.
|
Пожалуйста, авторизуйтесь для просмотра ссылки.
)

После успешного пастинга едем реализовывать наши функции.
Создаем класс Module и ModuleCategory
Java:
public abstract class Module {
    public String name;
    public ModuleCategory category;
    public String description;
    public int key;
    public boolean included;
    public List<Setting> settings = new ArrayList<>();
 
    public Module(String name, ModuleCategory category, String description) {
        this.name = name;
        this.category = category;
        this.description = description;
    }
 
     public Module(String name, ModuleCategory category, String description, int key) {
        this.name = name;
        this.category = category;
        this.key = key;
        this.description = description;
    }
 
    public void onEnable() {
        included = true;
        MinecraftForge.EVENT_BUS.register(this);
    }
 
    public void onDisable() {
        included = false;
        MinecraftForge.EVENT_BUS.unregister(this);
    }
 
    public void toggle() {
        if (included) {
            onDisable();
        } else {
            onEnable();
        }
    }
 
    public boolean isEnabled() {
        return included;
    }
 
    public ModuleCategory getCategory() {
        return category;
    }
}
Java:
public enum ModuleCategory {
    Combat,
    Movement,
    Player,
    Visuals
}
Так-же нам нужно создать менеджер для наших будущих функций
Java:
public class ModulesManager {
    public static ArrayList<Feature> modules = new ArrayList<>();

    public static void addModules() {
        try {
                // modules.add(new Class());
            new Thread(() -> {
                try {
                    Thread.sleep(5000);
                } catch (Exception ignored) {
                }
            }).start();
        } catch (Exception ignored) {
        }
    }

    public static boolean moduleIncluded(Class<?> featureClass) {
        for (Feature feature : features) {
            if (feature.included && feature.getClass() == featureClass) {
                return true;
            }
        }
        return false;
    }
}
В ините нашего мейн класса вызываем
Java:
ModuleManager.addModules();
Так-же добавляем в наш главный класс обработку нажатий на кнопки биндов

Java:
@SubscribeEvent
public void onKeyInput(InputEvent.KeyInputEvent keyInputEvent) {
    for (Module module : ModuleManager.modules) {
        if (Minecraft.getInstance().screen == null && keyInputEvent.getKey() == module.key && keyInputEvent.getAction() == 1) {
            module.toggle();
        }
    }
}
Уже сейчас мы можем для примера написать какую нибудь простенькую функцию

Java:
public class TestModule extends Module {
    public TestModule() {
        super("test module", ModuleCategory.Movement, "jumping$", GLFW.GLFW_KEY_X);
    }
 
    // логика нашего $elfcod'a
    @Override
    public void onEnable() {
        Minecraft.getInstance().player.jumpFromGround();
        super.onDisable();
    }
}
Не забываем зарегистрировать функцию с помощью ModuleManager'a

Чисто для нашего удобства создадит класс ClientUtil
Java:
public class ClientUtil {
    public static Minecraft mc = Minecraft.getInstance();
    public static MainWindow mw = mc.getWindow();
 
    // добавляем сюда все, что используем часто
}
Пришло время создать максимально простенькое нечто, напоминающее клик гуи

Java:
public class ClickUi extends Screen {
    private final List<Module> modules;
    private ModuleCategory selected;
    private int offset;

    public ClickUi() {
        super(new StringTextComponent("gui"));
        this.modules = ModuleManager.modules;
        this.selected = ModuleCategory.Combat;
        this.offset = 0;
    }

    @Override
    protected void init() {
        int y = this.height / 2 - 75;
        for (ModuleCategory category : ModuleCategory.values()) {
            this.addButton(new Buttons(this.width / 2 - 105, y, 75, 20, category.name(), (btn) -> {
                selected = category;
            }));
            y += 25;
        }
    }

    @Override
    public void render(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {
        this.renderBackground(matrixStack);
        int x = this.width / 2;
        int Ypos = this.height / 2;

        DrawHelper.drawRoundedRect(x - 110, Ypos + 80, 225, 160, 5, new Color(8, 10, 12).brighter());
        DrawHelper.drawRoundedRect(x - 20, Ypos + 75, 130, 150, 5, new Color(8, 10, 12));

        RenderSystem.enableScissor((x - 20) * this.minecraft.getWindow().getWidth() / this.width,
                (Ypos - 74) * this.minecraft.getWindow().getHeight() / this.height,
                130 * this.minecraft.getWindow().getWidth() / this.width,
                150 * this.minecraft.getWindow().getHeight() / this.height);

        int y = Ypos - 70 + offset;
        for (Module module : modules) {
            if (module.getCategory() == selected) {
                StyledFontRenderer.drawString(matrixStack, ClientEntry.big, module.name, x - 15, y + ClientEntry.big.getFontHeight(), module.isEnabled() ? new Color(56, 78, 126) : new Color(255, 255, 255));
                y += 15;
            }
        }

        RenderSystem.disableScissor();

        super.render(matrixStack, mouseX, mouseY, partialTicks);
    }

    @Override
    public boolean mouseClicked(double mouseX, double mouseY, int button) {
        if (button == 0) {
            int x = this.width / 2;
            int Ypos = this.height / 2;
            int y = Ypos - 70 + offset;
            for (Module module : modules) {
                if (module.getCategory() == selected) {
                    if (mouseX >= x - 15 && mouseX <= x + 85 && mouseY >= y && mouseY <= y + 15) {
                        module.toggle();
                        return true;
                    }
                    y += 15;
                }
            }
        }
        return super.mouseClicked(mouseX, mouseY, button);
    }

    @Override
    public boolean mouseScrolled(double mouseX, double mouseY, double value) {
        offset += value * 10;
        offset = Math.max(Math.min(offset, 0), -getMaxScroll());
        return true;
    }

    private int getMaxScroll() {
        int count = 0;
        for (Module module : modules) {
            if (module.getCategory() == selected) {
                count++;
            }
        }
        return Math.max(0, count * 15 - 125);
    }

    private static class Buttons extends Button {
        public Buttons(int x, int y, int width, int height, String text, IPressable onPress) {
            super(x, y, width, height, new StringTextComponent(text), onPress);
        }

        @Override
        public void renderButton(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {
            Color color = this.isHovered() ? new Color(56, 78, 126) : new Color(17, 24, 39);
            DrawHelper.drawRoundedRect(this.x, this.y + this.height, this.width, this.height, 3, color);
            StyledFontRenderer.drawCenteredXString(matrixStack, ClientEntry.big, this.getMessage().getString(), this.x + this.width / 2, this.y + (this.height / 2) + 4, Color.WHITE);
        }
    }
}
На выходе получаем микро вариант cs gui
Посмотреть вложение 289608
Визуально ее изменить думаю осилит каждый (если конечно iq чуть выше 15)

Но мы же блатные, поэтому надо сделать сеттинги

Создаем класс Setting

Java:
public class Setting {
    public String name;
    public boolean isVisible = true;

    public Setting(String name) {this.name = name;}

    public boolean isVisible() {return isVisible;}

    public String getName() {return name;}
}
Далее к нему уже создаем классы FloatSetting, BooleanSetting, ModeSetting
Java:
public class FloatSetting extends Setting {
    private double min, max, inc;
    public double value;
    double defaultvalue;

    public void setInc(double inc) {
        this.inc = inc;
    }

    public double getDefaultvalue() {
        return defaultvalue;
    }

    public void setDefaultvalue(double defaultvalue) {
        this.defaultvalue = defaultvalue;
    }

    public FloatSetting(String name, double min, double max, double defaultvalue, double inc) {
        super(name);
        this.max = max;
        this.min = min;
        this.defaultvalue = defaultvalue;
        this.inc = inc;
        this.value = clamp((float) defaultvalue, (float) min, (float) max);
    }

    public double getValue() {
        return (value != 0) ? value : defaultvalue;
    }

    public double getValueFloat() {
        return (float) value;
    }

    public void setValDouble(double in) {
        this.value = in;
    }

    public void setValue(double value) {
        value = Math.round(value / inc) * inc;
        this.value = clamp(value, min, max);
    }

    public static double clamp(double num, double min, double max) {
        return Math.max(min, Math.min(max, num));
    }

    public void reset() {
        setValue(defaultvalue);
    }

    public double getMin() {
        return min;
    }

    public void setMin(double min) {
        this.min = min;
    }

    public double getMax() {
        return max;
    }

    public void setMax(double max) {
        this.max = max;
    }

    public double getInc() {
        return inc;
    }

    public static float clamp(float num, float min, float max) {
        return num < min ? min : num > max ? max : num;
    }

    public int getValueInt() {
        return (int) value;
    }

    public void inc(boolean isPositive) {
        if (isPositive) setValue(getValue() + getInc());
        else setValue(getValue() - getInc());
    }
}
Java:
public class BooleanSetting extends Setting {
    public boolean value;

    public BooleanSetting(String name, boolean defaultVal) {
        super(name);
        this.value = defaultVal;
    }

    public void toggle() {
        this.value = !this.value;
    }

    public boolean isEnabled() {
        return value;
    }

    public void setEnabled() {
        this.value = value;
    }

    public boolean getValue() {
        return this.value;
    }
}
Java:
public class ModeSetting extends Setting {
    private List<String> modes;
    private int index;
    public String mode;
    public Animation animation;
    public String previousMode;
    private int previousIndex;

    public List<String> getModes() {
        return modes;
    }

    public void setModes(List<String> modes) {
        this.modes = modes;
    }

    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
        this.mode = modes.get(index);
    }

    public String getMode() {
        return mode;
    }


    public ModeSetting(String name, String... modes) {
        super(name);
        this.modes = Arrays.asList(modes);
        this.mode = this.modes.get(0);
        this.index = 0;
        this.animation = new Animation(1, 1, 0.1f);
        this.previousMode = null;
        this.previousIndex = 0;
    }

    public void cycle() {
        this.previousMode = this.mode;
        this.previousIndex = this.index;
        if (index < modes.size() - 1) {
            index++;
        } else {
            index = 0;
        }
        this.mode = modes.get(index);
        this.animation.setAnim(0);
    }

    public void setMode(String mode) {
        if (!this.mode.equals(mode)) {
            this.previousMode = this.mode;
            this.previousIndex = this.index;
            this.mode = mode;
            this.index = modes.indexOf(mode);
            this.animation.setAnim(0);
        }
    }

    public int getPreviousIndex() {
        return previousIndex;
    }

    public boolean isMode(String mode) {
        return Objects.equals(this.mode, mode);
    }

    public String getValue() {
        return this.mode;
    }
}
Сеттинги в гуи добавите сами, мне впадлу слишком <3

Пример использованию наших сеттингов


Java:
public class TestModule() {
 
    BooleanSetting booleanSetting = new BooleanSetting("Bool Setting", true);
 
    public TestModule() {
        super("module", ModuleCategory.Visuals, "test");
        addSettings(booleanSetting);
    }
 
    @SubscribeEvent
    public void onTick(TickEvent event) {
        if (booleanSetting.isEnabled()) {
            /* ... */
        }
    }
}
Так-же для возможности открыть нашу гуи создаем класс

Java:
public class ClickGUI extends Module {

    public ClickGUI() {
        super("gui", ModuleCategory.Visuals, "yougame gui", GLFW.GLFW_KEY_RIGHT_SHIFT);
    }

    @Override
    public void onEnable() {
        mc.setScreen(new ClickUi());
    }
}
И регистрируем его в ModuleManager'e
По итогу мы имеем достаточно простенькую, но какую никакую собственную базу.
Спасибо за уделенное время!

Нужно ли вообще делать тутор на хуки/миксины?
ебать имбо
 
Забаненный
Статус
Оффлайн
Регистрация
26 Окт 2024
Сообщения
125
Реакции[?]
0
Поинты[?]
0
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Forge Api ;-;
Начинающий
Статус
Оффлайн
Регистрация
3 Май 2023
Сообщения
776
Реакции[?]
18
Поинты[?]
13K
АПВЗ=ПВЗАХПАВЗХЗХПВАХЗПВАХЗПАВ
ну у меня свои прикольчики с инжектом типо да пон, типу который делает конкретно модом это не надо, но мне было слишком лень вырезать
 
Начинающий
Статус
Онлайн
Регистрация
20 Июн 2024
Сообщения
256
Реакции[?]
1
Поинты[?]
1K
Для начала устанавливаем плагин Minecraft Development

Далее создаем новый проект
Посмотреть вложение 289600
Заходим в главный класс мода и оставляем для себя только

Java:
@Mod("bigbrain")
public class ClientEntry {
 
    public ClientEntry() {
        init();
    }

    public void init() {
        MinecraftForge.EVENT_BUS.register(this);
    }
}
Далее мы берём ноги в зубы и идем плотно пастить утилки с гитхаба (
Пожалуйста, авторизуйтесь для просмотра ссылки.
|
Пожалуйста, авторизуйтесь для просмотра ссылки.
)

После успешного пастинга едем реализовывать наши функции.
Создаем класс Module и ModuleCategory
Java:
public abstract class Module {
    public String name;
    public ModuleCategory category;
    public String description;
    public int key;
    public boolean included;
    public List<Setting> settings = new ArrayList<>();
 
    public Module(String name, ModuleCategory category, String description) {
        this.name = name;
        this.category = category;
        this.description = description;
    }
 
     public Module(String name, ModuleCategory category, String description, int key) {
        this.name = name;
        this.category = category;
        this.key = key;
        this.description = description;
    }
 
    public void onEnable() {
        included = true;
        MinecraftForge.EVENT_BUS.register(this);
    }
 
    public void onDisable() {
        included = false;
        MinecraftForge.EVENT_BUS.unregister(this);
    }
 
    public void toggle() {
        if (included) {
            onDisable();
        } else {
            onEnable();
        }
    }
 
    public boolean isEnabled() {
        return included;
    }
 
    public ModuleCategory getCategory() {
        return category;
    }
}
Java:
public enum ModuleCategory {
    Combat,
    Movement,
    Player,
    Visuals
}
Так-же нам нужно создать менеджер для наших будущих функций
Java:
public class ModulesManager {
    public static ArrayList<Feature> modules = new ArrayList<>();

    public static void addModules() {
        try {
                // modules.add(new Class());
            new Thread(() -> {
                try {
                    Thread.sleep(5000);
                } catch (Exception ignored) {
                }
            }).start();
        } catch (Exception ignored) {
        }
    }

    public static boolean moduleIncluded(Class<?> featureClass) {
        for (Feature feature : features) {
            if (feature.included && feature.getClass() == featureClass) {
                return true;
            }
        }
        return false;
    }
}
В ините нашего мейн класса вызываем
Java:
ModuleManager.addModules();
Так-же добавляем в наш главный класс обработку нажатий на кнопки биндов

Java:
@SubscribeEvent
public void onKeyInput(InputEvent.KeyInputEvent keyInputEvent) {
    for (Module module : ModuleManager.modules) {
        if (Minecraft.getInstance().screen == null && keyInputEvent.getKey() == module.key && keyInputEvent.getAction() == 1) {
            module.toggle();
        }
    }
}
Уже сейчас мы можем для примера написать какую нибудь простенькую функцию

Java:
public class TestModule extends Module {
    public TestModule() {
        super("test module", ModuleCategory.Movement, "jumping$", GLFW.GLFW_KEY_X);
    }
 
    // логика нашего $elfcod'a
    @Override
    public void onEnable() {
        Minecraft.getInstance().player.jumpFromGround();
        super.onDisable();
    }
}
Не забываем зарегистрировать функцию с помощью ModuleManager'a

Чисто для нашего удобства создадит класс ClientUtil
Java:
public class ClientUtil {
    public static Minecraft mc = Minecraft.getInstance();
    public static MainWindow mw = mc.getWindow();
 
    // добавляем сюда все, что используем часто
}
Пришло время создать максимально простенькое нечто, напоминающее клик гуи

Java:
public class ClickUi extends Screen {
    private final List<Module> modules;
    private ModuleCategory selected;
    private int offset;

    public ClickUi() {
        super(new StringTextComponent("gui"));
        this.modules = ModuleManager.modules;
        this.selected = ModuleCategory.Combat;
        this.offset = 0;
    }

    @Override
    protected void init() {
        int y = this.height / 2 - 75;
        for (ModuleCategory category : ModuleCategory.values()) {
            this.addButton(new Buttons(this.width / 2 - 105, y, 75, 20, category.name(), (btn) -> {
                selected = category;
            }));
            y += 25;
        }
    }

    @Override
    public void render(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {
        this.renderBackground(matrixStack);
        int x = this.width / 2;
        int Ypos = this.height / 2;

        DrawHelper.drawRoundedRect(x - 110, Ypos + 80, 225, 160, 5, new Color(8, 10, 12).brighter());
        DrawHelper.drawRoundedRect(x - 20, Ypos + 75, 130, 150, 5, new Color(8, 10, 12));

        RenderSystem.enableScissor((x - 20) * this.minecraft.getWindow().getWidth() / this.width,
                (Ypos - 74) * this.minecraft.getWindow().getHeight() / this.height,
                130 * this.minecraft.getWindow().getWidth() / this.width,
                150 * this.minecraft.getWindow().getHeight() / this.height);

        int y = Ypos - 70 + offset;
        for (Module module : modules) {
            if (module.getCategory() == selected) {
                StyledFontRenderer.drawString(matrixStack, ClientEntry.big, module.name, x - 15, y + ClientEntry.big.getFontHeight(), module.isEnabled() ? new Color(56, 78, 126) : new Color(255, 255, 255));
                y += 15;
            }
        }

        RenderSystem.disableScissor();

        super.render(matrixStack, mouseX, mouseY, partialTicks);
    }

    @Override
    public boolean mouseClicked(double mouseX, double mouseY, int button) {
        if (button == 0) {
            int x = this.width / 2;
            int Ypos = this.height / 2;
            int y = Ypos - 70 + offset;
            for (Module module : modules) {
                if (module.getCategory() == selected) {
                    if (mouseX >= x - 15 && mouseX <= x + 85 && mouseY >= y && mouseY <= y + 15) {
                        module.toggle();
                        return true;
                    }
                    y += 15;
                }
            }
        }
        return super.mouseClicked(mouseX, mouseY, button);
    }

    @Override
    public boolean mouseScrolled(double mouseX, double mouseY, double value) {
        offset += value * 10;
        offset = Math.max(Math.min(offset, 0), -getMaxScroll());
        return true;
    }

    private int getMaxScroll() {
        int count = 0;
        for (Module module : modules) {
            if (module.getCategory() == selected) {
                count++;
            }
        }
        return Math.max(0, count * 15 - 125);
    }

    private static class Buttons extends Button {
        public Buttons(int x, int y, int width, int height, String text, IPressable onPress) {
            super(x, y, width, height, new StringTextComponent(text), onPress);
        }

        @Override
        public void renderButton(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {
            Color color = this.isHovered() ? new Color(56, 78, 126) : new Color(17, 24, 39);
            DrawHelper.drawRoundedRect(this.x, this.y + this.height, this.width, this.height, 3, color);
            StyledFontRenderer.drawCenteredXString(matrixStack, ClientEntry.big, this.getMessage().getString(), this.x + this.width / 2, this.y + (this.height / 2) + 4, Color.WHITE);
        }
    }
}
На выходе получаем микро вариант cs gui
Посмотреть вложение 289608
Визуально ее изменить думаю осилит каждый (если конечно iq чуть выше 15)

Но мы же блатные, поэтому надо сделать сеттинги

Создаем класс Setting

Java:
public class Setting {
    public String name;
    public boolean isVisible = true;

    public Setting(String name) {this.name = name;}

    public boolean isVisible() {return isVisible;}

    public String getName() {return name;}
}
Далее к нему уже создаем классы FloatSetting, BooleanSetting, ModeSetting
Java:
public class FloatSetting extends Setting {
    private double min, max, inc;
    public double value;
    double defaultvalue;

    public void setInc(double inc) {
        this.inc = inc;
    }

    public double getDefaultvalue() {
        return defaultvalue;
    }

    public void setDefaultvalue(double defaultvalue) {
        this.defaultvalue = defaultvalue;
    }

    public FloatSetting(String name, double min, double max, double defaultvalue, double inc) {
        super(name);
        this.max = max;
        this.min = min;
        this.defaultvalue = defaultvalue;
        this.inc = inc;
        this.value = clamp((float) defaultvalue, (float) min, (float) max);
    }

    public double getValue() {
        return (value != 0) ? value : defaultvalue;
    }

    public double getValueFloat() {
        return (float) value;
    }

    public void setValDouble(double in) {
        this.value = in;
    }

    public void setValue(double value) {
        value = Math.round(value / inc) * inc;
        this.value = clamp(value, min, max);
    }

    public static double clamp(double num, double min, double max) {
        return Math.max(min, Math.min(max, num));
    }

    public void reset() {
        setValue(defaultvalue);
    }

    public double getMin() {
        return min;
    }

    public void setMin(double min) {
        this.min = min;
    }

    public double getMax() {
        return max;
    }

    public void setMax(double max) {
        this.max = max;
    }

    public double getInc() {
        return inc;
    }

    public static float clamp(float num, float min, float max) {
        return num < min ? min : num > max ? max : num;
    }

    public int getValueInt() {
        return (int) value;
    }

    public void inc(boolean isPositive) {
        if (isPositive) setValue(getValue() + getInc());
        else setValue(getValue() - getInc());
    }
}
Java:
public class BooleanSetting extends Setting {
    public boolean value;

    public BooleanSetting(String name, boolean defaultVal) {
        super(name);
        this.value = defaultVal;
    }

    public void toggle() {
        this.value = !this.value;
    }

    public boolean isEnabled() {
        return value;
    }

    public void setEnabled() {
        this.value = value;
    }

    public boolean getValue() {
        return this.value;
    }
}
Java:
public class ModeSetting extends Setting {
    private List<String> modes;
    private int index;
    public String mode;
    public Animation animation;
    public String previousMode;
    private int previousIndex;

    public List<String> getModes() {
        return modes;
    }

    public void setModes(List<String> modes) {
        this.modes = modes;
    }

    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
        this.mode = modes.get(index);
    }

    public String getMode() {
        return mode;
    }


    public ModeSetting(String name, String... modes) {
        super(name);
        this.modes = Arrays.asList(modes);
        this.mode = this.modes.get(0);
        this.index = 0;
        this.animation = new Animation(1, 1, 0.1f);
        this.previousMode = null;
        this.previousIndex = 0;
    }

    public void cycle() {
        this.previousMode = this.mode;
        this.previousIndex = this.index;
        if (index < modes.size() - 1) {
            index++;
        } else {
            index = 0;
        }
        this.mode = modes.get(index);
        this.animation.setAnim(0);
    }

    public void setMode(String mode) {
        if (!this.mode.equals(mode)) {
            this.previousMode = this.mode;
            this.previousIndex = this.index;
            this.mode = mode;
            this.index = modes.indexOf(mode);
            this.animation.setAnim(0);
        }
    }

    public int getPreviousIndex() {
        return previousIndex;
    }

    public boolean isMode(String mode) {
        return Objects.equals(this.mode, mode);
    }

    public String getValue() {
        return this.mode;
    }
}
Сеттинги в гуи добавите сами, мне впадлу слишком <3

Пример использованию наших сеттингов


Java:
public class TestModule() {
 
    BooleanSetting booleanSetting = new BooleanSetting("Bool Setting", true);
 
    public TestModule() {
        super("module", ModuleCategory.Visuals, "test");
        addSettings(booleanSetting);
    }
 
    @SubscribeEvent
    public void onTick(TickEvent event) {
        if (booleanSetting.isEnabled()) {
            /* ... */
        }
    }
}
Так-же для возможности открыть нашу гуи создаем класс

Java:
public class ClickGUI extends Module {

    public ClickGUI() {
        super("gui", ModuleCategory.Visuals, "yougame gui", GLFW.GLFW_KEY_RIGHT_SHIFT);
    }

    @Override
    public void onEnable() {
        mc.setScreen(new ClickUi());
    }
}
И регистрируем его в ModuleManager'e
По итогу мы имеем достаточно простенькую, но какую никакую собственную базу.
Спасибо за уделенное время!

Нужно ли вообще делать тутор на хуки/миксины?
Ждём хуки и миксины, мне как типу который пишет на фордже интересно узнать
 
Начинающий
Статус
Оффлайн
Регистрация
15 Фев 2023
Сообщения
125
Реакции[?]
0
Поинты[?]
0
Для начала устанавливаем плагин Minecraft Development

Далее создаем новый проект
Посмотреть вложение 289600
Заходим в главный класс мода и оставляем для себя только

Java:
@Mod("bigbrain")
public class ClientEntry {
 
    public ClientEntry() {
        init();
    }

    public void init() {
        MinecraftForge.EVENT_BUS.register(this);
    }
}
Далее мы берём ноги в зубы и идем плотно пастить утилки с гитхаба (
Пожалуйста, авторизуйтесь для просмотра ссылки.
|
Пожалуйста, авторизуйтесь для просмотра ссылки.
)

После успешного пастинга едем реализовывать наши функции.
Создаем класс Module и ModuleCategory
Java:
public abstract class Module {
    public String name;
    public ModuleCategory category;
    public String description;
    public int key;
    public boolean included;
    public List<Setting> settings = new ArrayList<>();
 
    public Module(String name, ModuleCategory category, String description) {
        this.name = name;
        this.category = category;
        this.description = description;
    }
 
     public Module(String name, ModuleCategory category, String description, int key) {
        this.name = name;
        this.category = category;
        this.key = key;
        this.description = description;
    }
 
    public void onEnable() {
        included = true;
        MinecraftForge.EVENT_BUS.register(this);
    }
 
    public void onDisable() {
        included = false;
        MinecraftForge.EVENT_BUS.unregister(this);
    }
 
    public void toggle() {
        if (included) {
            onDisable();
        } else {
            onEnable();
        }
    }
 
    public boolean isEnabled() {
        return included;
    }
 
    public ModuleCategory getCategory() {
        return category;
    }
}
Java:
public enum ModuleCategory {
    Combat,
    Movement,
    Player,
    Visuals
}
Так-же нам нужно создать менеджер для наших будущих функций
Java:
public class ModulesManager {
    public static ArrayList<Feature> modules = new ArrayList<>();

    public static void addModules() {
        try {
                // modules.add(new Class());
            new Thread(() -> {
                try {
                    Thread.sleep(5000);
                } catch (Exception ignored) {
                }
            }).start();
        } catch (Exception ignored) {
        }
    }

    public static boolean moduleIncluded(Class<?> featureClass) {
        for (Feature feature : features) {
            if (feature.included && feature.getClass() == featureClass) {
                return true;
            }
        }
        return false;
    }
}
В ините нашего мейн класса вызываем
Java:
ModuleManager.addModules();
Так-же добавляем в наш главный класс обработку нажатий на кнопки биндов

Java:
@SubscribeEvent
public void onKeyInput(InputEvent.KeyInputEvent keyInputEvent) {
    for (Module module : ModuleManager.modules) {
        if (Minecraft.getInstance().screen == null && keyInputEvent.getKey() == module.key && keyInputEvent.getAction() == 1) {
            module.toggle();
        }
    }
}
Уже сейчас мы можем для примера написать какую нибудь простенькую функцию

Java:
public class TestModule extends Module {
    public TestModule() {
        super("test module", ModuleCategory.Movement, "jumping$", GLFW.GLFW_KEY_X);
    }
 
    // логика нашего $elfcod'a
    @Override
    public void onEnable() {
        Minecraft.getInstance().player.jumpFromGround();
        super.onDisable();
    }
}
Не забываем зарегистрировать функцию с помощью ModuleManager'a

Чисто для нашего удобства создадит класс ClientUtil
Java:
public class ClientUtil {
    public static Minecraft mc = Minecraft.getInstance();
    public static MainWindow mw = mc.getWindow();
 
    // добавляем сюда все, что используем часто
}
Пришло время создать максимально простенькое нечто, напоминающее клик гуи

Java:
public class ClickUi extends Screen {
    private final List<Module> modules;
    private ModuleCategory selected;
    private int offset;

    public ClickUi() {
        super(new StringTextComponent("gui"));
        this.modules = ModuleManager.modules;
        this.selected = ModuleCategory.Combat;
        this.offset = 0;
    }

    @Override
    protected void init() {
        int y = this.height / 2 - 75;
        for (ModuleCategory category : ModuleCategory.values()) {
            this.addButton(new Buttons(this.width / 2 - 105, y, 75, 20, category.name(), (btn) -> {
                selected = category;
            }));
            y += 25;
        }
    }

    @Override
    public void render(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {
        this.renderBackground(matrixStack);
        int x = this.width / 2;
        int Ypos = this.height / 2;

        DrawHelper.drawRoundedRect(x - 110, Ypos + 80, 225, 160, 5, new Color(8, 10, 12).brighter());
        DrawHelper.drawRoundedRect(x - 20, Ypos + 75, 130, 150, 5, new Color(8, 10, 12));

        RenderSystem.enableScissor((x - 20) * this.minecraft.getWindow().getWidth() / this.width,
                (Ypos - 74) * this.minecraft.getWindow().getHeight() / this.height,
                130 * this.minecraft.getWindow().getWidth() / this.width,
                150 * this.minecraft.getWindow().getHeight() / this.height);

        int y = Ypos - 70 + offset;
        for (Module module : modules) {
            if (module.getCategory() == selected) {
                StyledFontRenderer.drawString(matrixStack, ClientEntry.big, module.name, x - 15, y + ClientEntry.big.getFontHeight(), module.isEnabled() ? new Color(56, 78, 126) : new Color(255, 255, 255));
                y += 15;
            }
        }

        RenderSystem.disableScissor();

        super.render(matrixStack, mouseX, mouseY, partialTicks);
    }

    @Override
    public boolean mouseClicked(double mouseX, double mouseY, int button) {
        if (button == 0) {
            int x = this.width / 2;
            int Ypos = this.height / 2;
            int y = Ypos - 70 + offset;
            for (Module module : modules) {
                if (module.getCategory() == selected) {
                    if (mouseX >= x - 15 && mouseX <= x + 85 && mouseY >= y && mouseY <= y + 15) {
                        module.toggle();
                        return true;
                    }
                    y += 15;
                }
            }
        }
        return super.mouseClicked(mouseX, mouseY, button);
    }

    @Override
    public boolean mouseScrolled(double mouseX, double mouseY, double value) {
        offset += value * 10;
        offset = Math.max(Math.min(offset, 0), -getMaxScroll());
        return true;
    }

    private int getMaxScroll() {
        int count = 0;
        for (Module module : modules) {
            if (module.getCategory() == selected) {
                count++;
            }
        }
        return Math.max(0, count * 15 - 125);
    }

    private static class Buttons extends Button {
        public Buttons(int x, int y, int width, int height, String text, IPressable onPress) {
            super(x, y, width, height, new StringTextComponent(text), onPress);
        }

        @Override
        public void renderButton(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {
            Color color = this.isHovered() ? new Color(56, 78, 126) : new Color(17, 24, 39);
            DrawHelper.drawRoundedRect(this.x, this.y + this.height, this.width, this.height, 3, color);
            StyledFontRenderer.drawCenteredXString(matrixStack, ClientEntry.big, this.getMessage().getString(), this.x + this.width / 2, this.y + (this.height / 2) + 4, Color.WHITE);
        }
    }
}
На выходе получаем микро вариант cs gui
Посмотреть вложение 289608
Визуально ее изменить думаю осилит каждый (если конечно iq чуть выше 15)

Но мы же блатные, поэтому надо сделать сеттинги

Создаем класс Setting

Java:
public class Setting {
    public String name;
    public boolean isVisible = true;

    public Setting(String name) {this.name = name;}

    public boolean isVisible() {return isVisible;}

    public String getName() {return name;}
}
Далее к нему уже создаем классы FloatSetting, BooleanSetting, ModeSetting
Java:
public class FloatSetting extends Setting {
    private double min, max, inc;
    public double value;
    double defaultvalue;

    public void setInc(double inc) {
        this.inc = inc;
    }

    public double getDefaultvalue() {
        return defaultvalue;
    }

    public void setDefaultvalue(double defaultvalue) {
        this.defaultvalue = defaultvalue;
    }

    public FloatSetting(String name, double min, double max, double defaultvalue, double inc) {
        super(name);
        this.max = max;
        this.min = min;
        this.defaultvalue = defaultvalue;
        this.inc = inc;
        this.value = clamp((float) defaultvalue, (float) min, (float) max);
    }

    public double getValue() {
        return (value != 0) ? value : defaultvalue;
    }

    public double getValueFloat() {
        return (float) value;
    }

    public void setValDouble(double in) {
        this.value = in;
    }

    public void setValue(double value) {
        value = Math.round(value / inc) * inc;
        this.value = clamp(value, min, max);
    }

    public static double clamp(double num, double min, double max) {
        return Math.max(min, Math.min(max, num));
    }

    public void reset() {
        setValue(defaultvalue);
    }

    public double getMin() {
        return min;
    }

    public void setMin(double min) {
        this.min = min;
    }

    public double getMax() {
        return max;
    }

    public void setMax(double max) {
        this.max = max;
    }

    public double getInc() {
        return inc;
    }

    public static float clamp(float num, float min, float max) {
        return num < min ? min : num > max ? max : num;
    }

    public int getValueInt() {
        return (int) value;
    }

    public void inc(boolean isPositive) {
        if (isPositive) setValue(getValue() + getInc());
        else setValue(getValue() - getInc());
    }
}
Java:
public class BooleanSetting extends Setting {
    public boolean value;

    public BooleanSetting(String name, boolean defaultVal) {
        super(name);
        this.value = defaultVal;
    }

    public void toggle() {
        this.value = !this.value;
    }

    public boolean isEnabled() {
        return value;
    }

    public void setEnabled() {
        this.value = value;
    }

    public boolean getValue() {
        return this.value;
    }
}
Java:
public class ModeSetting extends Setting {
    private List<String> modes;
    private int index;
    public String mode;
    public Animation animation;
    public String previousMode;
    private int previousIndex;

    public List<String> getModes() {
        return modes;
    }

    public void setModes(List<String> modes) {
        this.modes = modes;
    }

    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
        this.mode = modes.get(index);
    }

    public String getMode() {
        return mode;
    }


    public ModeSetting(String name, String... modes) {
        super(name);
        this.modes = Arrays.asList(modes);
        this.mode = this.modes.get(0);
        this.index = 0;
        this.animation = new Animation(1, 1, 0.1f);
        this.previousMode = null;
        this.previousIndex = 0;
    }

    public void cycle() {
        this.previousMode = this.mode;
        this.previousIndex = this.index;
        if (index < modes.size() - 1) {
            index++;
        } else {
            index = 0;
        }
        this.mode = modes.get(index);
        this.animation.setAnim(0);
    }

    public void setMode(String mode) {
        if (!this.mode.equals(mode)) {
            this.previousMode = this.mode;
            this.previousIndex = this.index;
            this.mode = mode;
            this.index = modes.indexOf(mode);
            this.animation.setAnim(0);
        }
    }

    public int getPreviousIndex() {
        return previousIndex;
    }

    public boolean isMode(String mode) {
        return Objects.equals(this.mode, mode);
    }

    public String getValue() {
        return this.mode;
    }
}
Сеттинги в гуи добавите сами, мне впадлу слишком <3

Пример использованию наших сеттингов


Java:
public class TestModule() {
 
    BooleanSetting booleanSetting = new BooleanSetting("Bool Setting", true);
 
    public TestModule() {
        super("module", ModuleCategory.Visuals, "test");
        addSettings(booleanSetting);
    }
 
    @SubscribeEvent
    public void onTick(TickEvent event) {
        if (booleanSetting.isEnabled()) {
            /* ... */
        }
    }
}
Так-же для возможности открыть нашу гуи создаем класс

Java:
public class ClickGUI extends Module {

    public ClickGUI() {
        super("gui", ModuleCategory.Visuals, "yougame gui", GLFW.GLFW_KEY_RIGHT_SHIFT);
    }

    @Override
    public void onEnable() {
        mc.setScreen(new ClickUi());
    }
}
И регистрируем его в ModuleManager'e
По итогу мы имеем достаточно простенькую, но какую никакую собственную базу.
Спасибо за уделенное время!

Нужно ли вообще делать тутор на хуки/миксины?
годно :seemsgood:
 
Начинающий
Статус
Оффлайн
Регистрация
22 Мар 2022
Сообщения
181
Реакции[?]
7
Поинты[?]
6K
Начинающий
Статус
Оффлайн
Регистрация
17 Ноя 2023
Сообщения
114
Реакции[?]
1
Поинты[?]
1K
Для начала устанавливаем плагин Minecraft Development

Далее создаем новый проект
Посмотреть вложение 289600
Заходим в главный класс мода и оставляем для себя только

Java:
@Mod("bigbrain")
public class ClientEntry {
 
    public ClientEntry() {
        init();
    }

    public void init() {
        MinecraftForge.EVENT_BUS.register(this);
    }
}
Далее мы берём ноги в зубы и идем плотно пастить утилки с гитхаба (
Пожалуйста, авторизуйтесь для просмотра ссылки.
|
Пожалуйста, авторизуйтесь для просмотра ссылки.
)

После успешного пастинга едем реализовывать наши функции.
Создаем класс Module и ModuleCategory
Java:
public abstract class Module {
    public String name;
    public ModuleCategory category;
    public String description;
    public int key;
    public boolean included;
    public List<Setting> settings = new ArrayList<>();
 
    public Module(String name, ModuleCategory category, String description) {
        this.name = name;
        this.category = category;
        this.description = description;
    }
 
     public Module(String name, ModuleCategory category, String description, int key) {
        this.name = name;
        this.category = category;
        this.key = key;
        this.description = description;
    }
 
    public void onEnable() {
        included = true;
        MinecraftForge.EVENT_BUS.register(this);
    }
 
    public void onDisable() {
        included = false;
        MinecraftForge.EVENT_BUS.unregister(this);
    }
 
    public void toggle() {
        if (included) {
            onDisable();
        } else {
            onEnable();
        }
    }
 
    public boolean isEnabled() {
        return included;
    }
 
    public ModuleCategory getCategory() {
        return category;
    }
}
Java:
public enum ModuleCategory {
    Combat,
    Movement,
    Player,
    Visuals
}
Так-же нам нужно создать менеджер для наших будущих функций
Java:
public class ModulesManager {
    public static ArrayList<Feature> modules = new ArrayList<>();

    public static void addModules() {
        try {
                // modules.add(new Class());
            new Thread(() -> {
                try {
                    Thread.sleep(5000);
                } catch (Exception ignored) {
                }
            }).start();
        } catch (Exception ignored) {
        }
    }

    public static boolean moduleIncluded(Class<?> featureClass) {
        for (Feature feature : features) {
            if (feature.included && feature.getClass() == featureClass) {
                return true;
            }
        }
        return false;
    }
}
В ините нашего мейн класса вызываем
Java:
ModuleManager.addModules();
Так-же добавляем в наш главный класс обработку нажатий на кнопки биндов

Java:
@SubscribeEvent
public void onKeyInput(InputEvent.KeyInputEvent keyInputEvent) {
    for (Module module : ModuleManager.modules) {
        if (Minecraft.getInstance().screen == null && keyInputEvent.getKey() == module.key && keyInputEvent.getAction() == 1) {
            module.toggle();
        }
    }
}
Уже сейчас мы можем для примера написать какую нибудь простенькую функцию

Java:
public class TestModule extends Module {
    public TestModule() {
        super("test module", ModuleCategory.Movement, "jumping$", GLFW.GLFW_KEY_X);
    }
 
    // логика нашего $elfcod'a
    @Override
    public void onEnable() {
        Minecraft.getInstance().player.jumpFromGround();
        super.onDisable();
    }
}
Не забываем зарегистрировать функцию с помощью ModuleManager'a

Чисто для нашего удобства создадит класс ClientUtil
Java:
public class ClientUtil {
    public static Minecraft mc = Minecraft.getInstance();
    public static MainWindow mw = mc.getWindow();
 
    // добавляем сюда все, что используем часто
}
Пришло время создать максимально простенькое нечто, напоминающее клик гуи

Java:
public class ClickUi extends Screen {
    private final List<Module> modules;
    private ModuleCategory selected;
    private int offset;

    public ClickUi() {
        super(new StringTextComponent("gui"));
        this.modules = ModuleManager.modules;
        this.selected = ModuleCategory.Combat;
        this.offset = 0;
    }

    @Override
    protected void init() {
        int y = this.height / 2 - 75;
        for (ModuleCategory category : ModuleCategory.values()) {
            this.addButton(new Buttons(this.width / 2 - 105, y, 75, 20, category.name(), (btn) -> {
                selected = category;
            }));
            y += 25;
        }
    }

    @Override
    public void render(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {
        this.renderBackground(matrixStack);
        int x = this.width / 2;
        int Ypos = this.height / 2;

        DrawHelper.drawRoundedRect(x - 110, Ypos + 80, 225, 160, 5, new Color(8, 10, 12).brighter());
        DrawHelper.drawRoundedRect(x - 20, Ypos + 75, 130, 150, 5, new Color(8, 10, 12));

        RenderSystem.enableScissor((x - 20) * this.minecraft.getWindow().getWidth() / this.width,
                (Ypos - 74) * this.minecraft.getWindow().getHeight() / this.height,
                130 * this.minecraft.getWindow().getWidth() / this.width,
                150 * this.minecraft.getWindow().getHeight() / this.height);

        int y = Ypos - 70 + offset;
        for (Module module : modules) {
            if (module.getCategory() == selected) {
                StyledFontRenderer.drawString(matrixStack, ClientEntry.big, module.name, x - 15, y + ClientEntry.big.getFontHeight(), module.isEnabled() ? new Color(56, 78, 126) : new Color(255, 255, 255));
                y += 15;
            }
        }

        RenderSystem.disableScissor();

        super.render(matrixStack, mouseX, mouseY, partialTicks);
    }

    @Override
    public boolean mouseClicked(double mouseX, double mouseY, int button) {
        if (button == 0) {
            int x = this.width / 2;
            int Ypos = this.height / 2;
            int y = Ypos - 70 + offset;
            for (Module module : modules) {
                if (module.getCategory() == selected) {
                    if (mouseX >= x - 15 && mouseX <= x + 85 && mouseY >= y && mouseY <= y + 15) {
                        module.toggle();
                        return true;
                    }
                    y += 15;
                }
            }
        }
        return super.mouseClicked(mouseX, mouseY, button);
    }

    @Override
    public boolean mouseScrolled(double mouseX, double mouseY, double value) {
        offset += value * 10;
        offset = Math.max(Math.min(offset, 0), -getMaxScroll());
        return true;
    }

    private int getMaxScroll() {
        int count = 0;
        for (Module module : modules) {
            if (module.getCategory() == selected) {
                count++;
            }
        }
        return Math.max(0, count * 15 - 125);
    }

    private static class Buttons extends Button {
        public Buttons(int x, int y, int width, int height, String text, IPressable onPress) {
            super(x, y, width, height, new StringTextComponent(text), onPress);
        }

        @Override
        public void renderButton(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {
            Color color = this.isHovered() ? new Color(56, 78, 126) : new Color(17, 24, 39);
            DrawHelper.drawRoundedRect(this.x, this.y + this.height, this.width, this.height, 3, color);
            StyledFontRenderer.drawCenteredXString(matrixStack, ClientEntry.big, this.getMessage().getString(), this.x + this.width / 2, this.y + (this.height / 2) + 4, Color.WHITE);
        }
    }
}
На выходе получаем микро вариант cs gui
Посмотреть вложение 289608
Визуально ее изменить думаю осилит каждый (если конечно iq чуть выше 15)

Но мы же блатные, поэтому надо сделать сеттинги

Создаем класс Setting

Java:
public class Setting {
    public String name;
    public boolean isVisible = true;

    public Setting(String name) {this.name = name;}

    public boolean isVisible() {return isVisible;}

    public String getName() {return name;}
}
Далее к нему уже создаем классы FloatSetting, BooleanSetting, ModeSetting
Java:
public class FloatSetting extends Setting {
    private double min, max, inc;
    public double value;
    double defaultvalue;

    public void setInc(double inc) {
        this.inc = inc;
    }

    public double getDefaultvalue() {
        return defaultvalue;
    }

    public void setDefaultvalue(double defaultvalue) {
        this.defaultvalue = defaultvalue;
    }

    public FloatSetting(String name, double min, double max, double defaultvalue, double inc) {
        super(name);
        this.max = max;
        this.min = min;
        this.defaultvalue = defaultvalue;
        this.inc = inc;
        this.value = clamp((float) defaultvalue, (float) min, (float) max);
    }

    public double getValue() {
        return (value != 0) ? value : defaultvalue;
    }

    public double getValueFloat() {
        return (float) value;
    }

    public void setValDouble(double in) {
        this.value = in;
    }

    public void setValue(double value) {
        value = Math.round(value / inc) * inc;
        this.value = clamp(value, min, max);
    }

    public static double clamp(double num, double min, double max) {
        return Math.max(min, Math.min(max, num));
    }

    public void reset() {
        setValue(defaultvalue);
    }

    public double getMin() {
        return min;
    }

    public void setMin(double min) {
        this.min = min;
    }

    public double getMax() {
        return max;
    }

    public void setMax(double max) {
        this.max = max;
    }

    public double getInc() {
        return inc;
    }

    public static float clamp(float num, float min, float max) {
        return num < min ? min : num > max ? max : num;
    }

    public int getValueInt() {
        return (int) value;
    }

    public void inc(boolean isPositive) {
        if (isPositive) setValue(getValue() + getInc());
        else setValue(getValue() - getInc());
    }
}
Java:
public class BooleanSetting extends Setting {
    public boolean value;

    public BooleanSetting(String name, boolean defaultVal) {
        super(name);
        this.value = defaultVal;
    }

    public void toggle() {
        this.value = !this.value;
    }

    public boolean isEnabled() {
        return value;
    }

    public void setEnabled() {
        this.value = value;
    }

    public boolean getValue() {
        return this.value;
    }
}
Java:
public class ModeSetting extends Setting {
    private List<String> modes;
    private int index;
    public String mode;
    public Animation animation;
    public String previousMode;
    private int previousIndex;

    public List<String> getModes() {
        return modes;
    }

    public void setModes(List<String> modes) {
        this.modes = modes;
    }

    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
        this.mode = modes.get(index);
    }

    public String getMode() {
        return mode;
    }


    public ModeSetting(String name, String... modes) {
        super(name);
        this.modes = Arrays.asList(modes);
        this.mode = this.modes.get(0);
        this.index = 0;
        this.animation = new Animation(1, 1, 0.1f);
        this.previousMode = null;
        this.previousIndex = 0;
    }

    public void cycle() {
        this.previousMode = this.mode;
        this.previousIndex = this.index;
        if (index < modes.size() - 1) {
            index++;
        } else {
            index = 0;
        }
        this.mode = modes.get(index);
        this.animation.setAnim(0);
    }

    public void setMode(String mode) {
        if (!this.mode.equals(mode)) {
            this.previousMode = this.mode;
            this.previousIndex = this.index;
            this.mode = mode;
            this.index = modes.indexOf(mode);
            this.animation.setAnim(0);
        }
    }

    public int getPreviousIndex() {
        return previousIndex;
    }

    public boolean isMode(String mode) {
        return Objects.equals(this.mode, mode);
    }

    public String getValue() {
        return this.mode;
    }
}
Сеттинги в гуи добавите сами, мне впадлу слишком <3

Пример использованию наших сеттингов


Java:
public class TestModule() {
 
    BooleanSetting booleanSetting = new BooleanSetting("Bool Setting", true);
 
    public TestModule() {
        super("module", ModuleCategory.Visuals, "test");
        addSettings(booleanSetting);
    }
 
    @SubscribeEvent
    public void onTick(TickEvent event) {
        if (booleanSetting.isEnabled()) {
            /* ... */
        }
    }
}
Так-же для возможности открыть нашу гуи создаем класс

Java:
public class ClickGUI extends Module {

    public ClickGUI() {
        super("gui", ModuleCategory.Visuals, "yougame gui", GLFW.GLFW_KEY_RIGHT_SHIFT);
    }

    @Override
    public void onEnable() {
        mc.setScreen(new ClickUi());
    }
}
И регистрируем его в ModuleManager'e
По итогу мы имеем достаточно простенькую, но какую никакую собственную базу.
Спасибо за уделенное время!

Нужно ли вообще делать тутор на хуки/миксины?
Шо делать
for (Feature feature : Features) {
if (feature.included && feature.getClass() == featureClass) {
return true;
}



Вот тут ошибка в features, included
Шо делать
for (Feature feature : Features) {
if (feature.included && feature.getClass() == featureClass) {
return true;
}



Вот тут ошибка в features, included
ваще капец стал половина софта в ошибках
 
Сверху Снизу