diff --git a/src/main/java/me/x150/sipprivate/SipoverPrivateMain.java b/src/main/java/me/x150/sipprivate/SipoverPrivate.java similarity index 50% rename from src/main/java/me/x150/sipprivate/SipoverPrivateMain.java rename to src/main/java/me/x150/sipprivate/SipoverPrivate.java index 550ee74..698320e 100644 --- a/src/main/java/me/x150/sipprivate/SipoverPrivateMain.java +++ b/src/main/java/me/x150/sipprivate/SipoverPrivate.java @@ -1,26 +1,25 @@ package me.x150.sipprivate; import net.fabricmc.api.ModInitializer; - +import net.minecraft.client.MinecraftClient; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -public class SipoverPrivateMain implements ModInitializer { +public class SipoverPrivate implements ModInitializer { - public static Logger LOGGER = LogManager.getLogger(); - - public static final String MOD_ID = "sipoverprivate"; + public static final String MOD_ID = "sipoverprivate"; public static final String MOD_NAME = "SipoverPrivate"; + public static Logger LOGGER = LogManager.getLogger(); + public static MinecraftClient client = MinecraftClient.getInstance(); - @Override - public void onInitialize() { + public static void log(Level level, String message) { + LOGGER.log(level, "[" + MOD_NAME + "] " + message); + } + + @Override public void onInitialize() { log(Level.INFO, "Initializing"); //TODO: Initializer } - public static void log(Level level, String message){ - LOGGER.log(level, "["+MOD_NAME+"] " + message); - } - } \ No newline at end of file diff --git a/src/main/java/me/x150/sipprivate/command/Command.java b/src/main/java/me/x150/sipprivate/command/Command.java new file mode 100644 index 0000000..eb13a5e --- /dev/null +++ b/src/main/java/me/x150/sipprivate/command/Command.java @@ -0,0 +1,59 @@ +package me.x150.sipprivate.command; + +import net.minecraft.client.MinecraftClient; + +/** + * A class representing a command + */ +public abstract class Command { + + /** + * The minecraft instance + */ + public final MinecraftClient mc; + /** + * The main command name + */ + private final String command; + /** + * The command's aliases + */ + private final String[] alias; + + /** + * Constructs a new command instance + * + * @param command The name of the command + * @param aliases Triggers for the command + */ + public Command(String command, String... aliases) { + this.command = command; + this.alias = aliases; + this.mc = MinecraftClient.getInstance(); + } + + /** + * Gets the command's name + * + * @return The command name + */ + public String getCommand() { + return command; + } + + /** + * Gets the command's aliases + * + * @return The command's aliases + */ + public String[] getAliases() { + return alias; + } + + /** + * Called when the command is executed + * + * @param args The arguments (excluding prefix and command name) specified + */ + public abstract void runCommand(String[] args); +} diff --git a/src/main/java/me/x150/sipprivate/command/CommandManager.java b/src/main/java/me/x150/sipprivate/command/CommandManager.java new file mode 100644 index 0000000..667c069 --- /dev/null +++ b/src/main/java/me/x150/sipprivate/command/CommandManager.java @@ -0,0 +1,49 @@ +package me.x150.sipprivate.command; + +import me.x150.sipprivate.command.commands.BindCommand; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class CommandManager { + + /** + * A list of all registered commands + */ + private final List<Command> commands = new ArrayList<>(); + + /** + * Constructs a new command manager + */ + public CommandManager() { + addCommands(); + } + + /** + * Registers the commands + */ + public void addCommands() { + addCommand(new BindCommand()); + } + + /** + * Adds a command to the list of registered commands, registering it + * + * @param command The command instance + */ + private void addCommand(Command command) { + commands.add(command); + } + + /** + * Gets all registered commands + * + * @return The list of registered commands + */ + @NotNull public List<Command> getCommands() { + return Collections.unmodifiableList(commands); + } + +} diff --git a/src/main/java/me/x150/sipprivate/command/commands/BindCommand.java b/src/main/java/me/x150/sipprivate/command/commands/BindCommand.java new file mode 100644 index 0000000..bc96df9 --- /dev/null +++ b/src/main/java/me/x150/sipprivate/command/commands/BindCommand.java @@ -0,0 +1,38 @@ +package me.x150.sipprivate.command.commands; + +import me.x150.sipprivate.command.Command; +import me.x150.sipprivate.keybinding.KeybindingManager; +import me.x150.sipprivate.module.Module; +import me.x150.sipprivate.module.ModuleManager; +import me.x150.sipprivate.util.ChatUtil; + +public class BindCommand extends Command { + + public BindCommand() { + super("BindCommand", "bind"); + } + + @Override public void runCommand(String[] args) { + if (args.length < 2) { + ChatUtil.send("I need the module and key to bind"); + return; + } + String mod = args[0]; + String key = args[1]; + if (key.length() != 1) { + ChatUtil.send("One character as key allowed only"); + return; + } + + int kc = key.toUpperCase().charAt(0); + Module m = ModuleManager.instance().getModuleByName(mod); + if (m == null) { + ChatUtil.send("Cant find that module"); + return; + } + ChatUtil.send("BIND " + m.getName() + " -> " + kc + " (" + ((char) kc) + ")"); + //m.config.get("Keybind").setValue(kc); + m.keybind.setValue(kc); + KeybindingManager.reload(); + } +} diff --git a/src/main/java/me/x150/sipprivate/config/BooleanSetting.java b/src/main/java/me/x150/sipprivate/config/BooleanSetting.java new file mode 100644 index 0000000..02a2481 --- /dev/null +++ b/src/main/java/me/x150/sipprivate/config/BooleanSetting.java @@ -0,0 +1,26 @@ +package me.x150.sipprivate.config; + +/** + * A setting describing a boolean + */ +public class BooleanSetting extends SettingBase<Boolean> { + + public BooleanSetting(Boolean defaultValue, String name, String description) { + super(defaultValue, name, description); + } + + @Override public Boolean parse(String value) { + return (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("1")); + } + + public static class Builder extends SettingBase.Builder<Builder, Boolean, BooleanSetting> { + + public Builder(Boolean defaultValue) { + super(defaultValue); + } + + @Override public BooleanSetting get() { + return new BooleanSetting(defaultValue, name, description); + } + } +} diff --git a/src/main/java/me/x150/sipprivate/config/DoubleSetting.java b/src/main/java/me/x150/sipprivate/config/DoubleSetting.java new file mode 100644 index 0000000..bc465f8 --- /dev/null +++ b/src/main/java/me/x150/sipprivate/config/DoubleSetting.java @@ -0,0 +1,56 @@ +package me.x150.sipprivate.config; + +public class DoubleSetting extends SettingBase<Double> { + int prec; + double min, max; + + public DoubleSetting(Double defaultValue, String name, String description, int precision, double min, double max) { + super(defaultValue, name, description); + this.prec = precision; + this.min = min; + this.max = max; + } + + @Override public Double parse(String value) { + try { + return Double.parseDouble(value); + } catch (Exception ignored) { + return defaultValue; + } + } + + @Override public void setValue(Double value) { + if (value > max || value < min) { + return; + } + super.setValue(value); + } + + public static class Builder extends SettingBase.Builder<Builder, Double, DoubleSetting> { + double min = Double.NEGATIVE_INFINITY, max = Double.POSITIVE_INFINITY; + int prec = 2; + + public Builder(double defaultValue) { + super(defaultValue); + } + + public Builder precision(int prec) { + this.prec = prec; + return this; + } + + public Builder min(double min) { + this.min = min; + return this; + } + + public Builder max(double max) { + this.max = max; + return this; + } + + @Override public DoubleSetting get() { + return new DoubleSetting(defaultValue, name, description, prec, min, max); + } + } +} diff --git a/src/main/java/me/x150/sipprivate/config/EnumSetting.java b/src/main/java/me/x150/sipprivate/config/EnumSetting.java new file mode 100644 index 0000000..10c3723 --- /dev/null +++ b/src/main/java/me/x150/sipprivate/config/EnumSetting.java @@ -0,0 +1,46 @@ +package me.x150.sipprivate.config; + +import java.util.Arrays; + +public class EnumSetting<T extends Enum<?>> extends SettingBase<T> { + private T[] values; + + @SuppressWarnings("unchecked") public EnumSetting(T defaultValue, String name, String description) { + super(defaultValue, name, description); + try { + this.values = (T[]) defaultValue.getClass().getMethod("values").invoke(null); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override public T parse(String value) { + for (T t : values) { + if (value.equalsIgnoreCase(t.toString())) { + return t; + } + } + return defaultValue; + } + + public T[] getValues() { + return values; + } + + @Override public void setValue(T value) { + if (Arrays.stream(values).noneMatch(t -> t.equals(value))) { + return; + } + super.setValue(value); + } + + public static class Builder<T extends Enum<?>> extends SettingBase.Builder<Builder<T>, T, EnumSetting<T>> { + public Builder(T defaultValue) { + super(defaultValue); + } + + @Override public EnumSetting<T> get() { + return new EnumSetting<>(defaultValue, name, description); + } + } +} diff --git a/src/main/java/me/x150/sipprivate/config/IntSetting.java b/src/main/java/me/x150/sipprivate/config/IntSetting.java new file mode 100644 index 0000000..d178f62 --- /dev/null +++ b/src/main/java/me/x150/sipprivate/config/IntSetting.java @@ -0,0 +1,41 @@ +package me.x150.sipprivate.config; + +public class IntSetting extends SettingBase<Integer> { + int min, max; + + public IntSetting(Integer defaultValue, String name, String description, int min, int max) { + super(defaultValue, name, description); + this.min = min; + this.max = max; + } + + @Override public Integer parse(String value) { + try { + return Integer.parseInt(value); + } catch (Exception ignored) { + return defaultValue; + } + } + + public static class Builder extends SettingBase.Builder<Builder, Integer, IntSetting> { + int min = Integer.MIN_VALUE, max = Integer.MAX_VALUE; + + public Builder(Integer defaultValue) { + super(defaultValue); + } + + public Builder min(int min) { + this.min = min; + return this; + } + + public Builder max(int max) { + this.max = max; + return this; + } + + @Override public IntSetting get() { + return new IntSetting(defaultValue, name, description, min, max); + } + } +} diff --git a/src/main/java/me/x150/sipprivate/config/ModuleConfig.java b/src/main/java/me/x150/sipprivate/config/ModuleConfig.java new file mode 100644 index 0000000..ccf8a7e --- /dev/null +++ b/src/main/java/me/x150/sipprivate/config/ModuleConfig.java @@ -0,0 +1,36 @@ +package me.x150.sipprivate.config; + +import java.util.ArrayList; +import java.util.List; + +public class ModuleConfig { + List<SettingBase<?>> settings = new ArrayList<>(); + List<SettingsGroup> groups = new ArrayList<>(); + + public <S extends SettingBase<?>> S create(S in) { // used as a proxy to make a one liner + settings.add(in); + return in; + } + + public SettingsGroup create(SettingsGroup in) { + groups.add(in); + return in; + } + + public SettingBase<?> get(String name) { + for (SettingBase<?> setting : getSettings()) { + if (setting.getName().equals(name)) { + return setting; + } + } + return null; + } + + public List<SettingBase<?>> getSettings() { + return settings; + } + + public List<SettingsGroup> getGroups() { + return groups; + } +} diff --git a/src/main/java/me/x150/sipprivate/config/SettingBase.java b/src/main/java/me/x150/sipprivate/config/SettingBase.java new file mode 100644 index 0000000..e026d47 --- /dev/null +++ b/src/main/java/me/x150/sipprivate/config/SettingBase.java @@ -0,0 +1,184 @@ +package me.x150.sipprivate.config; + +import java.util.function.Consumer; + +/** + * A class depicting a setting + * + * @param <V> The type of which value should be stored here + */ +public abstract class SettingBase<V> { + /** + * The name and description of this setting + */ + public final String name, description; + /** + * The default value of this setting + */ + V defaultValue; + /** + * The current value of this setting + */ + V value; + + /** + * Constructs a new Setting + * + * @param defaultValue The default value + * @param name The name + * @param description The description + */ + public SettingBase(V defaultValue, String name, String description) { + this.name = name; + this.description = description; + this.defaultValue = this.value = defaultValue; + } + + /** + * Parses a string to its value, not implemented in the base class + * + * @param value The value we want to parse + * @return The parsed output + */ + public abstract V parse(String value); + + /** + * Parses and sets a value, implemented because intellij idea is slightly retarded + * + * @param value The value we want to parse + */ + public void accept(String value) { + this.setValue(this.parse(value)); + } + + /** + * Gets the current value of this setting + * + * @return The value of this setting + */ + public V getValue() { + return value; + } + + /** + * Sets the value of this setting + * + * @param value The new value + */ + public void setValue(V value) { + this.value = value; + } + + /** + * Gets the description of this setting + * + * @return The description + */ + public String getDescription() { + return description; + } + + /** + * Gets the name of this setting + * + * @return The name + */ + public String getName() { + return name; + } + + /** + * Gets the default value of this setting + * + * @return The default value + */ + public V getDefaultValue() { + return defaultValue; + } + + /** + * Builds a new Setting + * + * @param <B> The builder class + * @param <V> The type of value we want to parse + * @param <S> The setting class + */ + @SuppressWarnings("unchecked") public abstract static class Builder<B extends Builder<?, ?, ?>, V, S extends SettingBase<?>> { + /** + * Name and description + */ + String name = "none", description = ""; + /** + * The default value + */ + V defaultValue; + /** + * Event listener when the value changed + */ + Consumer<V> changed; + + /** + * Constructs a new builder + * + * @param defaultValue The default value + */ + protected Builder(V defaultValue) { + this.defaultValue = defaultValue; + } + + /** + * Sets the name of this setting + * + * @param name The name + * @return The current builder + */ + public B name(String name) { + this.name = name; + return getThis(); + } + + /** + * Sets the description of this setting + * + * @param description The description + * @return The current builder + */ + public B description(String description) { + this.description = description; + return getThis(); + } + + /** + * Sets the default value of this setting + * + * @param defaultValue The default value + * @return The current builder + */ + public B defaultValue(V defaultValue) { + this.defaultValue = defaultValue; + return getThis(); + } + + /** + * Sets the changed listener of this setting + * + * @param changed The listener + * @return The current builder + */ + public B onChanged(Consumer<V> changed) { + this.changed = changed; + return getThis(); + } + + /** + * Constructs the setting, not implemented in base class + * + * @return The setting + */ + public abstract S get(); + + protected B getThis() { + return (B) this; + } + } +} diff --git a/src/main/java/me/x150/sipprivate/config/SettingsGroup.java b/src/main/java/me/x150/sipprivate/config/SettingsGroup.java new file mode 100644 index 0000000..4a91838 --- /dev/null +++ b/src/main/java/me/x150/sipprivate/config/SettingsGroup.java @@ -0,0 +1,46 @@ +package me.x150.sipprivate.config; + +import java.util.ArrayList; +import java.util.List; + +/** + * A group of settings + */ +public class SettingsGroup { + String name, description; + List<SettingBase<?>> settings; + + SettingsGroup(String name, String description, List<SettingBase<?>> settings) { + this.name = name; + this.description = description; + this.settings = settings; + } + + public List<SettingBase<?>> getSettings() { + return settings; + } + + public static class Builder { + String name = "none", description = ""; + List<SettingBase<?>> s = new ArrayList<>(); + + public Builder name(String name) { + this.name = name; + return this; + } + + public Builder description(String desc) { + this.description = desc; + return this; + } + + public Builder settings(SettingBase<?>... settings) { + s.addAll(List.of(settings)); + return this; + } + + public SettingsGroup get() { + return new SettingsGroup(name, description, s); + } + } +} diff --git a/src/main/java/me/x150/sipprivate/config/StringSetting.java b/src/main/java/me/x150/sipprivate/config/StringSetting.java new file mode 100644 index 0000000..82d764a --- /dev/null +++ b/src/main/java/me/x150/sipprivate/config/StringSetting.java @@ -0,0 +1,23 @@ +package me.x150.sipprivate.config; + +public class StringSetting extends SettingBase<String> { + + public StringSetting(String defaultValue, String name, String description) { + super(defaultValue, name, description); + } + + @Override public String parse(String value) { + return value; + } + + public static class Builder extends SettingBase.Builder<Builder, String, StringSetting> { + + public Builder(String defaultValue) { + super(defaultValue); + } + + @Override public StringSetting get() { + return new StringSetting(defaultValue, name, description); + } + } +} diff --git a/src/main/java/me/x150/sipprivate/keybinding/Keybind.java b/src/main/java/me/x150/sipprivate/keybinding/Keybind.java new file mode 100644 index 0000000..a8531bc --- /dev/null +++ b/src/main/java/me/x150/sipprivate/keybinding/Keybind.java @@ -0,0 +1,7 @@ +package me.x150.sipprivate.keybinding; + +/** + * A container class for keybinds + */ +public record Keybind(int keycode) { +} diff --git a/src/main/java/me/x150/sipprivate/keybinding/KeybindingManager.java b/src/main/java/me/x150/sipprivate/keybinding/KeybindingManager.java new file mode 100644 index 0000000..62677b4 --- /dev/null +++ b/src/main/java/me/x150/sipprivate/keybinding/KeybindingManager.java @@ -0,0 +1,56 @@ +package me.x150.sipprivate.keybinding; + +import me.x150.sipprivate.module.Module; +import me.x150.sipprivate.module.ModuleManager; + +import java.util.HashMap; +import java.util.Map; + +/** + * The keybind manager + */ +public class KeybindingManager { + + /** + * List of all the modules with their respective keybinds + */ + public static final Map<Module, Keybind> keybindMap = new HashMap<>(); + + /** + * Init the keybinding manager + */ + public static void init() { + for (Module module : ModuleManager.instance().getModules()) { + keybindMap.put(module, new Keybind(module.keybind.getValue())); + } + } + + /** + * Update a single keybind via keyboard event + * + * @param kc The key which was changed + * @param action The action performed (0 = release, 1 = pressed, 2 = repeat pressed when holding) + */ + public static void updateSingle(int kc, int action) { + if (kc == -1) { + return; // JESSE WE FUCKED UP + } + if (action == 1) { // key pressed + for (Module o : keybindMap.keySet().toArray(new Module[0])) { + Keybind kb = keybindMap.get(o); + if (kb.keycode() == kc) { + o.toggle(); + } + } + } + } + + /** + * Reloads the keybind manager + */ + public static void reload() { + keybindMap.clear(); + init(); + } + +} diff --git a/src/main/java/me/x150/sipprivate/module/Category.java b/src/main/java/me/x150/sipprivate/module/Category.java new file mode 100644 index 0000000..ec5eb7b --- /dev/null +++ b/src/main/java/me/x150/sipprivate/module/Category.java @@ -0,0 +1,18 @@ +package me.x150.sipprivate.module; + +/** + * Enum containing each category of module + */ +public enum Category { + + COMBAT("Combat"), MOVEMENT("Movement"), RENDER("Render"), EXPLOIT("Exploit"), PLAYER("Player"), MISC("Miscellaneous"); + String name; + + Category(String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/src/main/java/me/x150/sipprivate/module/Module.java b/src/main/java/me/x150/sipprivate/module/Module.java new file mode 100644 index 0000000..2818ee7 --- /dev/null +++ b/src/main/java/me/x150/sipprivate/module/Module.java @@ -0,0 +1,123 @@ +package me.x150.sipprivate.module; + +import me.x150.sipprivate.config.IntSetting; +import me.x150.sipprivate.config.ModuleConfig; +import net.minecraft.client.MinecraftClient; + +/** + * A container describing a module + */ +public abstract class Module { + + /** + * The minecraft instance + */ + protected static final MinecraftClient mc = MinecraftClient.getInstance(); + /** + * The configuration of this module + */ + public final ModuleConfig config; + /** + * The name of this module + */ + private final String name; + /** + * The description of this module + */ + private final String description; + /** + * The category this module belongs in + */ + private final Category category; + /** + * The keybind of this module + */ + public IntSetting keybind; + /** + * Whether this module is currently enabled + */ + private boolean enabled; + + /** + * Constructs a new module + * + * @param name The name of the module + * @param description The description of this module + * @param category Which category this module belongs in + */ + public Module(String name, String description, Category category) { + this.name = name; + this.description = description; + this.category = category; + this.config = new ModuleConfig(); + keybind = config.create(new IntSetting.Builder(-1).min(-1).name("Keybind").description("The keybind to toggle the module with").get()); + // this.config.create("Keybind", -1).description("The keybind to toggle the module with"); + } + + /** + * Gets the name of this module + * + * @return This module's name + */ + public String getName() { + return name; + } + + /** + * Gets the description of this module + * + * @return This module's description + */ + public String getDescription() { + return description; + } + + /** + * Gets the category of this module + * + * @return This module's category + */ + public Category getCategory() { + return category; + } + + /** + * Whether this module is enabled or not + * + * @return true if the module is enabled, false if otherwise + */ + public boolean isEnabled() { + return enabled; + } + + /** + * Sets this module's enabled state + * + * @param enabled The new enabled state + */ + public void setEnabled(boolean enabled) { + this.enabled = enabled; + if (this.enabled) { + onEnable(); + } else { + onDisable(); + } + } + + /** + * Turns this module on if it's off, off when otherwise + */ + public void toggle() { + setEnabled(!isEnabled()); + } + + /** + * Gets called when the module switches from disabled to enabled, not implemented in base class + */ + protected abstract void onEnable(); + + /** + * Gets called when the module switches from enabled to disabled, not implemented in base class + */ + protected abstract void onDisable(); +} diff --git a/src/main/java/me/x150/sipprivate/module/ModuleManager.java b/src/main/java/me/x150/sipprivate/module/ModuleManager.java new file mode 100644 index 0000000..90ff340 --- /dev/null +++ b/src/main/java/me/x150/sipprivate/module/ModuleManager.java @@ -0,0 +1,69 @@ +package me.x150.sipprivate.module; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * The module manager + */ +public class ModuleManager { + + private static final ModuleManager instance = new ModuleManager(); + /** + * A list of all registered modules + */ + private final List<Module> modules = new ArrayList<>(); + + private ModuleManager() { + addModules(); + } + + public static ModuleManager instance() { + return instance; + } + + /** + * Adds all modules we want to register + */ + public void addModules() { + + } + + /** + * Registers a module + * + * @param module The module to register + */ + private void addModule(Module module) { + modules.add(module); + } + + /** + * Returns all modules + * + * @return The modules + */ + @NotNull public List<Module> getModules() { + return Collections.unmodifiableList(modules); + } + + /** + * Returns the first module which has the name we specified, null if no module matches + * + * @param name The name we want to find + * @return The module found, null otherwise + */ + @Nullable public Module getModuleByName(String name) { + for (Module m : modules) { + if (m.getName().equalsIgnoreCase(name)) { + return m; + } + } + + return null; + } +} diff --git a/src/main/java/me/x150/sipprivate/util/ChatUtil.java b/src/main/java/me/x150/sipprivate/util/ChatUtil.java new file mode 100644 index 0000000..3e6cdcd --- /dev/null +++ b/src/main/java/me/x150/sipprivate/util/ChatUtil.java @@ -0,0 +1,16 @@ +package me.x150.sipprivate.util; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.network.MessageType; +import net.minecraft.text.Text; + +public class ChatUtil { + /** + * Sends a message to the user, client side + * + * @param s The message to send. Formatting using ยง is allowed + */ + public static void send(final String s) { + MinecraftClient.getInstance().inGameHud.addChatMessage(MessageType.SYSTEM, Text.of(s), MinecraftClient.getInstance().player.getUuid()); + } +} diff --git a/src/main/java/me/x150/sipprivate/util/ConfigManager.java b/src/main/java/me/x150/sipprivate/util/ConfigManager.java new file mode 100644 index 0000000..73832e5 --- /dev/null +++ b/src/main/java/me/x150/sipprivate/util/ConfigManager.java @@ -0,0 +1,222 @@ +package me.x150.sipprivate.util; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import me.x150.sipprivate.SipoverPrivate; +import me.x150.sipprivate.config.SettingBase; +import me.x150.sipprivate.keybinding.KeybindingManager; +import me.x150.sipprivate.module.Module; +import me.x150.sipprivate.module.ModuleManager; +import org.apache.commons.io.FileUtils; + +import javax.crypto.Cipher; +import javax.crypto.spec.SecretKeySpec; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.zip.DeflaterOutputStream; +import java.util.zip.InflaterOutputStream; + +public class ConfigManager { + + static final List<Module> toBeEnabled = new ArrayList<>(); + static final File CONFIG_FILE; + public static boolean loaded = false; + public static boolean enabled = false; + + static { + CONFIG_FILE = new File(SipoverPrivate.client.runDirectory, "config.sip"); + } + + /** + * Encrypts a byte array with a key + * + * @param in The byte array to encrypt + * @param key The key to use + * @return The encrypted byte array + * @throws Exception If something goes wrong + */ + static byte[] encrypt(byte[] in, String key) throws Exception { + byte[] k = key.getBytes(StandardCharsets.UTF_8); + MessageDigest msgd = MessageDigest.getInstance("SHA-1"); + k = msgd.digest(k); + k = Arrays.copyOf(k, 16); + SecretKeySpec sks = new SecretKeySpec(k, "AES"); + Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); + cipher.init(Cipher.ENCRYPT_MODE, sks); + // return Base64.getEncoder().encodeToString(cipher.doFinal(in.getBytes(StandardCharsets.UTF_8))); + return cipher.doFinal(in); + } + + /** + * Compresses a byte array using GZIP Deflate + * + * @param in The input + * @return The compressed output + * @throws Exception If something goes wrong + */ + public static byte[] compress(byte[] in) throws Exception { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + try (DeflaterOutputStream dos = new DeflaterOutputStream(os)) { + dos.write(in); + } + return os.toByteArray(); + } + + /** + * Decompressed a byte array using GZIP Inflate + * + * @param in The compressed data + * @return The decompressed date + * @throws Exception If something goes wrong + */ + public static byte[] decompress(byte[] in) throws Exception { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + try (InflaterOutputStream ios = new InflaterOutputStream(os)) { + ios.write(in); + } + + return os.toByteArray(); + } + + /** + * Decrypts a byte array with a key + * + * @param in The byte array to decrypt + * @param key The key used to encrypt the byte array + * @return The decrypted byte array + * @throws Exception If something goes wrong + */ + static byte[] decrypt(byte[] in, String key) throws Exception { + byte[] k = key.getBytes(StandardCharsets.UTF_8); + MessageDigest msgd = MessageDigest.getInstance("SHA-1"); + k = msgd.digest(k); + k = Arrays.copyOf(k, 16); + SecretKeySpec sks = new SecretKeySpec(k, "AES"); + Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); + cipher.init(Cipher.DECRYPT_MODE, sks); + return cipher.doFinal(in); + } + + /** + * Saves the current state of the client to the file + */ + public static void saveState() { + if (!loaded || !enabled) { + System.out.println("Not saving config because we didnt load it yet"); + return; + } + System.out.println("Saving state"); + JsonObject base = new JsonObject(); + JsonArray enabled = new JsonArray(); + JsonArray config = new JsonArray(); + for (Module module : ModuleManager.instance().getModules()) { + if (module.isEnabled()) { + enabled.add(module.getName()); + } + JsonObject currentConfig = new JsonObject(); + currentConfig.addProperty("name", module.getName()); + JsonArray pairs = new JsonArray(); + for (SettingBase<?> dynamicValue : module.config.getSettings()) { + JsonObject jesus = new JsonObject(); + jesus.addProperty("key", dynamicValue.getName()); + jesus.addProperty("value", dynamicValue.getValue() + ""); + pairs.add(jesus); + } + currentConfig.add("pairs", pairs); + config.add(currentConfig); + } + base.add("enabled", enabled); + base.add("config", config); + try { + FileUtils.writeByteArrayToFile(CONFIG_FILE, encrypt(compress(base.toString().getBytes(StandardCharsets.UTF_8)), "amogus")); + // FileUtils.write(CONFIG_FILE, encrypt(base.toString(), "amogus"), StandardCharsets.UTF_8); + } catch (Exception e) { + e.printStackTrace(); + System.out.println("Failed to save config!"); + } + } + + /** + * Loads the state we saved earlier from the file + */ + public static void loadState() { + if (loaded) { + return; + } + loaded = true; + try { + if (!CONFIG_FILE.isFile()) { + //noinspection ResultOfMethodCallIgnored + CONFIG_FILE.delete(); + } + if (!CONFIG_FILE.exists()) { + return; + } + byte[] retrv = FileUtils.readFileToByteArray(CONFIG_FILE); + // String retrv = FileUtils.readFileToString(CONFIG_FILE, StandardCharsets.UTF_8); + String decr = new String(decompress(decrypt(retrv, "amogus"))); + JsonObject config = new JsonParser().parse(decr).getAsJsonObject(); + if (config.has("config") && config.get("config").isJsonArray()) { + JsonArray configArray = config.get("config").getAsJsonArray(); + for (JsonElement jsonElement : configArray) { + if (jsonElement.isJsonObject()) { + JsonObject jobj = jsonElement.getAsJsonObject(); + String name = jobj.get("name").getAsString(); + Module j = ModuleManager.instance().getModuleByName(name); + if (j == null) { + continue; + } + if (jobj.has("pairs") && jobj.get("pairs").isJsonArray()) { + JsonArray pairs = jobj.get("pairs").getAsJsonArray(); + for (JsonElement pair : pairs) { + JsonObject jo = pair.getAsJsonObject(); + String key = jo.get("key").getAsString(); + String value = jo.get("value").getAsString(); + SettingBase<?> val = j.config.get(key); + if (val != null) { + val.accept(value); + } + } + } + } + } + } + + if (config.has("enabled") && config.get("enabled").isJsonArray()) { + for (JsonElement enabled : config.get("enabled").getAsJsonArray()) { + String name = enabled.getAsString(); + Module m = ModuleManager.instance().getModuleByName(name); + if (m != null) { + toBeEnabled.add(m); + } + } + } + + } catch (Exception e) { + e.printStackTrace(); + } finally { + KeybindingManager.reload(); + } + } + + /** + * Enables all modules to be enabled, when we are in game + */ + public static void enableModules() { + if (enabled) { + return; + } + enabled = true; + for (Module module : toBeEnabled) { + module.setEnabled(true); + } + } + +} diff --git a/src/main/java/me/x150/sipprivate/util/Utils.java b/src/main/java/me/x150/sipprivate/util/Utils.java new file mode 100644 index 0000000..fe4c79f --- /dev/null +++ b/src/main/java/me/x150/sipprivate/util/Utils.java @@ -0,0 +1,16 @@ +package me.x150.sipprivate.util; + +import java.awt.Color; + +public class Utils { + + /** + * Returns an RGB color based on time + * + * @return The color + */ + public static Color getCurrentRGB() { + return new Color(Color.HSBtoRGB((System.currentTimeMillis() % 4750) / 4750f, 0.5f, 1)); + } + +} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index bf909d8..213f219 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -3,7 +3,7 @@ "id": "sipoverprivate", "version": "${version}", "name": "SipoverPrivate", - "description": "YOOOOO $2500 WE GETTIN RICH BOYYS", + "description": "YOOOOO 2500 KROMER WE GETTIN RICH BOYYS", "authors": [ "0x150", "Kopamed" @@ -15,7 +15,7 @@ "environment": "*", "entrypoints": { "main": [ - "me.x150.sipprivate.SipoverPrivateMain" + "me.x150.sipprivate.SipoverPrivate" ], "client": [], "server": []