commit 183c81258a522d6e9206b2fdd19b45e5ce911b36 Author: Jane Petrovna Date: Sat Dec 19 18:30:50 2020 -0500 just a copy of petroleum right now diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ed36e39 --- /dev/null +++ b/.gitignore @@ -0,0 +1,30 @@ +# gradle + +.gradle/ +build/ +out/ +classes/ + +# eclipse + +*.launch + +# idea + +.idea/ +*.iml +*.ipr +*.iws + +# vscode + +.settings/ +.vscode/ +bin/ +.classpath +.project + +# fabric + +run/ +logs/ \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..d4df2a8 --- /dev/null +++ b/README.md @@ -0,0 +1,10 @@ +# Petroleum +### A Minecraft "mod" + + +#### Features + +- none, yet. + +# +[by janeptrv](https://j4.pm) diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..30d30f5 --- /dev/null +++ b/build.gradle @@ -0,0 +1,80 @@ +plugins { + id 'java' + id 'idea' + id 'fabric-loom' version '0.5.9' + id 'maven-publish' +} + +sourceCompatibility = JavaVersion.VERSION_1_8 +targetCompatibility = JavaVersion.VERSION_1_8 + +archivesBaseName = project.archives_base_name +version = project.mod_version +group = project.maven_group + +dependencies { + //to change the versions see the gradle.properties file + minecraft "com.mojang:minecraft:${project.minecraft_version}" + mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" + modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" + + // Fabric API. This is technically optional, but you probably want it anyway. + modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" + + // PSA: Some older mods, compiled on Loom 0.2.1, might have outdated Maven POMs. + // You may need to force-disable transitiveness on them. + compileOnly "com.google.code.findbugs:jsr305:3.0.2" +} + +processResources { + inputs.property "version", project.version + + from(sourceSets.main.resources.srcDirs) { + include "fabric.mod.json" + expand "version": project.version + } + + from(sourceSets.main.resources.srcDirs) { + exclude "fabric.mod.json" + } +} + +// ensure that the encoding is set to UTF-8, no matter what the system default is +// this fixes some edge cases with special characters not displaying correctly +// see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html +tasks.withType(JavaCompile) { + options.encoding = "UTF-8" +} + +// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task +// if it is present. +// If you remove this task, sources will not be generated. +task sourcesJar(type: Jar, dependsOn: classes) { + classifier = "sources" + from sourceSets.main.allSource +} + +jar { + from "LICENSE" +} + +// configure the maven publication +publishing { + publications { + mavenJava(MavenPublication) { + // add all the jars that should be included when publishing to maven + artifact(remapJar) { + builtBy remapJar + } + artifact(sourcesJar) { + builtBy remapSourcesJar + } + } + } + + // select the repositories you want to publish to + repositories { + // uncomment to publish to the local maven + // mavenLocal() + } +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..922b5e9 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,17 @@ +# Done to increase the memory available to gradle. +org.gradle.jvmargs=-Xmx1G + +# Fabric Properties + # check these on https://fabricmc.net/use + minecraft_version=1.16.4 + yarn_mappings=1.16.4+build.7 + loader_version=0.10.8 + +# Mod Properties + mod_version = 0.1.4 + maven_group = pm.j4 + archives_base_name = petroleum + +# Dependencies + # currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api + fabric_version=0.28.1+1.16 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..490fda8 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..622ab64 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..2fe81a7 --- /dev/null +++ b/gradlew @@ -0,0 +1,183 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..62bd9b9 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,103 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/remappedSrc/pm/j4/petroleum/PetroleumMod.java b/remappedSrc/pm/j4/petroleum/PetroleumMod.java new file mode 100644 index 0000000..ce543eb --- /dev/null +++ b/remappedSrc/pm/j4/petroleum/PetroleumMod.java @@ -0,0 +1,168 @@ +package pm.j4.petroleum; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.fabricmc.loader.api.FabricLoader; +import net.fabricmc.loader.api.ModContainer; +import net.fabricmc.loader.api.metadata.ModMetadata; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.options.KeyBinding; +import net.minecraft.server.integrated.IntegratedServer; +import pm.j4.petroleum.modules.ExampleModule; +import pm.j4.petroleum.modules.bindings.BindingManager; +import pm.j4.petroleum.modules.list.ModList; +import pm.j4.petroleum.modules.menu.ModMenu; +import pm.j4.petroleum.modules.splash.SplashText; +import pm.j4.petroleum.modules.xray.Xray; +import pm.j4.petroleum.util.config.ConfigHolder; +import pm.j4.petroleum.util.config.ConfigManager; +import pm.j4.petroleum.util.module.ModuleBase; + + +//TODO: +// petroleum module checklist +// [ ] xray (lol) +// [ ] combat stuff. killaura, anti knockback, etc +// [ ] render stuff. tracers, nametags +// [ ] wurst taco. but a fish +// [ ] elytra fly +// [ ] movement stuff. nofall, jesus, speed +// [ ] elytra bhop +// [ ] boatfly +// [ ] anti anti cheat + +/** + * The type Petroleum mod. + */ +public class PetroleumMod implements ModInitializer { + /** + * The Mod data. + */ + public static ModMetadata modData = null; + /** + * The constant client. + */ + private static MinecraftClient client; + /** + * The constant activeMods. + */ + private static final List activeMods = Arrays.asList( + new SplashText(), + new ModMenu(), + new ModList(), + new BindingManager(), + new ExampleModule(), + new Xray() + ); + + /** + * Is active boolean. + * + * @param modName the mod name + * @return the boolean + */ + public static boolean isActive(String modName) { + return activeMods.stream().anyMatch(mod -> mod.getModuleName().equals(modName)); + } + + /** + * Gets mod. + * + * @param modName the mod name + * @return the mod + */ + public static Optional getMod(String modName) { + return activeMods.stream().filter(mod -> mod.getModuleName().equals(modName)).findFirst(); + } + + /** + * Gets active mods. + * + * @return the active mods + */ + public static List getActiveMods() { + return activeMods; + } + + /** + * The constant registeredBinds. + */ + private static final List registeredBinds = new ArrayList<>(); + + /** + * Add bind. + * + * @param b the b + */ + public static void addBind(KeyBinding b) { + registeredBinds.add(b); + } + + /** + * Remove bind. + * + * @param b the b + */ + public static void removeBind(KeyBinding b) { + registeredBinds.remove(b); + } + + /** + * Gets active keybinds. + * + * @return the active keybinds + */ + public static List getActiveKeybinds() { + return registeredBinds; + } + + /** + * Gets server address. + * + * @return the server address + */ + public static String getServerAddress() { + if (client != null && client.getServer() != null) { + IntegratedServer server = client.getServer(); + if (!server.isRemote()) { + return "localhost"; + } + if (server.isRemote() && !server.getServerIp().isEmpty()) { + return server.getServerIp(); + } + } + return null; + } + + @Override + public void onInitialize() { + + ConfigManager.initConfig(); + + // always update mod data + Optional modContainer = FabricLoader.getInstance().getModContainer("petroleum"); + modContainer.ifPresent(container -> modData = container.getMetadata()); + + Optional conf = ConfigManager.getConfig(); + + + //initialize any keybinds, data, etc. + activeMods.forEach(ModuleBase::init); + + //initialize keybind handler + conf.ifPresent(configHolder -> ClientTickEvents.END_CLIENT_TICK.register(client -> { + if (PetroleumMod.client != client) { + PetroleumMod.client = client; + } + for (KeyBinding b : PetroleumMod.getActiveKeybinds()) { + while (b.wasPressed()) { + configHolder.globalConfig.bindings.get(b).activate(client); + } + } + })); + } +} diff --git a/remappedSrc/pm/j4/petroleum/gui/PModMenuScreen.java b/remappedSrc/pm/j4/petroleum/gui/PModMenuScreen.java new file mode 100644 index 0000000..fbc9ec8 --- /dev/null +++ b/remappedSrc/pm/j4/petroleum/gui/PModMenuScreen.java @@ -0,0 +1,70 @@ +package pm.j4.petroleum.gui; + +import com.mojang.blaze3d.systems.RenderSystem; +import java.util.Map; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.render.BufferBuilder; +import net.minecraft.client.render.Tessellator; +import net.minecraft.client.render.VertexFormats; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.LiteralText; +import net.minecraft.text.TranslatableText; +import pm.j4.petroleum.modules.menu.ModMenu; +import pm.j4.petroleum.util.config.ConfigManager; +import pm.j4.petroleum.util.data.ButtonInformation; +import pm.j4.petroleum.util.data.Category; + +/** + * The type P mod menu screen. + */ +public class PModMenuScreen extends Screen { + /** + * Instantiates a new P mod menu screen. + */ + public PModMenuScreen() { + super(new TranslatableText("petroleum.modmenu")); + } + + @Override + public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { + this.renderBackground(matrices); + super.render(matrices, mouseX, mouseY, delta); + } + + @Override + protected void init() { + Map coordinateMap = ModMenu.getButtons(); + coordinateMap.forEach((category, coord) -> { + this.addButton(new PMovableButton((int) (coord.x * this.width), + (int) (coord.y * this.height), + category, + Category.getByCategory(category), + coord.open, + this)); + }); + } + + @Override + public void onClose() { + if (ConfigManager.getConfig().isPresent()) { + ConfigManager.getConfig().get().disableModule("petroleum.modmenu"); + this.buttons.forEach(button -> ((PMovableButton) button).updateCoordinate()); + ConfigManager.saveGlobalConfig(); + } + super.onClose(); + } + + @Override + public void renderBackground(MatrixStack matrices) { + Tessellator t_1 = Tessellator.getInstance(); + BufferBuilder buffer = t_1.getBuffer(); + RenderSystem.enableBlend(); + buffer.begin(7, VertexFormats.POSITION_COLOR); + buffer.vertex(0, this.height, 0.0D).color(0.1F, 0.1F, 0.1F, 0.3F).next(); + buffer.vertex(this.width, this.height, 0.0D).color(0.1F, 0.1F, 0.1F, 0.3F).next(); + buffer.vertex(this.width, 0, 0.0D).color(0.1F, 0.1F, 0.1F, 0.3F).next(); + buffer.vertex(0, 0, 0.0D).color(0.1F, 0.1F, 0.1F, 0.3F).next(); + t_1.draw(); + RenderSystem.disableBlend(); + } +} diff --git a/remappedSrc/pm/j4/petroleum/gui/PModuleConfigEntry.java b/remappedSrc/pm/j4/petroleum/gui/PModuleConfigEntry.java new file mode 100644 index 0000000..3125ed1 --- /dev/null +++ b/remappedSrc/pm/j4/petroleum/gui/PModuleConfigEntry.java @@ -0,0 +1,69 @@ +package pm.j4.petroleum.gui; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.widget.EntryListWidget; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.LiteralText; +import net.minecraft.text.Text; +import pm.j4.petroleum.util.module.option.BooleanOption; +import pm.j4.petroleum.util.module.option.ConfigurationOption; +import pm.j4.petroleum.util.module.option.ListOption; + +/** + * The type P module config entry. + */ +public class PModuleConfigEntry extends EntryListWidget.Entry { + /** + * The Option. + */ + protected final ConfigurationOption option; + /** + * The Display text. + */ + protected final Text displayText; + + /** + * Instantiates a new P module config entry. + * + * @param option the option + * @param text the text + */ + public PModuleConfigEntry(ConfigurationOption option, Text text) { + this.option = option; + this.displayText = text; + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + if (this.isMouseOver(mouseX, mouseY)) { + return true; + } + return false; + } + + @Override + public void render(MatrixStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) { + if (this.displayText != null) { + MinecraftClient.getInstance().textRenderer.drawWithShadow(matrices, displayText, x, y, 0xAAAAAA); + } + if (this.option != null) { + //TODO option text box (?) + // option should be centered or otherwise offset + // but not extend past the side of the pane + int fontHeight = MinecraftClient.getInstance().textRenderer.fontHeight; + MinecraftClient.getInstance().textRenderer.drawWithShadow(matrices, new LiteralText(option.getDescription() + " " + option.getStringValue()), x, y + fontHeight + 4, 0xFFFFFF); + String className = option.getClass().toString(); + if (className == BooleanOption.class.toString()) { + // boolean button + } + else if (className == ListOption.class.toString()) { + // handle list + // TODO: determine whether list options are viable, + // considering that it would be easier to split lists into multiple PModuleConfigEntries + } + else { + // string button + } + } + } +} \ No newline at end of file diff --git a/remappedSrc/pm/j4/petroleum/gui/PModuleConfigPane.java b/remappedSrc/pm/j4/petroleum/gui/PModuleConfigPane.java new file mode 100644 index 0000000..31d6160 --- /dev/null +++ b/remappedSrc/pm/j4/petroleum/gui/PModuleConfigPane.java @@ -0,0 +1,115 @@ +package pm.j4.petroleum.gui; + +import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.systems.RenderSystem; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.widget.EntryListWidget; +import net.minecraft.client.render.BufferBuilder; +import net.minecraft.client.render.Tessellator; +import net.minecraft.client.render.VertexFormats; +import net.minecraft.client.util.math.MatrixStack; + +/** + * The type P module config pane. + */ +public class PModuleConfigPane extends EntryListWidget { + /** + * The Parent. + */ + private final POptionsScreen parent; + /** + * The Last selected. + */ + private POptionEntry lastSelected; + + /** + * Instantiates a new P module config pane. + * + * @param client the client + * @param width the width + * @param height the height + * @param top the top + * @param bottom the bottom + * @param entryHeight the entry height + * @param screen the screen + */ + public PModuleConfigPane(MinecraftClient client, int width, int height, int top, int bottom, int entryHeight, POptionsScreen screen) { + super(client, width, height, top, bottom, entryHeight); + this.parent = screen; + /** + * The Text renderer. + */ + TextRenderer textRenderer = client.textRenderer; + } + + @Override + public PModuleConfigEntry getSelected() { + return null; + } + + @Override + public int getRowWidth() { + return this.width - 10; + } + + @Override + protected int getScrollbarPositionX() { + return this.width - 6 + left; + } + + @Override + public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { + POptionEntry selectedEntry = parent.getSelected(); + if (selectedEntry != lastSelected) { + lastSelected = selectedEntry; + clearEntries(); + setScrollAmount(-Double.MAX_VALUE); + String id = lastSelected.getModId(); + if (lastSelected != null && id != null && !id.isEmpty()) { + children().addAll(lastSelected.module.getConfigEntries()); + } + } + + Tessellator t_1 = Tessellator.getInstance(); + BufferBuilder buffer = t_1.getBuffer(); + + RenderSystem.depthFunc(515); + RenderSystem.disableDepthTest(); + RenderSystem.enableBlend(); + RenderSystem.blendFuncSeparate(GlStateManager.SrcFactor.SRC_ALPHA, + GlStateManager.DstFactor.ONE_MINUS_DST_ALPHA, + GlStateManager.SrcFactor.ZERO, + GlStateManager.DstFactor.ONE); + RenderSystem.disableAlphaTest(); + RenderSystem.shadeModel(7425); + RenderSystem.disableTexture(); + + buffer.begin(7, VertexFormats.POSITION_COLOR_TEXTURE); + buffer.vertex(this.left, (this.top + 4), 0.0D).texture(0.0F, 1.0F).color(0, 0, 0, 0).next(); + buffer.vertex(this.right, (this.top + 4), 0.0D).texture(1.0F, 1.0F).color(0, 0, 0, 0).next(); + buffer.vertex(this.right, this.top, 0.0D).texture(1.0F, 0.0F).color(0, 0, 0, 255).next(); + buffer.vertex(this.left, this.top, 0.0D).texture(0.0F, 0.0F).color(0, 0, 0, 255).next(); + buffer.vertex(this.left, this.bottom, 0.0D).texture(0.0F, 1.0F).color(0, 0, 0, 255).next(); + buffer.vertex(this.right, this.bottom, 0.0D).texture(1.0F, 1.0F).color(0, 0, 0, 255).next(); + buffer.vertex(this.right, (this.bottom - 4), 0.0D).texture(1.0F, 0.0F).color(0, 0, 0, 0).next(); + buffer.vertex(this.left, (this.bottom - 4), 0.0D).texture(0.0F, 0.0F).color(0, 0, 0, 0).next(); + t_1.draw(); + + buffer.begin(7, VertexFormats.POSITION_COLOR); + buffer.vertex(this.left, this.bottom, 0.0D).color(0, 0, 0, 128).next(); + buffer.vertex(this.right, this.bottom, 0.0D).color(0, 0, 0, 128).next(); + buffer.vertex(this.right, this.top, 0.0D).color(0, 0, 0, 128).next(); + buffer.vertex(this.left, this.top, 0.0D).color(0, 0, 0, 128).next(); + t_1.draw(); + + int rl = this.getRowLeft(); + int sc = this.top + 4 - (int) this.getScrollAmount(); + this.renderList(matrices, rl, sc, mouseX, mouseY, delta); + + RenderSystem.enableTexture(); + RenderSystem.shadeModel(7424); + RenderSystem.enableAlphaTest(); + RenderSystem.disableBlend(); + } +} diff --git a/remappedSrc/pm/j4/petroleum/gui/PModuleConfigurationWidget.java b/remappedSrc/pm/j4/petroleum/gui/PModuleConfigurationWidget.java new file mode 100644 index 0000000..495da1c --- /dev/null +++ b/remappedSrc/pm/j4/petroleum/gui/PModuleConfigurationWidget.java @@ -0,0 +1,281 @@ +package pm.j4.petroleum.gui; + +import com.mojang.blaze3d.systems.RenderSystem; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.widget.AlwaysSelectedEntryListWidget; +import net.minecraft.client.render.BufferBuilder; +import net.minecraft.client.render.Tessellator; +import net.minecraft.client.render.VertexFormats; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Matrix4f; +import pm.j4.petroleum.mixin.EntryListWidgetAccessor; +import pm.j4.petroleum.util.module.ModuleBase; + +/** + * The type P module configuration widget. + */ +public class PModuleConfigurationWidget extends AlwaysSelectedEntryListWidget { + /** + * The Parent. + */ + private final POptionsScreen parent; + /** + * The Module id. + */ + private String moduleId = null; + /** + * The Mods. + */ + private List mods; + /** + * The Extra mods. + */ + private final Set extraMods = new HashSet<>(); + /** + * The Scrolling. + */ + private boolean scrolling = false; + + /** + * Instantiates a new P module configuration widget. + * + * @param client the client + * @param width the width + * @param height the height + * @param y1 the y 1 + * @param y2 the y 2 + * @param entryHeight the entry height + * @param list the list + * @param parent the parent + */ + public PModuleConfigurationWidget(MinecraftClient client, int width, int height, int y1, int y2, int entryHeight, PModuleConfigurationWidget list, POptionsScreen parent) { + super(client, width, height, y1, y2, entryHeight); + this.parent = parent; + if (list != null) { + mods = list.mods; + } + setScrollAmount(parent.getScrollPercent() * Math.max(0, this.getMaxPosition() - (this.bottom - this.top - 4))); + } + + @Override + public void setScrollAmount(double amount) { + super.setScrollAmount(amount); + int denominator = Math.max(0, this.getMaxPosition() - (this.bottom - this.top - 4)); + if (denominator <= 0) { + parent.updateScrollPercent(0); + } else { + parent.updateScrollPercent(getScrollAmount() / Math.max(0, this.getMaxPosition() - (this.bottom - this.top - 4))); + } + } + + @Override + protected boolean isFocused() { + return parent.getFocused() == this; + } + + /** + * Select. + * + * @param entry the entry + */ + public void select(POptionEntry entry) { + this.setSelected(entry); + } + + @Override + public void setSelected(POptionEntry entry) { + super.setSelected(entry); + moduleId = entry.getModId(); + parent.updateSelected(entry); + } + + @Override + protected boolean isSelectedItem(int index) { + return super.isSelectedItem(index); + } + + @Override + public int addEntry(POptionEntry entry) { + if (extraMods.contains(entry.module)) { + return 0; + } + extraMods.add(entry.module); + int i = super.addEntry(entry); + if (entry.getModId().equals(moduleId)) { + setSelected(entry); + } + return i; + } + + @Override + protected boolean removeEntry(POptionEntry entry) { + extraMods.remove(entry.module); + return super.removeEntry(entry); + } + + @Override + protected POptionEntry remove(int index) { + extraMods.remove(getEntry(index).module); + return super.remove(index); + } + + @Override + protected void renderList(MatrixStack matrices, int x, int y, int mouseX, int mouseY, float delta) { + int itemCount = this.getItemCount(); + Tessellator t_1 = Tessellator.getInstance(); + BufferBuilder buffer = t_1.getBuffer(); + + for (int index = 0; index < itemCount; ++index) { + int entryTop = this.getRowTop(index); + int entryBottom = this.getRowTop(index) + this.itemHeight; + if (entryBottom >= this.top && entryTop <= this.bottom) { + int entryHeight = this.itemHeight - 4; + POptionEntry entry = this.getEntry(index); + int rowWidth = this.getRowWidth(); + int entryLeft; + if (((EntryListWidgetAccessor) this).isRenderSelection() && this.isSelectedItem(index)) { + entryLeft = getRowLeft() - 2 + entry.getXOffset(); + int selectionRight = x + rowWidth + 2; + RenderSystem.disableTexture(); + float brightness = this.isFocused() ? 1.0F : 0.5F; + RenderSystem.color4f(brightness, brightness, brightness, 1.0F); + Matrix4f matrix = matrices.peek().getModel(); + buffer.begin(7, VertexFormats.POSITION); + buffer.vertex(matrix, entryLeft, entryTop + entryHeight + 2, 0.0F).next(); + buffer.vertex(matrix, selectionRight, entryTop + entryHeight + 2, 0.0F).next(); + buffer.vertex(matrix, selectionRight, entryTop - 2, 0.0F).next(); + buffer.vertex(matrix, entryLeft, entryTop - 2, 0.0F).next(); + t_1.draw(); + RenderSystem.color4f(0.0F, 0.0F, 0.0F, 1.0F); + buffer.begin(7, VertexFormats.POSITION); + buffer.vertex(matrix, entryLeft + 1, entryTop + entryHeight + 1, 0.0F).next(); + buffer.vertex(matrix, selectionRight, entryTop + entryHeight + 1, 0.0F).next(); + buffer.vertex(matrix, selectionRight, entryTop - 1, 0.0F).next(); + buffer.vertex(matrix, entryLeft + 1, entryTop - 1, 0.0F).next(); + t_1.draw(); + RenderSystem.enableTexture(); + } + + entryLeft = this.getRowLeft(); + entry.render(matrices, + index, + entryTop, + entryLeft, + rowWidth, + entryHeight, + mouseX, + mouseY, + this.isMouseOver(mouseX, mouseY) && Objects.equals(this.getEntryAtPos(mouseX, mouseY), entry), + delta); + } + } + } + + @Override + protected void updateScrollingState(double mouseX, double mouseY, int button) { + super.updateScrollingState(mouseX, mouseY, button); + this.scrolling = button == 0 && + mouseX >= (double) this.getScrollbarPositionX() && + mouseX < (double) (this.getScrollbarPositionX() + 6); + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + this.updateScrollingState(mouseX, mouseY, button); + if (!this.isMouseOver(mouseX, mouseY)) { + return false; + } else { + POptionEntry entry = this.getEntryAtPos(mouseX, mouseY); + if (entry != null) { + if (entry.mouseClicked(mouseX, mouseY, button)) { + this.setFocused(entry); + this.setDragging(true); + return true; + } else if (button == 0) { + this.clickedHeader((int) (mouseX - (double) (this.left + this.width / 2 - this.getRowWidth() / 2)), + (int) (mouseY - (double) this.top) + (int) this.getScrollAmount() - 4); + } + } + } + + return this.scrolling; + } + + /** + * Gets entry at pos. + * + * @param x the x + * @param y the y + * @return the entry at pos + */ + public final POptionEntry getEntryAtPos(double x, double y) { + int i = MathHelper.floor(y - (double) this.top) - this.headerHeight + (int) this.getScrollAmount() - 4; + int index = i / this.itemHeight; + return x < (double) this.getScrollbarPositionX() && + x >= (double) getRowLeft() && + x <= (double) (getRowLeft() + getRowWidth()) && + index >= 0 && i >= 0 && + index < this.getItemCount() ? this.children().get(index) : null; + } + + @Override + protected int getScrollbarPositionX() { + return this.width - 6; + } + + @Override + public int getRowWidth() { + return this.width - (Math.max(0, this.getMaxPosition() - (this.bottom - this.top - 4)) > 0 ? 18 : 12); + } + + @Override + public int getRowLeft() { + return left + 6; + } + + /** + * Gets width. + * + * @return the width + */ + public int getWidth() { + return width; + } + + /** + * Gets top. + * + * @return the top + */ + public int getTop() { + return this.top; + } + + /** + * Gets parent. + * + * @return the parent + */ + public POptionsScreen getParent() { + return parent; + } + + @Override + protected int getMaxPosition() { + return super.getMaxPosition() + 4; + } + + /** + * Gets displayed count. + * + * @return the displayed count + */ + public int getDisplayedCount() { + return children().size(); + } +} diff --git a/remappedSrc/pm/j4/petroleum/gui/PMovableButton.java b/remappedSrc/pm/j4/petroleum/gui/PMovableButton.java new file mode 100644 index 0000000..4ff84fa --- /dev/null +++ b/remappedSrc/pm/j4/petroleum/gui/PMovableButton.java @@ -0,0 +1,389 @@ +package pm.j4.petroleum.gui; + +import com.mojang.blaze3d.systems.RenderSystem; +import java.util.List; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.widget.AbstractButtonWidget; +import net.minecraft.client.render.BufferBuilder; +import net.minecraft.client.render.Tessellator; +import net.minecraft.client.render.VertexFormats; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.LiteralText; +import net.minecraft.text.TranslatableText; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Matrix4f; +import pm.j4.petroleum.modules.menu.ModMenu; +import pm.j4.petroleum.util.data.ButtonInformation; +import pm.j4.petroleum.util.module.ModuleBase; + +/** + * The type P movable button. + */ +public class PMovableButton extends AbstractButtonWidget { + /** + * The Expanded. + */ + private boolean expanded; + /** + * The Collapsed width. + */ + private final int collapsedWidth; + /** + * The Expanded width. + */ + private int expandedWidth; + /** + * The Collapsed height. + */ + private final int collapsedHeight; + /** + * The Expanded height. + */ + private int expandedHeight; + /** + * The Module height. + */ + private final int moduleHeight; + /** + * The Modules. + */ + private final List modules; + + /** + * The Stored x. + */ + private int storedX; + /** + * The Stored y. + */ + private int storedY; + + /** + * The Spin. + */ + private double spin; + + /** + * The Arrow size. + */ + private final int arrowSize = 10; + + + /** + * The Category. + */ + private final String category; + + /** + * The Parent. + */ + private final PModMenuScreen parent; + + /** + * Instantiates a new P movable button. + * + * @param x the x + * @param y the y + * @param categoryName the category name + * @param modules the modules + * @param open the open + * @param parent the parent + */ + public PMovableButton(int x, int y, String categoryName, List modules, boolean open, PModMenuScreen parent) { + super(x, y, 0, 0, new TranslatableText(categoryName)); + this.category = categoryName; + int w = MinecraftClient.getInstance().textRenderer.getWidth(new TranslatableText(categoryName)) + 8; + int h = MinecraftClient.getInstance().textRenderer.fontHeight + 8; + this.width = w; + this.collapsedWidth = w; + this.expandedWidth = 0; + this.height = h; + this.collapsedHeight = h; + this.expandedHeight = 0; + this.moduleHeight = h; + this.expanded = open; + this.modules = modules; + this.parent = parent; + } + + @Override + public void onClick(double mouseX, double mouseY) { + this.storedX = (int) mouseX; + this.storedY = (int) mouseY; + super.onClick(mouseX, mouseY); + } + + /** + * On extra click. + * + * @param mouseX the mouse x + * @param mouseY the mouse y + */ + private void onExtraClick(double mouseX, double mouseY) { + System.out.println("extra click"); + int increment = this.moduleHeight + 4; + int location = (int)mouseY - (this.y + this.collapsedHeight); + int index = location / increment; + System.out.println("index: " + index); + if(modules.size() >= index) { + ModuleBase affectedModule = modules.get(index); + System.out.println("module: " + affectedModule); + if(affectedModule.isActivatable()) { + System.out.println("toggling"); + affectedModule.toggle(); + } + } + else { + System.out.println("index too great"); + } + //TODO module things + } + + @Override + public void onRelease(double mouseX, double mouseY) { + int mx = (int) mouseX; + int my = (int) mouseY; + /** + * The Padding. + */ + int padding = 5; + if (storedX + padding > mx && storedX - padding < mx && + storedY + padding > my && storedY - padding < my) { + this.expanded = !this.expanded; + } + } + + @Override + protected void onDrag(double mouseX, double mouseY, double deltaX, double deltaY) { + this.x += (int) deltaX; + this.y += (int) deltaY; + + // i really hate to do it but nowhere else will it properly save + this.updateCoordinate(); + } + + /** + * Update coordinate. + */ + public void updateCoordinate() { + ModMenu.updateCoord(this.category, new ButtonInformation((this.x / (double) parent.width), (this.y / (double) parent.height), this.expanded)); + } + + // fuck click sounds + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + if (this.active && this.visible) { + if (this.isValidClickButton(button)) { + boolean bl = this.clicked(mouseX, mouseY); + if (bl && mouseY > this.y + this.collapsedHeight && mouseY < this.y + this.expandedHeight) { + this.onExtraClick(mouseX, mouseY); + return true; + } else if (bl) { + this.onClick(mouseX, mouseY); + return true; + } + } + + } + return false; + } + + /** + * Transition max width. + * + * @param width the width + */ + private void transitionMaxWidth(int width) { + double increment = ((width - this.width) / 20.0); + int sign = (width > this.width) ? 1 : -1; + if (increment == 0) { + this.width = width; + } else if (increment < 1 && increment > -1) { + this.width += sign; + } else { + this.width += (int) increment; + } + } + + /** + * Transition max height. + * + * @param height the height + */ + private void transitionMaxHeight(int height) { + double increment = ((height - this.height) / 20.0); + int sign = (height > this.height) ? 1 : -1; + if (increment == 0) { + this.height = height; + } else if (increment < 1 && increment > -1) { + this.height += sign; + } else { + this.height += (int) increment; + } + } + + @Override + public void renderButton(MatrixStack matrices, int mouseX, int mouseY, float delta) { + + if (this.expandedWidth == 0 || this.expandedHeight == 0) { + this.expandedHeight = this.collapsedHeight + ((this.moduleHeight + 4) * modules.size()); + modules.forEach(module -> { + this.expandedWidth = this.width; + int w = MinecraftClient.getInstance().textRenderer.getWidth(module.getReadableName()) + arrowSize + 8; + if (w > this.expandedWidth) { + this.expandedWidth = w; + } + }); + // this should only run when opening the screen for the first time + if (this.expanded) { + this.height = expandedHeight; + this.width = expandedWidth; + } + } + + MinecraftClient minecraftClient = MinecraftClient.getInstance(); + TextRenderer textRenderer = minecraftClient.textRenderer; + minecraftClient.getTextureManager().bindTexture(WIDGETS_LOCATION); + RenderSystem.color4f(1.0F, 1.0F, 1.0F, this.alpha); + + RenderSystem.disableTexture(); + RenderSystem.defaultBlendFunc(); + float brightness = this.isFocused() ? 1.0F : 0.5F; + RenderSystem.color4f(brightness, brightness, brightness, 1.0F); + Matrix4f matrix = matrices.peek().getModel(); + + int buttonLeft = this.x; + int buttonRight = this.x + width + 2; + int buttonTop = this.y; + int buttonBottom = this.y + this.collapsedHeight; + int buttonExpandedBottom = this.y + this.height; + Tessellator t_1 = Tessellator.getInstance(); + BufferBuilder buffer = t_1.getBuffer(); + + RenderSystem.color4f(0.5F, 0.5F, 0.5F, 0.5F); + drawBox(t_1, buffer, matrix, buttonLeft, buttonRight, buttonTop - 2, buttonBottom + 2); + + RenderSystem.color4f(0.0F, 0.0F, 0.0F, 0.3F); + drawBox(t_1, buffer, matrix, buttonLeft + 1, buttonRight - 1, buttonTop - 1, buttonBottom + 1); + + RenderSystem.color4f(1.0F, 1.0F, 1.0F, 0.9F); + drawEquilateralTriangle(t_1, buffer, matrix, 40, 40, 180, arrowSize); + drawEquilateralTriangle(t_1, buffer, matrix, 60, 60, 0, arrowSize); + drawEquilateralTriangle(t_1, buffer, matrix, 40, 60, 90, arrowSize); + drawEquilateralTriangle(t_1, buffer, matrix, 60, 40, 360, arrowSize); + drawEquilateralTriangle(t_1, buffer, matrix, 80, 40, 270, arrowSize); + drawEquilateralTriangle(t_1, buffer, matrix, 80, 60, 120, arrowSize); + + int j = this.active ? 16777215 : 10526880; + if (this.expanded) { + if (this.width != this.expandedWidth || this.height != this.expandedHeight) { + transitionMaxWidth(this.expandedWidth); + transitionMaxHeight(this.expandedHeight); + RenderSystem.color4f(0.5F, 0.5F, 0.5F, 0.5F); + drawBox(t_1, buffer, matrix, buttonLeft, buttonRight, buttonBottom + 1, buttonExpandedBottom + 2); + + RenderSystem.color4f(0.0F, 0.0F, 0.0F, 0.3F); + drawBox(t_1, buffer, matrix, buttonLeft + 1, buttonRight - 1, buttonBottom + 2, buttonExpandedBottom + 1); + if ((this.height - 8) / 2 > (this.collapsedHeight)) { + drawCenteredText(matrices, textRenderer, new LiteralText("..."), this.x + this.width / 2, this.y + (this.height - 8) / 2, j | MathHelper.ceil(this.alpha * 255.0F) << 24); + } + } else { + for (int i = 0; i < modules.size(); i++) { + int adjustedIndex = i + 1; + int previousBottom = buttonBottom + (i * (this.moduleHeight + 4)); + int currentBottom = buttonBottom + ((i + 1) * (this.moduleHeight + 4)); + + RenderSystem.defaultBlendFunc(); + RenderSystem.color4f(0.5F, 0.5F, 0.5F, 0.5F); + drawBox(t_1, buffer, matrix, buttonLeft, buttonRight, previousBottom + 1, currentBottom + 2); + + RenderSystem.color4f(0.0F, 0.0F, 0.0F, 0.3F); + drawBox(t_1, buffer, matrix, buttonLeft + 1, buttonRight - 1, previousBottom + 2, currentBottom + 1); + + drawCenteredText(matrices, + textRenderer, + modules.get(i).getReadableName(), + this.x + this.width / 2, + this.y + ((this.collapsedHeight - 8) / 2 + ((moduleHeight + 4) * adjustedIndex)), + j | MathHelper.ceil(this.alpha * 255.0F) << 24); + } + } + } else { + if (this.width != this.collapsedWidth || this.height != this.collapsedHeight) { + transitionMaxWidth(this.collapsedWidth); + transitionMaxHeight(this.collapsedHeight); + RenderSystem.color4f(0.5F, 0.5F, 0.5F, 0.5F); + drawBox(t_1, buffer, matrix, buttonLeft, buttonRight, buttonBottom + 1, buttonExpandedBottom + 2); + + RenderSystem.color4f(0.0F, 0.0F, 0.0F, 0.3F); + drawBox(t_1, buffer, matrix, buttonLeft + 1, buttonRight - 1, buttonBottom + 2, buttonExpandedBottom + 1); + if ((this.height - 8) / 2 > (this.collapsedHeight)) { + drawCenteredText(matrices, textRenderer, new LiteralText("..."), this.x + this.width / 2, this.y + (this.height - 8) / 2, j | MathHelper.ceil(this.alpha * 255.0F) << 24); + } + } + } + RenderSystem.enableTexture(); + drawCenteredText(matrices, textRenderer, this.getMessage(), this.x + this.width / 2, this.y + (this.collapsedHeight - 8) / 2, j | MathHelper.ceil(this.alpha * 255.0F) << 24); + } + + /** + * Draw equilateral triangle. + * + * @param t_1 the t 1 + * @param buffer the buffer + * @param matrix the matrix + * @param centerX the center x + * @param centerY the center y + * @param rotation the rotation + * @param distance the distance + */ + private void drawEquilateralTriangle(Tessellator t_1, BufferBuilder buffer, Matrix4f matrix, int centerX, int centerY, double rotation, int distance) { + double rotation1 = rotation; + double rotation2 = rotation + 120; + double rotation3 = rotation + 240; + int point1X = (int)(distance * Math.cos(Math.toRadians(rotation1))) + centerX; + int point1Y = (int)(distance * Math.sin(Math.toRadians(rotation1))) + centerY; + int point2X = (int)(distance * Math.cos(Math.toRadians(rotation2))) + centerX; + int point2Y = (int)(distance * Math.sin(Math.toRadians(rotation2))) + centerY; + int point3X = (int)(distance * Math.cos(Math.toRadians(rotation3))) + centerX; + int point3Y = (int)(distance * Math.sin(Math.toRadians(rotation3))) + centerY; + + //RenderSystem.enableBlend(); + RenderSystem.disableBlend(); + buffer.begin(7, VertexFormats.POSITION_COLOR); + buffer.vertex(matrix, centerX, centerY, 0.0F).color(0.0F, 1.0F, 1.0F, 1.0F).next(); + buffer.vertex(matrix, centerX, point1Y, 0.0F).color(0.0F, 1.0F, 1.0F, 1.0F).next(); + buffer.vertex(matrix, point1X, point1Y, 0.0F).color(0.0F, 1.0F, 1.0F, 1.0F).next(); + + buffer.vertex(matrix, centerX, centerY, 0.0F).color(0.5F, 1.0F, 1.0F, 1.0F).next(); + buffer.vertex(matrix, centerX, point2Y, 0.0F).color(0.5F, 1.0F, 1.0F, 1.0F).next(); + buffer.vertex(matrix, point2X, point2Y, 0.0F).color(0.5F, 1.0F, 1.0F, 1.0F).next(); + + buffer.vertex(matrix, centerX, centerY, 0.0F).color(1.0F, 0.0F, 1.0F, 1.0F).next(); + buffer.vertex(matrix, centerX, point3Y, 0.0F).color(1.0F, 0.0F, 1.0F, 1.0F).next(); + buffer.vertex(matrix, point3X, point3Y, 0.0F).color(1.0F, 0.0F, 1.0F, 1.0F).next(); + t_1.draw(); + } + + /** + * Draw box. + * + * @param t_1 the t 1 + * @param buffer the buffer + * @param matrix the matrix + * @param buttonLeft the button left + * @param buttonRight the button right + * @param buttonTop the button top + * @param buttonBottom the button bottom + */ + private void drawBox(Tessellator t_1, BufferBuilder buffer, Matrix4f matrix, int buttonLeft, int buttonRight, int buttonTop, int buttonBottom) { + RenderSystem.enableBlend(); + buffer.begin(7, VertexFormats.POSITION); + buffer.vertex(matrix, buttonLeft, buttonBottom, 0.0F).next(); + buffer.vertex(matrix, buttonRight, buttonBottom, 0.0F).next(); + buffer.vertex(matrix, buttonRight, buttonTop, 0.0F).next(); + buffer.vertex(matrix, buttonLeft, buttonTop, 0.0F).next(); + t_1.draw(); + } +} diff --git a/remappedSrc/pm/j4/petroleum/gui/POptionEntry.java b/remappedSrc/pm/j4/petroleum/gui/POptionEntry.java new file mode 100644 index 0000000..4132848 --- /dev/null +++ b/remappedSrc/pm/j4/petroleum/gui/POptionEntry.java @@ -0,0 +1,94 @@ +package pm.j4.petroleum.gui; + +import com.mojang.blaze3d.systems.RenderSystem; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.widget.AlwaysSelectedEntryListWidget; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.StringVisitable; +import net.minecraft.text.Text; +import net.minecraft.text.TranslatableText; +import net.minecraft.util.Language; +import pm.j4.petroleum.util.module.ModuleBase; + +/** + * The type P option entry. + */ +public class POptionEntry extends AlwaysSelectedEntryListWidget.Entry { + + /** + * The Module. + */ + protected final ModuleBase module; + /** + * The Client. + */ + protected final MinecraftClient client; + /** + * The List. + */ + private final PModuleConfigurationWidget list; + + /** + * Instantiates a new P option entry. + * + * @param mod the mod + * @param list the list + */ + public POptionEntry(ModuleBase mod, PModuleConfigurationWidget list) { + this.module = mod; + this.client = MinecraftClient.getInstance(); + this.list = list; + } + + //TODO TEST move text to be centered + @Override + public void render(MatrixStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) { + x += getXOffset(); + entryWidth -= getXOffset(); + RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F); + Text name = this.getModName(); + StringVisitable nameString = name; + int maxNameWidth = entryWidth - 32 - 3; + TextRenderer font = this.client.textRenderer; + if (font.getWidth(name) > maxNameWidth) { + StringVisitable ellipse = StringVisitable.plain("..."); + nameString = StringVisitable.concat(font.trimToWidth(nameString, maxNameWidth - font.getWidth(ellipse)), ellipse); + } + + font.draw(matrices, Language.getInstance().reorder(nameString), x + 32 + 3, y + (entryHeight / 2), 0xFFFFFF); + } + + @Override + public boolean mouseClicked(double x, double y, int b) { + this.list.select(this); + return true; + } + + /** + * Gets mod id. + * + * @return the mod id + */ + public String getModId() { + return module.getModuleName(); + } + + /** + * Gets mod name. + * + * @return the mod name + */ + public TranslatableText getModName() { + return module.getReadableName(); + } + + /** + * Gets x offset. + * + * @return the x offset + */ + public int getXOffset() { + return 0; + } +} diff --git a/remappedSrc/pm/j4/petroleum/gui/POptionsScreen.java b/remappedSrc/pm/j4/petroleum/gui/POptionsScreen.java new file mode 100644 index 0000000..de409d6 --- /dev/null +++ b/remappedSrc/pm/j4/petroleum/gui/POptionsScreen.java @@ -0,0 +1,224 @@ +package pm.j4.petroleum.gui; + +import com.mojang.blaze3d.systems.RenderSystem; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawableHelper; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.ScreenTexts; +import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.render.BufferBuilder; +import net.minecraft.client.render.Tessellator; +import net.minecraft.client.render.VertexFormats; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.LiteralText; +import net.minecraft.text.StringVisitable; +import net.minecraft.text.Text; +import net.minecraft.text.TranslatableText; +import pm.j4.petroleum.PetroleumMod; +import pm.j4.petroleum.util.config.ConfigManager; +import pm.j4.petroleum.util.module.ModuleBase; + +/** + * The type P options screen. + */ +@SuppressWarnings("deprecation") +public class POptionsScreen extends Screen { + /** + * The Previous screen. + */ + private final Screen previousScreen; + /** + * The Scroll percent. + */ + private double scrollPercent = 0; + /** + * The Modules. + */ + private PModuleConfigurationWidget modules; + /** + * The Config pane. + */ + private PModuleConfigPane configPane; + /** + * The Selected. + */ + private POptionEntry selected; + /** + * The Tooltip. + */ + private Text tooltip; + + /** + * The Pane y. + */ + private int paneY; + /** + * The Right pane x. + */ + private int rightPaneX; + + /** + * Instantiates a new P options screen. + * + * @param previousScreen the previous screen + */ + public POptionsScreen(Screen previousScreen) { + super(new TranslatableText("petroleum.options")); + this.previousScreen = previousScreen; + } + + @Override + public void onClose() { + super.onClose(); + assert this.client != null; + this.client.openScreen(previousScreen); + } + + protected void init() { + paneY = 48; + int paneWidth = this.width / 2 - 8; + rightPaneX = width - paneWidth; + this.modules = new PModuleConfigurationWidget(this.client, + this.width - paneWidth, + this.height, + paneY + 19, + this.height - 36, + 36, + this.modules, + this); + this.modules.setLeftPos(0); + this.children.add(this.modules); + this.configPane = new PModuleConfigPane(this.client, + paneWidth, + this.height, + paneY + 19, + this.height - 36, + 48, + this); + this.configPane.setLeftPos(paneWidth); + this.children.add(this.configPane); + List configurableModules = new ArrayList<>(); + if (ConfigManager.getConfig().isPresent()) { + configurableModules.addAll(PetroleumMod.getActiveMods() + .stream().filter(ModuleBase::configurable) + .collect(Collectors.toList())); + } + configurableModules.forEach(module -> this.modules.addEntry(new POptionEntry(module, this.modules))); + this.addButton(new ButtonWidget(this.width / 2 - 75, this.height - 30, 150, 20, ScreenTexts.DONE, (buttonWidget) -> { + ConfigManager.saveAllModules(); + assert this.client != null; + this.client.openScreen(this.previousScreen); + })); + } + + @Override + public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { + this.renderBackground(matrices); + + this.modules.render(matrices, mouseX, mouseY, delta); + if (selected != null) { + this.configPane.render(matrices, mouseX, mouseY, delta); + } + RenderSystem.disableBlend(); + drawTextWithShadow(matrices, this.textRenderer, this.title, this.modules.getWidth() / 2, 8, 16777215); + super.render(matrices, mouseX, mouseY, delta); + + if (selected != null) { + int offset = 36; + int x = rightPaneX; + int maxNameWidth = this.width - (x + offset); + int lineSpacing = textRenderer.fontHeight + 1; + Text name = selected.getModName(); + + StringVisitable trimmedName = name; + + if (textRenderer.getWidth(name) > maxNameWidth) { + StringVisitable ellipsis = StringVisitable.plain("..."); + trimmedName = StringVisitable.concat(textRenderer.trimToWidth(name, maxNameWidth - textRenderer.getWidth(ellipsis)), ellipsis); + } + if (mouseX > x + offset && mouseY > paneY + 1 && mouseY < paneY + 1 + textRenderer.fontHeight && mouseX < x + offset + textRenderer.getWidth(trimmedName)) { + setTooltip(new LiteralText("Configure " + selected.getModName())); + } + textRenderer.draw(matrices, selected.getModName(), x + offset, paneY + 2 + lineSpacing, 0x808080); + + if (this.tooltip != null) { + this.renderOrderedTooltip(matrices, textRenderer.wrapLines(this.tooltip, Integer.MAX_VALUE), mouseX, mouseY); + } + } + } + + /** + * Sets tooltip. + * + * @param tooltip the tooltip + */ + private void setTooltip(Text tooltip) { + this.tooltip = tooltip; + } + + @Override + public void renderBackground(MatrixStack matrices) { + POptionsScreen.overlayBackground(this.width, this.height); + } + + /** + * Overlay background. + * + * @param x2 the x 2 + * @param y2 the y 2 + */ + static void overlayBackground(int x2, int y2) { + Tessellator t_1 = Tessellator.getInstance(); + BufferBuilder buffer = t_1.getBuffer(); + Objects.requireNonNull(MinecraftClient.getInstance()).getTextureManager().bindTexture(DrawableHelper.OPTIONS_BACKGROUND_TEXTURE); + RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F); + buffer.begin(7, VertexFormats.POSITION_TEXTURE_COLOR); + buffer.vertex(0, y2, 0.0D).texture(0 / 32.0F, y2 / 32.0F).color(64, 64, 64, 255).next(); + buffer.vertex(x2, y2, 0.0D).texture(x2 / 32.0F, y2 / 32.0F).color(64, 64, 64, 255).next(); + buffer.vertex(x2, 0, 0.0D).texture(x2 / 32.0F, 0 / 32.0F).color(64, 64, 64, 255).next(); + buffer.vertex(0, 0, 0.0D).texture(0 / 32.0F, 0 / 32.0F).color(64, 64, 64, 255).next(); + t_1.draw(); + } + + /** + * Gets scroll percent. + * + * @return the scroll percent + */ + double getScrollPercent() { + return scrollPercent; + } + + /** + * Update scroll percent. + * + * @param scrollPercent the scroll percent + */ + void updateScrollPercent(double scrollPercent) { + this.scrollPercent = scrollPercent; + } + + /** + * Gets selected. + * + * @return the selected + */ + POptionEntry getSelected() { + return selected; + } + + /** + * Update selected. + * + * @param entry the entry + */ + void updateSelected(POptionEntry entry) { + if (entry != null) { + this.selected = entry; + } + } +} diff --git a/remappedSrc/pm/j4/petroleum/mixin/DebugHudMixin.java b/remappedSrc/pm/j4/petroleum/mixin/DebugHudMixin.java new file mode 100644 index 0000000..2a79bdd --- /dev/null +++ b/remappedSrc/pm/j4/petroleum/mixin/DebugHudMixin.java @@ -0,0 +1,38 @@ +package pm.j4.petroleum.mixin; + +import java.util.List; +import java.util.Optional; +import net.minecraft.client.gui.hud.DebugHud; +import net.minecraft.client.util.math.MatrixStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; +import pm.j4.petroleum.modules.splash.SplashText; +import pm.j4.petroleum.util.config.ConfigHolder; +import pm.j4.petroleum.util.config.ConfigManager; + +/** + * The type Debug hud mixin. + */ +@Mixin(DebugHud.class) +public class DebugHudMixin { + /** + * Render text right. + * + * @param matrices the matrices + * @param ci the ci + * @param list the list + */ + @Inject(method = "renderLeftText", + at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/client/gui/hud/DebugHud;getLeftText()Ljava/util/List;"), + locals = LocalCapture.CAPTURE_FAILSOFT) + protected void renderTextRight(MatrixStack matrices, CallbackInfo ci, List list) { + Optional config = ConfigManager.getConfig(); + if (config.isPresent() && config.get().isModuleEnabled("petroleum.splashtext")) { + list.add("[Petroleum] " + SplashText.get() + " loaded"); + } + + } +} diff --git a/remappedSrc/pm/j4/petroleum/mixin/EntryListWidgetAccessor.java b/remappedSrc/pm/j4/petroleum/mixin/EntryListWidgetAccessor.java new file mode 100644 index 0000000..eea68ab --- /dev/null +++ b/remappedSrc/pm/j4/petroleum/mixin/EntryListWidgetAccessor.java @@ -0,0 +1,19 @@ +package pm.j4.petroleum.mixin; + +import net.minecraft.client.gui.widget.EntryListWidget; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +/** + * The interface Entry list widget accessor. + */ +@Mixin(EntryListWidget.class) +public interface EntryListWidgetAccessor { + /** + * Is render selection boolean. + * + * @return the boolean + */ + @Accessor("renderSelection") + boolean isRenderSelection(); +} diff --git a/remappedSrc/pm/j4/petroleum/mixin/ModListMixin.java b/remappedSrc/pm/j4/petroleum/mixin/ModListMixin.java new file mode 100644 index 0000000..7ee7248 --- /dev/null +++ b/remappedSrc/pm/j4/petroleum/mixin/ModListMixin.java @@ -0,0 +1,89 @@ +package pm.j4.petroleum.mixin; + + +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.DrawableHelper; +import net.minecraft.client.gui.hud.InGameHud; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.TranslatableText; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import pm.j4.petroleum.modules.list.ModList; +import pm.j4.petroleum.util.config.ConfigHolder; +import pm.j4.petroleum.util.config.ConfigManager; +import pm.j4.petroleum.util.module.ModuleBase; + +/** + * The type Mod list mixin. + */ +@Mixin(InGameHud.class) +public abstract class ModListMixin extends DrawableHelper { + /** + * The Scaled height. + */ + @Shadow + private int scaledHeight; + /** + * The Client. + */ + private final MinecraftClient client; + + /** + * Gets font renderer. + * + * @return the font renderer + */ + @Shadow + public abstract TextRenderer getFontRenderer(); + + + /** + * Instantiates a new Mod list mixin. + * + * @param client the client + */ + public ModListMixin(MinecraftClient client) { + this.client = client; + } + + /** + * Render. + * + * @param matrices the matrices + * @param tickDelta the tick delta + * @param ci the ci + */ + @Inject(method = "render(Lnet/minecraft/client/util/math/MatrixStack;F)V", + at = @At("HEAD")) + public void render(MatrixStack matrices, float tickDelta, CallbackInfo ci) { + Optional config = ConfigManager.getConfig(); + if (config.isPresent() && + config.get().isModuleEnabled("petroleum.modlist") && + !this.client.options.hudHidden && + !this.client.options.debugEnabled) { + renderModuleList(matrices); + } + } + + /** + * Render module list. + * + * @param matrices the matrices + */ + private void renderModuleList(MatrixStack matrices) { + List modules = ModList.getActive(); + List activeModuleList = modules.stream().map(module -> module.getReadableName()).collect(Collectors.toList()); + int fontHeight = this.getFontRenderer().fontHeight; + int startHeight = this.scaledHeight - (activeModuleList.size() * (fontHeight + 4)); + for (int i = 0; i < activeModuleList.size(); i++) { + this.getFontRenderer().drawWithShadow(matrices, activeModuleList.get(i), 10, 10 + (i * (fontHeight + 4)), -1); + } + } +} diff --git a/remappedSrc/pm/j4/petroleum/mixin/OptionsMenuMixin.java b/remappedSrc/pm/j4/petroleum/mixin/OptionsMenuMixin.java new file mode 100644 index 0000000..be27f25 --- /dev/null +++ b/remappedSrc/pm/j4/petroleum/mixin/OptionsMenuMixin.java @@ -0,0 +1,42 @@ +package pm.j4.petroleum.mixin; + +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.options.OptionsScreen; +import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.text.Text; +import net.minecraft.text.TranslatableText; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import pm.j4.petroleum.gui.POptionsScreen; + +/** + * The type Options menu mixin. + */ +@Mixin(OptionsScreen.class) +public class OptionsMenuMixin extends Screen { + + /** + * Instantiates a new Options menu mixin. + * + * @param title the title + */ + protected OptionsMenuMixin(Text title) { + super(title); + } + + /** + * Init. + * + * @param ci the ci + */ + @Inject(at = @At(value = "TAIL"), + method = "init()V") + protected void init(CallbackInfo ci) { + this.addButton(new ButtonWidget(this.width / 2 - 75, this.height / 6 + 140, 150, 20, new TranslatableText("petroleum.options"), (buttonWidget) -> { + assert this.client != null; + this.client.openScreen(new POptionsScreen(this)); + })); + } +} diff --git a/remappedSrc/pm/j4/petroleum/mixin/TitleScreenMixin.java b/remappedSrc/pm/j4/petroleum/mixin/TitleScreenMixin.java new file mode 100644 index 0000000..e915a62 --- /dev/null +++ b/remappedSrc/pm/j4/petroleum/mixin/TitleScreenMixin.java @@ -0,0 +1,132 @@ +package pm.j4.petroleum.mixin; + +import java.util.Optional; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.TitleScreen; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.Text; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; +import pm.j4.petroleum.modules.splash.SplashText; +import pm.j4.petroleum.util.config.ConfigHolder; +import pm.j4.petroleum.util.config.ConfigManager; + + +/** + * Mixin attached to the TitleScreen. + * Currently, it is only used to display a string of text with the mod's version. + * Any other modules will likely extend the options screen or pause screen, + * so the module is unlikely to be used elsewhere. + */ +@Mixin(TitleScreen.class) +public class TitleScreenMixin extends Screen { + /** + * The Opacity. + */ + private double opacity = 0; + /** + * The Ascending. + */ + private boolean ascending = false; + + /** + * Stub method. + * Since the mixin injects itself into the *actual* TitleScreen used by the game, + * this should never run. + * + * @param title the title + */ + protected TitleScreenMixin(Text title) { + super(title); + } + + /** + * Mixin injection into the render method. + * It captures locals so that the text can be rendered alongside the + * screen fade-in. + * It injects before the call to @link com.mojang.bridge.game.GameVersion#getName() using INVOKE_ASSIGN, + * because attempting to use a regular invoke statement on @link net.minecraft.client.gui.DrawHelper#drawStringWithShadow() + * repeatedly failed. + *

+ * + * @param matrices the matrices + * @param mouseX the mouse x + * @param mouseY the mouse y + * @param delta the delta + * @param ci the ci + * @param f the f + * @param i the + * @param j the j + * @param g the g + * @param l the l + */ + @Inject(method = "render", + at = @At( + value = "INVOKE_ASSIGN", + target = "Lcom/mojang/bridge/game/GameVersion;getName()Ljava/lang/String;", + ordinal = 0), + locals = LocalCapture.CAPTURE_FAILSOFT) + private void render(MatrixStack matrices, int mouseX, int mouseY, float delta, CallbackInfo ci, float f, int i, int j, float g, int l) { + Optional config = ConfigManager.getConfig(); + if (config.isPresent() && config.get().isModuleEnabled("petroleum.splashtext")) { + drawStringWithShadow(matrices, this.textRenderer, SplashText.get(), 2, this.height - 20, blink(13108374) | l); + } + } + + /** + * fades an integer color based on the values declared at the top of the class. + * + * @param color the integer representation of the color to fade. this should generally remain constant. + * @return the color, adjusted for "opacity". It's RGB and not RGBA, so it just lowers all color values. + */ + @SuppressWarnings("SameParameterValue") + private int blink(int color) { + /* + The Speed. + */ + int speed = 3; + /* + The Opacity max. + */ + double opacity_max = 1000; + if (ascending) { + opacity += speed; + if (opacity > opacity_max) { + opacity = opacity_max; + ascending = false; + } + } else { + opacity -= speed; + /* + The Opacity min. + */ + double opacity_min = 500; + if (opacity < opacity_min) { + opacity = opacity_min; + ascending = true; + } + } + double opacityD = (opacity / opacity_max); + /* + The R mask. + */ + int r_mask = 16711680; + int r = ((color & r_mask) / Integer.parseInt("010000", 16)); + /* + The G mask. + */ + int g_mask = 65280; + int g = ((color & g_mask) / Integer.parseInt("000100", 16)); + /* + The B mask. + */ + int b_mask = 255; + int b = ((color & b_mask)); + return ((int) (r * opacityD) * Integer.parseInt("010000", 16)) | + ((int) (g * opacityD) * Integer.parseInt("000100", 16)) | + ((int) (b * opacityD)); + } +} diff --git a/remappedSrc/pm/j4/petroleum/modules/ExampleModule.java b/remappedSrc/pm/j4/petroleum/modules/ExampleModule.java new file mode 100644 index 0000000..0bb285a --- /dev/null +++ b/remappedSrc/pm/j4/petroleum/modules/ExampleModule.java @@ -0,0 +1,37 @@ +package pm.j4.petroleum.modules; + +import java.util.HashMap; +import java.util.Map; +import net.minecraft.client.MinecraftClient; +import pm.j4.petroleum.util.module.ModuleBase; +import pm.j4.petroleum.util.module.option.BooleanOption; +import pm.j4.petroleum.util.module.option.ConfigurationOption; + +/** + * The type Example module. + */ +public class ExampleModule extends ModuleBase { + /** + * example mod + */ + public ExampleModule() { + super("petroleum.example", + "petroleum.misc", + true, + false, + true); + } + + @Override + protected Map getDefaultConfig() { + Map options = new HashMap<>(); + options.put("petroleum.example_b_one", new BooleanOption("example")); + options.put("petroleum.example_b_two", new BooleanOption("example")); + return options; + } + + @Override + public void activate(MinecraftClient client) { + System.out.println("Example Mod Keybind Activate"); + } +} diff --git a/remappedSrc/pm/j4/petroleum/modules/bindings/BindingInfo.java b/remappedSrc/pm/j4/petroleum/modules/bindings/BindingInfo.java new file mode 100644 index 0000000..c147d8a --- /dev/null +++ b/remappedSrc/pm/j4/petroleum/modules/bindings/BindingInfo.java @@ -0,0 +1,30 @@ +package pm.j4.petroleum.modules.bindings; + +import net.minecraft.client.util.InputUtil; + +/** + * The type Binding info. + */ +public class BindingInfo { + /** + * The Translation key. + */ + public String translationKey; + /** + * The Type. + */ + public InputUtil.Type type; + /** + * The Key. + */ + public int key; + /** + * The Category. + */ + public String category; + + /** + * The Attached function id. + */ + public String attachedModuleName; +} diff --git a/remappedSrc/pm/j4/petroleum/modules/bindings/BindingManager.java b/remappedSrc/pm/j4/petroleum/modules/bindings/BindingManager.java new file mode 100644 index 0000000..c9af1ef --- /dev/null +++ b/remappedSrc/pm/j4/petroleum/modules/bindings/BindingManager.java @@ -0,0 +1,96 @@ +package pm.j4.petroleum.modules.bindings; + +import java.util.*; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.options.KeyBinding; +import net.minecraft.client.util.InputUtil; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.TranslatableText; +import org.lwjgl.glfw.GLFW; +import pm.j4.petroleum.PetroleumMod; +import pm.j4.petroleum.gui.PModuleConfigEntry; +import pm.j4.petroleum.util.config.ConfigManager; +import pm.j4.petroleum.util.config.GlobalConfig; +import pm.j4.petroleum.util.module.ModuleBase; +import pm.j4.petroleum.util.module.option.KeybindOption; + +/** + * The type Binding manager. + */ +public class BindingManager extends ModuleBase { + /** + * Instantiates a new Module base. + * Parameters should be constant across restarts. + */ + public BindingManager() { + super("petroleum.bindings", + "petroleum.misc", + false, + true, + true); + } + + @Override + public void init() { + registerBindings(); + super.init(); + } + + @Override + public List getConfigEntries() { + List entries = new ArrayList<>(); + + Map mapped = new HashMap<>(); + if (ConfigManager.getConfig().isPresent()) { + Map binds = ConfigManager.getConfig().get().globalConfig.bindings; + + binds.forEach((key, func) -> { + KeybindOption option = new KeybindOption(func.getModuleName() + " " + func.getCategory()); + option.fromKeybind(key, func); + mapped.put(option, func); + }); + } + mapped.forEach((configEntry, module) -> { + PModuleConfigEntry entry = new PModuleConfigEntry(configEntry, new TranslatableText(module.getModuleName())) { + //TODO keybinding. most likely involves mixin to take direct key input + // look into how keybinding in regular options screen works + @Override + public void render(MatrixStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) { + if (this.displayText != null) { + MinecraftClient.getInstance().textRenderer.drawWithShadow(matrices, displayText, x, y, 0xAAAAAA); + } + if (this.option != null) { + int fontHeight = MinecraftClient.getInstance().textRenderer.fontHeight; + MinecraftClient.getInstance().textRenderer.drawWithShadow(matrices, "Key Value: " + this.option.getStringValue(), x, y + fontHeight + 4, 0xFFFFFF); + } + } + }; + entries.add(entry); + }); + return entries; + } + + /** + * Register bindings. + */ + private void registerBindings() { + if (!ConfigManager.getConfig().isPresent()) { + return; + } + GlobalConfig c = ConfigManager.getConfig().get().globalConfig; + Optional mod = PetroleumMod.getMod("petroleum.modmenu"); + if (mod.isPresent() && !c.isBound(mod.get())) { + //TODO + // the only explicit keybinding (for now.) + // once the binding manager has been completed, + // this should be migrated there, as a default binding + KeyBinding binding = new KeyBinding( + "key.petroleum.togglemodmenu", + InputUtil.Type.KEYSYM, + GLFW.GLFW_KEY_RIGHT_CONTROL, + "category.petroleum" + ); + ConfigManager.getConfig().get().globalConfig.setBinding(binding, mod.get()); + } + } +} diff --git a/remappedSrc/pm/j4/petroleum/modules/list/ModList.java b/remappedSrc/pm/j4/petroleum/modules/list/ModList.java new file mode 100644 index 0000000..8c4bb9f --- /dev/null +++ b/remappedSrc/pm/j4/petroleum/modules/list/ModList.java @@ -0,0 +1,44 @@ +package pm.j4.petroleum.modules.list; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import jdk.nashorn.internal.runtime.options.Option; +import pm.j4.petroleum.PetroleumMod; +import pm.j4.petroleum.util.config.ConfigHolder; +import pm.j4.petroleum.util.config.ConfigManager; +import pm.j4.petroleum.util.module.ModuleBase; + +/** + * The type Mod list. + */ +public class ModList extends ModuleBase { + /** + * Instantiates a new Mod list. + */ + public ModList() { + super("petroleum.modlist", + "petroleum.misc", + true, + true, + true); + } + + /** + * Gets active. + * + * @return the active + */ + public static List getActive() { + List result = new ArrayList<>(); + Optional config = ConfigManager.getConfig(); + if(config.isPresent()) { + config.get().getEnabledModules().forEach((mod) -> { + if (!mod.isHidden()) { + result.add(mod); + } + }); + } + return result; + } +} diff --git a/remappedSrc/pm/j4/petroleum/modules/menu/ModMenu.java b/remappedSrc/pm/j4/petroleum/modules/menu/ModMenu.java new file mode 100644 index 0000000..7ed0500 --- /dev/null +++ b/remappedSrc/pm/j4/petroleum/modules/menu/ModMenu.java @@ -0,0 +1,98 @@ +package pm.j4.petroleum.modules.menu; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import net.minecraft.client.MinecraftClient; +import pm.j4.petroleum.gui.PModMenuScreen; +import pm.j4.petroleum.util.config.ConfigManager; +import pm.j4.petroleum.util.data.ButtonInformation; +import pm.j4.petroleum.util.data.Category; +import pm.j4.petroleum.util.module.ModuleBase; + +/** + * The type Mod menu. + */ +public class ModMenu extends ModuleBase { + + /** + * The constant coordinates. + */ + private static final Map coordinates = new HashMap<>(); + + /** + * Instantiates a new Mod menu. + */ + public ModMenu() { + super("petroleum.modmenu", + "petroleum.misc", + true, + true, + true); + } + + // TODO figure out resizing + // the number itself changes, so it should just be probably like some onResize bullshit in PModMenuScreen + @Override + public void init() { + Map> categories = Category.getCategoryMap(); + final double[] h = {.1}; + categories.forEach((category, moduleList) -> { + ButtonInformation conf = ConfigManager.getConfig().isPresent() ? + ConfigManager.getConfig().get().globalConfig.getButton(category) : + null; + ButtonInformation coord = conf != null ? conf : new ButtonInformation(.1, h[0], false); + h[0] += .01; + coordinates.put(category, coord); + if (ConfigManager.getConfig().isPresent()) { + ConfigManager.getConfig().get().globalConfig.setButton(category, coord); + } + }); + } + + /** + * Update coord. + * + * @param b the b + * @param c the c + */ + public static void updateCoord(String b, ButtonInformation c) { + if (c.x < 0.05) { + c.x = 0.05; + } + if (c.x > .95) { + c.x = .95; + } + if (c.y < 0.05) { + c.y = 0.05; + } + if (c.y > .95) { + c.y = .95; + } + if (coordinates.containsKey(b)) { + coordinates.replace(b, c); + if (ConfigManager.getConfig().isPresent()) { + ConfigManager.getConfig().get().globalConfig.setButton(b, c); + } + } + } + + @Override + public void activate(MinecraftClient client) { + this.toggle(); + if (ConfigManager.getConfig().get().isModuleEnabled(this.getModuleName())) { + client.openScreen(new PModMenuScreen()); + } else { + client.openScreen(null); + } + } + + /** + * Gets buttons. + * + * @return the buttons + */ + public static Map getButtons() { + return coordinates; + } +} \ No newline at end of file diff --git a/remappedSrc/pm/j4/petroleum/modules/splash/SplashText.java b/remappedSrc/pm/j4/petroleum/modules/splash/SplashText.java new file mode 100644 index 0000000..c5c60ae --- /dev/null +++ b/remappedSrc/pm/j4/petroleum/modules/splash/SplashText.java @@ -0,0 +1,56 @@ +package pm.j4.petroleum.modules.splash; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.options.KeyBinding; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.LiteralText; +import net.minecraft.text.Text; +import net.minecraft.text.TranslatableText; +import pm.j4.petroleum.PetroleumMod; +import pm.j4.petroleum.gui.PModuleConfigEntry; +import pm.j4.petroleum.util.config.ConfigManager; +import pm.j4.petroleum.util.module.ModuleBase; +import pm.j4.petroleum.util.module.option.BooleanOption; +import pm.j4.petroleum.util.module.option.ConfigurationOption; +import pm.j4.petroleum.util.module.option.KeybindOption; + +/** + * The type Splash text. + */ +public class SplashText extends ModuleBase { + /** + * Instantiates a new Splash text. + */ + public SplashText() { + super("petroleum.splashtext", + "petroleum.misc", + false, + true, + true); + } + + @Override + public List getConfigEntries() { + List entries = new ArrayList<>(); + ConfigurationOption activeToggle = new BooleanOption("Show the main menu version text:"); + PModuleConfigEntry activeEntry = new PModuleConfigEntry(activeToggle, new LiteralText("Active")); + entries.add(activeEntry); + return entries; + } + + /** + * Get string. + * + * @return the string + */ + public static String get() { + if (PetroleumMod.modData != null) { + return "Petroleum v" + PetroleumMod.modData.getVersion().getFriendlyString(); + } + return "Petroleum vUnknown"; + } +} diff --git a/remappedSrc/pm/j4/petroleum/modules/xray/Xray.java b/remappedSrc/pm/j4/petroleum/modules/xray/Xray.java new file mode 100644 index 0000000..7e31116 --- /dev/null +++ b/remappedSrc/pm/j4/petroleum/modules/xray/Xray.java @@ -0,0 +1,19 @@ +package pm.j4.petroleum.modules.xray; + +import pm.j4.petroleum.util.module.ModuleBase; + +/** + * The type Xray. + */ +public class Xray extends ModuleBase { + /** + * Instantiates a new Xray. + */ + public Xray() { + super("petroleum.xray", + "petroleum.render", + true, + false, + true); + } +} diff --git a/remappedSrc/pm/j4/petroleum/util/config/Config.java b/remappedSrc/pm/j4/petroleum/util/config/Config.java new file mode 100644 index 0000000..695be65 --- /dev/null +++ b/remappedSrc/pm/j4/petroleum/util/config/Config.java @@ -0,0 +1,59 @@ +package pm.j4.petroleum.util.config; + +import java.util.ArrayList; +import java.util.List; +import pm.j4.petroleum.PetroleumMod; +import pm.j4.petroleum.util.module.ModuleBase; + +/** + * The type Config. + */ +public abstract class Config { + /** + * The Enabled modules. + */ + public List enabledModules = new ArrayList<>(); + + /** + * Is enabled boolean. + * + * @param mod the mod + * @return the boolean + */ + public boolean isEnabled(String mod) { + return enabledModules.contains(mod); + } + + + /** + * Disable module. + * + * @param mod the mod + */ + public void disableModule(String mod) { + if (isEnabled(mod) && PetroleumMod.isActive(mod) && PetroleumMod.getMod(mod).isPresent()) { + ModuleBase moduleInfo = PetroleumMod.getMod(mod).get(); + if (moduleInfo.isActivatable()) { + enabledModules.remove(mod); + } + } + } + + /** + * Toggle module. + * + * @param mod the mod + */ + public void toggleModule(String mod) { + if (PetroleumMod.isActive(mod) && PetroleumMod.getMod(mod).isPresent()) { + ModuleBase moduleInfo = PetroleumMod.getMod(mod).get(); + if (moduleInfo.isActivatable()) { + if (isEnabled(mod)) { + enabledModules.remove(mod); + } else { + enabledModules.add(mod); + } + } + } + } +} diff --git a/remappedSrc/pm/j4/petroleum/util/config/ConfigHolder.java b/remappedSrc/pm/j4/petroleum/util/config/ConfigHolder.java new file mode 100644 index 0000000..531e90c --- /dev/null +++ b/remappedSrc/pm/j4/petroleum/util/config/ConfigHolder.java @@ -0,0 +1,102 @@ +package pm.j4.petroleum.util.config; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import pm.j4.petroleum.PetroleumMod; +import pm.j4.petroleum.util.module.ModuleBase; + +/** + * The type Config holder. + */ +public class ConfigHolder { + /** + * The Global config. + */ + public GlobalConfig globalConfig; + /** + * The Server configs. + */ + public Map serverConfigs; + + /** + * Is module enabled boolean. + * + * @param module the module + * @return the boolean + */ + public boolean isModuleEnabled(String module) { + + if (!PetroleumMod.isActive(module)) { + return false; + } + if (globalConfig.isEnabled(module)) { + return true; + } + String server = this.getServer(); + if (serverConfigs.containsKey(server)) { + return serverConfigs.get(server).isEnabled(module); + } + return false; + } + + /** + * Gets enabled modules. + * + * @return the enabled modules + */ + public List getEnabledModules() { + List modules = PetroleumMod.getActiveMods(); + return modules.stream().filter(module -> + isModuleEnabled(module.getModuleName()) + ).collect(Collectors.toList()); + } + + /** + * Gets server. + * + * @return the server + */ + public String getServer() { + return PetroleumMod.getServerAddress(); + } + + /** + * Toggle module. + * + * @param module the module + */ + public void toggleModule(String module) { + String server = this.getServer(); + if (serverConfigs.containsKey(server)) { + System.out.println("Toggling module " + module + " on server " + server); + serverConfigs.get(server).toggleModule(module); + } else { + globalConfig.toggleModule(module); + } + } + + /** + * Disable module. + * + * @param module the module + */ + public void disableModule(String module) { + String server = this.getServer(); + if (serverConfigs.containsKey(server)) { + System.out.println("disabling module " + module + " on server " + server); + serverConfigs.get(server).disableModule(module); + } else { + globalConfig.disableModule(module); + } + } + + /** + * Save module. + * + * @param module the module + */ + public static void saveModule(ModuleBase module) { + + } +} diff --git a/remappedSrc/pm/j4/petroleum/util/config/ConfigManager.java b/remappedSrc/pm/j4/petroleum/util/config/ConfigManager.java new file mode 100644 index 0000000..f44e8b6 --- /dev/null +++ b/remappedSrc/pm/j4/petroleum/util/config/ConfigManager.java @@ -0,0 +1,270 @@ +package pm.j4.petroleum.util.config; + +import com.google.common.reflect.TypeToken; +import com.google.gson.*; +import java.io.*; +import java.lang.reflect.Type; +import java.util.*; +import net.fabricmc.loader.api.FabricLoader; +import pm.j4.petroleum.PetroleumMod; +import pm.j4.petroleum.modules.bindings.BindingInfo; +import pm.j4.petroleum.modules.menu.ModMenu; +import pm.j4.petroleum.util.data.ButtonInformation; +import pm.j4.petroleum.util.data.ModuleConfig; +import pm.j4.petroleum.util.data.OptionSerializiable; +import pm.j4.petroleum.util.module.ModuleBase; + +/** + * The type Config manager. + */ +public class ConfigManager { + /** + * The constant GSON. + */ + public static final Gson GSON = new GsonBuilder() + .registerTypeAdapter(GlobalConfig.class, SerializationHelper.getGlobalSerializer()) + .registerTypeAdapter(GlobalConfig.class, SerializationHelper.getGlobalDeserializer()) + .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).setPrettyPrinting().create(); + /** + * The constant config. + */ + private static ConfigHolder config; + + /** + * Prepare config file. + * + * @param path the path + * @param filename the filename + * @return the file + */ + private static File prepareConfigFile(String path, String filename) { + if (path != "") { + File directory = new File(FabricLoader.getInstance().getConfigDir().toString(), path); + if (!directory.exists()) directory.mkdir(); + } + return new File(FabricLoader.getInstance().getConfigDir().toString(), path + filename); + } + + /** + * Init config. + */ + public static void initConfig() { + if (config != null) { + return; + } + + config = new ConfigHolder(); + config.globalConfig = new DefaultConfig(); + config.serverConfigs = new HashMap<>(); + + config = load("petroleum/", "petroleum.json", ConfigHolder.class); + initModules(); + } + + /** + * Init modules. + */ + public static void initModules() { + PetroleumMod.getActiveMods().forEach(module -> { + ModuleConfig options = load("petroleum/modules/", module.getModuleName() + ".json", ModuleConfig.class); + if (options != null && options.options != null) { + options.options.forEach((key, option) -> { + if (module.hasOption(option.key)) { + module.setConfigOption(option.key, option.value); + } + }); + } + }); + } + + /** + * Load. + * + * @param the type parameter + * @param path the path + * @param filename the filename + * @param tClass the t class + * @return the t + */ + private static T load(String path, String filename, Class tClass) { + File file = prepareConfigFile(path, filename); + + try { + if (!file.exists()) { + save(path, filename, tClass.newInstance()); + } + if (file.exists()) { + BufferedReader reader = new BufferedReader(new FileReader(file)); + T parsedConfig = null; + try { + parsedConfig = GSON.fromJson(reader, tClass); + } catch (Exception e) { + System.out.println("Couldn't parse config file"); + e.printStackTrace(); + } + if (parsedConfig != null) { + return parsedConfig; + } + } + } catch (FileNotFoundException | InstantiationException | IllegalAccessException e) { + System.out.println("Couldn't load configuration file at " + path); + e.printStackTrace(); + } + return null; + } + + /** + * Deserialize element t. + * + * @param the type parameter + * @param element the element + * @param tClass the t class + * @return the t + */ + public static T deserializeElement(JsonElement element, Class tClass) { + return GSON.fromJson(element, tClass); + } + + /** + * Save. + * + * @param the type parameter + * @param path the path + * @param filename the filename + * @param data the data + */ + private static void save(String path, String filename, T data) { + File file = prepareConfigFile(path, filename); + + String json = GSON.toJson(data); + try (FileWriter fileWriter = new FileWriter(file)) { + fileWriter.write(json); + } catch (IOException e) { + System.out.println("Couldn't save configuration file at " + path); + e.printStackTrace(); + } + } + + /** + * Save module. + * + * @param b the b + */ + public static void saveModule(ModuleBase b) { + ModuleConfig c = new ModuleConfig(); + c.options = GlobalConfig.serializeModuleConfiguration(b); + save("petroleum/modules/", b.getModuleName() + ".json", c); + } + + /** + * Save all modules. + */ + public static void saveAllModules() { + List mods = PetroleumMod.getActiveMods(); + mods.forEach(ConfigManager::saveModule); + } + + /** + * Save global config. + */ + public static void saveGlobalConfig() { + save("petroleum/", "petroleum.json", config); + } + + /** + * Gets config. + * + * @return the config + */ + public static Optional getConfig() { + if (config == null) { + return Optional.empty(); + } + return Optional.of(config); + } +} + +/** + * The type Serialization helper. + */ +class SerializationHelper { + + /** + * The constant s. + */ + private static final JsonSerializer GLOBAL_CONFIG_JSON_SERIALIZER = (src, typeOfSrc, ctx) -> { + JsonObject jsonConfig = new JsonObject(); + + JsonArray bindings = ctx.serialize(src.serializeBindings()).getAsJsonArray(); + jsonConfig.add("bindings", bindings); + + JsonArray modules = ctx.serialize(src.enabledModules).getAsJsonArray(); + jsonConfig.add("enabled_modules", modules); + + JsonObject tabCoordinates = new JsonObject(); + ModMenu.getButtons().forEach((category, coordinates) -> { + tabCoordinates.add(category, ctx.serialize(coordinates)); + }); + jsonConfig.add("button_coordinates", tabCoordinates); + + return jsonConfig; + }; + + /** + * The constant ds. + */ + private static final JsonDeserializer GLOBAL_CONFIG_JSON_DESERIALIZER = ((json, typeOfT, ctx) -> { + JsonObject obj = json.getAsJsonObject(); + + List bindings = new ArrayList<>(); + if (obj.has("bindings")) { + obj.get("bindings").getAsJsonArray().forEach(b -> bindings.add(ctx.deserialize(b, BindingInfo.class))); + } + List modules = new ArrayList<>(); + if (obj.has("enabled_modules")) { + obj.get("enabled_modules").getAsJsonArray().forEach(m -> modules.add(m.getAsString())); + } + GlobalConfig cfg = new GlobalConfig(); + Map> options; + Type type = new TypeToken>>() { + }.getType(); + if (obj.has("module_configuration")) { + options = ctx.deserialize(obj.get("module_configuration"), type); + } else { + options = new HashMap<>(); + } + if (obj.has("button_coordinates")) { + obj.get("button_coordinates").getAsJsonObject().entrySet().forEach( + value -> { + cfg.setButton(value.getKey(), ctx.deserialize(value.getValue(), ButtonInformation.class)); + } + ); + } + PetroleumMod.getActiveMods().forEach(module -> { + if (options.containsKey(module.getModuleName())) { + cfg.deserializeModuleConfiguration(options.get(module.getModuleName()), module); + } + }); + cfg.deserializeBindings(bindings); + cfg.enabledModules = modules; + return cfg; + }); + + /** + * Gets serializer. + * + * @return the serializer + */ + public static JsonSerializer getGlobalSerializer() { + return GLOBAL_CONFIG_JSON_SERIALIZER; + } + + /** + * Gets deserializer. + * + * @return the deserializer + */ + public static JsonDeserializer getGlobalDeserializer() { + return GLOBAL_CONFIG_JSON_DESERIALIZER; + } +} \ No newline at end of file diff --git a/remappedSrc/pm/j4/petroleum/util/config/DefaultConfig.java b/remappedSrc/pm/j4/petroleum/util/config/DefaultConfig.java new file mode 100644 index 0000000..f50bea2 --- /dev/null +++ b/remappedSrc/pm/j4/petroleum/util/config/DefaultConfig.java @@ -0,0 +1,15 @@ +package pm.j4.petroleum.util.config; + +import java.util.Collections; + +/** + * The type Default config. + */ +public class DefaultConfig extends GlobalConfig { + /** + * Instantiates a new Default config. + */ + public DefaultConfig() { + this.enabledModules = Collections.singletonList("petroleum.splashtext"); + } +} diff --git a/remappedSrc/pm/j4/petroleum/util/config/GlobalConfig.java b/remappedSrc/pm/j4/petroleum/util/config/GlobalConfig.java new file mode 100644 index 0000000..91d7b07 --- /dev/null +++ b/remappedSrc/pm/j4/petroleum/util/config/GlobalConfig.java @@ -0,0 +1,189 @@ +package pm.j4.petroleum.util.config; + +import java.util.*; +import java.util.concurrent.atomic.AtomicBoolean; +import net.minecraft.client.options.KeyBinding; +import net.minecraft.client.util.InputUtil; +import pm.j4.petroleum.PetroleumMod; +import pm.j4.petroleum.modules.bindings.BindingInfo; +import pm.j4.petroleum.util.data.ButtonInformation; +import pm.j4.petroleum.util.data.OptionSerializiable; +import pm.j4.petroleum.util.module.ModuleBase; +import pm.j4.petroleum.util.module.option.ConfigurationOption; + +/** + * The type Global config. + */ +public class GlobalConfig extends Config { + /** + * The Bindings. + */ + public final Map bindings = new HashMap<>(); + + /** + * Is bound boolean. + * + * @param func the func + * @return the boolean + */ + public boolean isBound(ModuleBase func) { + AtomicBoolean found = new AtomicBoolean(false); + bindings.forEach((key, binding) -> { + if (binding.equals(func)) { + found.set(true); + } + }); + return found.get(); + } + + /** + * Sets binding. + * + * @param bind the bind + * @param func the func + */ + public void setBinding(KeyBinding bind, ModuleBase func) { + if (bindings.containsValue(func)) { + bindings.forEach((key, binding) -> { + if (binding.equals(func)) { + PetroleumMod.removeBind(key); + bindings.remove(key); + } + }); + } + + if (PetroleumMod.isActive(func.getModuleName())) { + PetroleumMod.addBind(bind); + bindings.put(bind, func); + } + } + + /** + * Convert binding. + * + * @param info the info + */ + private void convertBinding(BindingInfo info) { + Optional match = PetroleumMod.getMod(info.attachedModuleName); + match.ifPresent(moduleBase -> setBinding(reconstructBinding(info), + moduleBase)); + } + + /** + * Reconstruct binding key binding. + * + * @param info the info + * @return the key binding + */ + public static KeyBinding reconstructBinding(BindingInfo info) { + return new KeyBinding( + info.translationKey, + info.type, + info.key, + info.category + ); + } + + /** + * Extract binding info. + * + * @param b the b + * @param f the f + * @return the binding info + */ + public static BindingInfo extractBinding(KeyBinding b, ModuleBase f) { + BindingInfo res = new BindingInfo(); + res.attachedModuleName = f.getModuleName(); + + res.translationKey = b.getTranslationKey(); + InputUtil.Key k = b.getDefaultKey(); + res.type = k.getCategory(); + res.key = k.getCode(); + res.category = b.getCategory(); + + return res; + } + + /** + * Serialize bindings list. + * + * @return the list + */ + public List serializeBindings() { + List b = new ArrayList<>(); + bindings.forEach((k, f) -> b.add(extractBinding(k, f))); + return b; + } + + /** + * Deserialize bindings. + * + * @param info the info + */ + public void deserializeBindings(List info) { + info.forEach(this::convertBinding); + } + + /** + * Serialize module configuration list. + * + * @param module the module + * @return the list + */ + public static Map serializeModuleConfiguration(ModuleBase module) { + Map opts = new HashMap<>(); + Map configuration = module.getModuleConfiguration(); + configuration.forEach((key, value) -> { + opts.put(key, new OptionSerializiable(key, value.toJson())); + }); + return opts; + } + + /** + * Deserialize module configuration. + * + * @param opts the opts + * @param module the module + */ + public void deserializeModuleConfiguration(List opts, ModuleBase module) { + opts.forEach(option -> { + if (module.hasOption(option.key)) { + module.setConfigOption(option.key, option.value); + } + }); + } + + /** + * The Button locations. + */ + private final Map buttonLocations = new HashMap<>(); + + /** + * Sets button. + * + * @param category the category + * @param buttonInformation the button information + */ + public void setButton(String category, ButtonInformation buttonInformation) { + if (buttonLocations.containsKey(category)) { + buttonLocations.replace(category, buttonInformation); + } else { + buttonLocations.put(category, buttonInformation); + } + } + + /** + * Gets button. + * + * @param category the category + * @return the button + */ + public ButtonInformation getButton(String category) { + if (buttonLocations.containsKey(category)) { + return buttonLocations.get(category); + } + System.out.println("Could not find button of category " + category); + return null; + } +} + diff --git a/remappedSrc/pm/j4/petroleum/util/config/ServerConfig.java b/remappedSrc/pm/j4/petroleum/util/config/ServerConfig.java new file mode 100644 index 0000000..9df6464 --- /dev/null +++ b/remappedSrc/pm/j4/petroleum/util/config/ServerConfig.java @@ -0,0 +1,11 @@ +package pm.j4.petroleum.util.config; + +/** + * The type Server config. + */ +public class ServerConfig extends Config { + /** + * The Address. + */ + public String address = ""; +} diff --git a/remappedSrc/pm/j4/petroleum/util/data/ButtonInformation.java b/remappedSrc/pm/j4/petroleum/util/data/ButtonInformation.java new file mode 100644 index 0000000..e4ff031 --- /dev/null +++ b/remappedSrc/pm/j4/petroleum/util/data/ButtonInformation.java @@ -0,0 +1,32 @@ +package pm.j4.petroleum.util.data; + +/** + * The type Button information. + */ +public class ButtonInformation { + /** + * The X. + */ + public double x; + /** + * The Y. + */ + public double y; + /** + * The Open. + */ + public boolean open; + + /** + * Instantiates a new Button information. + * + * @param x the x + * @param y the y + * @param open the open + */ + public ButtonInformation(double x, double y, boolean open) { + this.x = x; + this.y = y; + this.open = open; + } +} diff --git a/remappedSrc/pm/j4/petroleum/util/data/Category.java b/remappedSrc/pm/j4/petroleum/util/data/Category.java new file mode 100644 index 0000000..c2210a5 --- /dev/null +++ b/remappedSrc/pm/j4/petroleum/util/data/Category.java @@ -0,0 +1,47 @@ +package pm.j4.petroleum.util.data; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import pm.j4.petroleum.PetroleumMod; +import pm.j4.petroleum.util.module.ModuleBase; + +/** + * The type Category. + */ +public class Category { + /** + * Gets category map. + * + * @return the category map + */ + public static Map> getCategoryMap() { + List modules = PetroleumMod.getActiveMods(); + Map> categoryMap = new HashMap<>(); + modules.forEach(module -> { + if (!categoryMap.containsKey(module.getCategory())) { + List m = new ArrayList<>(); + m.add(module); + categoryMap.put(module.getCategory(), m); + } else { + List m = categoryMap.get(module.getCategory()); + List nm = new ArrayList<>(); + nm.addAll(m); + nm.add(module); + categoryMap.replace(module.getCategory(), nm); + } + }); + return categoryMap; + } + + /** + * Gets by category. + * + * @param category the category + * @return the by category + */ + public static List getByCategory(String category) { + return getCategoryMap().containsKey(category) ? getCategoryMap().get(category) : new ArrayList<>(); + } +} diff --git a/remappedSrc/pm/j4/petroleum/util/data/ModuleConfig.java b/remappedSrc/pm/j4/petroleum/util/data/ModuleConfig.java new file mode 100644 index 0000000..33c1365 --- /dev/null +++ b/remappedSrc/pm/j4/petroleum/util/data/ModuleConfig.java @@ -0,0 +1,13 @@ +package pm.j4.petroleum.util.data; + +import java.util.Map; + +/** + * The type Module config. + */ +public class ModuleConfig { + /** + * The Options. + */ + public Map options; +} diff --git a/remappedSrc/pm/j4/petroleum/util/data/OptionSerializiable.java b/remappedSrc/pm/j4/petroleum/util/data/OptionSerializiable.java new file mode 100644 index 0000000..197332f --- /dev/null +++ b/remappedSrc/pm/j4/petroleum/util/data/OptionSerializiable.java @@ -0,0 +1,28 @@ +package pm.j4.petroleum.util.data; + +import com.google.gson.JsonElement; + +/** + * The type Option serializiable. + */ +public class OptionSerializiable { + /** + * Instantiates a new Option serializiable. + * + * @param key the key + * @param value the value + */ + public OptionSerializiable(String key, JsonElement value) { + this.value = value; + this.key = key; + } + + /** + * The Value. + */ + public final JsonElement value; + /** + * The Key. + */ + public final String key; +} diff --git a/remappedSrc/pm/j4/petroleum/util/module/ModuleBase.java b/remappedSrc/pm/j4/petroleum/util/module/ModuleBase.java new file mode 100644 index 0000000..514405c --- /dev/null +++ b/remappedSrc/pm/j4/petroleum/util/module/ModuleBase.java @@ -0,0 +1,229 @@ +package pm.j4.petroleum.util.module; + +import com.google.gson.JsonElement; +import java.util.*; +import net.minecraft.client.MinecraftClient; +import net.minecraft.text.TranslatableText; +import pm.j4.petroleum.gui.PModuleConfigEntry; +import pm.j4.petroleum.util.config.ConfigHolder; +import pm.j4.petroleum.util.config.ConfigManager; +import pm.j4.petroleum.util.module.option.ConfigurationOption; + +/** + * The Basis for all mods, used so that modules all have a common activation point and settings. + */ +public abstract class ModuleBase { + + /** + * Instantiates a new Module base. + * Parameters should be constant across restarts. + * + * @param name The name of the module + * @param category the category + * @param activatable Whether a module can be activated, or if it will remain in the state it was upon startup + * @param hidden Whether the module will show up in @link pm.j4.petroleum.modules.menu.ModMenu or the active module list + * @param hasConfigMenu whether a button in the configuration menu will show + */ + public ModuleBase(String name, String category, boolean activatable, boolean hidden, boolean hasConfigMenu) { + this.moduleName = name; + this.category = category; + this.readableName = new TranslatableText(name); + this.activatable = activatable; + this.hidden = hidden; + this.hasConfigMenu = hasConfigMenu; + this.moduleOptions = this.getDefaultConfig(); + } + + /** + * Init. + */ + public void init() { + + } + + /** + * Activate. Should be overridden. + * + * @param client the client + */ + public void activate(MinecraftClient client) { + this.toggle(); + } + + /** + * Toggle mod. + */ + public void toggle() { + Optional config = ConfigManager.getConfig(); + config.ifPresent(configHolder -> configHolder.toggleModule(this.moduleName)); + } + + /** + * The Module's name. + */ + private final String moduleName; + + /** + * Gets module name. + * + * @return the module name + */ + public String getModuleName() { + return this.moduleName; + } + + /** + * The Category. + */ + private final String category; + + /** + * Gets category. + * + * @return the category + */ + public String getCategory() { + return this.category; + } + + /** + * The Readable name. + */ + private final TranslatableText readableName; + + /** + * Gets readable name. + * + * @return the readable name + */ + public TranslatableText getReadableName() { + return this.readableName; + } + + /** + * The Activatable. + */ + private final boolean activatable; + + /** + * Is activatable boolean. + * + * @return the boolean + */ + public boolean isActivatable() { + return activatable; + } + + /** + * The Hidden. + */ + private final boolean hidden; + + /** + * Is hidden boolean. + * + * @return the boolean + */ + public boolean isHidden() { + return hidden; + } + + + /** + * The Has config menu. + */ + private final boolean hasConfigMenu; + + /** + * Configurable boolean. + * + * @return the boolean + */ + public boolean configurable() { + return hasConfigMenu; + } + + /** + * The Module options. + */ + private final Map moduleOptions; + + /** + * Gets module configuration. + * + * @return the module configuration + */ + public Map getModuleConfiguration() { + return moduleOptions; + } + + /** + * Sets config option. + * This will fail if the option is not already present in a module. + *

+ * + * @param key the key + * @param value the value + * @return whether the operation was successful. + */ + public boolean setConfigOption(String key, JsonElement value) { + if (moduleOptions.containsKey(key)) { + moduleOptions.get(key).fromJson(value); + return true; + } + return false; + } + + /** + * Has option boolean. + * + * @param key the key + * @return the boolean + */ + public boolean hasOption(String key) { + return moduleOptions.containsKey(key); + } + + /** + * Gets default config. + * + * @return the default config + */ + protected Map getDefaultConfig() { + return new HashMap<>(); + } + + /** + * Gets config option. + * + * @param key the key + * @return the config option + */ + public Optional getConfigOption(String key) { + if (moduleOptions.containsKey(key)) { + return Optional.of(moduleOptions.get(key)); + } + return Optional.empty(); + } + + /** + * Gets config entries. + * + * @return the config entries + */ + public List getConfigEntries() { + List entries = new ArrayList<>(); + this.getModuleConfiguration().forEach((name, option) -> entries.add(new PModuleConfigEntry(option, new TranslatableText(name)))); + return entries; + } + + /** + * Equals boolean. + * + * @param other the other + * @return the boolean + */ + public boolean equals(ModuleBase other) { + return Objects.equals(this.moduleName, other.getModuleName()); + } +} diff --git a/remappedSrc/pm/j4/petroleum/util/module/option/BooleanOption.java b/remappedSrc/pm/j4/petroleum/util/module/option/BooleanOption.java new file mode 100644 index 0000000..1a33c41 --- /dev/null +++ b/remappedSrc/pm/j4/petroleum/util/module/option/BooleanOption.java @@ -0,0 +1,38 @@ +package pm.j4.petroleum.util.module.option; + +import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; + +/** + * The type Boolean value. + */ +public class BooleanOption extends ConfigurationOption { + /** + * The Value. + */ + private boolean value; + + /** + * Instantiates a new Boolean option. + * + * @param description the description + */ + public BooleanOption(String description) { + super(description); + } + + @Override + public String getStringValue() { + return Boolean.toString(value); + } + + @Override + public void fromJson(JsonElement e) { + this.value = e.getAsBoolean(); + } + + @Override + public JsonElement toJson() { + return new JsonPrimitive(value); + } +} diff --git a/remappedSrc/pm/j4/petroleum/util/module/option/ConfigurationOption.java b/remappedSrc/pm/j4/petroleum/util/module/option/ConfigurationOption.java new file mode 100644 index 0000000..629cc35 --- /dev/null +++ b/remappedSrc/pm/j4/petroleum/util/module/option/ConfigurationOption.java @@ -0,0 +1,59 @@ +package pm.j4.petroleum.util.module.option; + +import com.google.gson.JsonElement; + +/** + * The type Configuration option. + */ +public abstract class ConfigurationOption { + /** + * The Description. + */ + private final String description; + + /** + * Instantiates a new Configuration option. + * + * @param description the description + */ + protected ConfigurationOption(String description) { + this.description = description; + } + + /** + * Gets description. + * + * @return the description + */ + public final String getDescription() { + return this.description; + } + + /** + * Gets string value. + * + * @return the string value + */ + public abstract String getStringValue(); + + /** + * From json. + * + * @param e the e + */ + public abstract void fromJson(JsonElement e); + + /** + * To json json element. + * + * @return the json element + */ + public abstract JsonElement toJson(); + + /** + * Update. + */ + public void update() { + + } +} diff --git a/remappedSrc/pm/j4/petroleum/util/module/option/IntegerOption.java b/remappedSrc/pm/j4/petroleum/util/module/option/IntegerOption.java new file mode 100644 index 0000000..b39718d --- /dev/null +++ b/remappedSrc/pm/j4/petroleum/util/module/option/IntegerOption.java @@ -0,0 +1,38 @@ +package pm.j4.petroleum.util.module.option; + +import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; + +/** + * The type Integer value. + */ +public class IntegerOption extends ConfigurationOption { + /** + * The Value. + */ + private int value; + + /** + * Instantiates a new Integer option. + * + * @param description the description + */ + protected IntegerOption(String description) { + super(description); + } + + @Override + public String getStringValue() { + return Integer.toString(value); + } + + @Override + public void fromJson(JsonElement e) { + this.value = e.getAsInt(); + } + + @Override + public JsonElement toJson() { + return new JsonPrimitive(value); + } +} diff --git a/remappedSrc/pm/j4/petroleum/util/module/option/KeybindOption.java b/remappedSrc/pm/j4/petroleum/util/module/option/KeybindOption.java new file mode 100644 index 0000000..b39f6ab --- /dev/null +++ b/remappedSrc/pm/j4/petroleum/util/module/option/KeybindOption.java @@ -0,0 +1,60 @@ +package pm.j4.petroleum.util.module.option; + +import com.google.gson.JsonElement; +import net.minecraft.client.options.KeyBinding; +import pm.j4.petroleum.modules.bindings.BindingInfo; +import pm.j4.petroleum.util.config.ConfigManager; +import pm.j4.petroleum.util.config.GlobalConfig; +import pm.j4.petroleum.util.module.ModuleBase; + +/** + * The type Keybind value. + */ +public class KeybindOption extends ConfigurationOption { + + /** + * The Value. + */ + private KeyBinding value; + /** + * The Converted value. + */ + private BindingInfo convertedValue; + + /** + * Instantiates a new Keybind option. + * + * @param description the description + */ + public KeybindOption(String description) { + super(description); + } + + @Override + public String getStringValue() { + return value.getDefaultKey().getLocalizedText().getString(); + } + + @Override + public void fromJson(JsonElement e) { + BindingInfo bindingInfo = ConfigManager.deserializeElement(e, BindingInfo.class); + this.convertedValue = bindingInfo; + this.value = GlobalConfig.reconstructBinding(bindingInfo); + } + + @Override + public JsonElement toJson() { + return null; + } + + /** + * From keybind. + * + * @param bind the bind + * @param base the base + */ + public void fromKeybind(KeyBinding bind, ModuleBase base) { + this.value = bind; + this.convertedValue = GlobalConfig.extractBinding(bind, base); + } +} diff --git a/remappedSrc/pm/j4/petroleum/util/module/option/ListOption.java b/remappedSrc/pm/j4/petroleum/util/module/option/ListOption.java new file mode 100644 index 0000000..2b37c29 --- /dev/null +++ b/remappedSrc/pm/j4/petroleum/util/module/option/ListOption.java @@ -0,0 +1,32 @@ +package pm.j4.petroleum.util.module.option; + +import com.google.gson.JsonElement; + +/** + * The type List option. + */ +public class ListOption extends ConfigurationOption { + /** + * Instantiates a new List option. + * + * @param description the description + */ + protected ListOption(String description) { + super(description); + } + + @Override + public String getStringValue() { + return "ListObject"; + } + + @Override + public void fromJson(JsonElement e) { + + } + + @Override + public JsonElement toJson() { + return null; + } +} diff --git a/remappedSrc/pm/j4/petroleum/util/module/option/StringOption.java b/remappedSrc/pm/j4/petroleum/util/module/option/StringOption.java new file mode 100644 index 0000000..174d056 --- /dev/null +++ b/remappedSrc/pm/j4/petroleum/util/module/option/StringOption.java @@ -0,0 +1,38 @@ +package pm.j4.petroleum.util.module.option; + +import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; + +/** + * The type String value. + */ +public class StringOption extends ConfigurationOption { + + /** + * The Value. + */ + private String value; + + /** + * Instantiates a new String option. + * + * @param description the description + */ + protected StringOption(String description) { + super(description); + } + + public String getStringValue() { + return value; + } + + @Override + public void fromJson(JsonElement e) { + this.value = e.getAsString(); + } + + @Override + public JsonElement toJson() { + return new JsonPrimitive(value); + } +} diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..5b60df3 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,10 @@ +pluginManagement { + repositories { + jcenter() + maven { + name = 'Fabric' + url = 'https://maven.fabricmc.net/' + } + gradlePluginPortal() + } +} diff --git a/src/main/java/pm/j4/petroleum/PetroleumMod.java b/src/main/java/pm/j4/petroleum/PetroleumMod.java new file mode 100644 index 0000000..ce543eb --- /dev/null +++ b/src/main/java/pm/j4/petroleum/PetroleumMod.java @@ -0,0 +1,168 @@ +package pm.j4.petroleum; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.fabricmc.loader.api.FabricLoader; +import net.fabricmc.loader.api.ModContainer; +import net.fabricmc.loader.api.metadata.ModMetadata; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.options.KeyBinding; +import net.minecraft.server.integrated.IntegratedServer; +import pm.j4.petroleum.modules.ExampleModule; +import pm.j4.petroleum.modules.bindings.BindingManager; +import pm.j4.petroleum.modules.list.ModList; +import pm.j4.petroleum.modules.menu.ModMenu; +import pm.j4.petroleum.modules.splash.SplashText; +import pm.j4.petroleum.modules.xray.Xray; +import pm.j4.petroleum.util.config.ConfigHolder; +import pm.j4.petroleum.util.config.ConfigManager; +import pm.j4.petroleum.util.module.ModuleBase; + + +//TODO: +// petroleum module checklist +// [ ] xray (lol) +// [ ] combat stuff. killaura, anti knockback, etc +// [ ] render stuff. tracers, nametags +// [ ] wurst taco. but a fish +// [ ] elytra fly +// [ ] movement stuff. nofall, jesus, speed +// [ ] elytra bhop +// [ ] boatfly +// [ ] anti anti cheat + +/** + * The type Petroleum mod. + */ +public class PetroleumMod implements ModInitializer { + /** + * The Mod data. + */ + public static ModMetadata modData = null; + /** + * The constant client. + */ + private static MinecraftClient client; + /** + * The constant activeMods. + */ + private static final List activeMods = Arrays.asList( + new SplashText(), + new ModMenu(), + new ModList(), + new BindingManager(), + new ExampleModule(), + new Xray() + ); + + /** + * Is active boolean. + * + * @param modName the mod name + * @return the boolean + */ + public static boolean isActive(String modName) { + return activeMods.stream().anyMatch(mod -> mod.getModuleName().equals(modName)); + } + + /** + * Gets mod. + * + * @param modName the mod name + * @return the mod + */ + public static Optional getMod(String modName) { + return activeMods.stream().filter(mod -> mod.getModuleName().equals(modName)).findFirst(); + } + + /** + * Gets active mods. + * + * @return the active mods + */ + public static List getActiveMods() { + return activeMods; + } + + /** + * The constant registeredBinds. + */ + private static final List registeredBinds = new ArrayList<>(); + + /** + * Add bind. + * + * @param b the b + */ + public static void addBind(KeyBinding b) { + registeredBinds.add(b); + } + + /** + * Remove bind. + * + * @param b the b + */ + public static void removeBind(KeyBinding b) { + registeredBinds.remove(b); + } + + /** + * Gets active keybinds. + * + * @return the active keybinds + */ + public static List getActiveKeybinds() { + return registeredBinds; + } + + /** + * Gets server address. + * + * @return the server address + */ + public static String getServerAddress() { + if (client != null && client.getServer() != null) { + IntegratedServer server = client.getServer(); + if (!server.isRemote()) { + return "localhost"; + } + if (server.isRemote() && !server.getServerIp().isEmpty()) { + return server.getServerIp(); + } + } + return null; + } + + @Override + public void onInitialize() { + + ConfigManager.initConfig(); + + // always update mod data + Optional modContainer = FabricLoader.getInstance().getModContainer("petroleum"); + modContainer.ifPresent(container -> modData = container.getMetadata()); + + Optional conf = ConfigManager.getConfig(); + + + //initialize any keybinds, data, etc. + activeMods.forEach(ModuleBase::init); + + //initialize keybind handler + conf.ifPresent(configHolder -> ClientTickEvents.END_CLIENT_TICK.register(client -> { + if (PetroleumMod.client != client) { + PetroleumMod.client = client; + } + for (KeyBinding b : PetroleumMod.getActiveKeybinds()) { + while (b.wasPressed()) { + configHolder.globalConfig.bindings.get(b).activate(client); + } + } + })); + } +} diff --git a/src/main/java/pm/j4/petroleum/gui/PModMenuScreen.java b/src/main/java/pm/j4/petroleum/gui/PModMenuScreen.java new file mode 100644 index 0000000..4ea2711 --- /dev/null +++ b/src/main/java/pm/j4/petroleum/gui/PModMenuScreen.java @@ -0,0 +1,69 @@ +package pm.j4.petroleum.gui; + +import com.mojang.blaze3d.systems.RenderSystem; +import java.util.Map; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.render.BufferBuilder; +import net.minecraft.client.render.Tessellator; +import net.minecraft.client.render.VertexFormats; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.TranslatableText; +import pm.j4.petroleum.modules.menu.ModMenu; +import pm.j4.petroleum.util.config.ConfigManager; +import pm.j4.petroleum.util.data.ButtonInformation; +import pm.j4.petroleum.util.data.Category; + +/** + * The type P mod menu screen. + */ +public class PModMenuScreen extends Screen { + /** + * Instantiates a new P mod menu screen. + */ + public PModMenuScreen() { + super(new TranslatableText("petroleum.modmenu")); + } + + @Override + public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { + this.renderBackground(matrices); + super.render(matrices, mouseX, mouseY, delta); + } + + @Override + protected void init() { + Map coordinateMap = ModMenu.getButtons(); + coordinateMap.forEach((category, coord) -> { + this.addButton(new PMovableButton((int) (coord.x * this.width), + (int) (coord.y * this.height), + category, + Category.getByCategory(category), + coord.open, + this)); + }); + } + + @Override + public void onClose() { + if (ConfigManager.getConfig().isPresent()) { + ConfigManager.getConfig().get().disableModule("petroleum.modmenu"); + this.buttons.forEach(button -> ((PMovableButton) button).updateCoordinate()); + ConfigManager.saveGlobalConfig(); + } + super.onClose(); + } + + @Override + public void renderBackground(MatrixStack matrices) { + Tessellator t_1 = Tessellator.getInstance(); + BufferBuilder buffer = t_1.getBuffer(); + RenderSystem.enableBlend(); + buffer.begin(7, VertexFormats.POSITION_COLOR); + buffer.vertex(0, this.height, 0.0D).color(0.1F, 0.1F, 0.1F, 0.3F).next(); + buffer.vertex(this.width, this.height, 0.0D).color(0.1F, 0.1F, 0.1F, 0.3F).next(); + buffer.vertex(this.width, 0, 0.0D).color(0.1F, 0.1F, 0.1F, 0.3F).next(); + buffer.vertex(0, 0, 0.0D).color(0.1F, 0.1F, 0.1F, 0.3F).next(); + t_1.draw(); + RenderSystem.disableBlend(); + } +} diff --git a/src/main/java/pm/j4/petroleum/gui/PModuleConfigEntry.java b/src/main/java/pm/j4/petroleum/gui/PModuleConfigEntry.java new file mode 100644 index 0000000..0d99ed0 --- /dev/null +++ b/src/main/java/pm/j4/petroleum/gui/PModuleConfigEntry.java @@ -0,0 +1,194 @@ +package pm.j4.petroleum.gui; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.Element; +import net.minecraft.client.gui.widget.AbstractButtonWidget; +import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.gui.widget.ElementListWidget; +import net.minecraft.client.options.KeyBinding; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.LiteralText; +import net.minecraft.text.Text; +import pm.j4.petroleum.util.config.ConfigHolder; +import pm.j4.petroleum.util.config.ConfigManager; +import pm.j4.petroleum.util.module.option.BooleanOption; +import pm.j4.petroleum.util.module.option.ConfigurationOption; +import pm.j4.petroleum.util.module.option.KeybindOption; +import pm.j4.petroleum.util.module.option.ListOption; + +/** + * The type P module config entry. + */ +public class PModuleConfigEntry extends ElementListWidget.Entry { + /** + * The Option. + */ + protected ConfigurationOption option; + /** + * The Display text. + */ + protected final Text displayText; + + private PModuleConfigPane parent; + + private List elements = new ArrayList<>(); + + private String trueValue; + private String falseValue; + + private Element selected; + + /** + * Instantiates a new P module config entry. + * + * @param option the option + * @param text the text + */ + public PModuleConfigEntry(ConfigurationOption option, Text text, PModuleConfigPane parent) { + this.option = option; + this.displayText = text; + this.parent = parent; + this.trueValue = "Yes"; + this.falseValue = "No"; + } + + public PModuleConfigEntry(ConfigurationOption option, Text text, PModuleConfigPane parent, String trueValue, String falseValue) { + this.option = option; + this.displayText = text; + this.parent = parent; + this.trueValue = trueValue; + this.falseValue = falseValue; + } + + @Override + public List children() { + return elements; + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + if (this.isMouseOver(mouseX, mouseY)) { + this.parent.setSelected(this); + System.out.println(displayText.getString() + " clicked"); + String className = option.getClass().toString(); + elements.forEach((widget) -> { + if (widget.mouseClicked(mouseX, mouseY, button)) { + System.out.println("Button clicked"); + selected = widget; + } + }); + return true; + } + return false; + } + + @Override + public boolean mouseReleased(double mouseX, double mouseY, int button) { + return this.isMouseOver(mouseX, mouseY); + } + + @Override + public boolean keyPressed(int keyCode, int scanCode, int modifiers) { + if(this.selected != null) { + return this.selected.keyPressed(keyCode, scanCode, modifiers); + } + return false; + } + + @Override + public boolean keyReleased(int keyCode, int scanCode, int modifiers) { + if(this.selected != null) { + return this.selected.keyReleased(keyCode, scanCode, modifiers); + } + return false; + } + + @Override + public void render(MatrixStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) { + if (this.displayText != null) { + MinecraftClient.getInstance().textRenderer.drawWithShadow(matrices, displayText, x, y, 0xAAAAAA); + } + System.out.println(option); + if (this.option != null) { + //TODO option text box (?) + // option should be centered or otherwise offset + // but not extend past the side of the pane + int fontHeight = MinecraftClient.getInstance().textRenderer.fontHeight; + //TODO use TranslatableText instead of LiteralText + MinecraftClient.getInstance().textRenderer.drawWithShadow(matrices, new LiteralText(option.getDescription() + " " + option.getStringValue()), x, y + fontHeight + 4, 0xFFFFFF); + + System.out.println(elements.size()); + if(elements.size() == 0) { + String className = option.getClass().toString(); + System.out.println(className); + if (className.equals(BooleanOption.class.toString())) { + System.out.println("boolean"); + elements.add(new ButtonWidget(x, y + (int)(fontHeight * 2.5), + entryWidth, + fontHeight * 2, + new LiteralText(((BooleanOption)option).getValue() ? this.trueValue : this.falseValue), (button) -> { + button.setMessage(new LiteralText((!((BooleanOption)option).getValue()) ? this.trueValue : this.falseValue)); + BooleanOption newValue = new BooleanOption(option.getConfigKey(), option.getDescription(), option.getParent()); + newValue.setValue((!((BooleanOption)option).getValue())); + option.getParent().updateConfigOption(newValue.getConfigKey(), newValue); + this.option = newValue; + })); + } + else if (className.equals(ListOption.class.toString())) { + // TODO: determine whether list options are viable, + // considering that it would be easier to split lists into multiple PModuleConfigEntries + System.out.println("list"); + } + else if (className.equals(KeybindOption.class.toString())) { + System.out.println("keybind"); + ButtonWidget bindButton = new ButtonWidget(x, y + (int)(fontHeight * 2.5), + entryWidth, + fontHeight * 2, + new LiteralText(option.getStringValue().toUpperCase()), (button) -> { + button.setMessage(new LiteralText("Press any key...")); + }) { + @Override + public boolean keyPressed(int keyCode, int scanCode, int modifiers) { + if (this.active && this.visible) { + //TODO + if (keyCode != 257 && keyCode != 32 && keyCode != 335) { + KeybindOption newValue = new KeybindOption(option.getConfigKey(), option.getDescription(), option.getParent()); + KeyBinding bind = new KeyBinding(((KeybindOption)option).getTranslationKey(), keyCode, "category.petroleum"); + newValue.fromKeybind(bind, option.getParent()); + Optional config = ConfigManager.getConfig(); + assert config.isPresent(); + config.get().globalConfig.setBinding(bind, option.getParent()); + option = newValue; + this.setMessage(new LiteralText(option.getStringValue().toUpperCase())); + selected = null; + return false; + } else { + this.playDownSound(MinecraftClient.getInstance().getSoundManager()); + this.onPress(); + return true; + } + } else { + return false; + } + } + }; + elements.add(bindButton); + } + else { + System.out.println("other/string"); + //TODO + } + } + else { + elements.forEach((widget) -> { + if (widget instanceof AbstractButtonWidget) { + ((AbstractButtonWidget)widget).render(matrices, mouseX, mouseY, tickDelta); + } + }); + } + } + } +} \ No newline at end of file diff --git a/src/main/java/pm/j4/petroleum/gui/PModuleConfigPane.java b/src/main/java/pm/j4/petroleum/gui/PModuleConfigPane.java new file mode 100644 index 0000000..a5242fd --- /dev/null +++ b/src/main/java/pm/j4/petroleum/gui/PModuleConfigPane.java @@ -0,0 +1,120 @@ +package pm.j4.petroleum.gui; + +import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.systems.RenderSystem; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.widget.ElementListWidget; +import net.minecraft.client.gui.widget.EntryListWidget; +import net.minecraft.client.render.BufferBuilder; +import net.minecraft.client.render.Tessellator; +import net.minecraft.client.render.VertexFormats; +import net.minecraft.client.util.math.MatrixStack; + +/** + * The type P module config pane. + */ +public class PModuleConfigPane extends ElementListWidget { + /** + * The Parent. + */ + private final POptionsScreen parent; + /** + * The Last selected. + */ + private POptionEntry lastSelected; + + private PModuleConfigEntry selectedConfigEntry; + + /** + * Instantiates a new P module config pane. + * + * @param client the client + * @param width the width + * @param height the height + * @param top the top + * @param bottom the bottom + * @param entryHeight the entry height + * @param screen the screen + */ + public PModuleConfigPane(MinecraftClient client, int width, int height, int top, int bottom, int entryHeight, POptionsScreen screen) { + super(client, width, height, top, bottom, entryHeight); + this.parent = screen; + } + + public void setSelected(PModuleConfigEntry entry) { + selectedConfigEntry = entry; + } + + @Override + public PModuleConfigEntry getSelected() { + return selectedConfigEntry; + } + + @Override + public int getRowWidth() { + return this.width - 10; + } + + @Override + protected int getScrollbarPositionX() { + return this.width - 6 + left; + } + + @Override + public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { + POptionEntry selectedEntry = parent.getSelected(); + if (selectedEntry != lastSelected) { + lastSelected = selectedEntry; + clearEntries(); + setScrollAmount(-Double.MAX_VALUE); + String id = lastSelected.getModId(); + if (lastSelected != null && id != null && !id.isEmpty()) { + children().addAll(lastSelected.module.getConfigEntries(this)); + } + } + + Tessellator t_1 = Tessellator.getInstance(); + BufferBuilder buffer = t_1.getBuffer(); + + RenderSystem.depthFunc(515); + RenderSystem.disableDepthTest(); + RenderSystem.enableBlend(); + RenderSystem.blendFuncSeparate(GlStateManager.SrcFactor.SRC_ALPHA, + GlStateManager.DstFactor.ONE_MINUS_DST_ALPHA, + GlStateManager.SrcFactor.ZERO, + GlStateManager.DstFactor.ONE); + RenderSystem.disableAlphaTest(); + RenderSystem.shadeModel(7425); + RenderSystem.disableTexture(); + + // darken config pane area + + buffer.begin(7, VertexFormats.POSITION_COLOR_TEXTURE); + buffer.vertex(this.left, (this.top + 4), 0.0D).color(0, 0, 0, 0).texture(0.0F, 1.0F).next(); + buffer.vertex(this.right, (this.top + 4), 0.0D).color(0, 0, 0, 0).texture(1.0F, 1.0F).next(); + buffer.vertex(this.right, this.top, 0.0D).color(0, 0, 0, 255).texture(1.0F, 0.0F).next(); + buffer.vertex(this.left, this.top, 0.0D).color(0, 0, 0, 255).texture(0.0F, 0.0F).next(); + buffer.vertex(this.left, this.bottom, 0.0D).color(0, 0, 0, 255).texture(0.0F, 1.0F).next(); + buffer.vertex(this.right, this.bottom, 0.0D).color(0, 0, 0, 255).texture(1.0F, 1.0F).next(); + buffer.vertex(this.right, (this.bottom - 4), 0.0D).color(0, 0, 0, 0).texture(1.0F, 0.0F).next(); + buffer.vertex(this.left, (this.bottom - 4), 0.0D).color(0, 0, 0, 0).texture(0.0F, 0.0F).next(); + t_1.draw(); + + buffer.begin(7, VertexFormats.POSITION_COLOR); + buffer.vertex(this.left, this.bottom, 0.0D).color(0, 0, 0, 128).next(); + buffer.vertex(this.right, this.bottom, 0.0D).color(0, 0, 0, 128).next(); + buffer.vertex(this.right, this.top, 0.0D).color(0, 0, 0, 128).next(); + buffer.vertex(this.left, this.top, 0.0D).color(0, 0, 0, 128).next(); + t_1.draw(); + + int rl = this.getRowLeft(); + int sc = this.top + 4 - (int) this.getScrollAmount(); + this.renderList(matrices, rl, sc, mouseX, mouseY, delta); + + RenderSystem.enableTexture(); + RenderSystem.shadeModel(7424); + RenderSystem.enableAlphaTest(); + RenderSystem.disableBlend(); + } +} diff --git a/src/main/java/pm/j4/petroleum/gui/PModuleConfigurationWidget.java b/src/main/java/pm/j4/petroleum/gui/PModuleConfigurationWidget.java new file mode 100644 index 0000000..495da1c --- /dev/null +++ b/src/main/java/pm/j4/petroleum/gui/PModuleConfigurationWidget.java @@ -0,0 +1,281 @@ +package pm.j4.petroleum.gui; + +import com.mojang.blaze3d.systems.RenderSystem; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.widget.AlwaysSelectedEntryListWidget; +import net.minecraft.client.render.BufferBuilder; +import net.minecraft.client.render.Tessellator; +import net.minecraft.client.render.VertexFormats; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Matrix4f; +import pm.j4.petroleum.mixin.EntryListWidgetAccessor; +import pm.j4.petroleum.util.module.ModuleBase; + +/** + * The type P module configuration widget. + */ +public class PModuleConfigurationWidget extends AlwaysSelectedEntryListWidget { + /** + * The Parent. + */ + private final POptionsScreen parent; + /** + * The Module id. + */ + private String moduleId = null; + /** + * The Mods. + */ + private List mods; + /** + * The Extra mods. + */ + private final Set extraMods = new HashSet<>(); + /** + * The Scrolling. + */ + private boolean scrolling = false; + + /** + * Instantiates a new P module configuration widget. + * + * @param client the client + * @param width the width + * @param height the height + * @param y1 the y 1 + * @param y2 the y 2 + * @param entryHeight the entry height + * @param list the list + * @param parent the parent + */ + public PModuleConfigurationWidget(MinecraftClient client, int width, int height, int y1, int y2, int entryHeight, PModuleConfigurationWidget list, POptionsScreen parent) { + super(client, width, height, y1, y2, entryHeight); + this.parent = parent; + if (list != null) { + mods = list.mods; + } + setScrollAmount(parent.getScrollPercent() * Math.max(0, this.getMaxPosition() - (this.bottom - this.top - 4))); + } + + @Override + public void setScrollAmount(double amount) { + super.setScrollAmount(amount); + int denominator = Math.max(0, this.getMaxPosition() - (this.bottom - this.top - 4)); + if (denominator <= 0) { + parent.updateScrollPercent(0); + } else { + parent.updateScrollPercent(getScrollAmount() / Math.max(0, this.getMaxPosition() - (this.bottom - this.top - 4))); + } + } + + @Override + protected boolean isFocused() { + return parent.getFocused() == this; + } + + /** + * Select. + * + * @param entry the entry + */ + public void select(POptionEntry entry) { + this.setSelected(entry); + } + + @Override + public void setSelected(POptionEntry entry) { + super.setSelected(entry); + moduleId = entry.getModId(); + parent.updateSelected(entry); + } + + @Override + protected boolean isSelectedItem(int index) { + return super.isSelectedItem(index); + } + + @Override + public int addEntry(POptionEntry entry) { + if (extraMods.contains(entry.module)) { + return 0; + } + extraMods.add(entry.module); + int i = super.addEntry(entry); + if (entry.getModId().equals(moduleId)) { + setSelected(entry); + } + return i; + } + + @Override + protected boolean removeEntry(POptionEntry entry) { + extraMods.remove(entry.module); + return super.removeEntry(entry); + } + + @Override + protected POptionEntry remove(int index) { + extraMods.remove(getEntry(index).module); + return super.remove(index); + } + + @Override + protected void renderList(MatrixStack matrices, int x, int y, int mouseX, int mouseY, float delta) { + int itemCount = this.getItemCount(); + Tessellator t_1 = Tessellator.getInstance(); + BufferBuilder buffer = t_1.getBuffer(); + + for (int index = 0; index < itemCount; ++index) { + int entryTop = this.getRowTop(index); + int entryBottom = this.getRowTop(index) + this.itemHeight; + if (entryBottom >= this.top && entryTop <= this.bottom) { + int entryHeight = this.itemHeight - 4; + POptionEntry entry = this.getEntry(index); + int rowWidth = this.getRowWidth(); + int entryLeft; + if (((EntryListWidgetAccessor) this).isRenderSelection() && this.isSelectedItem(index)) { + entryLeft = getRowLeft() - 2 + entry.getXOffset(); + int selectionRight = x + rowWidth + 2; + RenderSystem.disableTexture(); + float brightness = this.isFocused() ? 1.0F : 0.5F; + RenderSystem.color4f(brightness, brightness, brightness, 1.0F); + Matrix4f matrix = matrices.peek().getModel(); + buffer.begin(7, VertexFormats.POSITION); + buffer.vertex(matrix, entryLeft, entryTop + entryHeight + 2, 0.0F).next(); + buffer.vertex(matrix, selectionRight, entryTop + entryHeight + 2, 0.0F).next(); + buffer.vertex(matrix, selectionRight, entryTop - 2, 0.0F).next(); + buffer.vertex(matrix, entryLeft, entryTop - 2, 0.0F).next(); + t_1.draw(); + RenderSystem.color4f(0.0F, 0.0F, 0.0F, 1.0F); + buffer.begin(7, VertexFormats.POSITION); + buffer.vertex(matrix, entryLeft + 1, entryTop + entryHeight + 1, 0.0F).next(); + buffer.vertex(matrix, selectionRight, entryTop + entryHeight + 1, 0.0F).next(); + buffer.vertex(matrix, selectionRight, entryTop - 1, 0.0F).next(); + buffer.vertex(matrix, entryLeft + 1, entryTop - 1, 0.0F).next(); + t_1.draw(); + RenderSystem.enableTexture(); + } + + entryLeft = this.getRowLeft(); + entry.render(matrices, + index, + entryTop, + entryLeft, + rowWidth, + entryHeight, + mouseX, + mouseY, + this.isMouseOver(mouseX, mouseY) && Objects.equals(this.getEntryAtPos(mouseX, mouseY), entry), + delta); + } + } + } + + @Override + protected void updateScrollingState(double mouseX, double mouseY, int button) { + super.updateScrollingState(mouseX, mouseY, button); + this.scrolling = button == 0 && + mouseX >= (double) this.getScrollbarPositionX() && + mouseX < (double) (this.getScrollbarPositionX() + 6); + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + this.updateScrollingState(mouseX, mouseY, button); + if (!this.isMouseOver(mouseX, mouseY)) { + return false; + } else { + POptionEntry entry = this.getEntryAtPos(mouseX, mouseY); + if (entry != null) { + if (entry.mouseClicked(mouseX, mouseY, button)) { + this.setFocused(entry); + this.setDragging(true); + return true; + } else if (button == 0) { + this.clickedHeader((int) (mouseX - (double) (this.left + this.width / 2 - this.getRowWidth() / 2)), + (int) (mouseY - (double) this.top) + (int) this.getScrollAmount() - 4); + } + } + } + + return this.scrolling; + } + + /** + * Gets entry at pos. + * + * @param x the x + * @param y the y + * @return the entry at pos + */ + public final POptionEntry getEntryAtPos(double x, double y) { + int i = MathHelper.floor(y - (double) this.top) - this.headerHeight + (int) this.getScrollAmount() - 4; + int index = i / this.itemHeight; + return x < (double) this.getScrollbarPositionX() && + x >= (double) getRowLeft() && + x <= (double) (getRowLeft() + getRowWidth()) && + index >= 0 && i >= 0 && + index < this.getItemCount() ? this.children().get(index) : null; + } + + @Override + protected int getScrollbarPositionX() { + return this.width - 6; + } + + @Override + public int getRowWidth() { + return this.width - (Math.max(0, this.getMaxPosition() - (this.bottom - this.top - 4)) > 0 ? 18 : 12); + } + + @Override + public int getRowLeft() { + return left + 6; + } + + /** + * Gets width. + * + * @return the width + */ + public int getWidth() { + return width; + } + + /** + * Gets top. + * + * @return the top + */ + public int getTop() { + return this.top; + } + + /** + * Gets parent. + * + * @return the parent + */ + public POptionsScreen getParent() { + return parent; + } + + @Override + protected int getMaxPosition() { + return super.getMaxPosition() + 4; + } + + /** + * Gets displayed count. + * + * @return the displayed count + */ + public int getDisplayedCount() { + return children().size(); + } +} diff --git a/src/main/java/pm/j4/petroleum/gui/PMovableButton.java b/src/main/java/pm/j4/petroleum/gui/PMovableButton.java new file mode 100644 index 0000000..abcb8b3 --- /dev/null +++ b/src/main/java/pm/j4/petroleum/gui/PMovableButton.java @@ -0,0 +1,388 @@ +package pm.j4.petroleum.gui; + +import com.mojang.blaze3d.systems.RenderSystem; +import java.util.List; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.widget.AbstractButtonWidget; +import net.minecraft.client.render.BufferBuilder; +import net.minecraft.client.render.Tessellator; +import net.minecraft.client.render.VertexFormats; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.LiteralText; +import net.minecraft.text.TranslatableText; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Matrix4f; +import pm.j4.petroleum.modules.menu.ModMenu; +import pm.j4.petroleum.util.data.ButtonInformation; +import pm.j4.petroleum.util.module.ModuleBase; + +/** + * The type P movable button. + */ +public class PMovableButton extends AbstractButtonWidget { + /** + * The Expanded. + */ + private boolean expanded; + /** + * The Collapsed width. + */ + private final int collapsedWidth; + /** + * The Expanded width. + */ + private int expandedWidth; + /** + * The Collapsed height. + */ + private final int collapsedHeight; + /** + * The Expanded height. + */ + private int expandedHeight; + /** + * The Module height. + */ + private final int moduleHeight; + /** + * The Modules. + */ + private final List modules; + + /** + * The Stored x. + */ + private int storedX; + /** + * The Stored y. + */ + private int storedY; + + /** + * The Spin. + */ + private double spin; + + /** + * The Arrow size. + */ + private final int arrowSize = 10; + + + /** + * The Category. + */ + private final String category; + + /** + * The Parent. + */ + private final PModMenuScreen parent; + + /** + * Instantiates a new P movable button. + * + * @param x the x + * @param y the y + * @param categoryName the category name + * @param modules the modules + * @param open the open + * @param parent the parent + */ + public PMovableButton(int x, int y, String categoryName, List modules, boolean open, PModMenuScreen parent) { + super(x, y, 0, 0, new TranslatableText(categoryName)); + this.category = categoryName; + int w = MinecraftClient.getInstance().textRenderer.getWidth(new TranslatableText(categoryName)) + 8; + int h = MinecraftClient.getInstance().textRenderer.fontHeight + 8; + this.width = w; + this.collapsedWidth = w; + this.expandedWidth = 0; + this.height = h; + this.collapsedHeight = h; + this.expandedHeight = 0; + this.moduleHeight = h; + this.expanded = open; + this.modules = modules; + this.parent = parent; + } + + @Override + public void onClick(double mouseX, double mouseY) { + this.storedX = (int) mouseX; + this.storedY = (int) mouseY; + super.onClick(mouseX, mouseY); + } + + /** + * On extra click. + * + * @param mouseX the mouse x + * @param mouseY the mouse y + */ + private void onExtraClick(double mouseX, double mouseY) { + System.out.println("extra click"); + int increment = this.moduleHeight + 4; + int location = (int)mouseY - (this.y + this.collapsedHeight); + int index = location / increment; + System.out.println("index: " + index); + if(modules.size() >= index) { + ModuleBase affectedModule = modules.get(index); + System.out.println("module: " + affectedModule); + if(affectedModule.isActivatable()) { + System.out.println("toggling"); + affectedModule.toggle(); + } + } + else { + System.out.println("index too great"); + } + //TODO module things + } + + @Override + public void onRelease(double mouseX, double mouseY) { + int mx = (int) mouseX; + int my = (int) mouseY; + /** + * The Padding. + */ + int padding = 5; + if (storedX + padding > mx && storedX - padding < mx && + storedY + padding > my && storedY - padding < my) { + this.expanded = !this.expanded; + } + } + + @Override + protected void onDrag(double mouseX, double mouseY, double deltaX, double deltaY) { + this.x += (int) deltaX; + this.y += (int) deltaY; + + // i really hate to do it but nowhere else will it properly save + this.updateCoordinate(); + } + + /** + * Update coordinate. + */ + public void updateCoordinate() { + ModMenu.updateCoord(this.category, new ButtonInformation((this.x / (double) parent.width), (this.y / (double) parent.height), this.expanded)); + } + + // fuck click sounds + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + if (this.active && this.visible) { + if (this.isValidClickButton(button)) { + boolean bl = this.clicked(mouseX, mouseY); + if (bl && mouseY > this.y + this.collapsedHeight && mouseY < this.y + this.expandedHeight) { + this.onExtraClick(mouseX, mouseY); + return true; + } else if (bl) { + this.onClick(mouseX, mouseY); + return true; + } + } + + } + return false; + } + + /** + * Transition max width. + * + * @param width the width + */ + private void transitionMaxWidth(int width) { + double increment = ((width - this.width) / 20.0); + int sign = (width > this.width) ? 1 : -1; + if (increment == 0) { + this.width = width; + } else if (increment < 1 && increment > -1) { + this.width += sign; + } else { + this.width += (int) increment; + } + } + + /** + * Transition max height. + * + * @param height the height + */ + private void transitionMaxHeight(int height) { + double increment = ((height - this.height) / 20.0); + int sign = (height > this.height) ? 1 : -1; + if (increment == 0) { + this.height = height; + } else if (increment < 1 && increment > -1) { + this.height += sign; + } else { + this.height += (int) increment; + } + } + + @Override + public void renderButton(MatrixStack matrices, int mouseX, int mouseY, float delta) { + + if (this.expandedWidth == 0 || this.expandedHeight == 0) { + this.expandedHeight = this.collapsedHeight + ((this.moduleHeight + 4) * modules.size()); + modules.forEach(module -> { + this.expandedWidth = this.width; + int w = MinecraftClient.getInstance().textRenderer.getWidth(module.getReadableName()) + arrowSize + 8; + if (w > this.expandedWidth) { + this.expandedWidth = w; + } + }); + // this should only run when opening the screen for the first time + if (this.expanded) { + this.height = expandedHeight; + this.width = expandedWidth; + } + } + + MinecraftClient minecraftClient = MinecraftClient.getInstance(); + TextRenderer textRenderer = minecraftClient.textRenderer; + minecraftClient.getTextureManager().bindTexture(WIDGETS_LOCATION); + RenderSystem.color4f(1.0F, 1.0F, 1.0F, this.alpha); + + RenderSystem.disableTexture(); + RenderSystem.defaultBlendFunc(); + float brightness = this.isFocused() ? 1.0F : 0.5F; + RenderSystem.color4f(brightness, brightness, brightness, 1.0F); + Matrix4f matrix = matrices.peek().getModel(); + + int buttonLeft = this.x; + int buttonRight = this.x + width + 2; + int buttonTop = this.y; + int buttonBottom = this.y + this.collapsedHeight; + int buttonExpandedBottom = this.y + this.height; + Tessellator t_1 = Tessellator.getInstance(); + BufferBuilder buffer = t_1.getBuffer(); + + RenderSystem.color4f(0.5F, 0.5F, 0.5F, 0.5F); + drawBox(t_1, buffer, matrix, buttonLeft, buttonRight, buttonTop - 2, buttonBottom + 2); + + RenderSystem.color4f(0.0F, 0.0F, 0.0F, 0.3F); + drawBox(t_1, buffer, matrix, buttonLeft + 1, buttonRight - 1, buttonTop - 1, buttonBottom + 1); + + RenderSystem.color4f(1.0F, 1.0F, 1.0F, 0.9F); + drawEquilateralTriangle(t_1, buffer, matrix, 40, 40, 180, arrowSize); + drawEquilateralTriangle(t_1, buffer, matrix, 60, 60, 0, arrowSize); + drawEquilateralTriangle(t_1, buffer, matrix, 40, 60, 90, arrowSize); + drawEquilateralTriangle(t_1, buffer, matrix, 60, 40, 360, arrowSize); + drawEquilateralTriangle(t_1, buffer, matrix, 80, 40, 270, arrowSize); + drawEquilateralTriangle(t_1, buffer, matrix, 80, 60, 120, arrowSize); + + int j = this.active ? 16777215 : 10526880; + if (this.expanded) { + if (this.width != this.expandedWidth || this.height != this.expandedHeight) { + transitionMaxWidth(this.expandedWidth); + transitionMaxHeight(this.expandedHeight); + RenderSystem.color4f(0.5F, 0.5F, 0.5F, 0.5F); + drawBox(t_1, buffer, matrix, buttonLeft, buttonRight, buttonBottom + 1, buttonExpandedBottom + 2); + + RenderSystem.color4f(0.0F, 0.0F, 0.0F, 0.3F); + drawBox(t_1, buffer, matrix, buttonLeft + 1, buttonRight - 1, buttonBottom + 2, buttonExpandedBottom + 1); + if ((this.height - 8) / 2 > (this.collapsedHeight)) { + drawCenteredText(matrices, textRenderer, new LiteralText("..."), this.x + this.width / 2, this.y + (this.height - 8) / 2, j | MathHelper.ceil(this.alpha * 255.0F) << 24); + } + } else { + for (int i = 0; i < modules.size(); i++) { + int adjustedIndex = i + 1; + int previousBottom = buttonBottom + (i * (this.moduleHeight + 4)); + int currentBottom = buttonBottom + ((i + 1) * (this.moduleHeight + 4)); + + RenderSystem.defaultBlendFunc(); + RenderSystem.color4f(0.5F, 0.5F, 0.5F, 0.5F); + drawBox(t_1, buffer, matrix, buttonLeft, buttonRight, previousBottom + 1, currentBottom + 2); + + RenderSystem.color4f(0.0F, 0.0F, 0.0F, 0.3F); + drawBox(t_1, buffer, matrix, buttonLeft + 1, buttonRight - 1, previousBottom + 2, currentBottom + 1); + + drawCenteredText(matrices, + textRenderer, + modules.get(i).getReadableName(), + this.x + this.width / 2, + this.y + ((this.collapsedHeight - 8) / 2 + ((moduleHeight + 4) * adjustedIndex)), + j | MathHelper.ceil(this.alpha * 255.0F) << 24); + } + } + } else { + if (this.width != this.collapsedWidth || this.height != this.collapsedHeight) { + transitionMaxWidth(this.collapsedWidth); + transitionMaxHeight(this.collapsedHeight); + RenderSystem.color4f(0.5F, 0.5F, 0.5F, 0.5F); + drawBox(t_1, buffer, matrix, buttonLeft, buttonRight, buttonBottom + 1, buttonExpandedBottom + 2); + + RenderSystem.color4f(0.0F, 0.0F, 0.0F, 0.3F); + drawBox(t_1, buffer, matrix, buttonLeft + 1, buttonRight - 1, buttonBottom + 2, buttonExpandedBottom + 1); + if ((this.height - 8) / 2 > (this.collapsedHeight)) { + drawCenteredText(matrices, textRenderer, new LiteralText("..."), this.x + this.width / 2, this.y + (this.height - 8) / 2, j | MathHelper.ceil(this.alpha * 255.0F) << 24); + } + } + } + RenderSystem.enableTexture(); + drawCenteredText(matrices, textRenderer, this.getMessage(), this.x + this.width / 2, this.y + (this.collapsedHeight - 8) / 2, j | MathHelper.ceil(this.alpha * 255.0F) << 24); + } + + /** + * Draw equilateral triangle. + * + * @param t_1 the t 1 + * @param buffer the buffer + * @param matrix the matrix + * @param centerX the center x + * @param centerY the center y + * @param rotation the rotation + * @param distance the distance + */ + private void drawEquilateralTriangle(Tessellator t_1, BufferBuilder buffer, Matrix4f matrix, int centerX, int centerY, double rotation, int distance) { + double rotation2 = rotation + 120; + double rotation3 = rotation + 240; + int point1X = (int)(distance * Math.cos(Math.toRadians(rotation))) + centerX; + int point1Y = (int)(distance * Math.sin(Math.toRadians(rotation))) + centerY; + int point2X = (int)(distance * Math.cos(Math.toRadians(rotation2))) + centerX; + int point2Y = (int)(distance * Math.sin(Math.toRadians(rotation2))) + centerY; + int point3X = (int)(distance * Math.cos(Math.toRadians(rotation3))) + centerX; + int point3Y = (int)(distance * Math.sin(Math.toRadians(rotation3))) + centerY; + + //RenderSystem.enableBlend(); + RenderSystem.disableBlend(); + buffer.begin(7, VertexFormats.POSITION_COLOR); + buffer.vertex(matrix, centerX, centerY, 0.0F).color(0.0F, 1.0F, 1.0F, 1.0F).next(); + buffer.vertex(matrix, centerX, point1Y, 0.0F).color(0.0F, 1.0F, 1.0F, 1.0F).next(); + buffer.vertex(matrix, point1X, point1Y, 0.0F).color(0.0F, 1.0F, 1.0F, 1.0F).next(); + + buffer.vertex(matrix, centerX, centerY, 0.0F).color(0.5F, 1.0F, 1.0F, 1.0F).next(); + buffer.vertex(matrix, centerX, point2Y, 0.0F).color(0.5F, 1.0F, 1.0F, 1.0F).next(); + buffer.vertex(matrix, point2X, point2Y, 0.0F).color(0.5F, 1.0F, 1.0F, 1.0F).next(); + + buffer.vertex(matrix, centerX, centerY, 0.0F).color(1.0F, 0.0F, 1.0F, 1.0F).next(); + buffer.vertex(matrix, centerX, point3Y, 0.0F).color(1.0F, 0.0F, 1.0F, 1.0F).next(); + buffer.vertex(matrix, point3X, point3Y, 0.0F).color(1.0F, 0.0F, 1.0F, 1.0F).next(); + t_1.draw(); + } + + /** + * Draw box. + * + * @param t_1 the t 1 + * @param buffer the buffer + * @param matrix the matrix + * @param buttonLeft the button left + * @param buttonRight the button right + * @param buttonTop the button top + * @param buttonBottom the button bottom + */ + private void drawBox(Tessellator t_1, BufferBuilder buffer, Matrix4f matrix, int buttonLeft, int buttonRight, int buttonTop, int buttonBottom) { + RenderSystem.enableBlend(); + buffer.begin(7, VertexFormats.POSITION); + buffer.vertex(matrix, buttonLeft, buttonBottom, 0.0F).next(); + buffer.vertex(matrix, buttonRight, buttonBottom, 0.0F).next(); + buffer.vertex(matrix, buttonRight, buttonTop, 0.0F).next(); + buffer.vertex(matrix, buttonLeft, buttonTop, 0.0F).next(); + t_1.draw(); + } +} diff --git a/src/main/java/pm/j4/petroleum/gui/POptionEntry.java b/src/main/java/pm/j4/petroleum/gui/POptionEntry.java new file mode 100644 index 0000000..4132848 --- /dev/null +++ b/src/main/java/pm/j4/petroleum/gui/POptionEntry.java @@ -0,0 +1,94 @@ +package pm.j4.petroleum.gui; + +import com.mojang.blaze3d.systems.RenderSystem; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.widget.AlwaysSelectedEntryListWidget; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.StringVisitable; +import net.minecraft.text.Text; +import net.minecraft.text.TranslatableText; +import net.minecraft.util.Language; +import pm.j4.petroleum.util.module.ModuleBase; + +/** + * The type P option entry. + */ +public class POptionEntry extends AlwaysSelectedEntryListWidget.Entry { + + /** + * The Module. + */ + protected final ModuleBase module; + /** + * The Client. + */ + protected final MinecraftClient client; + /** + * The List. + */ + private final PModuleConfigurationWidget list; + + /** + * Instantiates a new P option entry. + * + * @param mod the mod + * @param list the list + */ + public POptionEntry(ModuleBase mod, PModuleConfigurationWidget list) { + this.module = mod; + this.client = MinecraftClient.getInstance(); + this.list = list; + } + + //TODO TEST move text to be centered + @Override + public void render(MatrixStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) { + x += getXOffset(); + entryWidth -= getXOffset(); + RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F); + Text name = this.getModName(); + StringVisitable nameString = name; + int maxNameWidth = entryWidth - 32 - 3; + TextRenderer font = this.client.textRenderer; + if (font.getWidth(name) > maxNameWidth) { + StringVisitable ellipse = StringVisitable.plain("..."); + nameString = StringVisitable.concat(font.trimToWidth(nameString, maxNameWidth - font.getWidth(ellipse)), ellipse); + } + + font.draw(matrices, Language.getInstance().reorder(nameString), x + 32 + 3, y + (entryHeight / 2), 0xFFFFFF); + } + + @Override + public boolean mouseClicked(double x, double y, int b) { + this.list.select(this); + return true; + } + + /** + * Gets mod id. + * + * @return the mod id + */ + public String getModId() { + return module.getModuleName(); + } + + /** + * Gets mod name. + * + * @return the mod name + */ + public TranslatableText getModName() { + return module.getReadableName(); + } + + /** + * Gets x offset. + * + * @return the x offset + */ + public int getXOffset() { + return 0; + } +} diff --git a/src/main/java/pm/j4/petroleum/gui/POptionsScreen.java b/src/main/java/pm/j4/petroleum/gui/POptionsScreen.java new file mode 100644 index 0000000..6384ac7 --- /dev/null +++ b/src/main/java/pm/j4/petroleum/gui/POptionsScreen.java @@ -0,0 +1,222 @@ +package pm.j4.petroleum.gui; + +import com.mojang.blaze3d.systems.RenderSystem; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawableHelper; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.ScreenTexts; +import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.render.BufferBuilder; +import net.minecraft.client.render.Tessellator; +import net.minecraft.client.render.VertexFormats; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.*; +import pm.j4.petroleum.PetroleumMod; +import pm.j4.petroleum.util.config.ConfigManager; +import pm.j4.petroleum.util.module.ModuleBase; + +/** + * The type P options screen. + */ +@SuppressWarnings("deprecation") +public class POptionsScreen extends Screen { + /** + * The Previous screen. + */ + private final Screen previousScreen; + /** + * The Scroll percent. + */ + private double scrollPercent = 0; + /** + * The Modules. + */ + private PModuleConfigurationWidget modules; + /** + * The Config pane. + */ + private PModuleConfigPane configPane; + /** + * The Selected. + */ + private POptionEntry selected; + /** + * The Tooltip. + */ + private Text tooltip; + + /** + * The Pane y. + */ + private int paneY; + /** + * The Right pane x. + */ + private int rightPaneX; + + /** + * Instantiates a new P options screen. + * + * @param previousScreen the previous screen + */ + public POptionsScreen(Screen previousScreen) { + super(new TranslatableText("petroleum.options")); + this.previousScreen = previousScreen; + } + + @Override + public void onClose() { + super.onClose(); + assert this.client != null; + this.client.openScreen(previousScreen); + } + + protected void init() { + paneY = 48; + int paneWidth = this.width / 2 - 8; + rightPaneX = width - paneWidth; + this.modules = new PModuleConfigurationWidget(this.client, + this.width - paneWidth, + this.height, + paneY + 19, + this.height - 36, + 36, + this.modules, + this); + this.modules.setLeftPos(0); + this.children.add(this.modules); + this.configPane = new PModuleConfigPane(this.client, + paneWidth, + this.height, + paneY + 19, + this.height - 36, + 48, + this); + this.configPane.setLeftPos(paneWidth); + this.children.add(this.configPane); + List configurableModules = new ArrayList<>(); + if (ConfigManager.getConfig().isPresent()) { + configurableModules.addAll(PetroleumMod.getActiveMods() + .stream().filter(ModuleBase::configurable) + .collect(Collectors.toList())); + } + configurableModules.forEach(module -> this.modules.addEntry(new POptionEntry(module, this.modules))); + this.addButton(new ButtonWidget(this.width / 2 - 75, this.height - 30, 150, 20, ScreenTexts.DONE, (buttonWidget) -> { + ConfigManager.saveAllModules(); + assert this.client != null; + this.client.openScreen(this.previousScreen); + })); + } + + @Override + public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { + this.renderBackground(matrices); + + this.modules.render(matrices, mouseX, mouseY, delta); + if (selected != null) { + this.configPane.render(matrices, mouseX, mouseY, delta); + } + RenderSystem.disableBlend(); + drawTextWithShadow(matrices, this.textRenderer, this.title, this.modules.getWidth() / 2, 8, 16777215); + super.render(matrices, mouseX, mouseY, delta); + + if (selected != null) { + int offset = 36; + int x = rightPaneX; + int maxNameWidth = this.width - (x + offset); + int lineSpacing = textRenderer.fontHeight + 1; + Text name = selected.getModName(); + + StringVisitable trimmedName = name; + + if (textRenderer.getWidth(name) > maxNameWidth) { + StringVisitable ellipsis = StringVisitable.plain("..."); + trimmedName = StringVisitable.concat(textRenderer.trimToWidth(name, maxNameWidth - textRenderer.getWidth(ellipsis)), ellipsis); + } + if (mouseX > x + offset && mouseY > paneY + 1 && mouseY < paneY + 1 + textRenderer.fontHeight && mouseX < x + offset + textRenderer.getWidth(trimmedName)) { + //TODO tooltop + //selected.getModName() + } + textRenderer.draw(matrices, selected.getModName(), x + offset, paneY + 2 + lineSpacing, 0x808080); + + if (this.tooltip != null) { + this.renderOrderedTooltip(matrices, textRenderer.wrapLines(this.tooltip, Integer.MAX_VALUE), mouseX, mouseY); + } + } + } + + /** + * Sets tooltip. + * + * @param tooltip the tooltip + */ + private void setTooltip(Text tooltip) { + this.tooltip = tooltip; + } + + @Override + public void renderBackground(MatrixStack matrices) { + POptionsScreen.overlayBackground(this.width, this.height); + } + + /** + * Overlay background. + * + * @param x2 the x 2 + * @param y2 the y 2 + */ + static void overlayBackground(int x2, int y2) { + Tessellator t_1 = Tessellator.getInstance(); + BufferBuilder buffer = t_1.getBuffer(); + Objects.requireNonNull(MinecraftClient.getInstance()).getTextureManager().bindTexture(DrawableHelper.OPTIONS_BACKGROUND_TEXTURE); + RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F); + buffer.begin(7, VertexFormats.POSITION_TEXTURE_COLOR); + buffer.vertex(0, y2, 0.0D).texture(0 / 32.0F, y2 / 32.0F).color(64, 64, 64, 255).next(); + buffer.vertex(x2, y2, 0.0D).texture(x2 / 32.0F, y2 / 32.0F).color(64, 64, 64, 255).next(); + buffer.vertex(x2, 0, 0.0D).texture(x2 / 32.0F, 0 / 32.0F).color(64, 64, 64, 255).next(); + buffer.vertex(0, 0, 0.0D).texture(0 / 32.0F, 0 / 32.0F).color(64, 64, 64, 255).next(); + t_1.draw(); + } + + /** + * Gets scroll percent. + * + * @return the scroll percent + */ + double getScrollPercent() { + return scrollPercent; + } + + /** + * Update scroll percent. + * + * @param scrollPercent the scroll percent + */ + void updateScrollPercent(double scrollPercent) { + this.scrollPercent = scrollPercent; + } + + /** + * Gets selected. + * + * @return the selected + */ + POptionEntry getSelected() { + return selected; + } + + /** + * Update selected. + * + * @param entry the entry + */ + void updateSelected(POptionEntry entry) { + if (entry != null) { + this.selected = entry; + } + } +} diff --git a/src/main/java/pm/j4/petroleum/mixin/DebugHudMixin.java b/src/main/java/pm/j4/petroleum/mixin/DebugHudMixin.java new file mode 100644 index 0000000..2a79bdd --- /dev/null +++ b/src/main/java/pm/j4/petroleum/mixin/DebugHudMixin.java @@ -0,0 +1,38 @@ +package pm.j4.petroleum.mixin; + +import java.util.List; +import java.util.Optional; +import net.minecraft.client.gui.hud.DebugHud; +import net.minecraft.client.util.math.MatrixStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; +import pm.j4.petroleum.modules.splash.SplashText; +import pm.j4.petroleum.util.config.ConfigHolder; +import pm.j4.petroleum.util.config.ConfigManager; + +/** + * The type Debug hud mixin. + */ +@Mixin(DebugHud.class) +public class DebugHudMixin { + /** + * Render text right. + * + * @param matrices the matrices + * @param ci the ci + * @param list the list + */ + @Inject(method = "renderLeftText", + at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/client/gui/hud/DebugHud;getLeftText()Ljava/util/List;"), + locals = LocalCapture.CAPTURE_FAILSOFT) + protected void renderTextRight(MatrixStack matrices, CallbackInfo ci, List list) { + Optional config = ConfigManager.getConfig(); + if (config.isPresent() && config.get().isModuleEnabled("petroleum.splashtext")) { + list.add("[Petroleum] " + SplashText.get() + " loaded"); + } + + } +} diff --git a/src/main/java/pm/j4/petroleum/mixin/EntryListWidgetAccessor.java b/src/main/java/pm/j4/petroleum/mixin/EntryListWidgetAccessor.java new file mode 100644 index 0000000..eea68ab --- /dev/null +++ b/src/main/java/pm/j4/petroleum/mixin/EntryListWidgetAccessor.java @@ -0,0 +1,19 @@ +package pm.j4.petroleum.mixin; + +import net.minecraft.client.gui.widget.EntryListWidget; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +/** + * The interface Entry list widget accessor. + */ +@Mixin(EntryListWidget.class) +public interface EntryListWidgetAccessor { + /** + * Is render selection boolean. + * + * @return the boolean + */ + @Accessor("renderSelection") + boolean isRenderSelection(); +} diff --git a/src/main/java/pm/j4/petroleum/mixin/ModListMixin.java b/src/main/java/pm/j4/petroleum/mixin/ModListMixin.java new file mode 100644 index 0000000..7ee7248 --- /dev/null +++ b/src/main/java/pm/j4/petroleum/mixin/ModListMixin.java @@ -0,0 +1,89 @@ +package pm.j4.petroleum.mixin; + + +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.DrawableHelper; +import net.minecraft.client.gui.hud.InGameHud; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.TranslatableText; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import pm.j4.petroleum.modules.list.ModList; +import pm.j4.petroleum.util.config.ConfigHolder; +import pm.j4.petroleum.util.config.ConfigManager; +import pm.j4.petroleum.util.module.ModuleBase; + +/** + * The type Mod list mixin. + */ +@Mixin(InGameHud.class) +public abstract class ModListMixin extends DrawableHelper { + /** + * The Scaled height. + */ + @Shadow + private int scaledHeight; + /** + * The Client. + */ + private final MinecraftClient client; + + /** + * Gets font renderer. + * + * @return the font renderer + */ + @Shadow + public abstract TextRenderer getFontRenderer(); + + + /** + * Instantiates a new Mod list mixin. + * + * @param client the client + */ + public ModListMixin(MinecraftClient client) { + this.client = client; + } + + /** + * Render. + * + * @param matrices the matrices + * @param tickDelta the tick delta + * @param ci the ci + */ + @Inject(method = "render(Lnet/minecraft/client/util/math/MatrixStack;F)V", + at = @At("HEAD")) + public void render(MatrixStack matrices, float tickDelta, CallbackInfo ci) { + Optional config = ConfigManager.getConfig(); + if (config.isPresent() && + config.get().isModuleEnabled("petroleum.modlist") && + !this.client.options.hudHidden && + !this.client.options.debugEnabled) { + renderModuleList(matrices); + } + } + + /** + * Render module list. + * + * @param matrices the matrices + */ + private void renderModuleList(MatrixStack matrices) { + List modules = ModList.getActive(); + List activeModuleList = modules.stream().map(module -> module.getReadableName()).collect(Collectors.toList()); + int fontHeight = this.getFontRenderer().fontHeight; + int startHeight = this.scaledHeight - (activeModuleList.size() * (fontHeight + 4)); + for (int i = 0; i < activeModuleList.size(); i++) { + this.getFontRenderer().drawWithShadow(matrices, activeModuleList.get(i), 10, 10 + (i * (fontHeight + 4)), -1); + } + } +} diff --git a/src/main/java/pm/j4/petroleum/mixin/OptionsMenuMixin.java b/src/main/java/pm/j4/petroleum/mixin/OptionsMenuMixin.java new file mode 100644 index 0000000..be27f25 --- /dev/null +++ b/src/main/java/pm/j4/petroleum/mixin/OptionsMenuMixin.java @@ -0,0 +1,42 @@ +package pm.j4.petroleum.mixin; + +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.options.OptionsScreen; +import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.text.Text; +import net.minecraft.text.TranslatableText; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import pm.j4.petroleum.gui.POptionsScreen; + +/** + * The type Options menu mixin. + */ +@Mixin(OptionsScreen.class) +public class OptionsMenuMixin extends Screen { + + /** + * Instantiates a new Options menu mixin. + * + * @param title the title + */ + protected OptionsMenuMixin(Text title) { + super(title); + } + + /** + * Init. + * + * @param ci the ci + */ + @Inject(at = @At(value = "TAIL"), + method = "init()V") + protected void init(CallbackInfo ci) { + this.addButton(new ButtonWidget(this.width / 2 - 75, this.height / 6 + 140, 150, 20, new TranslatableText("petroleum.options"), (buttonWidget) -> { + assert this.client != null; + this.client.openScreen(new POptionsScreen(this)); + })); + } +} diff --git a/src/main/java/pm/j4/petroleum/mixin/TitleScreenMixin.java b/src/main/java/pm/j4/petroleum/mixin/TitleScreenMixin.java new file mode 100644 index 0000000..e8a7b45 --- /dev/null +++ b/src/main/java/pm/j4/petroleum/mixin/TitleScreenMixin.java @@ -0,0 +1,141 @@ +package pm.j4.petroleum.mixin; + +import java.util.Optional; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.TitleScreen; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.Text; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; +import pm.j4.petroleum.PetroleumMod; +import pm.j4.petroleum.modules.splash.SplashText; +import pm.j4.petroleum.util.config.ConfigHolder; +import pm.j4.petroleum.util.config.ConfigManager; +import pm.j4.petroleum.util.module.ModuleBase; +import pm.j4.petroleum.util.module.option.BooleanOption; +import pm.j4.petroleum.util.module.option.ConfigurationOption; + + +/** + * Mixin attached to the TitleScreen. + * Currently, it is only used to display a string of text with the mod's version. + * Any other modules will likely extend the options screen or pause screen, + * so the module is unlikely to be used elsewhere. + */ +@Mixin(TitleScreen.class) +public class TitleScreenMixin extends Screen { + /** + * The Opacity. + */ + private double opacity = 0; + /** + * The Ascending. + */ + private boolean ascending = false; + + /** + * Stub method. + * Since the mixin injects itself into the *actual* TitleScreen used by the game, + * this should never run. + * + * @param title the title + */ + protected TitleScreenMixin(Text title) { + super(title); + } + + /** + * Mixin injection into the render method. + * It captures locals so that the text can be rendered alongside the + * screen fade-in. + * It injects before the call to @link com.mojang.bridge.game.GameVersion#getName() using INVOKE_ASSIGN, + * because attempting to use a regular invoke statement on @link net.minecraft.client.gui.DrawHelper#drawStringWithShadow() + * repeatedly failed. + *

+ * + * @param matrices the matrices + * @param mouseX the mouse x + * @param mouseY the mouse y + * @param delta the delta + * @param ci the ci + * @param f the f + * @param i the + * @param j the j + * @param g the g + * @param l the l + */ + @Inject(method = "render", + at = @At( + value = "INVOKE_ASSIGN", + target = "Lcom/mojang/bridge/game/GameVersion;getName()Ljava/lang/String;", + ordinal = 0), + locals = LocalCapture.CAPTURE_FAILSOFT) + private void render(MatrixStack matrices, int mouseX, int mouseY, float delta, CallbackInfo ci, float f, int i, int j, float g, int l) { + Optional config = ConfigManager.getConfig(); + Optional splashText = PetroleumMod.getMod("petroleum.splashtext"); + if (config.isPresent() && config.get().isModuleEnabled("petroleum.splashtext") + && splashText.isPresent()) { + Optional isActive = splashText.get().getConfigOption("petroleum.splashtext.active"); + if(isActive.isPresent() && ((BooleanOption)isActive.get()).getValue()) { + drawStringWithShadow(matrices, this.textRenderer, SplashText.get(), 2, this.height - 20, blink(13108374) | l); + } + } + } + + /** + * fades an integer color based on the values declared at the top of the class. + * + * @param color the integer representation of the color to fade. this should generally remain constant. + * @return the color, adjusted for "opacity". It's RGB and not RGBA, so it just lowers all color values. + */ + @SuppressWarnings("SameParameterValue") + private int blink(int color) { + /* + The Speed. + */ + int speed = 3; + /* + The Opacity max. + */ + double opacity_max = 1000; + if (ascending) { + opacity += speed; + if (opacity > opacity_max) { + opacity = opacity_max; + ascending = false; + } + } else { + opacity -= speed; + /* + The Opacity min. + */ + double opacity_min = 500; + if (opacity < opacity_min) { + opacity = opacity_min; + ascending = true; + } + } + double opacityD = (opacity / opacity_max); + /* + The R mask. + */ + int r_mask = 16711680; + int r = ((color & r_mask) / Integer.parseInt("010000", 16)); + /* + The G mask. + */ + int g_mask = 65280; + int g = ((color & g_mask) / Integer.parseInt("000100", 16)); + /* + The B mask. + */ + int b_mask = 255; + int b = ((color & b_mask)); + return ((int) (r * opacityD) * Integer.parseInt("010000", 16)) | + ((int) (g * opacityD) * Integer.parseInt("000100", 16)) | + ((int) (b * opacityD)); + } +} diff --git a/src/main/java/pm/j4/petroleum/modules/ExampleModule.java b/src/main/java/pm/j4/petroleum/modules/ExampleModule.java new file mode 100644 index 0000000..eceefac --- /dev/null +++ b/src/main/java/pm/j4/petroleum/modules/ExampleModule.java @@ -0,0 +1,42 @@ +package pm.j4.petroleum.modules; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import net.minecraft.client.MinecraftClient; +import net.minecraft.text.LiteralText; +import pm.j4.petroleum.gui.PModuleConfigEntry; +import pm.j4.petroleum.gui.PModuleConfigPane; +import pm.j4.petroleum.util.module.ModuleBase; +import pm.j4.petroleum.util.module.option.BooleanOption; +import pm.j4.petroleum.util.module.option.ConfigurationOption; + +/** + * The type Example module. + */ +public class ExampleModule extends ModuleBase { + /** + * example mod + */ + public ExampleModule() { + super("petroleum.example", + "petroleum.misc", + true, + false, + true); + } + + @Override + public List getDefaultConfig() { + List options = new ArrayList<>(); + options.add(new BooleanOption("petroleum.example.b_one","example", this)); + options.add(new BooleanOption("petroleum.example.b_two","example", this)); + return options; + } + + @Override + public void activate(MinecraftClient client) { + System.out.println("Example Mod Keybind Activate"); + } +} diff --git a/src/main/java/pm/j4/petroleum/modules/bindings/BindingInfo.java b/src/main/java/pm/j4/petroleum/modules/bindings/BindingInfo.java new file mode 100644 index 0000000..c147d8a --- /dev/null +++ b/src/main/java/pm/j4/petroleum/modules/bindings/BindingInfo.java @@ -0,0 +1,30 @@ +package pm.j4.petroleum.modules.bindings; + +import net.minecraft.client.util.InputUtil; + +/** + * The type Binding info. + */ +public class BindingInfo { + /** + * The Translation key. + */ + public String translationKey; + /** + * The Type. + */ + public InputUtil.Type type; + /** + * The Key. + */ + public int key; + /** + * The Category. + */ + public String category; + + /** + * The Attached function id. + */ + public String attachedModuleName; +} diff --git a/src/main/java/pm/j4/petroleum/modules/bindings/BindingManager.java b/src/main/java/pm/j4/petroleum/modules/bindings/BindingManager.java new file mode 100644 index 0000000..33d4c39 --- /dev/null +++ b/src/main/java/pm/j4/petroleum/modules/bindings/BindingManager.java @@ -0,0 +1,89 @@ +package pm.j4.petroleum.modules.bindings; + +import java.util.*; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.options.KeyBinding; +import net.minecraft.client.util.InputUtil; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.TranslatableText; +import org.lwjgl.glfw.GLFW; +import pm.j4.petroleum.PetroleumMod; +import pm.j4.petroleum.gui.PModuleConfigEntry; +import pm.j4.petroleum.gui.PModuleConfigPane; +import pm.j4.petroleum.util.config.ConfigManager; +import pm.j4.petroleum.util.config.GlobalConfig; +import pm.j4.petroleum.util.module.ModuleBase; +import pm.j4.petroleum.util.module.option.ConfigurationOption; +import pm.j4.petroleum.util.module.option.KeybindOption; + +/** + * The type Binding manager. + */ +public class BindingManager extends ModuleBase { + /** + * Instantiates a new Module base. + * Parameters should be constant across restarts. + */ + public BindingManager() { + super("petroleum.bindings", + "petroleum.misc", + false, + true, + true); + } + + @Override + public void init() { + registerBindings(); + super.init(); + } + + @Override + public List getConfigEntries(PModuleConfigPane sourcePane) { + + //TODO multiple binds per module + // thoughts: have modules include a list of module triggers/functions + // which replace the ModuleBase in bindings? + List entries = new ArrayList<>(); + + Map mapped = new HashMap<>(); + if (ConfigManager.getConfig().isPresent()) { + Map binds = ConfigManager.getConfig().get().globalConfig.bindings; + + binds.forEach((key, func) -> { + KeybindOption option = new KeybindOption(func.getModuleName() + " " + func.getCategory(), func.getModuleName() + " " + func.getCategory(), func); + option.fromKeybind(key, func); + mapped.put(option, func); + }); + } + mapped.forEach((configEntry, module) -> { + PModuleConfigEntry entry = new PModuleConfigEntry(configEntry, new TranslatableText(module.getModuleName()), sourcePane); + entries.add(entry); + }); + return entries; + } + + /** + * Register bindings. + */ + private void registerBindings() { + if (!ConfigManager.getConfig().isPresent()) { + return; + } + GlobalConfig c = ConfigManager.getConfig().get().globalConfig; + Optional mod = PetroleumMod.getMod("petroleum.modmenu"); + if (mod.isPresent() && !c.isBound(mod.get())) { + //TODO + // the only explicit keybinding (for now.) + // once the binding manager has been completed, + // this should be migrated there, as a default binding + KeyBinding binding = new KeyBinding( + "key.petroleum.togglemodmenu", + InputUtil.Type.KEYSYM, + GLFW.GLFW_KEY_RIGHT_CONTROL, + "category.petroleum" + ); + ConfigManager.getConfig().get().globalConfig.setBinding(binding, mod.get()); + } + } +} diff --git a/src/main/java/pm/j4/petroleum/modules/list/ModList.java b/src/main/java/pm/j4/petroleum/modules/list/ModList.java new file mode 100644 index 0000000..cc473b3 --- /dev/null +++ b/src/main/java/pm/j4/petroleum/modules/list/ModList.java @@ -0,0 +1,40 @@ +package pm.j4.petroleum.modules.list; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import pm.j4.petroleum.util.config.ConfigHolder; +import pm.j4.petroleum.util.config.ConfigManager; +import pm.j4.petroleum.util.module.ModuleBase; + +/** + * The type Mod list. + */ +public class ModList extends ModuleBase { + /** + * Instantiates a new Mod list. + */ + public ModList() { + super("petroleum.modlist", + "petroleum.misc", + true, + true, + true); + } + + /** + * Gets active. + * + * @return the active + */ + public static List getActive() { + List result = new ArrayList<>(); + Optional config = ConfigManager.getConfig(); + config.ifPresent(configHolder -> configHolder.getEnabledModules().forEach((mod) -> { + if (!mod.isHidden()) { + result.add(mod); + } + })); + return result; + } +} diff --git a/src/main/java/pm/j4/petroleum/modules/menu/ModMenu.java b/src/main/java/pm/j4/petroleum/modules/menu/ModMenu.java new file mode 100644 index 0000000..7ed0500 --- /dev/null +++ b/src/main/java/pm/j4/petroleum/modules/menu/ModMenu.java @@ -0,0 +1,98 @@ +package pm.j4.petroleum.modules.menu; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import net.minecraft.client.MinecraftClient; +import pm.j4.petroleum.gui.PModMenuScreen; +import pm.j4.petroleum.util.config.ConfigManager; +import pm.j4.petroleum.util.data.ButtonInformation; +import pm.j4.petroleum.util.data.Category; +import pm.j4.petroleum.util.module.ModuleBase; + +/** + * The type Mod menu. + */ +public class ModMenu extends ModuleBase { + + /** + * The constant coordinates. + */ + private static final Map coordinates = new HashMap<>(); + + /** + * Instantiates a new Mod menu. + */ + public ModMenu() { + super("petroleum.modmenu", + "petroleum.misc", + true, + true, + true); + } + + // TODO figure out resizing + // the number itself changes, so it should just be probably like some onResize bullshit in PModMenuScreen + @Override + public void init() { + Map> categories = Category.getCategoryMap(); + final double[] h = {.1}; + categories.forEach((category, moduleList) -> { + ButtonInformation conf = ConfigManager.getConfig().isPresent() ? + ConfigManager.getConfig().get().globalConfig.getButton(category) : + null; + ButtonInformation coord = conf != null ? conf : new ButtonInformation(.1, h[0], false); + h[0] += .01; + coordinates.put(category, coord); + if (ConfigManager.getConfig().isPresent()) { + ConfigManager.getConfig().get().globalConfig.setButton(category, coord); + } + }); + } + + /** + * Update coord. + * + * @param b the b + * @param c the c + */ + public static void updateCoord(String b, ButtonInformation c) { + if (c.x < 0.05) { + c.x = 0.05; + } + if (c.x > .95) { + c.x = .95; + } + if (c.y < 0.05) { + c.y = 0.05; + } + if (c.y > .95) { + c.y = .95; + } + if (coordinates.containsKey(b)) { + coordinates.replace(b, c); + if (ConfigManager.getConfig().isPresent()) { + ConfigManager.getConfig().get().globalConfig.setButton(b, c); + } + } + } + + @Override + public void activate(MinecraftClient client) { + this.toggle(); + if (ConfigManager.getConfig().get().isModuleEnabled(this.getModuleName())) { + client.openScreen(new PModMenuScreen()); + } else { + client.openScreen(null); + } + } + + /** + * Gets buttons. + * + * @return the buttons + */ + public static Map getButtons() { + return coordinates; + } +} \ No newline at end of file diff --git a/src/main/java/pm/j4/petroleum/modules/splash/SplashText.java b/src/main/java/pm/j4/petroleum/modules/splash/SplashText.java new file mode 100644 index 0000000..c5b6f88 --- /dev/null +++ b/src/main/java/pm/j4/petroleum/modules/splash/SplashText.java @@ -0,0 +1,46 @@ +package pm.j4.petroleum.modules.splash; + +import java.util.ArrayList; +import java.util.List; +import net.minecraft.text.LiteralText; +import pm.j4.petroleum.PetroleumMod; +import pm.j4.petroleum.gui.PModuleConfigEntry; +import pm.j4.petroleum.gui.PModuleConfigPane; +import pm.j4.petroleum.util.module.ModuleBase; +import pm.j4.petroleum.util.module.option.BooleanOption; +import pm.j4.petroleum.util.module.option.ConfigurationOption; + +/** + * The type Splash text. + */ +public class SplashText extends ModuleBase { + /** + * Instantiates a new Splash text. + */ + public SplashText() { + super("petroleum.splashtext", + "petroleum.misc", + false, + true, + true); + } + + @Override + public List getDefaultConfig() { + List options = new ArrayList<>(); + options.add(new BooleanOption("petroleum.splashtext.active", "Show the main menu version text.", this)); + return options; + } + + /** + * Get string. + * + * @return the string + */ + public static String get() { + if (PetroleumMod.modData != null) { + return "Petroleum v" + PetroleumMod.modData.getVersion().getFriendlyString(); + } + return "Petroleum vUnknown"; + } +} diff --git a/src/main/java/pm/j4/petroleum/modules/xray/Xray.java b/src/main/java/pm/j4/petroleum/modules/xray/Xray.java new file mode 100644 index 0000000..7e31116 --- /dev/null +++ b/src/main/java/pm/j4/petroleum/modules/xray/Xray.java @@ -0,0 +1,19 @@ +package pm.j4.petroleum.modules.xray; + +import pm.j4.petroleum.util.module.ModuleBase; + +/** + * The type Xray. + */ +public class Xray extends ModuleBase { + /** + * Instantiates a new Xray. + */ + public Xray() { + super("petroleum.xray", + "petroleum.render", + true, + false, + true); + } +} diff --git a/src/main/java/pm/j4/petroleum/util/config/Config.java b/src/main/java/pm/j4/petroleum/util/config/Config.java new file mode 100644 index 0000000..695be65 --- /dev/null +++ b/src/main/java/pm/j4/petroleum/util/config/Config.java @@ -0,0 +1,59 @@ +package pm.j4.petroleum.util.config; + +import java.util.ArrayList; +import java.util.List; +import pm.j4.petroleum.PetroleumMod; +import pm.j4.petroleum.util.module.ModuleBase; + +/** + * The type Config. + */ +public abstract class Config { + /** + * The Enabled modules. + */ + public List enabledModules = new ArrayList<>(); + + /** + * Is enabled boolean. + * + * @param mod the mod + * @return the boolean + */ + public boolean isEnabled(String mod) { + return enabledModules.contains(mod); + } + + + /** + * Disable module. + * + * @param mod the mod + */ + public void disableModule(String mod) { + if (isEnabled(mod) && PetroleumMod.isActive(mod) && PetroleumMod.getMod(mod).isPresent()) { + ModuleBase moduleInfo = PetroleumMod.getMod(mod).get(); + if (moduleInfo.isActivatable()) { + enabledModules.remove(mod); + } + } + } + + /** + * Toggle module. + * + * @param mod the mod + */ + public void toggleModule(String mod) { + if (PetroleumMod.isActive(mod) && PetroleumMod.getMod(mod).isPresent()) { + ModuleBase moduleInfo = PetroleumMod.getMod(mod).get(); + if (moduleInfo.isActivatable()) { + if (isEnabled(mod)) { + enabledModules.remove(mod); + } else { + enabledModules.add(mod); + } + } + } + } +} diff --git a/src/main/java/pm/j4/petroleum/util/config/ConfigHolder.java b/src/main/java/pm/j4/petroleum/util/config/ConfigHolder.java new file mode 100644 index 0000000..f4a68ba --- /dev/null +++ b/src/main/java/pm/j4/petroleum/util/config/ConfigHolder.java @@ -0,0 +1,94 @@ +package pm.j4.petroleum.util.config; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import pm.j4.petroleum.PetroleumMod; +import pm.j4.petroleum.util.module.ModuleBase; + +/** + * The type Config holder. + */ +public class ConfigHolder { + /** + * The Global config. + */ + public GlobalConfig globalConfig; + /** + * The Server configs. + */ + public Map serverConfigs; + + /** + * Is module enabled boolean. + * + * @param module the module + * @return the boolean + */ + public boolean isModuleEnabled(String module) { + + if (!PetroleumMod.isActive(module)) { + return false; + } + if (globalConfig.isEnabled(module)) { + return true; + } + String server = this.getServer(); + if (serverConfigs.containsKey(server)) { + return serverConfigs.get(server).isEnabled(module); + } + return false; + } + + /** + * Gets enabled modules. + * + * @return the enabled modules + */ + public List getEnabledModules() { + List modules = PetroleumMod.getActiveMods(); + return modules.stream().filter(module -> + isModuleEnabled(module.getModuleName()) + ).collect(Collectors.toList()); + } + + /** + * Gets server. + * + * @return the server + */ + public String getServer() { + return PetroleumMod.getServerAddress(); + } + + /** + * Toggle module. + * + * @param module the module + */ + public void toggleModule(String module) { + String server = this.getServer(); + if (serverConfigs.containsKey(server)) { + System.out.println("Toggling module " + module + " on server " + server); + serverConfigs.get(server).toggleModule(module); + } else { + globalConfig.toggleModule(module); + } + } + + /** + * Disable module. + * + * @param module the module + */ + public void disableModule(String module) { + String server = this.getServer(); + if (serverConfigs.containsKey(server)) { + System.out.println("disabling module " + module + " on server " + server); + serverConfigs.get(server).disableModule(module); + } else { + globalConfig.disableModule(module); + } + } + +} diff --git a/src/main/java/pm/j4/petroleum/util/config/ConfigManager.java b/src/main/java/pm/j4/petroleum/util/config/ConfigManager.java new file mode 100644 index 0000000..f44e8b6 --- /dev/null +++ b/src/main/java/pm/j4/petroleum/util/config/ConfigManager.java @@ -0,0 +1,270 @@ +package pm.j4.petroleum.util.config; + +import com.google.common.reflect.TypeToken; +import com.google.gson.*; +import java.io.*; +import java.lang.reflect.Type; +import java.util.*; +import net.fabricmc.loader.api.FabricLoader; +import pm.j4.petroleum.PetroleumMod; +import pm.j4.petroleum.modules.bindings.BindingInfo; +import pm.j4.petroleum.modules.menu.ModMenu; +import pm.j4.petroleum.util.data.ButtonInformation; +import pm.j4.petroleum.util.data.ModuleConfig; +import pm.j4.petroleum.util.data.OptionSerializiable; +import pm.j4.petroleum.util.module.ModuleBase; + +/** + * The type Config manager. + */ +public class ConfigManager { + /** + * The constant GSON. + */ + public static final Gson GSON = new GsonBuilder() + .registerTypeAdapter(GlobalConfig.class, SerializationHelper.getGlobalSerializer()) + .registerTypeAdapter(GlobalConfig.class, SerializationHelper.getGlobalDeserializer()) + .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).setPrettyPrinting().create(); + /** + * The constant config. + */ + private static ConfigHolder config; + + /** + * Prepare config file. + * + * @param path the path + * @param filename the filename + * @return the file + */ + private static File prepareConfigFile(String path, String filename) { + if (path != "") { + File directory = new File(FabricLoader.getInstance().getConfigDir().toString(), path); + if (!directory.exists()) directory.mkdir(); + } + return new File(FabricLoader.getInstance().getConfigDir().toString(), path + filename); + } + + /** + * Init config. + */ + public static void initConfig() { + if (config != null) { + return; + } + + config = new ConfigHolder(); + config.globalConfig = new DefaultConfig(); + config.serverConfigs = new HashMap<>(); + + config = load("petroleum/", "petroleum.json", ConfigHolder.class); + initModules(); + } + + /** + * Init modules. + */ + public static void initModules() { + PetroleumMod.getActiveMods().forEach(module -> { + ModuleConfig options = load("petroleum/modules/", module.getModuleName() + ".json", ModuleConfig.class); + if (options != null && options.options != null) { + options.options.forEach((key, option) -> { + if (module.hasOption(option.key)) { + module.setConfigOption(option.key, option.value); + } + }); + } + }); + } + + /** + * Load. + * + * @param the type parameter + * @param path the path + * @param filename the filename + * @param tClass the t class + * @return the t + */ + private static T load(String path, String filename, Class tClass) { + File file = prepareConfigFile(path, filename); + + try { + if (!file.exists()) { + save(path, filename, tClass.newInstance()); + } + if (file.exists()) { + BufferedReader reader = new BufferedReader(new FileReader(file)); + T parsedConfig = null; + try { + parsedConfig = GSON.fromJson(reader, tClass); + } catch (Exception e) { + System.out.println("Couldn't parse config file"); + e.printStackTrace(); + } + if (parsedConfig != null) { + return parsedConfig; + } + } + } catch (FileNotFoundException | InstantiationException | IllegalAccessException e) { + System.out.println("Couldn't load configuration file at " + path); + e.printStackTrace(); + } + return null; + } + + /** + * Deserialize element t. + * + * @param the type parameter + * @param element the element + * @param tClass the t class + * @return the t + */ + public static T deserializeElement(JsonElement element, Class tClass) { + return GSON.fromJson(element, tClass); + } + + /** + * Save. + * + * @param the type parameter + * @param path the path + * @param filename the filename + * @param data the data + */ + private static void save(String path, String filename, T data) { + File file = prepareConfigFile(path, filename); + + String json = GSON.toJson(data); + try (FileWriter fileWriter = new FileWriter(file)) { + fileWriter.write(json); + } catch (IOException e) { + System.out.println("Couldn't save configuration file at " + path); + e.printStackTrace(); + } + } + + /** + * Save module. + * + * @param b the b + */ + public static void saveModule(ModuleBase b) { + ModuleConfig c = new ModuleConfig(); + c.options = GlobalConfig.serializeModuleConfiguration(b); + save("petroleum/modules/", b.getModuleName() + ".json", c); + } + + /** + * Save all modules. + */ + public static void saveAllModules() { + List mods = PetroleumMod.getActiveMods(); + mods.forEach(ConfigManager::saveModule); + } + + /** + * Save global config. + */ + public static void saveGlobalConfig() { + save("petroleum/", "petroleum.json", config); + } + + /** + * Gets config. + * + * @return the config + */ + public static Optional getConfig() { + if (config == null) { + return Optional.empty(); + } + return Optional.of(config); + } +} + +/** + * The type Serialization helper. + */ +class SerializationHelper { + + /** + * The constant s. + */ + private static final JsonSerializer GLOBAL_CONFIG_JSON_SERIALIZER = (src, typeOfSrc, ctx) -> { + JsonObject jsonConfig = new JsonObject(); + + JsonArray bindings = ctx.serialize(src.serializeBindings()).getAsJsonArray(); + jsonConfig.add("bindings", bindings); + + JsonArray modules = ctx.serialize(src.enabledModules).getAsJsonArray(); + jsonConfig.add("enabled_modules", modules); + + JsonObject tabCoordinates = new JsonObject(); + ModMenu.getButtons().forEach((category, coordinates) -> { + tabCoordinates.add(category, ctx.serialize(coordinates)); + }); + jsonConfig.add("button_coordinates", tabCoordinates); + + return jsonConfig; + }; + + /** + * The constant ds. + */ + private static final JsonDeserializer GLOBAL_CONFIG_JSON_DESERIALIZER = ((json, typeOfT, ctx) -> { + JsonObject obj = json.getAsJsonObject(); + + List bindings = new ArrayList<>(); + if (obj.has("bindings")) { + obj.get("bindings").getAsJsonArray().forEach(b -> bindings.add(ctx.deserialize(b, BindingInfo.class))); + } + List modules = new ArrayList<>(); + if (obj.has("enabled_modules")) { + obj.get("enabled_modules").getAsJsonArray().forEach(m -> modules.add(m.getAsString())); + } + GlobalConfig cfg = new GlobalConfig(); + Map> options; + Type type = new TypeToken>>() { + }.getType(); + if (obj.has("module_configuration")) { + options = ctx.deserialize(obj.get("module_configuration"), type); + } else { + options = new HashMap<>(); + } + if (obj.has("button_coordinates")) { + obj.get("button_coordinates").getAsJsonObject().entrySet().forEach( + value -> { + cfg.setButton(value.getKey(), ctx.deserialize(value.getValue(), ButtonInformation.class)); + } + ); + } + PetroleumMod.getActiveMods().forEach(module -> { + if (options.containsKey(module.getModuleName())) { + cfg.deserializeModuleConfiguration(options.get(module.getModuleName()), module); + } + }); + cfg.deserializeBindings(bindings); + cfg.enabledModules = modules; + return cfg; + }); + + /** + * Gets serializer. + * + * @return the serializer + */ + public static JsonSerializer getGlobalSerializer() { + return GLOBAL_CONFIG_JSON_SERIALIZER; + } + + /** + * Gets deserializer. + * + * @return the deserializer + */ + public static JsonDeserializer getGlobalDeserializer() { + return GLOBAL_CONFIG_JSON_DESERIALIZER; + } +} \ No newline at end of file diff --git a/src/main/java/pm/j4/petroleum/util/config/DefaultConfig.java b/src/main/java/pm/j4/petroleum/util/config/DefaultConfig.java new file mode 100644 index 0000000..f50bea2 --- /dev/null +++ b/src/main/java/pm/j4/petroleum/util/config/DefaultConfig.java @@ -0,0 +1,15 @@ +package pm.j4.petroleum.util.config; + +import java.util.Collections; + +/** + * The type Default config. + */ +public class DefaultConfig extends GlobalConfig { + /** + * Instantiates a new Default config. + */ + public DefaultConfig() { + this.enabledModules = Collections.singletonList("petroleum.splashtext"); + } +} diff --git a/src/main/java/pm/j4/petroleum/util/config/GlobalConfig.java b/src/main/java/pm/j4/petroleum/util/config/GlobalConfig.java new file mode 100644 index 0000000..97a5d16 --- /dev/null +++ b/src/main/java/pm/j4/petroleum/util/config/GlobalConfig.java @@ -0,0 +1,195 @@ +package pm.j4.petroleum.util.config; + +import java.util.*; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; +import net.minecraft.client.options.KeyBinding; +import net.minecraft.client.util.InputUtil; +import pm.j4.petroleum.PetroleumMod; +import pm.j4.petroleum.modules.bindings.BindingInfo; +import pm.j4.petroleum.util.data.ButtonInformation; +import pm.j4.petroleum.util.data.OptionSerializiable; +import pm.j4.petroleum.util.module.ModuleBase; +import pm.j4.petroleum.util.module.option.ConfigurationOption; + +/** + * The type Global config. + */ +public class GlobalConfig extends Config { + /** + * The Bindings. + */ + public final Map bindings = new HashMap<>(); + + /** + * Is bound boolean. + * + * @param func the func + * @return the boolean + */ + public boolean isBound(ModuleBase func) { + AtomicBoolean found = new AtomicBoolean(false); + bindings.forEach((key, binding) -> { + if (binding.equals(func)) { + found.set(true); + } + }); + return found.get(); + } + + /** + * Sets binding. + * + * @param bind the bind + * @param func the func + */ + public void setBinding(KeyBinding bind, ModuleBase func) { + AtomicReference match = new AtomicReference<>(); + if (bindings.containsValue(func)) { + bindings.forEach((key, binding) -> { + if (binding.equals(func)) { + PetroleumMod.removeBind(key); + match.set(key); + } + }); + } + + if (match.get() != null) { + bindings.remove(match.get()); + } + + if (PetroleumMod.isActive(func.getModuleName())) { + PetroleumMod.addBind(bind); + bindings.put(bind, func); + } + } + + /** + * Convert binding. + * + * @param info the info + */ + private void convertBinding(BindingInfo info) { + Optional match = PetroleumMod.getMod(info.attachedModuleName); + match.ifPresent(moduleBase -> setBinding(reconstructBinding(info), + moduleBase)); + } + + /** + * Reconstruct binding key binding. + * + * @param info the info + * @return the key binding + */ + public static KeyBinding reconstructBinding(BindingInfo info) { + return new KeyBinding( + info.translationKey, + info.type, + info.key, + info.category + ); + } + + /** + * Extract binding info. + * + * @param b the b + * @param f the f + * @return the binding info + */ + public static BindingInfo extractBinding(KeyBinding b, ModuleBase f) { + BindingInfo res = new BindingInfo(); + res.attachedModuleName = f.getModuleName(); + + res.translationKey = b.getTranslationKey(); + InputUtil.Key k = b.getDefaultKey(); + res.type = k.getCategory(); + res.key = k.getCode(); + res.category = b.getCategory(); + + return res; + } + + /** + * Serialize bindings list. + * + * @return the list + */ + public List serializeBindings() { + List b = new ArrayList<>(); + bindings.forEach((k, f) -> b.add(extractBinding(k, f))); + return b; + } + + /** + * Deserialize bindings. + * + * @param info the info + */ + public void deserializeBindings(List info) { + info.forEach(this::convertBinding); + } + + /** + * Serialize module configuration list. + * + * @param module the module + * @return the list + */ + public static Map serializeModuleConfiguration(ModuleBase module) { + Map opts = new HashMap<>(); + Map configuration = module.getModuleConfiguration(); + configuration.forEach((key, value) -> { + opts.put(key, new OptionSerializiable(key, value.toJson())); + }); + return opts; + } + + /** + * Deserialize module configuration. + * + * @param opts the opts + * @param module the module + */ + public void deserializeModuleConfiguration(List opts, ModuleBase module) { + opts.forEach(option -> { + if (module.hasOption(option.key)) { + module.setConfigOption(option.key, option.value); + } + }); + } + + /** + * The Button locations. + */ + private final Map buttonLocations = new HashMap<>(); + + /** + * Sets button. + * + * @param category the category + * @param buttonInformation the button information + */ + public void setButton(String category, ButtonInformation buttonInformation) { + if (buttonLocations.containsKey(category)) { + buttonLocations.replace(category, buttonInformation); + } else { + buttonLocations.put(category, buttonInformation); + } + } + + /** + * Gets button. + * + * @param category the category + * @return the button + */ + public ButtonInformation getButton(String category) { + if (buttonLocations.containsKey(category)) { + return buttonLocations.get(category); + } + System.out.println("Could not find button of category " + category); + return null; + } +} + diff --git a/src/main/java/pm/j4/petroleum/util/config/ServerConfig.java b/src/main/java/pm/j4/petroleum/util/config/ServerConfig.java new file mode 100644 index 0000000..9df6464 --- /dev/null +++ b/src/main/java/pm/j4/petroleum/util/config/ServerConfig.java @@ -0,0 +1,11 @@ +package pm.j4.petroleum.util.config; + +/** + * The type Server config. + */ +public class ServerConfig extends Config { + /** + * The Address. + */ + public String address = ""; +} diff --git a/src/main/java/pm/j4/petroleum/util/data/ButtonInformation.java b/src/main/java/pm/j4/petroleum/util/data/ButtonInformation.java new file mode 100644 index 0000000..3eb4834 --- /dev/null +++ b/src/main/java/pm/j4/petroleum/util/data/ButtonInformation.java @@ -0,0 +1,32 @@ +package pm.j4.petroleum.util.data; + +/** + * The type Button information. + */ +public class ButtonInformation { + /** + * The X. + */ + public double x; + /** + * The Y. + */ + public double y; + /** + * The Open. + */ + public final boolean open; + + /** + * Instantiates a new Button information. + * + * @param x the x + * @param y the y + * @param open the open + */ + public ButtonInformation(double x, double y, boolean open) { + this.x = x; + this.y = y; + this.open = open; + } +} diff --git a/src/main/java/pm/j4/petroleum/util/data/Category.java b/src/main/java/pm/j4/petroleum/util/data/Category.java new file mode 100644 index 0000000..c2210a5 --- /dev/null +++ b/src/main/java/pm/j4/petroleum/util/data/Category.java @@ -0,0 +1,47 @@ +package pm.j4.petroleum.util.data; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import pm.j4.petroleum.PetroleumMod; +import pm.j4.petroleum.util.module.ModuleBase; + +/** + * The type Category. + */ +public class Category { + /** + * Gets category map. + * + * @return the category map + */ + public static Map> getCategoryMap() { + List modules = PetroleumMod.getActiveMods(); + Map> categoryMap = new HashMap<>(); + modules.forEach(module -> { + if (!categoryMap.containsKey(module.getCategory())) { + List m = new ArrayList<>(); + m.add(module); + categoryMap.put(module.getCategory(), m); + } else { + List m = categoryMap.get(module.getCategory()); + List nm = new ArrayList<>(); + nm.addAll(m); + nm.add(module); + categoryMap.replace(module.getCategory(), nm); + } + }); + return categoryMap; + } + + /** + * Gets by category. + * + * @param category the category + * @return the by category + */ + public static List getByCategory(String category) { + return getCategoryMap().containsKey(category) ? getCategoryMap().get(category) : new ArrayList<>(); + } +} diff --git a/src/main/java/pm/j4/petroleum/util/data/ModuleConfig.java b/src/main/java/pm/j4/petroleum/util/data/ModuleConfig.java new file mode 100644 index 0000000..33c1365 --- /dev/null +++ b/src/main/java/pm/j4/petroleum/util/data/ModuleConfig.java @@ -0,0 +1,13 @@ +package pm.j4.petroleum.util.data; + +import java.util.Map; + +/** + * The type Module config. + */ +public class ModuleConfig { + /** + * The Options. + */ + public Map options; +} diff --git a/src/main/java/pm/j4/petroleum/util/data/OptionSerializiable.java b/src/main/java/pm/j4/petroleum/util/data/OptionSerializiable.java new file mode 100644 index 0000000..197332f --- /dev/null +++ b/src/main/java/pm/j4/petroleum/util/data/OptionSerializiable.java @@ -0,0 +1,28 @@ +package pm.j4.petroleum.util.data; + +import com.google.gson.JsonElement; + +/** + * The type Option serializiable. + */ +public class OptionSerializiable { + /** + * Instantiates a new Option serializiable. + * + * @param key the key + * @param value the value + */ + public OptionSerializiable(String key, JsonElement value) { + this.value = value; + this.key = key; + } + + /** + * The Value. + */ + public final JsonElement value; + /** + * The Key. + */ + public final String key; +} diff --git a/src/main/java/pm/j4/petroleum/util/module/ModuleBase.java b/src/main/java/pm/j4/petroleum/util/module/ModuleBase.java new file mode 100644 index 0000000..012d550 --- /dev/null +++ b/src/main/java/pm/j4/petroleum/util/module/ModuleBase.java @@ -0,0 +1,248 @@ +package pm.j4.petroleum.util.module; + +import com.google.gson.JsonElement; +import java.util.*; +import net.minecraft.client.MinecraftClient; +import net.minecraft.text.TranslatableText; +import pm.j4.petroleum.gui.PModuleConfigEntry; +import pm.j4.petroleum.gui.PModuleConfigPane; +import pm.j4.petroleum.util.config.ConfigHolder; +import pm.j4.petroleum.util.config.ConfigManager; +import pm.j4.petroleum.util.module.option.ConfigurationOption; + +/** + * The Basis for all mods, used so that modules all have a common activation point and settings. + */ +public abstract class ModuleBase { + + /** + * Instantiates a new Module base. + * Parameters should be constant across restarts. + * + * @param name The name of the module + * @param category the category + * @param activatable Whether a module can be activated, or if it will remain in the state it was upon startup + * @param hidden Whether the module will show up in @link pm.j4.petroleum.modules.menu.ModMenu or the active module list + * @param hasConfigMenu whether a button in the configuration menu will show + */ + public ModuleBase(String name, String category, boolean activatable, boolean hidden, boolean hasConfigMenu) { + this.moduleName = name; + this.category = category; + this.readableName = new TranslatableText(name); + this.activatable = activatable; + this.hidden = hidden; + this.hasConfigMenu = hasConfigMenu; + this.moduleOptions = this.convertDefaultConfig(); + } + + /** + * Init. + */ + public void init() { + + } + + /** + * Activate. Should be overridden. + * + * @param client the client + */ + public void activate(MinecraftClient client) { + this.toggle(); + } + + /** + * Toggle mod. + */ + public void toggle() { + Optional config = ConfigManager.getConfig(); + config.ifPresent(configHolder -> configHolder.toggleModule(this.moduleName)); + } + + /** + * The Module's name. + */ + private final String moduleName; + + /** + * Gets module name. + * + * @return the module name + */ + public String getModuleName() { + return this.moduleName; + } + + /** + * The Category. + */ + private final String category; + + /** + * Gets category. + * + * @return the category + */ + public String getCategory() { + return this.category; + } + + /** + * The Readable name. + */ + private final TranslatableText readableName; + + /** + * Gets readable name. + * + * @return the readable name + */ + public TranslatableText getReadableName() { + return this.readableName; + } + + /** + * The Activatable. + */ + private final boolean activatable; + + /** + * Is activatable boolean. + * + * @return the boolean + */ + public boolean isActivatable() { + return activatable; + } + + /** + * The Hidden. + */ + private final boolean hidden; + + /** + * Is hidden boolean. + * + * @return the boolean + */ + public boolean isHidden() { + return hidden; + } + + + /** + * The Has config menu. + */ + private final boolean hasConfigMenu; + + /** + * Configurable boolean. + * + * @return the boolean + */ + public boolean configurable() { + return hasConfigMenu; + } + + /** + * The Module options. + */ + private final Map moduleOptions; + + /** + * Gets module configuration. + * + * @return the module configuration + */ + public Map getModuleConfiguration() { + return moduleOptions; + } + + /** + * Sets config option. + * This will fail if the option is not already present in a module. + *

+ * + * @param key the key + * @param value the value + * @return whether the operation was successful. + */ + public boolean setConfigOption(String key, JsonElement value) { + if (moduleOptions.containsKey(key)) { + moduleOptions.get(key).fromJson(value); + return true; + } + return false; + } + + public void updateConfigOption(String key, ConfigurationOption option) { + System.out.println("update config option" + key + option.getStringValue()); + System.out.println(moduleOptions.keySet()); + if(moduleOptions.containsKey(key)) { + System.out.println("matched"); + moduleOptions.replace(key, option); + } + } + + /** + * Has option boolean. + * + * @param key the key + * @return the boolean + */ + public boolean hasOption(String key) { + return moduleOptions.containsKey(key); + } + + /** + * Gets default config. + * + * @return the default config + */ + protected List getDefaultConfig() { + return new ArrayList<>(); + } + + private Map convertDefaultConfig() { + List options = this.getDefaultConfig(); + Map mapped = new HashMap<>(); + options.forEach((option) -> { + mapped.put(option.getConfigKey(), option); + }); + return mapped; + } + + /** + * Gets config option. + * + * @param key the key + * @return the config option + */ + public Optional getConfigOption(String key) { + if (moduleOptions.containsKey(key)) { + return Optional.of(moduleOptions.get(key)); + } + return Optional.empty(); + } + + /** + * Gets config entries. + * + * @return the config entries + */ + public List getConfigEntries(PModuleConfigPane sourcePane) { + List entries = new ArrayList<>(); + this.getModuleConfiguration().forEach((name, option) -> entries.add(new PModuleConfigEntry(option, new TranslatableText(name), sourcePane))); + return entries; + } + + /** + * Equals boolean. + * + * @param other the other + * @return the boolean + */ + public boolean equals(ModuleBase other) { + return Objects.equals(this.moduleName, other.getModuleName()); + } +} diff --git a/src/main/java/pm/j4/petroleum/util/module/option/BooleanOption.java b/src/main/java/pm/j4/petroleum/util/module/option/BooleanOption.java new file mode 100644 index 0000000..c68e08a --- /dev/null +++ b/src/main/java/pm/j4/petroleum/util/module/option/BooleanOption.java @@ -0,0 +1,45 @@ +package pm.j4.petroleum.util.module.option; + +import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; +import pm.j4.petroleum.util.module.ModuleBase; + +/** + * The type Boolean value. + */ +public class BooleanOption extends ConfigurationOption { + /** + * The Value. + */ + private boolean value; + + /** + * Instantiates a new Configuration option. + * + * @param key + * @param description the description + */ + public BooleanOption(String key, String description, ModuleBase parent) { + super(key, description, parent); + } + + public boolean getValue() { + return value; + } + public void setValue(boolean value) { this.value = value; } + + @Override + public String getStringValue() { + return Boolean.toString(value); + } + + @Override + public void fromJson(JsonElement e) { + this.value = e.getAsBoolean(); + } + + @Override + public JsonElement toJson() { + return new JsonPrimitive(value); + } +} diff --git a/src/main/java/pm/j4/petroleum/util/module/option/ConfigurationOption.java b/src/main/java/pm/j4/petroleum/util/module/option/ConfigurationOption.java new file mode 100644 index 0000000..31005db --- /dev/null +++ b/src/main/java/pm/j4/petroleum/util/module/option/ConfigurationOption.java @@ -0,0 +1,59 @@ +package pm.j4.petroleum.util.module.option; + +import com.google.gson.JsonElement; +import pm.j4.petroleum.util.module.ModuleBase; + +/** + * The type Configuration option. + */ +public abstract class ConfigurationOption { + /** + * The Description. + */ + private final String description; + private final String key; + private final ModuleBase parent; + + /** + * Instantiates a new Configuration option. + * + * @param description the description + */ + public ConfigurationOption(String key, String description, ModuleBase parent) { + this.description = description; + this.key = key; + this.parent = parent; + } + /** + * Gets description. + * + * @return the description + */ + public final String getDescription() { + return this.description; + } + public final String getConfigKey() { return key; } + public final ModuleBase getParent() { return parent; } + + /** + * Gets string value. + * + * @return the string value + */ + public abstract String getStringValue(); + + /** + * From json. + * + * @param e the e + */ + public abstract void fromJson(JsonElement e); + + /** + * To json json element. + * + * @return the json element + */ + public abstract JsonElement toJson(); + +} diff --git a/src/main/java/pm/j4/petroleum/util/module/option/IntegerOption.java b/src/main/java/pm/j4/petroleum/util/module/option/IntegerOption.java new file mode 100644 index 0000000..ea938e6 --- /dev/null +++ b/src/main/java/pm/j4/petroleum/util/module/option/IntegerOption.java @@ -0,0 +1,42 @@ +package pm.j4.petroleum.util.module.option; + +import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; +import pm.j4.petroleum.util.module.ModuleBase; + +/** + * The type Integer value. + */ +public class IntegerOption extends ConfigurationOption { + /** + * The Value. + */ + private int value; + + /** + * Instantiates a new Configuration option. + * + * @param key + * @param description the description + * @param parent + */ + public IntegerOption(String key, String description, ModuleBase parent) { + super(key, description, parent); + } + + + @Override + public String getStringValue() { + return Integer.toString(value); + } + + @Override + public void fromJson(JsonElement e) { + this.value = e.getAsInt(); + } + + @Override + public JsonElement toJson() { + return new JsonPrimitive(value); + } +} diff --git a/src/main/java/pm/j4/petroleum/util/module/option/KeybindOption.java b/src/main/java/pm/j4/petroleum/util/module/option/KeybindOption.java new file mode 100644 index 0000000..7fe2d6e --- /dev/null +++ b/src/main/java/pm/j4/petroleum/util/module/option/KeybindOption.java @@ -0,0 +1,66 @@ +package pm.j4.petroleum.util.module.option; + +import com.google.gson.JsonElement; +import net.minecraft.client.options.KeyBinding; +import pm.j4.petroleum.modules.bindings.BindingInfo; +import pm.j4.petroleum.util.config.ConfigManager; +import pm.j4.petroleum.util.config.GlobalConfig; +import pm.j4.petroleum.util.module.ModuleBase; + +/** + * The type Keybind value. + */ +public class KeybindOption extends ConfigurationOption { + + /** + * The Value. + */ + private KeyBinding value; + /** + * The Converted value. + */ + private BindingInfo convertedValue; + + /** + * Instantiates a new Configuration option. + * + * @param key + * @param description the description + * @param parent + */ + public KeybindOption(String key, String description, ModuleBase parent) { + super(key, description, parent); + } + + public String getTranslationKey() { + return value.getTranslationKey(); + } + + @Override + public String getStringValue() { + return value.getDefaultKey().getLocalizedText().getString(); + } + + @Override + public void fromJson(JsonElement e) { + BindingInfo bindingInfo = ConfigManager.deserializeElement(e, BindingInfo.class); + this.convertedValue = bindingInfo; + this.value = GlobalConfig.reconstructBinding(bindingInfo); + } + + @Override + public JsonElement toJson() { + return null; + } + + /** + * From keybind. + * + * @param bind the bind + * @param base the base + */ + public void fromKeybind(KeyBinding bind, ModuleBase base) { + this.value = bind; + this.convertedValue = GlobalConfig.extractBinding(bind, base); + } +} diff --git a/src/main/java/pm/j4/petroleum/util/module/option/ListOption.java b/src/main/java/pm/j4/petroleum/util/module/option/ListOption.java new file mode 100644 index 0000000..204eed6 --- /dev/null +++ b/src/main/java/pm/j4/petroleum/util/module/option/ListOption.java @@ -0,0 +1,37 @@ +package pm.j4.petroleum.util.module.option; + +import com.google.gson.JsonElement; +import pm.j4.petroleum.util.module.ModuleBase; + +/** + * The type List option. + */ +public class ListOption extends ConfigurationOption { + + + /** + * Instantiates a new Configuration option. + * + * @param key + * @param description the description + * @param parent + */ + public ListOption(String key, String description, ModuleBase parent) { + super(key, description, parent); + } + + @Override + public String getStringValue() { + return "ListObject"; + } + + @Override + public void fromJson(JsonElement e) { + + } + + @Override + public JsonElement toJson() { + return null; + } +} diff --git a/src/main/java/pm/j4/petroleum/util/module/option/StringOption.java b/src/main/java/pm/j4/petroleum/util/module/option/StringOption.java new file mode 100644 index 0000000..590a5de --- /dev/null +++ b/src/main/java/pm/j4/petroleum/util/module/option/StringOption.java @@ -0,0 +1,42 @@ +package pm.j4.petroleum.util.module.option; + +import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; +import pm.j4.petroleum.util.module.ModuleBase; + +/** + * The type String value. + */ +public class StringOption extends ConfigurationOption { + + /** + * The Value. + */ + private String value; + + /** + * Instantiates a new Configuration option. + * + * @param key + * @param description the description + * @param parent + */ + public StringOption(String key, String description, ModuleBase parent) { + super(key, description, parent); + } + + + public String getStringValue() { + return value; + } + + @Override + public void fromJson(JsonElement e) { + this.value = e.getAsString(); + } + + @Override + public JsonElement toJson() { + return new JsonPrimitive(value); + } +} diff --git a/src/main/resources/assets/petroleum/icon.png b/src/main/resources/assets/petroleum/icon.png new file mode 100644 index 0000000..5980ba8 Binary files /dev/null and b/src/main/resources/assets/petroleum/icon.png differ diff --git a/src/main/resources/assets/petroleum/lang/en_us.json b/src/main/resources/assets/petroleum/lang/en_us.json new file mode 100644 index 0000000..4c689ba --- /dev/null +++ b/src/main/resources/assets/petroleum/lang/en_us.json @@ -0,0 +1,13 @@ +{ + "petroleum.bindings": "Binding Manager", + "petroleum.example": "Test Module", + "petroleum.splashtext": "Splash Text", + "petroleum.modlist": "Module List", + "petroleum.modmenu": "Mod Menu", + + "petroleum.xray": "X-ray", + + "petroleum.misc": "Miscellaneous", + "petroleum.render": "Render", + "petroleum.options": "Petroleum Options" +} \ No newline at end of file diff --git a/src/main/resources/assets/petroleum/textures/options_background.png b/src/main/resources/assets/petroleum/textures/options_background.png new file mode 100644 index 0000000..d2f690b Binary files /dev/null and b/src/main/resources/assets/petroleum/textures/options_background.png differ diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json new file mode 100644 index 0000000..c246645 --- /dev/null +++ b/src/main/resources/fabric.mod.json @@ -0,0 +1,34 @@ +{ + "schemaVersion": 1, + "id": "petroleum", + "version": "${version}", + + "name": "Petroleum", + "description": "Burn it down.", + "authors": [ + "janeptrv" + ], + "contact": { + "homepage": "https://j4.pm/", + "sources": "https://gitdab.com/jane/petroleum" + }, + "license": "WTFPL", + "icon": "assets/petroleum/icon.png", + "environment": "*", + "entrypoints": { + "main": [ + "pm.j4.petroleum.PetroleumMod" + ] + }, + "mixins": [ + "petroleum.mixins.json" + ], + "depends": { + "fabricloader": ">=0.7.4", + "fabric": "*", + "minecraft": "1.16.x" + }, + "suggests": { + "flamingo": "*" + } +} diff --git a/src/main/resources/petroleum.mixins.json b/src/main/resources/petroleum.mixins.json new file mode 100644 index 0000000..1601ae6 --- /dev/null +++ b/src/main/resources/petroleum.mixins.json @@ -0,0 +1,18 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "pm.j4.petroleum.mixin", + "compatibilityLevel": "JAVA_8", + "mixins": [ + ], + "client": [ + "DebugHudMixin", + "EntryListWidgetAccessor", + "ModListMixin", + "OptionsMenuMixin", + "TitleScreenMixin" + ], + "injectors": { + "defaultRequire": 1 + } +}