diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000..7f45d8f644 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = true + +[*.{java,kts}] +indent_style = tab +tab_width = 2 \ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2df530bf07..3b6d0cbd64 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,13 +2,15 @@ name: Build on: push: - branches: [ master ] + branches: + - '*' paths-ignore: - 'README.md' - 'LICENSE' - '.gitignore' pull_request: - branches: [ master ] + branches: + - '*' paths-ignore: - 'README.md' - 'LICENSE' @@ -16,27 +18,44 @@ on: workflow_dispatch: jobs: build: - + env: + GIT_URL: ${{ github.server_url }}/${{ github.repository }}/tree/${{ github.sha }} + REF_NAME: ${{ github.ref_name }} + WEBHOOK_URL: ${{ secrets.WEBHOOK_URL }} + ACTOR: ${{ github.actor }} runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - name: Set up JDK 1.8 - uses: actions/setup-java@v1 - with: - java-version: 1.8 - - uses: actions/cache@v2 + - name: Send discord notification + id: sendmsg + if: ${{ env.WEBHOOK_URL }} + run: | + ./.github/workflows/send_webhook_update.sh + env: + STATUS: WORKING + - name: Set up JDK 8 + uses: actions/setup-java@v2 with: - path: | - ~/.gradle/caches - ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} - restore-keys: | - ${{ runner.os }}-gradle- - - name: Grant execute permission for gradlew - run: chmod +x gradlew + java-version: 8 + distribution: zulu + cache: gradle - name: Build with Gradle - run: ./gradlew build --no-daemon + run: chmod +x ./gradlew && ./gradlew setupCIWorkspace build --no-daemon - uses: actions/upload-artifact@v2 with: - path: build/libs/*.jar + path: build/libs/*-dep.jar + - name: Update discord notification + if: ${{ env.WEBHOOK_URL && success() }} + run: | + ./.github/workflows/send_webhook_update.sh + env: + STATUS: SUCCESS + MESSAGE_ID: ${{ steps.sendmsg.outputs.MESSAGE_ID }} + - name: Update discord notification + if: ${{ env.WEBHOOK_URL && failure() }} + run: | + ./.github/workflows/send_webhook_update.sh + env: + STATUS: FAILURE + MESSAGE_ID: ${{ steps.sendmsg.outputs.MESSAGE_ID }} diff --git a/.github/workflows/send_webhook_update.sh b/.github/workflows/send_webhook_update.sh new file mode 100755 index 0000000000..56852159bb --- /dev/null +++ b/.github/workflows/send_webhook_update.sh @@ -0,0 +1,88 @@ +#!/bin/bash +set -x + +COLOR_SUCCESS=8040199 +COLOR_WORKING=7472302 +COLOR_ERROR=14960972 +case "$STATUS" in + WORKING) + color="$COLOR_WORKING" + status_message="Build started." + ;; + FAILURE) + color="$COLOR_ERROR" + status_message="Build failed." + ;; + SUCCESS) + color="$COLOR_SUCCESS" + status_message="Build succeeded." + to_upload=$(echo build/libs/*-dep.jar) + upload_name=NotEnoughUpdates-beta-dep.jar + ;; +esac + +author_name="$ACTOR" +commit_hash=$(git log -1 --pretty=format:'%h') +commit_subject=$(git log -1 --pretty=format:'%s') +commit_body=$(git log -1 --pretty=format:'%b') +commit_date=$(git log -1 --pretty=format:'%ct') + +author_avatar="https://github.com/$author_name.png" + +#language=json +read -r -d '' structure <<-"EOF" +{ + "content": $status, + "username": $username, + "avatar_url": $avatar_url, + "embeds": [ + { + "color": $color, + "url": $url, + "title": $subject, + "description": $body, + "footer": { + "text": $ref + } + } + ], + "allowed_mentions": { + "parse": [] + } +} +EOF +json=$(jq -n \ + --arg body "$commit_body" \ + --arg status "$status_message" \ + --arg subject "$commit_subject" \ + --arg username "$author_name" \ + --arg avatar_url "$author_avatar" \ + --argjson color "$color" \ + --arg url "$GIT_URL" \ + --arg ref "$REF_NAME" \ + "$structure") + +function make_request() { + if [ "$to_upload" != "" ]; then + upload_arg="-F" + fi + curl -X $1 -H "Content-Type: multipart/form-data" -F "payload_json=$json" "$upload_arg" "$upload_name=@$to_upload" "$WEBHOOK_URL$2?wait=true" +} + +echo "Should replace message with id: $MESSAGE_ID" +if [ "$MESSAGE_ID" != "" ]; then + discord_output=$(make_request PATCH "/messages/$MESSAGE_ID") + RESULT=$? +else + discord_output=$(make_request POST) + RESULT=$? +fi + +if [ $RESULT != 0 ]; then + echo "$discord_output" + exit 1 +fi +echo "Message sent to discord." +echo "$discord_output" | jq . +id_string=$(echo "$discord_output" | jq .id) +echo "::set-output name=MESSAGE_ID::${id_string//\"/}" diff --git a/.gitignore b/.gitignore index e5ac98936e..a7b89d9412 100644 --- a/.gitignore +++ b/.gitignore @@ -11,7 +11,8 @@ out *.ipr *.iws *.iml -.idea +.idea/* +!.idea/codeStyles # gradle build diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000000..6cedf3ffca --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,55 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000000..79ee123c2b --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/README.md b/README.md index 0b6648c4b4..2b771bb929 100644 --- a/README.md +++ b/README.md @@ -26,9 +26,9 @@ discord - - - patreon + + + downloads

@@ -76,4 +76,4 @@ NotEnoughUpdates (NEU) is a feature rich 1.8.9 Minecraft forge mod for Hypixel S - A custom enchanting table GUI. - Slot Locking - Fishing Particle customization & alerts. -- And much, much, more. +- And [much, much, more.](https://gist.github.com/jani270/d33e249d40b0333b87ba5c5e70fca398) diff --git a/Update Notes/2.1.md b/Update Notes/2.1.md new file mode 100644 index 0000000000..1a120dfb8d --- /dev/null +++ b/Update Notes/2.1.md @@ -0,0 +1,89 @@ +# These are the change notes for NEU 2.1 REL + +### **Major Changes** +- Added mining skill overlay +- Added fishing skill overlay +- Added combat skill overlay +- Added slayer overlay +- [Added mining tab in /pv](https://cdn.discordapp.com/attachments/832652653292027904/903619242384056370/unknown.png) +- Big thanks to kwev1n for some math and jani for the texture +- Added blocking clicks back to the enchanting minigames (because apparently, it's not bannable?) +- [Donpireso replied to a sba dev's email about some of sba features, and it seems to imply that blocking clicks in guis aren't bannable](https://cdn.discordapp.com/attachments/823769568933576764/906101631861526559/unknown.png) +- Fixed pet overlay not updating when going into /pets +- [Added an armor overlay for the new armor slots](https://cdn.discordapp.com/attachments/832652653292027904/922399046528794634/unknown.png) +- Added a pet overlay that shows your active pet in your inventory +- [Price graph for items on /ah and /bz](https://cdn.discordapp.com/attachments/896407218151366687/926968296929107999/unknown.png) - DeDiamondPro +### **Minor Changes:** +- Add built-in recipes for forge crafts - nea89 +- Add Stranded Villager Trades to the item list - nea89 +- Make cata xp in /pv be calculated on how many runs you have and shows master mode xp rates +- Added a config option to hide Dwarven Mines waypoints when already at the location - Lulonaut +- Added some info panels to some settings in /neu +- Added Kat Level After Upgrade Estimator - nea89 +- Added /pv button in /neu +- Added pitch and coins/m as options in farming skill overlay +- Make it so tab completion in ah search GUI goes down the items - Lulonaut +- Added a toggle for enchant glint in storage gui (ty ery for texture) +- Added fairy souls option to /neu misc +- Make it so fairy souls are tracked independently for each profile - Lulonaut +- Added a button in the storage gui to open the settings +- Added an option to change the click names for /pv to /ah +- Added a help menu to /neuec +- Made it so treecap shows foraging xp instead of farming xp on the farming overlay +- Made it so a jungle axe with cult will show the "farming" overlay +- Added /neurepomode to toggle item editing and dev mode +- Changed "NEUAH is DISABLED! Enable in /neusettings." to /neu +- Changed misc overlays tab to todo overlays +- Added a config option for npc retexturing +- Added a config option for dirt wand overlay +- Added a config option for hoe of tilling +- Added an option to use short numbers (1.5mil) for price tooltips +- Added Drills and Gauntlet to the itemlist tools category - jani +- Added an option to turn off showing next click in chronomatron +- Turns off inv search mode after 2 minutes +- Made /neustats modlist show normal /neustats if under 15 mods +- Added max enchant book to /neuec - Dokm +- [Added bingo and Stranded profile icons to /pv](https://cdn.discordapp.com/attachments/832652653292027904/915844465372065842/unknown.png) +- Added an icon if neu doesn't know about a gamemode in /pv +- Fixed pet overlay not resetting pet when making new profile +- Added a warning in the tooltip when price info couldn't be found/is outdated - Lulonaut +- Added "Has Advanced Tab" to /neustats +- Added custom runes and crab hat system - jani +- Removed unused textures +- Added total xp if player is above cata 50 in /pv - efefury +- Added daily powder to todo overlay - efefury +- Added a way to include kismet feather to profit calculator - efefury +- Added custom sounds for crystal hollow gemstones - nea89 +- Added custom biomes for crystal hollow areas - nopo +- Added a config option to hide the reforge stats for Legendary items from Hypixel on reforge stones - Lulonaut +### **Bug Fixes** +- Fix wiki pages freezing the entire game - nea89 +- Made titanium overlay and waypoints work with dwarven overlay off +- "fixed" divan rarity in NEUAH (scuffed) +- Made etherwarp block overlay config option +- Fixed ram usage in crystal hollows - Dokm +- Made skills not show int limit when at max level in skill overlays +- Fixed space cape texture - Microcontrollers +- Make it so you can hold down keys in sign GUIs +- Added entrance to "floor one" + made blur limit at 100 +- Fixed screenshot key in /et overlay +- Fixed api key autofill with dg copy chat feature +- Made missing enchants not show on an item if its not missing any enchants +- Fixed Mining overlay crash - Dokm +- Fixed pet crash - Dokm +- Fixed fetchur for the 75th time +- [Made an error if you have new tab list off](https://cdn.discordapp.com/attachments/896407218151366687/913681097605398528/unknown.png) +- Fixed lava fishing with the fishing alert +- Fixed /locraw detection, [previously allowed chat messages to trigger it](https://github.com/NotEnoughUpdates/NotEnoughUpdates/issues/35) - IRONM00N +- Fixed experiment timer in todo overlay - efefury +- Fixed replace click events with /pv working in other modes +- Fixed /neuec presets not applying the strikethrough attribute - Lulonaut +### **Other** +- New icons was added in storage_icons.png +- Moved the help icon in /neucustomize over a little +- Added dg partner cape +- Changed custom_enchant_gui.png to remove top right button +- Added 4 new textures for the on/off switches in /neu +- Code Cleanup - IRONM00N +### **Previous change log** +https://github.com/NotEnoughUpdates/NotEnoughUpdates/blob/master/Update%20Notes/2.0-Pre31-Release.md diff --git a/build.gradle b/build.gradle deleted file mode 100644 index f2620a00b3..0000000000 --- a/build.gradle +++ /dev/null @@ -1,128 +0,0 @@ -buildscript { - repositories { - jcenter() - maven { - name 'JitPack' - url 'https://jitpack.io' - } - maven { url = "https://maven.minecraftforge.net/" } - maven { url = "https://repo.spongepowered.org/maven" } - } - dependencies { - classpath "com.github.asbyth:ForgeGradle:6f53277" - classpath 'com.github.LxGaming:MixinGradle:d75e32e'//0.6-SNAPSHOT' - classpath 'com.github.jengelman.gradle.plugins:shadow:6.1.0' - } -} - -apply plugin: 'java' -apply plugin: "net.minecraftforge.gradle.forge" -apply plugin: 'org.spongepowered.mixin' -apply plugin: 'com.github.johnrengelman.shadow' - -sourceCompatibility = 1.8 -targetCompatibility = 1.8 - -version = "2.0-PRE" -group= "io.github.moulberry" -archivesBaseName = "NotEnoughUpdates" -String modid = "notenoughupdates" -String mixinClassifier = "dep" -compileJava.options.encoding = 'UTF-8' - -minecraft { - version = "1.8.9-11.15.1.2318-1.8.9" - runDir = "run" - mappings = "stable_22" -} - -repositories { - jcenter() - maven { url 'https://repo.spongepowered.org/maven/' } - flatDir { - dirs 'deps' - } -} - -dependencies { - compile('org.spongepowered:mixin:0.7.11-SNAPSHOT') - annotationProcessor('org.spongepowered:mixin:0.7.11-SNAPSHOT') - compile('com.fasterxml.jackson.core:jackson-core:2.10.2') - compile('info.bliki.wiki:bliki-core:3.1.0') -} - -mixin { - add sourceSets.main, "mixins.${modid}.refmap.json" -} - -jar { - manifest.attributes( - 'Main-Class': 'NotSkyblockAddonsInstallerFrame', - 'TweakClass': 'org.spongepowered.asm.launch.MixinTweaker', - 'MixinConfigs': "mixins.${modid}.json", - 'FMLCorePluginContainsFMLMod': true, - "ForceLoadAsMod": true, - "FMLAT": 'notenoughupdates_at.cfg' - ) -} - -shadowJar { - dependencies { - include(dependency('org.spongepowered:mixin:0.7.11-SNAPSHOT')) - - include(dependency('commons-io:commons-io')) - include(dependency('org.apache.commons:commons-lang3')) - include(dependency('com.fasterxml.jackson.core:jackson-databind:2.10.2')) - include(dependency('com.fasterxml.jackson.core:jackson-annotations:2.10.2')) - include(dependency('com.fasterxml.jackson.core:jackson-core:2.10.2')) - - include(dependency('info.bliki.wiki:bliki-core:3.1.0')) - include(dependency('org.slf4j:slf4j-api:1.7.18')) - include(dependency('org.luaj:luaj-jse:3.0.1')) - } - - relocate 'com.fasterxml.jackson', 'neu.com.fasterxml.jackson' - relocate 'org.eclipse', 'neu.org.eclipse' - relocate 'org.slf4j', 'neu.org.slf4j' - - exclude 'module-info.class' - exclude 'dummyThing' - exclude 'LICENSE.txt' - - classifier = mixinClassifier -} - -reobf { - shadowJar { - mappingType = 'SEARGE' - } -} - -build.dependsOn(shadowJar) -runClient.dependsOn(build) - -processResources -{ - inputs.property "version", project.version - inputs.property "mcversion", project.minecraft.version - - from(sourceSets.main.resources.srcDirs) { - include 'mcmod.info' - expand 'version':project.version, 'mcversion':project.minecraft.version - } - - from(sourceSets.main.resources.srcDirs) { - exclude 'mcmod.info' - } - - rename '(.+_at.cfg)', 'META-INF/$1' -} - -task moveResources { - doLast { - ant.move file: "${buildDir}/resources/main", - todir: "${buildDir}/classes/java" - } -} -moveResources.dependsOn processResources -classes.dependsOn moveResources diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000000..e824a9a0e1 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,149 @@ +import java.io.ByteArrayOutputStream +import net.minecraftforge.gradle.user.ReobfMappingType +plugins { + java + id("net.minecraftforge.gradle.forge") version "6f5327738df" + id("com.github.johnrengelman.shadow") version "6.1.0" + id("org.spongepowered.mixin") version "d75e32e" +} + +group = "io.github.moulberry" +val baseVersion = "2.1" + + +var buildVersion = properties["BUILD_VERSION"] +if (buildVersion == null) { + val stdout = ByteArrayOutputStream() + val execResult = exec { + commandLine("git", "describe", "--always", "--first-parent", "--abbrev=7") + standardOutput = stdout + } + if (execResult.exitValue == 0) + buildVersion = String(stdout.toByteArray()).trim() +} + +version = baseVersion + (buildVersion?.let { "+$it" } ?: "") + + +// Toolchains: + +java { + // Forge Gradle currently prevents using the toolchain: toolchain.languageVersion.set(JavaLanguageVersion.of(8)) + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 +} + +minecraft { + version = "1.8.9-11.15.1.2318-1.8.9" + runDir = "run" + mappings = "stable_22" + clientJvmArgs.addAll( + listOf( + "-Dmixin.debug=true", + "-Dasmhelper.verbose=true" + ) + ) + clientRunArgs.addAll( + listOf( + "--tweakClass org.spongepowered.asm.launch.MixinTweaker", + "--mixin mixins.notenoughupdates.json" + ) + ) +} + +mixin { + add(sourceSets.main.get(), "mixins.notenoughupdates.refmap.json") +} + +// Dependencies: + +repositories { + mavenCentral() + flatDir { dirs("deps/") } + maven("https://repo.spongepowered.org/maven/") +} + +dependencies { + implementation("org.spongepowered:mixin:0.7.11-SNAPSHOT") + annotationProcessor("org.spongepowered:mixin:0.7.11-SNAPSHOT") + implementation("com.fasterxml.jackson.core:jackson-core:2.13.1") + implementation("info.bliki.wiki:bliki-core:3.1.0") +} + + +// Tasks: + +tasks.withType(JavaCompile::class) { + options.encoding = "UTF-8" +} + +tasks.withType(Jar::class) { + archiveBaseName.set("NotEnoughUpdates") + manifest.attributes.run { + this["Main-Class"] = "NotSkyblockAddonsInstallerFrame" + this["TweakClass"] = "org.spongepowered.asm.launch.MixinTweaker" + this["MixinConfigs"] = "mixins.notenoughupdates.json" + this["FMLCorePluginContainsFMLMod"] = "true" + this["ForceLoadAsMod"] = "true" + this["FMLAT"] = "notenoughupdates_at.cfg" + } +} + +tasks.shadowJar { + archiveClassifier.set("dep") + exclude( + "module-info.class", + "LICENSE.txt" + ) + dependencies { + include(dependency("org.spongepowered:mixin:0.7.11-SNAPSHOT")) + + include(dependency("commons-io:commons-io")) + include(dependency("org.apache.commons:commons-lang3")) + include(dependency("com.fasterxml.jackson.core:jackson-databind:2.10.2")) + include(dependency("com.fasterxml.jackson.core:jackson-annotations:2.10.2")) + include(dependency("com.fasterxml.jackson.core:jackson-core:2.10.2")) + + include(dependency("info.bliki.wiki:bliki-core:3.1.0")) + include(dependency("org.slf4j:slf4j-api:1.7.18")) + include(dependency("org.luaj:luaj-jse:3.0.1")) + } + fun relocate(name: String) = relocate(name, "io.github.moulberry.notenoughupdates.deps.$name") + relocate("com.fasterxml.jackson") + relocate("org.eclipse") + relocate("org.slf4j") +} + +tasks.build.get().dependsOn(tasks.shadowJar) + +reobf { + create("shadowJar") { + mappingType = ReobfMappingType.SEARGE + } +} + +tasks.processResources { + from(sourceSets.main.get().resources.srcDirs) + filesMatching("mcmod.info") { + expand( + "version" to project.version, + "mcversion" to minecraft.version + ) + } + rename("(.+_at.cfg)".toPattern(), "META-INF/$1") +} + +val moveResources by tasks.creating { + doLast { + ant.withGroovyBuilder { + "move"( + "file" to "$buildDir/resources/main", + "todir" to "$buildDir/classes/java" + ) + } + } + dependsOn(tasks.processResources) +} + +tasks.classes { dependsOn(moveResources) } + diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000000..441383126c --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,17 @@ +pluginManagement { + repositories { + mavenCentral() + gradlePluginPortal() + maven(url = "https://jitpack.io/") + maven(url = "https://maven.minecraftforge.net/") + maven(url = "https://repo.spongepowered.org/maven/") + } + resolutionStrategy { + eachPlugin { + when (requested.id.id) { + "net.minecraftforge.gradle.forge" -> useModule("com.github.asbyth:ForgeGradle:${requested.version}") + "org.spongepowered.mixin" -> useModule("com.github.LxGaming:MixinGradle:${requested.version}") + } + } + } +} diff --git a/src/main/java/NotSkyblockAddonsInstallerFrame.java b/src/main/java/NotSkyblockAddonsInstallerFrame.java index 7c5a16385d..e654361704 100644 --- a/src/main/java/NotSkyblockAddonsInstallerFrame.java +++ b/src/main/java/NotSkyblockAddonsInstallerFrame.java @@ -16,652 +16,663 @@ import java.util.zip.ZipEntry; public class NotSkyblockAddonsInstallerFrame extends JFrame implements ActionListener, MouseListener { - - private static final Pattern IN_MODS_SUBFOLDER = Pattern.compile("1\\.8\\.9[/\\\\]?$"); - - private JLabel logo = null; - private JLabel versionInfo = null; - private JLabel labelFolder = null; - - private JPanel panelCenter = null; - private JPanel panelBottom = null; - private JPanel totalContentPane = null; - - private JTextArea descriptionText = null; - private JTextArea forgeDescriptionText = null; - - private JTextField textFieldFolderLocation = null; - private JButton buttonChooseFolder = null; - - private JButton buttonInstall = null; - private JButton buttonOpenFolder = null; - private JButton buttonClose = null; - - private static final int TOTAL_HEIGHT = 435; - private static final int TOTAL_WIDTH = 404; - - private int x = 0; - private int y = 0; - - private int w = TOTAL_WIDTH; - private int h; - private int margin; - - public NotSkyblockAddonsInstallerFrame() { - try { - setName("NotEnoughUpdatesInstallerFrame"); - setTitle("NotEnoughUpdates Installer"); - setResizable(false); - setSize(TOTAL_WIDTH, TOTAL_HEIGHT); - setContentPane(getPanelContentPane()); - - getButtonFolder().addActionListener(this); - getButtonInstall().addActionListener(this); - getButtonOpenFolder().addActionListener(this); - getButtonClose().addActionListener(this); - getForgeTextArea().addMouseListener(this); - - pack(); - setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); - - getFieldFolder().setText(getModsFolder().getPath()); - getButtonInstall().setEnabled(true); - getButtonInstall().requestFocus(); - } catch (Exception ex) { - showErrorPopup(ex); - } - } - - public static void main(String[] args) { - try { - UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - NotSkyblockAddonsInstallerFrame frame = new NotSkyblockAddonsInstallerFrame(); - frame.centerFrame(frame); - frame.show(); - - } catch (Exception ex) { - showErrorPopup(ex); - } - } - - private JPanel getPanelContentPane() { - if (totalContentPane == null) { - try { - totalContentPane = new JPanel(); - totalContentPane.setName("PanelContentPane"); - totalContentPane.setLayout(new BorderLayout(5, 5)); - totalContentPane.setPreferredSize(new Dimension(TOTAL_WIDTH, TOTAL_HEIGHT)); - totalContentPane.add(getPanelCenter(), "Center"); - totalContentPane.add(getPanelBottom(), "South"); - } catch (Throwable ivjExc) { - showErrorPopup(ivjExc); - } - } - return totalContentPane; - } - - private JPanel getPanelCenter() { - if (panelCenter == null) { - try { - (panelCenter = new JPanel()).setName("PanelCenter"); - panelCenter.setLayout(null); - panelCenter.add(getPictureLabel(), getPictureLabel().getName()); - panelCenter.add(getVersionInfo(), getVersionInfo().getName()); - panelCenter.add(getTextArea(), getTextArea().getName()); - panelCenter.add(getForgeTextArea(), getForgeTextArea().getName()); - panelCenter.add(getLabelFolder(), getLabelFolder().getName()); - panelCenter.add(getFieldFolder(), getFieldFolder().getName()); - panelCenter.add(getButtonFolder(), getButtonFolder().getName()); - } catch (Throwable ivjExc) { - showErrorPopup(ivjExc); - } - } - return panelCenter; - } - - private JLabel getPictureLabel() { - if (logo == null) { - try { - h = w/2; - margin = 5; - - BufferedImage myPicture = ImageIO.read(getClass().getClassLoader().getResourceAsStream("assets/notenoughupdates/logo.png")); - Image scaled = myPicture.getScaledInstance(w-margin*2, h-margin, Image.SCALE_SMOOTH); - logo = new JLabel(new ImageIcon(scaled)); - logo.setName("Logo"); - logo.setBounds(x+margin, y+margin, w-margin*2, h-margin); - logo.setFont(new Font(Font.DIALOG, Font.BOLD, 18)); - logo.setHorizontalAlignment(SwingConstants.CENTER); - logo.setPreferredSize(new Dimension(h*742/537, h)); - - y += h; - } catch (Throwable ivjExc) { - showErrorPopup(ivjExc); - } - } - return logo; - } - - private JLabel getVersionInfo() { - if (versionInfo == null) { - try { - h = 25; - - versionInfo = new JLabel(); - versionInfo.setName("LabelMcVersion"); - versionInfo.setBounds(x, y, w, h); - versionInfo.setFont(new Font(Font.DIALOG, Font.BOLD, 14)); - versionInfo.setHorizontalAlignment(SwingConstants.CENTER); - versionInfo.setPreferredSize(new Dimension(w, h)); - versionInfo.setText("NEU by Moulberry, Installer by Biscuit - for Minecraft 1.8.9"); - - y += h; - } catch (Throwable ivjExc) { - showErrorPopup(ivjExc); - } - } - return versionInfo; - } - - private JTextArea getTextArea() { - if (descriptionText == null) { - try { - h = 60; - margin = 10; - - descriptionText = new JTextArea(); - descriptionText.setName("TextArea"); - descriptionText.setBounds(x+margin, y+margin, w-margin*2, h-margin); - descriptionText.setEditable(false); - descriptionText.setHighlighter(null); - descriptionText.setEnabled(true); - descriptionText.setFont(new Font(Font.DIALOG, Font.PLAIN, 12)); - descriptionText.setLineWrap(true); - descriptionText.setOpaque(false); - descriptionText.setPreferredSize(new Dimension(w-margin*2, h-margin)); - descriptionText.setText("This installer will copy NotEnoughUpdates into your forge mods folder for you, and replace any old versions that already exist. " + - "Close this if you prefer to do this yourself!"); - descriptionText.setWrapStyleWord(true); - - y += h; - } catch (Throwable ivjExc) { - showErrorPopup(ivjExc); - } - } - return descriptionText; - } - - private JTextArea getForgeTextArea() { - if (forgeDescriptionText == null) { - try { - h = 55; - margin = 10; - - forgeDescriptionText = new JTextArea(); - forgeDescriptionText.setName("TextAreaForge"); - forgeDescriptionText.setBounds(x+margin, y+margin, w-margin*2, h-margin); - forgeDescriptionText.setEditable(false); - forgeDescriptionText.setHighlighter(null); - forgeDescriptionText.setEnabled(true); - forgeDescriptionText.setFont(new Font(Font.DIALOG, Font.PLAIN, 12)); - forgeDescriptionText.setLineWrap(true); - forgeDescriptionText.setOpaque(false); - forgeDescriptionText.setPreferredSize(new Dimension(w-margin*2, h-margin)); - forgeDescriptionText.setText("However, you still need to install Forge client in order to be able to run this mod. Click here to visit the download page for Forge 1.8.9!"); - forgeDescriptionText.setForeground(Color.BLUE.darker()); - forgeDescriptionText.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - forgeDescriptionText.setWrapStyleWord(true); - - y += h; - } catch (Throwable ivjExc) { - showErrorPopup(ivjExc); - } - } - return forgeDescriptionText; - } - - private JLabel getLabelFolder() { - if (labelFolder == null) { - h = 16; - w = 65; - - x += 10; // Padding - - try { - labelFolder = new JLabel(); - labelFolder.setName("LabelFolder"); - labelFolder.setBounds(x, y+2, w, h); - labelFolder.setPreferredSize(new Dimension(w, h)); - labelFolder.setText("Mods Folder"); - } catch (Throwable ivjExc) { - showErrorPopup(ivjExc); - } - - x += w; - } - return labelFolder; - } - - private JTextField getFieldFolder() { - if (textFieldFolderLocation == null) { - h = 20; - w = 287; - - try { - textFieldFolderLocation = new JTextField(); - textFieldFolderLocation.setName("FieldFolder"); - textFieldFolderLocation.setBounds(x, y, w, h); - textFieldFolderLocation.setEditable(false); - textFieldFolderLocation.setPreferredSize(new Dimension(w, h)); - } catch (Throwable ivjExc) { - showErrorPopup(ivjExc); - } - - x += w; - } - return textFieldFolderLocation; - } - - private JButton getButtonFolder() { - if (buttonChooseFolder == null) { - h = 20; - w = 25; - - x += 10; // Padding - - try { - BufferedImage myPicture = ImageIO.read(getClass().getClassLoader().getResourceAsStream("assets/notenoughupdates/folder.png")); - Image scaled = myPicture.getScaledInstance(w-8, h-6, Image.SCALE_SMOOTH); - buttonChooseFolder = new JButton(new ImageIcon(scaled)); - buttonChooseFolder.setName("ButtonFolder"); - buttonChooseFolder.setBounds(x, y, w, h); - buttonChooseFolder.setPreferredSize(new Dimension(w, h)); - } catch (Throwable ivjExc) { - showErrorPopup(ivjExc); - } - } - return buttonChooseFolder; - } - - private JPanel getPanelBottom() { - if (panelBottom == null) { - try { - panelBottom = new JPanel(); - panelBottom.setName("PanelBottom"); - panelBottom.setLayout(new FlowLayout(FlowLayout.CENTER, 15, 10)); - panelBottom.setPreferredSize(new Dimension(390, 55)); - panelBottom.add(getButtonInstall(), getButtonInstall().getName()); - panelBottom.add(getButtonOpenFolder(), getButtonOpenFolder().getName()); - panelBottom.add(getButtonClose(), getButtonClose().getName()); - } catch (Throwable ivjExc) { - showErrorPopup(ivjExc); - } - } - return panelBottom; - } - - private JButton getButtonInstall() { - if (buttonInstall == null) { - w = 100; - h = 26; - - try { - buttonInstall = new JButton(); - buttonInstall.setName("ButtonInstall"); - buttonInstall.setPreferredSize(new Dimension(w, h)); - buttonInstall.setText("Install"); - } catch (Throwable ivjExc) { - showErrorPopup(ivjExc); - } - } - return buttonInstall; - } - - private JButton getButtonOpenFolder() { - if (buttonOpenFolder == null) { - w = 130; - h = 26; - - try { - buttonOpenFolder = new JButton(); - buttonOpenFolder.setName("ButtonOpenFolder"); - buttonOpenFolder.setPreferredSize(new Dimension(w, h)); - buttonOpenFolder.setText("Open Mods Folder"); - } catch (Throwable ivjExc) { - showErrorPopup(ivjExc); - } - } - return buttonOpenFolder; - } - - private JButton getButtonClose() { - if (buttonClose == null) { - w = 100; - h = 26; - - try { - (buttonClose = new JButton()).setName("ButtonClose"); - buttonClose.setPreferredSize(new Dimension(w, h)); - buttonClose.setText("Cancel"); - } catch (Throwable ivjExc) { - showErrorPopup(ivjExc); - } - } - return buttonClose; - } - - public void onFolderSelect() { - File currentDirectory = new File(getFieldFolder().getText()); - - JFileChooser jFileChooser = new JFileChooser(currentDirectory); - jFileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - jFileChooser.setAcceptAllFileFilterUsed(false); - if (jFileChooser.showOpenDialog(this) == 0) { - File newDirectory = jFileChooser.getSelectedFile(); - getFieldFolder().setText(newDirectory.getPath()); - } - } - - @Override - public void actionPerformed(ActionEvent e) { - if (e.getSource() == getButtonClose()) { - dispose(); - System.exit(0); - } - if (e.getSource() == getButtonFolder()) { - onFolderSelect(); - } - if (e.getSource() == getButtonInstall()) { - onInstall(); - } - if (e.getSource() == getButtonOpenFolder()) { - onOpenFolder(); - } - } - - @Override - public void mouseClicked(MouseEvent e) { - if (e.getSource() == getForgeTextArea()) { - try { - Desktop.getDesktop().browse(new URI("http://files.minecraftforge.net/maven/net/minecraftforge/forge/index_1.8.9.html")); - } catch (IOException | URISyntaxException ex) { - showErrorPopup(ex); - } - } - } - - public void onInstall() { - try { - File modsFolder = new File(getFieldFolder().getText()); - if (!modsFolder.exists()) { - showErrorMessage("Folder not found: " + modsFolder.getPath()); - return; - } - if (!modsFolder.isDirectory()) { - showErrorMessage("Not a folder: " + modsFolder.getPath()); - return; - } - tryInstall(modsFolder); - } catch (Exception e) { - showErrorPopup(e); - } - } - - private void tryInstall(File modsFolder) { - File thisFile = getThisFile(); - - if (thisFile != null) { - boolean inSubFolder = false; - if (IN_MODS_SUBFOLDER.matcher(modsFolder.getPath()).find()) { - inSubFolder = true; - } - - boolean deletingFailure = false; - if (modsFolder.isDirectory()) { // Delete in this current folder. - boolean failed = findSkyblockAddonsAndDelete(modsFolder.listFiles()); - if (failed) deletingFailure = true; - } - if (inSubFolder) { // We are in the 1.8.9 folder, delete in the parent folder as well. - if (modsFolder.getParentFile().isDirectory()) { - boolean failed = findSkyblockAddonsAndDelete(modsFolder.getParentFile().listFiles()); - if (failed) deletingFailure = true; - } - } else { // We are in the main mods folder, but the 1.8.9 subfolder exists... delete in there too. - File subFolder = new File(modsFolder, "1.8.9"); - if (subFolder.exists() && subFolder.isDirectory()) { - boolean failed = findSkyblockAddonsAndDelete(subFolder.listFiles()); - if (failed) deletingFailure = true; - } - } - - if (deletingFailure) return; - - if (thisFile.isDirectory()) { - showErrorMessage("This file is a directory... Are we in a development environment?"); - return; - } - - try { - Files.copy(thisFile.toPath(), new File(modsFolder, thisFile.getName()).toPath()); - } catch (Exception ex) { - showErrorPopup(ex); - return; - } - - showMessage("NotEnoughUpdates has been successfully installed into your mods folder."); - dispose(); - System.exit(0); - } - } - - private boolean findSkyblockAddonsAndDelete(File[] files) { - if (files == null) return false; - - for (File file : files) { - if (!file.isDirectory() && file.getPath().endsWith(".jar")) { - try { - JarFile jarFile = new JarFile(file); - ZipEntry mcModInfo = jarFile.getEntry("mcmod.info"); - if (mcModInfo != null) { - InputStream inputStream = jarFile.getInputStream(mcModInfo); - String modID = getModIDFromInputStream(inputStream); - if (modID.equals("notenoughupdates")) { - jarFile.close(); - try { - boolean deleted = file.delete(); - if (!deleted) { - throw new Exception(); - } - } catch (Exception ex) { - ex.printStackTrace(); - showErrorMessage("Was not able to delete the other NotEnoughUpdates files found in your mods folder!" + System.lineSeparator() + - "Please make sure that your minecraft is currently closed and try again, or feel" + System.lineSeparator() + - "free to open your mods folder and delete those files manually."); - return true; - } - continue; - } - } - jarFile.close(); - } catch (Exception ex) { - // Just don't check the file I guess, move on to the next... - } - } - } - return false; - } - - public void onOpenFolder() { - try { - Desktop.getDesktop().open(getModsFolder()); - } catch (Exception e) { - showErrorPopup(e); - } - } - - public File getModsFolder() { - String userHome = System.getProperty("user.home", "."); - - File modsFolder = getFile(userHome, "minecraft/mods/1.8.9"); - if (!modsFolder.exists()) { - modsFolder = getFile(userHome, "minecraft/mods"); - } - - if (!modsFolder.exists() && !modsFolder.mkdirs()) { - throw new RuntimeException("The working directory could not be created: " + modsFolder); - } - return modsFolder; - } - - public File getFile(String userHome, String minecraftPath) { - File workingDirectory; - switch (getOperatingSystem()) { - case LINUX: - case SOLARIS: { - workingDirectory = new File(userHome, '.' + minecraftPath + '/'); - break; - } - case WINDOWS: { - String applicationData = System.getenv("APPDATA"); - if (applicationData != null) { - workingDirectory = new File(applicationData, "." + minecraftPath + '/'); - break; - } - workingDirectory = new File(userHome, '.' + minecraftPath + '/'); - break; - } - case MACOS: { - workingDirectory = new File(userHome, "Library/Application Support/" + minecraftPath); - break; - } - default: { - workingDirectory = new File(userHome, minecraftPath + '/'); - break; - } - } - return workingDirectory; - } - - public OperatingSystem getOperatingSystem() { - String osName = System.getProperty("os.name").toLowerCase(Locale.US); - if (osName.contains("win")) { - return OperatingSystem.WINDOWS; - - } else if (osName.contains("mac")) { - return OperatingSystem.MACOS; - - } else if (osName.contains("solaris") || osName.contains("sunos")) { - - return OperatingSystem.SOLARIS; - } else if (osName.contains("linux") || osName.contains("unix")) { - - return OperatingSystem.LINUX; - } - return OperatingSystem.UNKNOWN; - } - - public void centerFrame(JFrame frame) { - Rectangle rectangle = frame.getBounds(); - Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); - Rectangle screenRectangle = new Rectangle(0, 0, screenSize.width, screenSize.height); - - int newX = screenRectangle.x + (screenRectangle.width - rectangle.width) / 2; - int newY = screenRectangle.y + (screenRectangle.height - rectangle.height) / 2; - - if (newX < 0) newX = 0; - if (newY < 0) newY = 0; - - frame.setBounds(newX, newY, rectangle.width, rectangle.height); - } - - public void showMessage(String message) { - JOptionPane.showMessageDialog(null, message, "NotEnoughUpdates", JOptionPane.INFORMATION_MESSAGE); - } - - public void showErrorMessage(String message) { - JOptionPane.showMessageDialog(null, message, "NotEnoughUpdates - Error", JOptionPane.ERROR_MESSAGE); - } - - public enum OperatingSystem { - LINUX, - SOLARIS, - WINDOWS, - MACOS, - UNKNOWN - } - - private static String getStacktraceText(Throwable ex) { - StringWriter stringWriter = new StringWriter(); - ex.printStackTrace(new PrintWriter(stringWriter)); - return stringWriter.toString().replace("\t", " "); - } - - private static void showErrorPopup(Throwable ex) { - ex.printStackTrace(); - - JTextArea textArea = new JTextArea(getStacktraceText(ex)); - textArea.setEditable(false); - Font currentFont = textArea.getFont(); - Font newFont = new Font(Font.MONOSPACED, currentFont.getStyle(), currentFont.getSize()); - textArea.setFont(newFont); - - JScrollPane errorScrollPane = new JScrollPane(textArea); - errorScrollPane.setPreferredSize(new Dimension(600, 400)); - JOptionPane.showMessageDialog(null, errorScrollPane, "Error", JOptionPane.ERROR_MESSAGE); - } - - private String getVersionFromMcmodInfo() { - String version = ""; - try { - BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(getClass().getClassLoader().getResourceAsStream("mcmod.info"))); - while ((version = bufferedReader.readLine()) != null) { - if (version.contains("\"version\": \"")) { - version = version.split(Pattern.quote("\"version\": \""))[1]; - version = version.substring(0, version.length() - 2); - break; - } - } - } catch (Exception ex) { - // It's okay, I guess just don't use the version lol. - } - return version; - } - - private String getModIDFromInputStream(InputStream inputStream) { - String version = ""; - try { - BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); - while ((version = bufferedReader.readLine()) != null) { - if (version.contains("\"modid\": \"")) { - version = version.split(Pattern.quote("\"modid\": \""))[1]; - version = version.substring(0, version.length() - 2); - break; - } - } - } catch (Exception ex) { - // RIP, couldn't find the modid... - } - return version; - } - - private File getThisFile() { - try { - return new File(NotSkyblockAddonsInstallerFrame.class.getProtectionDomain().getCodeSource().getLocation().toURI()); - } catch (URISyntaxException ex) { - showErrorPopup(ex); - } - return null; - } - - @Override - public void mousePressed(MouseEvent e) {} - - @Override - public void mouseReleased(MouseEvent e) {} - - @Override - public void mouseEntered(MouseEvent e) {} - - @Override - public void mouseExited(MouseEvent e) {} + private static final Pattern IN_MODS_SUBFOLDER = Pattern.compile("1\\.8\\.9[/\\\\]?$"); + + private JLabel logo = null; + private JLabel versionInfo = null; + private JLabel labelFolder = null; + + private JPanel panelCenter = null; + private JPanel panelBottom = null; + private JPanel totalContentPane = null; + + private JTextArea descriptionText = null; + private JTextArea forgeDescriptionText = null; + + private JTextField textFieldFolderLocation = null; + private JButton buttonChooseFolder = null; + + private JButton buttonInstall = null; + private JButton buttonOpenFolder = null; + private JButton buttonClose = null; + + private static final int TOTAL_HEIGHT = 435; + private static final int TOTAL_WIDTH = 404; + + private int x = 0; + private int y = 0; + + private int w = TOTAL_WIDTH; + private int h; + private int margin; + + public NotSkyblockAddonsInstallerFrame() { + try { + setName("NotEnoughUpdatesInstallerFrame"); + setTitle("NotEnoughUpdates Installer"); + setResizable(false); + setSize(TOTAL_WIDTH, TOTAL_HEIGHT); + setContentPane(getPanelContentPane()); + + getButtonFolder().addActionListener(this); + getButtonInstall().addActionListener(this); + getButtonOpenFolder().addActionListener(this); + getButtonClose().addActionListener(this); + getForgeTextArea().addMouseListener(this); + + pack(); + setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + + getFieldFolder().setText(getModsFolder().getPath()); + getButtonInstall().setEnabled(true); + getButtonInstall().requestFocus(); + } catch (Exception ex) { + showErrorPopup(ex); + } + } + + public static void main(String[] args) { + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + NotSkyblockAddonsInstallerFrame frame = new NotSkyblockAddonsInstallerFrame(); + frame.centerFrame(frame); + frame.show(); + + } catch (Exception ex) { + showErrorPopup(ex); + } + } + + private JPanel getPanelContentPane() { + if (totalContentPane == null) { + try { + totalContentPane = new JPanel(); + totalContentPane.setName("PanelContentPane"); + totalContentPane.setLayout(new BorderLayout(5, 5)); + totalContentPane.setPreferredSize(new Dimension(TOTAL_WIDTH, TOTAL_HEIGHT)); + totalContentPane.add(getPanelCenter(), "Center"); + totalContentPane.add(getPanelBottom(), "South"); + } catch (Throwable ivjExc) { + showErrorPopup(ivjExc); + } + } + return totalContentPane; + } + + private JPanel getPanelCenter() { + if (panelCenter == null) { + try { + (panelCenter = new JPanel()).setName("PanelCenter"); + panelCenter.setLayout(null); + panelCenter.add(getPictureLabel(), getPictureLabel().getName()); + panelCenter.add(getVersionInfo(), getVersionInfo().getName()); + panelCenter.add(getTextArea(), getTextArea().getName()); + panelCenter.add(getForgeTextArea(), getForgeTextArea().getName()); + panelCenter.add(getLabelFolder(), getLabelFolder().getName()); + panelCenter.add(getFieldFolder(), getFieldFolder().getName()); + panelCenter.add(getButtonFolder(), getButtonFolder().getName()); + } catch (Throwable ivjExc) { + showErrorPopup(ivjExc); + } + } + return panelCenter; + } + + private JLabel getPictureLabel() { + if (logo == null) { + try { + h = w / 2; + margin = 5; + + BufferedImage myPicture = ImageIO.read(getClass() + .getClassLoader() + .getResourceAsStream("assets/notenoughupdates/logo.png")); + Image scaled = myPicture.getScaledInstance(w - margin * 2, h - margin, Image.SCALE_SMOOTH); + logo = new JLabel(new ImageIcon(scaled)); + logo.setName("Logo"); + logo.setBounds(x + margin, y + margin, w - margin * 2, h - margin); + logo.setFont(new Font(Font.DIALOG, Font.BOLD, 18)); + logo.setHorizontalAlignment(SwingConstants.CENTER); + logo.setPreferredSize(new Dimension(h * 742 / 537, h)); + + y += h; + } catch (Throwable ivjExc) { + showErrorPopup(ivjExc); + } + } + return logo; + } + + private JLabel getVersionInfo() { + if (versionInfo == null) { + try { + h = 25; + + versionInfo = new JLabel(); + versionInfo.setName("LabelMcVersion"); + versionInfo.setBounds(x, y, w, h); + versionInfo.setFont(new Font(Font.DIALOG, Font.BOLD, 14)); + versionInfo.setHorizontalAlignment(SwingConstants.CENTER); + versionInfo.setPreferredSize(new Dimension(w, h)); + versionInfo.setText("NEU by Moulberry, Installer by Biscuit - for Minecraft 1.8.9"); + + y += h; + } catch (Throwable ivjExc) { + showErrorPopup(ivjExc); + } + } + return versionInfo; + } + + private JTextArea getTextArea() { + if (descriptionText == null) { + try { + h = 60; + margin = 10; + + descriptionText = new JTextArea(); + descriptionText.setName("TextArea"); + descriptionText.setBounds(x + margin, y + margin, w - margin * 2, h - margin); + descriptionText.setEditable(false); + descriptionText.setHighlighter(null); + descriptionText.setEnabled(true); + descriptionText.setFont(new Font(Font.DIALOG, Font.PLAIN, 12)); + descriptionText.setLineWrap(true); + descriptionText.setOpaque(false); + descriptionText.setPreferredSize(new Dimension(w - margin * 2, h - margin)); + descriptionText.setText( + "This installer will copy NotEnoughUpdates into your forge mods folder for you, and replace any old versions that already exist. " + + "Close this if you prefer to do this yourself!"); + descriptionText.setWrapStyleWord(true); + + y += h; + } catch (Throwable ivjExc) { + showErrorPopup(ivjExc); + } + } + return descriptionText; + } + + private JTextArea getForgeTextArea() { + if (forgeDescriptionText == null) { + try { + h = 55; + margin = 10; + + forgeDescriptionText = new JTextArea(); + forgeDescriptionText.setName("TextAreaForge"); + forgeDescriptionText.setBounds(x + margin, y + margin, w - margin * 2, h - margin); + forgeDescriptionText.setEditable(false); + forgeDescriptionText.setHighlighter(null); + forgeDescriptionText.setEnabled(true); + forgeDescriptionText.setFont(new Font(Font.DIALOG, Font.PLAIN, 12)); + forgeDescriptionText.setLineWrap(true); + forgeDescriptionText.setOpaque(false); + forgeDescriptionText.setPreferredSize(new Dimension(w - margin * 2, h - margin)); + forgeDescriptionText.setText( + "However, you still need to install Forge client in order to be able to run this mod. Click here to visit the download page for Forge 1.8.9!"); + forgeDescriptionText.setForeground(Color.BLUE.darker()); + forgeDescriptionText.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + forgeDescriptionText.setWrapStyleWord(true); + + y += h; + } catch (Throwable ivjExc) { + showErrorPopup(ivjExc); + } + } + return forgeDescriptionText; + } + + private JLabel getLabelFolder() { + if (labelFolder == null) { + h = 16; + w = 65; + + x += 10; // Padding + + try { + labelFolder = new JLabel(); + labelFolder.setName("LabelFolder"); + labelFolder.setBounds(x, y + 2, w, h); + labelFolder.setPreferredSize(new Dimension(w, h)); + labelFolder.setText("Mods Folder"); + } catch (Throwable ivjExc) { + showErrorPopup(ivjExc); + } + + x += w; + } + return labelFolder; + } + + private JTextField getFieldFolder() { + if (textFieldFolderLocation == null) { + h = 20; + w = 287; + + try { + textFieldFolderLocation = new JTextField(); + textFieldFolderLocation.setName("FieldFolder"); + textFieldFolderLocation.setBounds(x, y, w, h); + textFieldFolderLocation.setEditable(false); + textFieldFolderLocation.setPreferredSize(new Dimension(w, h)); + } catch (Throwable ivjExc) { + showErrorPopup(ivjExc); + } + + x += w; + } + return textFieldFolderLocation; + } + + private JButton getButtonFolder() { + if (buttonChooseFolder == null) { + h = 20; + w = 25; + + x += 10; // Padding + + try { + BufferedImage myPicture = ImageIO.read(getClass() + .getClassLoader() + .getResourceAsStream("assets/notenoughupdates/folder.png")); + Image scaled = myPicture.getScaledInstance(w - 8, h - 6, Image.SCALE_SMOOTH); + buttonChooseFolder = new JButton(new ImageIcon(scaled)); + buttonChooseFolder.setName("ButtonFolder"); + buttonChooseFolder.setBounds(x, y, w, h); + buttonChooseFolder.setPreferredSize(new Dimension(w, h)); + } catch (Throwable ivjExc) { + showErrorPopup(ivjExc); + } + } + return buttonChooseFolder; + } + + private JPanel getPanelBottom() { + if (panelBottom == null) { + try { + panelBottom = new JPanel(); + panelBottom.setName("PanelBottom"); + panelBottom.setLayout(new FlowLayout(FlowLayout.CENTER, 15, 10)); + panelBottom.setPreferredSize(new Dimension(390, 55)); + panelBottom.add(getButtonInstall(), getButtonInstall().getName()); + panelBottom.add(getButtonOpenFolder(), getButtonOpenFolder().getName()); + panelBottom.add(getButtonClose(), getButtonClose().getName()); + } catch (Throwable ivjExc) { + showErrorPopup(ivjExc); + } + } + return panelBottom; + } + + private JButton getButtonInstall() { + if (buttonInstall == null) { + w = 100; + h = 26; + + try { + buttonInstall = new JButton(); + buttonInstall.setName("ButtonInstall"); + buttonInstall.setPreferredSize(new Dimension(w, h)); + buttonInstall.setText("Install"); + } catch (Throwable ivjExc) { + showErrorPopup(ivjExc); + } + } + return buttonInstall; + } + + private JButton getButtonOpenFolder() { + if (buttonOpenFolder == null) { + w = 130; + h = 26; + + try { + buttonOpenFolder = new JButton(); + buttonOpenFolder.setName("ButtonOpenFolder"); + buttonOpenFolder.setPreferredSize(new Dimension(w, h)); + buttonOpenFolder.setText("Open Mods Folder"); + } catch (Throwable ivjExc) { + showErrorPopup(ivjExc); + } + } + return buttonOpenFolder; + } + + private JButton getButtonClose() { + if (buttonClose == null) { + w = 100; + h = 26; + + try { + (buttonClose = new JButton()).setName("ButtonClose"); + buttonClose.setPreferredSize(new Dimension(w, h)); + buttonClose.setText("Cancel"); + } catch (Throwable ivjExc) { + showErrorPopup(ivjExc); + } + } + return buttonClose; + } + + public void onFolderSelect() { + File currentDirectory = new File(getFieldFolder().getText()); + + JFileChooser jFileChooser = new JFileChooser(currentDirectory); + jFileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + jFileChooser.setAcceptAllFileFilterUsed(false); + if (jFileChooser.showOpenDialog(this) == 0) { + File newDirectory = jFileChooser.getSelectedFile(); + getFieldFolder().setText(newDirectory.getPath()); + } + } + + @Override + public void actionPerformed(ActionEvent e) { + if (e.getSource() == getButtonClose()) { + dispose(); + System.exit(0); + } + if (e.getSource() == getButtonFolder()) { + onFolderSelect(); + } + if (e.getSource() == getButtonInstall()) { + onInstall(); + } + if (e.getSource() == getButtonOpenFolder()) { + onOpenFolder(); + } + } + + @Override + public void mouseClicked(MouseEvent e) { + if (e.getSource() == getForgeTextArea()) { + try { + Desktop.getDesktop().browse(new URI( + "http://files.minecraftforge.net/maven/net/minecraftforge/forge/index_1.8.9.html")); + } catch (IOException | URISyntaxException ex) { + showErrorPopup(ex); + } + } + } + + public void onInstall() { + try { + File modsFolder = new File(getFieldFolder().getText()); + if (!modsFolder.exists()) { + showErrorMessage("Folder not found: " + modsFolder.getPath()); + return; + } + if (!modsFolder.isDirectory()) { + showErrorMessage("Not a folder: " + modsFolder.getPath()); + return; + } + tryInstall(modsFolder); + } catch (Exception e) { + showErrorPopup(e); + } + } + + private void tryInstall(File modsFolder) { + File thisFile = getThisFile(); + + if (thisFile != null) { + boolean inSubFolder = IN_MODS_SUBFOLDER.matcher(modsFolder.getPath()).find(); + + boolean deletingFailure = false; + if (modsFolder.isDirectory()) { // Delete in this current folder. + boolean failed = findSkyblockAddonsAndDelete(modsFolder.listFiles()); + if (failed) deletingFailure = true; + } + if (inSubFolder) { // We are in the 1.8.9 folder, delete in the parent folder as well. + if (modsFolder.getParentFile().isDirectory()) { + boolean failed = findSkyblockAddonsAndDelete(modsFolder.getParentFile().listFiles()); + if (failed) deletingFailure = true; + } + } else { // We are in the main mods folder, but the 1.8.9 subfolder exists... delete in there too. + File subFolder = new File(modsFolder, "1.8.9"); + if (subFolder.exists() && subFolder.isDirectory()) { + boolean failed = findSkyblockAddonsAndDelete(subFolder.listFiles()); + if (failed) deletingFailure = true; + } + } + + if (deletingFailure) return; + + if (thisFile.isDirectory()) { + showErrorMessage("This file is a directory... Are we in a development environment?"); + return; + } + + try { + Files.copy(thisFile.toPath(), new File(modsFolder, thisFile.getName()).toPath()); + } catch (Exception ex) { + showErrorPopup(ex); + return; + } + + showMessage("NotEnoughUpdates has been successfully installed into your mods folder."); + dispose(); + System.exit(0); + } + } + + private boolean findSkyblockAddonsAndDelete(File[] files) { + if (files == null) return false; + + for (File file : files) { + if (!file.isDirectory() && file.getPath().endsWith(".jar")) { + try { + JarFile jarFile = new JarFile(file); + ZipEntry mcModInfo = jarFile.getEntry("mcmod.info"); + if (mcModInfo != null) { + InputStream inputStream = jarFile.getInputStream(mcModInfo); + String modID = getModIDFromInputStream(inputStream); + if (modID.equals("notenoughupdates")) { + jarFile.close(); + try { + boolean deleted = file.delete(); + if (!deleted) { + throw new Exception(); + } + } catch (Exception ex) { + ex.printStackTrace(); + showErrorMessage("Was not able to delete the other NotEnoughUpdates files found in your mods folder!" + + System.lineSeparator() + + "Please make sure that your minecraft is currently closed and try again, or feel" + + System.lineSeparator() + + "free to open your mods folder and delete those files manually."); + return true; + } + continue; + } + } + jarFile.close(); + } catch (Exception ex) { + // Just don't check the file I guess, move on to the next... + } + } + } + return false; + } + + public void onOpenFolder() { + try { + Desktop.getDesktop().open(getModsFolder()); + } catch (Exception e) { + showErrorPopup(e); + } + } + + public File getModsFolder() { + String userHome = System.getProperty("user.home", "."); + + File modsFolder = getFile(userHome, "minecraft/mods/1.8.9"); + if (!modsFolder.exists()) { + modsFolder = getFile(userHome, "minecraft/mods"); + } + + if (!modsFolder.exists() && !modsFolder.mkdirs()) { + throw new RuntimeException("The working directory could not be created: " + modsFolder); + } + return modsFolder; + } + + public File getFile(String userHome, String minecraftPath) { + File workingDirectory; + switch (getOperatingSystem()) { + case LINUX: + case SOLARIS: { + workingDirectory = new File(userHome, '.' + minecraftPath + '/'); + break; + } + case WINDOWS: { + String applicationData = System.getenv("APPDATA"); + if (applicationData != null) { + workingDirectory = new File(applicationData, "." + minecraftPath + '/'); + break; + } + workingDirectory = new File(userHome, '.' + minecraftPath + '/'); + break; + } + case MACOS: { + workingDirectory = new File(userHome, "Library/Application Support/" + minecraftPath); + break; + } + default: { + workingDirectory = new File(userHome, minecraftPath + '/'); + break; + } + } + return workingDirectory; + } + + public OperatingSystem getOperatingSystem() { + String osName = System.getProperty("os.name").toLowerCase(Locale.US); + if (osName.contains("win")) { + return OperatingSystem.WINDOWS; + + } else if (osName.contains("mac")) { + return OperatingSystem.MACOS; + + } else if (osName.contains("solaris") || osName.contains("sunos")) { + + return OperatingSystem.SOLARIS; + } else if (osName.contains("linux") || osName.contains("unix")) { + + return OperatingSystem.LINUX; + } + return OperatingSystem.UNKNOWN; + } + + public void centerFrame(JFrame frame) { + Rectangle rectangle = frame.getBounds(); + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + Rectangle screenRectangle = new Rectangle(0, 0, screenSize.width, screenSize.height); + + int newX = screenRectangle.x + (screenRectangle.width - rectangle.width) / 2; + int newY = screenRectangle.y + (screenRectangle.height - rectangle.height) / 2; + + if (newX < 0) newX = 0; + if (newY < 0) newY = 0; + + frame.setBounds(newX, newY, rectangle.width, rectangle.height); + } + + public void showMessage(String message) { + JOptionPane.showMessageDialog(null, message, "NotEnoughUpdates", JOptionPane.INFORMATION_MESSAGE); + } + + public void showErrorMessage(String message) { + JOptionPane.showMessageDialog(null, message, "NotEnoughUpdates - Error", JOptionPane.ERROR_MESSAGE); + } + + public enum OperatingSystem { + LINUX, + SOLARIS, + WINDOWS, + MACOS, + UNKNOWN + } + + private static String getStacktraceText(Throwable ex) { + StringWriter stringWriter = new StringWriter(); + ex.printStackTrace(new PrintWriter(stringWriter)); + return stringWriter.toString().replace("\t", " "); + } + + private static void showErrorPopup(Throwable ex) { + ex.printStackTrace(); + + JTextArea textArea = new JTextArea(getStacktraceText(ex)); + textArea.setEditable(false); + Font currentFont = textArea.getFont(); + Font newFont = new Font(Font.MONOSPACED, currentFont.getStyle(), currentFont.getSize()); + textArea.setFont(newFont); + + JScrollPane errorScrollPane = new JScrollPane(textArea); + errorScrollPane.setPreferredSize(new Dimension(600, 400)); + JOptionPane.showMessageDialog(null, errorScrollPane, "Error", JOptionPane.ERROR_MESSAGE); + } + + private String getVersionFromMcmodInfo() { + String version = ""; + try { + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(getClass() + .getClassLoader() + .getResourceAsStream("mcmod.info"))); + while ((version = bufferedReader.readLine()) != null) { + if (version.contains("\"version\": \"")) { + version = version.split(Pattern.quote("\"version\": \""))[1]; + version = version.substring(0, version.length() - 2); + break; + } + } + } catch (Exception ex) { + // It's okay, I guess just don't use the version lol. + } + return version; + } + + private String getModIDFromInputStream(InputStream inputStream) { + String version = ""; + try { + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); + while ((version = bufferedReader.readLine()) != null) { + if (version.contains("\"modid\": \"")) { + version = version.split(Pattern.quote("\"modid\": \""))[1]; + version = version.substring(0, version.length() - 2); + break; + } + } + } catch (Exception ex) { + // RIP, couldn't find the modid... + } + return version; + } + + private File getThisFile() { + try { + return new File(NotSkyblockAddonsInstallerFrame.class + .getProtectionDomain() + .getCodeSource() + .getLocation() + .toURI()); + } catch (URISyntaxException ex) { + showErrorPopup(ex); + } + return null; + } + + @Override + public void mousePressed(MouseEvent e) {} + + @Override + public void mouseReleased(MouseEvent e) {} + + @Override + public void mouseEntered(MouseEvent e) {} + + @Override + public void mouseExited(MouseEvent e) {} } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/CustomItems.java b/src/main/java/io/github/moulberry/notenoughupdates/CustomItems.java index c16cb7d0be..28686073a0 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/CustomItems.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/CustomItems.java @@ -7,84 +7,100 @@ import net.minecraft.util.EnumChatFormatting; public class CustomItems { + /* + * So it has come to this, huh? Snooping through the source to find all my carefully crafted easter eggs. You + * cheated not only the game, but yourself. You didn't grow. You didn't improve. You took a + * shortcut and gained nothing. You experienced a hollow victory. Nothing was risked and nothing was gained. + * It's sad that you don't know the difference. + */ - /** - * So it has come to this, huh? Snooping through the source to find all my carefully crafted easter eggs. You - * cheated not only the game, but yourself. You didn't grow. You didn't improve. You took a - * shortcut and gained nothing. You experienced a hollow victory. Nothing was risked and nothing was gained. - * It's sad that you don't know the difference. - */ + public static JsonObject NULLZEE = create( + "NULLZEE", + "dirt", + "Nullzee242 Youtube Channel", + "Dirt, AOTD. Dirt, AOTD.", + "Dirt, AOTD. Dirt, AOTD.", + "Ooh, Dirt to Midas! Let's shake it up a little.", + "", + "Also, did you know that only 8.7% of the people watching are subscribed?", + "It's OK, everyone makes mistakes", + "Also follow -> twitch.tv/nullzeelive", + "Also -> discord.gg/nullzee" + ); + public static JsonObject DUCTTAPE = create( + "DUCTTAPE", + "iron_shovel", + "You ever accidentally bury your duct tape?", + "No problem! Our team of experts specialise in", + "subterranean duct tape excavation. That's right:", + "your buried duct tape problems are a thing of the past,", + "all for the low price of $7.99 or a subscription", + "to the Ducttapedigger youtube channel!" + ); + public static JsonObject SPINAXX = create( + "SPINAXX", + "emerald", + "Spinaxx", + "Famous streamer btw :)" + ); + public static JsonObject RUNE = create("RUNE", "paper", "No.", "I hate runes."); + public static JsonObject TWOBEETWOTEE = create( + "2B2T", + "bedrock", + "Minecraft's oldest anarchy Minecraft server in Minecraft.", + "This Minecraft anarchy server is the oldest server,", + "being a server since 2010 when Minecraft was a game with a server.", + "It is complete anarchy in Minecraft which means that there is total anarchy.", + "Hacking is allowed in Minecraft on this anarchy server which", + "is the oldest anarchy server in Minecraft, 2b2t. Hack. Steal. Cheat. Lie.", + "On the oldest anarchy server in Minecraft. 2b2t. The worst server in Minecraft,", + "where there are no rules. On the oldest anarchy server in Minecraft.", + "In this Minecraft anarchy server, there have been numerous Minecraft", + "incursions on the server, some of which I, a player on this Minecraft", + "anarchy server in Minecraft, have participated in. One of this server's", + "most infamous Minecraft players on the oldest Minecraft" + ); + public static JsonObject LEOCTHL = create( + "LEOCTHL", + "dragon_egg", + "--- Stats below may not be entirely accurate ---", + "17 legendary dragon pets", + "24 epic dragon pets", + "18 epic golem pets", + "12 legendary golem pets", + "39 legendary phoenix pets", + "", + "get flexed" + ); + public static JsonObject CREDITS = Constants.MISC.getAsJsonObject("credits"); + public static JsonObject IRONM00N = create( + "IRONM00N", + "end_stone", + "IRONM00N", + "Your life has been a lie,", + "the moon is made out of iron." + ); + public static JsonObject NOPO = create( + "nopo", + "writable_book", + "Nopo", + "We do a lil Chatting" + ); - public static JsonObject NULLZEE = create( - "NULLZEE", - "dirt", - "Nullzee242 Youtube Channel", - "Dirt, AOTD. Dirt, AOTD.", - "Dirt, AOTD. Dirt, AOTD.", - "Ooh, Dirt to Midas! Let's shake it up a little.", - "", - "Also, did you know that only 8.7% of the people watching are subscribed?", - "It's OK, everyone makes mistakes", - "Also follow -> twitch.tv/nullzeelive", - "Also -> discord.gg/nullzee"); - public static JsonObject DUCTTAPE = create( - "DUCTTAPE", - "iron_shovel", - "You ever accidentally bury your duct tape?", - "No problem! Our team of experts specialise in", - "subterranean duct tape excavation. That's right:", - "your buried duct tape problems are a thing of the past,", - "all for the low price of $7.99 or a subscription", - "to the Ducttapedigger youtube channel!"); - public static JsonObject SPINAXX = create( - "SPINAXX", - "emerald", - "Spinaxx", - "Famous streamer btw :)"); - public static JsonObject RUNE = create("RUNE", "paper", "No.", "I hate runes."); - public static JsonObject TWOBEETWOTEE = create("2B2T", "bedrock", "Minecraft's oldest anarchy Minecraft server in Minecraft.", - "This Minecraft anarchy server is the oldest server,", - "being a server since 2010 when Minecraft was a game with a server.", - "It is complete anarchy in Minecraft which means that there is total anarchy.", - "Hacking is allowed in Minecraft on this anarchy server which", - "is the oldest anarchy server in Minecraft, 2b2t. Hack. Steal. Cheat. Lie.", - "On the oldest anarchy server in Minecraft. 2b2t. The worst server in Minecraft,", - "where there are no rules. On the oldest anarchy server in Minecraft.", - "In this Minecraft anarchy server, there have been numerous Minecraft", - "incursions on the server, some of which I, a player on this Minecraft", - "anarchy server in Minecraft, have participated in. One of this server's", - "most infamous Minecraft players on the oldest Minecraft"); - public static JsonObject LEOCTHL = create("LEOCTHL", "dragon_egg", "--- Stats below may not be entirely accurate ---", - "17 legendary dragon pets", - "24 epic dragon pets", - "18 epic golem pets", - "12 legendary golem pets", - "39 legendary phoenix pets", - "", - "get flexed"); - public static JsonObject CREDITS = Constants.MISC.getAsJsonObject("credits"); - public static JsonObject IRONM00N = create( - "IRONM00N", - "end_stone", - "IRONM00N", - "Your life has been a lie,", - "the moon is made out of iron." - ); + /* + * SHAAAAAAAAAAAAAAAAAAME + */ - /** - * SHAAAAAAAAAAAAAAAAAAME - */ - - private static JsonObject create(String internalname, String itemid, String displayname, String... lore) { - JsonObject json = new JsonObject(); - json.addProperty("itemid", itemid); - json.addProperty("internalname", internalname); - json.addProperty("displayname", EnumChatFormatting.RED+displayname); - JsonArray jsonlore = new JsonArray(); - for(String line : lore) { - jsonlore.add(new JsonPrimitive(EnumChatFormatting.GRAY + line)); - } - json.add("lore", jsonlore); - return json; - } + private static JsonObject create(String internalname, String itemid, String displayname, String... lore) { + JsonObject json = new JsonObject(); + json.addProperty("itemid", itemid); + json.addProperty("internalname", internalname); + json.addProperty("displayname", EnumChatFormatting.RED + displayname); + JsonArray jsonlore = new JsonArray(); + for (String line : lore) { + jsonlore.add(new JsonPrimitive(EnumChatFormatting.GRAY + line)); + } + json.add("lore", jsonlore); + return json; + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/ItemPriceInformation.java b/src/main/java/io/github/moulberry/notenoughupdates/ItemPriceInformation.java index 83c4b7ae2f..1804831b1a 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/ItemPriceInformation.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/ItemPriceInformation.java @@ -1,5 +1,6 @@ package io.github.moulberry.notenoughupdates; +import com.google.gson.Gson; import com.google.gson.JsonObject; import io.github.moulberry.notenoughupdates.auction.APIManager; import io.github.moulberry.notenoughupdates.core.config.KeybindHelper; @@ -10,233 +11,344 @@ import net.minecraft.util.EnumChatFormatting; import org.lwjgl.input.Keyboard; +import java.io.*; +import java.nio.charset.StandardCharsets; import java.text.NumberFormat; +import java.util.HashSet; import java.util.List; import java.util.Locale; +import java.util.Set; public class ItemPriceInformation { + private static File file; + private static HashSet auctionableItems = null; + private static Gson gson; - public static boolean addToTooltip(List tooltip, String internalname, ItemStack stack) { - return addToTooltip(tooltip, internalname, stack, true); - } - - public static boolean addToTooltip(List tooltip, String internalname, ItemStack stack, boolean useStackSize) { - if(stack.getTagCompound().hasKey("disableNeuTooltip") && stack.getTagCompound().getBoolean("disableNeuTooltip")){ - return false; - } - if(NotEnoughUpdates.INSTANCE.config.tooltipTweaks.disablePriceKey && !KeybindHelper.isKeyDown(NotEnoughUpdates.INSTANCE.config.tooltipTweaks.disablePriceKeyKeybind)){ - return false; - } - JsonObject auctionInfo = NotEnoughUpdates.INSTANCE.manager.auctionManager.getItemAuctionInfo(internalname); - JsonObject bazaarInfo = NotEnoughUpdates.INSTANCE.manager.auctionManager.getBazaarInfo(internalname); - float lowestBinAvg = NotEnoughUpdates.INSTANCE.manager.auctionManager.getItemAvgBin(internalname); - - int lowestBin = NotEnoughUpdates.INSTANCE.manager.auctionManager.getLowestBin(internalname); - APIManager.CraftInfo craftCost = NotEnoughUpdates.INSTANCE.manager.auctionManager.getCraftCost(internalname); - - boolean auctionItem = lowestBin > 0 || lowestBinAvg > 0 || auctionInfo != null; - boolean bazaarItem = bazaarInfo != null; - - NumberFormat format = NumberFormat.getInstance(Locale.US); - - if(bazaarItem) { - List lines = NotEnoughUpdates.INSTANCE.config.tooltipTweaks.priceInfoBaz; - - boolean added = false; - - boolean shiftPressed = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT); - - int stackMultiplier = 1; - int shiftStackMultiplier = useStackSize && stack.stackSize > 1 ? stack.stackSize : 64; - if(shiftPressed) { - stackMultiplier = shiftStackMultiplier; - } - - //values = {"", "Buy", "Sell", "Buy (Insta)", "Sell (Insta)", "Raw Craft Cost"} - for(int lineId : lines) { - switch (lineId) { - case 0: - if(bazaarInfo.has("avg_buy")) { - if(!added) { - tooltip.add(""); - if(!shiftPressed) tooltip.add(EnumChatFormatting.DARK_GRAY.toString()+"[SHIFT show x"+shiftStackMultiplier+"]"); - added = true; - } - int bazaarBuyPrice = (int)bazaarInfo.get("avg_buy").getAsFloat()*stackMultiplier; - tooltip.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Bazaar Buy: "+ - EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(bazaarBuyPrice)+" coins"); - } - break; - case 1: - if(bazaarInfo.has("avg_sell")) { - if(!added) { - tooltip.add(""); - if(!shiftPressed) tooltip.add(EnumChatFormatting.DARK_GRAY.toString()+"[SHIFT show x"+shiftStackMultiplier+"]"); - added = true; - } - int bazaarSellPrice = (int)bazaarInfo.get("avg_sell").getAsFloat()*stackMultiplier; - tooltip.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Bazaar Sell: "+ - EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(bazaarSellPrice)+" coins"); - } - break; - case 2: - if(bazaarInfo.has("curr_buy")) { - if(!added) { - tooltip.add(""); - if(!shiftPressed) tooltip.add(EnumChatFormatting.DARK_GRAY.toString()+"[SHIFT show x"+shiftStackMultiplier+"]"); - added = true; - } - int bazaarInstantBuyPrice = (int)bazaarInfo.get("curr_buy").getAsFloat()*stackMultiplier; - tooltip.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Bazaar Insta-Buy: "+ - EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(bazaarInstantBuyPrice)+" coins"); - } - break; - case 3: - if(bazaarInfo.has("curr_sell")) { - if(!added) { - tooltip.add(""); - if(!shiftPressed) tooltip.add(EnumChatFormatting.DARK_GRAY.toString()+"[SHIFT show x"+shiftStackMultiplier+"]"); - added = true; - } - int bazaarInstantSellPrice = (int)bazaarInfo.get("curr_sell").getAsFloat()*stackMultiplier; - tooltip.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Bazaar Insta-Sell: "+ - EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(bazaarInstantSellPrice)+" coins"); - } - break; - case 4: - if(craftCost.fromRecipe) { - if((int)craftCost.craftCost == 0){ continue;} - if(!added) { - tooltip.add(""); - added = true; - } - tooltip.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Raw Craft Cost: "+ - EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format((int)craftCost.craftCost)+" coins"); - } - break; - } - } - - return added; - } else if(auctionItem) { - List lines = NotEnoughUpdates.INSTANCE.config.tooltipTweaks.priceInfoAuc; - - boolean added = false; - - for(int lineId : lines) { - switch (lineId) { - case 0: - if(lowestBin > 0) { - if(!added) { - tooltip.add(""); - added = true; - } - tooltip.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Lowest BIN: " + - EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(lowestBin)+" coins"); - } - break; - case 1: - if(auctionInfo != null) { - if(!added) { - tooltip.add(""); - added = true; - } - - if(auctionInfo.has("clean_price")) { - tooltip.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"AH Price (Clean): "+ EnumChatFormatting.GOLD+ - EnumChatFormatting.BOLD+ - format.format((int)auctionInfo.get("clean_price").getAsFloat())+" coins"); - } else { - int auctionPrice = (int)(auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat()); - tooltip.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"AH Price: "+ EnumChatFormatting.GOLD+ - EnumChatFormatting.BOLD+format.format(auctionPrice)+" coins"); - } - - } - break; - case 2: - if(auctionInfo != null) { - if(!added) { - tooltip.add(""); - added = true; - } - if(auctionInfo.has("clean_price")) { - tooltip.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"AH Sales (Clean): "+ - EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+ - format.format(auctionInfo.get("clean_sales").getAsFloat())+" sales/day"); - } else { - tooltip.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"AH Sales: "+ - EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+ - format.format(auctionInfo.get("sales").getAsFloat())+" sales/day"); - } - } - break; - case 3: - if(craftCost.fromRecipe) { - if((int)craftCost.craftCost == 0){ continue;} - if(!added) { - tooltip.add(""); - added = true; - } - tooltip.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Raw Craft Cost: "+ - EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format((int)craftCost.craftCost)+" coins"); - } - break; - case 4: - if(lowestBinAvg > 0) { - if(!added) { - tooltip.add(""); - added = true; - } - tooltip.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"AVG Lowest BIN: "+ - EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(lowestBinAvg)+" coins"); - } - break; - case 5: - if(Constants.ESSENCECOSTS == null) break; - JsonObject essenceCosts = Constants.ESSENCECOSTS; - if(!essenceCosts.has(internalname)) { - break; - } - JsonObject itemCosts = essenceCosts.get(internalname).getAsJsonObject(); - String essenceType = itemCosts.get("type").getAsString(); - - int dungeonItemLevel = -1; - if(stack != null && stack.hasTagCompound() && - stack.getTagCompound().hasKey("ExtraAttributes", 10)) { - NBTTagCompound ea = stack.getTagCompound().getCompoundTag("ExtraAttributes"); - - if (ea.hasKey("dungeon_item_level", 99)) { - dungeonItemLevel = ea.getInteger("dungeon_item_level"); - } - } - if(dungeonItemLevel == -1) { - int dungeonizeCost = 0; - if(itemCosts.has("dungeonize")) { - dungeonizeCost = itemCosts.get("dungeonize").getAsInt(); - } - tooltip.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Dungeonize Cost: " + - EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+dungeonizeCost+" "+essenceType); - } else if(dungeonItemLevel >= 0 && dungeonItemLevel <= 4) { - String costType = (dungeonItemLevel+1)+""; - - int upgradeCost = itemCosts.get(costType).getAsInt(); - StringBuilder star = new StringBuilder(); - for(int i=0; i<=dungeonItemLevel; i++) { - star.append('\u272A'); - } - tooltip.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Upgrade to "+ - EnumChatFormatting.GOLD+star+EnumChatFormatting.YELLOW+EnumChatFormatting.BOLD+": " + - EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+upgradeCost+" "+essenceType); - } - break; - } - } - - return added; - } - - return false; - } + public static boolean addToTooltip(List tooltip, String internalname, ItemStack stack) { + return addToTooltip(tooltip, internalname, stack, true); + } + public static void init(File saveLocation, Gson neuGson) { + file = saveLocation; + gson = neuGson; + if (file.exists()) { + try ( + BufferedReader reader = new BufferedReader(new InputStreamReader( + new FileInputStream(file), + StandardCharsets.UTF_8 + )) + ) { + auctionableItems = gson.fromJson(reader, HashSet.class); + } catch (Exception ignored) { + } + } + } + + public static void updateAuctionableItemsList() { + Set items = NotEnoughUpdates.INSTANCE.manager.auctionManager.getItemAuctionInfoKeySet(); + if (!items.isEmpty()) { + auctionableItems = (HashSet) items; + try ( + BufferedWriter writer = new BufferedWriter(new OutputStreamWriter( + new FileOutputStream(file), + StandardCharsets.UTF_8 + )) + ) { + //noinspection ResultOfMethodCallIgnored + file.createNewFile(); + writer.write(gson.toJson(items)); + } catch (IOException ignored) { + } + } + } + + public static boolean addToTooltip(List tooltip, String internalname, ItemStack stack, boolean useStackSize) { + if (stack.getTagCompound().hasKey("disableNeuTooltip") && stack.getTagCompound().getBoolean("disableNeuTooltip")) { + return false; + } + if (NotEnoughUpdates.INSTANCE.config.tooltipTweaks.disablePriceKey && + !KeybindHelper.isKeyDown(NotEnoughUpdates.INSTANCE.config.tooltipTweaks.disablePriceKeyKeybind)) { + return false; + } + if (internalname.equals("SKYBLOCK_MENU")) { + return false; + } + JsonObject auctionInfo = NotEnoughUpdates.INSTANCE.manager.auctionManager.getItemAuctionInfo(internalname); + JsonObject bazaarInfo = NotEnoughUpdates.INSTANCE.manager.auctionManager.getBazaarInfo(internalname); + float lowestBinAvg = NotEnoughUpdates.INSTANCE.manager.auctionManager.getItemAvgBin(internalname); + + int lowestBin = NotEnoughUpdates.INSTANCE.manager.auctionManager.getLowestBin(internalname); + APIManager.CraftInfo craftCost = NotEnoughUpdates.INSTANCE.manager.auctionManager.getCraftCost(internalname); + + boolean auctionItem = lowestBin > 0 || lowestBinAvg > 0; + boolean auctionInfoErrored = auctionInfo == null; + if (auctionItem) { + long currentTime = System.currentTimeMillis(); + long lastUpdate = NotEnoughUpdates.INSTANCE.manager.auctionManager.getLastLowestBinUpdateTime(); + //check if info is older than 10 minutes + if (currentTime - lastUpdate > 600 * 1000) { + tooltip.add(EnumChatFormatting.RED + "[NEU] Price info is outdated."); + tooltip.add(EnumChatFormatting.RED + "It will be updated again as soon as possible."); + } + } + + boolean bazaarItem = bazaarInfo != null; + + NumberFormat format = NumberFormat.getInstance(Locale.US); + boolean shortNumber = NotEnoughUpdates.INSTANCE.config.tooltipTweaks.shortNumberFormatPrices; + if (bazaarItem) { + List lines = NotEnoughUpdates.INSTANCE.config.tooltipTweaks.priceInfoBaz; + + boolean added = false; + + boolean shiftPressed = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT); + + int stackMultiplier = 1; + int shiftStackMultiplier = useStackSize && stack.stackSize > 1 ? stack.stackSize : 64; + if (shiftPressed) { + stackMultiplier = shiftStackMultiplier; + } + + //values = {"", "Buy", "Sell", "Buy (Insta)", "Sell (Insta)", "Raw Craft Cost"} + for (int lineId : lines) { + switch (lineId) { + case 0: + if (bazaarInfo.has("avg_buy")) { + if (!added) { + tooltip.add(""); + if (!shiftPressed) + tooltip.add(EnumChatFormatting.DARK_GRAY + "[SHIFT show x" + shiftStackMultiplier + "]"); + added = true; + } + int bazaarBuyPrice = (int) bazaarInfo.get("avg_buy").getAsFloat() * stackMultiplier; + tooltip.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "Bazaar Buy: " + + EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + (shortNumber && bazaarBuyPrice > 1000 + ? Utils.shortNumberFormat(bazaarBuyPrice, 0) + : format.format(bazaarBuyPrice)) + " coins"); + } + break; + case 1: + if (bazaarInfo.has("avg_sell")) { + if (!added) { + tooltip.add(""); + if (!shiftPressed) + tooltip.add(EnumChatFormatting.DARK_GRAY + "[SHIFT show x" + shiftStackMultiplier + "]"); + added = true; + } + int bazaarSellPrice = (int) bazaarInfo.get("avg_sell").getAsFloat() * stackMultiplier; + tooltip.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "Bazaar Sell: " + + EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + (shortNumber && bazaarSellPrice > 1000 + ? Utils.shortNumberFormat(bazaarSellPrice, 0) + : format.format(bazaarSellPrice)) + " coins"); + } + break; + case 2: + if (bazaarInfo.has("curr_buy")) { + if (!added) { + tooltip.add(""); + if (!shiftPressed) + tooltip.add(EnumChatFormatting.DARK_GRAY + "[SHIFT show x" + shiftStackMultiplier + "]"); + added = true; + } + int bazaarInstantBuyPrice = (int) bazaarInfo.get("curr_buy").getAsFloat() * stackMultiplier; + tooltip.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "Bazaar Insta-Buy: " + + EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + (shortNumber && bazaarInstantBuyPrice > 1000 + ? Utils.shortNumberFormat(bazaarInstantBuyPrice, 0) + : format.format(bazaarInstantBuyPrice)) + + " coins"); + } + break; + case 3: + if (bazaarInfo.has("curr_sell")) { + if (!added) { + tooltip.add(""); + if (!shiftPressed) + tooltip.add(EnumChatFormatting.DARK_GRAY + "[SHIFT show x" + shiftStackMultiplier + "]"); + added = true; + } + int bazaarInstantSellPrice = (int) bazaarInfo.get("curr_sell").getAsFloat() * stackMultiplier; + tooltip.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "Bazaar Insta-Sell: " + + EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + (shortNumber && bazaarInstantSellPrice > 1000 + ? Utils.shortNumberFormat( + bazaarInstantSellPrice, + 0 + ) + : format.format(bazaarInstantSellPrice)) + + " coins"); + } + break; + case 4: + if (craftCost != null && craftCost.fromRecipe) { + if ((int) craftCost.craftCost == 0) { + continue; + } + if (!added) { + tooltip.add(""); + added = true; + } + float cost = craftCost.craftCost; + if (shiftPressed) cost = cost * shiftStackMultiplier; + + tooltip.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "Raw Craft Cost: " + + EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + + (shortNumber && cost > 1000 ? Utils.shortNumberFormat(cost, 0) : format.format((int) cost)) + " coins"); + } + break; + } + } + + return added; + } else if (auctionItem) { + List lines = NotEnoughUpdates.INSTANCE.config.tooltipTweaks.priceInfoAuc; + + boolean added = false; + + for (int lineId : lines) { + switch (lineId) { + case 0: + if (lowestBin > 0) { + if (!added) { + tooltip.add(""); + added = true; + } + tooltip.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "Lowest BIN: " + + EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + format.format(lowestBin) + " coins"); + } + break; + case 1: + if (auctionInfo != null) { + if (!added) { + tooltip.add(""); + added = true; + } + + if (auctionInfo.has("clean_price")) { + tooltip.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "AH Price (Clean): " + + EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + + (shortNumber && auctionInfo.get("clean_price").getAsFloat() > 1000 ? Utils.shortNumberFormat( + auctionInfo.get("clean_price").getAsFloat(), + 0 + ) : format.format((int) auctionInfo.get("clean_price").getAsFloat()) + + " coins")); + } else { + int auctionPrice = + (int) (auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat()); + tooltip.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "AH Price: " + + EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + + (shortNumber && auctionPrice > 1000 + ? Utils.shortNumberFormat(auctionPrice, 0) + : format.format(auctionPrice)) + " coins"); + } + + } + break; + case 2: + if (auctionInfo != null) { + if (!added) { + tooltip.add(""); + added = true; + } + if (auctionInfo.has("clean_price")) { + tooltip.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "AH Sales (Clean): " + + EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + + (auctionInfo.get("clean_sales").getAsFloat() < 2 ? + format.format(auctionInfo.get("clean_sales").getAsFloat()) + " sale/day" + : + format.format(auctionInfo.get("clean_sales").getAsFloat()) + " sales/day")); + } else { + tooltip.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "AH Sales: " + + EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + + (auctionInfo.get("sales").getAsFloat() < 2 ? format.format(auctionInfo.get("sales").getAsFloat()) + + " sale/day" + : format.format(auctionInfo.get("sales").getAsFloat()) + + " sales/day")); + } + } + break; + case 3: + if (craftCost != null && craftCost.fromRecipe) { + if ((int) craftCost.craftCost == 0) { + continue; + } + if (!added) { + tooltip.add(""); + added = true; + } + tooltip.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "Raw Craft Cost: " + + EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + + (shortNumber && craftCost.craftCost > 1000 + ? Utils.shortNumberFormat(craftCost.craftCost, 0) + : format.format((int) craftCost.craftCost)) + " coins"); + } + break; + case 4: + if (lowestBinAvg > 0) { + if (!added) { + tooltip.add(""); + added = true; + } + tooltip.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "AVG Lowest BIN: " + + EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + + (shortNumber && lowestBinAvg > 1000 + ? Utils.shortNumberFormat(lowestBinAvg, 0) + : format.format(lowestBinAvg)) + " coins"); + } + break; + case 5: + if (Constants.ESSENCECOSTS == null) break; + JsonObject essenceCosts = Constants.ESSENCECOSTS; + if (!essenceCosts.has(internalname)) { + break; + } + JsonObject itemCosts = essenceCosts.get(internalname).getAsJsonObject(); + String essenceType = itemCosts.get("type").getAsString(); + + int dungeonItemLevel = -1; + if (stack != null && stack.hasTagCompound() && + stack.getTagCompound().hasKey("ExtraAttributes", 10)) { + NBTTagCompound ea = stack.getTagCompound().getCompoundTag("ExtraAttributes"); + + if (ea.hasKey("dungeon_item_level", 99)) { + dungeonItemLevel = ea.getInteger("dungeon_item_level"); + } + } + if (dungeonItemLevel == -1) { + int dungeonizeCost = 0; + if (itemCosts.has("dungeonize")) { + dungeonizeCost = itemCosts.get("dungeonize").getAsInt(); + } + tooltip.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "Dungeonize Cost: " + + EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + dungeonizeCost + " " + essenceType); + } else if (dungeonItemLevel >= 0 && dungeonItemLevel <= 4) { + String costType = (dungeonItemLevel + 1) + ""; + + int upgradeCost = itemCosts.get(costType).getAsInt(); + StringBuilder star = new StringBuilder(); + for (int i = 0; i <= dungeonItemLevel; i++) { + star.append('\u272A'); + } + tooltip.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "Upgrade to " + + EnumChatFormatting.GOLD + star + EnumChatFormatting.YELLOW + EnumChatFormatting.BOLD + ": " + + EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + upgradeCost + " " + essenceType); + } + break; + } + } + + return added; + } else if (auctionInfoErrored) { + String message = EnumChatFormatting.RED.toString() + EnumChatFormatting.BOLD + "[NEU] API is down"; + if (auctionableItems != null && !auctionableItems.isEmpty()) { + if (auctionableItems.contains(internalname)) { + tooltip.add(message); + return true; + } + } else { + tooltip.add(message + " and no item data is cached"); + return true; + } + } + + return false; + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUApi.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUApi.java index 56a196b4a6..d83035d0db 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NEUApi.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUApi.java @@ -3,8 +3,9 @@ import net.minecraftforge.fml.relauncher.ReflectionHelper; public class NEUApi { - static boolean disableInventoryButtons = false; - public static void setInventoryButtonsToDisabled(){ - disableInventoryButtons = true; - } + static boolean disableInventoryButtons = false; + + public static void setInventoryButtonsToDisabled() { + disableInventoryButtons = true; + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUEventListener.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUEventListener.java index 42b53ef24f..84289e3456 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NEUEventListener.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUEventListener.java @@ -1,10 +1,14 @@ package io.github.moulberry.notenoughupdates; import com.google.common.collect.Lists; -import com.google.gson.*; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; import com.mojang.authlib.GameProfile; import com.mojang.authlib.minecraft.MinecraftProfileTexture; import io.github.moulberry.notenoughupdates.auction.CustomAHGui; +import io.github.moulberry.notenoughupdates.commands.profile.ViewProfileCommand; import io.github.moulberry.notenoughupdates.core.BackgroundBlur; import io.github.moulberry.notenoughupdates.core.GuiScreenElementWrapper; import io.github.moulberry.notenoughupdates.core.util.MiscUtils; @@ -30,6 +34,7 @@ import net.minecraft.init.Items; import net.minecraft.inventory.ContainerChest; import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.Slot; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; @@ -65,333 +70,356 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import static io.github.moulberry.notenoughupdates.overlays.SlayerOverlay.*; import static io.github.moulberry.notenoughupdates.util.GuiTextures.dungeon_chest_worth; public class NEUEventListener { - private final NotEnoughUpdates neu; - - private boolean hoverInv = false; - private boolean focusInv = false; - - private boolean joinedSB = false; - - public NEUEventListener(NotEnoughUpdates neu) { - this.neu = neu; - } - - private void displayUpdateMessageIfOutOfDate() { - File repo = neu.manager.repoLocation; - if(repo.exists()) { - File updateJson = new File(repo, "update.json"); - try { - JsonObject o = neu.manager.getJsonFromFile(updateJson); - - String version = o.get("version").getAsString(); - String preVersion = o.get("pre_version").getAsString(); - - boolean shouldUpdate = !NotEnoughUpdates.VERSION.equalsIgnoreCase(version); - boolean shouldPreUpdate = !NotEnoughUpdates.PRE_VERSION.equalsIgnoreCase(preVersion); - - if(o.has("version_id") && o.get("version_id").isJsonPrimitive()) { - int version_id = o.get("version_id").getAsInt(); - shouldUpdate = version_id > NotEnoughUpdates.VERSION_ID; - } - if (o.has("pre_version_id") && o.get("pre_version_id").isJsonPrimitive()) { - int pre_version_id = o.get("pre_version_id").getAsInt(); - shouldPreUpdate = pre_version_id > NotEnoughUpdates.PRE_VERSION_ID; - } - - if(shouldUpdate) { - String update_msg = o.get("update_msg").getAsString(); - - int first_len = -1; - for(String line : update_msg.split("\n")) { - FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; - int len = fr.getStringWidth(line); - if(first_len == -1) { - first_len = len; - } - int missing_len = first_len-len; - if(missing_len > 0) { - StringBuilder sb = new StringBuilder(line); - for(int i=0; i 0) { - StringBuilder sb = new StringBuilder(line); - for (int i = 0; i < missing_len / 8; i++) { - sb.insert(0, " "); - } - line = sb.toString(); - } - line = line.replaceAll("\\{pre_version}", preVersion); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(line)); - } - - neu.displayLinks(o); - - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); - } - } catch(Exception ignored) {} - } - } - - @SubscribeEvent - public void onWorldLoad(WorldEvent.Unload event) { - NotEnoughUpdates.INSTANCE.saveConfig(); - CrystalMetalDetectorSolver.reset(false); - } - - private static long notificationDisplayMillis = 0; - private static List notificationLines = null; - private static boolean showNotificationOverInv = false; - - private static final Pattern BAD_ITEM_REGEX = Pattern.compile("x[0-9]{1,2}$"); - - /** - * 1)Will send the cached message from #sendChatMessage when at least 200ms has passed since the last message. - * This is used in order to prevent the mod spamming messages. - * 2)Adds unique items to the collection log - */ - private boolean preloadedItems = false; - private long lastLongUpdate = 0; - private long lastSkyblockScoreboard = 0; - - private final ExecutorService itemPreloader = Executors.newFixedThreadPool(10); - private final List toPreload = new ArrayList<>(); - - private int inventoryLoadedTicks = 0; - private String loadedInvName = ""; - public static boolean inventoryLoaded = false; - public static void displayNotification(List lines, boolean showForever) { - displayNotification(lines, showForever, false); - } - - public static void displayNotification(List lines, boolean showForever, boolean overInventory) { - if(showForever) { - notificationDisplayMillis = -420; - } else { - notificationDisplayMillis = System.currentTimeMillis(); - } - notificationLines = lines; - showNotificationOverInv = overInventory; - } - - @SubscribeEvent - public void onTick(TickEvent.ClientTickEvent event) { - if(Minecraft.getMinecraft().currentScreen == null || !(Minecraft.getMinecraft().currentScreen instanceof GuiChat)) { - Keyboard.enableRepeatEvents(false); - } - if(event.phase != TickEvent.Phase.START) return; - if(Minecraft.getMinecraft().theWorld == null) return; - if(Minecraft.getMinecraft().thePlayer == null) return; - - if(Minecraft.getMinecraft().currentScreen instanceof GuiChest) { - GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen; - ContainerChest cc = (ContainerChest) chest.inventorySlots; - - if(!loadedInvName.equals(cc.getLowerChestInventory().getDisplayName().getUnformattedText())) { - loadedInvName = cc.getLowerChestInventory().getDisplayName().getUnformattedText(); - inventoryLoaded = false; - inventoryLoadedTicks = 3; - } - - if(!inventoryLoaded) { - if(cc.getLowerChestInventory().getStackInSlot(cc.getLowerChestInventory().getSizeInventory()-1) != null) { - inventoryLoaded = true; - } else { - for(ItemStack stack : chest.inventorySlots.getInventory()) { - if(stack != null) { - if(--inventoryLoadedTicks <= 0) { - inventoryLoaded = true; - } - break; - } - } - } - } - } else { - inventoryLoaded = false; - inventoryLoadedTicks = 3; - } - - if(Keyboard.isKeyDown(Keyboard.KEY_NUMPAD1) && Keyboard.isKeyDown(Keyboard.KEY_NUMPAD4) && Keyboard.isKeyDown(Keyboard.KEY_NUMPAD9)) { - ChatComponentText component = new ChatComponentText("\u00a7cYou are permanently banned from this server!"); - component.appendText("\n"); - component.appendText("\n\u00a77Reason: \u00a7rSuspicious account activity/Other"); - component.appendText("\n\u00a77Find out more: \u00a7b\u00a7nhttps://www.hypixel.net/appeal"); - component.appendText("\n"); - component.appendText("\n\u00a77Ban ID: \u00a7r#49871982"); - component.appendText("\n\u00a77Sharing your Ban ID may affect the processing of your appeal!"); - Minecraft.getMinecraft().getNetHandler().getNetworkManager().closeChannel(component); - return; - } - - if(neu.hasSkyblockScoreboard()) { - if(!preloadedItems) { - preloadedItems = true; - List list = new ArrayList<>(neu.manager.getItemInformation().values()); - for(JsonObject json : list) { - itemPreloader.submit(() -> { - ItemStack stack = neu.manager.jsonToStack(json, true, true); - if(stack.getItem() == Items.skull) toPreload.add(stack); - }); - } - } else if(!toPreload.isEmpty()) { - Utils.drawItemStack(toPreload.get(0), -100, -100); - toPreload.remove(0); - } else { - itemPreloader.shutdown(); - } - - for(TextOverlay overlay : OverlayManager.textOverlays) { - overlay.shouldUpdateFrequent = true; - } - } - - boolean longUpdate = false; - long currentTime = System.currentTimeMillis(); - if(currentTime - lastLongUpdate > 1000) { - longUpdate = true; - lastLongUpdate = currentTime; - } - if(!NotEnoughUpdates.INSTANCE.config.dungeons.slowDungeonBlocks) { - DungeonBlocks.tick(); - } - DungeonWin.tick(); - - String containerName = null; - if(Minecraft.getMinecraft().currentScreen instanceof GuiChest) { - GuiChest eventGui = (GuiChest) Minecraft.getMinecraft().currentScreen; - ContainerChest cc = (ContainerChest) eventGui.inventorySlots; - containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText(); - - if(GuiCustomEnchant.getInstance().shouldOverride(containerName)) { - GuiCustomEnchant.getInstance().tick(); - } - } - - if(longUpdate) { - CrystalOverlay.tick(); - DwarvenMinesTextures.tick(); - FairySouls.tick(); - XPInformation.getInstance().tick(); - ProfileApiSyncer.getInstance().tick(); - ItemCustomizeManager.tick(); - BackgroundBlur.markDirty(); - NPCRetexturing.getInstance().tick(); - StorageOverlay.getInstance().markDirty(); - - if(neu.hasSkyblockScoreboard()) { - for(TextOverlay overlay : OverlayManager.textOverlays) { - overlay.tick(); - } - } - - NotEnoughUpdates.INSTANCE.overlay.redrawItems(); - CapeManager.onTickSlow(); - - NotEnoughUpdates.profileViewer.putNameUuid(Minecraft.getMinecraft().thePlayer.getName(), - Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", "")); - - if(NotEnoughUpdates.INSTANCE.config.dungeons.slowDungeonBlocks) { - DungeonBlocks.tick(); - } - - if(System.currentTimeMillis() - SBInfo.getInstance().joinedWorld > 500 && - System.currentTimeMillis() - SBInfo.getInstance().unloadedWorld > 500) { - neu.updateSkyblockScoreboard(); - } - CapeManager.getInstance().tick(); - - if(containerName != null) { - if(!containerName.trim().startsWith("Accessory Bag")) { - AccessoryBagOverlay.resetCache(); - } - } else { - AccessoryBagOverlay.resetCache(); - } - - if(neu.hasSkyblockScoreboard()) { - SBInfo.getInstance().tick(); - lastSkyblockScoreboard = currentTime; - if(!joinedSB) { - joinedSB = true; - - //SBGamemodes.loadFromFile(); - - - if(NotEnoughUpdates.INSTANCE.config.notifications.showUpdateMsg) { - displayUpdateMessageIfOutOfDate(); - } - - if(NotEnoughUpdates.INSTANCE.config.notifications.doRamNotif) { - long maxMemoryMB = Runtime.getRuntime().maxMemory()/1024L/1024L; - if(maxMemoryMB > 4100) { - notificationDisplayMillis = System.currentTimeMillis(); - notificationLines = new ArrayList<>(); - notificationLines.add(EnumChatFormatting.GRAY+"Too much memory allocated!"); - notificationLines.add(String.format(EnumChatFormatting.DARK_GRAY+"NEU has detected %03dMB of memory allocated to Minecraft!", maxMemoryMB)); - notificationLines.add(EnumChatFormatting.GRAY+"It is recommended to allocated between 2-4GB of memory"); - notificationLines.add(EnumChatFormatting.GRAY+"More than 4GB MAY cause FPS issues, EVEN if you have 16GB+ available"); - notificationLines.add(""); - notificationLines.add(EnumChatFormatting.GRAY+"For more information, visit #ram-info in discord.gg/moulberry"); - } - } - - if(!NotEnoughUpdates.INSTANCE.config.hidden.loadedModBefore) { - NotEnoughUpdates.INSTANCE.config.hidden.loadedModBefore = true; - if(Constants.MISC == null || !Constants.MISC.has("featureslist")){ - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(""+EnumChatFormatting.DARK_RED+EnumChatFormatting.BOLD+"WARNING: "+EnumChatFormatting.RESET+EnumChatFormatting.RED+"Could not load Feature List URL from repo.")); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(""+EnumChatFormatting.RED+ "Please run "+EnumChatFormatting.BOLD+"/neuresetrepo"+EnumChatFormatting.RESET+EnumChatFormatting.RED+" and "+EnumChatFormatting.BOLD+"restart your game"+EnumChatFormatting.RESET+EnumChatFormatting.RED+" in order to fix. "+EnumChatFormatting.DARK_RED+EnumChatFormatting.BOLD+"If that doesn't fix it"+EnumChatFormatting.RESET+EnumChatFormatting.RED+", please join discord.gg/moulberry and post in #neu-support")); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(""+EnumChatFormatting.GOLD+"To view the feature list after restarting type /neufeatures")); - } else { - String url = Constants.MISC.get("featureslist").getAsString(); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.BLUE + "It seems this is your first time using NotEnoughUpdates.")); - ChatComponentText clickTextFeatures = new ChatComponentText( - EnumChatFormatting.YELLOW + "Click this message if you would like to view a list of NotEnoughUpdate's Features."); - clickTextFeatures.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, url)); - Minecraft.getMinecraft().thePlayer.addChatMessage(clickTextFeatures); - } - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); - ChatComponentText clickTextHelp = new ChatComponentText( - EnumChatFormatting.YELLOW+"Click this message if you would like to view a list of NotEnoughUpdate's commands."); - clickTextHelp.setChatStyle(Utils.createClickStyle(ClickEvent.Action.RUN_COMMAND, "/neuhelp")); - Minecraft.getMinecraft().thePlayer.addChatMessage(clickTextHelp); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); - } - } - } - if(currentTime - lastSkyblockScoreboard < 5*60*1000) { //5 minutes - neu.manager.auctionManager.tick(); - } else { - neu.manager.auctionManager.markNeedsUpdate(); - } - } + private final NotEnoughUpdates neu; + + private boolean hoverInv = false; + private boolean focusInv = false; + + private boolean joinedSB = false; + + public NEUEventListener(NotEnoughUpdates neu) { + this.neu = neu; + } + + private void displayUpdateMessageIfOutOfDate() { + File repo = neu.manager.repoLocation; + if (repo.exists()) { + File updateJson = new File(repo, "update.json"); + try { + JsonObject o = neu.manager.getJsonFromFile(updateJson); + + String version = o.get("version").getAsString(); + String preVersion = o.get("pre_version").getAsString(); + + boolean shouldUpdate = !NotEnoughUpdates.VERSION.equalsIgnoreCase(version); + boolean shouldPreUpdate = !NotEnoughUpdates.PRE_VERSION.equalsIgnoreCase(preVersion); + + if (o.has("version_id") && o.get("version_id").isJsonPrimitive()) { + int version_id = o.get("version_id").getAsInt(); + shouldUpdate = version_id > NotEnoughUpdates.VERSION_ID; + } + if (o.has("pre_version_id") && o.get("pre_version_id").isJsonPrimitive()) { + int pre_version_id = o.get("pre_version_id").getAsInt(); + shouldPreUpdate = pre_version_id > NotEnoughUpdates.PRE_VERSION_ID; + } + + if (shouldUpdate) { + String update_msg = o.get("update_msg").getAsString(); + + int first_len = -1; + for (String line : update_msg.split("\n")) { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + int len = fr.getStringWidth(line); + if (first_len == -1) { + first_len = len; + } + int missing_len = first_len - len; + if (missing_len > 0) { + StringBuilder sb = new StringBuilder(line); + for (int i = 0; i < missing_len / 8; i++) { + sb.insert(0, " "); + } + line = sb.toString(); + } + line = line.replaceAll("\\{version}", version); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(line)); + } + + neu.displayLinks(o); + + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); + } else if (shouldPreUpdate && NotEnoughUpdates.VERSION_ID == o.get("version").getAsInt()) { + String pre_update_msg = o.get("pre_update_msg").getAsString(); + + int first_len = -1; + for (String line : pre_update_msg.split("\n")) { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + int len = fr.getStringWidth(line); + if (first_len == -1) { + first_len = len; + } + int missing_len = first_len - len; + if (missing_len > 0) { + StringBuilder sb = new StringBuilder(line); + for (int i = 0; i < missing_len / 8; i++) { + sb.insert(0, " "); + } + line = sb.toString(); + } + line = line.replaceAll("\\{pre_version}", preVersion); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(line)); + } + + neu.displayLinks(o); + + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); + } + } catch (Exception ignored) { + } + } + } + + @SubscribeEvent + public void onWorldLoad(WorldEvent.Unload event) { + NotEnoughUpdates.INSTANCE.saveConfig(); + CrystalMetalDetectorSolver.reset(false); + } + + private static long notificationDisplayMillis = 0; + private static List notificationLines = null; + private static boolean showNotificationOverInv = false; + + private static final Pattern BAD_ITEM_REGEX = Pattern.compile("x[0-9]{1,2}$"); + private static final Pattern SLAYER_XP = + Pattern.compile(" (Spider|Zombie|Wolf|Enderman) Slayer LVL (\\d) - (?:Next LVL in ([\\d,]+) XP!|LVL MAXED OUT!)"); + + /** + * 1)Will send the cached message from #sendChatMessage when at least 200ms has passed since the last message. + * This is used in order to prevent the mod spamming messages. + * 2)Adds unique items to the collection log + */ + private boolean preloadedItems = false; + private long lastLongUpdate = 0; + private long lastSkyblockScoreboard = 0; + + private final ExecutorService itemPreloader = Executors.newFixedThreadPool(10); + private final List toPreload = new ArrayList<>(); + + private int inventoryLoadedTicks = 0; + private String loadedInvName = ""; + public static boolean inventoryLoaded = false; + + public static void displayNotification(List lines, boolean showForever) { + displayNotification(lines, showForever, false); + } + + public static void displayNotification(List lines, boolean showForever, boolean overInventory) { + if (showForever) { + notificationDisplayMillis = -420; + } else { + notificationDisplayMillis = System.currentTimeMillis(); + } + notificationLines = lines; + showNotificationOverInv = overInventory; + } + + @SubscribeEvent + public void onTick(TickEvent.ClientTickEvent event) { + Keyboard.enableRepeatEvents( + Minecraft.getMinecraft().currentScreen != null && (Minecraft.getMinecraft().currentScreen instanceof GuiChat + || Minecraft.getMinecraft().currentScreen instanceof GuiEditSign || + Minecraft.getMinecraft().currentScreen instanceof GuiScreenBook)); + if (event.phase != TickEvent.Phase.START) return; + if (Minecraft.getMinecraft().theWorld == null) return; + if (Minecraft.getMinecraft().thePlayer == null) return; + + if (Minecraft.getMinecraft().currentScreen instanceof GuiChest) { + GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen; + ContainerChest cc = (ContainerChest) chest.inventorySlots; + + if (!loadedInvName.equals(cc.getLowerChestInventory().getDisplayName().getUnformattedText())) { + loadedInvName = cc.getLowerChestInventory().getDisplayName().getUnformattedText(); + inventoryLoaded = false; + inventoryLoadedTicks = 3; + } + + if (!inventoryLoaded) { + if (cc.getLowerChestInventory().getStackInSlot(cc.getLowerChestInventory().getSizeInventory() - 1) != null) { + inventoryLoaded = true; + } else { + for (ItemStack stack : chest.inventorySlots.getInventory()) { + if (stack != null) { + if (--inventoryLoadedTicks <= 0) { + inventoryLoaded = true; + } + break; + } + } + } + } + } else { + inventoryLoaded = false; + inventoryLoadedTicks = 3; + } + + if ((Keyboard.isKeyDown(Keyboard.KEY_NUMPAD1) && Keyboard.isKeyDown(Keyboard.KEY_NUMPAD4) && + Keyboard.isKeyDown(Keyboard.KEY_NUMPAD9))) { + ChatComponentText component = new ChatComponentText("\u00a7cYou are permanently banned from this server!"); + component.appendText("\n"); + component.appendText("\n\u00a77Reason: \u00a7rSuspicious account activity/Other"); + component.appendText("\n\u00a77Find out more: \u00a7b\u00a7nhttps://www.hypixel.net/appeal"); + component.appendText("\n"); + component.appendText("\n\u00a77Ban ID: \u00a7r#49871982"); + component.appendText("\n\u00a77Sharing your Ban ID may affect the processing of your appeal!"); + Minecraft.getMinecraft().getNetHandler().getNetworkManager().closeChannel(component); + return; + } + + if (neu.hasSkyblockScoreboard()) { + if (!preloadedItems) { + preloadedItems = true; + List list = new ArrayList<>(neu.manager.getItemInformation().values()); + for (JsonObject json : list) { + itemPreloader.submit(() -> { + ItemStack stack = neu.manager.jsonToStack(json, true, true); + if (stack.getItem() == Items.skull) toPreload.add(stack); + }); + } + } else if (!toPreload.isEmpty()) { + Utils.drawItemStack(toPreload.get(0), -100, -100); + toPreload.remove(0); + } else { + itemPreloader.shutdown(); + } + + for (TextOverlay overlay : OverlayManager.textOverlays) { + overlay.shouldUpdateFrequent = true; + } + } + + boolean longUpdate = false; + long currentTime = System.currentTimeMillis(); + if (currentTime - lastLongUpdate > 1000) { + longUpdate = true; + lastLongUpdate = currentTime; + } + if (!NotEnoughUpdates.INSTANCE.config.dungeons.slowDungeonBlocks) { + DungeonBlocks.tick(); + } + DungeonWin.tick(); + + String containerName = null; + if (Minecraft.getMinecraft().currentScreen instanceof GuiChest) { + GuiChest eventGui = (GuiChest) Minecraft.getMinecraft().currentScreen; + ContainerChest cc = (ContainerChest) eventGui.inventorySlots; + containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText(); + + if (GuiCustomEnchant.getInstance().shouldOverride(containerName)) { + GuiCustomEnchant.getInstance().tick(); + } + } + + if (longUpdate) { + CrystalOverlay.tick(); + FairySouls.tick(); + XPInformation.getInstance().tick(); + ProfileApiSyncer.getInstance().tick(); + ItemCustomizeManager.tick(); + BackgroundBlur.markDirty(); + NPCRetexturing.getInstance().tick(); + StorageOverlay.getInstance().markDirty(); + + if (neu.hasSkyblockScoreboard()) { + for (TextOverlay overlay : OverlayManager.textOverlays) { + overlay.tick(); + } + } + + NotEnoughUpdates.INSTANCE.overlay.redrawItems(); + CapeManager.onTickSlow(); + + NotEnoughUpdates.profileViewer.putNameUuid( + Minecraft.getMinecraft().thePlayer.getName(), + Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", "") + ); + + if (NotEnoughUpdates.INSTANCE.config.dungeons.slowDungeonBlocks) { + DungeonBlocks.tick(); + } + + if (System.currentTimeMillis() - SBInfo.getInstance().joinedWorld > 500 && + System.currentTimeMillis() - SBInfo.getInstance().unloadedWorld > 500) { + neu.updateSkyblockScoreboard(); + } + CapeManager.getInstance().tick(); + + if (containerName != null) { + if (!containerName.trim().startsWith("Accessory Bag")) { + AccessoryBagOverlay.resetCache(); + } + } else { + AccessoryBagOverlay.resetCache(); + } + + if (neu.hasSkyblockScoreboard()) { + SBInfo.getInstance().tick(); + lastSkyblockScoreboard = currentTime; + if (!joinedSB) { + joinedSB = true; + + //SBGamemodes.loadFromFile(); + + if (NotEnoughUpdates.INSTANCE.config.notifications.showUpdateMsg) { + displayUpdateMessageIfOutOfDate(); + } + + if (NotEnoughUpdates.INSTANCE.config.notifications.doRamNotif) { + long maxMemoryMB = Runtime.getRuntime().maxMemory() / 1024L / 1024L; + if (maxMemoryMB > 4100) { + notificationDisplayMillis = System.currentTimeMillis(); + notificationLines = new ArrayList<>(); + notificationLines.add(EnumChatFormatting.GRAY + "Too much memory allocated!"); + notificationLines.add(String.format( + EnumChatFormatting.DARK_GRAY + "NEU has detected %03dMB of memory allocated to Minecraft!", + maxMemoryMB + )); + notificationLines.add(EnumChatFormatting.GRAY + "It is recommended to allocated between 2-4GB of memory"); + notificationLines.add( + EnumChatFormatting.GRAY + "More than 4GB MAY cause FPS issues, EVEN if you have 16GB+ available"); + notificationLines.add(""); + notificationLines.add( + EnumChatFormatting.GRAY + "For more information, visit #ram-info in discord.gg/moulberry"); + } + } + + if (!NotEnoughUpdates.INSTANCE.config.hidden.loadedModBefore) { + NotEnoughUpdates.INSTANCE.config.hidden.loadedModBefore = true; + if (Constants.MISC == null || !Constants.MISC.has("featureslist")) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( + "" + EnumChatFormatting.DARK_RED + EnumChatFormatting.BOLD + "WARNING: " + EnumChatFormatting.RESET + + EnumChatFormatting.RED + "Could not load Feature List URL from repo.")); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( + "" + EnumChatFormatting.RED + "Please run " + EnumChatFormatting.BOLD + "/neuresetrepo" + + EnumChatFormatting.RESET + EnumChatFormatting.RED + " and " + EnumChatFormatting.BOLD + + "restart your game" + EnumChatFormatting.RESET + EnumChatFormatting.RED + " in order to fix. " + + EnumChatFormatting.DARK_RED + EnumChatFormatting.BOLD + "If that doesn't fix it" + + EnumChatFormatting.RESET + EnumChatFormatting.RED + + ", please join discord.gg/moulberry and post in #neu-support")); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( + "" + EnumChatFormatting.GOLD + "To view the feature list after restarting type /neufeatures")); + } else { + String url = Constants.MISC.get("featureslist").getAsString(); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( + EnumChatFormatting.BLUE + "It seems this is your first time using NotEnoughUpdates.")); + ChatComponentText clickTextFeatures = new ChatComponentText( + EnumChatFormatting.YELLOW + + "Click this message if you would like to view a list of NotEnoughUpdate's Features."); + clickTextFeatures.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, url)); + Minecraft.getMinecraft().thePlayer.addChatMessage(clickTextFeatures); + } + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); + ChatComponentText clickTextHelp = new ChatComponentText( + EnumChatFormatting.YELLOW + + "Click this message if you would like to view a list of NotEnoughUpdate's commands."); + clickTextHelp.setChatStyle(Utils.createClickStyle(ClickEvent.Action.RUN_COMMAND, "/neuhelp")); + Minecraft.getMinecraft().thePlayer.addChatMessage(clickTextHelp); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); + } + } + } + if (currentTime - lastSkyblockScoreboard < 5 * 60 * 1000) { //5 minutes + neu.manager.auctionManager.tick(); + } else { + neu.manager.auctionManager.markNeedsUpdate(); + } + } /*if(longUpdate && neu.hasSkyblockScoreboard()) { if(neu.manager.getCurrentProfile() == null || neu.manager.getCurrentProfile().length() == 0) { @@ -449,7 +477,7 @@ public void onTick(TickEvent.ClientTickEvent event) { newItemAddMap.keySet().retainAll(newItem); } }*/ - } + } /*private void processUniqueStack(ItemStack stack, HashSet newItem) { if(stack != null && stack.hasTagCompound()) { @@ -472,196 +500,205 @@ public void onTick(TickEvent.ClientTickEvent event) { } }*/ - @SubscribeEvent(priority= EventPriority.HIGHEST) - public void onRenderEntitySpecials(RenderLivingEvent.Specials.Pre event) { - if(Minecraft.getMinecraft().currentScreen instanceof GuiProfileViewer) { - if(((GuiProfileViewer)Minecraft.getMinecraft().currentScreen).getEntityPlayer() == event.entity) { - event.setCanceled(true); - } - } - } - - @SubscribeEvent - public void onRenderGameOverlayPre(RenderGameOverlayEvent.Pre event) { - if (event.type != null && event.type.equals(RenderGameOverlayEvent.ElementType.BOSSHEALTH) && - Minecraft.getMinecraft().currentScreen instanceof GuiContainer && neu.overlay.isUsingMobsFilter()) { - event.setCanceled(true); - } - if(event.type != null && event.type.equals(RenderGameOverlayEvent.ElementType.PLAYER_LIST)) { - GlStateManager.enableDepth(); - } - } - - @SubscribeEvent - public void onRenderGameOverlayPost(RenderGameOverlayEvent.Post event) { - if(neu.hasSkyblockScoreboard() && event.type.equals(RenderGameOverlayEvent.ElementType.ALL)) { - DungeonWin.render(event.partialTicks); - GlStateManager.pushMatrix(); - GlStateManager.translate(0, 0, -200); - for(TextOverlay overlay : OverlayManager.textOverlays) { - if(OverlayManager.dontRenderOverlay != null && OverlayManager.dontRenderOverlay.isAssignableFrom(overlay.getClass())) { - continue; - } - GlStateManager.translate(0, 0, -1); - GlStateManager.enableDepth(); - overlay.render(); - } - GlStateManager.popMatrix(); - OverlayManager.dontRenderOverlay = null; - } - if(Keyboard.isKeyDown(Keyboard.KEY_X)) { - notificationDisplayMillis = 0; - } - - if(event.type == RenderGameOverlayEvent.ElementType.ALL){ - renderNotification(); - } - - } - private static void renderNotification(){ - - long timeRemaining = 15000 - (System.currentTimeMillis() - notificationDisplayMillis); - boolean display = timeRemaining > 0 || notificationDisplayMillis == -420; - if(display && notificationLines != null && notificationLines.size() > 0) { - int width = 0; - int height = notificationLines.size()*10+10; - - for(String line : notificationLines) { - int len = Minecraft.getMinecraft().fontRendererObj.getStringWidth(line) + 8; - if(len > width) { - width = len; - } - } - - ScaledResolution sr = Utils.pushGuiScale(2); - - int midX = sr.getScaledWidth()/2; - int topY = sr.getScaledHeight()*3/4-height/2; - RenderUtils.drawFloatingRectDark(midX-width/2, sr.getScaledHeight()*3/4-height/2, width, height); + @SubscribeEvent(priority = EventPriority.HIGHEST) + public void onRenderEntitySpecials(RenderLivingEvent.Specials.Pre event) { + if (Minecraft.getMinecraft().currentScreen instanceof GuiProfileViewer) { + if (((GuiProfileViewer) Minecraft.getMinecraft().currentScreen).getEntityPlayer() == event.entity) { + event.setCanceled(true); + } + } + } + + @SubscribeEvent + public void onRenderGameOverlayPre(RenderGameOverlayEvent.Pre event) { + if (event.type != null && event.type.equals(RenderGameOverlayEvent.ElementType.BOSSHEALTH) && + Minecraft.getMinecraft().currentScreen instanceof GuiContainer && neu.overlay.isUsingMobsFilter()) { + event.setCanceled(true); + } + if (event.type != null && event.type.equals(RenderGameOverlayEvent.ElementType.PLAYER_LIST)) { + GlStateManager.enableDepth(); + } + } + + @SubscribeEvent + public void onRenderGameOverlayPost(RenderGameOverlayEvent.Post event) { + if (neu.hasSkyblockScoreboard() && event.type.equals(RenderGameOverlayEvent.ElementType.ALL)) { + DungeonWin.render(event.partialTicks); + GlStateManager.pushMatrix(); + GlStateManager.translate(0, 0, -200); + for (TextOverlay overlay : OverlayManager.textOverlays) { + if (OverlayManager.dontRenderOverlay != null && + OverlayManager.dontRenderOverlay.isAssignableFrom(overlay.getClass())) { + continue; + } + GlStateManager.translate(0, 0, -1); + GlStateManager.enableDepth(); + overlay.render(); + } + GlStateManager.popMatrix(); + OverlayManager.dontRenderOverlay = null; + } + if (Keyboard.isKeyDown(Keyboard.KEY_X)) { + notificationDisplayMillis = 0; + } + + if (event.type == RenderGameOverlayEvent.ElementType.ALL) { + renderNotification(); + } + + } + + private static void renderNotification() { + + long timeRemaining = 15000 - (System.currentTimeMillis() - notificationDisplayMillis); + boolean display = timeRemaining > 0 || notificationDisplayMillis == -420; + if (display && notificationLines != null && notificationLines.size() > 0) { + int width = 0; + int height = notificationLines.size() * 10 + 10; + + for (String line : notificationLines) { + int len = Minecraft.getMinecraft().fontRendererObj.getStringWidth(line) + 8; + if (len > width) { + width = len; + } + } + + ScaledResolution sr = Utils.pushGuiScale(2); + + int midX = sr.getScaledWidth() / 2; + int topY = sr.getScaledHeight() * 3 / 4 - height / 2; + RenderUtils.drawFloatingRectDark(midX - width / 2, sr.getScaledHeight() * 3 / 4 - height / 2, width, height); /*Gui.drawRect(midX-width/2, sr.getScaledHeight()*3/4-height/2, midX+width/2, sr.getScaledHeight()*3/4+height/2, 0xFF3C3C3C); Gui.drawRect(midX-width/2+2, sr.getScaledHeight()*3/4-height/2+2, midX+width/2-2, sr.getScaledHeight()*3/4+height/2-2, 0xFFC8C8C8);*/ - int xLen = Minecraft.getMinecraft().fontRendererObj.getStringWidth("[X] Close"); - Minecraft.getMinecraft().fontRendererObj.drawString("[X] Close", midX+width/2f-3-xLen, - topY+3, 0xFFFF5555, false); - - if(notificationDisplayMillis > 0) { - Minecraft.getMinecraft().fontRendererObj.drawString((timeRemaining/1000)+"s", midX-width/2f+3, - topY+3, 0xFFaaaaaa, false); - } - - Utils.drawStringCentered(notificationLines.get(0), Minecraft.getMinecraft().fontRendererObj, - midX, topY+4+5, false, -1); - for(int i=1; i { - if(Minecraft.getMinecraft().currentScreen != event.gui) { - return; - } - if(lower.getStackInSlot(23).getDisplayName().endsWith("Crafting Table")) { - try { - ItemStack res = lower.getStackInSlot(25); - String resInternalname = neu.manager.getInternalNameForItem(res); - - if(lower.getStackInSlot(48) != null) { - String backName = null; - NBTTagCompound tag = lower.getStackInSlot(48).getTagCompound(); - if(tag.hasKey("display", 10)) { - NBTTagCompound nbttagcompound = tag.getCompoundTag("display"); - if(nbttagcompound.getTagId("Lore") == 9){ - NBTTagList nbttaglist1 = nbttagcompound.getTagList("Lore", 8); - backName = nbttaglist1.getStringTagAt(0); - } - } - - if(backName != null) { - String[] split = backName.split(" "); - if(split[split.length-1].contains("Rewards")) { - String col = backName.substring(split[0].length()+1, - backName.length()-split[split.length-1].length()-1); - - JsonObject json = neu.manager.getItemInformation().get(resInternalname); - json.addProperty("crafttext", "Requires: " + col); - - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("Added: " + resInternalname)); - neu.manager.writeJsonDefaultDir(json, resInternalname+".json"); - neu.manager.loadItem(resInternalname); - } - } - } + int xLen = Minecraft.getMinecraft().fontRendererObj.getStringWidth("[X] Close"); + Minecraft.getMinecraft().fontRendererObj.drawString("[X] Close", midX + width / 2f - 3 - xLen, + topY + 3, 0xFFFF5555, false + ); + + if (notificationDisplayMillis > 0) { + Minecraft.getMinecraft().fontRendererObj.drawString((timeRemaining / 1000) + "s", midX - width / 2f + 3, + topY + 3, 0xFFaaaaaa, false + ); + } + + Utils.drawStringCentered(notificationLines.get(0), Minecraft.getMinecraft().fontRendererObj, + midX, topY + 4 + 5, false, -1 + ); + for (int i = 1; i < notificationLines.size(); i++) { + String line = notificationLines.get(i); + Utils.drawStringCentered(line, Minecraft.getMinecraft().fontRendererObj, + midX, topY + 4 + 5 + 2 + i * 10, false, -1 + ); + } + + Utils.pushGuiScale(-1); + } + } + + public static long lastGuiClosed = 0; + + /** + * When opening a GuiContainer, will reset the overlay and load the config. + * When closing a GuiContainer, will save the config. + * Also includes a dev feature used for automatically acquiring crafting information from the "Crafting Table" GUI. + */ + AtomicBoolean missingRecipe = new AtomicBoolean(false); + + @SubscribeEvent + public void onGuiOpen(GuiOpenEvent event) { + NEUApi.disableInventoryButtons = false; + + if ((Minecraft.getMinecraft().currentScreen instanceof GuiScreenElementWrapper || + Minecraft.getMinecraft().currentScreen instanceof GuiItemRecipe) && + event.gui == null && !(Keyboard.getEventKeyState() && Keyboard.getEventKey() == Keyboard.KEY_ESCAPE) && + System.currentTimeMillis() - NotEnoughUpdates.INSTANCE.lastOpenedGui < 500) { + NotEnoughUpdates.INSTANCE.lastOpenedGui = 0; + event.setCanceled(true); + return; + } + + if (!(event.gui instanceof GuiContainer) && Minecraft.getMinecraft().currentScreen != null) { + CalendarOverlay.setEnabled(false); + } + + if (Minecraft.getMinecraft().currentScreen != null) { + lastGuiClosed = System.currentTimeMillis(); + } + + neu.manager.auctionManager.customAH.lastGuiScreenSwitch = System.currentTimeMillis(); + BetterContainers.reset(); + inventoryLoaded = false; + inventoryLoadedTicks = 3; + + if (event.gui == null && neu.manager.auctionManager.customAH.isRenderOverAuctionView() && + !(Minecraft.getMinecraft().currentScreen instanceof CustomAHGui)) { + event.gui = new CustomAHGui(); + } + + if (!(event.gui instanceof GuiChest || event.gui instanceof GuiEditSign)) { + neu.manager.auctionManager.customAH.setRenderOverAuctionView(false); + } else if (event.gui instanceof GuiChest && (neu.manager.auctionManager.customAH.isRenderOverAuctionView() || + Minecraft.getMinecraft().currentScreen instanceof CustomAHGui)) { + GuiChest chest = (GuiChest) event.gui; + ContainerChest container = (ContainerChest) chest.inventorySlots; + String containerName = container.getLowerChestInventory().getDisplayName().getUnformattedText(); + + neu.manager.auctionManager.customAH.setRenderOverAuctionView(containerName.trim().equals("Auction View") || + containerName.trim().equals("BIN Auction View") || containerName.trim().equals("Confirm Bid") || + containerName.trim().equals("Confirm Purchase")); + } + + //OPEN + if (Minecraft.getMinecraft().currentScreen == null + && event.gui instanceof GuiContainer) { + neu.overlay.reset(); + } + if (event.gui != null && NotEnoughUpdates.INSTANCE.config.hidden.dev) { + if (event.gui instanceof GuiChest) { + GuiChest eventGui = (GuiChest) event.gui; + ContainerChest cc = (ContainerChest) eventGui.inventorySlots; + IInventory lower = cc.getLowerChestInventory(); + ses.schedule(() -> { + if (Minecraft.getMinecraft().currentScreen != event.gui) { + return; + } + if (lower.getStackInSlot(23).getDisplayName().endsWith("Crafting Table")) { + try { + ItemStack res = lower.getStackInSlot(25); + String resInternalname = neu.manager.getInternalNameForItem(res); + + if (lower.getStackInSlot(48) != null) { + String backName = null; + NBTTagCompound tag = lower.getStackInSlot(48).getTagCompound(); + if (tag.hasKey("display", 10)) { + NBTTagCompound nbttagcompound = tag.getCompoundTag("display"); + if (nbttagcompound.getTagId("Lore") == 9) { + NBTTagList nbttaglist1 = nbttagcompound.getTagList("Lore", 8); + backName = nbttaglist1.getStringTagAt(0); + } + } + + if (backName != null) { + String[] split = backName.split(" "); + if (split[split.length - 1].contains("Rewards")) { + String col = backName.substring( + split[0].length() + 1, + backName.length() - split[split.length - 1].length() - 1 + ); + + JsonObject json = neu.manager.getItemInformation().get(resInternalname); + json.addProperty("crafttext", "Requires: " + col); + + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( + "Added: " + resInternalname)); + neu.manager.writeJsonDefaultDir(json, resInternalname + ".json"); + neu.manager.loadItem(resInternalname); + } + } + } /*JsonArray arr = null; File f = new File(neu.manager.configLocation, "missing.json"); @@ -713,14 +750,14 @@ public void onGuiOpen(GuiOpenEvent event) { Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("Added: " + resInternalname)); neu.manager.writeJsonDefaultDir(json, resInternalname+".json"); neu.manager.loadItem(resInternalname);*/ - } catch(Exception e) { - e.printStackTrace(); - } - } - }, 200, TimeUnit.MILLISECONDS); - } - } - } + } catch (Exception e) { + e.printStackTrace(); + } + } + }, 200, TimeUnit.MILLISECONDS); + } + } + } /*@SubscribeEvent public void onPlayerInteract(EntityInteractEvent event) { @@ -740,1884 +777,2066 @@ public void onPlayerInteract(EntityInteractEvent event) { } }*/ - private IChatComponent processChatComponent(IChatComponent chatComponent) { - IChatComponent newComponent; - if(chatComponent instanceof ChatComponentText) { - ChatComponentText text = (ChatComponentText) chatComponent; - - newComponent = new ChatComponentText(processText(text.getUnformattedTextForChat())); - newComponent.setChatStyle(text.getChatStyle().createShallowCopy()); - - for(IChatComponent sibling : text.getSiblings()) { - newComponent.appendSibling(processChatComponent(sibling)); - } - } else if(chatComponent instanceof ChatComponentTranslation) { - ChatComponentTranslation trans = (ChatComponentTranslation) chatComponent; - - Object[] args = trans.getFormatArgs(); - Object[] newArgs = new Object[args.length]; - for(int i=0; i width*neu.overlay.getItemPaneOffsetFactor(); - - if(event.gui instanceof GuiContainer) { - try { - int xSize = ((GuiContainer)event.gui).xSize; - int ySize = ((GuiContainer)event.gui).ySize; - int guiLeft = ((GuiContainer)event.gui).guiLeft; - int guiTop = ((GuiContainer)event.gui).guiTop; - - hoverInv = event.getMouseX() > guiLeft && event.getMouseX() < guiLeft + xSize && - event.getMouseY() > guiTop && event.getMouseY() < guiTop + ySize; - - if(hoverPane) { - if(!hoverInv) focusInv = false; - } else { - focusInv = true; - } - } catch(NullPointerException npe) { - focusInv = !hoverPane; - } - } - if(event.gui instanceof GuiItemRecipe) { - GuiItemRecipe guiItemRecipe = ((GuiItemRecipe)event.gui); - hoverInv = event.getMouseX() > guiItemRecipe.guiLeft && event.getMouseX() < guiItemRecipe.guiLeft + guiItemRecipe.xSize && - event.getMouseY() > guiItemRecipe.guiTop && event.getMouseY() < guiItemRecipe.guiTop + guiItemRecipe.ySize; - - if(hoverPane) { - if(!hoverInv) focusInv = false; - } else { - focusInv = true; - } - } - if(focusInv) { - try { - neu.overlay.render(hoverInv); - } catch(ConcurrentModificationException e) {e.printStackTrace();} - GL11.glTranslatef(0, 0, 10); - } - if(hoverInv) { - renderDungeonChestOverlay(event.gui); - if(NotEnoughUpdates.INSTANCE.config.accessoryBag.enableOverlay) { - AccessoryBagOverlay.renderOverlay(); - } - } - } - - drawingGuiScreen = true; - } - - private boolean doInventoryButtons = false; - - @SubscribeEvent - public void onGuiScreenDrawPre(GuiScreenEvent.DrawScreenEvent.Pre event) { - doInventoryButtons = false; - - if(AuctionSearchOverlay.shouldReplace()) { - AuctionSearchOverlay.render(); - event.setCanceled(true); - return; - } - if(RancherBootOverlay.shouldReplace()) { - RancherBootOverlay.render(); - event.setCanceled(true); - return; - } - - String containerName = null; - GuiScreen guiScreen = Minecraft.getMinecraft().currentScreen; - if(guiScreen instanceof GuiChest) { - GuiChest eventGui = (GuiChest) guiScreen; - ContainerChest cc = (ContainerChest) eventGui.inventorySlots; - containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText(); - } - - if(GuiCustomEnchant.getInstance().shouldOverride(containerName)) { - GuiCustomEnchant.getInstance().render(event.renderPartialTicks); - event.setCanceled(true); - return; - } - - boolean tradeWindowActive = TradeWindow.tradeWindowActive(containerName); - boolean storageOverlayActive = StorageManager.getInstance().shouldRenderStorageOverlay(containerName); - boolean customAhActive = event.gui instanceof CustomAHGui || neu.manager.auctionManager.customAH.isRenderOverAuctionView(); - - if(storageOverlayActive) { - StorageOverlay.getInstance().render(); - event.setCanceled(true); - return; - } - - if(tradeWindowActive || customAhActive) { - event.setCanceled(true); - - ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); - int width = scaledResolution.getScaledWidth(); - int height = scaledResolution.getScaledHeight(); - - //Dark background - Utils.drawGradientRect(0, 0, width, height, -1072689136, -804253680); - - if(event.mouseX < width*neu.overlay.getWidthMult()/3 || event.mouseX > width-width*neu.overlay.getWidthMult()/3) { - if(customAhActive) { - neu.manager.auctionManager.customAH.drawScreen(event.mouseX, event.mouseY); - } else if(tradeWindowActive) { - TradeWindow.render(event.mouseX, event.mouseY); - } - neu.overlay.render(false); - } else { - neu.overlay.render(false); - if(customAhActive) { - neu.manager.auctionManager.customAH.drawScreen(event.mouseX, event.mouseY); - } else if(tradeWindowActive) { - TradeWindow.render(event.mouseX, event.mouseY); - } - } - } - - if(CalendarOverlay.isEnabled() || event.isCanceled()) return; - if(NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() && shouldRenderOverlay(event.gui) - && event.gui instanceof GuiContainer) { - doInventoryButtons = true; - - int zOffset = 50; - - GlStateManager.translate(0, 0, zOffset); - - int xSize = ((GuiContainer) event.gui).xSize; - int ySize = ((GuiContainer) event.gui).ySize; - int guiLeft = ((GuiContainer) event.gui).guiLeft; - int guiTop = ((GuiContainer) event.gui).guiTop; - - if (!NEUApi.disableInventoryButtons) { - for (NEUConfig.InventoryButton button : NotEnoughUpdates.INSTANCE.config.hidden.inventoryButtons) { - if (!button.isActive()) continue; - if (button.playerInvOnly && !(event.gui instanceof GuiInventory)) continue; - - int x = guiLeft + button.x; - int y = guiTop + button.y; - if (button.anchorRight) { - x += xSize; - } - if (button.anchorBottom) { - y += ySize; - } - if (AccessoryBagOverlay.isInAccessoryBag()) { - if (x > guiLeft + xSize && x < guiLeft + xSize + 80 + 28 + 5 && y > guiTop - 18 && y < guiTop + 150) { - x += 80 + 28; - } - } - - GlStateManager.color(1, 1, 1, 1f); - - GlStateManager.enableDepth(); - GlStateManager.enableAlpha(); - Minecraft.getMinecraft().getTextureManager().bindTexture(EDITOR); - Utils.drawTexturedRect(x, y, 18, 18, - button.backgroundIndex * 18 / 256f, (button.backgroundIndex * 18 + 18) / 256f, - 18 / 256f, 36 / 256f, GL11.GL_NEAREST); - - if (button.icon != null && !button.icon.trim().isEmpty()) { - GuiInvButtonEditor.renderIcon(button.icon, x + 1, y + 1); - } - } - } - GlStateManager.translate(0, 0, -zOffset); - } - } - - private static boolean shouldRenderOverlay(Gui gui) { - boolean validGui = gui instanceof GuiContainer || gui instanceof GuiItemRecipe; - if(gui instanceof GuiChest) { - GuiChest eventGui = (GuiChest) gui; - ContainerChest cc = (ContainerChest) eventGui.inventorySlots; - String containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText(); - if(containerName.trim().equals("Fast Travel")) { - validGui = false; - } - } - return validGui; - } - - private static final ResourceLocation EDITOR = new ResourceLocation("notenoughupdates:invbuttons/editor.png"); - private NEUConfig.InventoryButton buttonHovered = null; - private long buttonHoveredMillis = 0; - public static boolean disableCraftingText = false; - - /** - * Will draw the NEUOverlay over the inventory if focusInv == false. (z-translation of 300 is so that NEUOverlay - * will draw over Items in the inventory (which render at a z value of about 250)) - * @param event - */ - @SubscribeEvent - public void onGuiScreenDrawPost(GuiScreenEvent.DrawScreenEvent.Post event) { - drawingGuiScreen = false; - disableCraftingText = false; - - String containerName = null; - GuiScreen guiScreen = Minecraft.getMinecraft().currentScreen; - if(guiScreen instanceof GuiChest) { - GuiChest eventGui = (GuiChest) guiScreen; - ContainerChest cc = (ContainerChest) eventGui.inventorySlots; - containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText(); - if (containerName.equals("Craft Item")) { - CraftingOverlay.render(); - } - } - - if(GuiCustomEnchant.getInstance().shouldOverride(containerName)) { - return; - } - - boolean tradeWindowActive = TradeWindow.tradeWindowActive(containerName); - boolean storageOverlayActive = StorageManager.getInstance().shouldRenderStorageOverlay(containerName); - boolean customAhActive = event.gui instanceof CustomAHGui || neu.manager.auctionManager.customAH.isRenderOverAuctionView(); - - if(!(tradeWindowActive || storageOverlayActive || customAhActive)) { - if(shouldRenderOverlay(event.gui) && neu.isOnSkyblock()) { - GlStateManager.pushMatrix(); - if(!focusInv) { - GL11.glTranslatef(0, 0, 300); - neu.overlay.render(hoverInv && focusInv); - GL11.glTranslatef(0, 0, -300); - } - GlStateManager.popMatrix(); - } - } - - if(shouldRenderOverlay(event.gui) && neu.isOnSkyblock() && !hoverInv) { - renderDungeonChestOverlay(event.gui); - if(NotEnoughUpdates.INSTANCE.config.accessoryBag.enableOverlay) { - AccessoryBagOverlay.renderOverlay(); - } - } - - boolean hoveringButton = false; - if(!doInventoryButtons) return; - if(NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() && shouldRenderOverlay(event.gui) && - event.gui instanceof GuiContainer) { - int xSize = ((GuiContainer) event.gui).xSize; - int ySize = ((GuiContainer) event.gui).ySize; - int guiLeft = ((GuiContainer) event.gui).guiLeft; - int guiTop = ((GuiContainer) event.gui).guiTop; - - if (!NEUApi.disableInventoryButtons) { - for (NEUConfig.InventoryButton button : NotEnoughUpdates.INSTANCE.config.hidden.inventoryButtons) { - if (!button.isActive()) continue; - if (button.playerInvOnly && !(event.gui instanceof GuiInventory)) continue; - - int x = guiLeft + button.x; - int y = guiTop + button.y; - if (button.anchorRight) { - x += xSize; - } - if (button.anchorBottom) { - y += ySize; - } - if (AccessoryBagOverlay.isInAccessoryBag()) { - if (x > guiLeft + xSize && x < guiLeft + xSize + 80 + 28 + 5 && y > guiTop - 18 && y < guiTop + 150) { - x += 80 + 28; - } - } - - if (x - guiLeft >= 85 && x - guiLeft <= 115 && y - guiTop >= 4 && y - guiTop <= 25) { - disableCraftingText = true; - } - - if (event.mouseX >= x && event.mouseX <= x + 18 && - event.mouseY >= y && event.mouseY <= y + 18) { - hoveringButton = true; - long currentTime = System.currentTimeMillis(); - - if (buttonHovered != button) { - buttonHoveredMillis = currentTime; - buttonHovered = button; - } - - if (currentTime - buttonHoveredMillis > 600) { - String command = button.command.trim(); - if (!command.startsWith("/")) { - command = "/" + command; - } - - Utils.drawHoveringText(Lists.newArrayList("\u00a77" + command), event.mouseX, event.mouseY, - event.gui.width, event.gui.height, -1, Minecraft.getMinecraft().fontRendererObj); - } - } - } - } - } - if(!hoveringButton) buttonHovered = null; - - if(AuctionBINWarning.getInstance().shouldShow()) { - AuctionBINWarning.getInstance().render(); - } - } - - private void renderDungeonChestOverlay(GuiScreen gui) { - if(NotEnoughUpdates.INSTANCE.config.dungeons.profitDisplayLoc == 3) return; - - if(gui instanceof GuiChest && NotEnoughUpdates.INSTANCE.config.dungeons.profitDisplayLoc != 2) { - try { - int xSize = ((GuiContainer)gui).xSize; - int ySize = ((GuiContainer)gui).ySize; - int guiLeft = ((GuiContainer)gui).guiLeft; - int guiTop = ((GuiContainer)gui).guiTop; - - GuiChest eventGui = (GuiChest) gui; - ContainerChest cc = (ContainerChest) eventGui.inventorySlots; - IInventory lower = cc.getLowerChestInventory(); - - ItemStack rewardChest = lower.getStackInSlot(31); - if (rewardChest != null && rewardChest.getDisplayName().endsWith(EnumChatFormatting.GREEN+"Open Reward Chest")) { - int chestCost = 0; - try { - String line6 = Utils.cleanColour(neu.manager.getLoreFromNBT(rewardChest.getTagCompound())[6]); - StringBuilder cost = new StringBuilder(); - for(int i=0; i= 0) { - cost.append(c); - } - } - if(cost.length() > 0) { - chestCost = Integer.parseInt(cost.toString()); - } - } catch(Exception ignored) {} - - String missingItem = null; - int totalValue = 0; - HashMap itemValues = new HashMap<>(); - for(int i=0; i<5; i++) { - ItemStack item = lower.getStackInSlot(11+i); - String internal = neu.manager.getInternalNameForItem(item); - if(internal != null) { - internal = internal.replace("\u00CD", "I").replace("\u0130", "I"); - float bazaarPrice = -1; - JsonObject bazaarInfo = neu.manager.auctionManager.getBazaarInfo(internal); - if(bazaarInfo != null && bazaarInfo.has("curr_sell")) { - bazaarPrice = bazaarInfo.get("curr_sell").getAsFloat(); - } - if(bazaarPrice < 5000000 && internal.equals("RECOMBOBULATOR_3000")) bazaarPrice = 5000000; - - float worth = -1; - if(bazaarPrice > 0) { - worth = bazaarPrice; - } else { - switch(NotEnoughUpdates.INSTANCE.config.dungeons.profitType) { - case 1: - worth = neu.manager.auctionManager.getItemAvgBin(internal); - break; - case 2: - JsonObject auctionInfo = neu.manager.auctionManager.getItemAuctionInfo(internal); - if(auctionInfo != null) { - if(auctionInfo.has("clean_price")) { - worth = (int)auctionInfo.get("clean_price").getAsFloat(); - } else { - worth = (int)(auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat()); - } - } - break; - default: - worth = neu.manager.auctionManager.getLowestBin(internal); - } - if(worth <= 0) { - worth = neu.manager.auctionManager.getLowestBin(internal); - if(worth <= 0) { - worth = neu.manager.auctionManager.getItemAvgBin(internal); - if(worth <= 0) { - JsonObject auctionInfo = neu.manager.auctionManager.getItemAuctionInfo(internal); - if(auctionInfo != null) { - if(auctionInfo.has("clean_price")) { - worth = (int)auctionInfo.get("clean_price").getAsFloat(); - } else { - worth = (int)(auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat()); - } - } - } - } - } - } - - if(worth > 0 && totalValue >= 0) { - totalValue += worth; - String display = item.getDisplayName(); - - if(display.contains("Enchanted Book")) { - NBTTagCompound tag = item.getTagCompound(); - if(tag != null && tag.hasKey("ExtraAttributes", 10)) { - NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes"); - NBTTagCompound enchants = ea.getCompoundTag("enchantments"); - - int highestLevel = -1; - for(String enchname : enchants.getKeySet()) { - int level = enchants.getInteger(enchname); - if(level > highestLevel) { - display = EnumChatFormatting.BLUE+WordUtils.capitalizeFully( - enchname.replace("_", " ") - .replace("Ultimate", "") - .trim()) + " " + level; - } - } - } - } - - itemValues.put(display, worth); - } else { - if(totalValue != -1) { - missingItem = internal; - } - totalValue = -1; - } - } - } - - NumberFormat format = NumberFormat.getInstance(Locale.US); - String valueStringBIN1; - String valueStringBIN2; - if(totalValue >= 0) { - valueStringBIN1 = EnumChatFormatting.YELLOW+"Value (BIN): "; - valueStringBIN2 = EnumChatFormatting.GOLD + format.format(totalValue) + " coins"; - } else { - valueStringBIN1 = EnumChatFormatting.YELLOW+"Can't find BIN: "; - valueStringBIN2 = missingItem; - } - - int profitLossBIN = totalValue - chestCost; - - String profitPrefix = EnumChatFormatting.DARK_GREEN.toString(); - String lossPrefix = EnumChatFormatting.RED.toString(); - String prefix = profitLossBIN >= 0 ? profitPrefix : lossPrefix; - - String plStringBIN; - if(profitLossBIN >= 0) { - plStringBIN = prefix + "+" + format.format(profitLossBIN) + " coins"; - } else { - plStringBIN = prefix + "-" + format.format(-profitLossBIN) + " coins"; - } - - if(NotEnoughUpdates.INSTANCE.config.dungeons.profitDisplayLoc == 1 && !valueStringBIN2.equals(missingItem)) { - int w = Minecraft.getMinecraft().fontRendererObj.getStringWidth(plStringBIN); - GlStateManager.disableLighting(); - GlStateManager.translate(0, 0, 200); - Minecraft.getMinecraft().fontRendererObj.drawString(plStringBIN, guiLeft+xSize-5-w, guiTop+5, - 0xffffffff, true); - GlStateManager.translate(0, 0, -200); - return; - } - - Minecraft.getMinecraft().getTextureManager().bindTexture(dungeon_chest_worth); - GL11.glColor4f(1, 1, 1, 1); - GlStateManager.disableLighting(); - Utils.drawTexturedRect(guiLeft+xSize+4, guiTop, 180, 101, 0, 180/256f, 0, 101/256f, GL11.GL_NEAREST); - - Utils.renderAlignedString(valueStringBIN1, valueStringBIN2, - guiLeft+xSize+4+10, guiTop+14, 160); - if(totalValue >= 0) { - Utils.renderAlignedString(EnumChatFormatting.YELLOW+"Profit/Loss: ", plStringBIN, - guiLeft+xSize+4+10, guiTop+24, 160); - } - - int index=0; - for(Map.Entry entry : itemValues.entrySet()) { - Utils.renderAlignedString(entry.getKey(), prefix+ - format.format(entry.getValue().intValue()), - guiLeft+xSize+4+10, guiTop+29+(++index)*10, 160); - } - } - } catch(Exception e) { - e.printStackTrace(); - } - } - } - - public void drawStringShadow(String str, float x, float y, int len) { - for(int xOff=-2; xOff<=2; xOff++) { - for(int yOff=-2; yOff<=2; yOff++) { - if(Math.abs(xOff) != Math.abs(yOff)) { - Utils.drawStringCenteredScaledMaxWidth(Utils.cleanColourNotModifiers(str), - Minecraft.getMinecraft().fontRendererObj, - x+xOff/2f, y+yOff/2f, false, len, - new Color(20, 20, 20, 100/Math.max(Math.abs(xOff), Math.abs(yOff))).getRGB()); - } - } - } - - Utils.drawStringCenteredScaledMaxWidth(str, - Minecraft.getMinecraft().fontRendererObj, - x, y, false, len, - new Color(64, 64, 64, 255).getRGB()); - } - - /** - * Sends a mouse event to NEUOverlay if the inventory isn't hovered AND focused. - * Will also cancel the event if if NEUOverlay#mouseInput returns true. - * @param event - */ - @SubscribeEvent(priority = EventPriority.LOW) - public void onGuiScreenMouse(GuiScreenEvent.MouseInputEvent.Pre event) { - if(Mouse.getEventButtonState() && StorageManager.getInstance().onAnyClick()) { - event.setCanceled(true); - return; - } - - final ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft()); - final int scaledWidth = scaledresolution.getScaledWidth(); - final int scaledHeight = scaledresolution.getScaledHeight(); - int mouseX = Mouse.getX() * scaledWidth / Minecraft.getMinecraft().displayWidth; - int mouseY = scaledHeight - Mouse.getY() * scaledHeight / Minecraft.getMinecraft().displayHeight - 1; - - if(AuctionBINWarning.getInstance().shouldShow()) { - AuctionBINWarning.getInstance().mouseInput(mouseX, mouseY); - event.setCanceled(true); - return; - } - - if(!event.isCanceled()) { - Utils.scrollTooltip(Mouse.getEventDWheel()); - } - if(AuctionSearchOverlay.shouldReplace()) { - AuctionSearchOverlay.mouseEvent(); - event.setCanceled(true); - return; - } - if(RancherBootOverlay.shouldReplace()) { - RancherBootOverlay.mouseEvent(); - event.setCanceled(true); - return; - } - - String containerName = null; - GuiScreen guiScreen = Minecraft.getMinecraft().currentScreen; - if(guiScreen instanceof GuiChest) { - GuiChest eventGui = (GuiChest) guiScreen; - ContainerChest cc = (ContainerChest) eventGui.inventorySlots; - containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText(); - if(containerName.contains(" Profile") && BetterContainers.profileViewerStackIndex != -1 && - eventGui.isMouseOverSlot(cc.inventorySlots.get(BetterContainers.profileViewerStackIndex), mouseX, mouseY) && Mouse.getEventButton() >= 0) { - event.setCanceled(true); - if(Mouse.getEventButtonState() && eventGui.inventorySlots.inventorySlots.get(22).getStack() != null && - eventGui.inventorySlots.inventorySlots.get(22).getStack().getTagCompound() != null){ - NBTTagCompound tag = eventGui.inventorySlots.inventorySlots.get(22).getStack().getTagCompound(); - if(tag.hasKey("SkullOwner") && tag.getCompoundTag("SkullOwner").hasKey("Name")){ - String username = tag.getCompoundTag("SkullOwner").getString("Name"); - Utils.playPressSound(); - NotEnoughUpdates.INSTANCE.commands.viewProfileRunnable.processCommand(null, new String[]{username}); - } - } - } - } - - if(GuiCustomEnchant.getInstance().shouldOverride(containerName) && - GuiCustomEnchant.getInstance().mouseInput(mouseX, mouseY)) { - event.setCanceled(true); - return; - } - - boolean tradeWindowActive = TradeWindow.tradeWindowActive(containerName); - boolean storageOverlayActive = StorageManager.getInstance().shouldRenderStorageOverlay(containerName); - boolean customAhActive = event.gui instanceof CustomAHGui || neu.manager.auctionManager.customAH.isRenderOverAuctionView(); - - if(storageOverlayActive) { - if(StorageOverlay.getInstance().mouseInput(mouseX, mouseY)) { - event.setCanceled(true); - } - return; - } - - if(tradeWindowActive || customAhActive) { - event.setCanceled(true); - if(customAhActive) { - neu.manager.auctionManager.customAH.handleMouseInput(); - } else if(tradeWindowActive) { - TradeWindow.handleMouseInput(); - } - neu.overlay.mouseInput(); - return; - } - - if(shouldRenderOverlay(event.gui) && neu.isOnSkyblock()) { - if(!NotEnoughUpdates.INSTANCE.config.accessoryBag.enableOverlay || !AccessoryBagOverlay.mouseClick()) { - if(!(hoverInv && focusInv)) { - if(neu.overlay.mouseInput()) { - event.setCanceled(true); - } - } else { - neu.overlay.mouseInputInv(); - } - } - } - if(event.isCanceled()) return; - if(!doInventoryButtons) return; - if(NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() && shouldRenderOverlay(event.gui) && Mouse.getEventButton() >= 0 - && event.gui instanceof GuiContainer) { - int xSize = ((GuiContainer)event.gui).xSize; - int ySize = ((GuiContainer)event.gui).ySize; - int guiLeft = ((GuiContainer)event.gui).guiLeft; - int guiTop = ((GuiContainer)event.gui).guiTop; - if(!NEUApi.disableInventoryButtons) { - for (NEUConfig.InventoryButton button : NotEnoughUpdates.INSTANCE.config.hidden.inventoryButtons) { - if (!button.isActive()) continue; - if (button.playerInvOnly && !(event.gui instanceof GuiInventory)) continue; - - int x = guiLeft + button.x; - int y = guiTop + button.y; - if (button.anchorRight) { - x += xSize; - } - if (button.anchorBottom) { - y += ySize; - } - if (AccessoryBagOverlay.isInAccessoryBag()) { - if (x > guiLeft + xSize && x < guiLeft + xSize + 80 + 28 + 5 && y > guiTop - 18 && y < guiTop + 150) { - x += 80 + 28; - } - } - - if (mouseX >= x && mouseX <= x + 18 && mouseY >= y && mouseY <= y + 18) { - if (Minecraft.getMinecraft().thePlayer.inventory.getItemStack() == null) { - int clickType = NotEnoughUpdates.INSTANCE.config.inventoryButtons.clickType; - if ((clickType == 0 && Mouse.getEventButtonState()) || (clickType == 1 && !Mouse.getEventButtonState())) { - String command = button.command.trim(); - if (!command.startsWith("/")) { - command = "/" + command; - } - if (ClientCommandHandler.instance.executeCommand(Minecraft.getMinecraft().thePlayer, command) == 0) { - NotEnoughUpdates.INSTANCE.sendChatMessage(command); - } - } - } else { - event.setCanceled(true); - } - return; - } - } - } - } - } - - ScheduledExecutorService ses = Executors.newScheduledThreadPool(1); - - JsonObject essenceJson = new JsonObject(); - - /** - * Sends a kbd event to NEUOverlay, cancelling if NEUOverlay#keyboardInput returns true. - * Also includes a dev function used for creating custom named json files with recipes. - */ - @SubscribeEvent - public void onGuiScreenKeyboard(GuiScreenEvent.KeyboardInputEvent.Pre event) { - if(AuctionBINWarning.getInstance().shouldShow()) { - AuctionBINWarning.getInstance().keyboardInput(); - event.setCanceled(true); - return; - } - - if(AuctionSearchOverlay.shouldReplace()) { - AuctionSearchOverlay.keyEvent(); - event.setCanceled(true); - return; - } - if(RancherBootOverlay.shouldReplace()) { - RancherBootOverlay.keyEvent(); - event.setCanceled(true); - return; - } - - String containerName = null; - GuiScreen guiScreen = Minecraft.getMinecraft().currentScreen; - if(guiScreen instanceof GuiChest) { - GuiChest eventGui = (GuiChest) guiScreen; - ContainerChest cc = (ContainerChest) eventGui.inventorySlots; - containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText(); - if(CraftingOverlay.shouldRender && containerName.equals("Craft Item")){ - CraftingOverlay.keyInput(); - } - } - - if(GuiCustomEnchant.getInstance().shouldOverride(containerName) && - GuiCustomEnchant.getInstance().keyboardInput()) { - event.setCanceled(true); - return; - } - - boolean tradeWindowActive = TradeWindow.tradeWindowActive(containerName); - boolean storageOverlayActive = StorageManager.getInstance().shouldRenderStorageOverlay(containerName); - boolean customAhActive = event.gui instanceof CustomAHGui || neu.manager.auctionManager.customAH.isRenderOverAuctionView(); - - if(storageOverlayActive) { - if(StorageOverlay.getInstance().keyboardInput()) { - event.setCanceled(true); - return; - } - } - - if(tradeWindowActive || customAhActive) { - if(customAhActive) { - if(neu.manager.auctionManager.customAH.keyboardInput()) { - event.setCanceled(true); - Minecraft.getMinecraft().dispatchKeypresses(); - } else if(neu.overlay.keyboardInput(focusInv)) { - event.setCanceled(true); - } - } else if(tradeWindowActive) { - TradeWindow.keyboardInput(); - if(Keyboard.getEventKey() != Keyboard.KEY_ESCAPE) { - event.setCanceled(true); - Minecraft.getMinecraft().dispatchKeypresses(); - neu.overlay.keyboardInput(focusInv); - } - } - return; - } - - if(shouldRenderOverlay(event.gui) && neu.isOnSkyblock()) { - if(neu.overlay.keyboardInput(focusInv)) { - event.setCanceled(true); - } - } - if(NotEnoughUpdates.INSTANCE.config.hidden.dev && NotEnoughUpdates.INSTANCE.config.hidden.enableItemEditing && Minecraft.getMinecraft().theWorld != null && - Keyboard.getEventKey() == Keyboard.KEY_N && Keyboard.getEventKeyState()) { - GuiScreen gui = Minecraft.getMinecraft().currentScreen; - if(gui instanceof GuiChest) { - GuiChest eventGui = (GuiChest) event.gui; - ContainerChest cc = (ContainerChest) eventGui.inventorySlots; - IInventory lower = cc.getLowerChestInventory(); - - if(!lower.getDisplayName().getUnformattedText().endsWith("Essence")) return; - - for(int i=0; i= '0' && c <= '9') { - costS.append(c); - } - } - int cost = Integer.parseInt(costS.toString()); - String[] afterSplit = after.split(" "); - String type = afterSplit[afterSplit.length-2]; - - if(!essenceJson.has(internalname)) { - essenceJson.add(internalname, new JsonObject()); - } - JsonObject obj = essenceJson.get(internalname).getAsJsonObject(); - obj.addProperty("type", type); - - if(line.startsWith("\u00A77Convert to Dungeon Item")) { - obj.addProperty("dungeonize", cost); - } else if(line.startsWith("\u00A77Upgrade to")) { - int stars = 0; - for(char c : line.toCharArray()) { - if(c == '\u272A') stars++; - } - if(stars > 0) { - obj.addProperty(stars+"", cost); - } - } - } - } - } - } - System.out.println(essenceJson); - } - } - if(NotEnoughUpdates.INSTANCE.config.hidden.dev && NotEnoughUpdates.INSTANCE.config.hidden.enableItemEditing && Minecraft.getMinecraft().theWorld != null && - Keyboard.getEventKey() == Keyboard.KEY_O && Keyboard.getEventKeyState()) { - GuiScreen gui = Minecraft.getMinecraft().currentScreen; - if(gui instanceof GuiChest) { - GuiChest eventGui = (GuiChest) event.gui; - ContainerChest cc = (ContainerChest) eventGui.inventorySlots; - IInventory lower = cc.getLowerChestInventory(); - - if(lower.getStackInSlot(23) != null && - lower.getStackInSlot(23).getDisplayName().endsWith("Crafting Table")) { - ItemStack res = lower.getStackInSlot(25); - String resInternalname = neu.manager.getInternalNameForItem(res); - JTextField tf = new JTextField(); - tf.setText(resInternalname); - tf.addAncestorListener(new RequestFocusListener()); - JOptionPane.showOptionDialog(null, - tf, - "Enter Name:", - JOptionPane.NO_OPTION, - JOptionPane.PLAIN_MESSAGE, - null, new String[]{"Enter"}, "Enter"); - resInternalname = tf.getText(); - if(resInternalname.trim().length() == 0) { - return; - } - - JsonObject recipe = new JsonObject(); - - String[] x = {"1","2","3"}; - String[] y = {"A","B","C"}; - - for(int i=0; i<=18; i+=9) { - for(int j=0; j<3; j++) { - ItemStack stack = lower.getStackInSlot(10+i+j); - String internalname = ""; - if(stack != null) { - internalname = neu.manager.getInternalNameForItem(stack); - if(!neu.manager.getItemInformation().containsKey(internalname)) { - neu.manager.writeItemToFile(stack); - } - internalname += ":"+stack.stackSize; - } - recipe.addProperty(y[i/9]+x[j], internalname); - } - } - - JsonObject json = neu.manager.getJsonForItem(res); - json.add("recipe", recipe); - json.addProperty("internalname", resInternalname); - json.addProperty("clickcommand", "viewrecipe"); - json.addProperty("modver", NotEnoughUpdates.VERSION); - try { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("Added: " + resInternalname)); - neu.manager.writeJsonDefaultDir(json, resInternalname+".json"); - neu.manager.loadItem(resInternalname); - } catch(IOException e) {} - } - } - } - } - - - - private HashSet percentStats = new HashSet<>(); - { - percentStats.add("bonus_attack_speed"); - percentStats.add("crit_damage"); - percentStats.add("crit_chance"); - percentStats.add("sea_creature_chance"); - percentStats.add("ability_damage"); - } - - private String currentRarity = "COMMON"; - private boolean showReforgeStoneStats = true; - private boolean pressedArrowLast = false; - private boolean pressedShiftLast = false; - - private boolean copied = false; - - //just to try and optimize it a bit - private int sbaloaded = -1; - private boolean isSbaloaded(){ - if(sbaloaded == -1){ - if(Loader.isModLoaded("skyblockaddons")) { - sbaloaded = 1; - } else { - sbaloaded = 0; - } - } - return sbaloaded == 1; - } - - @SubscribeEvent(priority = EventPriority.LOW) - public void onItemTooltipLow(ItemTooltipEvent event) { - if(!NotEnoughUpdates.INSTANCE.isOnSkyblock()) return; - - String internalname = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(event.itemStack); - if(internalname == null) { - onItemToolTipInternalNameNull(event); - return; - } - - boolean hasEnchantments = event.itemStack.getTagCompound().getCompoundTag("ExtraAttributes").hasKey("enchantments", 10); - Set enchantIds = new HashSet<>(); - if(hasEnchantments) enchantIds = event.itemStack.getTagCompound().getCompoundTag("ExtraAttributes").getCompoundTag("enchantments").getKeySet(); - - JsonObject enchantsConst = Constants.ENCHANTS; - JsonArray allItemEnchs = null; - Set ignoreFromPool = new HashSet<>(); - if(enchantsConst != null && hasEnchantments && NotEnoughUpdates.INSTANCE.config.tooltipTweaks.missingEnchantList) { - try { - JsonArray enchantPools = enchantsConst.get("enchant_pools").getAsJsonArray(); - for(JsonElement element : enchantPools) { - Set currentPool = new HashSet<>(); - for(JsonElement poolElement : element.getAsJsonArray()) { - String poolS = poolElement.getAsString(); - currentPool.add(poolS); - } - for(JsonElement poolElement : element.getAsJsonArray()) { - String poolS = poolElement.getAsString(); - if(enchantIds.contains(poolS)) { - ignoreFromPool.addAll(currentPool); - break; - } - } - } - - JsonObject enchantsObj = enchantsConst.get("enchants").getAsJsonObject(); - NBTTagCompound tag = event.itemStack.getTagCompound(); - if(tag != null) { - NBTTagCompound display = tag.getCompoundTag("display"); - if (display.hasKey("Lore", 9)) { - NBTTagList list = display.getTagList("Lore", 8); - out: - for (int i = list.tagCount(); i >= 0; i--) { - String line = list.getStringTagAt(i); - for(int j=0; j entry : enchantsObj.entrySet()) { - if(line.contains(Utils.rarityArrC[j] + " " + entry.getKey()) || line.contains(Utils.rarityArrC[j] + " DUNGEON " + entry.getKey())) { - allItemEnchs = entry.getValue().getAsJsonArray(); - break out; - } - } - } - } - } - } - } catch(Exception e) {} - } - - boolean gotToEnchants = false; - boolean passedEnchants = false; - - boolean dungeonProfit = false; - int index = 0; - List newTooltip = new ArrayList<>(); - - for(String line : event.toolTip) { - if(line.endsWith(EnumChatFormatting.DARK_GRAY+"Reforge Stone") && NotEnoughUpdates.INSTANCE.config.tooltipTweaks.showReforgeStats) { - JsonObject reforgeStones = Constants.REFORGESTONES; - - - if(reforgeStones != null && reforgeStones.has(internalname)) { - boolean shift = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT); - if(!pressedShiftLast && shift) { - showReforgeStoneStats = !showReforgeStoneStats; - } - pressedShiftLast = shift; - - newTooltip.add(line); - newTooltip.add(""); - if(!showReforgeStoneStats) { - newTooltip.add(EnumChatFormatting.DARK_GRAY+"[Press SHIFT to show extra info]"); - } else { - newTooltip.add(EnumChatFormatting.DARK_GRAY+"[Press SHIFT to hide extra info]"); - } - - JsonObject reforgeInfo = reforgeStones.get(internalname).getAsJsonObject(); - JsonArray requiredRaritiesArray = reforgeInfo.get("requiredRarities").getAsJsonArray(); - - if(showReforgeStoneStats && requiredRaritiesArray.size() > 0) { - String reforgeName = Utils.getElementAsString(reforgeInfo.get("reforgeName"), ""); - - String[] requiredRarities = new String[requiredRaritiesArray.size()]; - for(int i=0; i= requiredRarities.length) rarityIndex = requiredRarities.length-1; - currentRarity = requiredRarities[rarityIndex]; - rarity = currentRarity; - } - pressedArrowLast = left || right; - - JsonElement statsE = reforgeInfo.get("reforgeStats"); - - - String rarityFormatted = Utils.rarityArrMap.getOrDefault(rarity, rarity); - - JsonElement reforgeAbilityE = reforgeInfo.get("reforgeAbility"); - String reforgeAbility = null; - if (reforgeAbilityE != null) { - if (reforgeAbilityE.isJsonPrimitive() && reforgeAbilityE.getAsJsonPrimitive().isString()) { - reforgeAbility = Utils.getElementAsString(reforgeInfo.get("reforgeAbility"), ""); - - } else if (reforgeAbilityE.isJsonObject()) { - if (reforgeAbilityE.getAsJsonObject().has(rarity)) { - reforgeAbility = reforgeAbilityE.getAsJsonObject().get(rarity).getAsString(); - } - } - } - - if (reforgeAbility != null && !reforgeAbility.isEmpty()) { - String text = EnumChatFormatting.BLUE + (reforgeName.isEmpty() ? "Bonus: " : reforgeName + " Bonus: ") + - EnumChatFormatting.GRAY + reforgeAbility; - boolean first = true; - for (String s : Minecraft.getMinecraft().fontRendererObj.listFormattedStringToWidth(text, 150)) { - newTooltip.add((first ? "" : " ") + s); - first = false; - } - newTooltip.add(""); - } - - newTooltip.add(EnumChatFormatting.BLUE + "Stats for " + rarityFormatted + "\u00a79: [\u00a7l\u00a7m< \u00a79Switch\u00a7l\u27a1\u00a79]"); - - if(statsE != null && statsE.isJsonObject()) { - JsonObject stats = statsE.getAsJsonObject(); - - JsonElement statsRarE = stats.get(rarity); - if (statsRarE != null && statsRarE.isJsonObject()) { - - JsonObject statsRar = statsRarE.getAsJsonObject(); - - TreeSet> sorted = new TreeSet<>(Map.Entry.comparingByKey()); - sorted.addAll(statsRar.entrySet()); - - for (Map.Entry entry : sorted) { - if (entry.getValue().isJsonPrimitive() && ((JsonPrimitive) entry.getValue()).isNumber()) { - float statNumF = entry.getValue().getAsFloat(); - String statNumS; - if (statNumF % 1 == 0) { - statNumS = String.valueOf(Math.round(statNumF)); - } else { - statNumS = Utils.floatToString(statNumF, 1); - } - String reforgeNamePretty = WordUtils.capitalizeFully(entry.getKey().replace("_", " ")); - String text = EnumChatFormatting.GRAY + reforgeNamePretty + ": " + EnumChatFormatting.GREEN + "+" + statNumS; - if (percentStats.contains(entry.getKey())) { - text += "%"; - } - newTooltip.add(" " + text); - } - } - } - } - - JsonElement reforgeCostsE = reforgeInfo.get("reforgeCosts"); - int reforgeCost = -1; - if (reforgeCostsE != null) { - if (reforgeCostsE.isJsonPrimitive() && reforgeCostsE.getAsJsonPrimitive().isNumber()) { - reforgeCost = (int) Utils.getElementAsFloat(reforgeInfo.get("reforgeAbility"), -1); - - } else if (reforgeCostsE.isJsonObject()) { - if (reforgeCostsE.getAsJsonObject().has(rarity)) { - reforgeCost = (int) Utils.getElementAsFloat(reforgeCostsE.getAsJsonObject().get(rarity), -1); - } - } - } - - if (reforgeCost >= 0) { - String text = EnumChatFormatting.BLUE + "Apply Cost: " + EnumChatFormatting.GOLD + NumberFormat.getNumberInstance().format(reforgeCost) + " coins"; - newTooltip.add(""); - newTooltip.add(text); - } - - } - - - continue; - } - - } else if(line.contains("\u00A7cR\u00A76a\u00A7ei\u00A7an\u00A7bb\u00A79o\u00A7dw\u00A79 Rune")) { - line = line.replace("\u00A7cR\u00A76a\u00A7ei\u00A7an\u00A7bb\u00A79o\u00A7dw\u00A79 Rune", - Utils.chromaString("Rainbow Rune", index, false)+EnumChatFormatting.BLUE); - } else if(hasEnchantments) { - if(Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) && NotEnoughUpdates.INSTANCE.config.tooltipTweaks.missingEnchantList) { - boolean lineHasEnch = false; - for(String s : enchantIds) { - String enchantName = WordUtils.capitalizeFully(s.replace("_", " ")); - if(line.contains(enchantName)) { - lineHasEnch = true; - break; - } - } - if(lineHasEnch) { - gotToEnchants = true; - } else { - if(gotToEnchants && !passedEnchants && Utils.cleanColour(line).trim().length() == 0) { - if(enchantsConst != null && allItemEnchs != null) { - List missing = new ArrayList<>(); - for(JsonElement enchIdElement : allItemEnchs) { - String enchId = enchIdElement.getAsString(); - if(!enchId.startsWith("ultimate_") && !ignoreFromPool.contains(enchId) && !enchantIds.contains(enchId)) { - missing.add(enchId); - } - } - newTooltip.add(""); - StringBuilder currentLine = new StringBuilder(EnumChatFormatting.RED+"Missing: "+EnumChatFormatting.GRAY); - for(int i=0; i 40) { - newTooltip.add(currentLine.toString()); - currentLine = new StringBuilder(); - } - if(currentLine.length() != 0 && i != 0) { - currentLine.append(", ").append(enchName); - } else { - currentLine.append(EnumChatFormatting.GRAY).append(enchName); - } - } - if(currentLine.length() != 0) { - newTooltip.add(currentLine.toString()); - } - } - passedEnchants = true; - } - } - } - for(String op : NotEnoughUpdates.INSTANCE.config.hidden.enchantColours) { - List colourOps = GuiEnchantColour.splitter.splitToList(op); - String enchantName = GuiEnchantColour.getColourOpIndex(colourOps, 0); - String comparator = GuiEnchantColour.getColourOpIndex(colourOps, 1); - String comparison = GuiEnchantColour.getColourOpIndex(colourOps, 2); - String colourCode = GuiEnchantColour.getColourOpIndex(colourOps, 3); - String modifier = GuiEnchantColour.getColourOpIndex(colourOps, 4); - - int modifierI = GuiEnchantColour.getIntModifier(modifier); - - if(enchantName.length() == 0) continue; - if(comparator.length() == 0) continue; - if(comparison.length() == 0) continue; - if(colourCode.length() == 0) continue; - - int comparatorI = ">=<".indexOf(comparator.charAt(0)); - - int levelToFind = -1; - try { - levelToFind = Integer.parseInt(comparison); - } catch(Exception e) { continue; } - - if(comparatorI < 0) continue; - String regexText = "0123456789abcdefz"; - if(isSbaloaded()) { - regexText = regexText + "Z"; - } - - if (regexText.indexOf(colourCode.charAt(0)) < 0) continue; - - //item_lore = item_lore.replaceAll("\\u00A79("+lvl4Max+" IV)", EnumChatFormatting.DARK_PURPLE+"$1"); - //9([a-zA-Z ]+?) ([0-9]+|(I|II|III|IV|V|VI|VII|VIII|IX|X))(,|$) - Pattern pattern; - try { - pattern = Pattern.compile("(\\u00A79|\\u00A7(9|l)\\u00A7d\\u00A7l)(?"+enchantName+") " + - "(?[0-9]+|(I|II|III|IV|V|VI|VII|VIII|IX|X|XI|XII|XIII|XIV|XV|XVI|XVII|XVIII|XIX|XX))((\\u00A79)?,|( \\u00A78(?:,?[0-9]+)*)?$)"); - } catch(Exception e) {continue;} //malformed regex - Matcher matcher = pattern.matcher(line); - int matchCount = 0; - while(matcher.find() && matchCount < 5) { - if(Utils.cleanColour(matcher.group("enchantName")).startsWith(" ")) continue; - - - matchCount++; - int level = -1; - String levelStr = matcher.group("level"); - if(levelStr == null) continue; - try { - level = Integer.parseInt(levelStr); - } catch(Exception e) { - switch(levelStr) { - case "I": - level = 1; break; - case "II": - level = 2; break; - case "III": - level = 3; break; - case "IV": - level = 4; break; - case "V": - level = 5; break; - case "VI": - level = 6; break; - case "VII": - level = 7; break; - case "VIII": - level = 8; break; - case "IX": - level = 9; break; - case "X": - level = 10; break; - case "XI": - level = 11; break; - case "XII": - level = 12; break; - case "XIII": - level = 13; break; - case "XIV": - level = 14; break; - case "XV": - level = 15; break; - case "XVI": - level = 16; break; - case "XVII": - level = 17; break; - case "XVIII": - level = 18; break; - case "XIX": - level = 19; break; - case "XX": - level = 20; break; - } - } - boolean matches = false; - if(level > 0) { - switch(comparator) { - case ">": - matches = level > levelToFind; break; - case "=": - matches = level == levelToFind; break; - case "<": - matches = level < levelToFind; break; - } - } - if(matches) { - String enchantText = matcher.group("enchantName"); - StringBuilder extraModifiersBuilder = new StringBuilder(); - - if((modifierI & GuiEnchantColour.BOLD_MODIFIER) != 0) { - extraModifiersBuilder.append(EnumChatFormatting.BOLD); - } - if((modifierI & GuiEnchantColour.ITALIC_MODIFIER) != 0) { - extraModifiersBuilder.append(EnumChatFormatting.ITALIC); - } - if((modifierI & GuiEnchantColour.UNDERLINE_MODIFIER) != 0) { - extraModifiersBuilder.append(EnumChatFormatting.UNDERLINE); - } - if((modifierI & GuiEnchantColour.OBFUSCATED_MODIFIER) != 0) { - extraModifiersBuilder.append(EnumChatFormatting.OBFUSCATED); - } - if((modifierI & GuiEnchantColour.STRIKETHROUGH_MODIFIER) != 0) { - extraModifiersBuilder.append(EnumChatFormatting.STRIKETHROUGH); - } - - String extraMods = extraModifiersBuilder.toString(); - - if(!colourCode.equals("z")) { - line = line.replace("\u00A79"+enchantText, - "\u00A7"+colourCode+extraMods+enchantText); - line = line.replace("\u00A79\u00A7d\u00A7l"+enchantText, - "\u00A7"+colourCode+extraMods+enchantText); - line = line.replace("\u00A7l\u00A7d\u00A7l"+enchantText, - "\u00A7"+colourCode+extraMods+enchantText); - } else { - int offset = Minecraft.getMinecraft().fontRendererObj.getStringWidth(line.replaceAll( - "\\u00A79"+enchantText+".*", "")); - line = line.replace("\u00A79"+enchantText, Utils.chromaString(enchantText, offset/12f+index, false)); - - offset = Minecraft.getMinecraft().fontRendererObj.getStringWidth(line.replaceAll( - "\\u00A79\\u00A7d\\u00A7l"+enchantText+".*", "")); - line = line.replace("\u00A79\u00A7d\u00A7l"+enchantText, Utils.chromaString(enchantText, - offset/12f+index, true)); - offset = Minecraft.getMinecraft().fontRendererObj.getStringWidth(line.replaceAll( - "\\u00A7l\\u00A7d\\u00A7l"+enchantText+".*", "")); - line = line.replace("\u00A7l\u00A7d\u00A7l"+enchantText, Utils.chromaString(enchantText, - offset/12f+index, true)); - } - } - } - } - } - - newTooltip.add(line); - - - if(NotEnoughUpdates.INSTANCE.config.tooltipTweaks.showPriceInfoAucItem) { - if(line.contains(EnumChatFormatting.GRAY+"Buy it now: ") || - line.contains(EnumChatFormatting.GRAY+"Bidder: ") || - line.contains(EnumChatFormatting.GRAY+"Starting bid: ")) { - - if(!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) && !Keyboard.isKeyDown(Keyboard.KEY_RSHIFT)) { - newTooltip.add(""); - newTooltip.add(EnumChatFormatting.GRAY+"[SHIFT for Price Info]"); - } else { - ItemPriceInformation.addToTooltip(newTooltip, internalname, event.itemStack); - } - } - } - - if(NotEnoughUpdates.INSTANCE.config.dungeons.profitDisplayLoc == 2 && Minecraft.getMinecraft().currentScreen instanceof GuiChest) { - if(line.contains(EnumChatFormatting.GREEN+"Open Reward Chest")) { - dungeonProfit = true; - } else if(index == 7 && dungeonProfit) { - GuiChest eventGui = (GuiChest) Minecraft.getMinecraft().currentScreen; - ContainerChest cc = (ContainerChest) eventGui.inventorySlots; - IInventory lower = cc.getLowerChestInventory(); - - int chestCost = 0; - try { - String line6 = Utils.cleanColour(line); - StringBuilder cost = new StringBuilder(); - for(int i=0; i= 0) { - cost.append(c); - } - } - if(cost.length() > 0) { - chestCost = Integer.parseInt(cost.toString()); - } - } catch(Exception ignored) {} - - String missingItem = null; - int totalValue = 0; - HashMap itemValues = new HashMap<>(); - for(int i=0; i<5; i++) { - ItemStack item = lower.getStackInSlot(11+i); - String internal = neu.manager.getInternalNameForItem(item); - if(internal != null) { - internal = internal.replace("\u00CD", "I").replace("\u0130", "I"); - float bazaarPrice = -1; - JsonObject bazaarInfo = neu.manager.auctionManager.getBazaarInfo(internal); - if(bazaarInfo != null && bazaarInfo.has("curr_sell")) { - bazaarPrice = bazaarInfo.get("curr_sell").getAsFloat(); - } - if(bazaarPrice < 5000000 && internal.equals("RECOMBOBULATOR_3000")) bazaarPrice = 5000000; - - float worth = -1; - if(bazaarPrice > 0) { - worth = bazaarPrice; - } else { - switch(NotEnoughUpdates.INSTANCE.config.dungeons.profitType) { - case 1: - worth = neu.manager.auctionManager.getItemAvgBin(internal); - break; - case 2: - JsonObject auctionInfo = neu.manager.auctionManager.getItemAuctionInfo(internal); - if(auctionInfo != null) { - if(auctionInfo.has("clean_price")) { - worth = (int)auctionInfo.get("clean_price").getAsFloat(); - } else { - worth = (int)(auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat()); - } - } - break; - default: - worth = neu.manager.auctionManager.getLowestBin(internal); - } - if(worth <= 0) { - worth = neu.manager.auctionManager.getLowestBin(internal); - if(worth <= 0) { - worth = neu.manager.auctionManager.getItemAvgBin(internal); - if(worth <= 0) { - JsonObject auctionInfo = neu.manager.auctionManager.getItemAuctionInfo(internal); - if(auctionInfo != null) { - if(auctionInfo.has("clean_price")) { - worth = (int)auctionInfo.get("clean_price").getAsFloat(); - } else { - worth = (int)(auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat()); - } - } - } - } - } - } - - if(worth > 0 && totalValue >= 0) { - totalValue += worth; - - String display = item.getDisplayName(); - - if(display.contains("Enchanted Book")) { - NBTTagCompound tag = item.getTagCompound(); - if(tag != null && tag.hasKey("ExtraAttributes", 10)) { - NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes"); - NBTTagCompound enchants = ea.getCompoundTag("enchantments"); - - int highestLevel = -1; - for(String enchname : enchants.getKeySet()) { - int level = enchants.getInteger(enchname); - if(level > highestLevel) { - display = EnumChatFormatting.BLUE+WordUtils.capitalizeFully( - enchname.replace("_", " ") - .replace("Ultimate", "") - .trim()) + " " + level; - } - } - } - } - - itemValues.put(display, worth); - } else { - if(totalValue != -1) { - missingItem = internal; - } - totalValue = -1; - } - } - } - - NumberFormat format = NumberFormat.getInstance(Locale.US); - String valueStringBIN1; - String valueStringBIN2; - if(totalValue >= 0) { - valueStringBIN1 = EnumChatFormatting.YELLOW+"Value (BIN): "; - valueStringBIN2 = EnumChatFormatting.GOLD + format.format(totalValue) + " coins"; - } else { - valueStringBIN1 = EnumChatFormatting.YELLOW+"Can't find BIN: "; - valueStringBIN2 = missingItem; - } - - int profitLossBIN = totalValue - chestCost; - String profitPrefix = EnumChatFormatting.DARK_GREEN.toString(); - String lossPrefix = EnumChatFormatting.RED.toString(); - String prefix = profitLossBIN >= 0 ? profitPrefix : lossPrefix; - - String plStringBIN; - if(profitLossBIN >= 0) { - plStringBIN = prefix + "+" + format.format(profitLossBIN) + " coins"; - } else { - plStringBIN = prefix + "-"+ format.format(-profitLossBIN) + " coins"; - } - - String neu = EnumChatFormatting.YELLOW + "[NEU] "; - - newTooltip.add(neu + valueStringBIN1 + " " + valueStringBIN2); - if(totalValue >= 0) { - newTooltip.add(neu + EnumChatFormatting.YELLOW+"Profit/Loss: " + plStringBIN); - } - - for(Map.Entry entry : itemValues.entrySet()) { - newTooltip.add(neu + entry.getKey() + prefix+"+"+ - format.format(entry.getValue().intValue())); - } - } - } - - index++; - } - - for (int i = newTooltip.size()-1; i >=0; i--) { - String line = Utils.cleanColour(newTooltip.get(i)); - for (int i1 = 0; i1 < Utils.rarityArr.length; i1++) { - if(line.equals(Utils.rarityArr[i1])){ - if(i-2 <0){ - break; - } - newTooltip.addAll(i-1, petToolTipXPExtend(event)); - break; - } - } - } - - pressedShiftLast = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT); - pressedArrowLast = Keyboard.isKeyDown(Keyboard.KEY_LEFT) || Keyboard.isKeyDown(Keyboard.KEY_RIGHT); - - event.toolTip.clear(); - event.toolTip.addAll(newTooltip); - - HashMap> loreBuckets = new HashMap<>(); - - List hypixelOrder = new ArrayList<>(); - - hypixelOrder.add("attributes"); - hypixelOrder.add("enchants"); - hypixelOrder.add("ability"); - hypixelOrder.add("reforge_bonus"); - hypixelOrder.add("rarity"); - - if(NotEnoughUpdates.INSTANCE.config.tooltipTweaks.showPriceInfoInvItem) { - ItemPriceInformation.addToTooltip(event.toolTip, internalname, event.itemStack); - } - - - - - - } - - private Pattern xpLevelPattern = Pattern.compile("(.*) (\\xA7e(.*)\\xA76/\\xA7e(.*))"); - - private void onItemToolTipInternalNameNull(ItemTooltipEvent event){ - petToolTipXPExtendPetMenu(event); - } - - private List petToolTipXPExtend(ItemTooltipEvent event) { - List tooltipText = new ArrayList(); - if (NotEnoughUpdates.INSTANCE.config.tooltipTweaks.petExtendExp) { - if(event.itemStack.getTagCompound().hasKey("DisablePetExp")){ - if(event.itemStack.getTagCompound().getBoolean("DisablePetExp")){ - return tooltipText; - } - } - //7 is just a random number i chose, prob no pets with less lines than 7 - if (event.toolTip.size() > 7) { - if (Utils.cleanColour(event.toolTip.get(1)).matches(petToolTipRegex)) { - - GuiProfileViewer.PetLevel petlevel = null; - - //this is the item itself - NBTTagCompound tag = event.itemStack.getTagCompound(); - if (tag.hasKey("ExtraAttributes")) { - if (tag.getCompoundTag("ExtraAttributes").hasKey("petInfo")) { - JsonObject petInfo = NotEnoughUpdates.INSTANCE.manager.gson.fromJson( - tag.getCompoundTag("ExtraAttributes").getString("petInfo"), JsonObject.class); - if (petInfo.has("exp") && petInfo.get("exp").isJsonPrimitive()) { - JsonPrimitive exp = petInfo.getAsJsonPrimitive("exp"); - String petName = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(event.itemStack); - //Utils.getRarityFromInt(Utils.checkItemTypePet(event.toolTip))).getAsInt(); - petlevel = GuiProfileViewer.getPetLevel(petName, Utils.getRarityFromInt(Utils.checkItemTypePet(event.toolTip)), exp.getAsLong()); - } - } - } - - if (petlevel != null) { - tooltipText.add(""); - if(petlevel.totalXp > petlevel.maxXP) { - tooltipText.add(EnumChatFormatting.AQUA + "" + EnumChatFormatting.BOLD +"MAX LEVEL"); - } else { - tooltipText.add(EnumChatFormatting.GRAY+"Progress to Level "+(int)Math.floor(petlevel.level+1)+": "+EnumChatFormatting.YELLOW+Utils.round(petlevel.levelPercentage*100, 1)+"%"); - int levelpercentage = Math.round(petlevel.levelPercentage*20); - tooltipText.add(EnumChatFormatting.DARK_GREEN+String.join("", Collections.nCopies(levelpercentage, "-"))+EnumChatFormatting.WHITE+String.join("", Collections.nCopies(20-levelpercentage, "-"))); - tooltipText.add(EnumChatFormatting.GRAY + "EXP: " + EnumChatFormatting.YELLOW + myFormatter.format(petlevel.levelXp) + - EnumChatFormatting.GOLD + "/" + EnumChatFormatting.YELLOW + myFormatter.format(petlevel.currentLevelRequirement) + " EXP"); - } - } - } - } - } - return tooltipText; - } - - private static final String petToolTipRegex = "((Farming)|(Combat)|(Fishing)|(Mining)|(Foraging)|(Enchanting)|(Alchemy)) ((Mount)|(Pet)|(Morph)).*"; - - private void petToolTipXPExtendPetMenu(ItemTooltipEvent event) { - if (NotEnoughUpdates.INSTANCE.config.tooltipTweaks.petExtendExp) { - //7 is just a random number i chose, prob no pets with less lines than 7 - if (event.toolTip.size() > 7) { - if (Utils.cleanColour(event.toolTip.get(1)).matches(petToolTipRegex)) { - GuiProfileViewer.PetLevel petlevel = null; - - int xpLine = -1; - for (int i = event.toolTip.size() - 1; i >= 0; i--) { - Matcher matcher = xpLevelPattern.matcher(event.toolTip.get(i)); - if (matcher.matches()) { - xpLine = i; - event.toolTip.set(xpLine, matcher.group(1)); - break; - } else if (event.toolTip.get(i).matches("MAX LEVEL")) { - return; - } - } - - PetInfoOverlay.Pet pet = PetInfoOverlay.getPetFromStack(event.itemStack.getDisplayName(), NotEnoughUpdates.INSTANCE.manager.getLoreFromNBT(event.itemStack.getTagCompound())); - if (pet == null) { - return; - } - petlevel = pet.petLevel; - - if (petlevel == null||xpLine==-1) { - return; - } - - event.toolTip.add(xpLine+1, EnumChatFormatting.GRAY + "EXP: " + EnumChatFormatting.YELLOW + myFormatter.format(petlevel.levelXp) + - EnumChatFormatting.GOLD + "/" + EnumChatFormatting.YELLOW + myFormatter.format(petlevel.currentLevelRequirement)); - - } - } - } - } - - DecimalFormat myFormatter = new DecimalFormat("###,###.###"); - - /** - * This makes it so that holding LCONTROL while hovering over an item with NBT will show the NBT of the item. - * @param event - */ - @SubscribeEvent - public void onItemTooltip(ItemTooltipEvent event) { - if(!neu.isOnSkyblock()) return; - /*if(NotEnoughUpdates.INSTANCE.config.improvedSBMenu.hideEmptyPanes && - event.itemStack.getItem().equals(Item.getItemFromBlock(Blocks.stained_glass_pane))) { - String first = Utils.cleanColour(event.toolTip.get(0)); - first = first.replaceAll("\\(.*\\)", "").trim(); - if(first.length() == 0) { - event.toolTip.clear(); - } - }*/ - //AH prices - /*if(Minecraft.getMinecraft().currentScreen != null) { - if(Minecraft.getMinecraft().currentScreen instanceof GuiChest) { - GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen; - ContainerChest container = (ContainerChest) chest.inventorySlots; - String containerName = container.getLowerChestInventory().getDisplayName().getUnformattedText(); - if(containerName.trim().equals("Auctions Browser")) { - String internalname = neu.manager.getInternalNameForItem(event.itemStack); - if(internalname != null) { - for(int i=0; i 0) { - event.toolTip.add(++i, EnumChatFormatting.GRAY + "Average price (w/ enchants): " + - EnumChatFormatting.GOLD + - format.format(priceWithEnchants) + " coins"); - } - - if(neu.manager.config.advancedPriceInfo.value) { - int salesVolume = (int) auctionInfo.get("sales").getAsFloat(); - int flipPrice = (int)(0.93*priceWithEnchants); - - event.toolTip.add(++i, EnumChatFormatting.GRAY + "Flip Price (93%): " + - EnumChatFormatting.GOLD + format.format(flipPrice) + " coins"); - event.toolTip.add(++i, EnumChatFormatting.GRAY + "Volume: " + - EnumChatFormatting.GOLD + format.format(salesVolume) + " sales/day"); - } - break; - } - } - } - } - } - } - }*/ - if(Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) && NotEnoughUpdates.INSTANCE.config.hidden.dev && - event.toolTip.size()>0&&event.toolTip.get(event.toolTip.size()-1).startsWith(EnumChatFormatting.DARK_GRAY + "NBT: ")) { - event.toolTip.remove(event.toolTip.size()-1); - - StringBuilder sb = new StringBuilder(); - String nbt = event.itemStack.getTagCompound().toString(); - int indent = 0; - for(char c : nbt.toCharArray()) { - boolean newline = false; - if(c == '{' || c == '[') { - indent++; - newline = true; - } else if(c == '}' || c == ']') { - indent--; - sb.append("\n"); - for(int i=0; i map = Minecraft.getMinecraft().getSkinManager().loadSkinFromCache(gameprofile); - - if (map.containsKey(MinecraftProfileTexture.Type.SKIN)) { - MinecraftProfileTexture profTex = map.get(MinecraftProfileTexture.Type.SKIN); - event.toolTip.add(EnumChatFormatting.AQUA+"Skull Texture Link: "+EnumChatFormatting.GRAY+profTex.getUrl()+EnumChatFormatting.GOLD+" [N]"); - - if(!copied && n) { - MiscUtils.copyToClipboard(profTex.getUrl()); - } - } - } - } - } - - if(k || m || n) { - copied = true; - } else { - copied = false; - } - } - } - - @SubscribeEvent - public void onRenderLast(RenderWorldLastEvent event){ - CrystalMetalDetectorSolver.render(event.partialTicks); - } + private IChatComponent processChatComponent(IChatComponent chatComponent) { + IChatComponent newComponent; + if (chatComponent instanceof ChatComponentText) { + ChatComponentText text = (ChatComponentText) chatComponent; + + newComponent = new ChatComponentText(processText(text.getUnformattedTextForChat())); + newComponent.setChatStyle(text.getChatStyle().createShallowCopy()); + + for (IChatComponent sibling : text.getSiblings()) { + newComponent.appendSibling(processChatComponent(sibling)); + } + } else if (chatComponent instanceof ChatComponentTranslation) { + ChatComponentTranslation trans = (ChatComponentTranslation) chatComponent; + + Object[] args = trans.getFormatArgs(); + Object[] newArgs = new Object[args.length]; + for (int i = 0; i < trans.getFormatArgs().length; i++) { + if (args[i] instanceof IChatComponent) { + newArgs[i] = processChatComponent((IChatComponent) args[i]); + } else { + newArgs[i] = args[i]; + } + } + newComponent = new ChatComponentTranslation(trans.getKey(), newArgs); + + for (IChatComponent sibling : trans.getSiblings()) { + newComponent.appendSibling(processChatComponent(sibling)); + } + } else { + newComponent = chatComponent.createCopy(); + } + + return newComponent; + } + + private String processText(String text) { + if (SBInfo.getInstance().getLocation() == null) return text; + if (!SBInfo.getInstance().getLocation().startsWith("mining_") && + !SBInfo.getInstance().getLocation().equals("crystal_hollows")) + return text; + + if (Minecraft.getMinecraft().thePlayer == null) return text; + if (!NotEnoughUpdates.INSTANCE.config.mining.drillFuelBar) return text; + + return Utils.trimIgnoreColour(text.replaceAll(EnumChatFormatting.DARK_GREEN + "\\S+ Drill Fuel", "")); + } + + private IChatComponent replaceSocialControlsWithPV(IChatComponent chatComponent) { + + if (NotEnoughUpdates.INSTANCE.config.misc.replaceSocialOptions1 > 0 && chatComponent.getChatStyle() != null && + chatComponent.getChatStyle().getChatClickEvent() != null && + chatComponent.getChatStyle().getChatClickEvent().getAction() == ClickEvent.Action.RUN_COMMAND && + NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) { + if (chatComponent.getChatStyle().getChatClickEvent().getValue().startsWith("/socialoptions")) { + String username = chatComponent.getChatStyle().getChatClickEvent().getValue().substring(15); + if (NotEnoughUpdates.INSTANCE.config.misc.replaceSocialOptions1 == 1) { + chatComponent.setChatStyle(Utils.createClickStyle( + ClickEvent.Action.RUN_COMMAND, + "/pv " + username, + "" + EnumChatFormatting.YELLOW + "Click to open " + EnumChatFormatting.AQUA + EnumChatFormatting.BOLD + + username + EnumChatFormatting.RESET + EnumChatFormatting.YELLOW + "'s profile in " + + EnumChatFormatting.DARK_PURPLE + EnumChatFormatting.BOLD + "NEU's" + EnumChatFormatting.RESET + + EnumChatFormatting.YELLOW + " profile viewer." + )); + return chatComponent; + } else if (NotEnoughUpdates.INSTANCE.config.misc.replaceSocialOptions1 == 2) { + chatComponent.setChatStyle(Utils.createClickStyle( + ClickEvent.Action.RUN_COMMAND, + "/ah " + username, + "" + EnumChatFormatting.YELLOW + "Click to open " + EnumChatFormatting.AQUA + EnumChatFormatting.BOLD + + username + EnumChatFormatting.RESET + EnumChatFormatting.YELLOW + "'s /ah page" + )); + return chatComponent; + } + } // wanted to add this for guild but guild uses uuid :sad: + } + return chatComponent; + } + + /** + * 1) When receiving "You are playing on profile" messages, will set the current profile. + * 2) When a /viewrecipe command fails (i.e. player does not have recipe unlocked, will open the custom recipe GUI) + * 3) Replaces lobby join notifications when streamer mode is active + */ + @SubscribeEvent(priority = EventPriority.LOW, receiveCanceled = true) + public void onGuiChat(ClientChatReceivedEvent e) { + if (e.type == 2) { + CrystalMetalDetectorSolver.process(e.message); + e.message = processChatComponent(e.message); + return; + } else if (e.type == 0) { + e.message = replaceSocialControlsWithPV(e.message); + } + + DungeonWin.onChatMessage(e); + + String r = null; + String unformatted = Utils.cleanColour(e.message.getUnformattedText()); + Matcher matcher = SLAYER_XP.matcher(unformatted); + if (unformatted.startsWith("You are playing on profile: ")) { + neu.manager.setCurrentProfile(unformatted + .substring("You are playing on profile: ".length()) + .split(" ")[0].trim()); + } else if (unformatted.startsWith("Your profile was changed to: ")) {//Your profile was changed to: + neu.manager.setCurrentProfile(unformatted + .substring("Your profile was changed to: ".length()) + .split(" ")[0].trim()); + } else if (unformatted.startsWith("Your new API key is ")) { + NotEnoughUpdates.INSTANCE.config.apiKey.apiKey = unformatted.substring("Your new API key is ".length()); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + + "[NEU] API Key automatically configured")); + NotEnoughUpdates.INSTANCE.config.apiKey.apiKey = NotEnoughUpdates.INSTANCE.config.apiKey.apiKey.substring(0, 36); + } else if (unformatted.startsWith("Player List Info is now disabled!")) { + SBInfo.getInstance().hasNewTab = false; + } else if (unformatted.startsWith("Player List Info is now enabled!")) { + SBInfo.getInstance().hasNewTab = true; + } + if (e.message.getFormattedText().equals(EnumChatFormatting.RESET.toString() + + EnumChatFormatting.RED + "You haven't unlocked this recipe!" + EnumChatFormatting.RESET)) { + r = EnumChatFormatting.RED + "You haven't unlocked this recipe!"; + } else if (e.message.getFormattedText().startsWith(EnumChatFormatting.RESET.toString() + + EnumChatFormatting.RED + "Invalid recipe ")) { + r = ""; + } else if (unformatted.equals(" NICE! SLAYER BOSS SLAIN!")) { + SlayerOverlay.isSlain = true; + } else if (unformatted.equals(" SLAYER QUEST STARTED!")) { + SlayerOverlay.isSlain = false; + if (timeSinceLastBoss == 0) { + SlayerOverlay.timeSinceLastBoss = System.currentTimeMillis(); + } else { + timeSinceLastBoss2 = timeSinceLastBoss; + timeSinceLastBoss = System.currentTimeMillis(); + } + } else if (unformatted.startsWith(" RNGesus Meter:")) { + RNGMeter = unformatted.substring(" RNGesus Meter: -------------------- ".length()); + } else if (matcher.matches()) { + //matcher.group(1); + SlayerOverlay.slayerLVL = matcher.group(2); + if (!SlayerOverlay.slayerLVL.equals("9")) { + SlayerOverlay.slayerXp = matcher.group(3); + } else { + slayerXp = "maxed"; + } + } else if (unformatted.startsWith("Sending to server") || + (unformatted.startsWith("Your Slayer Quest has been cancelled!"))) { + SlayerOverlay.slayerQuest = false; + SlayerOverlay.unloadOverlayTimer = System.currentTimeMillis(); + } + if (e.message + .getFormattedText() + .contains(EnumChatFormatting.YELLOW + "Visit the Auction House to collect your item!")) { + if (NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.latestBid != null && + System.currentTimeMillis() - NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.latestBidMillis < 5000) { + NotEnoughUpdates.INSTANCE.sendChatMessage("/viewauction " + + NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.niceAucId( + NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.latestBid)); + } + } + if (r != null) { + if (neu.manager.failViewItem(r)) { + e.setCanceled(true); + } + missingRecipe.set(true); + } + //System.out.println(e.message); + if (unformatted.startsWith("Sending to server") && + neu.isOnSkyblock() && NotEnoughUpdates.INSTANCE.config.misc.streamerMode && + e.message instanceof ChatComponentText) { + String m = e.message.getFormattedText(); + String m2 = StreamerMode.filterChat(e.message.getFormattedText()); + if (!m.equals(m2)) { + e.message = new ChatComponentText(m2); + } + } + if (unformatted.startsWith("You found ") && SBInfo.getInstance().getLocation() != null && + SBInfo.getInstance().getLocation().equals("crystal_hollows")) { + CrystalMetalDetectorSolver.reset(true); + } + if (unformatted.startsWith("[NPC] Keeper of ") | unformatted.startsWith("[NPC] Professor Robot: ") || + unformatted.startsWith(" ") || unformatted.startsWith("✦") || + unformatted.equals(" You've earned a Crystal Loot Bundle!")) + OverlayManager.crystalHollowOverlay.message(unformatted); + } + + public static boolean drawingGuiScreen = false; + + /** + * Sets hoverInv and focusInv variables, representing whether the NEUOverlay should render behind the inventory when + * (hoverInv == true) and whether mouse/kbd inputs shouldn't be sent to NEUOverlay (focusInv == true). + *

+ * If hoverInv is true, will render the overlay immediately (resulting in the inventory being drawn over the GUI) + * If hoverInv is false, the overlay will render in #onGuiScreenDraw (resulting in the GUI being drawn over the inv) + *

+ * All of this only matters if players are using gui scale auto which may result in the inventory being drawn + * over the various panes. + */ + @SubscribeEvent + public void onGuiBackgroundDraw(GuiScreenEvent.BackgroundDrawnEvent event) { + if (showNotificationOverInv) { + + renderNotification(); + + } + if ((shouldRenderOverlay(event.gui) || event.gui instanceof CustomAHGui) && neu.isOnSkyblock()) { + ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft()); + int width = scaledresolution.getScaledWidth(); + + boolean hoverPane = event.getMouseX() < width * neu.overlay.getInfoPaneOffsetFactor() || + event.getMouseX() > width * neu.overlay.getItemPaneOffsetFactor(); + + if (event.gui instanceof GuiContainer) { + try { + int xSize = ((GuiContainer) event.gui).xSize; + int ySize = ((GuiContainer) event.gui).ySize; + int guiLeft = ((GuiContainer) event.gui).guiLeft; + int guiTop = ((GuiContainer) event.gui).guiTop; + + hoverInv = event.getMouseX() > guiLeft && event.getMouseX() < guiLeft + xSize && + event.getMouseY() > guiTop && event.getMouseY() < guiTop + ySize; + + if (hoverPane) { + if (!hoverInv) focusInv = false; + } else { + focusInv = true; + } + } catch (NullPointerException npe) { + focusInv = !hoverPane; + } + } + if (event.gui instanceof GuiItemRecipe) { + GuiItemRecipe guiItemRecipe = ((GuiItemRecipe) event.gui); + hoverInv = event.getMouseX() > guiItemRecipe.guiLeft && + event.getMouseX() < guiItemRecipe.guiLeft + guiItemRecipe.xSize && + event.getMouseY() > guiItemRecipe.guiTop && event.getMouseY() < guiItemRecipe.guiTop + guiItemRecipe.ySize; + + if (hoverPane) { + if (!hoverInv) focusInv = false; + } else { + focusInv = true; + } + } + if (focusInv) { + try { + neu.overlay.render(hoverInv); + } catch (ConcurrentModificationException e) { + e.printStackTrace(); + } + GL11.glTranslatef(0, 0, 10); + } + if (hoverInv) { + renderDungeonChestOverlay(event.gui); + if (NotEnoughUpdates.INSTANCE.config.accessoryBag.enableOverlay) { + AccessoryBagOverlay.renderOverlay(); + } + } + } + + drawingGuiScreen = true; + } + + private boolean doInventoryButtons = false; + + @SubscribeEvent + public void onGuiScreenDrawPre(GuiScreenEvent.DrawScreenEvent.Pre event) { + doInventoryButtons = false; + + if (AuctionSearchOverlay.shouldReplace()) { + AuctionSearchOverlay.render(); + event.setCanceled(true); + return; + } + if (RancherBootOverlay.shouldReplace()) { + RancherBootOverlay.render(); + event.setCanceled(true); + return; + } + + String containerName = null; + GuiScreen guiScreen = Minecraft.getMinecraft().currentScreen; + if (guiScreen instanceof GuiChest) { + GuiChest eventGui = (GuiChest) guiScreen; + ContainerChest cc = (ContainerChest) eventGui.inventorySlots; + containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText(); + } + + if (GuiCustomEnchant.getInstance().shouldOverride(containerName)) { + GuiCustomEnchant.getInstance().render(event.renderPartialTicks); + event.setCanceled(true); + return; + } + + boolean tradeWindowActive = TradeWindow.tradeWindowActive(containerName); + boolean storageOverlayActive = StorageManager.getInstance().shouldRenderStorageOverlay(containerName); + boolean customAhActive = + event.gui instanceof CustomAHGui || neu.manager.auctionManager.customAH.isRenderOverAuctionView(); + + if (storageOverlayActive) { + StorageOverlay.getInstance().render(); + event.setCanceled(true); + return; + } + + if (tradeWindowActive || customAhActive) { + event.setCanceled(true); + + ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + int width = scaledResolution.getScaledWidth(); + int height = scaledResolution.getScaledHeight(); + + //Dark background + Utils.drawGradientRect(0, 0, width, height, -1072689136, -804253680); + + if (event.mouseX < width * neu.overlay.getWidthMult() / 3 || + event.mouseX > width - width * neu.overlay.getWidthMult() / 3) { + if (customAhActive) { + neu.manager.auctionManager.customAH.drawScreen(event.mouseX, event.mouseY); + } else if (tradeWindowActive) { + TradeWindow.render(event.mouseX, event.mouseY); + } + neu.overlay.render(false); + } else { + neu.overlay.render(false); + if (customAhActive) { + neu.manager.auctionManager.customAH.drawScreen(event.mouseX, event.mouseY); + } else if (tradeWindowActive) { + TradeWindow.render(event.mouseX, event.mouseY); + } + } + } + + if (CalendarOverlay.isEnabled() || event.isCanceled()) return; + if (NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() && shouldRenderOverlay(event.gui) + && event.gui instanceof GuiContainer) { + doInventoryButtons = true; + + int zOffset = 50; + + GlStateManager.translate(0, 0, zOffset); + + int xSize = ((GuiContainer) event.gui).xSize; + int ySize = ((GuiContainer) event.gui).ySize; + int guiLeft = ((GuiContainer) event.gui).guiLeft; + int guiTop = ((GuiContainer) event.gui).guiTop; + + if (!NEUApi.disableInventoryButtons) { + for (NEUConfig.InventoryButton button : NotEnoughUpdates.INSTANCE.config.hidden.inventoryButtons) { + if (!button.isActive()) continue; + if (button.playerInvOnly && !(event.gui instanceof GuiInventory)) continue; + + int x = guiLeft + button.x; + int y = guiTop + button.y; + if (button.anchorRight) { + x += xSize; + } + if (button.anchorBottom) { + y += ySize; + } + if (AccessoryBagOverlay.isInAccessoryBag()) { + if (x > guiLeft + xSize && x < guiLeft + xSize + 80 + 28 + 5 && y > guiTop - 18 && y < guiTop + 150) { + x += 80 + 28; + } + } + if (NEUOverlay.isRenderingArmorHud()) { + if (x < guiLeft + xSize - 150 && x > guiLeft + xSize - 200 && y > guiTop && y < guiTop + 84) { + x -= 25; + } + } + if (NEUOverlay.isRenderingPetHud()) { + if (x < guiLeft + xSize - 150 && x > guiLeft + xSize - 200 && y > guiTop + 60 && y < guiTop + 120) { + x -= 25; + } + } + + GlStateManager.color(1, 1, 1, 1f); + + GlStateManager.enableDepth(); + GlStateManager.enableAlpha(); + Minecraft.getMinecraft().getTextureManager().bindTexture(EDITOR); + Utils.drawTexturedRect(x, y, 18, 18, + button.backgroundIndex * 18 / 256f, (button.backgroundIndex * 18 + 18) / 256f, + 18 / 256f, 36 / 256f, GL11.GL_NEAREST + ); + + if (button.icon != null && !button.icon.trim().isEmpty()) { + GuiInvButtonEditor.renderIcon(button.icon, x + 1, y + 1); + } + } + } + GlStateManager.translate(0, 0, -zOffset); + } + } + + private static boolean shouldRenderOverlay(Gui gui) { + boolean validGui = gui instanceof GuiContainer || gui instanceof GuiItemRecipe; + if (gui instanceof GuiChest) { + GuiChest eventGui = (GuiChest) gui; + ContainerChest cc = (ContainerChest) eventGui.inventorySlots; + String containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText(); + if (containerName.trim().equals("Fast Travel")) { + validGui = false; + } + } + return validGui; + } + + private static final ResourceLocation EDITOR = new ResourceLocation("notenoughupdates:invbuttons/editor.png"); + private NEUConfig.InventoryButton buttonHovered = null; + private long buttonHoveredMillis = 0; + public static boolean disableCraftingText = false; + + /** + * Will draw the NEUOverlay over the inventory if focusInv == false. (z-translation of 300 is so that NEUOverlay + * will draw over Items in the inventory (which render at a z value of about 250)) + */ + @SubscribeEvent + public void onGuiScreenDrawPost(GuiScreenEvent.DrawScreenEvent.Post event) { + drawingGuiScreen = false; + disableCraftingText = false; + + String containerName = null; + GuiScreen guiScreen = Minecraft.getMinecraft().currentScreen; + if (guiScreen instanceof GuiChest) { + GuiChest eventGui = (GuiChest) guiScreen; + ContainerChest cc = (ContainerChest) eventGui.inventorySlots; + containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText(); + + if (GuiCustomEnchant.getInstance().shouldOverride(containerName)) + return; + } + + boolean tradeWindowActive = TradeWindow.tradeWindowActive(containerName); + boolean storageOverlayActive = StorageManager.getInstance().shouldRenderStorageOverlay(containerName); + boolean customAhActive = + event.gui instanceof CustomAHGui || neu.manager.auctionManager.customAH.isRenderOverAuctionView(); + + if (!(tradeWindowActive || storageOverlayActive || customAhActive)) { + if (shouldRenderOverlay(event.gui) && neu.isOnSkyblock()) { + GlStateManager.pushMatrix(); + if (!focusInv) { + GL11.glTranslatef(0, 0, 300); + neu.overlay.render(hoverInv && focusInv); + GL11.glTranslatef(0, 0, -300); + } + GlStateManager.popMatrix(); + } + } + + if (shouldRenderOverlay(event.gui) && neu.isOnSkyblock() && !hoverInv) { + renderDungeonChestOverlay(event.gui); + if (NotEnoughUpdates.INSTANCE.config.accessoryBag.enableOverlay) { + AccessoryBagOverlay.renderOverlay(); + } + } + + boolean hoveringButton = false; + if (!doInventoryButtons) return; + if (NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() && shouldRenderOverlay(event.gui) && + event.gui instanceof GuiContainer) { + int xSize = ((GuiContainer) event.gui).xSize; + int ySize = ((GuiContainer) event.gui).ySize; + int guiLeft = ((GuiContainer) event.gui).guiLeft; + int guiTop = ((GuiContainer) event.gui).guiTop; + + if (!NEUApi.disableInventoryButtons) { + for (NEUConfig.InventoryButton button : NotEnoughUpdates.INSTANCE.config.hidden.inventoryButtons) { + if (!button.isActive()) continue; + if (button.playerInvOnly && !(event.gui instanceof GuiInventory)) continue; + + int x = guiLeft + button.x; + int y = guiTop + button.y; + if (button.anchorRight) { + x += xSize; + } + if (button.anchorBottom) { + y += ySize; + } + if (AccessoryBagOverlay.isInAccessoryBag()) { + if (x > guiLeft + xSize && x < guiLeft + xSize + 80 + 28 + 5 && y > guiTop - 18 && y < guiTop + 150) { + x += 80 + 28; + } + } + if (NEUOverlay.isRenderingArmorHud()) { + if (x < guiLeft + xSize - 150 && x > guiLeft + xSize - 200 && y > guiTop && y < guiTop + 84) { + x -= 25; + } + } + if (NEUOverlay.isRenderingPetHud()) { + if (x < guiLeft + xSize - 150 && x > guiLeft + xSize - 200 && y > guiTop + 60 && y < guiTop + 120) { + x -= 25; + } + } + + if (x - guiLeft >= 85 && x - guiLeft <= 115 && y - guiTop >= 4 && y - guiTop <= 25) { + disableCraftingText = true; + } + + if (event.mouseX >= x && event.mouseX <= x + 18 && + event.mouseY >= y && event.mouseY <= y + 18) { + hoveringButton = true; + long currentTime = System.currentTimeMillis(); + + if (buttonHovered != button) { + buttonHoveredMillis = currentTime; + buttonHovered = button; + } + + if (currentTime - buttonHoveredMillis > 600) { + String command = button.command.trim(); + if (!command.startsWith("/")) { + command = "/" + command; + } + + Utils.drawHoveringText(Lists.newArrayList("\u00a77" + command), event.mouseX, event.mouseY, + event.gui.width, event.gui.height, -1, Minecraft.getMinecraft().fontRendererObj + ); + } + } + } + } + } + if (!hoveringButton) buttonHovered = null; + + if (AuctionBINWarning.getInstance().shouldShow()) { + AuctionBINWarning.getInstance().render(); + } + } + + private void renderDungeonChestOverlay(GuiScreen gui) { + if (NotEnoughUpdates.INSTANCE.config.dungeons.profitDisplayLoc == 3) return; + + if (gui instanceof GuiChest && NotEnoughUpdates.INSTANCE.config.dungeons.profitDisplayLoc != 2) { + try { + int xSize = ((GuiContainer) gui).xSize; + int ySize = ((GuiContainer) gui).ySize; + int guiLeft = ((GuiContainer) gui).guiLeft; + int guiTop = ((GuiContainer) gui).guiTop; + + GuiChest eventGui = (GuiChest) gui; + ContainerChest cc = (ContainerChest) eventGui.inventorySlots; + IInventory lower = cc.getLowerChestInventory(); + + ItemStack rewardChest = lower.getStackInSlot(31); + if (rewardChest != null && + rewardChest.getDisplayName().endsWith(EnumChatFormatting.GREEN + "Open Reward Chest")) { + int chestCost = 0; + try { + String line6 = Utils.cleanColour(neu.manager.getLoreFromNBT(rewardChest.getTagCompound())[6]); + StringBuilder cost = new StringBuilder(); + for (int i = 0; i < line6.length(); i++) { + char c = line6.charAt(i); + if ("0123456789".indexOf(c) >= 0) { + cost.append(c); + } + } + if (cost.length() > 0) { + chestCost = Integer.parseInt(cost.toString()); + } + } catch (Exception ignored) { + } + + String missingItem = null; + int totalValue = 0; + HashMap itemValues = new HashMap<>(); + for (int i = 0; i < 5; i++) { + ItemStack item = lower.getStackInSlot(11 + i); + String internal = neu.manager.getInternalNameForItem(item); + if (internal != null) { + internal = internal.replace("\u00CD", "I").replace("\u0130", "I"); + float bazaarPrice = -1; + JsonObject bazaarInfo = neu.manager.auctionManager.getBazaarInfo(internal); + if (bazaarInfo != null && bazaarInfo.has("curr_sell")) { + bazaarPrice = bazaarInfo.get("curr_sell").getAsFloat(); + } + if (bazaarPrice < 5000000 && internal.equals("RECOMBOBULATOR_3000")) bazaarPrice = 5000000; + + float worth = -1; + if (bazaarPrice > 0) { + worth = bazaarPrice; + } else { + switch (NotEnoughUpdates.INSTANCE.config.dungeons.profitType) { + case 1: + worth = neu.manager.auctionManager.getItemAvgBin(internal); + break; + case 2: + JsonObject auctionInfo = neu.manager.auctionManager.getItemAuctionInfo(internal); + if (auctionInfo != null) { + if (auctionInfo.has("clean_price")) { + worth = (int) auctionInfo.get("clean_price").getAsFloat(); + } else { + worth = (int) (auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat()); + } + } + break; + default: + worth = neu.manager.auctionManager.getLowestBin(internal); + } + if (worth <= 0) { + worth = neu.manager.auctionManager.getLowestBin(internal); + if (worth <= 0) { + worth = neu.manager.auctionManager.getItemAvgBin(internal); + if (worth <= 0) { + JsonObject auctionInfo = neu.manager.auctionManager.getItemAuctionInfo(internal); + if (auctionInfo != null) { + if (auctionInfo.has("clean_price")) { + worth = (int) auctionInfo.get("clean_price").getAsFloat(); + } else { + worth = (int) (auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat()); + } + } + } + } + } + } + + if (worth > 0 && totalValue >= 0) { + totalValue += worth; + String display = item.getDisplayName(); + + if (display.contains("Enchanted Book")) { + NBTTagCompound tag = item.getTagCompound(); + if (tag != null && tag.hasKey("ExtraAttributes", 10)) { + NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes"); + NBTTagCompound enchants = ea.getCompoundTag("enchantments"); + + int highestLevel = -1; + for (String enchname : enchants.getKeySet()) { + int level = enchants.getInteger(enchname); + if (level > highestLevel) { + display = EnumChatFormatting.BLUE + WordUtils.capitalizeFully( + enchname.replace("_", " ") + .replace("Ultimate", "") + .trim()) + " " + level; + } + } + } + } + + itemValues.put(display, worth); + } else { + if (totalValue != -1) { + missingItem = internal; + } + totalValue = -1; + } + } + } + + NumberFormat format = NumberFormat.getInstance(Locale.US); + String valueStringBIN1; + String valueStringBIN2; + if (totalValue >= 0) { + valueStringBIN1 = EnumChatFormatting.YELLOW + "Value (BIN): "; + valueStringBIN2 = EnumChatFormatting.GOLD + format.format(totalValue) + " coins"; + } else { + valueStringBIN1 = EnumChatFormatting.YELLOW + "Can't find BIN: "; + valueStringBIN2 = missingItem; + } + + int profitLossBIN = totalValue - chestCost; + + boolean kismetUsed = false; + // checking for kismet + Slot slot = (eventGui.inventorySlots.getSlot(50)); + if (slot.getHasStack()) { + String[] lore = NotEnoughUpdates.INSTANCE.manager.getLoreFromNBT(slot.getStack().getTagCompound()); + for (String line : lore) { + if (line.contains("You already rerolled a chest!")) { + kismetUsed = true; + break; + } + } + } + int kismetPrice = neu.manager.auctionManager.getLowestBin("KISMET_FEATHER"); + String kismetStr = EnumChatFormatting.RED + format.format(kismetPrice) + " coins"; + if (neu.config.dungeons.useKismetOnDungeonProfit) + profitLossBIN = kismetUsed ? profitLossBIN - kismetPrice : profitLossBIN; + + String profitPrefix = EnumChatFormatting.DARK_GREEN.toString(); + String lossPrefix = EnumChatFormatting.RED.toString(); + String prefix = profitLossBIN >= 0 ? profitPrefix : lossPrefix; + + String plStringBIN; + if (profitLossBIN >= 0) { + plStringBIN = prefix + "+" + format.format(profitLossBIN) + " coins"; + } else { + plStringBIN = prefix + "-" + format.format(-profitLossBIN) + " coins"; + } + + if (NotEnoughUpdates.INSTANCE.config.dungeons.profitDisplayLoc == 1 && !valueStringBIN2.equals(missingItem)) { + int w = Minecraft.getMinecraft().fontRendererObj.getStringWidth(plStringBIN); + GlStateManager.disableLighting(); + GlStateManager.translate(0, 0, 200); + Minecraft.getMinecraft().fontRendererObj.drawString(plStringBIN, guiLeft + xSize - 5 - w, guiTop + 5, + 0xffffffff, true + ); + GlStateManager.translate(0, 0, -200); + return; + } + + Minecraft.getMinecraft().getTextureManager().bindTexture(dungeon_chest_worth); + GL11.glColor4f(1, 1, 1, 1); + GlStateManager.disableLighting(); + Utils.drawTexturedRect(guiLeft + xSize + 4, guiTop, 180, 101, 0, 180 / 256f, 0, 101 / 256f, GL11.GL_NEAREST); + + Utils.renderAlignedString(valueStringBIN1, valueStringBIN2, + guiLeft + xSize + 4 + 10, guiTop + 14, 160 + ); + if (neu.config.dungeons.useKismetOnDungeonProfit && kismetUsed) { + Utils.renderAlignedString(EnumChatFormatting.YELLOW + "Kismet Feather: ", kismetStr, + guiLeft + xSize + 4 + 10, guiTop + 24, 160 + ); + } + if (totalValue >= 0) { + Utils.renderAlignedString( + EnumChatFormatting.YELLOW + "Profit/Loss: ", + plStringBIN, + guiLeft + xSize + 4 + 10, + guiTop + (neu.config.dungeons.useKismetOnDungeonProfit ? (kismetUsed ? 34 : 24) : 24), + 160 + ); + } + + int index = 0; + for (Map.Entry entry : itemValues.entrySet()) { + Utils.renderAlignedString( + entry.getKey(), + prefix + + format.format(entry.getValue().intValue()), + guiLeft + xSize + 4 + 10, + guiTop + (neu.config.dungeons.useKismetOnDungeonProfit ? (kismetUsed ? 39 : 29) : 29) + (++index) * 10, + 160 + ); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + public void drawStringShadow(String str, float x, float y, int len) { + for (int xOff = -2; xOff <= 2; xOff++) { + for (int yOff = -2; yOff <= 2; yOff++) { + if (Math.abs(xOff) != Math.abs(yOff)) { + Utils.drawStringCenteredScaledMaxWidth(Utils.cleanColourNotModifiers(str), + Minecraft.getMinecraft().fontRendererObj, + x + xOff / 2f, y + yOff / 2f, false, len, + new Color(20, 20, 20, 100 / Math.max(Math.abs(xOff), Math.abs(yOff))).getRGB() + ); + } + } + } + + Utils.drawStringCenteredScaledMaxWidth(str, + Minecraft.getMinecraft().fontRendererObj, + x, y, false, len, + new Color(64, 64, 64, 255).getRGB() + ); + } + + /** + * Sends a mouse event to NEUOverlay if the inventory isn't hovered AND focused. + * Will also cancel the event if if NEUOverlay#mouseInput returns true. + */ + @SubscribeEvent(priority = EventPriority.LOW) + public void onGuiScreenMouse(GuiScreenEvent.MouseInputEvent.Pre event) { + if (Mouse.getEventButtonState() && StorageManager.getInstance().onAnyClick()) { + event.setCanceled(true); + return; + } + + final ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft()); + final int scaledWidth = scaledresolution.getScaledWidth(); + final int scaledHeight = scaledresolution.getScaledHeight(); + int mouseX = Mouse.getX() * scaledWidth / Minecraft.getMinecraft().displayWidth; + int mouseY = scaledHeight - Mouse.getY() * scaledHeight / Minecraft.getMinecraft().displayHeight - 1; + + if (AuctionBINWarning.getInstance().shouldShow()) { + AuctionBINWarning.getInstance().mouseInput(mouseX, mouseY); + event.setCanceled(true); + return; + } + + if (!event.isCanceled()) { + Utils.scrollTooltip(Mouse.getEventDWheel()); + } + if (AuctionSearchOverlay.shouldReplace()) { + AuctionSearchOverlay.mouseEvent(); + event.setCanceled(true); + return; + } + if (RancherBootOverlay.shouldReplace()) { + RancherBootOverlay.mouseEvent(); + event.setCanceled(true); + return; + } + + String containerName = null; + GuiScreen guiScreen = Minecraft.getMinecraft().currentScreen; + if (guiScreen instanceof GuiChest) { + GuiChest eventGui = (GuiChest) guiScreen; + ContainerChest cc = (ContainerChest) eventGui.inventorySlots; + containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText(); + if (containerName.contains(" Profile") && BetterContainers.profileViewerStackIndex != -1 && + eventGui.isMouseOverSlot(cc.inventorySlots.get(BetterContainers.profileViewerStackIndex), mouseX, mouseY) && + Mouse.getEventButton() >= 0) { + event.setCanceled(true); + if (Mouse.getEventButtonState() && eventGui.inventorySlots.inventorySlots.get(22).getStack() != null && + eventGui.inventorySlots.inventorySlots.get(22).getStack().getTagCompound() != null) { + NBTTagCompound tag = eventGui.inventorySlots.inventorySlots.get(22).getStack().getTagCompound(); + if (tag.hasKey("SkullOwner") && tag.getCompoundTag("SkullOwner").hasKey("Name")) { + String username = tag.getCompoundTag("SkullOwner").getString("Name"); + Utils.playPressSound(); + ViewProfileCommand.RUNNABLE.accept(new String[]{username}); + } + } + } + } + + if (GuiCustomEnchant.getInstance().shouldOverride(containerName) && + GuiCustomEnchant.getInstance().mouseInput(mouseX, mouseY)) { + event.setCanceled(true); + return; + } + + boolean tradeWindowActive = TradeWindow.tradeWindowActive(containerName); + boolean storageOverlayActive = StorageManager.getInstance().shouldRenderStorageOverlay(containerName); + boolean customAhActive = + event.gui instanceof CustomAHGui || neu.manager.auctionManager.customAH.isRenderOverAuctionView(); + + if (storageOverlayActive) { + if (StorageOverlay.getInstance().mouseInput(mouseX, mouseY)) { + event.setCanceled(true); + } + return; + } + + if (tradeWindowActive || customAhActive) { + event.setCanceled(true); + if (customAhActive) { + neu.manager.auctionManager.customAH.handleMouseInput(); + } else if (tradeWindowActive) { + TradeWindow.handleMouseInput(); + } + neu.overlay.mouseInput(); + return; + } + + if (shouldRenderOverlay(event.gui) && neu.isOnSkyblock()) { + if (!NotEnoughUpdates.INSTANCE.config.accessoryBag.enableOverlay || !AccessoryBagOverlay.mouseClick()) { + if (!(hoverInv && focusInv)) { + if (neu.overlay.mouseInput()) { + event.setCanceled(true); + } + } else { + neu.overlay.mouseInputInv(); + } + } + } + if (event.isCanceled()) return; + if (!doInventoryButtons) return; + if (NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() && shouldRenderOverlay(event.gui) && + Mouse.getEventButton() >= 0 + && event.gui instanceof GuiContainer) { + int xSize = ((GuiContainer) event.gui).xSize; + int ySize = ((GuiContainer) event.gui).ySize; + int guiLeft = ((GuiContainer) event.gui).guiLeft; + int guiTop = ((GuiContainer) event.gui).guiTop; + if (!NEUApi.disableInventoryButtons) { + for (NEUConfig.InventoryButton button : NotEnoughUpdates.INSTANCE.config.hidden.inventoryButtons) { + if (!button.isActive()) continue; + if (button.playerInvOnly && !(event.gui instanceof GuiInventory)) continue; + + int x = guiLeft + button.x; + int y = guiTop + button.y; + if (button.anchorRight) { + x += xSize; + } + if (button.anchorBottom) { + y += ySize; + } + if (AccessoryBagOverlay.isInAccessoryBag()) { + if (x > guiLeft + xSize && x < guiLeft + xSize + 80 + 28 + 5 && y > guiTop - 18 && y < guiTop + 150) { + x += 80 + 28; + } + } + if (NEUOverlay.isRenderingArmorHud()) { + if (x < guiLeft + xSize - 150 && x > guiLeft + xSize - 200 && y > guiTop && y < guiTop + 84) { + x -= 25; + } + } + if (NEUOverlay.isRenderingPetHud()) { + if (x < guiLeft + xSize - 150 && x > guiLeft + xSize - 200 && y > guiTop + 60 && y < guiTop + 120) { + x -= 25; + } + } + + if (mouseX >= x && mouseX <= x + 18 && mouseY >= y && mouseY <= y + 18) { + if (Minecraft.getMinecraft().thePlayer.inventory.getItemStack() == null) { + int clickType = NotEnoughUpdates.INSTANCE.config.inventoryButtons.clickType; + if ((clickType == 0 && Mouse.getEventButtonState()) || (clickType == 1 && !Mouse.getEventButtonState())) { + String command = button.command.trim(); + if (!command.startsWith("/")) { + command = "/" + command; + } + if (ClientCommandHandler.instance.executeCommand(Minecraft.getMinecraft().thePlayer, command) == 0) { + NotEnoughUpdates.INSTANCE.sendChatMessage(command); + } + } + } else { + event.setCanceled(true); + } + return; + } + } + } + } + } + + ScheduledExecutorService ses = Executors.newScheduledThreadPool(1); + + JsonObject essenceJson = new JsonObject(); + + /** + * Sends a kbd event to NEUOverlay, cancelling if NEUOverlay#keyboardInput returns true. + * Also includes a dev function used for creating custom named json files with recipes. + */ + @SubscribeEvent + public void onGuiScreenKeyboard(GuiScreenEvent.KeyboardInputEvent.Pre event) { + if (AuctionBINWarning.getInstance().shouldShow()) { + AuctionBINWarning.getInstance().keyboardInput(); + event.setCanceled(true); + return; + } + + if (AuctionSearchOverlay.shouldReplace()) { + AuctionSearchOverlay.keyEvent(); + event.setCanceled(true); + return; + } + if (RancherBootOverlay.shouldReplace()) { + RancherBootOverlay.keyEvent(); + event.setCanceled(true); + return; + } + + String containerName = null; + GuiScreen guiScreen = Minecraft.getMinecraft().currentScreen; + + if (guiScreen instanceof GuiChest) { + containerName = ((ContainerChest) ((GuiChest) guiScreen).inventorySlots) + .getLowerChestInventory() + .getDisplayName() + .getUnformattedText(); + } + + if (GuiCustomEnchant.getInstance().shouldOverride(containerName) && + GuiCustomEnchant.getInstance().keyboardInput()) { + event.setCanceled(true); + return; + } + + boolean tradeWindowActive = TradeWindow.tradeWindowActive(containerName); + boolean storageOverlayActive = StorageManager.getInstance().shouldRenderStorageOverlay(containerName); + boolean customAhActive = + event.gui instanceof CustomAHGui || neu.manager.auctionManager.customAH.isRenderOverAuctionView(); + + if (storageOverlayActive) { + if (StorageOverlay.getInstance().keyboardInput()) { + event.setCanceled(true); + return; + } + } + + if (tradeWindowActive || customAhActive) { + if (customAhActive) { + if (neu.manager.auctionManager.customAH.keyboardInput()) { + event.setCanceled(true); + Minecraft.getMinecraft().dispatchKeypresses(); + } else if (neu.overlay.keyboardInput(focusInv)) { + event.setCanceled(true); + } + } else if (tradeWindowActive) { + TradeWindow.keyboardInput(); + if (Keyboard.getEventKey() != Keyboard.KEY_ESCAPE) { + event.setCanceled(true); + Minecraft.getMinecraft().dispatchKeypresses(); + neu.overlay.keyboardInput(focusInv); + } + } + return; + } + + if (shouldRenderOverlay(event.gui) && neu.isOnSkyblock()) { + if (neu.overlay.keyboardInput(focusInv)) { + event.setCanceled(true); + } + } + if (NotEnoughUpdates.INSTANCE.config.hidden.dev && NotEnoughUpdates.INSTANCE.config.hidden.enableItemEditing && + Minecraft.getMinecraft().theWorld != null && + Keyboard.getEventKey() == Keyboard.KEY_N && Keyboard.getEventKeyState()) { + GuiScreen gui = Minecraft.getMinecraft().currentScreen; + if (gui instanceof GuiChest) { + GuiChest eventGui = (GuiChest) event.gui; + ContainerChest cc = (ContainerChest) eventGui.inventorySlots; + IInventory lower = cc.getLowerChestInventory(); + + if (!lower.getDisplayName().getUnformattedText().endsWith("Essence")) return; + + for (int i = 0; i < lower.getSizeInventory(); i++) { + ItemStack stack = lower.getStackInSlot(i); + + String internalname = neu.manager.getInternalNameForItem(stack); + if (internalname != null) { + String[] lore = neu.manager.getLoreFromNBT(stack.getTagCompound()); + + for (String line : lore) { + if (line.contains(":") && (line.startsWith("\u00A77Upgrade to") || + line.startsWith("\u00A77Convert to Dungeon Item"))) { + String[] split = line.split(":"); + String after = Utils.cleanColour(split[1]); + StringBuilder costS = new StringBuilder(); + for (char c : after.toCharArray()) { + if (c >= '0' && c <= '9') { + costS.append(c); + } + } + int cost = Integer.parseInt(costS.toString()); + String[] afterSplit = after.split(" "); + String type = afterSplit[afterSplit.length - 2]; + + if (!essenceJson.has(internalname)) { + essenceJson.add(internalname, new JsonObject()); + } + JsonObject obj = essenceJson.get(internalname).getAsJsonObject(); + obj.addProperty("type", type); + + if (line.startsWith("\u00A77Convert to Dungeon Item")) { + obj.addProperty("dungeonize", cost); + } else if (line.startsWith("\u00A77Upgrade to")) { + int stars = 0; + for (char c : line.toCharArray()) { + if (c == '\u272A') stars++; + } + if (stars > 0) { + obj.addProperty(stars + "", cost); + } + } + } + } + } + } + System.out.println(essenceJson); + } + } + if (NotEnoughUpdates.INSTANCE.config.hidden.dev && NotEnoughUpdates.INSTANCE.config.hidden.enableItemEditing && + Minecraft.getMinecraft().theWorld != null && + Keyboard.getEventKey() == Keyboard.KEY_O && Keyboard.getEventKeyState()) { + GuiScreen gui = Minecraft.getMinecraft().currentScreen; + if (gui instanceof GuiChest) { + GuiChest eventGui = (GuiChest) event.gui; + ContainerChest cc = (ContainerChest) eventGui.inventorySlots; + IInventory lower = cc.getLowerChestInventory(); + + if (lower.getStackInSlot(23) != null && + lower.getStackInSlot(23).getDisplayName().endsWith("Crafting Table")) { + ItemStack res = lower.getStackInSlot(25); + String resInternalname = neu.manager.getInternalNameForItem(res); + JTextField tf = new JTextField(); + tf.setText(resInternalname); + tf.addAncestorListener(new RequestFocusListener()); + JOptionPane.showOptionDialog(null, + tf, + "Enter Name:", + JOptionPane.NO_OPTION, + JOptionPane.PLAIN_MESSAGE, + null, new String[]{"Enter"}, "Enter" + ); + resInternalname = tf.getText(); + if (resInternalname.trim().length() == 0) { + return; + } + + JsonObject recipe = new JsonObject(); + + String[] x = {"1", "2", "3"}; + String[] y = {"A", "B", "C"}; + + for (int i = 0; i <= 18; i += 9) { + for (int j = 0; j < 3; j++) { + ItemStack stack = lower.getStackInSlot(10 + i + j); + String internalname = ""; + if (stack != null) { + internalname = neu.manager.getInternalNameForItem(stack); + if (!neu.manager.getItemInformation().containsKey(internalname)) { + neu.manager.writeItemToFile(stack); + } + internalname += ":" + stack.stackSize; + } + recipe.addProperty(y[i / 9] + x[j], internalname); + } + } + + JsonObject json = neu.manager.getJsonForItem(res); + json.add("recipe", recipe); + json.addProperty("internalname", resInternalname); + json.addProperty("clickcommand", "viewrecipe"); + json.addProperty("modver", NotEnoughUpdates.VERSION); + try { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("Added: " + resInternalname)); + neu.manager.writeJsonDefaultDir(json, resInternalname + ".json"); + neu.manager.loadItem(resInternalname); + } catch (IOException ignored) { + } + } + } + } + } + + private final HashSet percentStats = new HashSet<>(); + + { + percentStats.add("bonus_attack_speed"); + percentStats.add("crit_damage"); + percentStats.add("crit_chance"); + percentStats.add("sea_creature_chance"); + percentStats.add("ability_damage"); + } + + private String currentRarity = "COMMON"; + private boolean showReforgeStoneStats = true; + private boolean pressedArrowLast = false; + private boolean pressedShiftLast = false; + + private boolean copied = false; + + //just to try and optimize it a bit + private int sbaloaded = -1; + + private boolean isSbaloaded() { + if (sbaloaded == -1) { + if (Loader.isModLoaded("skyblockaddons")) { + sbaloaded = 1; + } else { + sbaloaded = 0; + } + } + return sbaloaded == 1; + } + + @SubscribeEvent(priority = EventPriority.LOW) + public void onItemTooltipLow(ItemTooltipEvent event) { + if (!NotEnoughUpdates.INSTANCE.isOnSkyblock()) return; + + String internalname = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(event.itemStack); + if (internalname == null) { + onItemToolTipInternalNameNull(event); + return; + } + + boolean hasEnchantments = + event.itemStack.getTagCompound().getCompoundTag("ExtraAttributes").hasKey("enchantments", 10); + Set enchantIds = new HashSet<>(); + if (hasEnchantments) + enchantIds = + event.itemStack.getTagCompound().getCompoundTag("ExtraAttributes").getCompoundTag("enchantments").getKeySet(); + + JsonObject enchantsConst = Constants.ENCHANTS; + JsonArray allItemEnchs = null; + Set ignoreFromPool = new HashSet<>(); + if (enchantsConst != null && hasEnchantments && NotEnoughUpdates.INSTANCE.config.tooltipTweaks.missingEnchantList) { + try { + JsonArray enchantPools = enchantsConst.get("enchant_pools").getAsJsonArray(); + for (JsonElement element : enchantPools) { + Set currentPool = new HashSet<>(); + for (JsonElement poolElement : element.getAsJsonArray()) { + String poolS = poolElement.getAsString(); + currentPool.add(poolS); + } + for (JsonElement poolElement : element.getAsJsonArray()) { + String poolS = poolElement.getAsString(); + if (enchantIds.contains(poolS)) { + ignoreFromPool.addAll(currentPool); + break; + } + } + } + + JsonObject enchantsObj = enchantsConst.get("enchants").getAsJsonObject(); + NBTTagCompound tag = event.itemStack.getTagCompound(); + if (tag != null) { + NBTTagCompound display = tag.getCompoundTag("display"); + if (display.hasKey("Lore", 9)) { + NBTTagList list = display.getTagList("Lore", 8); + out: + for (int i = list.tagCount(); i >= 0; i--) { + String line = list.getStringTagAt(i); + for (int j = 0; j < Utils.rarityArrC.length; j++) { + for (Map.Entry entry : enchantsObj.entrySet()) { + if (line.contains(Utils.rarityArrC[j] + " " + entry.getKey()) || + line.contains(Utils.rarityArrC[j] + " DUNGEON " + entry.getKey())) { + allItemEnchs = entry.getValue().getAsJsonArray(); + break out; + } + } + } + } + } + } + } catch (Exception ignored) { + } + } + + boolean gotToEnchants = false; + boolean passedEnchants = false; + + boolean dungeonProfit = false; + int index = 0; + List newTooltip = new ArrayList<>(); + + for (String line : event.toolTip) { + if (line.endsWith(EnumChatFormatting.DARK_GRAY + "Reforge Stone") && + NotEnoughUpdates.INSTANCE.config.tooltipTweaks.showReforgeStats) { + JsonObject reforgeStones = Constants.REFORGESTONES; + + if (reforgeStones != null && reforgeStones.has(internalname)) { + boolean shift = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT); + if (!pressedShiftLast && shift) { + showReforgeStoneStats = !showReforgeStoneStats; + } + pressedShiftLast = shift; + + newTooltip.add(line); + newTooltip.add(""); + if (!showReforgeStoneStats) { + newTooltip.add(EnumChatFormatting.DARK_GRAY + "[Press SHIFT to show extra info]"); + } else { + newTooltip.add(EnumChatFormatting.DARK_GRAY + "[Press SHIFT to hide extra info]"); + } + + JsonObject reforgeInfo = reforgeStones.get(internalname).getAsJsonObject(); + JsonArray requiredRaritiesArray = reforgeInfo.get("requiredRarities").getAsJsonArray(); + + if (showReforgeStoneStats && requiredRaritiesArray.size() > 0) { + String reforgeName = Utils.getElementAsString(reforgeInfo.get("reforgeName"), ""); + + String[] requiredRarities = new String[requiredRaritiesArray.size()]; + for (int i = 0; i < requiredRaritiesArray.size(); i++) { + requiredRarities[i] = requiredRaritiesArray.get(i).getAsString(); + } + + int rarityIndex = requiredRarities.length - 1; + String rarity = requiredRarities[rarityIndex]; + for (int i = 0; i < requiredRarities.length; i++) { + String rar = requiredRarities[i]; + if (rar.equalsIgnoreCase(currentRarity)) { + rarity = rar; + rarityIndex = i; + break; + } + } + + boolean left = Keyboard.isKeyDown(Keyboard.KEY_LEFT); + boolean right = Keyboard.isKeyDown(Keyboard.KEY_RIGHT); + if (!pressedArrowLast && (left || right)) { + if (left) { + rarityIndex--; + } else if (right) { + rarityIndex++; + } + if (rarityIndex < 0) rarityIndex = 0; + if (rarityIndex >= requiredRarities.length) rarityIndex = requiredRarities.length - 1; + currentRarity = requiredRarities[rarityIndex]; + rarity = currentRarity; + } + pressedArrowLast = left || right; + + JsonElement statsE = reforgeInfo.get("reforgeStats"); + + String rarityFormatted = Utils.rarityArrMap.getOrDefault(rarity, rarity); + + JsonElement reforgeAbilityE = reforgeInfo.get("reforgeAbility"); + String reforgeAbility = null; + if (reforgeAbilityE != null) { + if (reforgeAbilityE.isJsonPrimitive() && reforgeAbilityE.getAsJsonPrimitive().isString()) { + reforgeAbility = Utils.getElementAsString(reforgeInfo.get("reforgeAbility"), ""); + + } else if (reforgeAbilityE.isJsonObject()) { + if (reforgeAbilityE.getAsJsonObject().has(rarity)) { + reforgeAbility = reforgeAbilityE.getAsJsonObject().get(rarity).getAsString(); + } + } + } + + if (reforgeAbility != null && !reforgeAbility.isEmpty()) { + String text = EnumChatFormatting.BLUE + (reforgeName.isEmpty() ? "Bonus: " : reforgeName + " Bonus: ") + + EnumChatFormatting.GRAY + reforgeAbility; + boolean first = true; + for (String s : Minecraft.getMinecraft().fontRendererObj.listFormattedStringToWidth(text, 150)) { + newTooltip.add((first ? "" : " ") + s); + first = false; + } + newTooltip.add(""); + } + + newTooltip.add(EnumChatFormatting.BLUE + "Stats for " + rarityFormatted + + "\u00a79: [\u00a7l\u00a7m< \u00a79Switch\u00a7l\u27a1\u00a79]"); + + if (statsE != null && statsE.isJsonObject()) { + JsonObject stats = statsE.getAsJsonObject(); + + JsonElement statsRarE = stats.get(rarity); + if (statsRarE != null && statsRarE.isJsonObject()) { + + JsonObject statsRar = statsRarE.getAsJsonObject(); + + TreeSet> sorted = new TreeSet<>(Map.Entry.comparingByKey()); + sorted.addAll(statsRar.entrySet()); + + for (Map.Entry entry : sorted) { + if (entry.getValue().isJsonPrimitive() && ((JsonPrimitive) entry.getValue()).isNumber()) { + float statNumF = entry.getValue().getAsFloat(); + String statNumS; + if (statNumF % 1 == 0) { + statNumS = String.valueOf(Math.round(statNumF)); + } else { + statNumS = Utils.floatToString(statNumF, 1); + } + String reforgeNamePretty = WordUtils.capitalizeFully(entry.getKey().replace("_", " ")); + String text = + EnumChatFormatting.GRAY + reforgeNamePretty + ": " + EnumChatFormatting.GREEN + "+" + statNumS; + if (percentStats.contains(entry.getKey())) { + text += "%"; + } + newTooltip.add(" " + text); + } + } + } + } + + JsonElement reforgeCostsE = reforgeInfo.get("reforgeCosts"); + int reforgeCost = -1; + if (reforgeCostsE != null) { + if (reforgeCostsE.isJsonPrimitive() && reforgeCostsE.getAsJsonPrimitive().isNumber()) { + reforgeCost = (int) Utils.getElementAsFloat(reforgeInfo.get("reforgeAbility"), -1); + + } else if (reforgeCostsE.isJsonObject()) { + if (reforgeCostsE.getAsJsonObject().has(rarity)) { + reforgeCost = (int) Utils.getElementAsFloat(reforgeCostsE.getAsJsonObject().get(rarity), -1); + } + } + } + + if (reforgeCost >= 0) { + String text = EnumChatFormatting.BLUE + "Apply Cost: " + EnumChatFormatting.GOLD + + NumberFormat.getNumberInstance().format(reforgeCost) + " coins"; + newTooltip.add(""); + newTooltip.add(text); + } + + } + + continue; + } + + } else if (line.contains("\u00A7cR\u00A76a\u00A7ei\u00A7an\u00A7bb\u00A79o\u00A7dw\u00A79 Rune")) { + line = line.replace( + "\u00A7cR\u00A76a\u00A7ei\u00A7an\u00A7bb\u00A79o\u00A7dw\u00A79 Rune", + Utils.chromaString("Rainbow Rune", index, false) + EnumChatFormatting.BLUE + ); + } else if (hasEnchantments) { + if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) && + NotEnoughUpdates.INSTANCE.config.tooltipTweaks.missingEnchantList) { + boolean lineHasEnch = false; + for (String s : enchantIds) { + String enchantName = WordUtils.capitalizeFully(s.replace("_", " ")); + if (line.contains(enchantName)) { + lineHasEnch = true; + break; + } + } + if (lineHasEnch) { + gotToEnchants = true; + } else { + if (gotToEnchants && !passedEnchants && Utils.cleanColour(line).trim().length() == 0) { + if (enchantsConst != null && allItemEnchs != null) { + List missing = new ArrayList<>(); + for (JsonElement enchIdElement : allItemEnchs) { + String enchId = enchIdElement.getAsString(); + if (!enchId.startsWith("ultimate_") && !ignoreFromPool.contains(enchId) && + !enchantIds.contains(enchId)) { + missing.add(enchId); + } + } + if (!missing.isEmpty()) { + newTooltip.add(""); + StringBuilder currentLine = + new StringBuilder(EnumChatFormatting.RED + "Missing: " + EnumChatFormatting.GRAY); + for (int i = 0; i < missing.size(); i++) { + String enchName = WordUtils.capitalizeFully(missing.get(i).replace("_", " ")); + if (currentLine.length() != 0 && + (Utils.cleanColour(currentLine.toString()).length() + enchName.length()) > 40) { + newTooltip.add(currentLine.toString()); + currentLine = new StringBuilder(); + } + if (currentLine.length() != 0 && i != 0) { + currentLine.append(", ").append(enchName); + } else { + currentLine.append(EnumChatFormatting.GRAY).append(enchName); + } + } + if (currentLine.length() != 0) { + newTooltip.add(currentLine.toString()); + } + } + } + passedEnchants = true; + } + } + } + for (String op : NotEnoughUpdates.INSTANCE.config.hidden.enchantColours) { + List colourOps = GuiEnchantColour.splitter.splitToList(op); + String enchantName = GuiEnchantColour.getColourOpIndex(colourOps, 0); + String comparator = GuiEnchantColour.getColourOpIndex(colourOps, 1); + String comparison = GuiEnchantColour.getColourOpIndex(colourOps, 2); + String colourCode = GuiEnchantColour.getColourOpIndex(colourOps, 3); + String modifier = GuiEnchantColour.getColourOpIndex(colourOps, 4); + + int modifierI = GuiEnchantColour.getIntModifier(modifier); + + if (enchantName.length() == 0) continue; + if (comparator.length() == 0) continue; + if (comparison.length() == 0) continue; + if (colourCode.length() == 0) continue; + + int comparatorI = ">=<".indexOf(comparator.charAt(0)); + + int levelToFind = -1; + try { + levelToFind = Integer.parseInt(comparison); + } catch (Exception e) { + continue; + } + + if (comparatorI < 0) continue; + String regexText = "0123456789abcdefz"; + if (isSbaloaded()) { + regexText = regexText + "Z"; + } + + if (regexText.indexOf(colourCode.charAt(0)) < 0) continue; + + //item_lore = item_lore.replaceAll("\\u00A79("+lvl4Max+" IV)", EnumChatFormatting.DARK_PURPLE+"$1"); + //9([a-zA-Z ]+?) ([0-9]+|(I|II|III|IV|V|VI|VII|VIII|IX|X))(,|$) + Pattern pattern; + try { + pattern = Pattern.compile("(\\u00A79|\\u00A7(9|l)\\u00A7d\\u00A7l)(?" + enchantName + ") " + + "(?[0-9]+|(I|II|III|IV|V|VI|VII|VIII|IX|X|XI|XII|XIII|XIV|XV|XVI|XVII|XVIII|XIX|XX))((\\u00A79)?,|( \\u00A78(?:,?[0-9]+)*)?$)"); + } catch (Exception e) { + continue; + } //malformed regex + Matcher matcher = pattern.matcher(line); + int matchCount = 0; + while (matcher.find() && matchCount < 5) { + if (Utils.cleanColour(matcher.group("enchantName")).startsWith(" ")) continue; + + matchCount++; + int level = -1; + String levelStr = matcher.group("level"); + if (levelStr == null) continue; + try { + level = Integer.parseInt(levelStr); + } catch (Exception e) { + switch (levelStr) { + case "I": + level = 1; + break; + case "II": + level = 2; + break; + case "III": + level = 3; + break; + case "IV": + level = 4; + break; + case "V": + level = 5; + break; + case "VI": + level = 6; + break; + case "VII": + level = 7; + break; + case "VIII": + level = 8; + break; + case "IX": + level = 9; + break; + case "X": + level = 10; + break; + case "XI": + level = 11; + break; + case "XII": + level = 12; + break; + case "XIII": + level = 13; + break; + case "XIV": + level = 14; + break; + case "XV": + level = 15; + break; + case "XVI": + level = 16; + break; + case "XVII": + level = 17; + break; + case "XVIII": + level = 18; + break; + case "XIX": + level = 19; + break; + case "XX": + level = 20; + break; + } + } + boolean matches = false; + if (level > 0) { + switch (comparator) { + case ">": + matches = level > levelToFind; + break; + case "=": + matches = level == levelToFind; + break; + case "<": + matches = level < levelToFind; + break; + } + } + if (matches) { + String enchantText = matcher.group("enchantName"); + StringBuilder extraModifiersBuilder = new StringBuilder(); + + if ((modifierI & GuiEnchantColour.BOLD_MODIFIER) != 0) { + extraModifiersBuilder.append(EnumChatFormatting.BOLD); + } + if ((modifierI & GuiEnchantColour.ITALIC_MODIFIER) != 0) { + extraModifiersBuilder.append(EnumChatFormatting.ITALIC); + } + if ((modifierI & GuiEnchantColour.UNDERLINE_MODIFIER) != 0) { + extraModifiersBuilder.append(EnumChatFormatting.UNDERLINE); + } + if ((modifierI & GuiEnchantColour.OBFUSCATED_MODIFIER) != 0) { + extraModifiersBuilder.append(EnumChatFormatting.OBFUSCATED); + } + if ((modifierI & GuiEnchantColour.STRIKETHROUGH_MODIFIER) != 0) { + extraModifiersBuilder.append(EnumChatFormatting.STRIKETHROUGH); + } + + String extraMods = extraModifiersBuilder.toString(); + + if (!colourCode.equals("z")) { + line = line.replace( + "\u00A79" + enchantText, + "\u00A7" + colourCode + extraMods + enchantText + ); + line = line.replace( + "\u00A79\u00A7d\u00A7l" + enchantText, + "\u00A7" + colourCode + extraMods + enchantText + ); + line = line.replace( + "\u00A7l\u00A7d\u00A7l" + enchantText, + "\u00A7" + colourCode + extraMods + enchantText + ); + } else { + int offset = Minecraft.getMinecraft().fontRendererObj.getStringWidth(line.replaceAll( + "\\u00A79" + enchantText + ".*", "")); + line = + line.replace("\u00A79" + enchantText, Utils.chromaString(enchantText, offset / 12f + index, false)); + + offset = Minecraft.getMinecraft().fontRendererObj.getStringWidth(line.replaceAll( + "\\u00A79\\u00A7d\\u00A7l" + enchantText + ".*", "")); + line = line.replace("\u00A79\u00A7d\u00A7l" + enchantText, Utils.chromaString(enchantText, + offset / 12f + index, true + )); + offset = Minecraft.getMinecraft().fontRendererObj.getStringWidth(line.replaceAll( + "\\u00A7l\\u00A7d\\u00A7l" + enchantText + ".*", "")); + line = line.replace("\u00A7l\u00A7d\u00A7l" + enchantText, Utils.chromaString(enchantText, + offset / 12f + index, true + )); + } + } + } + } + } + + newTooltip.add(line); + + if (NotEnoughUpdates.INSTANCE.config.tooltipTweaks.showPriceInfoAucItem) { + if (line.contains(EnumChatFormatting.GRAY + "Buy it now: ") || + line.contains(EnumChatFormatting.GRAY + "Bidder: ") || + line.contains(EnumChatFormatting.GRAY + "Starting bid: ")) { + + if (!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) && !Keyboard.isKeyDown(Keyboard.KEY_RSHIFT)) { + newTooltip.add(""); + newTooltip.add(EnumChatFormatting.GRAY + "[SHIFT for Price Info]"); + } else { + ItemPriceInformation.addToTooltip(newTooltip, internalname, event.itemStack); + } + } + } + + if (NotEnoughUpdates.INSTANCE.config.dungeons.profitDisplayLoc == 2 && + Minecraft.getMinecraft().currentScreen instanceof GuiChest) { + if (line.contains(EnumChatFormatting.GREEN + "Open Reward Chest")) { + dungeonProfit = true; + } else if (index == 7 && dungeonProfit) { + GuiChest eventGui = (GuiChest) Minecraft.getMinecraft().currentScreen; + ContainerChest cc = (ContainerChest) eventGui.inventorySlots; + IInventory lower = cc.getLowerChestInventory(); + + int chestCost = 0; + try { + String line6 = Utils.cleanColour(line); + StringBuilder cost = new StringBuilder(); + for (int i = 0; i < line6.length(); i++) { + char c = line6.charAt(i); + if ("0123456789".indexOf(c) >= 0) { + cost.append(c); + } + } + if (cost.length() > 0) { + chestCost = Integer.parseInt(cost.toString()); + } + } catch (Exception ignored) { + } + + String missingItem = null; + int totalValue = 0; + HashMap itemValues = new HashMap<>(); + for (int i = 0; i < 5; i++) { + ItemStack item = lower.getStackInSlot(11 + i); + String internal = neu.manager.getInternalNameForItem(item); + if (internal != null) { + internal = internal.replace("\u00CD", "I").replace("\u0130", "I"); + float bazaarPrice = -1; + JsonObject bazaarInfo = neu.manager.auctionManager.getBazaarInfo(internal); + if (bazaarInfo != null && bazaarInfo.has("curr_sell")) { + bazaarPrice = bazaarInfo.get("curr_sell").getAsFloat(); + } + if (bazaarPrice < 5000000 && internal.equals("RECOMBOBULATOR_3000")) bazaarPrice = 5000000; + + float worth = -1; + if (bazaarPrice > 0) { + worth = bazaarPrice; + } else { + switch (NotEnoughUpdates.INSTANCE.config.dungeons.profitType) { + case 1: + worth = neu.manager.auctionManager.getItemAvgBin(internal); + break; + case 2: + JsonObject auctionInfo = neu.manager.auctionManager.getItemAuctionInfo(internal); + if (auctionInfo != null) { + if (auctionInfo.has("clean_price")) { + worth = (int) auctionInfo.get("clean_price").getAsFloat(); + } else { + worth = (int) (auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat()); + } + } + break; + default: + worth = neu.manager.auctionManager.getLowestBin(internal); + } + if (worth <= 0) { + worth = neu.manager.auctionManager.getLowestBin(internal); + if (worth <= 0) { + worth = neu.manager.auctionManager.getItemAvgBin(internal); + if (worth <= 0) { + JsonObject auctionInfo = neu.manager.auctionManager.getItemAuctionInfo(internal); + if (auctionInfo != null) { + if (auctionInfo.has("clean_price")) { + worth = (int) auctionInfo.get("clean_price").getAsFloat(); + } else { + worth = (int) (auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat()); + } + } + } + } + } + } + + if (worth > 0 && totalValue >= 0) { + totalValue += worth; + + String display = item.getDisplayName(); + + if (display.contains("Enchanted Book")) { + NBTTagCompound tag = item.getTagCompound(); + if (tag != null && tag.hasKey("ExtraAttributes", 10)) { + NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes"); + NBTTagCompound enchants = ea.getCompoundTag("enchantments"); + + int highestLevel = -1; + for (String enchname : enchants.getKeySet()) { + int level = enchants.getInteger(enchname); + if (level > highestLevel) { + display = EnumChatFormatting.BLUE + WordUtils.capitalizeFully( + enchname.replace("_", " ") + .replace("Ultimate", "") + .trim()) + " " + level; + } + } + } + } + + itemValues.put(display, worth); + } else { + if (totalValue != -1) { + missingItem = internal; + } + totalValue = -1; + } + } + } + + NumberFormat format = NumberFormat.getInstance(Locale.US); + String valueStringBIN1; + String valueStringBIN2; + if (totalValue >= 0) { + valueStringBIN1 = EnumChatFormatting.YELLOW + "Value (BIN): "; + valueStringBIN2 = EnumChatFormatting.GOLD + format.format(totalValue) + " coins"; + } else { + valueStringBIN1 = EnumChatFormatting.YELLOW + "Can't find BIN: "; + valueStringBIN2 = missingItem; + } + + int profitLossBIN = totalValue - chestCost; + String profitPrefix = EnumChatFormatting.DARK_GREEN.toString(); + String lossPrefix = EnumChatFormatting.RED.toString(); + String prefix = profitLossBIN >= 0 ? profitPrefix : lossPrefix; + + String plStringBIN; + if (profitLossBIN >= 0) { + plStringBIN = prefix + "+" + format.format(profitLossBIN) + " coins"; + } else { + plStringBIN = prefix + "-" + format.format(-profitLossBIN) + " coins"; + } + + String neu = EnumChatFormatting.YELLOW + "[NEU] "; + + newTooltip.add(neu + valueStringBIN1 + " " + valueStringBIN2); + if (totalValue >= 0) { + newTooltip.add(neu + EnumChatFormatting.YELLOW + "Profit/Loss: " + plStringBIN); + } + + for (Map.Entry entry : itemValues.entrySet()) { + newTooltip.add(neu + entry.getKey() + prefix + "+" + + format.format(entry.getValue().intValue())); + } + } + } + + index++; + } + + for (int i = newTooltip.size() - 1; i >= 0; i--) { + String line = Utils.cleanColour(newTooltip.get(i)); + for (int i1 = 0; i1 < Utils.rarityArr.length; i1++) { + if (line.equals(Utils.rarityArr[i1])) { + if (i - 2 < 0) { + break; + } + newTooltip.addAll(i - 1, petToolTipXPExtend(event)); + break; + } + } + } + + pressedShiftLast = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT); + pressedArrowLast = Keyboard.isKeyDown(Keyboard.KEY_LEFT) || Keyboard.isKeyDown(Keyboard.KEY_RIGHT); + + event.toolTip.clear(); + event.toolTip.addAll(newTooltip); + + HashMap> loreBuckets = new HashMap<>(); + + List hypixelOrder = new ArrayList<>(); + + hypixelOrder.add("attributes"); + hypixelOrder.add("enchants"); + hypixelOrder.add("ability"); + hypixelOrder.add("reforge_bonus"); + hypixelOrder.add("rarity"); + + if (NotEnoughUpdates.INSTANCE.config.tooltipTweaks.showPriceInfoInvItem) { + ItemPriceInformation.addToTooltip(event.toolTip, internalname, event.itemStack); + } + + if (event.itemStack.getTagCompound() != null && event.itemStack.getTagCompound().getBoolean("NEUHIDEPETTOOLTIP") && + NotEnoughUpdates.INSTANCE.config.petOverlay.hidePetTooltip) { + event.toolTip.clear(); + } + } + + private final Pattern xpLevelPattern = Pattern.compile("(.*) (\\xA7e(.*)\\xA76/\\xA7e(.*))"); + + private void onItemToolTipInternalNameNull(ItemTooltipEvent event) { + petToolTipXPExtendPetMenu(event); + } + + private List petToolTipXPExtend(ItemTooltipEvent event) { + List tooltipText = new ArrayList<>(); + if (NotEnoughUpdates.INSTANCE.config.tooltipTweaks.petExtendExp) { + if (event.itemStack.getTagCompound().hasKey("DisablePetExp")) { + if (event.itemStack.getTagCompound().getBoolean("DisablePetExp")) { + return tooltipText; + } + } + //7 is just a random number i chose, prob no pets with less lines than 7 + if (event.toolTip.size() > 7) { + if (Utils.cleanColour(event.toolTip.get(1)).matches(petToolTipRegex)) { + + GuiProfileViewer.PetLevel petlevel = null; + + //this is the item itself + NBTTagCompound tag = event.itemStack.getTagCompound(); + if (tag.hasKey("ExtraAttributes")) { + if (tag.getCompoundTag("ExtraAttributes").hasKey("petInfo")) { + JsonObject petInfo = NotEnoughUpdates.INSTANCE.manager.gson.fromJson( + tag.getCompoundTag("ExtraAttributes").getString("petInfo"), JsonObject.class); + if (petInfo.has("exp") && petInfo.get("exp").isJsonPrimitive()) { + JsonPrimitive exp = petInfo.getAsJsonPrimitive("exp"); + String petName = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(event.itemStack); + //Utils.getRarityFromInt(Utils.checkItemTypePet(event.toolTip))).getAsInt(); + petlevel = GuiProfileViewer.getPetLevel( + petName, + Utils.getRarityFromInt(Utils.checkItemTypePet(event.toolTip)), + exp.getAsLong() + ); + } + } + } + + if (petlevel != null) { + tooltipText.add(""); + if (petlevel.totalXp > petlevel.maxXP) { + tooltipText.add(EnumChatFormatting.AQUA + "" + EnumChatFormatting.BOLD + "MAX LEVEL"); + } else { + tooltipText.add( + EnumChatFormatting.GRAY + "Progress to Level " + (int) Math.floor(petlevel.level + 1) + ": " + + EnumChatFormatting.YELLOW + Utils.round(petlevel.levelPercentage * 100, 1) + "%"); + int levelpercentage = Math.round(petlevel.levelPercentage * 20); + tooltipText.add( + EnumChatFormatting.DARK_GREEN + String.join("", Collections.nCopies(levelpercentage, "-")) + + EnumChatFormatting.WHITE + String.join("", Collections.nCopies(20 - levelpercentage, "-"))); + tooltipText.add( + EnumChatFormatting.GRAY + "EXP: " + EnumChatFormatting.YELLOW + myFormatter.format(petlevel.levelXp) + + EnumChatFormatting.GOLD + "/" + EnumChatFormatting.YELLOW + + myFormatter.format(petlevel.currentLevelRequirement) + " EXP"); + } + } + } + } + } + return tooltipText; + } + + private static final String petToolTipRegex = + "((Farming)|(Combat)|(Fishing)|(Mining)|(Foraging)|(Enchanting)|(Alchemy)) ((Mount)|(Pet)|(Morph)).*"; + + private void petToolTipXPExtendPetMenu(ItemTooltipEvent event) { + if (NotEnoughUpdates.INSTANCE.config.tooltipTweaks.petExtendExp) { + //7 is just a random number i chose, prob no pets with less lines than 7 + if (event.toolTip.size() > 7) { + if (Utils.cleanColour(event.toolTip.get(1)).matches(petToolTipRegex)) { + GuiProfileViewer.PetLevel petlevel = null; + + int xpLine = -1; + for (int i = event.toolTip.size() - 1; i >= 0; i--) { + Matcher matcher = xpLevelPattern.matcher(event.toolTip.get(i)); + if (matcher.matches()) { + xpLine = i; + event.toolTip.set(xpLine, matcher.group(1)); + break; + } else if (event.toolTip.get(i).matches("MAX LEVEL")) { + return; + } + } + + PetInfoOverlay.Pet pet = PetInfoOverlay.getPetFromStack( + event.itemStack.getDisplayName(), + NotEnoughUpdates.INSTANCE.manager.getLoreFromNBT(event.itemStack.getTagCompound()) + ); + if (pet == null) { + return; + } + petlevel = pet.petLevel; + + if (petlevel == null || xpLine == -1) { + return; + } + + event.toolTip.add( + xpLine + 1, + EnumChatFormatting.GRAY + "EXP: " + EnumChatFormatting.YELLOW + myFormatter.format(petlevel.levelXp) + + EnumChatFormatting.GOLD + "/" + EnumChatFormatting.YELLOW + + myFormatter.format(petlevel.currentLevelRequirement) + ); + + } + } + } + } + + DecimalFormat myFormatter = new DecimalFormat("###,###.###"); + + /** + * This method does the following: + * Move the pet inventory display tooltip to the left to avoid conflicts + * Remove reforge stats for Legendary items from Hypixel if enabled + * Show NBT data when holding LCONTROL + */ + @SubscribeEvent + public void onItemTooltip(ItemTooltipEvent event) { + if (!neu.isOnSkyblock()) return; + if (event.toolTip == null) return; + //Render the pet inventory display tooltip to the left to avoid things from other mods rendering over the tooltip + if (event.itemStack.getTagCompound() != null && event.itemStack.getTagCompound().getBoolean("NEUPETINVDISPLAY")) { + GlStateManager.translate(-200, 0, 0); + } + + if (event.toolTip.size() > 2 && NotEnoughUpdates.INSTANCE.config.tooltipTweaks.hideDefaultReforgeStats) { + String secondLine = StringUtils.stripControlCodes(event.toolTip.get(1)); + if (secondLine.equals("Reforge Stone")) { + Integer startIndex = null; + Integer cutoffIndex = null; + //loop from the back of the List to find the wanted index sooner + for (int i = event.toolTip.size() - 1; i >= 0; i--) { + //rarity or mining level requirement + String line = StringUtils.stripControlCodes(event.toolTip.get(i)); + if (line.contains("REFORGE STONE") || line.contains("Requires Mining Skill Level")) { + cutoffIndex = i; + } + + //The line where the Hypixel stats start + if (line.contains("(Legendary):")) { + startIndex = i; + break; + } + } + if (startIndex != null && cutoffIndex != null && startIndex < cutoffIndex) { + event.toolTip.subList(startIndex, cutoffIndex).clear(); + } + } + } + + if (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) && NotEnoughUpdates.INSTANCE.config.hidden.dev && + event.toolTip.size() > 0 && + event.toolTip.get(event.toolTip.size() - 1).startsWith(EnumChatFormatting.DARK_GRAY + "NBT: ")) { + event.toolTip.remove(event.toolTip.size() - 1); + + StringBuilder sb = new StringBuilder(); + String nbt = event.itemStack.getTagCompound().toString(); + int indent = 0; + for (char c : nbt.toCharArray()) { + boolean newline = false; + if (c == '{' || c == '[') { + indent++; + newline = true; + } else if (c == '}' || c == ']') { + indent--; + sb.append("\n"); + for (int i = 0; i < indent; i++) sb.append(" "); + } else if (c == ',') { + newline = true; + } else if (c == '\"') { + sb.append(EnumChatFormatting.RESET.toString() + EnumChatFormatting.GRAY); + } + + sb.append(c); + if (newline) { + sb.append("\n"); + for (int i = 0; i < indent; i++) sb.append(" "); + } + } + event.toolTip.add(sb.toString()); + if (Keyboard.isKeyDown(Keyboard.KEY_H)) { + if (!copied) { + copied = true; + StringSelection selection = new StringSelection(sb.toString()); + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(selection, selection); + } + } else { + copied = false; + } + } else if (NotEnoughUpdates.INSTANCE.packDevEnabled) { + event.toolTip.add(""); + event.toolTip.add(EnumChatFormatting.AQUA + "NEU Pack Dev Info:"); + event.toolTip.add("Press " + EnumChatFormatting.GOLD + "[KEY]" + EnumChatFormatting.GRAY + " to copy line"); + + String internal = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(event.itemStack); + + boolean k = Keyboard.isKeyDown(Keyboard.KEY_K); + boolean m = Keyboard.isKeyDown(Keyboard.KEY_M); + boolean n = Keyboard.isKeyDown(Keyboard.KEY_N); + + event.toolTip.add( + EnumChatFormatting.AQUA + "Internal Name: " + EnumChatFormatting.GRAY + internal + EnumChatFormatting.GOLD + + " [K]"); + if (!copied && k) { + MiscUtils.copyToClipboard(internal); + } + + if (event.itemStack.getTagCompound() != null) { + NBTTagCompound tag = event.itemStack.getTagCompound(); + + if (tag.hasKey("SkullOwner", 10)) { + GameProfile gameprofile = NBTUtil.readGameProfileFromNBT(tag.getCompoundTag("SkullOwner")); + + if (gameprofile != null) { + event.toolTip.add(EnumChatFormatting.AQUA + "Skull UUID: " + EnumChatFormatting.GRAY + gameprofile.getId() + + EnumChatFormatting.GOLD + " [M]"); + if (!copied && m) { + MiscUtils.copyToClipboard(gameprofile.getId().toString()); + } + + Map map = + Minecraft.getMinecraft().getSkinManager().loadSkinFromCache(gameprofile); + + if (map.containsKey(MinecraftProfileTexture.Type.SKIN)) { + MinecraftProfileTexture profTex = map.get(MinecraftProfileTexture.Type.SKIN); + event.toolTip.add( + EnumChatFormatting.AQUA + "Skull Texture Link: " + EnumChatFormatting.GRAY + profTex.getUrl() + + EnumChatFormatting.GOLD + " [N]"); + + if (!copied && n) { + MiscUtils.copyToClipboard(profTex.getUrl()); + } + } + } + } + } + + copied = k || m || n; + } + } + + @SubscribeEvent + public void onRenderLast(RenderWorldLastEvent event) { + CrystalMetalDetectorSolver.render(event.partialTicks); + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java index 5fef4c62e6..df31834f99 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java @@ -1,14 +1,14 @@ package io.github.moulberry.notenoughupdates; -import com.google.common.collect.Lists; import com.google.gson.*; import io.github.moulberry.notenoughupdates.auction.APIManager; import io.github.moulberry.notenoughupdates.miscgui.GuiItemRecipe; -import io.github.moulberry.notenoughupdates.overlays.CraftingOverlay; -import io.github.moulberry.notenoughupdates.util.Constants; -import io.github.moulberry.notenoughupdates.util.HypixelApi; -import io.github.moulberry.notenoughupdates.util.SBInfo; -import io.github.moulberry.notenoughupdates.util.Utils; +import io.github.moulberry.notenoughupdates.miscgui.KatSitterOverlay; +import io.github.moulberry.notenoughupdates.recipes.CraftingOverlay; +import io.github.moulberry.notenoughupdates.recipes.CraftingRecipe; +import io.github.moulberry.notenoughupdates.recipes.Ingredient; +import io.github.moulberry.notenoughupdates.recipes.NeuRecipe; +import io.github.moulberry.notenoughupdates.util.*; import net.minecraft.client.Minecraft; import net.minecraft.client.settings.KeyBinding; import net.minecraft.init.Blocks; @@ -17,113 +17,153 @@ import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.*; -import net.minecraft.network.play.client.C0DPacketCloseWindow; import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.common.ProgressManager; import org.apache.commons.io.FileUtils; import org.lwjgl.input.Keyboard; import org.lwjgl.opengl.Display; -import javax.swing.*; +import javax.swing.JDialog; +import javax.swing.JOptionPane; import java.io.*; import java.net.URL; import java.net.URLConnection; import java.nio.charset.StandardCharsets; import java.util.*; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.stream.Collectors; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; public class NEUManager { - - private final NotEnoughUpdates neu; - public final Gson gson; - public final APIManager auctionManager; - - private TreeMap itemMap = new TreeMap<>(); - - private TreeMap>> titleWordMap = new TreeMap<>(); - private TreeMap>> loreWordMap = new TreeMap<>(); - - public final KeyBinding keybindGive = new KeyBinding("Add item to inventory (Creative-only)", Keyboard.KEY_L, "NotEnoughUpdates"); - public final KeyBinding keybindFavourite = new KeyBinding("Set item as favourite", Keyboard.KEY_F, "NotEnoughUpdates"); - public final KeyBinding keybindViewUsages = new KeyBinding("Show usages for item", Keyboard.KEY_U, "NotEnoughUpdates"); - public final KeyBinding keybindViewRecipe = new KeyBinding("Show recipe for item", Keyboard.KEY_R, "NotEnoughUpdates"); - public final KeyBinding keybindToggleDisplay = new KeyBinding("Toggle NEU overlay", 0, "NotEnoughUpdates"); - public final KeyBinding keybindClosePanes = new KeyBinding("Close NEU panes", 0, "NotEnoughUpdates"); - public final KeyBinding keybindItemSelect = new KeyBinding("Select Item", -98 /*middle*/, "NotEnoughUpdates"); - public final KeyBinding[] keybinds = new KeyBinding[]{ keybindGive, keybindFavourite, keybindViewUsages, keybindViewRecipe, - keybindToggleDisplay, keybindClosePanes, keybindItemSelect}; - - public String viewItemAttemptID = null; - public long viewItemAttemptTime = 0; - - private String currentProfile = ""; - private String currentProfileBackup = ""; - public final HypixelApi hypixelApi = new HypixelApi(); - - private Map itemstackCache = new HashMap<>(); - - private ExecutorService repoLoaderES = Executors.newSingleThreadExecutor(); - - private static String GIT_COMMITS_URL; - - private HashMap> usagesMap = new HashMap<>(); - - public String latestRepoCommit = null; - - public File configLocation; - public File repoLocation; - public File configFile; - - public NEUManager(NotEnoughUpdates neu, File configLocation) { - this.neu = neu; - this.configLocation = configLocation; - this.auctionManager = new APIManager(this); - GIT_COMMITS_URL = neu.config.hidden.repoCommitsURL; - - gson = new GsonBuilder().setPrettyPrinting().create(); - - this.repoLocation = new File(configLocation, "repo"); - repoLocation.mkdir(); - } - - public void setCurrentProfile(String currentProfile) { - this.currentProfile = currentProfile; - } - - public String getCurrentProfile() { - return SBInfo.getInstance().currentProfile; - } - - public T getJsonFromFile(File file, Class clazz) { - try(BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8))) { - T obj = gson.fromJson(reader, clazz); - return obj; - } catch(Exception e) { return null; } - } - - /** - * Parses a file in to a JsonObject. - */ - public JsonObject getJsonFromFile(File file) { - try(BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8))) { - JsonObject json = gson.fromJson(reader, JsonObject.class); - return json; - } catch(Exception e) { return null; } - } - - public void resetRepo() { - try { Utils.recursiveDelete(new File(configLocation, "repo")); } catch(Exception e) {} - try { new File(configLocation, "currentCommit.json").delete(); } catch(Exception e) {} - } - - /** - * Called when the game is first loaded. Compares the local repository to the github repository and handles - * the downloading of new/updated files. This then calls the "loadItem" method for every item in the local - * repository. - */ - public void loadItemInformation() { + private final NotEnoughUpdates neu; + public final Gson gson; + public final APIManager auctionManager; + + private final TreeMap itemMap = new TreeMap<>(); + + private final TreeMap>> titleWordMap = new TreeMap<>(); + private final TreeMap>> loreWordMap = new TreeMap<>(); + + public final KeyBinding keybindGive = + new KeyBinding("Add item to inventory (Creative-only)", Keyboard.KEY_L, "NotEnoughUpdates"); + public final KeyBinding keybindFavourite = + new KeyBinding("Set item as favourite", Keyboard.KEY_F, "NotEnoughUpdates"); + public final KeyBinding keybindViewUsages = + new KeyBinding("Show usages for item", Keyboard.KEY_U, "NotEnoughUpdates"); + public final KeyBinding keybindViewRecipe = + new KeyBinding("Show recipe for item", Keyboard.KEY_R, "NotEnoughUpdates"); + public final KeyBinding keybindToggleDisplay = new KeyBinding("Toggle NEU overlay", 0, "NotEnoughUpdates"); + public final KeyBinding keybindClosePanes = new KeyBinding("Close NEU panes", 0, "NotEnoughUpdates"); + public final KeyBinding keybindItemSelect = new KeyBinding("Select Item", -98 /*middle*/, "NotEnoughUpdates"); + public final KeyBinding[] keybinds = new KeyBinding[]{ + keybindGive, keybindFavourite, keybindViewUsages, keybindViewRecipe, + keybindToggleDisplay, keybindClosePanes, keybindItemSelect + }; + + public String viewItemAttemptID = null; + public long viewItemAttemptTime = 0; + + private final String currentProfile = ""; + private final String currentProfileBackup = ""; + public final HypixelApi hypixelApi = new HypixelApi(); + + private final Map itemstackCache = new HashMap<>(); + + private final ExecutorService repoLoaderES = Executors.newSingleThreadExecutor(); + + private static String GIT_COMMITS_URL; + + // TODO: private final Map + + private final Set recipes = new HashSet<>(); + private final HashMap> recipesMap = new HashMap<>(); + private final HashMap> usagesMap = new HashMap<>(); + + public String latestRepoCommit = null; + + public File configLocation; + public File repoLocation; + public File configFile; + public HotmInformation hotm; + + public KatSitterOverlay katSitterOverlay; + + public CraftingOverlay craftingOverlay; + + public NEUManager(NotEnoughUpdates neu, File configLocation) { + this.neu = neu; + this.configLocation = configLocation; + this.auctionManager = new APIManager(this); + this.hotm = new HotmInformation(neu); + this.craftingOverlay = new CraftingOverlay(this); + this.katSitterOverlay = new KatSitterOverlay(); + + GIT_COMMITS_URL = neu.config.hidden.repoCommitsURL; + + gson = new GsonBuilder().setPrettyPrinting().create(); + + this.repoLocation = new File(configLocation, "repo"); + repoLocation.mkdir(); + } + + public void setCurrentProfile(String currentProfile) { + SBInfo.getInstance().currentProfile = currentProfile; + } + + public String getCurrentProfile() { + return SBInfo.getInstance().currentProfile; + } + + public T getJsonFromFile(File file, Class clazz) { + try ( + BufferedReader reader = new BufferedReader(new InputStreamReader( + new FileInputStream(file), + StandardCharsets.UTF_8 + )) + ) { + T obj = gson.fromJson(reader, clazz); + return obj; + } catch (Exception e) { + return null; + } + } + + /** + * Parses a file in to a JsonObject. + */ + public JsonObject getJsonFromFile(File file) { + try ( + BufferedReader reader = new BufferedReader(new InputStreamReader( + new FileInputStream(file), + StandardCharsets.UTF_8 + )) + ) { + JsonObject json = gson.fromJson(reader, JsonObject.class); + return json; + } catch (Exception e) { + return null; + } + } + + public void resetRepo() { + try { + Utils.recursiveDelete(new File(configLocation, "repo")); + } catch (Exception ignored) { + } + try { + new File(configLocation, "currentCommit.json").delete(); + } catch (Exception ignored) { + } + } + + /** + * Called when the game is first loaded. Compares the local repository to the github repository and handles the + * downloading of new/updated files. This then calls the "loadItem" method for every item in the local repository. + */ + public void loadItemInformation() { /*File repoFile = new File(configLocation, "repo2"); repoFile.mkdirs(); @@ -155,1297 +195,1377 @@ public void loadItemInformation() { }*/ - repoLoaderES.submit(() -> { - JDialog dialog = null; - try { - if(NotEnoughUpdates.INSTANCE.config.hidden.autoupdate) { - JOptionPane pane = new JOptionPane("Getting items to download from remote repository."); - dialog = pane.createDialog("NotEnoughUpdates Remote Sync"); - dialog.setModal(false); - if(NotEnoughUpdates.INSTANCE.config.hidden.dev) dialog.setVisible(true); - - if (Display.isActive()) dialog.toFront(); - - JsonObject currentCommitJSON = getJsonFromFile(new File(configLocation, "currentCommit.json")); - - latestRepoCommit = null; - try(Reader inReader = new InputStreamReader(new URL(GIT_COMMITS_URL).openStream())) { - JsonObject commits = gson.fromJson(inReader, JsonObject.class); - latestRepoCommit = commits.get("sha").getAsString(); - } catch (Exception e) { - e.printStackTrace(); - } - if(latestRepoCommit == null || latestRepoCommit.isEmpty()) return; - - if(new File(configLocation, "repo").exists() && new File(configLocation, "repo/items").exists()) { - if(currentCommitJSON != null && currentCommitJSON.get("sha").getAsString().equals(latestRepoCommit)) { - dialog.setVisible(false); - return; - } - } - - if (Display.isActive()) dialog.toFront(); - - Utils.recursiveDelete(repoLocation); - repoLocation.mkdirs(); - - - String dlUrl = neu.config.hidden.repoURL; - - pane.setMessage("Downloading NEU Master Archive. (DL# >20)"); - dialog.pack(); - if(NotEnoughUpdates.INSTANCE.config.hidden.dev) dialog.setVisible(true); - if (Display.isActive()) dialog.toFront(); - - File itemsZip = new File(repoLocation, "neu-items-master.zip"); - try { - itemsZip.createNewFile(); - } catch (IOException e) { - return; - } - - - URL url = new URL(dlUrl); - URLConnection urlConnection = url.openConnection(); - urlConnection.setConnectTimeout(15000); - urlConnection.setReadTimeout(30000); - - try(InputStream is = urlConnection.getInputStream()) { - FileUtils.copyInputStreamToFile(is, itemsZip); - } catch (IOException e) { - dialog.dispose(); - e.printStackTrace(); - System.err.println("Failed to download NEU Repo! Please report this issue to the mod creator"); - return; - } - /*try (BufferedInputStream inStream = new BufferedInputStream(urlConnection.getInputStream()); - FileOutputStream fileOutputStream = new FileOutputStream(itemsZip)) { - byte dataBuffer[] = new byte[1024]; - int bytesRead; - while ((bytesRead = inStream.read(dataBuffer, 0, 1024)) != -1) { - fileOutputStream.write(dataBuffer, 0, bytesRead); - } - } catch (IOException e) { - dialog.dispose(); - return; - }*/ - - pane.setMessage("Unzipping NEU Master Archive."); - dialog.pack(); - //dialog.setVisible(true); - if (Display.isActive()) dialog.toFront(); - - unzipIgnoreFirstFolder(itemsZip.getAbsolutePath(), repoLocation.getAbsolutePath()); - - if(currentCommitJSON == null || !currentCommitJSON.get("sha").getAsString().equals(latestRepoCommit)) { - JsonObject newCurrentCommitJSON = new JsonObject(); - newCurrentCommitJSON.addProperty("sha", latestRepoCommit); - try { - writeJson(newCurrentCommitJSON, new File(configLocation, "currentCommit.json")); - } catch (IOException e) { - } - } - } - } catch(Exception e) { - e.printStackTrace(); - } finally { - if(dialog != null) dialog.dispose(); - } - - File items = new File(repoLocation, "items"); - if(items.exists()) { - File[] itemFiles = new File(repoLocation, "items").listFiles(); - if(itemFiles != null) { - for(File f : itemFiles) { - String internalname = f.getName().substring(0, f.getName().length()-5); - synchronized(itemMap) { - if(!itemMap.keySet().contains(internalname)) { - loadItem(internalname); - } - } - } - } - } - - try { - Constants.reload(); - } catch(Exception e) { - e.printStackTrace(); - } - }); - - File items = new File(repoLocation, "items"); - if(items.exists()) { - File[] itemFiles = new File(repoLocation, "items").listFiles(); - if(itemFiles != null) { - for(File f : itemFiles) { - String internalname = f.getName().substring(0, f.getName().length()-5); - synchronized(itemMap) { - if(!itemMap.keySet().contains(internalname)) { - loadItem(internalname); - } - } - } - } - } - - try { - Constants.reload(); - } catch(Exception e) { - e.printStackTrace(); - } - } - - /** - * Loads the item in to the itemMap and also stores various words associated with this item - * in to titleWordMap and loreWordMap. These maps are used in the searching algorithm. - * @param internalName - */ - public void loadItem(String internalName) { - itemstackCache.remove(internalName); - try { - JsonObject json = getJsonFromFile(new File(new File(repoLocation, "items"), internalName + ".json")); - if(json == null) { - return; - } - - if(json.get("itemid") == null) return; - - String itemid = json.get("itemid").getAsString(); - Item mcitem = Item.getByNameOrId(itemid); - if(mcitem != null) { - itemid = mcitem.getRegistryName(); - } - json.addProperty("itemid", itemid); - - itemMap.put(internalName, json); - - if(json.has("recipe")) { - synchronized(usagesMap) { - JsonObject recipe = json.get("recipe").getAsJsonObject(); - - String[] x = {"1","2","3"}; - String[] y = {"A","B","C"}; - for(int i=0; i<9; i++) { - String name = y[i/3]+x[i%3]; - String itemS = recipe.get(name).getAsString(); - if(itemS != null && itemS.split(":").length == 2) { - itemS = itemS.split(":")[0]; - } - - if(!usagesMap.containsKey(itemS)) { - usagesMap.put(itemS, new HashSet<>()); - } - usagesMap.get(itemS).add(internalName); - } - } - } - - if(json.has("displayname")) { - synchronized(titleWordMap) { - int wordIndex=0; - for(String str : json.get("displayname").getAsString().split(" ")) { - str = clean(str); - if(!titleWordMap.containsKey(str)) { - titleWordMap.put(str, new HashMap<>()); - } - if(!titleWordMap.get(str).containsKey(internalName)) { - titleWordMap.get(str).put(internalName, new ArrayList<>()); - } - titleWordMap.get(str).get(internalName).add(wordIndex); - wordIndex++; - } - } - } - - if(json.has("lore")) { - synchronized(loreWordMap) { - int wordIndex=0; - for(JsonElement element : json.get("lore").getAsJsonArray()) { - for(String str : element.getAsString().split(" ")) { - str = clean(str); - if(!loreWordMap.containsKey(str)) { - loreWordMap.put(str, new HashMap<>()); - } - if(!loreWordMap.get(str).containsKey(internalName)) { - loreWordMap.get(str).put(internalName, new ArrayList<>()); - } - loreWordMap.get(str).get(internalName).add(wordIndex); - wordIndex++; - } - } - } - } - } catch(Exception e) { - synchronized(loreWordMap) { - System.out.println("loreWordMap is : " + loreWordMap); - } - synchronized(titleWordMap) { - System.out.println("titleWordMap is : " + titleWordMap); - } - System.out.println("internalName is : " + internalName); - e.printStackTrace(); - } - } - - /** - * Searches a string for a query. This method is used to mimic the behaviour of the - * more complex map-based search function. This method is used for the chest-item-search feature. - */ - public boolean searchString(String toSearch, String query) { - int lastMatch = -1; - - toSearch = clean(toSearch).toLowerCase(); - query = clean(query).toLowerCase(); - String[] splitToSeach = toSearch.split(" "); - out: - for(String s : query.split(" ")) { - for(int i=0; i search(String query, boolean multi) { - if(multi) { - Set result = new HashSet<>(); - - StringBuilder query2 = new StringBuilder(); - char lastOp = '|'; - for(char c : query.toCharArray()) { - if(c == '|' || c == '&') { - if(lastOp == '|') { - result.addAll(search(query2.toString())); - } else if(lastOp == '&') { - result.retainAll(search(query2.toString())); - } - - query2 = new StringBuilder(); - lastOp = c; - } else { - query2.append(c); - } - } - if(lastOp == '|') { - result.addAll(search(query2.toString())); - } else if(lastOp == '&') { - result.retainAll(search(query2.toString())); - } - - return result; - } else { - return search(query); - } - } - - /*public TreeMap searchForStacks(String query, Set stacks, boolean multi) { - if(multi) { - Set result = new HashSet<>(); - - StringBuilder query2 = new StringBuilder(); - char lastOp = '|'; - for(char c : query.toCharArray()) { - if(c == '|' || c == '&') { - if(lastOp == '|') { - result.addAll(doesStackMatchSearch(stack, query2.toString())); - } else if(lastOp == '&') { - result.retainAll(search(query2.toString())); - } - - query2 = new StringBuilder(); - lastOp = c; - } else { - query2.append(c); - } - } - if(lastOp == '|') { - result.addAll(search(query2.toString())); - } else if(lastOp == '&') { - result.retainAll(search(query2.toString())); - } - - return result; - } else { - return search(query); - } - }*/ - - /** - * Returns the name of items which match a certain search query. - */ - public Set search(String query) { - query = query.trim(); - boolean negate = query.startsWith("!"); - if(negate) query = query.substring(1); - - LinkedHashSet results = new LinkedHashSet<>(); - if(query.startsWith("title:")) { - query = query.substring(6); - results.addAll(new TreeSet<>(search(query, titleWordMap))); - } else if(query.startsWith("desc:")) { - query = query.substring(5); - results.addAll(new TreeSet<>(search(query, loreWordMap))); - } else if(query.startsWith("id:")) { - query = query.substring(3); - results.addAll(new TreeSet<>(subMapWithKeysThatAreSuffixes(query.toUpperCase(), itemMap).keySet())); - } else { - if(!query.trim().contains(" ")) { - StringBuilder sb = new StringBuilder(); - for(char c : query.toCharArray()) { - sb.append(c).append(" "); - } - results.addAll(new TreeSet<>(search(sb.toString(), titleWordMap))); - } - results.addAll(new TreeSet<>(search(query, titleWordMap))); - results.addAll(new TreeSet<>(search(query, loreWordMap))); - } - if(!negate) { - return results; - } else { - Set negatedResults = new HashSet<>(); - for(String internalname : itemMap.keySet()) { - negatedResults.add(internalname); - } - negatedResults.removeAll(results); - return negatedResults; - } - } - - /** - * Splits a search query into an array of strings delimited by a space character. Then, matches the query to - * the start of words in the various maps (title & lore). The small query does not need to match the whole entry - * of the map, only the beginning. eg. "ench" and "encha" will both match "enchanted". All sub queries must - * follow a word matching the previous sub query. eg. "ench po" will match "enchanted pork" but will not match - * "pork enchanted". - */ - public Set search(String query, TreeMap>> wordMap) { - HashMap> matches = null; - - query = clean(query).toLowerCase(); - for(String queryWord : query.split(" ")) { - HashMap> matchesToKeep = new HashMap<>(); - for(HashMap> wordMatches : subMapWithKeysThatAreSuffixes(queryWord, wordMap).values()) { - if(wordMatches != null && !wordMatches.isEmpty()) { - if(matches == null) { - //Copy all wordMatches to titleMatches - for(String internalname : wordMatches.keySet()) { - if(!matchesToKeep.containsKey(internalname)) { - matchesToKeep.put(internalname, new ArrayList<>()); - } - matchesToKeep.get(internalname).addAll(wordMatches.get(internalname)); - } - } else { - for(String internalname : matches.keySet()) { - if(wordMatches.containsKey(internalname)) { - for(Integer newIndex : wordMatches.get(internalname)) { - if(matches.get(internalname).contains(newIndex-1)) { - if(!matchesToKeep.containsKey(internalname)) { - matchesToKeep.put(internalname, new ArrayList<>()); - } - matchesToKeep.get(internalname).add(newIndex); - } - } - } - } - } - } - } - if(matchesToKeep.isEmpty()) return new HashSet<>(); - matches = matchesToKeep; - } - - return matches.keySet(); - } - - /** - * From https://stackoverflow.com/questions/10711494/get-values-in-treemap-whose-string-keys-start-with-a-pattern - */ - public Map subMapWithKeysThatAreSuffixes(String prefix, NavigableMap map) { - if ("".equals(prefix)) return map; - String lastKey = createLexicographicallyNextStringOfTheSameLength(prefix); - return map.subMap(prefix, true, lastKey, false); - } - - public String createLexicographicallyNextStringOfTheSameLength(String input) { - final int lastCharPosition = input.length()-1; - String inputWithoutLastChar = input.substring(0, lastCharPosition); - char lastChar = input.charAt(lastCharPosition) ; - char incrementedLastChar = (char) (lastChar + 1); - return inputWithoutLastChar+incrementedLastChar; - } - - public JsonObject getJsonFromItemBytes(String item_bytes) { - try { - NBTTagCompound tag = CompressedStreamTools.readCompressed(new ByteArrayInputStream(Base64.getDecoder().decode(item_bytes))); - //System.out.println(tag.toString()); - return getJsonFromNBT(tag); - } catch(IOException e) { - return null; - } - } - - public String getUUIDFromNBT(NBTTagCompound tag) { - String uuid = null; - if (tag != null && tag.hasKey("ExtraAttributes", 10)) { - NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes"); - - if (ea.hasKey("uuid", 8)) { - uuid = ea.getString("uuid"); - } - } - return uuid; - } - - public String getInternalnameFromNBT(NBTTagCompound tag) { - String internalname = null; - if(tag != null && tag.hasKey("ExtraAttributes", 10)) { - NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes"); - - if(ea.hasKey("id", 8)) { - internalname = ea.getString("id").replaceAll(":", "-"); - } else { - return null; - } - - if("PET".equals(internalname)) { - String petInfo = ea.getString("petInfo"); - if(petInfo.length() > 0) { - JsonObject petInfoObject = gson.fromJson(petInfo, JsonObject.class); - internalname = petInfoObject.get("type").getAsString(); - String tier = petInfoObject.get("tier").getAsString(); - switch(tier) { - case "COMMON": - internalname += ";0"; break; - case "UNCOMMON": - internalname += ";1"; break; - case "RARE": - internalname += ";2"; break; - case "EPIC": - internalname += ";3"; break; - case "LEGENDARY": - internalname += ";4"; break; - case "MYTHIC": - internalname += ";5"; break; - } - } - } - if("ENCHANTED_BOOK".equals(internalname)) { - NBTTagCompound enchants = ea.getCompoundTag("enchantments"); - - for(String enchname : enchants.getKeySet()) { - internalname = enchname.toUpperCase() + ";" + enchants.getInteger(enchname); - break; - } - } - } - - return internalname; - } - - public String[] getLoreFromNBT(NBTTagCompound tag) { - String[] lore = new String[0]; - NBTTagCompound display = tag.getCompoundTag("display"); - - if(display.hasKey("Lore", 9)) { - NBTTagList list = display.getTagList("Lore", 8); - lore = new String[list.tagCount()]; - for(int k=0; k 0) { - JsonArray jsonLore = new JsonArray(); - for (String line : lore) { - jsonLore.add(new JsonPrimitive(line)); - } - item.add("lore", jsonLore); - } - - item.addProperty("damage", damage); - if(count > 1) item.addProperty("count", count); - item.addProperty("nbttag", tag.toString()); - - return item; - } - - private String clean(String str) { - return str.replaceAll("(\u00a7.)|[^0-9a-zA-Z ]", "").toLowerCase().trim(); - } - - public void showRecipe(JsonObject item) { - ContainerChest container = null; - if(Minecraft.getMinecraft().thePlayer.openContainer instanceof ContainerChest) - container = (ContainerChest) Minecraft.getMinecraft().thePlayer.openContainer; - if (item.has("recipe") && container != null && container.getLowerChestInventory().getDisplayName().getUnformattedText().equals("Craft Item")) { - CraftingOverlay.updateItem(item); - } else if(item.has("useneucraft") && item.get("useneucraft").getAsBoolean()) { - displayGuiItemRecipe(item.get("internalname").getAsString(), ""); - } else if(item.has("clickcommand")) { - String clickcommand = item.get("clickcommand").getAsString(); - - if(clickcommand.equals("viewrecipe")) { - neu.sendChatMessage( - "/" + clickcommand + " " + - item.get("internalname").getAsString().split(";")[0]); - viewItemAttemptID = item.get("internalname").getAsString(); - viewItemAttemptTime = System.currentTimeMillis(); - } else if(clickcommand.equals("viewpotion")) { - neu.sendChatMessage( - "/" + clickcommand + " " + - item.get("internalname").getAsString().split(";")[0].toLowerCase()); - viewItemAttemptID = item.get("internalname").getAsString(); - viewItemAttemptTime = System.currentTimeMillis(); - } - } - } - - /** - * Takes an item stack and produces a JsonObject. - */ - public JsonObject getJsonForItem(ItemStack stack) { - NBTTagCompound tag = stack.getTagCompound() == null ? new NBTTagCompound() : stack.getTagCompound(); - - //Item lore - String[] lore = new String[0]; - if(tag.hasKey("display", 10)) { - NBTTagCompound display = tag.getCompoundTag("display"); - - if(display.hasKey("Lore", 9)) { - NBTTagList list = display.getTagList("Lore", 8); - lore = new String[list.tagCount()]; - for(int i=0; i 0 && (lore[lore.length-1].contains("Click to view recipes!") || - lore[lore.length-1].contains("Click to view recipe!"))) { - String[] lore2 = new String[lore.length-2]; - System.arraycopy(lore, 0, lore2, 0, lore.length-2); - lore = lore2; - } - - JsonObject json = new JsonObject(); - json.addProperty("itemid", stack.getItem().getRegistryName()); - json.addProperty("displayname", stack.getDisplayName()); - json.addProperty("nbttag", tag.toString()); - json.addProperty("damage", stack.getItemDamage()); - - JsonArray jsonlore = new JsonArray(); - for(String line : lore) { - jsonlore.add(new JsonPrimitive(line)); - } - json.add("lore", jsonlore); - - return json; - } - - public String getInternalNameForItem(ItemStack stack) { - if(stack == null) return null; - NBTTagCompound tag = stack.getTagCompound(); - return getInternalnameFromNBT(tag); - } - - public String getUUIDForItem(ItemStack stack) { - if(stack == null) return null; - NBTTagCompound tag = stack.getTagCompound(); - return getUUIDFromNBT(tag); - } - - public void writeItemToFile(ItemStack stack) { - String internalname = getInternalNameForItem(stack); - - if(internalname == null) { - return; - } - - JsonObject json = getJsonForItem(stack); - json.addProperty("internalname", internalname); - json.addProperty("clickcommand", ""); - json.addProperty("modver", NotEnoughUpdates.VERSION); - - try { - writeJson(json, new File(new File(repoLocation, "items"), internalname+".json")); - } catch (IOException e) {} - - loadItem(internalname); - } - - /** - * Constructs a GuiItemUsages from the recipe usage data (see #usagesMap) of a given item - */ - public boolean displayGuiItemUsages(String internalName) { - List craftMatrices = new ArrayList<>(); - List results = new ArrayList<>(); - - if(!usagesMap.containsKey(internalName)) { - return false; - } - - for(String internalNameResult : usagesMap.get(internalName)) { - JsonObject item = getItemInformation().get(internalNameResult); - results.add(item); - - if(item != null && item.has("recipe")) { - JsonObject recipe = item.get("recipe").getAsJsonObject(); - - ItemStack[] craftMatrix = new ItemStack[9]; - - String[] x = {"1","2","3"}; - String[] y = {"A","B","C"}; - for(int i=0; i<9; i++) { - String name = y[i/3]+x[i%3]; - String itemS = recipe.get(name).getAsString(); - int count = 1; - if(itemS != null && itemS.split(":").length == 2) { - count = Integer.valueOf(itemS.split(":")[1]); - itemS = itemS.split(":")[0]; - } - JsonObject craft = getItemInformation().get(itemS); - if(craft != null) { - ItemStack stack = jsonToStack(craft); - stack.stackSize = count; - craftMatrix[i] = stack; - } - } - - craftMatrices.add(craftMatrix); - } - } - - if(craftMatrices.size() > 0) { - Minecraft.getMinecraft().displayGuiScreen(new GuiItemRecipe("Item Usages", craftMatrices, results, this)); - return true; - } - return false; - } - - /** - * Constructs a GuiItemRecipeOld from the recipe data of a given item. - */ - public boolean displayGuiItemRecipe(String internalName, String text) { - JsonObject item = getItemInformation().get(internalName); - if(item != null && item.has("recipe")) { - JsonObject recipe = item.get("recipe").getAsJsonObject(); - - ItemStack[] craftMatrix = new ItemStack[9]; - - String[] x = {"1","2","3"}; - String[] y = {"A","B","C"}; - for(int i=0; i<9; i++) { - String name = y[i/3]+x[i%3]; - String itemS = recipe.get(name).getAsString(); - int count = 1; - if(itemS != null && itemS.split(":").length == 2) { - count = Integer.valueOf(itemS.split(":")[1]); - itemS = itemS.split(":")[0]; - } - JsonObject craft = getItemInformation().get(itemS); - if(craft != null) { - ItemStack stack = jsonToStack(craft); - stack.stackSize = count; - craftMatrix[i] = stack; - } - } - - Minecraft.getMinecraft().thePlayer.sendQueue.addToSendQueue(new C0DPacketCloseWindow( - Minecraft.getMinecraft().thePlayer.openContainer.windowId)); - Minecraft.getMinecraft().displayGuiScreen(new GuiItemRecipe(text!=null?text:"Item Recipe", - Lists.newArrayList(craftMatrix), Lists.newArrayList(item), this)); - return true; - } - return false; - } - - /** - * Will display guiItemRecipe if a player attempted to view the recipe to an item but they didn't have the recipe - * unlocked. See NotEnoughUpdates#onGuiChat for where this method is called. - */ - public boolean failViewItem(String text) { - if(viewItemAttemptID != null && !viewItemAttemptID.isEmpty()) { - if(System.currentTimeMillis() - viewItemAttemptTime < 500) { - return displayGuiItemRecipe(viewItemAttemptID, text); - } - } - return false; - } - - /** - * Downloads a web file, appending some HTML attributes that makes wikia give us the raw wiki syntax. - */ - public File getWebFile(String url) { - File f = new File(configLocation, "tmp/"+Base64.getEncoder().encodeToString(url.getBytes())+".html"); - if(f.exists()) { - return f; - } - - try { - f.getParentFile().mkdirs(); - f.createNewFile(); - f.deleteOnExit(); - } catch (IOException e) { - return null; - } - try (BufferedInputStream inStream = new BufferedInputStream(new URL(url+"?action=raw&templates=expand").openStream()); - FileOutputStream fileOutputStream = new FileOutputStream(f)) { - byte dataBuffer[] = new byte[1024]; - int bytesRead; - while ((bytesRead = inStream.read(dataBuffer, 0, 1024)) != -1) { - fileOutputStream.write(dataBuffer, 0, bytesRead); - } - } catch (IOException e) { - e.printStackTrace(); - return null; - } - - return f; - } - - - /** - * Modified from https://www.journaldev.com/960/java-unzip-file-example - */ - private static void unzipIgnoreFirstFolder(String zipFilePath, String destDir) { - File dir = new File(destDir); - // create output directory if it doesn't exist - if(!dir.exists()) dir.mkdirs(); - FileInputStream fis; - //buffer for read and write data to file - byte[] buffer = new byte[1024]; - try { - fis = new FileInputStream(zipFilePath); - ZipInputStream zis = new ZipInputStream(fis); - ZipEntry ze = zis.getNextEntry(); - while(ze != null){ - if(!ze.isDirectory()) { - String fileName = ze.getName(); - fileName = fileName.substring(fileName.split("/")[0].length()+1); - File newFile = new File(destDir + File.separator + fileName); - //create directories for sub directories in zip - new File(newFile.getParent()).mkdirs(); - FileOutputStream fos = new FileOutputStream(newFile); - int len; - while ((len = zis.read(buffer)) > 0) { - fos.write(buffer, 0, len); - } - fos.close(); - } - //close this ZipEntry - zis.closeEntry(); - ze = zis.getNextEntry(); - } - //close last ZipEntry - zis.closeEntry(); - zis.close(); - fis.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - /** - * Modified from https://www.journaldev.com/960/java-unzip-file-example - */ - public static void unzip(InputStream src, File dest) { - //buffer for read and write data to file - byte[] buffer = new byte[1024]; - try { - ZipInputStream zis = new ZipInputStream(src); - ZipEntry ze = zis.getNextEntry(); - while(ze != null){ - if(!ze.isDirectory()) { - String fileName = ze.getName(); - File newFile = new File(dest, fileName); - //create directories for sub directories in zip - new File(newFile.getParent()).mkdirs(); - FileOutputStream fos = new FileOutputStream(newFile); - int len; - while ((len = zis.read(buffer)) > 0) { - fos.write(buffer, 0, len); - } - fos.close(); - } - //close this ZipEntry - zis.closeEntry(); - ze = zis.getNextEntry(); - } - //close last ZipEntry - zis.closeEntry(); - zis.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - /** - * From here to the end of the file are various helper functions for creating and writing json files, - * in particular json files representing skyblock item data. - */ - public JsonObject createItemJson(String internalname, String itemid, String displayname, String[] lore, - String crafttext, String infoType, String[] info, - String clickcommand, int damage, NBTTagCompound nbttag) { - return createItemJson(new JsonObject(), internalname, itemid, displayname, lore, crafttext, infoType, info, clickcommand, damage, nbttag); - } - - public JsonObject createItemJson(JsonObject base, String internalname, String itemid, String displayname, String[] lore, - String crafttext, String infoType, String[] info, - String clickcommand, int damage, NBTTagCompound nbttag) { - if(internalname == null || internalname.isEmpty()) { - return null; - } - - JsonObject json = gson.fromJson(gson.toJson(base, JsonObject.class), JsonObject.class); - json.addProperty("internalname", internalname); - json.addProperty("itemid", itemid); - json.addProperty("displayname", displayname); - json.addProperty("crafttext", crafttext); - json.addProperty("clickcommand", clickcommand); - json.addProperty("damage", damage); - json.addProperty("nbttag", nbttag.toString()); - json.addProperty("modver", NotEnoughUpdates.VERSION); - json.addProperty("infoType", infoType.toString()); - - if(info != null && info.length > 0) { - JsonArray jsoninfo = new JsonArray(); - for (String line : info) { - jsoninfo.add(new JsonPrimitive(line)); - } - json.add("info", jsoninfo); - } - - JsonArray jsonlore = new JsonArray(); - for(String line : lore) { - jsonlore.add(new JsonPrimitive(line)); - } - json.add("lore", jsonlore); - - return json; - } - - public boolean writeItemJson(String internalname, String itemid, String displayname, String[] lore, String crafttext, - String infoType, String[] info, String clickcommand, int damage, NBTTagCompound nbttag) { - return writeItemJson(new JsonObject(), internalname, itemid, displayname, lore, crafttext, infoType, info, clickcommand, damage, nbttag); - } - - public boolean writeItemJson(JsonObject base, String internalname, String itemid, String displayname, String[] lore, - String crafttext, String infoType, String[] info, String clickcommand, int damage, NBTTagCompound nbttag) { - JsonObject json = createItemJson(base, internalname, itemid, displayname, lore, crafttext, infoType, info, clickcommand, damage, nbttag); - if(json == null) { - return false; - } - - try { - writeJsonDefaultDir(json, internalname+".json"); - } catch(IOException e) { - return false; - } - - loadItem(internalname); - return true; - } - - public void writeJson(JsonObject json, File file) throws IOException { - file.createNewFile(); - - try(BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8))) { - writer.write(gson.toJson(json)); - } - } - - public void writeJsonDefaultDir(JsonObject json, String filename) throws IOException { - File file = new File(new File(repoLocation, "items"), filename); - writeJson(json, file); - } - - public TreeMap getItemInformation() { - return itemMap; - } - - public String removeUnusedDecimal(double num) { - if(num % 1 == 0) { - return String.valueOf((int)num); - } else { - return String.valueOf(num); - } - } - - public HashMap getLoreReplacements(String petname, String tier, int level) { - JsonObject petnums = null; - if(petname != null && tier != null) { - petnums = Constants.PETNUMS; - } - - HashMap replacements = new HashMap<>(); - if(level < 1) { - if (Constants.PETS.has("custom_pet_leveling") && Constants.PETS.getAsJsonObject("custom_pet_leveling").has(petname) && Constants.PETS.getAsJsonObject("custom_pet_leveling").getAsJsonObject(petname).has("max_level")){ - int maxLvl = Constants.PETS.getAsJsonObject("custom_pet_leveling").getAsJsonObject(petname).get("max_level").getAsInt(); - replacements.put("LVL", "1\u27A1"+maxLvl); - } else { - replacements.put("LVL", "1\u27A1100"); - } - } else { - replacements.put("LVL", ""+level); - } - - - if(petnums != null) { - if(petnums.has(petname)) { - JsonObject petInfo = petnums.get(petname).getAsJsonObject(); - if(petInfo.has(tier)) { - JsonObject petInfoTier = petInfo.get(tier).getAsJsonObject(); - if(petInfoTier == null || !petInfoTier.has("1") || !petInfoTier.has("100")) { - return replacements; - } - - JsonObject min = petInfoTier.get("1").getAsJsonObject(); - JsonObject max = petInfoTier.get("100").getAsJsonObject(); - - if(level < 1) { - JsonArray otherNumsMin = min.get("otherNums").getAsJsonArray(); - JsonArray otherNumsMax = max.get("otherNums").getAsJsonArray(); - boolean addZero = false; - if(petInfoTier.has("stats_levelling_curve")){ - String[] stringArray = petInfoTier.get("stats_levelling_curve").getAsString().split(":"); - if(stringArray.length == 3) { - int type = Integer.parseInt(stringArray[2]); - if(type == 1){ - addZero = true; - } - } - } - for(int i=0; i entry : max.get("statNums").getAsJsonObject().entrySet()) { - int statMax = (int)Math.floor(entry.getValue().getAsFloat()); - int statMin = (int)Math.floor(min.get("statNums").getAsJsonObject().get(entry.getKey()).getAsFloat()); - String statStr = (statMin>0?"+":"")+statMin+"\u27A1"+statMax; - statStr = (addZero?"0\u27A1":"")+statStr; - replacements.put(entry.getKey(), statStr); - } - } else { - - int minStatsLevel = 0; - int maxStatsLevel = 100; - int statsLevelingType = -1; - - int statsLevel = level; - - - if(petInfoTier.has("stats_levelling_curve")) { - String[] stringArray = petInfoTier.get("stats_levelling_curve").getAsString().split(":"); - if (stringArray.length == 3) { - minStatsLevel = Integer.parseInt(stringArray[0]); - maxStatsLevel = Integer.parseInt(stringArray[1]); - statsLevelingType = Integer.parseInt(stringArray[2]); - switch (statsLevelingType) { - //Case for maybe a pet that might exist - case 0: - case 1: - if (level < minStatsLevel) { - statsLevel = 1; - } else if (level < maxStatsLevel) { - statsLevel = level - minStatsLevel + 1; - } else { - statsLevel = maxStatsLevel - minStatsLevel + 1; - } - break; - - } - } - } - float minMix = (maxStatsLevel-(minStatsLevel-(statsLevelingType==-1?0:1))-statsLevel)/99f; - float maxMix = (statsLevel-1)/99f; - - JsonArray otherNumsMin = min.get("otherNums").getAsJsonArray(); - JsonArray otherNumsMax = max.get("otherNums").getAsJsonArray(); - for(int i=0; i entry : max.get("statNums").getAsJsonObject().entrySet()) { - if(statsLevelingType == 1 && level < minStatsLevel) { - replacements.put(entry.getKey(), "0"); - } else { - float statMax = entry.getValue().getAsFloat(); - float statMin = min.get("statNums").getAsJsonObject().get(entry.getKey()).getAsFloat(); - float val = statMin * minMix + statMax * maxMix; - String statStr = (statMin > 0 ? "+" : "") + (int) Math.floor(val); - replacements.put(entry.getKey(), statStr); - } - } - } - } - } - } - - return replacements; - } - - public HashMap getLoreReplacements(NBTTagCompound tag, int level) { - String petname = null; - String tier = null; - if(tag != null && tag.hasKey("ExtraAttributes")) { - NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes"); - if(ea.hasKey("petInfo")) { - String petInfoStr = ea.getString("petInfo"); - JsonObject petInfo = gson.fromJson(petInfoStr, JsonObject.class); - petname = petInfo.get("type").getAsString(); - tier = petInfo.get("tier").getAsString(); - if(petInfo.has("heldItem")) { - String heldItem = petInfo.get("heldItem").getAsString(); - if(heldItem.equals("PET_ITEM_TIER_BOOST")) { - switch(tier) { - case "COMMON": - tier = "UNCOMMON"; break; - case "UNCOMMON": - tier = "RARE"; break; - case "RARE": - tier = "EPIC"; break; - case "EPIC": - tier = "LEGENDARY"; break; - case "LEGENDARY": - tier = "MYTHIC"; break; - } - } - } - } - } - return getLoreReplacements(petname, tier, level); - } - - public NBTTagList processLore(JsonArray lore, HashMap replacements) { - NBTTagList nbtLore = new NBTTagList(); - for(JsonElement line : lore) { - String lineStr = line.getAsString(); - if(!lineStr.contains("Click to view recipes!") && - !lineStr.contains("Click to view recipe!")) { - for(Map.Entry entry : replacements.entrySet()) { - lineStr = lineStr.replace("{"+entry.getKey()+"}", entry.getValue()); - } - nbtLore.appendTag(new NBTTagString(lineStr)); - } - } - return nbtLore; - } - - public ItemStack jsonToStack(JsonObject json) { - return jsonToStack(json, true); - } - - public ItemStack jsonToStack(JsonObject json, boolean useCache) { - return jsonToStack(json, useCache, true); - } - - public ItemStack jsonToStack(JsonObject json, boolean useCache, boolean useReplacements) { - return jsonToStack(json, useCache, useReplacements, true); - } - - public ItemStack jsonToStack(JsonObject json, boolean useCache, boolean useReplacements, boolean copyStack) { - if(json == null) return new ItemStack(Items.painting, 1, 10); - String internalname = json.get("internalname").getAsString(); - - if(useCache) { - ItemStack stack = itemstackCache.get(internalname); - if(stack != null) { - if(copyStack) { - return stack.copy(); - } else { - return stack; - } - } - } - - ItemStack stack = new ItemStack(Item.itemRegistry.getObject( - new ResourceLocation(json.get("itemid").getAsString()))); - - if(json.has("count")) { - stack.stackSize = json.get("count").getAsInt(); - } - - if(stack.getItem() == null) { - stack = new ItemStack(Item.getItemFromBlock(Blocks.stone), 0, 255); //Purple broken texture item - } else { - if(json.has("damage")) { - stack.setItemDamage(json.get("damage").getAsInt()); - } - - if(json.has("nbttag")) { - try { - NBTTagCompound tag = JsonToNBT.getTagFromJson(json.get("nbttag").getAsString()); - stack.setTagCompound(tag); - } catch(NBTException e) { - } - } - - HashMap replacements = new HashMap<>(); - - if(useReplacements) { - replacements = getLoreReplacements(stack.getTagCompound(), -1); - - String displayname = json.get("displayname").getAsString(); - for(Map.Entry entry : replacements.entrySet()) { - displayname = displayname.replace("{"+entry.getKey()+"}", entry.getValue()); - } - stack.setStackDisplayName(displayname); - } - - if(json.has("lore")) { - NBTTagCompound display = new NBTTagCompound(); - if(stack.getTagCompound() != null && stack.getTagCompound().hasKey("display")) { - display = stack.getTagCompound().getCompoundTag("display"); - } - display.setTag("Lore", processLore(json.get("lore").getAsJsonArray(), replacements)); - NBTTagCompound tag = stack.getTagCompound() != null ? stack.getTagCompound() : new NBTTagCompound(); - tag.setTag("display", display); - stack.setTagCompound(tag); - } - } - - if(useCache) itemstackCache.put(internalname, stack); - if(copyStack) { - return stack.copy(); - } else { - return stack; - } - } - + repoLoaderES.submit(() -> { + JDialog dialog = null; + try { + if (NotEnoughUpdates.INSTANCE.config.hidden.autoupdate) { + JOptionPane pane = new JOptionPane("Getting items to download from remote repository."); + dialog = pane.createDialog("NotEnoughUpdates Remote Sync"); + dialog.setModal(false); + if (NotEnoughUpdates.INSTANCE.config.hidden.dev) dialog.setVisible(true); + + if (Display.isActive()) dialog.toFront(); + + JsonObject currentCommitJSON = getJsonFromFile(new File(configLocation, "currentCommit.json")); + + latestRepoCommit = null; + try (Reader inReader = new InputStreamReader(new URL(GIT_COMMITS_URL).openStream())) { + JsonObject commits = gson.fromJson(inReader, JsonObject.class); + latestRepoCommit = commits.get("sha").getAsString(); + } catch (Exception e) { + e.printStackTrace(); + } + if (latestRepoCommit == null || latestRepoCommit.isEmpty()) return; + + if (new File(configLocation, "repo").exists() && new File(configLocation, "repo/items").exists()) { + if (currentCommitJSON != null && currentCommitJSON.get("sha").getAsString().equals(latestRepoCommit)) { + dialog.setVisible(false); + return; + } + } + + if (Display.isActive()) dialog.toFront(); + + Utils.recursiveDelete(repoLocation); + repoLocation.mkdirs(); + + String dlUrl = neu.config.hidden.repoURL; + + pane.setMessage("Downloading NEU Master Archive. (DL# >20)"); + dialog.pack(); + if (NotEnoughUpdates.INSTANCE.config.hidden.dev) dialog.setVisible(true); + if (Display.isActive()) dialog.toFront(); + + File itemsZip = new File(repoLocation, "neu-items-master.zip"); + try { + itemsZip.createNewFile(); + } catch (IOException e) { + return; + } + + URL url = new URL(dlUrl); + URLConnection urlConnection = url.openConnection(); + urlConnection.setConnectTimeout(15000); + urlConnection.setReadTimeout(30000); + + try (InputStream is = urlConnection.getInputStream()) { + FileUtils.copyInputStreamToFile(is, itemsZip); + } catch (IOException e) { + dialog.dispose(); + e.printStackTrace(); + System.err.println("Failed to download NEU Repo! Please report this issue to the mod creator"); + return; + } + /*try ( + BufferedInputStream inStream = new BufferedInputStream(urlConnection.getInputStream()); + FileOutputStream fileOutputStream = new FileOutputStream(itemsZip) + ) { + byte dataBuffer[] = new byte[1024]; + int bytesRead; + while ((bytesRead = inStream.read(dataBuffer, 0, 1024)) != -1) { + fileOutputStream.write(dataBuffer, 0, bytesRead); + } + } catch (IOException e) { + dialog.dispose(); + return; + }*/ + + pane.setMessage("Unzipping NEU Master Archive."); + dialog.pack(); + //dialog.setVisible(true); + if (Display.isActive()) dialog.toFront(); + + unzipIgnoreFirstFolder(itemsZip.getAbsolutePath(), repoLocation.getAbsolutePath()); + + if (currentCommitJSON == null || !currentCommitJSON.get("sha").getAsString().equals(latestRepoCommit)) { + JsonObject newCurrentCommitJSON = new JsonObject(); + newCurrentCommitJSON.addProperty("sha", latestRepoCommit); + try { + writeJson(newCurrentCommitJSON, new File(configLocation, "currentCommit.json")); + } catch (IOException ignored) { + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (dialog != null) dialog.dispose(); + } + + File items = new File(repoLocation, "items"); + if (items.exists()) { + File[] itemFiles = new File(repoLocation, "items").listFiles(); + if (itemFiles != null) { + ProgressManager.ProgressBar bar = ProgressManager.push("Loading recipes", itemFiles.length); + for (File f : itemFiles) { + String internalname = f.getName().substring(0, f.getName().length() - 5); + bar.step(internalname); + synchronized (itemMap) { + if (!itemMap.containsKey(internalname)) { + loadItem(internalname); + } + } + } + ProgressManager.pop(bar); + } + } + + try { + Constants.reload(); + } catch (Exception e) { + e.printStackTrace(); + } + }); + + File items = new File(repoLocation, "items"); + if (items.exists()) { + File[] itemFiles = new File(repoLocation, "items").listFiles(); + if (itemFiles != null) { + ProgressManager.ProgressBar bar = ProgressManager.push("Loading items", itemFiles.length); + for (File f : itemFiles) { + String internalname = f.getName().substring(0, f.getName().length() - 5); + bar.step(internalname); + synchronized (itemMap) { + if (!itemMap.containsKey(internalname)) { + loadItem(internalname); + } + } + } + ProgressManager.pop(bar); + } + } + + try { + Constants.reload(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Loads the item in to the itemMap and also stores various words associated with this item in to titleWordMap and + * loreWordMap. These maps are used in the searching algorithm. + */ + public void loadItem(String internalName) { + itemstackCache.remove(internalName); + try { + JsonObject json = getJsonFromFile(new File(new File(repoLocation, "items"), internalName + ".json")); + if (json == null) { + return; + } + + if (json.get("itemid") == null) return; + + String itemid = json.get("itemid").getAsString(); + Item mcitem = Item.getByNameOrId(itemid); + if (mcitem != null) { + itemid = mcitem.getRegistryName(); + } + json.addProperty("itemid", itemid); + + itemMap.put(internalName, json); + + if (json.has("recipe")) { + JsonObject recipe = json.getAsJsonObject("recipe"); + NeuRecipe neuRecipe = NeuRecipe.parseRecipe(this, recipe, json); + if (neuRecipe != null) + registerNeuRecipe(neuRecipe); + } + if (json.has("recipes")) { + for (JsonElement element : json.getAsJsonArray("recipes")) { + JsonObject recipe = element.getAsJsonObject(); + NeuRecipe neuRecipe = NeuRecipe.parseRecipe(this, recipe, json); + if (neuRecipe != null) + registerNeuRecipe(neuRecipe); + } + } + + if (json.has("displayname")) { + synchronized (titleWordMap) { + int wordIndex = 0; + for (String str : json.get("displayname").getAsString().split(" ")) { + str = clean(str); + if (!titleWordMap.containsKey(str)) { + titleWordMap.put(str, new HashMap<>()); + } + if (!titleWordMap.get(str).containsKey(internalName)) { + titleWordMap.get(str).put(internalName, new ArrayList<>()); + } + titleWordMap.get(str).get(internalName).add(wordIndex); + wordIndex++; + } + } + } + + if (json.has("lore")) { + synchronized (loreWordMap) { + int wordIndex = 0; + for (JsonElement element : json.get("lore").getAsJsonArray()) { + for (String str : element.getAsString().split(" ")) { + str = clean(str); + if (!loreWordMap.containsKey(str)) { + loreWordMap.put(str, new HashMap<>()); + } + if (!loreWordMap.get(str).containsKey(internalName)) { + loreWordMap.get(str).put(internalName, new ArrayList<>()); + } + loreWordMap.get(str).get(internalName).add(wordIndex); + wordIndex++; + } + } + } + } + } catch (Exception e) { + synchronized (loreWordMap) { + System.out.println("loreWordMap is : " + loreWordMap); + } + synchronized (titleWordMap) { + System.out.println("titleWordMap is : " + titleWordMap); + } + System.out.println("internalName is : " + internalName); + e.printStackTrace(); + } + } + + public void registerNeuRecipe(NeuRecipe recipe) { + recipes.add(recipe); + for (Ingredient output : recipe.getOutputs()) { + recipesMap.computeIfAbsent(output.getInternalItemId(), ignored -> new HashSet<>()).add(recipe); + } + for (Ingredient input : recipe.getIngredients()) { + usagesMap.computeIfAbsent(input.getInternalItemId(), ignored -> new HashSet<>()).add(recipe); + } + } + + public Set getRecipesFor(String internalName) { + return recipesMap.getOrDefault(internalName, Collections.emptySet()); + } + + public List getAvailableRecipesFor(String internalname) { + return getRecipesFor(internalname).stream().filter(NeuRecipe::isAvailable).collect(Collectors.toList()); + } + + public Set getUsagesFor(String internalName) { + return usagesMap.getOrDefault(internalName, Collections.emptySet()); + } + + public List getAvailableUsagesFor(String internalname) { + return getUsagesFor(internalname).stream().filter(NeuRecipe::isAvailable).collect(Collectors.toList()); + } + + /** + * Searches a string for a query. This method is used to mimic the behaviour of the more complex map-based search + * function. This method is used for the chest-item-search feature. + */ + public boolean searchString(String toSearch, String query) { + int lastMatch = -1; + + toSearch = clean(toSearch).toLowerCase(); + query = clean(query).toLowerCase(); + String[] splitToSeach = toSearch.split(" "); + out: + for (String s : query.split(" ")) { + for (int i = 0; i < splitToSeach.length; i++) { + if (!(lastMatch == -1 || lastMatch == i - 1)) continue; + if (splitToSeach[i].startsWith(s)) { + lastMatch = i; + continue out; + } + } + return false; + } + + return true; + } + + /** + * Checks whether an itemstack matches a certain query, following the same rules implemented by the more complex + * map-based search function. + */ + public boolean doesStackMatchSearch(ItemStack stack, String query) { + if (query.startsWith("title:")) { + query = query.substring(6); + return searchString(stack.getDisplayName(), query); + } else if (query.startsWith("desc:")) { + query = query.substring(5); + String lore = ""; + NBTTagCompound tag = stack.getTagCompound(); + if (tag != null) { + NBTTagCompound display = tag.getCompoundTag("display"); + if (display.hasKey("Lore", 9)) { + NBTTagList list = display.getTagList("Lore", 8); + for (int i = 0; i < list.tagCount(); i++) { + lore += list.getStringTagAt(i) + " "; + } + } + } + return searchString(lore, query); + } else if (query.startsWith("id:")) { + query = query.substring(3); + String internalName = getInternalNameForItem(stack); + return query.equalsIgnoreCase(internalName); + } else { + boolean result = false; + if (!query.trim().contains(" ")) { + StringBuilder sb = new StringBuilder(); + for (char c : query.toCharArray()) { + sb.append(c).append(" "); + } + result = result || searchString(stack.getDisplayName(), sb.toString()); + } + result = result || searchString(stack.getDisplayName(), query); + + String lore = ""; + NBTTagCompound tag = stack.getTagCompound(); + if (tag != null) { + NBTTagCompound display = tag.getCompoundTag("display"); + if (display.hasKey("Lore", 9)) { + NBTTagList list = display.getTagList("Lore", 8); + for (int i = 0; i < list.tagCount(); i++) { + lore += list.getStringTagAt(i) + " "; + } + } + } + + result = result || searchString(lore, query); + + return result; + } + } + + /** + * Calls search for each query, separated by | eg. search(A|B) = search(A) + search(B) + */ + public Set search(String query, boolean multi) { + if (multi) { + Set result = new HashSet<>(); + + StringBuilder query2 = new StringBuilder(); + char lastOp = '|'; + for (char c : query.toCharArray()) { + if (c == '|' || c == '&') { + if (lastOp == '|') { + result.addAll(search(query2.toString())); + } else if (lastOp == '&') { + result.retainAll(search(query2.toString())); + } + + query2 = new StringBuilder(); + lastOp = c; + } else { + query2.append(c); + } + } + if (lastOp == '|') { + result.addAll(search(query2.toString())); + } else if (lastOp == '&') { + result.retainAll(search(query2.toString())); + } + + return result; + } else { + return search(query); + } + } + + /*public TreeMap searchForStacks(String query, Set stacks, boolean multi) { + if (multi) { + Set result = new HashSet<>(); + + StringBuilder query2 = new StringBuilder(); + char lastOp = '|'; + for (char c : query.toCharArray()) { + if (c == '|' || c == '&') { + if (lastOp == '|') { + result.addAll(doesStackMatchSearch(stack, query2.toString())); + } else if (lastOp == '&') { + result.retainAll(search(query2.toString())); + } + + query2 = new StringBuilder(); + lastOp = c; + } else { + query2.append(c); + } + } + if (lastOp == '|') { + result.addAll(search(query2.toString())); + } else if (lastOp == '&') { + result.retainAll(search(query2.toString())); + } + + return result; + } else { + return search(query); + } + }*/ + + /** + * Returns the name of items which match a certain search query. + */ + public Set search(String query) { + query = query.trim(); + boolean negate = query.startsWith("!"); + if (negate) query = query.substring(1); + + LinkedHashSet results = new LinkedHashSet<>(); + if (query.startsWith("title:")) { + query = query.substring(6); + results.addAll(new TreeSet<>(search(query, titleWordMap))); + } else if (query.startsWith("desc:")) { + query = query.substring(5); + results.addAll(new TreeSet<>(search(query, loreWordMap))); + } else if (query.startsWith("id:")) { + query = query.substring(3); + results.addAll(new TreeSet<>(subMapWithKeysThatAreSuffixes(query.toUpperCase(), itemMap).keySet())); + } else { + if (!query.trim().contains(" ")) { + StringBuilder sb = new StringBuilder(); + for (char c : query.toCharArray()) { + sb.append(c).append(" "); + } + results.addAll(new TreeSet<>(search(sb.toString(), titleWordMap))); + } + results.addAll(new TreeSet<>(search(query, titleWordMap))); + results.addAll(new TreeSet<>(search(query, loreWordMap))); + } + if (!negate) { + return results; + } else { + Set negatedResults = new HashSet<>(); + for (String internalname : itemMap.keySet()) { + negatedResults.add(internalname); + } + negatedResults.removeAll(results); + return negatedResults; + } + } + + /** + * Splits a search query into an array of strings delimited by a space character. Then, matches the query to the + * start of words in the various maps (title & lore). The small query does not need to match the whole entry of the + * map, only the beginning. eg. "ench" and "encha" will both match "enchanted". All sub queries must follow a word + * matching the previous sub query. eg. "ench po" will match "enchanted pork" but will not match "pork enchanted". + */ + public Set search(String query, TreeMap>> wordMap) { + HashMap> matches = null; + + query = clean(query).toLowerCase(); + for (String queryWord : query.split(" ")) { + HashMap> matchesToKeep = new HashMap<>(); + for (HashMap> wordMatches : subMapWithKeysThatAreSuffixes(queryWord, wordMap).values()) { + if (!(wordMatches != null && !wordMatches.isEmpty())) continue; + if (matches == null) { + //Copy all wordMatches to titleMatches + for (String internalname : wordMatches.keySet()) { + if (!matchesToKeep.containsKey(internalname)) { + matchesToKeep.put(internalname, new ArrayList<>()); + } + matchesToKeep.get(internalname).addAll(wordMatches.get(internalname)); + } + } else { + for (String internalname : matches.keySet()) { + if (!wordMatches.containsKey(internalname)) continue; + for (Integer newIndex : wordMatches.get(internalname)) { + if (!matches.get(internalname).contains(newIndex - 1)) continue; + if (!matchesToKeep.containsKey(internalname)) { + matchesToKeep.put(internalname, new ArrayList<>()); + } + matchesToKeep.get(internalname).add(newIndex); + } + } + } + } + if (matchesToKeep.isEmpty()) return new HashSet<>(); + matches = matchesToKeep; + } + + return matches.keySet(); + } + + /** + * From https://stackoverflow.com/questions/10711494/get-values-in-treemap-whose-string-keys-start-with-a-pattern + */ + public Map subMapWithKeysThatAreSuffixes(String prefix, NavigableMap map) { + if ("".equals(prefix)) return map; + String lastKey = createLexicographicallyNextStringOfTheSameLength(prefix); + return map.subMap(prefix, true, lastKey, false); + } + + public String createLexicographicallyNextStringOfTheSameLength(String input) { + final int lastCharPosition = input.length() - 1; + String inputWithoutLastChar = input.substring(0, lastCharPosition); + char lastChar = input.charAt(lastCharPosition); + char incrementedLastChar = (char) (lastChar + 1); + return inputWithoutLastChar + incrementedLastChar; + } + + public JsonObject getJsonFromItemBytes(String item_bytes) { + try { + NBTTagCompound tag = + CompressedStreamTools.readCompressed(new ByteArrayInputStream(Base64.getDecoder().decode(item_bytes))); + //System.out.println(tag.toString()); + return getJsonFromNBT(tag); + } catch (IOException e) { + return null; + } + } + + public String getUUIDFromNBT(NBTTagCompound tag) { + String uuid = null; + if (tag != null && tag.hasKey("ExtraAttributes", 10)) { + NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes"); + + if (ea.hasKey("uuid", 8)) { + uuid = ea.getString("uuid"); + } + } + return uuid; + } + + public String getInternalnameFromNBT(NBTTagCompound tag) { + String internalname = null; + if (tag != null && tag.hasKey("ExtraAttributes", 10)) { + NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes"); + + if (ea.hasKey("id", 8)) { + internalname = ea.getString("id").replaceAll(":", "-"); + } else { + return null; + } + + if ("PET".equals(internalname)) { + String petInfo = ea.getString("petInfo"); + if (petInfo.length() > 0) { + JsonObject petInfoObject = gson.fromJson(petInfo, JsonObject.class); + internalname = petInfoObject.get("type").getAsString(); + String tier = petInfoObject.get("tier").getAsString(); + switch (tier) { + case "COMMON": + internalname += ";0"; + break; + case "UNCOMMON": + internalname += ";1"; + break; + case "RARE": + internalname += ";2"; + break; + case "EPIC": + internalname += ";3"; + break; + case "LEGENDARY": + internalname += ";4"; + break; + case "MYTHIC": + internalname += ";5"; + break; + } + } + } + if ("ENCHANTED_BOOK".equals(internalname) && ea.hasKey("enchantments", 10)) { + NBTTagCompound enchants = ea.getCompoundTag("enchantments"); + + for (String enchname : enchants.getKeySet()) { + internalname = enchname.toUpperCase() + ";" + enchants.getInteger(enchname); + break; + } + } + if ("RUNE".equals(internalname) && ea.hasKey("runes", 10)) { + NBTTagCompound rune = ea.getCompoundTag("runes"); + + for (String runename : rune.getKeySet()) { + internalname = runename.toUpperCase() + "_RUNE" + ";" + rune.getInteger(runename); + break; + } + } + if ("PARTY_HAT_CRAB".equals(internalname) && (ea.getString("party_hat_color") != null)) { + String crabhat = ea.getString("party_hat_color"); + internalname = "PARTY_HAT_CRAB" + "_" + crabhat.toUpperCase(); + } + } + + return internalname; + } + + public String[] getLoreFromNBT(NBTTagCompound tag) { + String[] lore = new String[0]; + NBTTagCompound display = tag.getCompoundTag("display"); + + if (display.hasKey("Lore", 9)) { + NBTTagList list = display.getTagList("Lore", 8); + lore = new String[list.tagCount()]; + for (int k = 0; k < list.tagCount(); k++) { + lore[k] = list.getStringTagAt(k); + } + } + return lore; + } + + public JsonObject getJsonFromNBT(NBTTagCompound tag) { + return getJsonFromNBTEntry(tag.getTagList("i", 10).getCompoundTagAt(0)); + } + + public JsonObject getJsonFromNBTEntry(NBTTagCompound tag) { + if (tag.getKeySet().size() == 0) return null; + + int id = tag.getShort("id"); + int damage = tag.getShort("Damage"); + int count = tag.getShort("Count"); + tag = tag.getCompoundTag("tag"); + + if (id == 141) id = 391; //for some reason hypixel thinks carrots have id 141 + + String internalname = getInternalnameFromNBT(tag); + if (internalname == null) return null; + + NBTTagCompound display = tag.getCompoundTag("display"); + String[] lore = getLoreFromNBT(tag); + + Item itemMc = Item.getItemById(id); + String itemid = "null"; + if (itemMc != null) { + itemid = itemMc.getRegistryName(); + } + String displayname = display.getString("Name"); + String[] info = new String[0]; + String clickcommand = ""; + + JsonObject item = new JsonObject(); + item.addProperty("internalname", internalname); + item.addProperty("itemid", itemid); + item.addProperty("displayname", displayname); + + if (tag != null && tag.hasKey("ExtraAttributes", 10)) { + NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes"); + + byte[] bytes = null; + for (String key : ea.getKeySet()) { + if (key.endsWith("backpack_data") || key.equals("new_year_cake_bag_data")) { + bytes = ea.getByteArray(key); + break; + } + } + if (bytes != null) { + JsonArray bytesArr = new JsonArray(); + for (byte b : bytes) { + bytesArr.add(new JsonPrimitive(b)); + } + item.add("item_contents", bytesArr); + } + if (ea.hasKey("dungeon_item_level")) { + item.addProperty("dungeon_item_level", ea.getInteger("dungeon_item_level")); + } + } + + if (lore != null && lore.length > 0) { + JsonArray jsonLore = new JsonArray(); + for (String line : lore) { + jsonLore.add(new JsonPrimitive(line)); + } + item.add("lore", jsonLore); + } + + item.addProperty("damage", damage); + if (count > 1) item.addProperty("count", count); + item.addProperty("nbttag", tag.toString()); + + return item; + } + + private String clean(String str) { + return str.replaceAll("(\u00a7.)|[^0-9a-zA-Z ]", "").toLowerCase().trim(); + } + + public void showRecipe(JsonObject item) { + ContainerChest container = null; + if (Minecraft.getMinecraft().thePlayer.openContainer instanceof ContainerChest) + container = (ContainerChest) Minecraft.getMinecraft().thePlayer.openContainer; + String internalName = item.get("internalname").getAsString(); + Set recipesFor = getRecipesFor(internalName); + if (container != null && + container.getLowerChestInventory().getDisplayName().getUnformattedText().equals("Craft Item")) { + Optional recipe = recipesFor.stream().filter(it -> it instanceof CraftingRecipe).findAny(); + if (recipe.isPresent()) { + craftingOverlay.setShownRecipe((CraftingRecipe) recipe.get()); + return; + } + } + if (!item.has("clickcommand")) return; + String clickcommand = item.get("clickcommand").getAsString(); + switch (clickcommand.intern()) { + case "viewrecipe": + displayGuiItemRecipe(internalName, null); + break; + case "viewoption": + neu.sendChatMessage("/viewpotion " + internalName.split(";")[0].toLowerCase(Locale.ROOT)); + } + displayGuiItemRecipe(internalName, ""); + } + + public void showRecipe(String internalName) { + showRecipe(getItemInformation().get(internalName)); + } + + /** + * Takes an item stack and produces a JsonObject. + */ + public JsonObject getJsonForItem(ItemStack stack) { + NBTTagCompound tag = stack.getTagCompound() == null ? new NBTTagCompound() : stack.getTagCompound(); + + //Item lore + String[] lore = new String[0]; + if (tag.hasKey("display", 10)) { + NBTTagCompound display = tag.getCompoundTag("display"); + + if (display.hasKey("Lore", 9)) { + NBTTagList list = display.getTagList("Lore", 8); + lore = new String[list.tagCount()]; + for (int i = 0; i < list.tagCount(); i++) { + lore[i] = list.getStringTagAt(i); + } + } + } + + if (stack.getDisplayName().endsWith(" Recipes")) { + stack.setStackDisplayName(stack.getDisplayName().substring(0, stack.getDisplayName().length() - 8)); + } + + if (lore.length > 0 && (lore[lore.length - 1].contains("Click to view recipes!") || + lore[lore.length - 1].contains("Click to view recipe!"))) { + String[] lore2 = new String[lore.length - 2]; + System.arraycopy(lore, 0, lore2, 0, lore.length - 2); + lore = lore2; + } + + JsonObject json = new JsonObject(); + json.addProperty("itemid", stack.getItem().getRegistryName()); + json.addProperty("displayname", stack.getDisplayName()); + json.addProperty("nbttag", tag.toString()); + json.addProperty("damage", stack.getItemDamage()); + + JsonArray jsonlore = new JsonArray(); + for (String line : lore) { + jsonlore.add(new JsonPrimitive(line)); + } + json.add("lore", jsonlore); + + return json; + } + + public String getInternalNameForItem(ItemStack stack) { + if (stack == null) return null; + NBTTagCompound tag = stack.getTagCompound(); + return getInternalnameFromNBT(tag); + } + + public String getUUIDForItem(ItemStack stack) { + if (stack == null) return null; + NBTTagCompound tag = stack.getTagCompound(); + return getUUIDFromNBT(tag); + } + + public void writeItemToFile(ItemStack stack) { + String internalname = getInternalNameForItem(stack); + + if (internalname == null) { + return; + } + + JsonObject json = getJsonForItem(stack); + json.addProperty("internalname", internalname); + json.addProperty("clickcommand", ""); + json.addProperty("modver", NotEnoughUpdates.VERSION); + + try { + writeJson(json, new File(new File(repoLocation, "items"), internalname + ".json")); + } catch (IOException ignored) { + } + + loadItem(internalname); + } + + public boolean displayGuiItemUsages(String internalName) { + if (!usagesMap.containsKey(internalName)) return false; + List usages = getAvailableUsagesFor(internalName); + if (usages.isEmpty()) return false; + Minecraft.getMinecraft().displayGuiScreen( + new GuiItemRecipe("Item Usages", usages, this)); + return true; + } + + public boolean displayGuiItemRecipe(String internalName, String text) { + if (!recipesMap.containsKey(internalName)) return false; + List recipes = getAvailableRecipesFor(internalName); + if (recipes.isEmpty()) return false; + Minecraft.getMinecraft().displayGuiScreen( + new GuiItemRecipe(text != null ? text : "Item Recipe", recipes, this)); + return true; + } + + /** + * Will display guiItemRecipe if a player attempted to view the recipe to an item but they didn't have the recipe + * unlocked. See NotEnoughUpdates#onGuiChat for where this method is called. + */ + public boolean failViewItem(String text) { + if (viewItemAttemptID != null && !viewItemAttemptID.isEmpty()) { + if (System.currentTimeMillis() - viewItemAttemptTime < 500) { + return displayGuiItemRecipe(viewItemAttemptID, text); + } + } + return false; + } + + /** + * Downloads a web file, appending some HTML attributes that makes wikia give us the raw wiki syntax. + */ + public CompletableFuture getWebFile(String url) { + return CompletableFuture.supplyAsync(() -> { + File f = new File(configLocation, "tmp/" + Base64.getEncoder().encodeToString(url.getBytes()) + ".html"); + if (f.exists()) { + return f; + } + + try { + f.getParentFile().mkdirs(); + f.createNewFile(); + f.deleteOnExit(); + } catch (IOException e) { + return null; + } + try ( + BufferedInputStream inStream = new BufferedInputStream(new URL( + url + "?action=raw&templates=expand").openStream()); + FileOutputStream fileOutputStream = new FileOutputStream(f) + ) { + byte[] dataBuffer = new byte[1024]; + int bytesRead; + while ((bytesRead = inStream.read(dataBuffer, 0, 1024)) != -1) { + fileOutputStream.write(dataBuffer, 0, bytesRead); + } + } catch (IOException e) { + e.printStackTrace(); + return null; + } + + return f; + }); + } + + /** + * Modified from https://www.journaldev.com/960/java-unzip-file-example + */ + private static void unzipIgnoreFirstFolder(String zipFilePath, String destDir) { + File dir = new File(destDir); + // create output directory if it doesn't exist + if (!dir.exists()) dir.mkdirs(); + FileInputStream fis; + //buffer for read and write data to file + byte[] buffer = new byte[1024]; + try { + fis = new FileInputStream(zipFilePath); + ZipInputStream zis = new ZipInputStream(fis); + ZipEntry ze = zis.getNextEntry(); + while (ze != null) { + if (!ze.isDirectory()) { + String fileName = ze.getName(); + fileName = fileName.substring(fileName.split("/")[0].length() + 1); + File newFile = new File(destDir + File.separator + fileName); + //create directories for sub directories in zip + new File(newFile.getParent()).mkdirs(); + if (!isInTree(dir, newFile)) { + throw new RuntimeException( + "Not Enough Updates detected an invalid zip file. This is a potential security risk, please report this in the Moulberry discord."); + } + FileOutputStream fos = new FileOutputStream(newFile); + int len; + while ((len = zis.read(buffer)) > 0) { + fos.write(buffer, 0, len); + } + fos.close(); + } + //close this ZipEntry + zis.closeEntry(); + ze = zis.getNextEntry(); + } + //close last ZipEntry + zis.closeEntry(); + zis.close(); + fis.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private static boolean isInTree(File rootDirectory, File file) throws IOException { + file = file.getCanonicalFile(); + rootDirectory = rootDirectory.getCanonicalFile(); + while (file != null) { + if (file.equals(rootDirectory)) return true; + file = file.getParentFile(); + } + return false; + } + + /** + * Modified from https://www.journaldev.com/960/java-unzip-file-example + */ + public static void unzip(InputStream src, File dest) { + //buffer for read and write data to file + byte[] buffer = new byte[1024]; + try { + ZipInputStream zis = new ZipInputStream(src); + ZipEntry ze = zis.getNextEntry(); + while (ze != null) { + if (!ze.isDirectory()) { + String fileName = ze.getName(); + File newFile = new File(dest, fileName); + if (!isInTree(dest, newFile)) { + throw new RuntimeException( + "Not Enough Updates detected an invalid zip file. This is a potential security risk, please report this in the Moulberry discord."); + } + //create directories for sub directories in zip + new File(newFile.getParent()).mkdirs(); + FileOutputStream fos = new FileOutputStream(newFile); + int len; + while ((len = zis.read(buffer)) > 0) { + fos.write(buffer, 0, len); + } + fos.close(); + } + //close this ZipEntry + zis.closeEntry(); + ze = zis.getNextEntry(); + } + //close last ZipEntry + zis.closeEntry(); + zis.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * From here to the end of the file are various helper functions for creating and writing json files, in particular + * json files representing skyblock item data. + */ + public JsonObject createItemJson( + String internalname, String itemid, String displayname, String[] lore, + String crafttext, String infoType, String[] info, + String clickcommand, int damage, NBTTagCompound nbttag + ) { + return createItemJson( + new JsonObject(), + internalname, + itemid, + displayname, + lore, + crafttext, + infoType, + info, + clickcommand, + damage, + nbttag + ); + } + + public JsonObject createItemJson( + JsonObject base, String internalname, String itemid, String displayname, String[] lore, + String crafttext, String infoType, String[] info, + String clickcommand, int damage, NBTTagCompound nbttag + ) { + if (internalname == null || internalname.isEmpty()) { + return null; + } + + JsonObject json = gson.fromJson(gson.toJson(base, JsonObject.class), JsonObject.class); + json.addProperty("internalname", internalname); + json.addProperty("itemid", itemid); + json.addProperty("displayname", displayname); + json.addProperty("crafttext", crafttext); + json.addProperty("clickcommand", clickcommand); + json.addProperty("damage", damage); + json.addProperty("nbttag", nbttag.toString()); + json.addProperty("modver", NotEnoughUpdates.VERSION); + json.addProperty("infoType", infoType); + + if (info != null && info.length > 0) { + JsonArray jsoninfo = new JsonArray(); + for (String line : info) { + jsoninfo.add(new JsonPrimitive(line)); + } + json.add("info", jsoninfo); + } + + JsonArray jsonlore = new JsonArray(); + for (String line : lore) { + jsonlore.add(new JsonPrimitive(line)); + } + json.add("lore", jsonlore); + + return json; + } + + public boolean writeItemJson( + String internalname, String itemid, String displayname, String[] lore, String crafttext, + String infoType, String[] info, String clickcommand, int damage, NBTTagCompound nbttag + ) { + return writeItemJson( + new JsonObject(), + internalname, + itemid, + displayname, + lore, + crafttext, + infoType, + info, + clickcommand, + damage, + nbttag + ); + } + + public boolean writeItemJson( + JsonObject base, String internalname, String itemid, String displayname, String[] lore, + String crafttext, String infoType, String[] info, String clickcommand, int damage, NBTTagCompound nbttag + ) { + JsonObject json = createItemJson( + base, + internalname, + itemid, + displayname, + lore, + crafttext, + infoType, + info, + clickcommand, + damage, + nbttag + ); + if (json == null) { + return false; + } + + try { + writeJsonDefaultDir(json, internalname + ".json"); + } catch (IOException e) { + return false; + } + + loadItem(internalname); + return true; + } + + public void writeJson(JsonObject json, File file) throws IOException { + file.createNewFile(); + + try ( + BufferedWriter writer = new BufferedWriter(new OutputStreamWriter( + new FileOutputStream(file), + StandardCharsets.UTF_8 + )) + ) { + writer.write(gson.toJson(json)); + } + } + + public void writeJsonDefaultDir(JsonObject json, String filename) throws IOException { + File file = new File(new File(repoLocation, "items"), filename); + writeJson(json, file); + } + + public JsonObject readJsonDefaultDir(String filename) throws IOException { + File f = new File(new File(repoLocation, "items"), filename); + if (f.exists() && f.isFile() && f.canRead()) + try (Reader reader = new InputStreamReader(new FileInputStream(f), StandardCharsets.UTF_8)) { + return gson.fromJson(reader, JsonObject.class); + } // rethrow io exceptions + return null; + } + + public TreeMap getItemInformation() { + return itemMap; + } + + public String removeUnusedDecimal(double num) { + if (num % 1 == 0) { + return String.valueOf((int) num); + } else { + return String.valueOf(num); + } + } + + public HashMap getLoreReplacements(String petname, String tier, int level) { + JsonObject petnums = null; + if (petname != null && tier != null) { + petnums = Constants.PETNUMS; + } + + HashMap replacements = new HashMap<>(); + if (level < 1) { + if (Constants.PETS != null && Constants.PETS.has("custom_pet_leveling") && + Constants.PETS.getAsJsonObject("custom_pet_leveling").has(petname) && + Constants.PETS.getAsJsonObject("custom_pet_leveling").getAsJsonObject(petname).has("max_level")) { + int maxLvl = + Constants.PETS.getAsJsonObject("custom_pet_leveling").getAsJsonObject(petname).get("max_level").getAsInt(); + replacements.put("LVL", "1\u27A1" + maxLvl); + } else { + replacements.put("LVL", "1\u27A1100"); + } + } else { + replacements.put("LVL", "" + level); + } + + if (petnums != null) { + if (petnums.has(petname)) { + JsonObject petInfo = petnums.get(petname).getAsJsonObject(); + if (petInfo.has(tier)) { + JsonObject petInfoTier = petInfo.get(tier).getAsJsonObject(); + if (petInfoTier == null || !petInfoTier.has("1") || !petInfoTier.has("100")) { + return replacements; + } + + JsonObject min = petInfoTier.get("1").getAsJsonObject(); + JsonObject max = petInfoTier.get("100").getAsJsonObject(); + + if (level < 1) { + JsonArray otherNumsMin = min.get("otherNums").getAsJsonArray(); + JsonArray otherNumsMax = max.get("otherNums").getAsJsonArray(); + boolean addZero = false; + if (petInfoTier.has("stats_levelling_curve")) { + String[] stringArray = petInfoTier.get("stats_levelling_curve").getAsString().split(":"); + if (stringArray.length == 3) { + int type = Integer.parseInt(stringArray[2]); + if (type == 1) { + addZero = true; + } + } + } + for (int i = 0; i < otherNumsMax.size(); i++) { + replacements.put( + "" + i, + (addZero ? "0\u27A1" : "") + + removeUnusedDecimal(Math.floor(otherNumsMin.get(i).getAsFloat() * 10) / 10f) + + "\u27A1" + removeUnusedDecimal(Math.floor(otherNumsMax.get(i).getAsFloat() * 10) / 10f) + ); + } + + for (Map.Entry entry : max.get("statNums").getAsJsonObject().entrySet()) { + int statMax = (int) Math.floor(entry.getValue().getAsFloat()); + int statMin = (int) Math.floor(min.get("statNums").getAsJsonObject().get(entry.getKey()).getAsFloat()); + String statStr = (statMin > 0 ? "+" : "") + statMin + "\u27A1" + statMax; + statStr = (addZero ? "0\u27A1" : "") + statStr; + replacements.put(entry.getKey(), statStr); + } + } else { + + int minStatsLevel = 0; + int maxStatsLevel = 100; + int statsLevelingType = -1; + + int statsLevel = level; + + if (petInfoTier.has("stats_levelling_curve")) { + String[] stringArray = petInfoTier.get("stats_levelling_curve").getAsString().split(":"); + if (stringArray.length == 3) { + minStatsLevel = Integer.parseInt(stringArray[0]); + maxStatsLevel = Integer.parseInt(stringArray[1]); + statsLevelingType = Integer.parseInt(stringArray[2]); + switch (statsLevelingType) { + //Case for maybe a pet that might exist + case 0: + case 1: + if (level < minStatsLevel) { + statsLevel = 1; + } else if (level < maxStatsLevel) { + statsLevel = level - minStatsLevel + 1; + } else { + statsLevel = maxStatsLevel - minStatsLevel + 1; + } + break; + + } + } + } + float minMix = (maxStatsLevel - (minStatsLevel - (statsLevelingType == -1 ? 0 : 1)) - statsLevel) / 99f; + float maxMix = (statsLevel - 1) / 99f; + + JsonArray otherNumsMin = min.get("otherNums").getAsJsonArray(); + JsonArray otherNumsMax = max.get("otherNums").getAsJsonArray(); + for (int i = 0; i < otherNumsMax.size(); i++) { + float val = otherNumsMin.get(i).getAsFloat() * minMix + otherNumsMax.get(i).getAsFloat() * maxMix; + if (statsLevelingType == 1 && level < minStatsLevel) { + replacements.put("" + i, "0"); + } else { + replacements.put("" + i, removeUnusedDecimal(Math.floor(val * 10) / 10f)); + } + } + + for (Map.Entry entry : max.get("statNums").getAsJsonObject().entrySet()) { + if (statsLevelingType == 1 && level < minStatsLevel) { + replacements.put(entry.getKey(), "0"); + } else { + float statMax = entry.getValue().getAsFloat(); + float statMin = min.get("statNums").getAsJsonObject().get(entry.getKey()).getAsFloat(); + float val = statMin * minMix + statMax * maxMix; + String statStr = (statMin > 0 ? "+" : "") + (int) Math.floor(val); + replacements.put(entry.getKey(), statStr); + } + } + } + } + } + } + + return replacements; + } + + public HashMap getLoreReplacements(NBTTagCompound tag, int level) { + String petname = null; + String tier = null; + if (tag != null && tag.hasKey("ExtraAttributes")) { + NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes"); + if (ea.hasKey("petInfo")) { + String petInfoStr = ea.getString("petInfo"); + JsonObject petInfo = gson.fromJson(petInfoStr, JsonObject.class); + petname = petInfo.get("type").getAsString(); + tier = petInfo.get("tier").getAsString(); + if (petInfo.has("heldItem")) { + String heldItem = petInfo.get("heldItem").getAsString(); + if (heldItem.equals("PET_ITEM_TIER_BOOST")) { + switch (tier) { + case "COMMON": + tier = "UNCOMMON"; + break; + case "UNCOMMON": + tier = "RARE"; + break; + case "RARE": + tier = "EPIC"; + break; + case "EPIC": + tier = "LEGENDARY"; + break; + case "LEGENDARY": + tier = "MYTHIC"; + break; + } + } + } + } + } + return getLoreReplacements(petname, tier, level); + } + + public NBTTagList processLore(JsonArray lore, HashMap replacements) { + NBTTagList nbtLore = new NBTTagList(); + for (JsonElement line : lore) { + String lineStr = line.getAsString(); + if (!lineStr.contains("Click to view recipes!") && + !lineStr.contains("Click to view recipe!")) { + for (Map.Entry entry : replacements.entrySet()) { + lineStr = lineStr.replace("{" + entry.getKey() + "}", entry.getValue()); + } + nbtLore.appendTag(new NBTTagString(lineStr)); + } + } + return nbtLore; + } + + public ItemStack jsonToStack(JsonObject json) { + return jsonToStack(json, true); + } + + public ItemStack jsonToStack(JsonObject json, boolean useCache) { + return jsonToStack(json, useCache, true); + } + + public ItemStack jsonToStack(JsonObject json, boolean useCache, boolean useReplacements) { + return jsonToStack(json, useCache, useReplacements, true); + } + + public ItemStack jsonToStack(JsonObject json, boolean useCache, boolean useReplacements, boolean copyStack) { + if (json == null) return new ItemStack(Items.painting, 1, 10); + String internalname = json.get("internalname").getAsString(); + + if (useCache) { + ItemStack stack = itemstackCache.get(internalname); + if (stack != null) { + if (copyStack) { + return stack.copy(); + } else { + return stack; + } + } + } + + ItemStack stack = new ItemStack(Item.itemRegistry.getObject( + new ResourceLocation(json.get("itemid").getAsString()))); + + if (json.has("count")) { + stack.stackSize = json.get("count").getAsInt(); + } + + if (stack.getItem() == null) { + stack = new ItemStack(Item.getItemFromBlock(Blocks.stone), 0, 255); //Purple broken texture item + } else { + if (json.has("damage")) { + stack.setItemDamage(json.get("damage").getAsInt()); + } + + if (json.has("nbttag")) { + try { + NBTTagCompound tag = JsonToNBT.getTagFromJson(json.get("nbttag").getAsString()); + stack.setTagCompound(tag); + } catch (NBTException ignored) { + } + } + + HashMap replacements = new HashMap<>(); + + if (useReplacements) { + replacements = getLoreReplacements(stack.getTagCompound(), -1); + + String displayname = json.get("displayname").getAsString(); + for (Map.Entry entry : replacements.entrySet()) { + displayname = displayname.replace("{" + entry.getKey() + "}", entry.getValue()); + } + stack.setStackDisplayName(displayname); + } + + if (json.has("lore")) { + NBTTagCompound display = new NBTTagCompound(); + if (stack.getTagCompound() != null && stack.getTagCompound().hasKey("display")) { + display = stack.getTagCompound().getCompoundTag("display"); + } + display.setTag("Lore", processLore(json.get("lore").getAsJsonArray(), replacements)); + NBTTagCompound tag = stack.getTagCompound() != null ? stack.getTagCompound() : new NBTTagCompound(); + tag.setTag("display", display); + stack.setTagCompound(tag); + } + } + + if (useCache) itemstackCache.put(internalname, stack); + if (copyStack) { + return stack.copy(); + } else { + return stack; + } + } + + public void reloadRepository() { + File items = new File(repoLocation, "items"); + if (items.exists()) { + recipes.clear(); + recipesMap.clear(); + usagesMap.clear(); + + File[] itemFiles = new File(repoLocation, "items").listFiles(); + if (itemFiles != null) { + for (File f : itemFiles) { + String internalname = f.getName().substring(0, f.getName().length() - 5); + loadItem(internalname); + } + } + } + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java index 080353a78d..d1bfed14d1 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java @@ -8,18 +8,30 @@ import io.github.moulberry.notenoughupdates.core.BackgroundBlur; import io.github.moulberry.notenoughupdates.core.GuiScreenElementWrapper; import io.github.moulberry.notenoughupdates.core.util.lerp.LerpingInteger; -import io.github.moulberry.notenoughupdates.infopanes.*; +import io.github.moulberry.notenoughupdates.infopanes.DevInfoPane; +import io.github.moulberry.notenoughupdates.infopanes.InfoPane; +import io.github.moulberry.notenoughupdates.infopanes.TextInfoPane; import io.github.moulberry.notenoughupdates.itemeditor.NEUItemEditor; import io.github.moulberry.notenoughupdates.mbgui.MBAnchorPoint; import io.github.moulberry.notenoughupdates.mbgui.MBGuiElement; import io.github.moulberry.notenoughupdates.mbgui.MBGuiGroupAligned; import io.github.moulberry.notenoughupdates.mbgui.MBGuiGroupFloating; +import io.github.moulberry.notenoughupdates.miscfeatures.PetInfoOverlay; import io.github.moulberry.notenoughupdates.miscfeatures.SunTzu; +import io.github.moulberry.notenoughupdates.miscgui.GuiPriceGraph; import io.github.moulberry.notenoughupdates.options.NEUConfigEditor; -import io.github.moulberry.notenoughupdates.util.*; +import io.github.moulberry.notenoughupdates.util.Constants; +import io.github.moulberry.notenoughupdates.util.LerpingFloat; +import io.github.moulberry.notenoughupdates.util.SpecialColour; +import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.*; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.gui.GuiTextField; +import net.minecraft.client.gui.inventory.GuiChest; import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.client.gui.inventory.GuiInventory; import net.minecraft.client.renderer.*; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.renderer.entity.RenderManager; @@ -31,6 +43,8 @@ import net.minecraft.entity.EntityList; import net.minecraft.entity.EntityLivingBase; import net.minecraft.init.Items; +import net.minecraft.inventory.ContainerChest; +import net.minecraft.inventory.IInventory; import net.minecraft.inventory.Slot; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; @@ -42,17 +56,16 @@ import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import net.minecraftforge.client.ClientCommandHandler; -import org.apache.commons.lang3.StringUtils; import org.lwjgl.input.Keyboard; import org.lwjgl.input.Mouse; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL14; import org.lwjgl.util.vector.Vector2f; -import java.awt.*; +import java.awt.Color; import java.lang.reflect.InvocationTargetException; -import java.util.List; import java.util.*; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicBoolean; @@ -61,2276 +74,2800 @@ import static io.github.moulberry.notenoughupdates.util.GuiTextures.*; public class NEUOverlay extends Gui { - - private static final ResourceLocation SUPERGEHEIMNISVERMOGEN = new ResourceLocation("notenoughupdates:supersecretassets/bald.png"); - private static final ResourceLocation SEARCH_BAR = new ResourceLocation("notenoughupdates:search_bar.png"); - private static final ResourceLocation SEARCH_BAR_GOLD = new ResourceLocation("notenoughupdates:search_bar_gold.png"); - - private NEUManager manager; - - private String mobRegex = ".*?((_MONSTER)|(_ANIMAL)|(_MINIBOSS)|(_BOSS)|(_SC))$"; - private String petRegex = ".*?;[0-5]$"; - - private ResourceLocation[] sortIcons = new ResourceLocation[] { - sort_all, sort_mob, sort_pet, sort_tool, sort_armor, sort_accessory - }; - private ResourceLocation[] sortIconsActive = new ResourceLocation[] { - sort_all_active, sort_mob_active, sort_pet_active, sort_tool_active, sort_armor_active, sort_accessory_active - }; - - private ResourceLocation[] orderIcons = new ResourceLocation[] { - order_alphabetical, order_rarity, order_value - }; - private ResourceLocation[] orderIconsActive = new ResourceLocation[] { - order_alphabetical_active, order_rarity_active, order_value_active - }; - - //Various constants used for GUI structure - private final int searchBarYOffset = 10; - private final int searchBarPadding = 2; - - private float oldWidthMult = 0; - - public static final int ITEM_PADDING = 4; - public static final int ITEM_SIZE = 16; - - private Color bg = new Color(90, 90, 140, 50); - private Color fg = new Color(100,100,100, 255); - - private InfoPane activeInfoPane = null; - - private TreeSet searchedItems = null; - private final List searchedItemsArr = new ArrayList<>(); - - private HashMap> searchedItemsSubgroup = new HashMap<>(); - - private long selectedItemMillis = 0; - private int selectedItemGroupX = -1; - private int selectedItemGroupY = -1; - private List selectedItemGroup = null; - - private boolean itemPaneOpen = false; - - private int page = 0; - - private LerpingFloat itemPaneOffsetFactor = new LerpingFloat(1); - private LerpingInteger itemPaneTabOffset = new LerpingInteger(20, 50); - private LerpingFloat infoPaneOffsetFactor = new LerpingFloat(0); - - public boolean searchMode = false; - private long millisLastLeftClick = 0; - private long millisLastMouseMove = 0; - private int lastMouseX = 0; - private int lastMouseY = 0; - - public static final int overlayColourDark = new Color(0, 0, 0, 120).getRGB(); - public static final int overlayColourLight = new Color(255, 255, 255, 120).getRGB(); - - boolean mouseDown = false; - - private boolean redrawItems = false; - - private boolean searchBarHasFocus = false; - private GuiTextField textField = new GuiTextField(0, null, 0, 0, 0, 0); - - private static final int COMPARE_MODE_ALPHABETICAL = 0; - private static final int COMPARE_MODE_RARITY = 1; - private static final int COMPARE_MODE_VALUE = 2; - - private static final int SORT_MODE_ALL = 0; - private static final int SORT_MODE_MOB = 1; - private static final int SORT_MODE_PET = 2; - private static final int SORT_MODE_TOOL = 3; - private static final int SORT_MODE_ARMOR = 4; - private static final int SORT_MODE_ACCESSORY = 5; - - private boolean disabled = false; - - private int lastScreenWidth; - private int lastScreenHeight; - private int lastScale; - - private List textToDisplay = null; - - public MBGuiGroupFloating guiGroup = null; - - public NEUOverlay(NEUManager manager) { - this.manager = manager; - textField.setFocused(true); - textField.setCanLoseFocus(false); - - guiGroup = createGuiGroup(); - } - - private MBGuiElement createSearchBar() { - return new MBGuiElement() { - public int getWidth() { - int paddingUnscaled = getPaddingUnscaled(); - - return getSearchBarXSize() + 2*paddingUnscaled; - } - - public int getHeight() { - int paddingUnscaled = getPaddingUnscaled(); - - return getSearchBarYSize() + 2*paddingUnscaled; - } - - @Override - public void mouseClick(float x, float y, int mouseX, int mouseY) { - if(!NotEnoughUpdates.INSTANCE.config.toolbar.searchBar) { - return; - } - if(Mouse.getEventButtonState()) { - setSearchBarFocus(true); - if(Mouse.getEventButton() == 1) { //Right mouse button down - textField.setText(""); - updateSearch(); - } else { - if(System.currentTimeMillis() - millisLastLeftClick < 300) { - searchMode = !searchMode; - if (searchMode && NotEnoughUpdates.INSTANCE.config.hidden.firstTimeSearchFocus) { - NEUEventListener.displayNotification(Lists.newArrayList( - "\u00a7eSearch Highlight", - "\u00a77In this mode NEU will gray out non matching items in", - "\u00a77your inventory or chests.", - "\u00a77This allows you easily find items as the item will stand out.", - "\u00a77To toggle this please double click on the search bar in your inventory.", - "\u00a77", - "\u00a77Press X on your keyboard to close this notifcation"), true, true); - NotEnoughUpdates.INSTANCE.config.hidden.firstTimeSearchFocus = false; - - } - } - textField.setCursorPosition(getClickedIndex(mouseX, mouseY)); - millisLastLeftClick = System.currentTimeMillis(); - } - } - } - - @Override - public void mouseClickOutside() { - setSearchBarFocus(false); - } - - @Override - public void render(float x, float y) { - if(!NotEnoughUpdates.INSTANCE.config.toolbar.searchBar) { - return; - } - FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; - int paddingUnscaled = getPaddingUnscaled(); - - GlStateManager.color(1, 1, 1, 1); - if(searchMode) { - Minecraft.getMinecraft().getTextureManager().bindTexture(SEARCH_BAR_GOLD); - } else { - Minecraft.getMinecraft().getTextureManager().bindTexture(SEARCH_BAR); - } - - int w = getWidth(); - int h = getHeight(); - - for(int yIndex=0; yIndex<=2; yIndex++) { - for(int xIndex=0; xIndex<=2; xIndex++) { - float uMin = 0; - float uMax = 4/20f; - int partX = (int)x; - int partW = 4; - if(xIndex == 1) { - partX += 4; - uMin = 4/20f; - uMax = 16/20f; - partW = w-8; - } else if(xIndex == 2) { - partX += w-4; - uMin = 16/20f; - uMax = 20/20f; - } - - float vMin = 0; - float vMax = 4/20f; - int partY = (int)y; - int partH = 4; - if(yIndex == 1) { - partY += 4; - vMin = 4/20f; - vMax = 16/20f; - partH = h-8; - } else if(yIndex == 2) { - partY += h-4; - vMin = 16/20f; - vMax = 20/20f; - } - - Utils.drawTexturedRect(partX, partY, partW, partH, uMin, uMax, vMin, vMax, GL11.GL_NEAREST); - } - } - - //Search bar text - fr.drawString(textField.getText(), (int)x + 5, - (int) y-4 + getHeight()/2, Color.WHITE.getRGB()); - - //Determines position of cursor. Cursor blinks on and off every 500ms. - if(searchBarHasFocus && System.currentTimeMillis()%1000>500) { - String textBeforeCursor = textField.getText().substring(0, textField.getCursorPosition()); - int textBeforeCursorWidth = fr.getStringWidth(textBeforeCursor); - drawRect((int)x + 5 + textBeforeCursorWidth, - (int)y-5 + getHeight()/2, - (int)x + 5 + textBeforeCursorWidth+1, - (int)y-4+9 + getHeight()/2, Color.WHITE.getRGB()); - } - - String selectedText = textField.getSelectedText(); - if(!selectedText.isEmpty()) { - int selectionWidth = fr.getStringWidth(selectedText); - - int leftIndex = Math.min(textField.getCursorPosition(), textField.getSelectionEnd()); - String textBeforeSelection = textField.getText().substring(0, leftIndex); - int textBeforeSelectionWidth = fr.getStringWidth(textBeforeSelection); - - drawRect((int)x + 5 + textBeforeSelectionWidth, - (int)y-5 + getHeight()/2, - (int)x + 5 + textBeforeSelectionWidth + selectionWidth, - (int)y-4+9 + getHeight()/2, Color.LIGHT_GRAY.getRGB()); - - fr.drawString(selectedText, - (int)x + 5 + textBeforeSelectionWidth, - (int)y-4 + getHeight()/2, Color.BLACK.getRGB()); - } - - } - - @Override - public void recalculate() { - } - }; - } - - private MBGuiElement createSettingsButton(NEUOverlay overlay) { - return new MBGuiElement() { - @Override - public int getWidth() { - return getSearchBarYSize()+getPaddingUnscaled()*2; - } - - @Override - public int getHeight() { - return getWidth(); - } - - @Override - public void recalculate() { - } - - @Override - public void mouseClick(float x, float y, int mouseX, int mouseY) { - if(!NotEnoughUpdates.INSTANCE.config.toolbar.enableSettingsButton) { - return; - } - if(Mouse.getEventButtonState()) { - NotEnoughUpdates.INSTANCE.openGui = new GuiScreenElementWrapper(NEUConfigEditor.editor); - } - } - - @Override - public void mouseClickOutside() { - } - - @Override - public void render(float x, float y) { - int paddingUnscaled = getPaddingUnscaled(); - int searchYSize = getSearchBarYSize(); - - - if(!NotEnoughUpdates.INSTANCE.config.toolbar.enableSettingsButton) { - return; - } - Minecraft.getMinecraft().getTextureManager().bindTexture(quickcommand_background); - GlStateManager.color(1, 1, 1, 1); - Utils.drawTexturedRect(x, y, - searchYSize + paddingUnscaled * 2, searchYSize + paddingUnscaled * 2, GL11.GL_NEAREST); - - Minecraft.getMinecraft().getTextureManager().bindTexture(settings); - GlStateManager.color(1f, 1f, 1f, 1f); - Utils.drawTexturedRect((int) x + paddingUnscaled, (int) y + paddingUnscaled, - searchYSize, searchYSize); - - GlStateManager.bindTexture(0); - } - }; - } - - private MBGuiElement createHelpButton(NEUOverlay overlay) { - return new MBGuiElement() { - @Override - public int getWidth() { - return getSearchBarYSize()+getPaddingUnscaled()*2; - } - - @Override - public int getHeight() { - return getWidth(); - } - - @Override - public void recalculate() { - } - - @Override - public void mouseClick(float x, float y, int mouseX, int mouseY) { - if(!NotEnoughUpdates.INSTANCE.config.toolbar.enableHelpButton){ - return; - } - if(Mouse.getEventButtonState()) { - //displayInformationPane(HTMLInfoPane.createFromWikiUrl(overlay, manager, "Help", - // "https://moulberry.github.io/files/neu_help.html")); - //Minecraft.getMinecraft().displayGuiScreen(new HelpGUI()); - ClientCommandHandler.instance.executeCommand(Minecraft.getMinecraft().thePlayer, "/neuhelp"); - Utils.playPressSound(); - } - } - - @Override - public void mouseClickOutside() { - } - - @Override - public void render(float x, float y) { - int paddingUnscaled = getPaddingUnscaled(); - int searchYSize = getSearchBarYSize(); - - if(!NotEnoughUpdates.INSTANCE.config.toolbar.enableHelpButton) { - return; - } - - Minecraft.getMinecraft().getTextureManager().bindTexture(quickcommand_background); - GlStateManager.color(1, 1, 1, 1); - Utils.drawTexturedRect(x, y, - searchYSize + paddingUnscaled * 2, searchYSize + paddingUnscaled * 2, GL11.GL_NEAREST); - - Minecraft.getMinecraft().getTextureManager().bindTexture(help); - GlStateManager.color(1f, 1f, 1f, 1f); - Utils.drawTexturedRect((int) x + paddingUnscaled, (int) y + paddingUnscaled, - getSearchBarYSize(), getSearchBarYSize()); - GlStateManager.bindTexture(0); - - } - }; - } - - private MBGuiElement createQuickCommand(String quickCommandStr) { - return new MBGuiElement() { - @Override - public int getWidth() { - return getSearchBarYSize()+getPaddingUnscaled()*2; - } - - @Override - public int getHeight() { - return getWidth(); - } - - @Override - public void recalculate() { - } - - @Override - public void mouseClick(float x, float y, int mouseX, int mouseY) { - if(!NotEnoughUpdates.INSTANCE.config.toolbar.quickCommands) return; - - if((NotEnoughUpdates.INSTANCE.config.toolbar.quickCommandsClickType != 0 && Mouse.getEventButtonState()) || - (NotEnoughUpdates.INSTANCE.config.toolbar.quickCommandsClickType == 0 && !Mouse.getEventButtonState() && Mouse.getEventButton() != -1)) { - if(quickCommandStr.contains(":")) { - String command = quickCommandStr.split(":")[0].trim(); - if(command.startsWith("/")) { - NotEnoughUpdates.INSTANCE.sendChatMessage(command); - } else { - ClientCommandHandler.instance.executeCommand(Minecraft.getMinecraft().thePlayer, "/"+command); - } - Utils.playPressSound(); - } - } - } - - @Override - public void mouseClickOutside() { - } - - @Override - public void render(float x, float y) { - if(!NotEnoughUpdates.INSTANCE.config.toolbar.quickCommands) return; - - int paddingUnscaled = getPaddingUnscaled(); - int bigItemSize = getSearchBarYSize(); - - String[] quickCommandStrSplit = quickCommandStr.split(":"); - if(quickCommandStrSplit.length!=3) { - return; - } - String display = quickCommandStrSplit[2]; - ItemStack render = null; - float extraScale = 1; - if(display.length() > 20) { //Custom head - render = new ItemStack(Items.skull, 1, 3); - NBTTagCompound nbt = new NBTTagCompound(); - NBTTagCompound skullOwner = new NBTTagCompound(); - NBTTagCompound properties = new NBTTagCompound(); - NBTTagList textures = new NBTTagList(); - NBTTagCompound textures_0 = new NBTTagCompound(); - - String uuid = UUID.nameUUIDFromBytes(display.getBytes()).toString(); - skullOwner.setString("Id", uuid); - skullOwner.setString("Name", uuid); - - textures_0.setString("Value", display); - textures.appendTag(textures_0); - - properties.setTag("textures", textures); - skullOwner.setTag("Properties", properties); - nbt.setTag("SkullOwner", skullOwner); - render.setTagCompound(nbt); - - extraScale = 1.3f; - } else if(manager.getItemInformation().containsKey(display)) { - render = manager.jsonToStack(manager.getItemInformation().get(display), true, true); - } else { - Item item = Item.itemRegistry.getObject(new ResourceLocation(display.toLowerCase())); - if(item != null) { - render = new ItemStack(item); - } - } - if(render != null) { - NBTTagCompound tag = render.getTagCompound() != null ? render.getTagCompound() : new NBTTagCompound(); - tag.setString("qc_id", quickCommandStrSplit[0].toLowerCase().trim()); - render.setTagCompound(tag); - - Minecraft.getMinecraft().getTextureManager().bindTexture(quickcommand_background); - GlStateManager.color(1, 1, 1, 1); - Utils.drawTexturedRect(x, y, - bigItemSize + paddingUnscaled*2, bigItemSize + paddingUnscaled*2, GL11.GL_NEAREST); - - int mouseX = Mouse.getX() * Utils.peekGuiScale().getScaledWidth() / Minecraft.getMinecraft().displayWidth; - int mouseY = Utils.peekGuiScale().getScaledHeight() - Mouse.getY() * Utils.peekGuiScale().getScaledHeight() / Minecraft.getMinecraft().displayHeight - 1; - - if(mouseX > x && mouseX < x+bigItemSize) { - if(mouseY > y && mouseY < y+bigItemSize) { - textToDisplay = new ArrayList<>(); - textToDisplay.add(EnumChatFormatting.GRAY+quickCommandStrSplit[1]); - } - } - - GlStateManager.enableDepth(); - float itemScale = bigItemSize/(float)ITEM_SIZE*extraScale; - GlStateManager.pushMatrix(); - GlStateManager.scale(itemScale, itemScale, 1); - GlStateManager.translate((x-(extraScale-1)*bigItemSize/2+paddingUnscaled) /itemScale, - (y-(extraScale-1)*bigItemSize/2+paddingUnscaled)/itemScale, 0f); - Utils.drawItemStack(render, 0, 0); - GlStateManager.popMatrix(); - } - } - }; - } - - private MBGuiGroupAligned createQuickCommandGroup() { - List children = new ArrayList<>(); - for(String quickCommand : NotEnoughUpdates.INSTANCE.config.hidden.quickCommands) { - children.add(createQuickCommand(quickCommand)); - } - return new MBGuiGroupAligned(children, false) { - public int getPadding() { - return getPaddingUnscaled()*4; - } - }; - } - - private MBGuiGroupAligned createSearchBarGroup() { - List children = Lists.newArrayList(createSettingsButton(this), createSearchBar(), createHelpButton(this)); - return new MBGuiGroupAligned(children, false) { - public int getPadding() { - return getPaddingUnscaled()*4; - } - }; - } - - private MBGuiGroupFloating createGuiGroup() { - LinkedHashMap map = new LinkedHashMap<>(); - - MBAnchorPoint searchBarAnchor = MBAnchorPoint.createFromString(NotEnoughUpdates.INSTANCE.config.hidden.overlaySearchBar); - MBAnchorPoint quickCommandAnchor = MBAnchorPoint.createFromString(NotEnoughUpdates.INSTANCE.config.hidden.overlayQuickCommand); - - searchBarAnchor = searchBarAnchor != null ? searchBarAnchor : - new MBAnchorPoint(MBAnchorPoint.AnchorPoint.BOTMID, new Vector2f(0, -searchBarYOffset)); - quickCommandAnchor = quickCommandAnchor != null ? quickCommandAnchor : - new MBAnchorPoint(MBAnchorPoint.AnchorPoint.BOTMID, new Vector2f(0, - -searchBarYOffset-getSearchBarYSize()-getPaddingUnscaled()*4)); - - map.put(createSearchBarGroup(), searchBarAnchor); - map.put(createQuickCommandGroup(), quickCommandAnchor); - - return new MBGuiGroupFloating(Utils.peekGuiScale().getScaledWidth(), Utils.peekGuiScale().getScaledHeight(), map); - } - - public void resetAnchors(boolean onlyIfNull) { - MBAnchorPoint searchBarAnchor = MBAnchorPoint.createFromString(NotEnoughUpdates.INSTANCE.config.hidden.overlaySearchBar); - MBAnchorPoint quickCommandAnchor = MBAnchorPoint.createFromString(NotEnoughUpdates.INSTANCE.config.hidden.overlayQuickCommand); - - if(onlyIfNull) { - searchBarAnchor = searchBarAnchor != null ? null : - new MBAnchorPoint(MBAnchorPoint.AnchorPoint.BOTMID, new Vector2f(0, -searchBarYOffset)); - quickCommandAnchor = quickCommandAnchor != null ? null : - new MBAnchorPoint(MBAnchorPoint.AnchorPoint.BOTMID, new Vector2f(0, - -searchBarYOffset-getSearchBarYSize()-getPaddingUnscaled()*4)); - } else { - searchBarAnchor = searchBarAnchor != null ? searchBarAnchor : - new MBAnchorPoint(MBAnchorPoint.AnchorPoint.BOTMID, new Vector2f(0, -searchBarYOffset)); - quickCommandAnchor = quickCommandAnchor != null ? quickCommandAnchor : - new MBAnchorPoint(MBAnchorPoint.AnchorPoint.BOTMID, new Vector2f(0, - -searchBarYOffset-getSearchBarYSize()-getPaddingUnscaled()*4)); - } - - - int index = 0; - Set set = new LinkedHashSet<>(guiGroup.getChildrenMap().keySet()); - for(MBGuiElement element : set) { - switch(index) { - case 0: - if(searchBarAnchor == null) continue; - guiGroup.getChildrenMap().get(element).anchorPoint = searchBarAnchor.anchorPoint; - guiGroup.getChildrenMap().get(element).offset = searchBarAnchor.offset; - break; - case 1: - if(quickCommandAnchor == null) continue; - guiGroup.getChildrenMap().get(element).anchorPoint = quickCommandAnchor.anchorPoint; - guiGroup.getChildrenMap().get(element).offset = quickCommandAnchor.offset; - break; - } - index++; - } - } - - /** - * Disables searchBarFocus and resets the item pane position. Called whenever NEUOverlay is opened. - */ - public void reset() { - searchBarHasFocus = false; - if(!(searchMode || (NotEnoughUpdates.INSTANCE.config.itemlist.keepopen && itemPaneOpen))) { - itemPaneOpen = false; - itemPaneOffsetFactor.setValue(1); - itemPaneTabOffset.setValue(20); - } - if(activeInfoPane != null) activeInfoPane.reset(); - guiGroup.recalculate(); - } - - /** - * Calls #displayInformationPane with a HTMLInfoPane created from item.info and item.infoType. - */ - public void showInfo(JsonObject item) { - if(item.has("info") && item.has("infoType")) { - JsonArray lore = item.get("info").getAsJsonArray(); - String[] loreA = new String[lore.size()]; - for (int i = 0; i < lore.size(); i++) loreA[i] = lore.get(i).getAsString(); - String loreS = StringUtils.join(loreA, "\n"); - - String internalname = item.get("internalname").getAsString(); - String name = item.get("displayname").getAsString(); - switch(item.get("infoType").getAsString()) { - case "WIKI_URL": - displayInformationPane(HTMLInfoPane.createFromWikiUrl(this, manager, name, loreS)); - return; - case "WIKI": - displayInformationPane(HTMLInfoPane.createFromWiki(this, manager, name, internalname, loreS)); - return; - case "HTML": - displayInformationPane(new HTMLInfoPane(this, manager, name, internalname, loreS)); - return; - } - displayInformationPane(new TextInfoPane(this, manager, name, loreS)); - } - } - - public void mouseInputInv() { - if(Minecraft.getMinecraft().currentScreen instanceof GuiContainer) { - if(Mouse.getEventButton() == manager.keybindItemSelect.getKeyCode()+100 && NotEnoughUpdates.INSTANCE.config.toolbar.searchBar) { - Slot slot = Utils.getSlotUnderMouse((GuiContainer)Minecraft.getMinecraft().currentScreen); - if(slot != null) { - ItemStack hover = slot.getStack(); - if(hover != null) { - textField.setText("id:"+manager.getInternalNameForItem(hover)); - itemPaneOpen = true; - updateSearch(); - } - } - } - } - } - - /** - * Handles the mouse input, cancelling the forge event if a NEU gui element is clicked. - */ - public boolean mouseInput() { - if(disabled) { - return false; - } - - Utils.pushGuiScale(NotEnoughUpdates.INSTANCE.config.itemlist.paneGuiScale); - - int width = Utils.peekGuiScale().getScaledWidth(); - int height = Utils.peekGuiScale().getScaledHeight(); - int mouseX = Mouse.getX() * width / Minecraft.getMinecraft().displayWidth; - int mouseY = height - Mouse.getY() * height / Minecraft.getMinecraft().displayHeight - 1; - - //if(lastMouseX != mouseX || lastMouseY != mouseY) { - // millisLastMouseMove = System.currentTimeMillis(); - //} - - lastMouseX = mouseX; - lastMouseY = mouseY; - - if(Mouse.getEventButtonState()) { - mouseDown = true; - } else if(Mouse.getEventButton() != -1) { - mouseDown = false; - } - - //Unfocuses the search bar by default. Search bar is focused if the click is on the bar itself. - if(Mouse.getEventButtonState()) setSearchBarFocus(false); - - guiGroup.mouseClick(0, 0, mouseX, mouseY); - - if(selectedItemGroup != null) { - int selectedX = Math.min(selectedItemGroupX, width-getBoxPadding()-18*selectedItemGroup.size()); - if(mouseY > selectedItemGroupY+17 && mouseY < selectedItemGroupY+35) { - for(int i=0; i= selectedX-1+18*i && mouseX <= selectedX+17+18*i) { - JsonObject item = selectedItemGroup.get(i); - if (item != null) { - if(Mouse.getEventButton() == 0) { - manager.showRecipe(item); - } else if(Mouse.getEventButton() == 1) { - showInfo(item); - } else if(Mouse.getEventButton() == manager.keybindItemSelect.getKeyCode()+100 && NotEnoughUpdates.INSTANCE.config.toolbar.searchBar) { - textField.setText("id:"+item.get("internalname").getAsString()); - updateSearch(); - searchMode = true; - } - } - Utils.pushGuiScale(-1); - return true; - } - } - } - } - - //Item selection (right) gui - if(mouseX > width*getItemPaneOffsetFactor()) { - if(!Mouse.getEventButtonState()) { - Utils.pushGuiScale(-1); - return true; //End early if the mouse isn't pressed, but still cancel event. - } - - AtomicBoolean clickedItem = new AtomicBoolean(false); - iterateItemSlots(new ItemSlotConsumer() { - public void consume(int x, int y, int id) { - if(mouseX >= x-1 && mouseX <= x+ITEM_SIZE+1) { - if(mouseY >= y-1 && mouseY <= y+ITEM_SIZE+1) { - clickedItem.set(true); - - JsonObject item = getSearchedItemPage(id); - if (item != null) { - if(Mouse.getEventButton() == 0) { - manager.showRecipe(item); - } else if(Mouse.getEventButton() == 1) { - showInfo(item); - } else if(Mouse.getEventButton() == manager.keybindItemSelect.getKeyCode()+100 && NotEnoughUpdates.INSTANCE.config.toolbar.searchBar) { - textField.setText("id:"+item.get("internalname").getAsString()); - updateSearch(); - searchMode = true; - } - } - } - } - } - }); - if(!clickedItem.get()) { - int paneWidth = (int)(width/3*getWidthMult()); - int leftSide = (int)(width*getItemPaneOffsetFactor()); - int rightSide = leftSide+paneWidth-getBoxPadding()-getItemBoxXPadding(); - leftSide = leftSide+getBoxPadding()+getItemBoxXPadding(); - - FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; - int maxPages = getMaxPages(); - String name = Utils.peekGuiScale().getScaleFactor()<4?"Page: ":""; - float maxStrLen = fr.getStringWidth(EnumChatFormatting.BOLD+name + maxPages + "/" + maxPages); - float maxButtonXSize = (rightSide-leftSide+2 - maxStrLen*0.5f - 10)/2f; - int buttonXSize = (int)Math.min(maxButtonXSize, getSearchBarYSize()*480/160f); - int ySize = (int)(buttonXSize/480f*160); - int yOffset = (int)((getSearchBarYSize()-ySize)/2f); - int top = getBoxPadding()+yOffset; - - if(mouseY >= top && mouseY <= top+ySize) { - int leftPrev = leftSide-1; - if(mouseX > leftPrev && mouseX < leftPrev+buttonXSize) { //"Previous" button - setPage(page-1); - Utils.playPressSound(); - } - int leftNext = rightSide+1-buttonXSize; - if(mouseX > leftNext && mouseX < leftNext+buttonXSize) { //"Next" button - setPage(page+1); - Utils.playPressSound(); - } - } - - float sortIconsMinX = (sortIcons.length+orderIcons.length)*(ITEM_SIZE+ITEM_PADDING)+ITEM_SIZE; - float availableX = rightSide-leftSide; - float sortOrderScaleFactor = Math.min(1, availableX / sortIconsMinX); - - int scaledITEM_SIZE = (int)(ITEM_SIZE*sortOrderScaleFactor); - int scaledItemPaddedSize = (int)((ITEM_SIZE+ITEM_PADDING)*sortOrderScaleFactor); - int iconTop = height-getBoxPadding()-(ITEM_SIZE+scaledITEM_SIZE)/2-1; - - if(mouseY >= iconTop && mouseY <= iconTop+scaledITEM_SIZE) { - for(int i=0; i= orderIconX && mouseX <= orderIconX+scaledITEM_SIZE) { - if(Mouse.getEventButton() == 0) { - NotEnoughUpdates.INSTANCE.config.hidden.compareMode = i; - updateSearch(); - Utils.playPressSound(); - } else if(Mouse.getEventButton() == 1) { - NotEnoughUpdates.INSTANCE.config.hidden.compareAscending.set(i, - !NotEnoughUpdates.INSTANCE.config.hidden.compareAscending.get(i)); - updateSearch(); - Utils.playPressSound(); - } - } - } - - for(int i=0; i= sortIconX && mouseX <= sortIconX+scaledITEM_SIZE) { - NotEnoughUpdates.INSTANCE.config.hidden.sortMode = i; - updateSearch(); - Utils.playPressSound(); - } - } - } - } - Utils.pushGuiScale(-1); - return true; - } - - //Clicking on "close info pane" button - if(mouseX > width*getInfoPaneOffsetFactor()-getBoxPadding()-8 && mouseX < width*getInfoPaneOffsetFactor()-getBoxPadding()+8) { - if(mouseY > getBoxPadding()-8 && mouseY < getBoxPadding()+8) { - if(Mouse.getEventButtonState() && Mouse.getEventButton() < 2) { //Left or right click up - displayInformationPane(null); - Utils.pushGuiScale(-1); - return true; - } - } - } - - if(activeInfoPane != null) { - if(mouseX < width*getInfoPaneOffsetFactor()) { - activeInfoPane.mouseInput(width, height, mouseX, mouseY, mouseDown); - Utils.pushGuiScale(-1); - return true; - } else if(Mouse.getEventButton() <= 1 && Mouse.getEventButtonState()) { //Left or right click - activeInfoPane.mouseInputOutside(); - } - } - - Utils.pushGuiScale(-1); - return false; - } - - public int getPaddingUnscaled() { - int paddingUnscaled = searchBarPadding/Utils.peekGuiScale().getScaleFactor(); - if(paddingUnscaled < 1) paddingUnscaled = 1; - - return paddingUnscaled; - } - - public GuiTextField getTextField() { - return textField; - } - - /** - * Returns searchBarXSize, scaled by 0.8 if gui scale == AUTO. - */ - public int getSearchBarXSize() { - int searchBarXSize = NotEnoughUpdates.INSTANCE.config.toolbar.searchBarWidth; - if(Utils.peekGuiScale().getScaleFactor()==4) return (int)(searchBarXSize*0.8); - return searchBarXSize; - } - - /** - * Sets the activeInfoPane and sets the target of the infoPaneOffsetFactor to make the infoPane "slide" out. - */ - public void displayInformationPane(InfoPane pane) { - if(pane == null) { - infoPaneOffsetFactor.setTarget(0); - } else { - infoPaneOffsetFactor.setTarget(1/3f); - } - infoPaneOffsetFactor.resetTimer(); - this.activeInfoPane = pane; - } - - public InfoPane getActiveInfoPane() { - return activeInfoPane; - } - - /** - * Finds the index of the character inside the search bar that was clicked, used to set the caret. - */ - public int getClickedIndex(int mouseX, int mouseY) { - int width = Utils.peekGuiScale().getScaledWidth(); - int height = Utils.peekGuiScale().getScaledHeight(); - - int xComp = mouseX - (width/2 - getSearchBarXSize()/2 + 5); - - String trimmed = Minecraft.getMinecraft().fontRendererObj.trimStringToWidth(textField.getText(), xComp); - int linePos = trimmed.length(); - if(linePos != textField.getText().length()) { - char after = textField.getText().charAt(linePos); - int trimmedWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth(trimmed); - int charWidth = Minecraft.getMinecraft().fontRendererObj.getCharWidth(after); - if(trimmedWidth + charWidth/2 < xComp-5) { - linePos++; - } - } - return linePos; - } - - public void setSearchBarFocus(boolean focus) { - if(focus) { - itemPaneOpen = true; - } - searchBarHasFocus = focus; - } - - /** - * Handles the keyboard input, cancelling the forge event if the search bar has focus. - */ - public boolean keyboardInput(boolean hoverInv) { - if(Minecraft.getMinecraft().currentScreen == null) return false; - Keyboard.enableRepeatEvents(true); - - int keyPressed = Keyboard.getEventKey() == 0 ? Keyboard.getEventCharacter()+256 : Keyboard.getEventKey(); - - if(disabled) { - if(Keyboard.getEventKeyState() && keyPressed == manager.keybindToggleDisplay.getKeyCode()) { - disabled = !disabled; - } - return false; - } - - if(Keyboard.isKeyDown(Keyboard.KEY_Y) && NotEnoughUpdates.INSTANCE.config.hidden.dev) { - displayInformationPane(new DevInfoPane(this, manager)); - } - - if(Keyboard.getEventKeyState()) { - if(!NotEnoughUpdates.INSTANCE.config.toolbar.searchBar) { - searchBarHasFocus = false; - } - if(searchBarHasFocus) { - if(keyPressed == 1) { - searchBarHasFocus = false; - } else { - if(textField.textboxKeyTyped(Keyboard.getEventCharacter(), keyPressed)) { - updateSearch(); - } - } - } else { - if(activeInfoPane != null) { - if(activeInfoPane.keyboardInput()) { - return true; - } - } - - if(keyPressed == manager.keybindClosePanes.getKeyCode()) { - itemPaneOffsetFactor.setValue(1); - itemPaneTabOffset.setValue(20); - itemPaneOpen = false; - displayInformationPane(null); - } - - if(keyPressed == manager.keybindToggleDisplay.getKeyCode()) { - disabled = !disabled; - return true; - } - - AtomicReference internalname = new AtomicReference<>(null); - AtomicReference itemstack = new AtomicReference<>(null); - if(Minecraft.getMinecraft().currentScreen instanceof GuiContainer && - Utils.getSlotUnderMouse((GuiContainer)Minecraft.getMinecraft().currentScreen) != null) { - Slot slot = Utils.getSlotUnderMouse((GuiContainer)Minecraft.getMinecraft().currentScreen); - ItemStack hover = slot.getStack(); - if(hover != null) { - internalname.set(manager.getInternalNameForItem(hover)); - itemstack.set(hover); - } - } else if(!hoverInv) { - Utils.pushGuiScale(NotEnoughUpdates.INSTANCE.config.itemlist.paneGuiScale); - - int width = Utils.peekGuiScale().getScaledWidth(); - int height = Utils.peekGuiScale().getScaledHeight(); - int mouseX = Mouse.getX() * width / Minecraft.getMinecraft().displayWidth; - int mouseY = height - Mouse.getY() * height / Minecraft.getMinecraft().displayHeight - 1; - - if (selectedItemGroup != null) { - int selectedX = Math.min(selectedItemGroupX, width - getBoxPadding() - 18 * selectedItemGroup.size()); - - if (mouseY > selectedItemGroupY + 17 && mouseY < selectedItemGroupY + 35) { - for (int i = 0; i < selectedItemGroup.size(); i++) { - if (mouseX >= selectedX - 1 + 18 * i && mouseX <= selectedX + 17 + 18 * i) { - internalname.set(selectedItemGroup.get(i).get("internalname").getAsString()); - } - } - } - } else { - iterateItemSlots(new ItemSlotConsumer() { - public void consume(int x, int y, int id) { - if (mouseX >= x - 1 && mouseX <= x + ITEM_SIZE + 1) { - if (mouseY >= y - 1 && mouseY <= y + ITEM_SIZE + 1) { - JsonObject json = getSearchedItemPage(id); - if (json != null) internalname.set(json.get("internalname").getAsString()); - } - } - } - }); - } - - - Utils.pushGuiScale(-1); - } - if(internalname.get() != null) { - if(itemstack.get() != null) { - if(NotEnoughUpdates.INSTANCE.config.hidden.enableItemEditing && Keyboard.getEventCharacter() == 'k') { - Minecraft.getMinecraft().displayGuiScreen(new NEUItemEditor(manager, - internalname.get(), manager.getJsonForItem(itemstack.get()))); - return true; - } - } - JsonObject item = manager.getItemInformation().get(internalname.get()); - if(item != null) { - if(keyPressed == manager.keybindViewUsages.getKeyCode()) { - manager.displayGuiItemUsages(internalname.get()); - return true; - } else if(keyPressed == manager.keybindFavourite.getKeyCode()) { - toggleFavourite(item.get("internalname").getAsString()); - return true; - } else if(keyPressed == manager.keybindViewRecipe.getKeyCode()) { - manager.showRecipe(item); - return true; - } else if(keyPressed == manager.keybindGive.getKeyCode()) { - if(Minecraft.getMinecraft().thePlayer.capabilities.isCreativeMode) { - Minecraft.getMinecraft().thePlayer.inventory.addItemStackToInventory( - manager.jsonToStack(item)); - } - } else if(NotEnoughUpdates.INSTANCE.config.hidden.enableItemEditing && Keyboard.getEventCharacter() == 'k') { - Minecraft.getMinecraft().displayGuiScreen(new NEUItemEditor(manager, - internalname.get(), item)); - return true; - } else if(keyPressed == manager.keybindItemSelect.getKeyCode() && NotEnoughUpdates.INSTANCE.config.toolbar.searchBar) { - textField.setText("id:"+internalname.get()); - itemPaneOpen = true; - updateSearch(); - } - } - } - } - } - - return searchBarHasFocus; //Cancels keyboard events if the search bar has focus - } - - public void toggleFavourite(String internalname) { - if(getFavourites().contains(internalname)) { - getFavourites().remove(internalname); - } else { - getFavourites().add(internalname); - } - updateSearch(); - } - - String[] rarityArr = new String[] { - EnumChatFormatting.WHITE+EnumChatFormatting.BOLD.toString()+"COMMON", - EnumChatFormatting.GREEN+EnumChatFormatting.BOLD.toString()+"UNCOMMON", - EnumChatFormatting.BLUE+EnumChatFormatting.BOLD.toString()+"RARE", - EnumChatFormatting.DARK_PURPLE+EnumChatFormatting.BOLD.toString()+"EPIC", - EnumChatFormatting.GOLD+EnumChatFormatting.BOLD.toString()+"LEGENDARY", - EnumChatFormatting.LIGHT_PURPLE+EnumChatFormatting.BOLD.toString()+"MYTHIC", - EnumChatFormatting.RED+EnumChatFormatting.BOLD.toString()+"SPECIAL", - }; - - /** - * Finds the rarity from the lore of an item. - * -1 = UNKNOWN - * 0 = COMMON - * 1 = UNCOMMON - * 2 = RARE - * 3 = EPIC - * 4 = LEGENDARY - * 5 = MYTHIC - * 6 = SPECIAL - */ - public int getRarity(JsonArray lore) { - for(int i=lore.size()-1; i>=0; i--) { - String line = lore.get(i).getAsString(); - - for(int j=0; j getCompareAscending() { - return NotEnoughUpdates.INSTANCE.config.hidden.compareAscending; - } - private List getFavourites() { - return NotEnoughUpdates.INSTANCE.config.hidden.favourites; - } - - /** - * Creates an item comparator used to sort the list of items according to the favourite set then compare mode. - * Defaults to alphabetical sorting if the above factors cannot distinguish between two items. - */ - private Comparator getItemComparator() { - return (o1, o2) -> { - //1 (mult) if o1 should appear after o2 - //-1 (-mult) if o2 should appear after o1 - if(getFavourites().contains(o1.get("internalname").getAsString()) && !getFavourites().contains(o2.get("internalname").getAsString())) { - return -1; - } - if(!getFavourites().contains(o1.get("internalname").getAsString()) && getFavourites().contains(o2.get("internalname").getAsString())) { - return 1; - } - - int mult = getCompareAscending().get(getCompareMode()) ? 1 : -1; - if(getCompareMode() == COMPARE_MODE_RARITY) { - int rarity1 = getRarity(o1.get("lore").getAsJsonArray()); - int rarity2 = getRarity(o2.get("lore").getAsJsonArray()); - - if(rarity1 < rarity2) return mult; - if(rarity1 > rarity2) return -mult; - } else if(getCompareMode() == COMPARE_MODE_VALUE) { - String internal1 = o1.get("internalname").getAsString(); - String internal2 = o2.get("internalname").getAsString(); - - float cost1 = manager.auctionManager.getLowestBin(internal1); - float cost2 = manager.auctionManager.getLowestBin(internal2); - - - if(cost1 < cost2) return mult; - if(cost1 > cost2) return -mult; - } - - String i1 = o1.get("internalname").getAsString(); - String[] split1 = i1.split("_"); - String last1 = split1[split1.length-1]; - String start1 = i1.substring(0, i1.length()-last1.length()); - - String i2 = o2.get("internalname").getAsString(); - String[] split2 = i2.split("_"); - String last2 = split2[split2.length-1]; - String start2 = i2.substring(0, i2.length()-last2.length()); - - mult = getCompareAscending().get(COMPARE_MODE_ALPHABETICAL) ? 1 : -1; - if(start1.equals(start2)) { - String[] order = new String[]{"HELMET","CHESTPLATE","LEGGINGS","BOOTS"}; - int type1 = checkItemType(o1.get("lore").getAsJsonArray(), order); - int type2 = checkItemType(o2.get("lore").getAsJsonArray(), order); - - - if(type1 < type2) return -mult; - if(type1 > type2) return mult; - } - - int nameComp = mult*o1.get("displayname").getAsString().replaceAll("(?i)\\u00A7.", "") - .compareTo(o2.get("displayname").getAsString().replaceAll("(?i)\\u00A7.", "")); - if(nameComp != 0) { - return nameComp; - } - return mult*o1.get("internalname").getAsString().compareTo(o2.get("internalname").getAsString()); - }; - } - - /** - * Checks whether an item matches a certain type, i.e. whether the item lore ends in "{rarity} {item type}" - * eg. "SHOVEL" will return >0 for "COMMON SHOVEL", "EPIC SHOVEL", etc. - * @return the index of the type that matched, or -1 otherwise. - */ - public int checkItemType(JsonArray lore, String... typeMatches) { - for(int i=lore.size()-1; i>=0; i--) { - String line = lore.get(i).getAsString(); - - for(String rarity : rarityArr) { - for(int j=0; j= 0; - } else if(getSortMode() == SORT_MODE_ARMOR) { - return checkItemType(item.get("lore").getAsJsonArray(), "HELMET", "CHESTPLATE", "LEGGINGS", "BOOTS", "DUNGEON HELMET", "DUNGEON CHESTPLATE", "DUNGEON LEGGINGS", "DUNGEON BOOTS") >= 0; - } else if(getSortMode() == SORT_MODE_ACCESSORY) { - return checkItemType(item.get("lore").getAsJsonArray(), "ACCESSORY", "HATCCESSORY", "DUNGEON ACCESSORY") >= 0; - } - return true; - } - - private HashMap parentMap = new HashMap<>(); - - private ExecutorService searchES = Executors.newSingleThreadExecutor(); - - /** - * Clears the current item list, creating a new TreeSet if necessary. - * Adds all items that match the search AND match the sort mode to the current item list. - * Also adds some easter egg items. (Also I'm very upset if you came here to find them :'( ) - */ - public void updateSearch() { - SunTzu.randomizeQuote(); - - if(searchedItems == null) searchedItems = new TreeSet<>(getItemComparator()); - - searchES.submit(() -> { - TreeSet searchedItems = new TreeSet<>(getItemComparator()); - HashMap> searchedItemsSubgroup = new HashMap<>(); - - Set removeChildItems = new HashSet<>(); - Set itemsMatch = manager.search(textField.getText(), true); - for(String itemname : itemsMatch) { - JsonObject item = manager.getItemInformation().get(itemname); - if(checkMatchesSort(itemname, item)) { - if(Constants.PARENTS != null) { - if(Constants.PARENTS.has(itemname) && Constants.PARENTS.get(itemname).isJsonArray()) { - List children = new ArrayList<>(); - for(JsonElement e : Constants.PARENTS.get(itemname).getAsJsonArray()) { - if(e.isJsonPrimitive()) { - children.add(e.getAsString()); - } - } - children.retainAll(itemsMatch); - for(String child : children) { - removeChildItems.add(manager.getItemInformation().get(child)); - } - searchedItemsSubgroup.put(itemname, children); - } - } - searchedItems.add(item); - } - } - searchedItems.removeAll(removeChildItems); - out: - for(Map.Entry> entry : searchedItemsSubgroup.entrySet()) { - if(searchedItems.contains(manager.getItemInformation().get(entry.getKey()))) { - continue; - } - for(String itemname : entry.getValue()) { - JsonObject item = manager.getItemInformation().get(itemname); - if(item != null) searchedItems.add(item); - } - } - switch(textField.getText().toLowerCase().trim()) { - case "nullzee": - searchedItems.add(CustomItems.NULLZEE); - break; - case "rune": - searchedItems.add(CustomItems.RUNE); - break; - case "2b2t": - searchedItems.add(CustomItems.TWOBEETWOTEE); - break; - case "ducttape": - case "ducttapedigger": - searchedItems.add(CustomItems.DUCTTAPE); - break; - case "thirtyvirus": - searchedItems.add(manager.getItemInformation().get("SPIKED_BAIT")); - break; - case "leocthl": - searchedItems.add(CustomItems.LEOCTHL); - break; - case "spinaxx": - searchedItems.add(CustomItems.SPINAXX); - break; - case "credits": - case "credit": - case "who made this mod": - searchedItems.add(CustomItems.CREDITS); - break; - case "ironmoon": - case "ironm00n": - searchedItems.add(CustomItems.IRONM00N); - break; - } - - this.searchedItems = searchedItems; - this.searchedItemsSubgroup = searchedItemsSubgroup; - - synchronized(this.searchedItemsArr) { - this.searchedItemsArr.clear(); - } - - redrawItems = true; - }); - } - - /** - * Returns an index-able array containing the elements in searchedItems. - * Whenever searchedItems is updated in updateSearch(), the array is recreated here. - */ - public List getSearchedItems() { - if(searchedItems == null) { - updateSearch(); - return new ArrayList<>(); - } - - if(searchedItems.size() > 0 && searchedItemsArr.size() == 0) { - synchronized(searchedItemsArr) { - searchedItemsArr.addAll(searchedItems); - } - } - return searchedItemsArr; - } - - /** - * Gets the item in searchedItemArr corresponding to the certain index on the current page. - * @return item, if the item exists. null, otherwise. - */ - public JsonObject getSearchedItemPage(int index) { - if(index < getSlotsXSize()*getSlotsYSize()) { - int actualIndex = index + getSlotsXSize()*getSlotsYSize()*page; - List searchedItems = getSearchedItems(); - if(actualIndex < searchedItems.size()) { - return searchedItems.get(actualIndex); - } else { - return null; - } - } else { - return null; - } - } - - public int getItemBoxXPadding() { - int width = Utils.peekGuiScale().getScaledWidth(); - return (((int)(width/3*getWidthMult())-2*getBoxPadding())%(ITEM_SIZE+ITEM_PADDING)+ITEM_PADDING)/2; - } - - public int getBoxPadding() { - double panePadding = Math.max(0, Math.min(20, NotEnoughUpdates.INSTANCE.config.itemlist.panePadding)); - return (int)(panePadding*2/Utils.peekGuiScale().getScaleFactor()+5); - } - - private abstract class ItemSlotConsumer { - public abstract void consume(int x, int y, int id); - } - - public void iterateItemSlots(ItemSlotConsumer itemSlotConsumer) { - int width = Utils.peekGuiScale().getScaledWidth(); - int itemBoxXPadding = getItemBoxXPadding(); - iterateItemSlots(itemSlotConsumer, (int)(width*getItemPaneOffsetFactor())+getBoxPadding()+itemBoxXPadding); - } - - /** - * Iterates through all the item slots in the right panel and calls a ItemSlotConsumer for each slot with - * arguments equal to the slot's x and y position respectively. This is used in order to prevent - * code duplication issues. - */ - public void iterateItemSlots(ItemSlotConsumer itemSlotConsumer, int xStart) { - int width = Utils.peekGuiScale().getScaledWidth(); - int height = Utils.peekGuiScale().getScaledHeight(); - - int paneWidth = (int)(width/3*getWidthMult()); - int itemBoxYPadding = ((height-getSearchBarYSize()-2*getBoxPadding()-ITEM_SIZE-2)%(ITEM_SIZE+ITEM_PADDING)+ITEM_PADDING)/2; - - int yStart = getBoxPadding()+getSearchBarYSize()+itemBoxYPadding; - int itemBoxXPadding = getItemBoxXPadding(); - int xEnd = xStart+paneWidth-getBoxPadding()*2-ITEM_SIZE-itemBoxXPadding; - int yEnd = height-getBoxPadding()-ITEM_SIZE-2-itemBoxYPadding; - - //Render the items, displaying the tooltip if the cursor is over the item - int id = 0; - for(int y = yStart; y < yEnd; y+=ITEM_SIZE+ITEM_PADDING) { - for(int x = xStart; x < xEnd; x+=ITEM_SIZE+ITEM_PADDING) { - itemSlotConsumer.consume(x, y, id++); - } - } - } - - public float getWidthMult() { - float scaleFMult = 1; - if(Utils.peekGuiScale().getScaleFactor()==4) scaleFMult *= 0.9f; - if(manager.auctionManager.customAH.isRenderOverAuctionView() || Minecraft.getMinecraft().currentScreen instanceof CustomAHGui) scaleFMult *= 0.8f; - return (float)Math.max(0.5, Math.min(1.5, NotEnoughUpdates.INSTANCE.config.itemlist.paneWidthMult))*scaleFMult; - } - - /** - * Calculates the number of horizontal item slots. - */ - public int getSlotsXSize() { - int width = Utils.peekGuiScale().getScaledWidth(); - - int paneWidth = (int)(width/3*getWidthMult()); - int itemBoxXPadding = (((int)(width-width*getItemPaneOffsetFactor())-2*getBoxPadding())%(ITEM_SIZE+ITEM_PADDING)+ITEM_PADDING)/2; - int xStart = (int)(width*getItemPaneOffsetFactor())+getBoxPadding()+itemBoxXPadding; - int xEnd = (int)(width*getItemPaneOffsetFactor())+paneWidth-getBoxPadding()-ITEM_SIZE; - - return (int)Math.ceil((xEnd - xStart)/((float)(ITEM_SIZE+ITEM_PADDING))); - } - - /** - * Calculates the number of vertical item slots. - */ - public int getSlotsYSize() { - int height = Utils.peekGuiScale().getScaledHeight(); - - int itemBoxYPadding = ((height-getSearchBarYSize()-2*getBoxPadding()-ITEM_SIZE-2)%(ITEM_SIZE+ITEM_PADDING)+ITEM_PADDING)/2; - int yStart = getBoxPadding()+getSearchBarYSize()+itemBoxYPadding; - int yEnd = height-getBoxPadding()-ITEM_SIZE-2-itemBoxYPadding; - - return (int)Math.ceil((yEnd - yStart)/((float)(ITEM_SIZE+ITEM_PADDING))); - } - - public int getMaxPages() { - if(getSearchedItems().size() == 0) return 1; - return (int)Math.ceil(getSearchedItems().size()/(float)getSlotsYSize()/getSlotsXSize()); - } - - public int getSearchBarYSize() { - int searchBarYSize = NotEnoughUpdates.INSTANCE.config.toolbar.searchBarHeight; - return Math.max(searchBarYSize/Utils.peekGuiScale().getScaleFactor(), ITEM_SIZE); - } - - /** - * Renders the top navigation bar, can be used by InfoPane implementations (such as SettingsInfoPane). - * Renders "prev" button, index/maxIndex string, "next" button. - */ - public void renderNavElement(int leftSide, int rightSide, int maxPages, int page, String name) { - FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; - - String pageText = EnumChatFormatting.BOLD+name + page + "/" + maxPages; - - float maxStrLen = fr.getStringWidth(EnumChatFormatting.BOLD+name + maxPages + "/" + maxPages); - float maxButtonXSize = (rightSide-leftSide+2 - maxStrLen*0.5f - 10)/2f; - int buttonXSize = (int)Math.min(maxButtonXSize, getSearchBarYSize()*480/160f); - int ySize = (int)(buttonXSize/480f*160); - int yOffset = (int)((getSearchBarYSize()-ySize)/2f); - int top = getBoxPadding()+yOffset; - - int leftPressed = 0; - int rightPressed = 0; - - if(Mouse.isButtonDown(0) || Mouse.isButtonDown(1)) { - int width = Utils.peekGuiScale().getScaledWidth(); - int height = Utils.peekGuiScale().getScaledHeight(); - - int mouseX = Mouse.getX() * width / Minecraft.getMinecraft().displayWidth; - int mouseY = height - Mouse.getY() * height / Minecraft.getMinecraft().displayHeight - 1; - - if(mouseY >= top && mouseY <= top+ySize) { - int leftPrev = leftSide-1; - if(mouseX > leftPrev && mouseX < leftPrev+buttonXSize) { //"Previous" button - leftPressed = 1; - } - int leftNext = rightSide+1-buttonXSize; - if(mouseX > leftNext && mouseX < leftNext+buttonXSize) { //"Next" button - rightPressed = 1; - } - } - } - - drawRect(leftSide-1, top, leftSide-1+buttonXSize, top+ySize, fg.getRGB()); - GlStateManager.color(1f, 1f, 1f, 1f); - Minecraft.getMinecraft().getTextureManager().bindTexture(rightarrow); - Utils.drawTexturedRect(leftSide-1+leftPressed, - top+leftPressed, - buttonXSize, ySize, 1, 0, 0, 1); - Minecraft.getMinecraft().getTextureManager().bindTexture(rightarrow_overlay); - Utils.drawTexturedRect(leftSide-1, - top, - buttonXSize, ySize, 1-leftPressed, leftPressed, 1-leftPressed, leftPressed); - GlStateManager.bindTexture(0); - Utils.drawStringCenteredScaled(EnumChatFormatting.BOLD+"Prev", fr, - leftSide-1+buttonXSize*300/480f+leftPressed, - top+ySize/2f+leftPressed, false, - (int)(buttonXSize*240/480f), Color.BLACK.getRGB()); - - drawRect(rightSide+1-buttonXSize, top, rightSide+1, top+ySize, fg.getRGB()); - GlStateManager.color(1f, 1f, 1f, 1f); - Minecraft.getMinecraft().getTextureManager().bindTexture(rightarrow); - Utils.drawTexturedRect(rightSide+1-buttonXSize+rightPressed, - top+rightPressed, - buttonXSize, ySize); - Minecraft.getMinecraft().getTextureManager().bindTexture(rightarrow_overlay); - Utils.drawTexturedRect(rightSide+1-buttonXSize, - top, - buttonXSize, ySize, 1-rightPressed, rightPressed, 1-rightPressed, rightPressed); - GlStateManager.bindTexture(0); - Utils.drawStringCenteredScaled(EnumChatFormatting.BOLD+"Next", fr, - rightSide+1-buttonXSize*300/480f+rightPressed, - top+ySize/2f+rightPressed, false, - (int)(buttonXSize*240/480f), Color.BLACK.getRGB()); - - int strMaxLen = rightSide-leftSide-2*buttonXSize-10; - - drawRect(leftSide-1+buttonXSize+3, top, rightSide+1-buttonXSize-3, top+ySize, - new Color(177,177,177).getRGB()); - drawRect(leftSide+buttonXSize+3, top+1, rightSide+1-buttonXSize-3, top+ySize, - new Color(50,50,50).getRGB()); - drawRect(leftSide+buttonXSize+3, top+1, rightSide-buttonXSize-3, top+ySize-1, fg.getRGB()); - Utils.drawStringCenteredScaledMaxWidth(pageText, fr,(leftSide+rightSide)/2, - top+ySize/2f, false, strMaxLen, Color.BLACK.getRGB()); - } - - private int limCol(int col) { - return Math.min(255, Math.max(0, col)); - } - - public boolean isUsingMobsFilter() { - return getSortMode() == SORT_MODE_MOB; - } - - public float yaw = 0; - public float pitch = 20; - - /** - * Renders an entity onto the GUI at a certain x and y position. - */ - private void renderEntity(float posX, float posY, float scale, String name, Class... classes) { - EntityLivingBase[] entities = new EntityLivingBase[classes.length]; - try { - EntityLivingBase last = null; - for(int i=0; i clazz = classes[i]; - if(clazz == null) continue; - - EntityLivingBase newEnt = clazz.getConstructor(new Class[] {World.class}).newInstance(Minecraft.getMinecraft().theWorld); - - //newEnt.renderYawOffset = yaw; - //newEnt.rotationYaw = yaw; - newEnt.rotationPitch = pitch; - //newEnt.rotationYawHead = yaw; - //newEnt.prevRotationYawHead = yaw-1; - - newEnt.setCustomNameTag(name); - - if(last != null) { - last.riddenByEntity = newEnt; - newEnt.ridingEntity = last; - last.updateRiderPosition(); - } - last = newEnt; - - entities[i] = newEnt; - } - } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { - e.printStackTrace(); - return; - } - - - GlStateManager.enableColorMaterial(); - GlStateManager.pushMatrix(); - GlStateManager.translate(posX, posY, 50.0F); - GlStateManager.scale(-scale, scale, scale); - GlStateManager.rotate(180.0F, 0.0F, 0.0F, 1.0F); - - GlStateManager.rotate(135.0F, 0.0F, 1.0F, 0.0F); - RenderHelper.enableStandardItemLighting(); - GlStateManager.rotate(-135.0F, 0.0F, 1.0F, 0.0F); - - GlStateManager.rotate(pitch, 1.0F, 0.0F, 0.0F); - GlStateManager.rotate(yaw, 0.0F, 1.0F, 0.0F); - - RenderManager rendermanager = Minecraft.getMinecraft().getRenderManager(); - rendermanager.setPlayerViewY(180.0F); - rendermanager.setRenderShadow(false); - for(EntityLivingBase ent : entities) { - GL11.glColor4f(1,1,1,1); - if(ent != null) rendermanager.renderEntityWithPosYaw(ent, ent.posX, ent.posY, ent.posZ, 0.0F, 1.0F); - } - rendermanager.setRenderShadow(true); - - GlStateManager.popMatrix(); - RenderHelper.disableStandardItemLighting(); - GlStateManager.disableRescaleNormal(); - GlStateManager.setActiveTexture(OpenGlHelper.lightmapTexUnit); - GlStateManager.disableTexture2D(); - GlStateManager.setActiveTexture(OpenGlHelper.defaultTexUnit); - - GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); - } - - Shader blurShaderHorz = null; - Framebuffer blurOutputHorz = null; - Shader blurShaderVert = null; - Framebuffer blurOutputVert = null; - - /** - * Creates a projection matrix that projects from our coordinate space [0->width; 0->height] to OpenGL coordinate - * space [-1 -> 1; 1 -> -1] (Note: flipped y-axis). - * - * This is so that we can render to and from the framebuffer in a way that is familiar to us, instead of needing to - * apply scales and translations manually. - */ - private Matrix4f createProjectionMatrix(int width, int height) { - Matrix4f projMatrix = new Matrix4f(); - projMatrix.setIdentity(); - projMatrix.m00 = 2.0F / (float)width; - projMatrix.m11 = 2.0F / (float)(-height); - projMatrix.m22 = -0.0020001999F; - projMatrix.m33 = 1.0F; - projMatrix.m03 = -1.0F; - projMatrix.m13 = 1.0F; - projMatrix.m23 = -1.0001999F; - return projMatrix; - } - - public void updateGuiGroupSize() { - Utils.pushGuiScale(NotEnoughUpdates.INSTANCE.config.itemlist.paneGuiScale); - int width = Utils.peekGuiScale().getScaledWidth(); - int height = Utils.peekGuiScale().getScaledHeight(); - - if(lastScreenWidth != width || lastScreenHeight != height || Utils.peekGuiScale().getScaleFactor() != lastScale) { - guiGroup.width = width; - guiGroup.height = height; - - resetAnchors(true); - guiGroup.recalculate(); - - lastScreenWidth = width; - lastScreenHeight = height; - lastScale = Utils.peekGuiScale().getScaleFactor(); - } - - Utils.pushGuiScale(-1); - } - - int guiScaleLast = 0; - private boolean showVanillaLast = false; - - /** - * Renders the search bar, quick commands, item selection (right) and item info (left) gui elements. - */ - public void render(boolean hoverInv) { - if(disabled) { - return; - } - GlStateManager.enableDepth(); - - FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; - - Utils.resetGuiScale(); - Utils.pushGuiScale(NotEnoughUpdates.INSTANCE.config.itemlist.paneGuiScale); - - int width = Utils.peekGuiScale().getScaledWidth(); - int height = Utils.peekGuiScale().getScaledHeight(); - int mouseX = Mouse.getX() * width / Minecraft.getMinecraft().displayWidth; - int mouseY = height - Mouse.getY() * height / Minecraft.getMinecraft().displayHeight - 1; - - if(showVanillaLast != NotEnoughUpdates.INSTANCE.config.itemlist.showVanillaItems) { - showVanillaLast = NotEnoughUpdates.INSTANCE.config.itemlist.showVanillaItems; - updateSearch(); - } - - if(textField.getText().toLowerCase().contains("bald")) { - Minecraft.getMinecraft().getTextureManager().bindTexture(SUPERGEHEIMNISVERMOGEN); - GlStateManager.color(1, 1, 1, 1); - Utils.drawTexturedRect((width-64)/2f, (height-64)/2f-114, 64, 64, GL11.GL_LINEAR); - GlStateManager.bindTexture(0); - } - - SunTzu.setEnabled(textField.getText().toLowerCase().startsWith("potato")); - - updateGuiGroupSize(); - - if(guiScaleLast != Utils.peekGuiScale().getScaleFactor()) { - guiScaleLast = Utils.peekGuiScale().getScaleFactor(); - redrawItems = true; - } - - if(oldWidthMult != getWidthMult()) { - oldWidthMult = getWidthMult(); - redrawItems = true; - } - - yaw++; - yaw %= 360; - - bg = new Color(SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.itemlist.backgroundColour), true); - fg = new Color(SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.itemlist.foregroundColour)); - Color fgCustomOpacity = new Color(SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.itemlist.foregroundColour), true); - - Color fgFavourite2 = new Color(SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.itemlist.favouriteColour), true); - Color fgFavourite = new Color((int)(fgFavourite2.getRed()*0.8f), (int)(fgFavourite2.getGreen()*0.8f), - (int)(fgFavourite2.getBlue()*0.8f), fgFavourite2.getAlpha()); - - if(itemPaneOpen) { - if(itemPaneTabOffset.getValue() == 0) { - if(itemPaneOffsetFactor.getTarget() != 2/3f) { - itemPaneOffsetFactor.setTarget(2/3f); - itemPaneOffsetFactor.resetTimer(); - } - } else { - if(itemPaneTabOffset.getTarget() != 0) { - itemPaneTabOffset.setTarget(0); - itemPaneTabOffset.resetTimer(); - } - } - } else { - if(itemPaneOffsetFactor.getValue() == 1) { - if(itemPaneTabOffset.getTarget() != 20) { - itemPaneTabOffset.setTarget(20); - itemPaneTabOffset.resetTimer(); - } - } else { - if(itemPaneOffsetFactor.getTarget() != 1f) { - itemPaneOffsetFactor.setTarget(1f); - itemPaneOffsetFactor.resetTimer(); - } - } - } - - itemPaneOffsetFactor.tick(); - itemPaneTabOffset.tick(); - infoPaneOffsetFactor.tick(); - - if(page > getMaxPages()-1) setPage(getMaxPages()-1); - if(page < 0) setPage(0); - - GlStateManager.disableLighting(); - - /** - * Item selection (right) gui element rendering - */ - int paneWidth = (int)(width/3*getWidthMult()); - int leftSide = (int)(width*getItemPaneOffsetFactor()); - int rightSide = leftSide+paneWidth-getBoxPadding()-getItemBoxXPadding(); - - //Tab - if(NotEnoughUpdates.INSTANCE.config.itemlist.tabOpen) { - Minecraft.getMinecraft().getTextureManager().bindTexture(itemPaneTabArrow); - GlStateManager.color(1f, 1f, 1f, 0.3f); - Utils.drawTexturedRect(width-itemPaneTabOffset.getValue()*64/20f, height/2f - 32, 64, 64); - GlStateManager.bindTexture(0); - - if(!itemPaneOpen && mouseX > width-itemPaneTabOffset.getValue() && mouseY > height/2 - 32 - && mouseY < height/2 + 32) { - itemPaneOpen = true; - } - } - - //Atomic reference used so that below lambda doesn't complain about non-effectively-final variable - AtomicReference tooltipToDisplay = new AtomicReference<>(null); - //System.out.println(itemPaneOffsetFactor.getValue()); - if(itemPaneOffsetFactor.getValue() < 0.99) { - if(NotEnoughUpdates.INSTANCE.config.itemlist.bgBlurFactor > 0.5) { - BackgroundBlur.renderBlurredBackground(NotEnoughUpdates.INSTANCE.config.itemlist.bgBlurFactor, - width, height, - leftSide+getBoxPadding()-5, getBoxPadding()-5, - paneWidth-getBoxPadding()*2+10, height-getBoxPadding()*2+10, - itemPaneOffsetFactor.getValue() > 0.01); - Gui.drawRect(leftSide+getBoxPadding()-5, getBoxPadding()-5, - leftSide+getBoxPadding()-5+paneWidth-getBoxPadding()*2+10, - getBoxPadding()-5+height-getBoxPadding()*2+10, 0xc8101010); - } - - drawRect(leftSide+getBoxPadding()-5, getBoxPadding()-5, - leftSide+paneWidth-getBoxPadding()+5, height-getBoxPadding()+5, bg.getRGB()); - - renderNavElement(leftSide+getBoxPadding()+getItemBoxXPadding(), rightSide, getMaxPages(), page+1, - Utils.peekGuiScale().getScaleFactor()<4?"Page: ":""); - - //Sort bar - drawRect(leftSide+getBoxPadding()+getItemBoxXPadding()-1, - height-getBoxPadding()-ITEM_SIZE-2, - rightSide+1, - height-getBoxPadding(), fgCustomOpacity.getRGB()); - - float sortIconsMinX = (sortIcons.length+orderIcons.length)*(ITEM_SIZE+ITEM_PADDING)+ITEM_SIZE; - float availableX = rightSide-(leftSide+getBoxPadding()+getItemBoxXPadding()); - float sortOrderScaleFactor = Math.min(1, availableX / sortIconsMinX); - - int scaledITEM_SIZE = (int)(ITEM_SIZE*sortOrderScaleFactor); - int scaledItemPaddedSize = (int)((ITEM_SIZE+ITEM_PADDING)*sortOrderScaleFactor); - int iconTop = height-getBoxPadding()-(ITEM_SIZE+scaledITEM_SIZE)/2-1; - - boolean hoveredOverControl = false; - for(int i=0; i iconTop && mouseY < iconTop+scaledITEM_SIZE) { - if(mouseX > orderIconX && mouseX < orderIconX+scaledITEM_SIZE) { - hoveredOverControl = true; - if(System.currentTimeMillis() - millisLastMouseMove > 400) { - String text = EnumChatFormatting.GRAY+"Order "; - if(i == COMPARE_MODE_ALPHABETICAL) text += "Alphabetically"; - else if(i == COMPARE_MODE_RARITY) text += "by Rarity"; - else if(i == COMPARE_MODE_VALUE) text += "by Item Worth"; - else text = null; - if(text != null) textToDisplay = Utils.createList(text); - } - } - } - } - - for(int i=0; i iconTop && mouseY < iconTop+scaledITEM_SIZE) { - if(mouseX > sortIconX && mouseX < sortIconX+scaledITEM_SIZE) { - hoveredOverControl = true; - if(System.currentTimeMillis() - millisLastMouseMove > 400) { - String text = EnumChatFormatting.GRAY+"Filter "; - if(i == SORT_MODE_ALL) text = EnumChatFormatting.GRAY+"No Filter"; - else if(i == SORT_MODE_MOB) text += "Mobs"; - else if(i == SORT_MODE_PET) text += "Pets"; - else if(i == SORT_MODE_TOOL) text += "Tools"; - else if(i == SORT_MODE_ARMOR) text += "Armor"; - else if(i == SORT_MODE_ACCESSORY) text += "Accessories"; - else text = null; - if(text != null) textToDisplay = Utils.createList(text); - } - } - } - } - - if(!hoveredOverControl) { - millisLastMouseMove = System.currentTimeMillis(); - } - - if(selectedItemGroup != null) { - if(mouseX < selectedItemGroupX-1 || mouseX > selectedItemGroupX+17 || - mouseY < selectedItemGroupY-1 || mouseY > selectedItemGroupY+17) { - int selectedX = Math.min(selectedItemGroupX, width-getBoxPadding()-18*selectedItemGroup.size()); - if(mouseX < selectedX-1 || mouseX > selectedX-1+18*selectedItemGroup.size() || - mouseY < selectedItemGroupY+17 || mouseY > selectedItemGroupY+35) { - selectedItemGroup = null; - selectedItemMillis = -1; - } - } - } - - if(!hoverInv) { - iterateItemSlots(new ItemSlotConsumer() { - public void consume(int x, int y, int id) { - JsonObject json = getSearchedItemPage(id); - if (json == null) { - return; - } - if (mouseX > x - 1 && mouseX < x + ITEM_SIZE + 1) { - if (mouseY > y - 1 && mouseY < y + ITEM_SIZE + 1) { - String internalname = json.get("internalname").getAsString(); - if(searchedItemsSubgroup.containsKey(internalname)) { - if(selectedItemMillis == -1) selectedItemMillis = System.currentTimeMillis(); - if(System.currentTimeMillis() - selectedItemMillis > 200 && - (selectedItemGroup == null || selectedItemGroup.isEmpty())) { - - ArrayList children = new ArrayList<>(); - children.add(json); - for(String itemname : searchedItemsSubgroup.get(internalname)) { - children.add(manager.getItemInformation().get(itemname)); - } - - selectedItemGroup = children; - selectedItemGroupX = x; - selectedItemGroupY = y; - } - } else { - tooltipToDisplay.set(json); - } - } - } - } - }); - } - - //Iterate through all item slots and display the appropriate item - int itemBoxXPadding = getItemBoxXPadding(); - int xStart = (int)(width*getItemPaneOffsetFactor())+getBoxPadding()+itemBoxXPadding; - - if(OpenGlHelper.isFramebufferEnabled()) { - renderItemsFromImage(xStart, width, height); - renderEnchOverlay(); - - checkFramebufferSizes(width, height); - - if(redrawItems || !NotEnoughUpdates.INSTANCE.config.hidden.cacheRenderedItempane) { - renderItemsToImage(width, height, fgFavourite2, fgFavourite, fgCustomOpacity, true, true); - redrawItems = false; - } - } else { - renderItems(xStart, true, true, true); - } - - if(selectedItemGroup != null) { - GL11.glTranslatef(0, 0, 10); - - int selectedX = Math.min(selectedItemGroupX, width-getBoxPadding()-18*selectedItemGroup.size()); - - GlStateManager.enableDepth(); - GlStateManager.depthFunc(GL11.GL_LESS); - drawRect(selectedX, selectedItemGroupY+18, - selectedX-2+18*selectedItemGroup.size(), selectedItemGroupY+34, fgCustomOpacity.getRGB()); - drawRect(selectedX-1, selectedItemGroupY+17, - selectedX-2+18*selectedItemGroup.size(), selectedItemGroupY+34, new Color(180, 180, 180).getRGB()); - drawRect(selectedX, selectedItemGroupY+18, - selectedX-1+18*selectedItemGroup.size(), selectedItemGroupY+35, new Color(30, 30, 30).getRGB()); - drawRect(selectedX-1+2, selectedItemGroupY+17+2, - selectedX-1+18*selectedItemGroup.size()+2, selectedItemGroupY+35+2, 0xa0000000); - GlStateManager.depthFunc(GL11.GL_LEQUAL); - - GL11.glTranslatef(0, 0, 10); - - tooltipToDisplay.set(null); - if(mouseY > selectedItemGroupY+17 && mouseY < selectedItemGroupY+35) { - for(int i=0; i= selectedX-1+18*i && mouseX <= selectedX+17+18*i) { - tooltipToDisplay.set(selectedItemGroup.get(i)); - } - } - } - for(int i=0; i text = stack.getTooltip(Minecraft.getMinecraft().thePlayer, false); - - String internalname = json.get("internalname").getAsString(); - if(!NotEnoughUpdates.INSTANCE.config.tooltipTweaks.showPriceInfoInvItem) { - ItemPriceInformation.addToTooltip(text, internalname, stack); - } - - boolean hasClick = false; - boolean hasInfo = false; - if(json.has("clickcommand") && !json.get("clickcommand").getAsString().isEmpty()) { - hasClick = true; - } - if(json.has("info") && json.get("info").getAsJsonArray().size() > 0) { - hasInfo = true; - } - - if(hasClick || hasInfo) text.add(""); - if(hasClick) text.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"LMB/R : View recipe!"); - if(hasInfo) text.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"RMB : View additional information!"); - - - textToDisplay = text; - } - if(textToDisplay != null) { - Utils.drawHoveringText(textToDisplay, mouseX, mouseY, width, height, -1, fr); - textToDisplay = null; - } - - GlStateManager.enableBlend(); - GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); - GlStateManager.enableAlpha(); - GlStateManager.alphaFunc(516, 0.1F); - GlStateManager.disableLighting(); - - Utils.pushGuiScale(-1); - } - - /** - * Used in SettingsInfoPane to redraw the items when a setting changes. - */ - public void redrawItems() { - redrawItems = true; - } - - /** - * Sets the current page and marks that the itemsPane should be redrawn - * @param page - */ - public void setPage(int page) { - this.page = page; - redrawItems = true; - } - - private Framebuffer[] itemFramebuffers = new Framebuffer[2]; - - /** - * Checks whether the screen size has changed, if so it reconstructs the itemPane framebuffer and marks that the - * itemPane should be redrawn. - */ - private void checkFramebufferSizes(int width, int height) { - int sw = width*Utils.peekGuiScale().getScaleFactor(); - int sh = height*Utils.peekGuiScale().getScaleFactor(); - for(int i=0; i quads, int color) { - if(quads == null) return; - - for(BakedQuad quad : quads) { - renderer.addVertexData(quad.getVertexData()); - renderer.putColor4(color); - } - } - - /** - * Renders all the item backgrounds, either squares or squircles. - */ - private void renderItemBackgrounds(Color fgFavourite2, Color fgFavourite, Color fgCustomOpacity) { - if(fgCustomOpacity.getAlpha() == 0) return; - iterateItemSlots(new ItemSlotConsumer() { - public void consume(int x, int y, int id) { - JsonObject json = getSearchedItemPage(id); - if (json == null) { - return; - } - - Minecraft.getMinecraft().getTextureManager().bindTexture(item_mask); - if (getFavourites().contains(json.get("internalname").getAsString())) { - if(NotEnoughUpdates.INSTANCE.config.itemlist.itemStyle == 0) { - GlStateManager.color(fgFavourite2.getRed() / 255f, fgFavourite2.getGreen() / 255f, - fgFavourite2.getBlue() / 255f, fgFavourite2.getAlpha() / 255f); - Utils.drawTexturedRect(x - 1, y - 1, ITEM_SIZE + 2, ITEM_SIZE + 2, GL11.GL_NEAREST); - - GlStateManager.color(fgFavourite.getRed() / 255f, fgFavourite.getGreen() / 255f, - fgFavourite.getBlue() / 255f, fgFavourite.getAlpha() / 255f); - Utils.drawTexturedRect(x, y, ITEM_SIZE, ITEM_SIZE, GL11.GL_NEAREST); - } else { - drawRect(x-1, y-1, x+ITEM_SIZE+1, y+ITEM_SIZE+1, fgFavourite2.getRGB()); - drawRect(x, y, x+ITEM_SIZE, y+ITEM_SIZE, fgFavourite.getRGB()); - } - } else { - if(NotEnoughUpdates.INSTANCE.config.itemlist.itemStyle == 0) { - GlStateManager.color(fgCustomOpacity.getRed() / 255f, fgCustomOpacity.getGreen() / 255f, - fgCustomOpacity.getBlue() / 255f, fgCustomOpacity.getAlpha() / 255f); - Utils.drawTexturedRect(x - 1, y - 1, ITEM_SIZE + 2, ITEM_SIZE + 2, GL11.GL_NEAREST); - } else { - drawRect(x-1, y-1, x+ITEM_SIZE+1, y+ITEM_SIZE+1, fgCustomOpacity.getRGB()); - } - } - GlStateManager.bindTexture(0); - } - }, 10); - } - - private void renderItems(int xStart, boolean items, boolean entities, boolean glint) { - iterateItemSlots(new ItemSlotConsumer() { - public void consume(int x, int y, int id) { - JsonObject json = getSearchedItemPage(id); - if (json == null) { - return; - } - - if (json.has("entityrender")) { - if(!entities) return; - String name = json.get("displayname").getAsString(); - String[] split = name.split(" \\("); - name = name.substring(0, name.length() - split[split.length - 1].length() - 2); - - Class[] entities = new Class[1]; - if (json.get("entityrender").isJsonArray()) { - JsonArray entityrender = json.get("entityrender").getAsJsonArray(); - entities = new Class[entityrender.size()]; - for (int i = 0; i < entityrender.size(); i++) { - Class clazz = EntityList.stringToClassMapping.get(entityrender.get(i).getAsString()); - if (clazz != null && EntityLivingBase.class.isAssignableFrom(clazz)) { - entities[i] = (Class) clazz; - } - } - } else if (json.get("entityrender").isJsonPrimitive()) { - Class clazz = EntityList.stringToClassMapping.get(json.get("entityrender").getAsString()); - if (clazz != null && EntityLivingBase.class.isAssignableFrom(clazz)) { - entities[0] = (Class) clazz; - } - } - - float scale = 8; - if (json.has("entityscale")) { - scale *= json.get("entityscale").getAsFloat(); - } - - renderEntity(x + ITEM_SIZE / 2, y + ITEM_SIZE, scale, name, entities); - } else { - if(!items) return; - ItemStack stack = manager.jsonToStack(json, true, true, false); - if(stack != null) { - if(glint) { - Utils.drawItemStack(stack, x, y); - } else { - Utils.drawItemStackWithoutGlint(stack, x, y); - } - } - } - - GlStateManager.translate(0, 0, 50); - if(searchedItemsSubgroup.containsKey(json.get("internalname").getAsString())) { - Minecraft.getMinecraft().getTextureManager().bindTexture(item_haschild); - GlStateManager.color(1, 1, 1, 1); - Utils.drawTexturedRect(x-1, y-1, ITEM_SIZE+2, ITEM_SIZE+2, GL11.GL_NEAREST); - } - GlStateManager.translate(0, 0, -50); - } - }, xStart); - } - - public float getItemPaneOffsetFactor() { - return itemPaneOffsetFactor.getValue() * getWidthMult() + (1-getWidthMult()); - } - - public float getInfoPaneOffsetFactor() { - return infoPaneOffsetFactor.getValue() * getWidthMult(); - } - -} \ No newline at end of file + private static final ResourceLocation SUPERGEHEIMNISVERMOGEN = + new ResourceLocation("notenoughupdates:supersecretassets/bald.png"); + private static final ResourceLocation SEARCH_BAR = new ResourceLocation("notenoughupdates:search_bar.png"); + private static final ResourceLocation SEARCH_BAR_GOLD = new ResourceLocation("notenoughupdates:search_bar_gold.png"); + + private static final ResourceLocation ARMOR_DISPLAY = + new ResourceLocation("notenoughupdates:armordisplay/armordisplay.png"); + private static final ResourceLocation ARMOR_DISPLAY_GREY = + new ResourceLocation("notenoughupdates:armordisplay/armordisplay_grey.png"); + private static final ResourceLocation ARMOR_DISPLAY_DARK = + new ResourceLocation("notenoughupdates:armordisplay/armordisplay_phq_dark.png"); + private static final ResourceLocation ARMOR_DISPLAY_FSR = + new ResourceLocation("notenoughupdates:armordisplay/armordisplay_fsr.png"); + private static final ResourceLocation ARMOR_DISPLAY_TRANSPARENT = + new ResourceLocation("notenoughupdates:armordisplay/armordisplay_transparent.png"); + private static final ResourceLocation ARMOR_DISPLAY_TRANSPARENT_PET = + new ResourceLocation("notenoughupdates:armordisplay/armordisplay_transparent_pet.png"); + + private static final ResourceLocation QUESTION_MARK = new ResourceLocation("notenoughupdates:pv_unknown.png"); + + private static final ResourceLocation PET_DISPLAY = + new ResourceLocation("notenoughupdates:petdisplay/petdisplaysolo.png"); + private static final ResourceLocation PET_DISPLAY_GREY = + new ResourceLocation("notenoughupdates:petdisplay/petdisplaysolo_dark.png"); + private static final ResourceLocation PET_DISPLAY_DARK = + new ResourceLocation("notenoughupdates:petdisplay/petdisplaysolo_phqdark.png"); + private static final ResourceLocation PET_DISPLAY_FSR = + new ResourceLocation("notenoughupdates:petdisplay/petdisplaysolo_fsr.png"); + private static final ResourceLocation PET_DISPLAY_TRANSPARENT = + new ResourceLocation("notenoughupdates:petdisplay/petdisplaysolo_transparent.png"); + + private static final ResourceLocation PET_ARMOR_DISPLAY = + new ResourceLocation("notenoughupdates:petdisplay/petdisplayarmor.png"); + private static final ResourceLocation PET_ARMOR_DISPLAY_GREY = + new ResourceLocation("notenoughupdates:petdisplay/petdisplayarmor_dark.png"); + private static final ResourceLocation PET_ARMOR_DISPLAY_DARK = + new ResourceLocation("notenoughupdates:petdisplay/petdisplayarmor_phqdark.png"); + private static final ResourceLocation PET_ARMOR_DISPLAY_FSR = + new ResourceLocation("notenoughupdates:petdisplay/petdisplayarmor_fsr.png"); + private static final ResourceLocation PET_ARMOR_DISPLAY_TRANSPARENT = + new ResourceLocation("notenoughupdates:petdisplay/petdisplayarmor_transparent.png"); + + private static boolean renderingArmorHud; + private static boolean renderingPetHud; + public static boolean shouldUseCachedPet; + public static long cachedPetTimer; + + private final NEUManager manager; + + private final String mobRegex = ".*?((_MONSTER)|(_ANIMAL)|(_MINIBOSS)|(_BOSS)|(_SC))$"; + private final String petRegex = ".*?;[0-5]$"; + + private final ResourceLocation[] sortIcons = new ResourceLocation[]{ + sort_all, sort_mob, sort_pet, sort_tool, sort_armor, sort_accessory + }; + private final ResourceLocation[] sortIconsActive = new ResourceLocation[]{ + sort_all_active, sort_mob_active, sort_pet_active, sort_tool_active, sort_armor_active, sort_accessory_active + }; + + private final ResourceLocation[] orderIcons = new ResourceLocation[]{ + order_alphabetical, order_rarity, order_value + }; + private final ResourceLocation[] orderIconsActive = new ResourceLocation[]{ + order_alphabetical_active, order_rarity_active, order_value_active + }; + + //Various constants used for GUI structure + private final int searchBarYOffset = 10; + private final int searchBarPadding = 2; + private long lastSearchMode = 0; + + private float oldWidthMult = 0; + + public static final int ITEM_PADDING = 4; + public static final int ITEM_SIZE = 16; + + private Color bg = new Color(90, 90, 140, 50); + private Color fg = new Color(100, 100, 100, 255); + + private InfoPane activeInfoPane = null; + + private TreeSet searchedItems = null; + private final List searchedItemsArr = new ArrayList<>(); + + private HashMap> searchedItemsSubgroup = new HashMap<>(); + + private long selectedItemMillis = 0; + private int selectedItemGroupX = -1; + private int selectedItemGroupY = -1; + private List selectedItemGroup = null; + + private boolean itemPaneOpen = false; + + private int page = 0; + + private final LerpingFloat itemPaneOffsetFactor = new LerpingFloat(1); + private final LerpingInteger itemPaneTabOffset = new LerpingInteger(20, 50); + private final LerpingFloat infoPaneOffsetFactor = new LerpingFloat(0); + + public boolean searchMode = false; + private long millisLastLeftClick = 0; + private long millisLastMouseMove = 0; + private int lastMouseX = 0; + private int lastMouseY = 0; + + public static final int overlayColourDark = new Color(0, 0, 0, 120).getRGB(); + public static final int overlayColourLight = new Color(255, 255, 255, 120).getRGB(); + + boolean mouseDown = false; + + private boolean redrawItems = false; + + private boolean searchBarHasFocus = false; + private final GuiTextField textField = new GuiTextField(0, null, 0, 0, 0, 0); + + private static final int COMPARE_MODE_ALPHABETICAL = 0; + private static final int COMPARE_MODE_RARITY = 1; + private static final int COMPARE_MODE_VALUE = 2; + + private static final int SORT_MODE_ALL = 0; + private static final int SORT_MODE_MOB = 1; + private static final int SORT_MODE_PET = 2; + private static final int SORT_MODE_TOOL = 3; + private static final int SORT_MODE_ARMOR = 4; + private static final int SORT_MODE_ACCESSORY = 5; + + private boolean disabled = false; + + private int lastScreenWidth; + private int lastScreenHeight; + private int lastScale; + + private CompletableFuture infoPaneLoadingJob = CompletableFuture.completedFuture(null); + + private List textToDisplay = null; + + public MBGuiGroupFloating guiGroup = null; + + public NEUOverlay(NEUManager manager) { + this.manager = manager; + textField.setFocused(true); + textField.setCanLoseFocus(false); + + guiGroup = createGuiGroup(); + } + + private MBGuiElement createSearchBar() { + return new MBGuiElement() { + public int getWidth() { + int paddingUnscaled = getPaddingUnscaled(); + + return getSearchBarXSize() + 2 * paddingUnscaled; + } + + public int getHeight() { + int paddingUnscaled = getPaddingUnscaled(); + + return getSearchBarYSize() + 2 * paddingUnscaled; + } + + @Override + public void mouseClick(float x, float y, int mouseX, int mouseY) { + if (!NotEnoughUpdates.INSTANCE.config.toolbar.searchBar) { + return; + } + if (Mouse.getEventButtonState()) { + setSearchBarFocus(true); + if (Mouse.getEventButton() == 1) { //Right mouse button down + textField.setText(""); + updateSearch(); + } else { + if (System.currentTimeMillis() - millisLastLeftClick < 300) { + searchMode = !searchMode; + lastSearchMode = System.currentTimeMillis(); + if (searchMode && NotEnoughUpdates.INSTANCE.config.hidden.firstTimeSearchFocus) { + NEUEventListener.displayNotification(Lists.newArrayList( + "\u00a7eSearch Highlight", + "\u00a77In this mode NEU will gray out non matching items in", + "\u00a77your inventory or chests.", + "\u00a77This allows you easily find items as the item will stand out.", + "\u00a77To toggle this please double click on the search bar in your inventory.", + "\u00a77", + "\u00a77Press X on your keyboard to close this notification" + ), true, true); + NotEnoughUpdates.INSTANCE.config.hidden.firstTimeSearchFocus = false; + + } + } + textField.setCursorPosition(getClickedIndex(mouseX, mouseY)); + millisLastLeftClick = System.currentTimeMillis(); + if (searchMode) { + lastSearchMode = System.currentTimeMillis(); + } + } + } + } + + @Override + public void mouseClickOutside() { + setSearchBarFocus(false); + } + + @Override + public void render(float x, float y) { + if (!NotEnoughUpdates.INSTANCE.config.toolbar.searchBar) { + return; + } + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + int paddingUnscaled = getPaddingUnscaled(); + + GlStateManager.color(1, 1, 1, 1); + + Minecraft.getMinecraft().getTextureManager().bindTexture(searchMode ? SEARCH_BAR_GOLD : SEARCH_BAR); + + int w = getWidth(); + int h = getHeight(); + + for (int yIndex = 0; yIndex <= 2; yIndex++) { + for (int xIndex = 0; xIndex <= 2; xIndex++) { + float uMin = 0; + float uMax = 4 / 20f; + int partX = (int) x; + int partW = 4; + if (xIndex == 1) { + partX += 4; + uMin = 4 / 20f; + uMax = 16 / 20f; + partW = w - 8; + } else if (xIndex == 2) { + partX += w - 4; + uMin = 16 / 20f; + uMax = 20 / 20f; + } + + float vMin = 0; + float vMax = 4 / 20f; + int partY = (int) y; + int partH = 4; + if (yIndex == 1) { + partY += 4; + vMin = 4 / 20f; + vMax = 16 / 20f; + partH = h - 8; + } else if (yIndex == 2) { + partY += h - 4; + vMin = 16 / 20f; + vMax = 20 / 20f; + } + + Utils.drawTexturedRect(partX, partY, partW, partH, uMin, uMax, vMin, vMax, GL11.GL_NEAREST); + } + } + + //Search bar text + fr.drawString(textField.getText(), (int) x + 5, + (int) y - 4 + getHeight() / 2, Color.WHITE.getRGB() + ); + + //Determines position of cursor. Cursor blinks on and off every 500ms. + if (searchBarHasFocus && System.currentTimeMillis() % 1000 > 500) { + String textBeforeCursor = textField.getText().substring(0, textField.getCursorPosition()); + int textBeforeCursorWidth = fr.getStringWidth(textBeforeCursor); + drawRect((int) x + 5 + textBeforeCursorWidth, + (int) y - 5 + getHeight() / 2, + (int) x + 5 + textBeforeCursorWidth + 1, + (int) y - 4 + 9 + getHeight() / 2, Color.WHITE.getRGB() + ); + } + + String selectedText = textField.getSelectedText(); + if (!selectedText.isEmpty()) { + int selectionWidth = fr.getStringWidth(selectedText); + + int leftIndex = Math.min(textField.getCursorPosition(), textField.getSelectionEnd()); + String textBeforeSelection = textField.getText().substring(0, leftIndex); + int textBeforeSelectionWidth = fr.getStringWidth(textBeforeSelection); + + drawRect((int) x + 5 + textBeforeSelectionWidth, + (int) y - 5 + getHeight() / 2, + (int) x + 5 + textBeforeSelectionWidth + selectionWidth, + (int) y - 4 + 9 + getHeight() / 2, Color.LIGHT_GRAY.getRGB() + ); + + fr.drawString(selectedText, + (int) x + 5 + textBeforeSelectionWidth, + (int) y - 4 + getHeight() / 2, Color.BLACK.getRGB() + ); + } + + } + + @Override + public void recalculate() { + } + }; + } + + private MBGuiElement createSettingsButton(NEUOverlay overlay) { + return new MBGuiElement() { + @Override + public int getWidth() { + return getSearchBarYSize() + getPaddingUnscaled() * 2; + } + + @Override + public int getHeight() { + return getWidth(); + } + + @Override + public void recalculate() { + } + + @Override + public void mouseClick(float x, float y, int mouseX, int mouseY) { + if (!NotEnoughUpdates.INSTANCE.config.toolbar.enableSettingsButton) { + return; + } + if (Mouse.getEventButtonState()) { + NotEnoughUpdates.INSTANCE.openGui = new GuiScreenElementWrapper(NEUConfigEditor.editor); + } + } + + @Override + public void mouseClickOutside() { + } + + @Override + public void render(float x, float y) { + int paddingUnscaled = getPaddingUnscaled(); + int searchYSize = getSearchBarYSize(); + + if (!NotEnoughUpdates.INSTANCE.config.toolbar.enableSettingsButton) { + return; + } + Minecraft.getMinecraft().getTextureManager().bindTexture(quickcommand_background); + GlStateManager.color(1, 1, 1, 1); + Utils.drawTexturedRect(x, y, + searchYSize + paddingUnscaled * 2, searchYSize + paddingUnscaled * 2, GL11.GL_NEAREST + ); + + Minecraft.getMinecraft().getTextureManager().bindTexture(settings); + GlStateManager.color(1f, 1f, 1f, 1f); + Utils.drawTexturedRect((int) x + paddingUnscaled, (int) y + paddingUnscaled, + searchYSize, searchYSize + ); + + GlStateManager.bindTexture(0); + } + }; + } + + private MBGuiElement createHelpButton(NEUOverlay overlay) { + return new MBGuiElement() { + @Override + public int getWidth() { + return getSearchBarYSize() + getPaddingUnscaled() * 2; + } + + @Override + public int getHeight() { + return getWidth(); + } + + @Override + public void recalculate() { + } + + @Override + public void mouseClick(float x, float y, int mouseX, int mouseY) { + if (!NotEnoughUpdates.INSTANCE.config.toolbar.enableHelpButton) { + return; + } + if (Mouse.getEventButtonState()) { + //displayInformationPane(HTMLInfoPane.createFromWikiUrl(overlay, manager, "Help", + // "https://moulberry.github.io/files/neu_help.html")); + //Minecraft.getMinecraft().displayGuiScreen(new HelpGUI()); + ClientCommandHandler.instance.executeCommand(Minecraft.getMinecraft().thePlayer, "/neuhelp"); + Utils.playPressSound(); + } + } + + @Override + public void mouseClickOutside() { + } + + @Override + public void render(float x, float y) { + int paddingUnscaled = getPaddingUnscaled(); + int searchYSize = getSearchBarYSize(); + + if (!NotEnoughUpdates.INSTANCE.config.toolbar.enableHelpButton) { + return; + } + + Minecraft.getMinecraft().getTextureManager().bindTexture(quickcommand_background); + GlStateManager.color(1, 1, 1, 1); + Utils.drawTexturedRect(x, y, + searchYSize + paddingUnscaled * 2, searchYSize + paddingUnscaled * 2, GL11.GL_NEAREST + ); + + Minecraft.getMinecraft().getTextureManager().bindTexture(help); + GlStateManager.color(1f, 1f, 1f, 1f); + Utils.drawTexturedRect((int) x + paddingUnscaled, (int) y + paddingUnscaled, + getSearchBarYSize(), getSearchBarYSize() + ); + GlStateManager.bindTexture(0); + + } + }; + } + + private MBGuiElement createQuickCommand(String quickCommandStr) { + return new MBGuiElement() { + @Override + public int getWidth() { + return getSearchBarYSize() + getPaddingUnscaled() * 2; + } + + @Override + public int getHeight() { + return getWidth(); + } + + @Override + public void recalculate() { + } + + @Override + public void mouseClick(float x, float y, int mouseX, int mouseY) { + if (!NotEnoughUpdates.INSTANCE.config.toolbar.quickCommands) return; + + if ((NotEnoughUpdates.INSTANCE.config.toolbar.quickCommandsClickType != 0 && Mouse.getEventButtonState()) || + (NotEnoughUpdates.INSTANCE.config.toolbar.quickCommandsClickType == 0 && + !Mouse.getEventButtonState() && + Mouse.getEventButton() != -1)) { + if (quickCommandStr.contains(":")) { + String command = quickCommandStr.split(":")[0].trim(); + if (command.startsWith("/")) { + NotEnoughUpdates.INSTANCE.sendChatMessage(command); + } else { + ClientCommandHandler.instance.executeCommand(Minecraft.getMinecraft().thePlayer, "/" + command); + } + Utils.playPressSound(); + } + } + } + + @Override + public void mouseClickOutside() { + } + + @Override + public void render(float x, float y) { + if (!NotEnoughUpdates.INSTANCE.config.toolbar.quickCommands) return; + + int paddingUnscaled = getPaddingUnscaled(); + int bigItemSize = getSearchBarYSize(); + + String[] quickCommandStrSplit = quickCommandStr.split(":"); + if (quickCommandStrSplit.length != 3) { + return; + } + String display = quickCommandStrSplit[2]; + ItemStack render = null; + float extraScale = 1; + if (display.length() > 20) { //Custom head + render = new ItemStack(Items.skull, 1, 3); + NBTTagCompound nbt = new NBTTagCompound(); + NBTTagCompound skullOwner = new NBTTagCompound(); + NBTTagCompound properties = new NBTTagCompound(); + NBTTagList textures = new NBTTagList(); + NBTTagCompound textures_0 = new NBTTagCompound(); + + String uuid = UUID.nameUUIDFromBytes(display.getBytes()).toString(); + skullOwner.setString("Id", uuid); + skullOwner.setString("Name", uuid); + + textures_0.setString("Value", display); + textures.appendTag(textures_0); + + properties.setTag("textures", textures); + skullOwner.setTag("Properties", properties); + nbt.setTag("SkullOwner", skullOwner); + render.setTagCompound(nbt); + + extraScale = 1.3f; + } else if (manager.getItemInformation().containsKey(display)) { + render = manager.jsonToStack(manager.getItemInformation().get(display), true, true); + } else { + Item item = Item.itemRegistry.getObject(new ResourceLocation(display.toLowerCase())); + if (item != null) { + render = new ItemStack(item); + } + } + if (render != null) { + NBTTagCompound tag = render.getTagCompound() != null ? render.getTagCompound() : new NBTTagCompound(); + tag.setString("qc_id", quickCommandStrSplit[0].toLowerCase().trim()); + render.setTagCompound(tag); + + Minecraft.getMinecraft().getTextureManager().bindTexture(quickcommand_background); + GlStateManager.color(1, 1, 1, 1); + Utils.drawTexturedRect(x, y, + bigItemSize + paddingUnscaled * 2, bigItemSize + paddingUnscaled * 2, GL11.GL_NEAREST + ); + + int mouseX = Mouse.getX() * Utils.peekGuiScale().getScaledWidth() / Minecraft.getMinecraft().displayWidth; + int mouseY = Utils.peekGuiScale().getScaledHeight() - + Mouse.getY() * Utils.peekGuiScale().getScaledHeight() / Minecraft.getMinecraft().displayHeight - + 1; + + if (mouseX > x && mouseX < x + bigItemSize) { + if (mouseY > y && mouseY < y + bigItemSize) { + textToDisplay = new ArrayList<>(); + textToDisplay.add(EnumChatFormatting.GRAY + quickCommandStrSplit[1]); + } + } + + GlStateManager.enableDepth(); + float itemScale = bigItemSize / (float) ITEM_SIZE * extraScale; + GlStateManager.pushMatrix(); + GlStateManager.scale(itemScale, itemScale, 1); + GlStateManager.translate((x - (extraScale - 1) * bigItemSize / 2 + paddingUnscaled) / itemScale, + (y - (extraScale - 1) * bigItemSize / 2 + paddingUnscaled) / itemScale, 0f + ); + Utils.drawItemStack(render, 0, 0); + GlStateManager.popMatrix(); + } + } + }; + } + + private MBGuiGroupAligned createQuickCommandGroup() { + List children = new ArrayList<>(); + for (String quickCommand : NotEnoughUpdates.INSTANCE.config.hidden.quickCommands) { + children.add(createQuickCommand(quickCommand)); + } + return new MBGuiGroupAligned(children, false) { + public int getPadding() { + return getPaddingUnscaled() * 4; + } + }; + } + + private MBGuiGroupAligned createSearchBarGroup() { + List children = + Lists.newArrayList(createSettingsButton(this), createSearchBar(), createHelpButton(this)); + return new MBGuiGroupAligned(children, false) { + public int getPadding() { + return getPaddingUnscaled() * 4; + } + }; + } + + private MBGuiGroupFloating createGuiGroup() { + LinkedHashMap map = new LinkedHashMap<>(); + + MBAnchorPoint searchBarAnchor = + MBAnchorPoint.createFromString(NotEnoughUpdates.INSTANCE.config.hidden.overlaySearchBar); + MBAnchorPoint quickCommandAnchor = + MBAnchorPoint.createFromString(NotEnoughUpdates.INSTANCE.config.hidden.overlayQuickCommand); + + searchBarAnchor = searchBarAnchor != null ? searchBarAnchor : + new MBAnchorPoint(MBAnchorPoint.AnchorPoint.BOTMID, new Vector2f(0, -searchBarYOffset)); + quickCommandAnchor = quickCommandAnchor != null ? quickCommandAnchor : + new MBAnchorPoint(MBAnchorPoint.AnchorPoint.BOTMID, new Vector2f( + 0, + -searchBarYOffset - getSearchBarYSize() - getPaddingUnscaled() * 4 + )); + + map.put(createSearchBarGroup(), searchBarAnchor); + map.put(createQuickCommandGroup(), quickCommandAnchor); + + return new MBGuiGroupFloating(Utils.peekGuiScale().getScaledWidth(), Utils.peekGuiScale().getScaledHeight(), map); + } + + public void resetAnchors(boolean onlyIfNull) { + MBAnchorPoint searchBarAnchor = + MBAnchorPoint.createFromString(NotEnoughUpdates.INSTANCE.config.hidden.overlaySearchBar); + MBAnchorPoint quickCommandAnchor = + MBAnchorPoint.createFromString(NotEnoughUpdates.INSTANCE.config.hidden.overlayQuickCommand); + + if (onlyIfNull) { + searchBarAnchor = searchBarAnchor != null ? null : + new MBAnchorPoint(MBAnchorPoint.AnchorPoint.BOTMID, new Vector2f(0, -searchBarYOffset)); + quickCommandAnchor = quickCommandAnchor != null ? null : + new MBAnchorPoint(MBAnchorPoint.AnchorPoint.BOTMID, new Vector2f( + 0, + -searchBarYOffset - getSearchBarYSize() - getPaddingUnscaled() * 4 + )); + } else { + searchBarAnchor = searchBarAnchor != null ? searchBarAnchor : + new MBAnchorPoint(MBAnchorPoint.AnchorPoint.BOTMID, new Vector2f(0, -searchBarYOffset)); + quickCommandAnchor = quickCommandAnchor != null ? quickCommandAnchor : + new MBAnchorPoint(MBAnchorPoint.AnchorPoint.BOTMID, new Vector2f( + 0, + -searchBarYOffset - getSearchBarYSize() - getPaddingUnscaled() * 4 + )); + } + + int index = 0; + Set set = new LinkedHashSet<>(guiGroup.getChildrenMap().keySet()); + for (MBGuiElement element : set) { + switch (index) { + case 0: + if (searchBarAnchor == null) continue; + guiGroup.getChildrenMap().get(element).anchorPoint = searchBarAnchor.anchorPoint; + guiGroup.getChildrenMap().get(element).offset = searchBarAnchor.offset; + break; + case 1: + if (quickCommandAnchor == null) continue; + guiGroup.getChildrenMap().get(element).anchorPoint = quickCommandAnchor.anchorPoint; + guiGroup.getChildrenMap().get(element).offset = quickCommandAnchor.offset; + break; + } + index++; + } + } + + /** + * Disables searchBarFocus and resets the item pane position. Called whenever NEUOverlay is opened. + */ + public void reset() { + searchBarHasFocus = false; + if (!(searchMode || (NotEnoughUpdates.INSTANCE.config.itemlist.keepopen && itemPaneOpen))) { + itemPaneOpen = false; + displayInformationPane(null); + itemPaneOffsetFactor.setValue(1); + itemPaneTabOffset.setValue(20); + } + if (activeInfoPane != null) activeInfoPane.reset(); + guiGroup.recalculate(); + } + + /** + * Calls #displayInformationPane with a HTMLInfoPane created from item.info and item.infoType. + */ + public void showInfo(JsonObject item) { + if (item.has("info") && item.has("infoType")) { + JsonArray lore = item.get("info").getAsJsonArray(); + StringBuilder loreBuilder = new StringBuilder(); + for (int i = 0; i < lore.size(); i++) { + loreBuilder.append(lore.get(i).getAsString()); + if (i != lore.size() - 1) + loreBuilder.append("\n"); + } + String infoText = loreBuilder.toString(); + String internalname = item.get("internalname").getAsString(); + String name = item.get("displayname").getAsString(); + String infoType = item.get("infoType").getAsString(); + displayInformationPane(new TextInfoPane(this, manager, "Loading", "Loading your requested information about " + + name + + ".")); + infoPaneLoadingJob = InfoPane.create(this, manager, infoType, name, internalname, infoText) + .thenAccept(this::displayInformationPane); + } + } + + public void mouseInputInv() { + if (Minecraft.getMinecraft().currentScreen instanceof GuiContainer) { + if (Mouse.getEventButton() == manager.keybindItemSelect.getKeyCode() + 100 && + NotEnoughUpdates.INSTANCE.config.toolbar.searchBar) { + Slot slot = Utils.getSlotUnderMouse((GuiContainer) Minecraft.getMinecraft().currentScreen); + if (slot != null) { + ItemStack hover = slot.getStack(); + if (hover != null) { + textField.setText("id:" + manager.getInternalNameForItem(hover)); + itemPaneOpen = true; + updateSearch(); + } + } + } + } + } + + /** + * Handles the mouse input, cancelling the forge event if a NEU gui element is clicked. + */ + public boolean mouseInput() { + if (disabled) { + return false; + } + + Utils.pushGuiScale(NotEnoughUpdates.INSTANCE.config.itemlist.paneGuiScale); + + int width = Utils.peekGuiScale().getScaledWidth(); + int height = Utils.peekGuiScale().getScaledHeight(); + int mouseX = Mouse.getX() * width / Minecraft.getMinecraft().displayWidth; + int mouseY = height - Mouse.getY() * height / Minecraft.getMinecraft().displayHeight - 1; + + //if(lastMouseX != mouseX || lastMouseY != mouseY) { + // millisLastMouseMove = System.currentTimeMillis(); + //} + + lastMouseX = mouseX; + lastMouseY = mouseY; + + if (Mouse.getEventButtonState()) { + mouseDown = true; + } else if (Mouse.getEventButton() != -1) { + mouseDown = false; + } + + //Unfocuses the search bar by default. Search bar is focused if the click is on the bar itself. + if (Mouse.getEventButtonState()) setSearchBarFocus(false); + + guiGroup.mouseClick(0, 0, mouseX, mouseY); + + if (selectedItemGroup != null) { + int selectedX = Math.min(selectedItemGroupX, width - getBoxPadding() - 18 * selectedItemGroup.size()); + if (mouseY > selectedItemGroupY + 17 && mouseY < selectedItemGroupY + 35) { + for (int i = 0; i < selectedItemGroup.size(); i++) { + if (mouseX >= selectedX - 1 + 18 * i && mouseX <= selectedX + 17 + 18 * i) { + JsonObject item = selectedItemGroup.get(i); + if (item != null) { + if (Mouse.getEventButton() == 0) { + manager.showRecipe(item); + } else if (Mouse.getEventButton() == 1) { + showInfo(item); + } else if (Mouse.getEventButton() == manager.keybindItemSelect.getKeyCode() + 100 && + NotEnoughUpdates.INSTANCE.config.toolbar.searchBar) { + textField.setText("id:" + item.get("internalname").getAsString()); + updateSearch(); + searchMode = true; + } + } + Utils.pushGuiScale(-1); + return true; + } + } + } + } + + //Item selection (right) gui + if (mouseX > width * getItemPaneOffsetFactor()) { + if (!Mouse.getEventButtonState()) { + Utils.pushGuiScale(-1); + return true; //End early if the mouse isn't pressed, but still cancel event. + } + + AtomicBoolean clickedItem = new AtomicBoolean(false); + iterateItemSlots(new ItemSlotConsumer() { + public void consume(int x, int y, int id) { + if (mouseX >= x - 1 && mouseX <= x + ITEM_SIZE + 1) { + if (mouseY >= y - 1 && mouseY <= y + ITEM_SIZE + 1) { + clickedItem.set(true); + + JsonObject item = getSearchedItemPage(id); + if (item != null) { + if (Mouse.getEventButton() == 0) { + manager.showRecipe(item); + } else if (Mouse.getEventButton() == 1) { + showInfo(item); + } else if (Mouse.getEventButton() == manager.keybindItemSelect.getKeyCode() + 100 && + NotEnoughUpdates.INSTANCE.config.toolbar.searchBar) { + textField.setText("id:" + item.get("internalname").getAsString()); + updateSearch(); + searchMode = true; + } + } + } + } + } + }); + if (!clickedItem.get()) { + int paneWidth = (int) (width / 3 * getWidthMult()); + int leftSide = (int) (width * getItemPaneOffsetFactor()); + int rightSide = leftSide + paneWidth - getBoxPadding() - getItemBoxXPadding(); + leftSide = leftSide + getBoxPadding() + getItemBoxXPadding(); + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + int maxPages = getMaxPages(); + String name = Utils.peekGuiScale().getScaleFactor() < 4 ? "Page: " : ""; + float maxStrLen = fr.getStringWidth(EnumChatFormatting.BOLD + name + maxPages + "/" + maxPages); + float maxButtonXSize = (rightSide - leftSide + 2 - maxStrLen * 0.5f - 10) / 2f; + int buttonXSize = (int) Math.min(maxButtonXSize, getSearchBarYSize() * 480 / 160f); + int ySize = (int) (buttonXSize / 480f * 160); + int yOffset = (int) ((getSearchBarYSize() - ySize) / 2f); + int top = getBoxPadding() + yOffset; + + if (mouseY >= top && mouseY <= top + ySize) { + int leftPrev = leftSide - 1; + if (mouseX > leftPrev && mouseX < leftPrev + buttonXSize) { //"Previous" button + setPage(page - 1); + Utils.playPressSound(); + } + int leftNext = rightSide + 1 - buttonXSize; + if (mouseX > leftNext && mouseX < leftNext + buttonXSize) { //"Next" button + setPage(page + 1); + Utils.playPressSound(); + } + } + + float sortIconsMinX = (sortIcons.length + orderIcons.length) * (ITEM_SIZE + ITEM_PADDING) + ITEM_SIZE; + float availableX = rightSide - leftSide; + float sortOrderScaleFactor = Math.min(1, availableX / sortIconsMinX); + + int scaledITEM_SIZE = (int) (ITEM_SIZE * sortOrderScaleFactor); + int scaledItemPaddedSize = (int) ((ITEM_SIZE + ITEM_PADDING) * sortOrderScaleFactor); + int iconTop = height - getBoxPadding() - (ITEM_SIZE + scaledITEM_SIZE) / 2 - 1; + + if (mouseY >= iconTop && mouseY <= iconTop + scaledITEM_SIZE) { + for (int i = 0; i < orderIcons.length; i++) { + int orderIconX = leftSide + i * scaledItemPaddedSize; + if (mouseX >= orderIconX && mouseX <= orderIconX + scaledITEM_SIZE) { + if (Mouse.getEventButton() == 0) { + NotEnoughUpdates.INSTANCE.config.hidden.compareMode = i; + updateSearch(); + Utils.playPressSound(); + } else if (Mouse.getEventButton() == 1) { + NotEnoughUpdates.INSTANCE.config.hidden.compareAscending.set( + i, + !NotEnoughUpdates.INSTANCE.config.hidden.compareAscending.get(i) + ); + updateSearch(); + Utils.playPressSound(); + } + } + } + + for (int i = 0; i < sortIcons.length; i++) { + int sortIconX = rightSide - scaledITEM_SIZE - i * scaledItemPaddedSize; + if (mouseX >= sortIconX && mouseX <= sortIconX + scaledITEM_SIZE) { + NotEnoughUpdates.INSTANCE.config.hidden.sortMode = i; + updateSearch(); + Utils.playPressSound(); + } + } + } + } + Utils.pushGuiScale(-1); + return true; + } + + //Clicking on "close info pane" button + if (mouseX > width * getInfoPaneOffsetFactor() - getBoxPadding() - 8 && + mouseX < width * getInfoPaneOffsetFactor() - getBoxPadding() + 8) { + if (mouseY > getBoxPadding() - 8 && mouseY < getBoxPadding() + 8) { + if (Mouse.getEventButtonState() && Mouse.getEventButton() < 2) { //Left or right click up + displayInformationPane(null); + Utils.pushGuiScale(-1); + return true; + } + } + } + + if (activeInfoPane != null) { + if (mouseX < width * getInfoPaneOffsetFactor()) { + activeInfoPane.mouseInput(width, height, mouseX, mouseY, mouseDown); + Utils.pushGuiScale(-1); + return true; + } else if (Mouse.getEventButton() <= 1 && Mouse.getEventButtonState()) { //Left or right click + activeInfoPane.mouseInputOutside(); + } + } + + Utils.pushGuiScale(-1); + return false; + } + + public int getPaddingUnscaled() { + int paddingUnscaled = searchBarPadding / Utils.peekGuiScale().getScaleFactor(); + if (paddingUnscaled < 1) paddingUnscaled = 1; + + return paddingUnscaled; + } + + public GuiTextField getTextField() { + return textField; + } + + /** + * Returns searchBarXSize, scaled by 0.8 if gui scale == AUTO. + */ + public int getSearchBarXSize() { + int searchBarXSize = NotEnoughUpdates.INSTANCE.config.toolbar.searchBarWidth; + if (Utils.peekGuiScale().getScaleFactor() == 4) return (int) (searchBarXSize * 0.8); + return searchBarXSize; + } + + /** + * Sets the activeInfoPane and sets the target of the infoPaneOffsetFactor to make the infoPane "slide" out. + */ + public void displayInformationPane(InfoPane pane) { + infoPaneLoadingJob.cancel(false); + if (pane == null) { + infoPaneOffsetFactor.setTarget(0); + } else { + infoPaneOffsetFactor.setTarget(1 / 3f); + } + infoPaneOffsetFactor.resetTimer(); + this.activeInfoPane = pane; + } + + public InfoPane getActiveInfoPane() { + return activeInfoPane; + } + + /** + * Finds the index of the character inside the search bar that was clicked, used to set the caret. + */ + public int getClickedIndex(int mouseX, int mouseY) { + int width = Utils.peekGuiScale().getScaledWidth(); + int height = Utils.peekGuiScale().getScaledHeight(); + + int xComp = mouseX - (width / 2 - getSearchBarXSize() / 2 + 5); + + String trimmed = Minecraft.getMinecraft().fontRendererObj.trimStringToWidth(textField.getText(), xComp); + int linePos = trimmed.length(); + if (linePos != textField.getText().length()) { + char after = textField.getText().charAt(linePos); + int trimmedWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth(trimmed); + int charWidth = Minecraft.getMinecraft().fontRendererObj.getCharWidth(after); + if (trimmedWidth + charWidth / 2 < xComp - 5) { + linePos++; + } + } + return linePos; + } + + public void setSearchBarFocus(boolean focus) { + if (focus) { + itemPaneOpen = true; + } + searchBarHasFocus = focus; + } + + /** + * Handles the keyboard input, cancelling the forge event if the search bar has focus. + */ + public boolean keyboardInput(boolean hoverInv) { + if (Minecraft.getMinecraft().currentScreen == null) return false; + Keyboard.enableRepeatEvents(true); + + int keyPressed = Keyboard.getEventKey() == 0 ? Keyboard.getEventCharacter() + 256 : Keyboard.getEventKey(); + + if (disabled) { + if (Keyboard.getEventKeyState() && keyPressed == manager.keybindToggleDisplay.getKeyCode()) { + disabled = !disabled; + } + return false; + } + + if (Keyboard.isKeyDown(Keyboard.KEY_Y) && NotEnoughUpdates.INSTANCE.config.hidden.dev) { + displayInformationPane(new DevInfoPane(this, manager)); + } + + if (Keyboard.getEventKeyState()) { + if (!NotEnoughUpdates.INSTANCE.config.toolbar.searchBar) { + searchBarHasFocus = false; + } + if (searchBarHasFocus) { + if (keyPressed == 1) { + searchBarHasFocus = false; + } else { + if (textField.textboxKeyTyped(Keyboard.getEventCharacter(), keyPressed)) { + updateSearch(); + } + } + } else { + if (activeInfoPane != null) { + if (activeInfoPane.keyboardInput()) { + return true; + } + } + + if (keyPressed == manager.keybindClosePanes.getKeyCode()) { + itemPaneOffsetFactor.setValue(1); + itemPaneTabOffset.setValue(20); + itemPaneOpen = false; + displayInformationPane(null); + } + + if (keyPressed == manager.keybindToggleDisplay.getKeyCode()) { + disabled = !disabled; + return true; + } + + AtomicReference internalname = new AtomicReference<>(null); + AtomicReference itemstack = new AtomicReference<>(null); + if (Minecraft.getMinecraft().currentScreen instanceof GuiContainer && + Utils.getSlotUnderMouse((GuiContainer) Minecraft.getMinecraft().currentScreen) != null) { + Slot slot = Utils.getSlotUnderMouse((GuiContainer) Minecraft.getMinecraft().currentScreen); + ItemStack hover = slot.getStack(); + if (hover != null) { + internalname.set(manager.getInternalNameForItem(hover)); + itemstack.set(hover); + } + } else if (!hoverInv) { + Utils.pushGuiScale(NotEnoughUpdates.INSTANCE.config.itemlist.paneGuiScale); + + int width = Utils.peekGuiScale().getScaledWidth(); + int height = Utils.peekGuiScale().getScaledHeight(); + int mouseX = Mouse.getX() * width / Minecraft.getMinecraft().displayWidth; + int mouseY = height - Mouse.getY() * height / Minecraft.getMinecraft().displayHeight - 1; + + if (selectedItemGroup != null) { + int selectedX = Math.min(selectedItemGroupX, width - getBoxPadding() - 18 * selectedItemGroup.size()); + + if (mouseY > selectedItemGroupY + 17 && mouseY < selectedItemGroupY + 35) { + for (int i = 0; i < selectedItemGroup.size(); i++) { + if (mouseX >= selectedX - 1 + 18 * i && mouseX <= selectedX + 17 + 18 * i) { + internalname.set(selectedItemGroup.get(i).get("internalname").getAsString()); + } + } + } + } else { + iterateItemSlots(new ItemSlotConsumer() { + public void consume(int x, int y, int id) { + if (mouseX >= x - 1 && mouseX <= x + ITEM_SIZE + 1) { + if (mouseY >= y - 1 && mouseY <= y + ITEM_SIZE + 1) { + JsonObject json = getSearchedItemPage(id); + if (json != null) internalname.set(json.get("internalname").getAsString()); + } + } + } + }); + } + + Utils.pushGuiScale(-1); + } + if (internalname.get() != null) { + if (itemstack.get() != null) { + if (NotEnoughUpdates.INSTANCE.config.hidden.enableItemEditing && Keyboard.getEventCharacter() == 'k') { + Minecraft.getMinecraft().displayGuiScreen(new NEUItemEditor(manager, + internalname.get(), manager.getJsonForItem(itemstack.get()) + )); + return true; + } + } + JsonObject item = manager.getItemInformation().get(internalname.get()); + if (item != null) { + if (keyPressed == manager.keybindViewUsages.getKeyCode()) { + manager.displayGuiItemUsages(internalname.get()); + return true; + } else if (keyPressed == manager.keybindFavourite.getKeyCode()) { + toggleFavourite(item.get("internalname").getAsString()); + return true; + } else if (keyPressed == manager.keybindViewRecipe.getKeyCode()) { + manager.showRecipe(item); + return true; + } else if (keyPressed == manager.keybindGive.getKeyCode()) { + if (Minecraft.getMinecraft().thePlayer.capabilities.isCreativeMode) { + Minecraft.getMinecraft().thePlayer.inventory.addItemStackToInventory( + manager.jsonToStack(item)); + } + } else if (NotEnoughUpdates.INSTANCE.config.hidden.enableItemEditing && + Keyboard.getEventCharacter() == 'k') { + Minecraft.getMinecraft().displayGuiScreen(new NEUItemEditor(manager, + internalname.get(), item + )); + return true; + } else if (keyPressed == manager.keybindItemSelect.getKeyCode() && + NotEnoughUpdates.INSTANCE.config.toolbar.searchBar) { + textField.setText("id:" + internalname.get()); + itemPaneOpen = true; + updateSearch(); + } else if (keyPressed == NotEnoughUpdates.INSTANCE.config.ahGraph.graphKey && + NotEnoughUpdates.INSTANCE.config.ahGraph.graphEnabled) { + NotEnoughUpdates.INSTANCE.openGui = new GuiPriceGraph(internalname.get()); + return true; + } + } + } + } + } + + return searchBarHasFocus; //Cancels keyboard events if the search bar has focus + } + + public void toggleFavourite(String internalname) { + if (getFavourites().contains(internalname)) { + getFavourites().remove(internalname); + } else { + getFavourites().add(internalname); + } + updateSearch(); + } + + String[] rarityArr = new String[]{ + EnumChatFormatting.WHITE + EnumChatFormatting.BOLD.toString() + "COMMON", + EnumChatFormatting.GREEN + EnumChatFormatting.BOLD.toString() + "UNCOMMON", + EnumChatFormatting.BLUE + EnumChatFormatting.BOLD.toString() + "RARE", + EnumChatFormatting.DARK_PURPLE + EnumChatFormatting.BOLD.toString() + "EPIC", + EnumChatFormatting.GOLD + EnumChatFormatting.BOLD.toString() + "LEGENDARY", + EnumChatFormatting.LIGHT_PURPLE + EnumChatFormatting.BOLD.toString() + "MYTHIC", + EnumChatFormatting.RED + EnumChatFormatting.BOLD.toString() + "SPECIAL", + }; + + /** + * Finds the rarity from the lore of an item. + * -1 = UNKNOWN + * 0 = COMMON + * 1 = UNCOMMON + * 2 = RARE + * 3 = EPIC + * 4 = LEGENDARY + * 5 = MYTHIC + * 6 = SPECIAL + */ + public int getRarity(JsonArray lore) { + for (int i = lore.size() - 1; i >= 0; i--) { + String line = lore.get(i).getAsString(); + + for (int j = 0; j < rarityArr.length; j++) { + if (line.startsWith(rarityArr[j])) { + return j; + } + } + } + return -1; + } + + /** + * Convenience functions that get various compare/sort modes from the config. + */ + private int getCompareMode() { + return NotEnoughUpdates.INSTANCE.config.hidden.compareMode; + } + + private int getSortMode() { + return NotEnoughUpdates.INSTANCE.config.hidden.sortMode; + } + + private List getCompareAscending() { + return NotEnoughUpdates.INSTANCE.config.hidden.compareAscending; + } + + private List getFavourites() { + return NotEnoughUpdates.INSTANCE.config.hidden.favourites; + } + + /** + * Creates an item comparator used to sort the list of items according to the favourite set then compare mode. + * Defaults to alphabetical sorting if the above factors cannot distinguish between two items. + */ + private Comparator getItemComparator() { + return (o1, o2) -> { + //1 (mult) if o1 should appear after o2 + //-1 (-mult) if o2 should appear after o1 + if (getFavourites().contains(o1.get("internalname").getAsString()) && + !getFavourites().contains(o2.get("internalname").getAsString())) { + return -1; + } + if (!getFavourites().contains(o1.get("internalname").getAsString()) && + getFavourites().contains(o2.get("internalname").getAsString())) { + return 1; + } + + int mult = getCompareAscending().get(getCompareMode()) ? 1 : -1; + if (getCompareMode() == COMPARE_MODE_RARITY) { + int rarity1 = getRarity(o1.get("lore").getAsJsonArray()); + int rarity2 = getRarity(o2.get("lore").getAsJsonArray()); + + if (rarity1 < rarity2) return mult; + if (rarity1 > rarity2) return -mult; + } else if (getCompareMode() == COMPARE_MODE_VALUE) { + String internal1 = o1.get("internalname").getAsString(); + String internal2 = o2.get("internalname").getAsString(); + + float cost1 = manager.auctionManager.getLowestBin(internal1); + float cost2 = manager.auctionManager.getLowestBin(internal2); + + if (cost1 < cost2) return mult; + if (cost1 > cost2) return -mult; + } + + String i1 = o1.get("internalname").getAsString(); + String[] split1 = i1.split("_"); + String last1 = split1[split1.length - 1]; + String start1 = i1.substring(0, i1.length() - last1.length()); + + String i2 = o2.get("internalname").getAsString(); + String[] split2 = i2.split("_"); + String last2 = split2[split2.length - 1]; + String start2 = i2.substring(0, i2.length() - last2.length()); + + mult = getCompareAscending().get(COMPARE_MODE_ALPHABETICAL) ? 1 : -1; + if (start1.equals(start2)) { + String[] order = new String[]{"HELMET", "CHESTPLATE", "LEGGINGS", "BOOTS"}; + int type1 = checkItemType(o1.get("lore").getAsJsonArray(), order); + int type2 = checkItemType(o2.get("lore").getAsJsonArray(), order); + + if (type1 < type2) return -mult; + if (type1 > type2) return mult; + } + + int nameComp = mult * o1.get("displayname").getAsString().replaceAll("(?i)\\u00A7.", "") + .compareTo(o2.get("displayname").getAsString().replaceAll("(?i)\\u00A7.", "")); + if (nameComp != 0) { + return nameComp; + } + return mult * o1.get("internalname").getAsString().compareTo(o2.get("internalname").getAsString()); + }; + } + + /** + * Checks whether an item matches a certain type, i.e. whether the item lore ends in "{rarity} {item type}" + * eg. "SHOVEL" will return >0 for "COMMON SHOVEL", "EPIC SHOVEL", etc. + * + * @return the index of the type that matched, or -1 otherwise. + */ + public int checkItemType(JsonArray lore, String... typeMatches) { + for (int i = lore.size() - 1; i >= 0; i--) { + String line = lore.get(i).getAsString(); + + for (String rarity : rarityArr) { + for (int j = 0; j < typeMatches.length; j++) { + if (line.trim().equals(rarity + " " + typeMatches[j])) { + return j; + } + } + } + } + return -1; + } + + /** + * Checks whether an item matches the current sort mode. + */ + public boolean checkMatchesSort(String internalname, JsonObject item) { + if (!NotEnoughUpdates.INSTANCE.config.itemlist.showVanillaItems && + item.has("vanilla") && + item.get("vanilla").getAsBoolean()) { + return false; + } + + if (getSortMode() == SORT_MODE_ALL) { + return !internalname.matches(mobRegex); + } else if (getSortMode() == SORT_MODE_MOB) { + return internalname.matches(mobRegex); + } else if (getSortMode() == SORT_MODE_PET) { + return internalname.matches(petRegex) && item.get("displayname").getAsString().contains("["); + } else if (getSortMode() == SORT_MODE_TOOL) { + return checkItemType( + item.get("lore").getAsJsonArray(), + "SWORD", + "BOW", + "AXE", + "PICKAXE", + "FISHING ROD", + "WAND", + "SHOVEL", + "HOE", + "DUNGEON SWORD", + "DUNGEON BOW", + "DRILL", + "GAUNTLET" + ) >= 0; + } else if (getSortMode() == SORT_MODE_ARMOR) { + return checkItemType( + item + .get("lore") + .getAsJsonArray(), + "HELMET", + "CHESTPLATE", + "LEGGINGS", + "BOOTS", + "DUNGEON HELMET", + "DUNGEON CHESTPLATE", + "DUNGEON LEGGINGS", + "DUNGEON BOOTS" + ) >= + 0; + } else if (getSortMode() == SORT_MODE_ACCESSORY) { + return checkItemType(item.get("lore").getAsJsonArray(), "ACCESSORY", "HATCCESSORY", "DUNGEON ACCESSORY") >= 0; + } + return true; + } + + private final HashMap parentMap = new HashMap<>(); + + private final ExecutorService searchES = Executors.newSingleThreadExecutor(); + + /** + * Clears the current item list, creating a new TreeSet if necessary. + * Adds all items that match the search AND match the sort mode to the current item list. + * Also adds some easter egg items. (Also I'm very upset if you came here to find them :'( ) + */ + public void updateSearch() { + SunTzu.randomizeQuote(); + + if (searchedItems == null) searchedItems = new TreeSet<>(getItemComparator()); + + searchES.submit(() -> { + TreeSet searchedItems = new TreeSet<>(getItemComparator()); + HashMap> searchedItemsSubgroup = new HashMap<>(); + + Set removeChildItems = new HashSet<>(); + Set itemsMatch = manager.search(textField.getText(), true); + for (String itemname : itemsMatch) { + JsonObject item = manager.getItemInformation().get(itemname); + if (checkMatchesSort(itemname, item)) { + if (Constants.PARENTS != null) { + if (Constants.PARENTS.has(itemname) && Constants.PARENTS.get(itemname).isJsonArray()) { + List children = new ArrayList<>(); + for (JsonElement e : Constants.PARENTS.get(itemname).getAsJsonArray()) { + if (e.isJsonPrimitive()) { + children.add(e.getAsString()); + } + } + children.retainAll(itemsMatch); + for (String child : children) { + removeChildItems.add(manager.getItemInformation().get(child)); + } + searchedItemsSubgroup.put(itemname, children); + } + } + searchedItems.add(item); + } + } + searchedItems.removeAll(removeChildItems); + out: + for (Map.Entry> entry : searchedItemsSubgroup.entrySet()) { + if (searchedItems.contains(manager.getItemInformation().get(entry.getKey()))) { + continue; + } + for (String itemname : entry.getValue()) { + JsonObject item = manager.getItemInformation().get(itemname); + if (item != null) searchedItems.add(item); + } + } + switch (textField.getText().toLowerCase().trim()) { + case "nullzee": + searchedItems.add(CustomItems.NULLZEE); + break; + case "rune": + searchedItems.add(CustomItems.RUNE); + break; + case "2b2t": + searchedItems.add(CustomItems.TWOBEETWOTEE); + break; + case "ducttape": + case "ducttapedigger": + searchedItems.add(CustomItems.DUCTTAPE); + break; + case "thirtyvirus": + searchedItems.add(manager.getItemInformation().get("SPIKED_BAIT")); + break; + case "leocthl": + searchedItems.add(CustomItems.LEOCTHL); + break; + case "spinaxx": + searchedItems.add(CustomItems.SPINAXX); + break; + case "credits": + case "credit": + case "who made this mod": + searchedItems.add(CustomItems.CREDITS); + break; + case "ironmoon": + case "ironm00n": + searchedItems.add(CustomItems.IRONM00N); + break; + case "nopo": + case "nopothegamer": + searchedItems.add(CustomItems.NOPO); + break; + } + + this.searchedItems = searchedItems; + this.searchedItemsSubgroup = searchedItemsSubgroup; + + synchronized (this.searchedItemsArr) { + this.searchedItemsArr.clear(); + } + + redrawItems = true; + }); + } + + /** + * Returns an index-able array containing the elements in searchedItems. + * Whenever searchedItems is updated in updateSearch(), the array is recreated here. + */ + public List getSearchedItems() { + if (searchedItems == null) { + updateSearch(); + return new ArrayList<>(); + } + + if (searchedItems.size() > 0 && searchedItemsArr.size() == 0) { + synchronized (searchedItemsArr) { + searchedItemsArr.addAll(searchedItems); + } + } + return searchedItemsArr; + } + + /** + * Gets the item in searchedItemArr corresponding to the certain index on the current page. + * + * @return item, if the item exists. null, otherwise. + */ + public JsonObject getSearchedItemPage(int index) { + if (index < getSlotsXSize() * getSlotsYSize()) { + int actualIndex = index + getSlotsXSize() * getSlotsYSize() * page; + List searchedItems = getSearchedItems(); + if (actualIndex < searchedItems.size()) { + return searchedItems.get(actualIndex); + } else { + return null; + } + } else { + return null; + } + } + + public int getItemBoxXPadding() { + int width = Utils.peekGuiScale().getScaledWidth(); + return (((int) (width / 3 * getWidthMult()) - 2 * getBoxPadding()) % (ITEM_SIZE + ITEM_PADDING) + ITEM_PADDING) / 2; + } + + public int getBoxPadding() { + double panePadding = Math.max(0, Math.min(20, NotEnoughUpdates.INSTANCE.config.itemlist.panePadding)); + return (int) (panePadding * 2 / Utils.peekGuiScale().getScaleFactor() + 5); + } + + private abstract static class ItemSlotConsumer { + public abstract void consume(int x, int y, int id); + } + + public void iterateItemSlots(ItemSlotConsumer itemSlotConsumer) { + int width = Utils.peekGuiScale().getScaledWidth(); + int itemBoxXPadding = getItemBoxXPadding(); + iterateItemSlots(itemSlotConsumer, (int) (width * getItemPaneOffsetFactor()) + getBoxPadding() + itemBoxXPadding); + } + + /** + * Iterates through all the item slots in the right panel and calls a ItemSlotConsumer for each slot with + * arguments equal to the slot's x and y position respectively. This is used in order to prevent + * code duplication issues. + */ + public void iterateItemSlots(ItemSlotConsumer itemSlotConsumer, int xStart) { + int width = Utils.peekGuiScale().getScaledWidth(); + int height = Utils.peekGuiScale().getScaledHeight(); + + int paneWidth = (int) (width / 3 * getWidthMult()); + int itemBoxYPadding = + ((height - getSearchBarYSize() - 2 * getBoxPadding() - ITEM_SIZE - 2) % (ITEM_SIZE + ITEM_PADDING) + + ITEM_PADDING) / 2; + + int yStart = getBoxPadding() + getSearchBarYSize() + itemBoxYPadding; + int itemBoxXPadding = getItemBoxXPadding(); + int xEnd = xStart + paneWidth - getBoxPadding() * 2 - ITEM_SIZE - itemBoxXPadding; + int yEnd = height - getBoxPadding() - ITEM_SIZE - 2 - itemBoxYPadding; + + //Render the items, displaying the tooltip if the cursor is over the item + int id = 0; + for (int y = yStart; y < yEnd; y += ITEM_SIZE + ITEM_PADDING) { + for (int x = xStart; x < xEnd; x += ITEM_SIZE + ITEM_PADDING) { + itemSlotConsumer.consume(x, y, id++); + } + } + } + + public float getWidthMult() { + float scaleFMult = 1; + if (Utils.peekGuiScale().getScaleFactor() == 4) scaleFMult *= 0.9f; + if (manager.auctionManager.customAH.isRenderOverAuctionView() || + Minecraft.getMinecraft().currentScreen instanceof CustomAHGui) + scaleFMult *= 0.8f; + return (float) Math.max(0.5, Math.min(1.5, NotEnoughUpdates.INSTANCE.config.itemlist.paneWidthMult)) * scaleFMult; + } + + /** + * Calculates the number of horizontal item slots. + */ + public int getSlotsXSize() { + int width = Utils.peekGuiScale().getScaledWidth(); + + int paneWidth = (int) (width / 3 * getWidthMult()); + int itemBoxXPadding = + (((int) (width - width * getItemPaneOffsetFactor()) - 2 * getBoxPadding()) % (ITEM_SIZE + ITEM_PADDING) + + ITEM_PADDING) / 2; + int xStart = (int) (width * getItemPaneOffsetFactor()) + getBoxPadding() + itemBoxXPadding; + int xEnd = (int) (width * getItemPaneOffsetFactor()) + paneWidth - getBoxPadding() - ITEM_SIZE; + + return (int) Math.ceil((xEnd - xStart) / ((float) (ITEM_SIZE + ITEM_PADDING))); + } + + /** + * Calculates the number of vertical item slots. + */ + public int getSlotsYSize() { + int height = Utils.peekGuiScale().getScaledHeight(); + + int itemBoxYPadding = + ((height - getSearchBarYSize() - 2 * getBoxPadding() - ITEM_SIZE - 2) % (ITEM_SIZE + ITEM_PADDING) + + ITEM_PADDING) / 2; + int yStart = getBoxPadding() + getSearchBarYSize() + itemBoxYPadding; + int yEnd = height - getBoxPadding() - ITEM_SIZE - 2 - itemBoxYPadding; + + return (int) Math.ceil((yEnd - yStart) / ((float) (ITEM_SIZE + ITEM_PADDING))); + } + + public int getMaxPages() { + if (getSearchedItems().size() == 0) return 1; + return (int) Math.ceil(getSearchedItems().size() / (float) getSlotsYSize() / getSlotsXSize()); + } + + public int getSearchBarYSize() { + int searchBarYSize = NotEnoughUpdates.INSTANCE.config.toolbar.searchBarHeight; + return Math.max(searchBarYSize / Utils.peekGuiScale().getScaleFactor(), ITEM_SIZE); + } + + /** + * Renders the top navigation bar, can be used by InfoPane implementations (such as SettingsInfoPane). + * Renders "prev" button, index/maxIndex string, "next" button. + */ + public void renderNavElement(int leftSide, int rightSide, int maxPages, int page, String name) { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + + String pageText = EnumChatFormatting.BOLD + name + page + "/" + maxPages; + + float maxStrLen = fr.getStringWidth(EnumChatFormatting.BOLD + name + maxPages + "/" + maxPages); + float maxButtonXSize = (rightSide - leftSide + 2 - maxStrLen * 0.5f - 10) / 2f; + int buttonXSize = (int) Math.min(maxButtonXSize, getSearchBarYSize() * 480 / 160f); + int ySize = (int) (buttonXSize / 480f * 160); + int yOffset = (int) ((getSearchBarYSize() - ySize) / 2f); + int top = getBoxPadding() + yOffset; + + int leftPressed = 0; + int rightPressed = 0; + + if (Mouse.isButtonDown(0) || Mouse.isButtonDown(1)) { + int width = Utils.peekGuiScale().getScaledWidth(); + int height = Utils.peekGuiScale().getScaledHeight(); + + int mouseX = Mouse.getX() * width / Minecraft.getMinecraft().displayWidth; + int mouseY = height - Mouse.getY() * height / Minecraft.getMinecraft().displayHeight - 1; + + if (mouseY >= top && mouseY <= top + ySize) { + int leftPrev = leftSide - 1; + if (mouseX > leftPrev && mouseX < leftPrev + buttonXSize) { //"Previous" button + leftPressed = 1; + } + int leftNext = rightSide + 1 - buttonXSize; + if (mouseX > leftNext && mouseX < leftNext + buttonXSize) { //"Next" button + rightPressed = 1; + } + } + } + + drawRect(leftSide - 1, top, leftSide - 1 + buttonXSize, top + ySize, fg.getRGB()); + GlStateManager.color(1f, 1f, 1f, 1f); + Minecraft.getMinecraft().getTextureManager().bindTexture(rightarrow); + Utils.drawTexturedRect(leftSide - 1 + leftPressed, + top + leftPressed, + buttonXSize, ySize, 1, 0, 0, 1 + ); + Minecraft.getMinecraft().getTextureManager().bindTexture(rightarrow_overlay); + Utils.drawTexturedRect(leftSide - 1, + top, + buttonXSize, ySize, 1 - leftPressed, leftPressed, 1 - leftPressed, leftPressed + ); + GlStateManager.bindTexture(0); + Utils.drawStringCenteredScaled(EnumChatFormatting.BOLD + "Prev", fr, + leftSide - 1 + buttonXSize * 300 / 480f + leftPressed, + top + ySize / 2f + leftPressed, false, + (int) (buttonXSize * 240 / 480f), Color.BLACK.getRGB() + ); + + drawRect(rightSide + 1 - buttonXSize, top, rightSide + 1, top + ySize, fg.getRGB()); + GlStateManager.color(1f, 1f, 1f, 1f); + Minecraft.getMinecraft().getTextureManager().bindTexture(rightarrow); + Utils.drawTexturedRect(rightSide + 1 - buttonXSize + rightPressed, + top + rightPressed, + buttonXSize, ySize + ); + Minecraft.getMinecraft().getTextureManager().bindTexture(rightarrow_overlay); + Utils.drawTexturedRect(rightSide + 1 - buttonXSize, + top, + buttonXSize, ySize, 1 - rightPressed, rightPressed, 1 - rightPressed, rightPressed + ); + GlStateManager.bindTexture(0); + Utils.drawStringCenteredScaled(EnumChatFormatting.BOLD + "Next", fr, + rightSide + 1 - buttonXSize * 300 / 480f + rightPressed, + top + ySize / 2f + rightPressed, false, + (int) (buttonXSize * 240 / 480f), Color.BLACK.getRGB() + ); + + int strMaxLen = rightSide - leftSide - 2 * buttonXSize - 10; + + drawRect(leftSide - 1 + buttonXSize + 3, top, rightSide + 1 - buttonXSize - 3, top + ySize, + new Color(177, 177, 177).getRGB() + ); + drawRect(leftSide + buttonXSize + 3, top + 1, rightSide + 1 - buttonXSize - 3, top + ySize, + new Color(50, 50, 50).getRGB() + ); + drawRect(leftSide + buttonXSize + 3, top + 1, rightSide - buttonXSize - 3, top + ySize - 1, fg.getRGB()); + Utils.drawStringCenteredScaledMaxWidth(pageText, fr, (leftSide + rightSide) / 2, + top + ySize / 2f, false, strMaxLen, Color.BLACK.getRGB() + ); + } + + private int limCol(int col) { + return Math.min(255, Math.max(0, col)); + } + + public boolean isUsingMobsFilter() { + return getSortMode() == SORT_MODE_MOB; + } + + public float yaw = 0; + public float pitch = 20; + + /** + * Renders an entity onto the GUI at a certain x and y position. + */ + private void renderEntity( + float posX, + float posY, + float scale, + String name, + Class... classes + ) { + EntityLivingBase[] entities = new EntityLivingBase[classes.length]; + try { + EntityLivingBase last = null; + for (int i = 0; i < classes.length; i++) { + Class clazz = classes[i]; + if (clazz == null) continue; + + EntityLivingBase newEnt = + clazz.getConstructor(new Class[]{World.class}).newInstance(Minecraft.getMinecraft().theWorld); + + //newEnt.renderYawOffset = yaw; + //newEnt.rotationYaw = yaw; + newEnt.rotationPitch = pitch; + //newEnt.rotationYawHead = yaw; + //newEnt.prevRotationYawHead = yaw-1; + + newEnt.setCustomNameTag(name); + + if (last != null) { + last.riddenByEntity = newEnt; + newEnt.ridingEntity = last; + last.updateRiderPosition(); + } + last = newEnt; + + entities[i] = newEnt; + } + } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { + e.printStackTrace(); + return; + } + + GlStateManager.enableColorMaterial(); + GlStateManager.pushMatrix(); + GlStateManager.translate(posX, posY, 50.0F); + GlStateManager.scale(-scale, scale, scale); + GlStateManager.rotate(180.0F, 0.0F, 0.0F, 1.0F); + + GlStateManager.rotate(135.0F, 0.0F, 1.0F, 0.0F); + RenderHelper.enableStandardItemLighting(); + GlStateManager.rotate(-135.0F, 0.0F, 1.0F, 0.0F); + + GlStateManager.rotate(pitch, 1.0F, 0.0F, 0.0F); + GlStateManager.rotate(yaw, 0.0F, 1.0F, 0.0F); + + RenderManager rendermanager = Minecraft.getMinecraft().getRenderManager(); + rendermanager.setPlayerViewY(180.0F); + rendermanager.setRenderShadow(false); + for (EntityLivingBase ent : entities) { + GL11.glColor4f(1, 1, 1, 1); + if (ent != null) rendermanager.renderEntityWithPosYaw(ent, ent.posX, ent.posY, ent.posZ, 0.0F, 1.0F); + } + rendermanager.setRenderShadow(true); + + GlStateManager.popMatrix(); + RenderHelper.disableStandardItemLighting(); + GlStateManager.disableRescaleNormal(); + GlStateManager.setActiveTexture(OpenGlHelper.lightmapTexUnit); + GlStateManager.disableTexture2D(); + GlStateManager.setActiveTexture(OpenGlHelper.defaultTexUnit); + + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + } + + Shader blurShaderHorz = null; + Framebuffer blurOutputHorz = null; + Shader blurShaderVert = null; + Framebuffer blurOutputVert = null; + + /** + * Creates a projection matrix that projects from our coordinate space [0->width; 0->height] to OpenGL coordinate + * space [-1 -> 1; 1 -> -1] (Note: flipped y-axis). + *

+ * This is so that we can render to and from the framebuffer in a way that is familiar to us, instead of needing to + * apply scales and translations manually. + */ + private Matrix4f createProjectionMatrix(int width, int height) { + Matrix4f projMatrix = new Matrix4f(); + projMatrix.setIdentity(); + projMatrix.m00 = 2.0F / (float) width; + projMatrix.m11 = 2.0F / (float) (-height); + projMatrix.m22 = -0.0020001999F; + projMatrix.m33 = 1.0F; + projMatrix.m03 = -1.0F; + projMatrix.m13 = 1.0F; + projMatrix.m23 = -1.0001999F; + return projMatrix; + } + + public void updateGuiGroupSize() { + Utils.pushGuiScale(NotEnoughUpdates.INSTANCE.config.itemlist.paneGuiScale); + int width = Utils.peekGuiScale().getScaledWidth(); + int height = Utils.peekGuiScale().getScaledHeight(); + + if (lastScreenWidth != width || lastScreenHeight != height || Utils.peekGuiScale().getScaleFactor() != lastScale) { + guiGroup.width = width; + guiGroup.height = height; + + resetAnchors(true); + guiGroup.recalculate(); + + lastScreenWidth = width; + lastScreenHeight = height; + lastScale = Utils.peekGuiScale().getScaleFactor(); + } + + Utils.pushGuiScale(-1); + } + + int guiScaleLast = 0; + private boolean showVanillaLast = false; + + private boolean wardrobeOpen = false; + + private boolean isInNamedGui(String guiName) { + GuiScreen guiScreen = Minecraft.getMinecraft().currentScreen; + if (guiScreen instanceof GuiChest) { + GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen; + ContainerChest container = (ContainerChest) chest.inventorySlots; + IInventory lower = container.getLowerChestInventory(); + String containerName = lower.getDisplayName().getUnformattedText(); + wardrobeOpen = containerName.contains(guiName); + } + if (guiScreen instanceof GuiInventory) { + wardrobeOpen = false; + } + return wardrobeOpen; + } + + private int wardrobePage = -1; + + private int getWardrobePage() { + GuiScreen guiScreen = Minecraft.getMinecraft().currentScreen; + if (guiScreen instanceof GuiChest) { + if (isInNamedGui("Wardrobe")) { + GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen; + ContainerChest container = (ContainerChest) chest.inventorySlots; + IInventory lower = container.getLowerChestInventory(); + String containerName = lower.getDisplayName().getUnformattedText(); + try { + wardrobePage = Integer.parseInt(containerName.substring(10, 11)); + } catch (NumberFormatException e) { + System.out.println(containerName.charAt(10)); + System.out.println("Did hypixel change the wardrobe string?"); + wardrobePage = -1; + } + } else wardrobePage = -1; + } + return wardrobePage; + } + + private ItemStack getChestSlotsAsItemStack(int slot) { + GuiScreen guiScreen = Minecraft.getMinecraft().currentScreen; + if (guiScreen instanceof GuiChest) { + GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen; + return chest.inventorySlots.getSlot(slot).getStack(); + } else { + return null; + } + } + + private int selectedArmor = 9; + + private int getEquippedArmor() { + if (!isInNamedGui("Wardrobe")) return selectedArmor; + + ItemStack nullTest1 = getChestSlotsAsItemStack(8); + ItemStack nullTest2 = getChestSlotsAsItemStack(17); + ItemStack nullTest3 = getChestSlotsAsItemStack(26); + ItemStack nullTest4 = getChestSlotsAsItemStack(35); + ItemStack nullTest5 = getChestSlotsAsItemStack(44); + if (nullTest1 != null || nullTest2 != null || nullTest3 != null || nullTest4 != null || nullTest5 != null) { + selectedArmor = 9; + } + for (int ii = 1; ii < 5; ii++) { + if (ii != 1 && selectedArmor != 9) continue; + if (getWardrobePage() != ii) continue; + for (int i = 8; i < 54; i += 9) { + ItemStack stack1 = getChestSlotsAsItemStack(i); + if (stack1 == null) continue; + String[] lore1 = NotEnoughUpdates.INSTANCE.manager.getLoreFromNBT(stack1.getTagCompound()); + for (String line : lore1) { + if (line.contains("to unequip this armor")) { + selectedArmor = i; + break; + } + } + } + } + return selectedArmor; + } + + private ItemStack getWardrobeSlot(int armourSlot) { + if (isInNamedGui("Wardrobe")) { + if (getChestSlotsAsItemStack(getEquippedArmor() - armourSlot) != null && getEquippedArmor() != 9) { + return getChestSlotsAsItemStack(getEquippedArmor() - armourSlot); + } else return null; + } else return null; + } + + public boolean isWardrobeSystemOnMainServer() { + JsonElement alphaWardrobeElement = Utils.getElement(Constants.DISABLE, "wardrobeFeature"); + if (alphaWardrobeElement == null || !alphaWardrobeElement.isJsonObject()) { + return true; + } + JsonObject isWardrobe = alphaWardrobeElement.getAsJsonObject(); + if (isWardrobe.has("enableNewWardrob")) { + return isWardrobe.get("enableNewWardrob").getAsBoolean(); + } else { + return true; + } + } + + public ItemStack slot1 = null; + public ItemStack slot2 = null; + public ItemStack slot3 = null; + public ItemStack slot4 = null; + public ItemStack petSlot = null; + + public static boolean isRenderingArmorHud() { + return renderingArmorHud; + } + + public static boolean isRenderingPetHud() { + return renderingPetHud; + } + + /** + * Renders the search bar, quick commands, item selection (right), item info (left) and armor hud gui elements. + */ + public void render(boolean hoverInv) { + if (disabled) return; + renderingArmorHud = false; + renderingPetHud = false; + GlStateManager.enableDepth(); + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + + Utils.resetGuiScale(); + Utils.pushGuiScale(NotEnoughUpdates.INSTANCE.config.itemlist.paneGuiScale); + + int width = Utils.peekGuiScale().getScaledWidth(); + int height = Utils.peekGuiScale().getScaledHeight(); + int mouseX = Mouse.getX() * width / Minecraft.getMinecraft().displayWidth; + int mouseY = height - Mouse.getY() * height / Minecraft.getMinecraft().displayHeight - 1; + + if (showVanillaLast != NotEnoughUpdates.INSTANCE.config.itemlist.showVanillaItems) { + showVanillaLast = NotEnoughUpdates.INSTANCE.config.itemlist.showVanillaItems; + updateSearch(); + } + + if (textField.getText().toLowerCase().contains("bald")) { + Minecraft.getMinecraft().getTextureManager().bindTexture(SUPERGEHEIMNISVERMOGEN); + GlStateManager.color(1, 1, 1, 1); + Utils.drawTexturedRect((width - 64) / 2f, (height - 64) / 2f - 114, 64, 64, GL11.GL_LINEAR); + GlStateManager.bindTexture(0); + } + GuiScreen guiScreen = Minecraft.getMinecraft().currentScreen; + + if (NotEnoughUpdates.INSTANCE.config.customArmour.enableArmourHud && + NotEnoughUpdates.INSTANCE.config.misc.hidePotionEffect + && + NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() && + isWardrobeSystemOnMainServer()) { + if (getWardrobeSlot(1) != null) { + slot1 = getWardrobeSlot(4); + slot2 = getWardrobeSlot(3); + slot3 = getWardrobeSlot(2); + slot4 = getWardrobeSlot(1); + } + if (guiScreen instanceof GuiInventory) { + renderingArmorHud = true; + selectedArmor = 9; + + List tooltipToDisplay = null; + if (NotEnoughUpdates.INSTANCE.config.customArmour.colourStyle == 0) { + Minecraft.getMinecraft().getTextureManager().bindTexture(ARMOR_DISPLAY); + } + if (NotEnoughUpdates.INSTANCE.config.customArmour.colourStyle == 1) { + Minecraft.getMinecraft().getTextureManager().bindTexture(ARMOR_DISPLAY_GREY); + } + if (NotEnoughUpdates.INSTANCE.config.customArmour.colourStyle == 2) { + Minecraft.getMinecraft().getTextureManager().bindTexture(ARMOR_DISPLAY_DARK); + } + if (NotEnoughUpdates.INSTANCE.config.customArmour.colourStyle == 3) { + if (NotEnoughUpdates.INSTANCE.config.petOverlay.colourStyle == 3 && + NotEnoughUpdates.INSTANCE.config.petOverlay.petInvDisplay && + petSlot != null) { + Minecraft.getMinecraft().getTextureManager().bindTexture(ARMOR_DISPLAY_TRANSPARENT_PET); + } else { + Minecraft.getMinecraft().getTextureManager().bindTexture(ARMOR_DISPLAY_TRANSPARENT); + } + } + if (NotEnoughUpdates.INSTANCE.config.customArmour.colourStyle == 4) { + Minecraft.getMinecraft().getTextureManager().bindTexture(ARMOR_DISPLAY_FSR); + } + + GlStateManager.color(1, 1, 1, 1); + GL11.glTranslatef(0, 0, 401); + float yNumber = (float) (height - 167) / 2f; + Utils.drawTexturedRect((float) ((width - 224.1) / 2f), yNumber, 31, 86, GL11.GL_NEAREST); + GlStateManager.bindTexture(0); + + Utils.drawItemStack(slot1, (int) ((width - 208) / 2f), (int) ((height + 60) / 2f - 105)); + Utils.drawItemStack(slot2, (int) ((width - 208) / 2f), (int) ((height + 60) / 2f - 105) + 18); + Utils.drawItemStack(slot3, (int) ((width - 208) / 2f), (int) ((height + 60) / 2f - 105) + 36); + Utils.drawItemStack(slot4, (int) ((width - 208) / 2f), (int) ((height + 60) / 2f - 105) + 54); + if (slot1 == null) { + Minecraft.getMinecraft().getTextureManager().bindTexture(QUESTION_MARK); + GlStateManager.color(1, 1, 1, 1); + Utils.drawTexturedRect(((width - 208) / 2f), ((height + 60) / 2f - 105), 16, 16, GL11.GL_NEAREST); + GlStateManager.bindTexture(0); + + tooltipToDisplay = Lists.newArrayList( + EnumChatFormatting.RED + "Warning", + EnumChatFormatting.GREEN + "You need to open /wardrobe", + EnumChatFormatting.GREEN + "To cache your armour" + ); + if (mouseX >= ((width - 208) / 2f) && mouseX < ((width - 208) / 2f) + 16) { + if (mouseY >= ((height + 60) / 2f - 105) && + mouseY <= ((height + 60) / 2f - 105) + 70 && + NotEnoughUpdates.INSTANCE.config.customArmour.sendWardrobeCommand) { + if (Minecraft.getMinecraft().thePlayer.inventory.getItemStack() == null) { + if (Mouse.getEventButtonState()) { + if (ClientCommandHandler.instance.executeCommand(Minecraft.getMinecraft().thePlayer, "/wardrobe") == + 0) { + NotEnoughUpdates.INSTANCE.sendChatMessage("/wardrobe"); + } + } + } + } + if (mouseY >= ((height + 60) / 2f - 105) && mouseY <= ((height + 60) / 2f - 105) + 16) { + Utils.drawHoveringText(tooltipToDisplay, mouseX, mouseY, width, height, -1, fr); + GL11.glTranslatef(0, 0, -401); + } + } + + } + if (slot1 != null && slot2 != null && slot3 != null && slot4 != null) { + if (mouseX >= ((width - 208) / 2f) && mouseX < ((width - 208) / 2f) + 16) { + if (mouseY >= ((height + 60) / 2f - 105) && + mouseY <= ((height + 60) / 2f - 105) + 70 && + NotEnoughUpdates.INSTANCE.config.customArmour.sendWardrobeCommand) { + if (Minecraft.getMinecraft().thePlayer.inventory.getItemStack() == null) { + if (Mouse.getEventButtonState()) { + if (ClientCommandHandler.instance.executeCommand(Minecraft.getMinecraft().thePlayer, "/wardrobe") == + 0) { + NotEnoughUpdates.INSTANCE.sendChatMessage("/wardrobe"); + } + } + } + } + //top slot + if (mouseY >= ((height + 60) / 2f - 105) && mouseY <= ((height + 60) / 2f - 105) + 16) { + tooltipToDisplay = slot1.getTooltip(Minecraft.getMinecraft().thePlayer, false); + Utils.drawHoveringText(tooltipToDisplay, mouseX, mouseY, width, height, -1, fr); + tooltipToDisplay = null; + GL11.glTranslatef(0, 0, -401); + } + if (mouseY >= ((height + 60) / 2f - 105) + 18 && mouseY <= ((height + 60) / 2f - 105) + 34) { + tooltipToDisplay = slot2.getTooltip(Minecraft.getMinecraft().thePlayer, false); + Utils.drawHoveringText(tooltipToDisplay, mouseX, mouseY, width, height, -1, fr); + tooltipToDisplay = null; + GL11.glTranslatef(0, 0, -401); + } + if (mouseY >= ((height + 60) / 2f - 105) + 36 && mouseY <= ((height + 60) / 2f - 105) + 52) { + tooltipToDisplay = slot3.getTooltip(Minecraft.getMinecraft().thePlayer, false); + Utils.drawHoveringText(tooltipToDisplay, mouseX, mouseY, width, height, -1, fr); + tooltipToDisplay = null; + GL11.glTranslatef(0, 0, -401); + } + if (mouseY >= ((height + 60) / 2f - 105) + 54 && mouseY <= ((height + 60) / 2f - 105) + 70) { + tooltipToDisplay = slot4.getTooltip(Minecraft.getMinecraft().thePlayer, false); + Utils.drawHoveringText(tooltipToDisplay, mouseX, mouseY, width, height, -1, fr); + tooltipToDisplay = null; + GL11.glTranslatef(0, 0, -401); + } + } + GL11.glTranslatef(0, 0, -401); + } + } + } + if (PetInfoOverlay.getCurrentPet() != null) { + if (NotEnoughUpdates.INSTANCE.config.petOverlay.petInvDisplay + && + (NotEnoughUpdates.INSTANCE.manager + .jsonToStack(NotEnoughUpdates.INSTANCE.manager + .getItemInformation() + .get(PetInfoOverlay.getCurrentPet().petType + ";" + PetInfoOverlay.getCurrentPet().rarity.petId)) + .hasDisplayName() + || + NotEnoughUpdates.INSTANCE.manager + .jsonToStack(NotEnoughUpdates.INSTANCE.manager + .getItemInformation() + .get(PetInfoOverlay.getCurrentPet().petType + ";" + (PetInfoOverlay.getCurrentPet().rarity.petId - 1))) + .hasDisplayName()) + && + NotEnoughUpdates.INSTANCE.config.misc.hidePotionEffect && + NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) { + if (!NotEnoughUpdates.INSTANCE.manager + .jsonToStack( + NotEnoughUpdates.INSTANCE.manager + .getItemInformation() + .get(PetInfoOverlay.getCurrentPet().petType + ";" + PetInfoOverlay.getCurrentPet().rarity.petId)) + .hasDisplayName()) { + petSlot = NotEnoughUpdates.INSTANCE.manager.jsonToStack( + NotEnoughUpdates.INSTANCE.manager.getItemInformation().get( + PetInfoOverlay.getCurrentPet().petType + ";" + (PetInfoOverlay.getCurrentPet().rarity.petId - 1))); + } else { + petSlot = NotEnoughUpdates.INSTANCE.manager.jsonToStack( + NotEnoughUpdates.INSTANCE.manager.getItemInformation().get( + PetInfoOverlay.getCurrentPet().petType + ";" + PetInfoOverlay.getCurrentPet().rarity.petId)); + } + petSlot.getTagCompound().setBoolean("NEUPETINVDISPLAY", true); + petSlot + .getTagCompound() + .setBoolean("NEUHIDEPETTOOLTIP", NotEnoughUpdates.INSTANCE.config.petOverlay.hidePetTooltip); + ItemStack petInfo = petSlot; + + if (guiScreen instanceof GuiInventory) { + GL11.glTranslatef(0, 0, 401); + if (!NotEnoughUpdates.INSTANCE.config.customArmour.enableArmourHud || !isWardrobeSystemOnMainServer()) { + if (NotEnoughUpdates.INSTANCE.config.petOverlay.colourStyle == 0) { + Minecraft.getMinecraft().getTextureManager().bindTexture(PET_DISPLAY); + } + if (NotEnoughUpdates.INSTANCE.config.petOverlay.colourStyle == 1) { + Minecraft.getMinecraft().getTextureManager().bindTexture(PET_DISPLAY_GREY); + } + if (NotEnoughUpdates.INSTANCE.config.petOverlay.colourStyle == 2) { + Minecraft.getMinecraft().getTextureManager().bindTexture(PET_DISPLAY_DARK); + } + if (NotEnoughUpdates.INSTANCE.config.petOverlay.colourStyle == 3) { + Minecraft.getMinecraft().getTextureManager().bindTexture(PET_DISPLAY_TRANSPARENT); + } + if (NotEnoughUpdates.INSTANCE.config.petOverlay.colourStyle == 4) { + Minecraft.getMinecraft().getTextureManager().bindTexture(PET_DISPLAY_FSR); + } + } else { + if (NotEnoughUpdates.INSTANCE.config.petOverlay.colourStyle == 0) { + Minecraft.getMinecraft().getTextureManager().bindTexture(PET_ARMOR_DISPLAY); + } + if (NotEnoughUpdates.INSTANCE.config.petOverlay.colourStyle == 1) { + Minecraft.getMinecraft().getTextureManager().bindTexture(PET_ARMOR_DISPLAY_GREY); + } + if (NotEnoughUpdates.INSTANCE.config.petOverlay.colourStyle == 2) { + Minecraft.getMinecraft().getTextureManager().bindTexture(PET_ARMOR_DISPLAY_DARK); + } + if (NotEnoughUpdates.INSTANCE.config.petOverlay.colourStyle == 3) { + Minecraft.getMinecraft().getTextureManager().bindTexture(PET_ARMOR_DISPLAY_TRANSPARENT); + } + if (NotEnoughUpdates.INSTANCE.config.petOverlay.colourStyle == 4) { + Minecraft.getMinecraft().getTextureManager().bindTexture(PET_ARMOR_DISPLAY_FSR); + } + } + + GlStateManager.color(1, 1, 1, 1); + float yNumber = (float) (height - 23) / 2f; + Utils.drawTexturedRect((float) ((width - 224.1) / 2f), yNumber, 31, 32, GL11.GL_NEAREST); + GlStateManager.bindTexture(0); + + Utils.drawItemStack(petInfo, (int) ((width - 208) / 2f), (int) ((height + 60) / 2f - 105) + 72); + renderingPetHud = true; + + List tooltipToDisplay = null; + if (petInfo != null) { + if (mouseX >= ((width - 208) / 2f) && mouseX < ((width - 208) / 2f) + 16) { + if (mouseY >= ((height + 60) / 2f - 105) + 72 && + mouseY <= ((height + 60) / 2f - 105) + 88 && + NotEnoughUpdates.INSTANCE.config.petOverlay.sendPetsCommand) { + if (Minecraft.getMinecraft().thePlayer.inventory.getItemStack() == null) { + if (Mouse.getEventButtonState()) { + if (ClientCommandHandler.instance.executeCommand(Minecraft.getMinecraft().thePlayer, "/pets") == + 0) { + NotEnoughUpdates.INSTANCE.sendChatMessage("/pets"); + } + } + } + tooltipToDisplay = petInfo.getTooltip(Minecraft.getMinecraft().thePlayer, false); + Utils.drawHoveringText(tooltipToDisplay, mouseX, mouseY, width, height, -1, fr); + tooltipToDisplay = null; + GL11.glTranslatef(0, 0, -80); + } + } + + } + } + } + } + + SunTzu.setEnabled(textField.getText().toLowerCase().startsWith("potato")); + + updateGuiGroupSize(); + + if (guiScaleLast != Utils.peekGuiScale().getScaleFactor()) { + guiScaleLast = Utils.peekGuiScale().getScaleFactor(); + redrawItems = true; + } + + if (oldWidthMult != getWidthMult()) { + oldWidthMult = getWidthMult(); + redrawItems = true; + } + + yaw++; + yaw %= 360; + + bg = new Color(SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.itemlist.backgroundColour), true); + fg = new Color(SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.itemlist.foregroundColour)); + Color fgCustomOpacity = + new Color(SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.itemlist.foregroundColour), true); + + Color fgFavourite2 = + new Color(SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.itemlist.favouriteColour), true); + Color fgFavourite = new Color((int) (fgFavourite2.getRed() * 0.8f), (int) (fgFavourite2.getGreen() * 0.8f), + (int) (fgFavourite2.getBlue() * 0.8f), fgFavourite2.getAlpha() + ); + + if (itemPaneOpen) { + if (itemPaneTabOffset.getValue() == 0) { + if (itemPaneOffsetFactor.getTarget() != 2 / 3f) { + itemPaneOffsetFactor.setTarget(2 / 3f); + itemPaneOffsetFactor.resetTimer(); + } + } else { + if (itemPaneTabOffset.getTarget() != 0) { + itemPaneTabOffset.setTarget(0); + itemPaneTabOffset.resetTimer(); + } + } + } else { + if (itemPaneOffsetFactor.getValue() == 1) { + if (itemPaneTabOffset.getTarget() != 20) { + itemPaneTabOffset.setTarget(20); + itemPaneTabOffset.resetTimer(); + } + } else { + if (itemPaneOffsetFactor.getTarget() != 1f) { + itemPaneOffsetFactor.setTarget(1f); + itemPaneOffsetFactor.resetTimer(); + } + } + } + + itemPaneOffsetFactor.tick(); + itemPaneTabOffset.tick(); + infoPaneOffsetFactor.tick(); + + if (page > getMaxPages() - 1) setPage(getMaxPages() - 1); + if (page < 0) setPage(0); + + GlStateManager.disableLighting(); + + /* + * Item selection (right) gui element rendering + */ + int paneWidth = (int) (width / 3 * getWidthMult()); + int leftSide = (int) (width * getItemPaneOffsetFactor()); + int rightSide = leftSide + paneWidth - getBoxPadding() - getItemBoxXPadding(); + + //Tab + if (NotEnoughUpdates.INSTANCE.config.itemlist.tabOpen) { + Minecraft.getMinecraft().getTextureManager().bindTexture(itemPaneTabArrow); + GlStateManager.color(1f, 1f, 1f, 0.3f); + Utils.drawTexturedRect(width - itemPaneTabOffset.getValue() * 64 / 20f, height / 2f - 32, 64, 64); + GlStateManager.bindTexture(0); + + if (!itemPaneOpen && mouseX > width - itemPaneTabOffset.getValue() && mouseY > height / 2 - 32 + && mouseY < height / 2 + 32) { + itemPaneOpen = true; + } + } + + //Atomic reference used so that below lambda doesn't complain about non-effectively-final variable + AtomicReference tooltipToDisplay = new AtomicReference<>(null); + //System.out.println(itemPaneOffsetFactor.getValue()); + if (itemPaneOffsetFactor.getValue() < 0.99) { + if (NotEnoughUpdates.INSTANCE.config.itemlist.bgBlurFactor > 0.5) { + BackgroundBlur.renderBlurredBackground(NotEnoughUpdates.INSTANCE.config.itemlist.bgBlurFactor, + width, height, + leftSide + getBoxPadding() - 5, getBoxPadding() - 5, + paneWidth - getBoxPadding() * 2 + 10, height - getBoxPadding() * 2 + 10, + itemPaneOffsetFactor.getValue() > 0.01 + ); + Gui.drawRect(leftSide + getBoxPadding() - 5, getBoxPadding() - 5, + leftSide + getBoxPadding() - 5 + paneWidth - getBoxPadding() * 2 + 10, + getBoxPadding() - 5 + height - getBoxPadding() * 2 + 10, 0xc8101010 + ); + } + + drawRect(leftSide + getBoxPadding() - 5, getBoxPadding() - 5, + leftSide + paneWidth - getBoxPadding() + 5, height - getBoxPadding() + 5, bg.getRGB() + ); + + renderNavElement(leftSide + getBoxPadding() + getItemBoxXPadding(), rightSide, getMaxPages(), page + 1, + Utils.peekGuiScale().getScaleFactor() < 4 ? "Page: " : "" + ); + + //Sort bar + drawRect(leftSide + getBoxPadding() + getItemBoxXPadding() - 1, + height - getBoxPadding() - ITEM_SIZE - 2, + rightSide + 1, + height - getBoxPadding(), fgCustomOpacity.getRGB() + ); + + float sortIconsMinX = (sortIcons.length + orderIcons.length) * (ITEM_SIZE + ITEM_PADDING) + ITEM_SIZE; + float availableX = rightSide - (leftSide + getBoxPadding() + getItemBoxXPadding()); + float sortOrderScaleFactor = Math.min(1, availableX / sortIconsMinX); + + int scaledITEM_SIZE = (int) (ITEM_SIZE * sortOrderScaleFactor); + int scaledItemPaddedSize = (int) ((ITEM_SIZE + ITEM_PADDING) * sortOrderScaleFactor); + int iconTop = height - getBoxPadding() - (ITEM_SIZE + scaledITEM_SIZE) / 2 - 1; + + boolean hoveredOverControl = false; + for (int i = 0; i < orderIcons.length; i++) { + int orderIconX = leftSide + getBoxPadding() + getItemBoxXPadding() + i * scaledItemPaddedSize; + drawRect(orderIconX, iconTop, scaledITEM_SIZE + orderIconX, iconTop + scaledITEM_SIZE, fg.getRGB()); + + Minecraft + .getMinecraft() + .getTextureManager() + .bindTexture(getCompareMode() == i ? orderIconsActive[i] : orderIcons[i]); + GlStateManager.color(1f, 1f, 1f, 1f); + Utils.drawTexturedRect(orderIconX, iconTop, scaledITEM_SIZE, scaledITEM_SIZE, 0, 1, 0, 1, GL11.GL_NEAREST); + + Minecraft + .getMinecraft() + .getTextureManager() + .bindTexture(getCompareAscending().get(i) ? ascending_overlay : descending_overlay); + GlStateManager.color(1f, 1f, 1f, 1f); + Utils.drawTexturedRect(orderIconX, iconTop, scaledITEM_SIZE, scaledITEM_SIZE, 0, 1, 0, 1, GL11.GL_NEAREST); + GlStateManager.bindTexture(0); + + if (mouseY > iconTop && mouseY < iconTop + scaledITEM_SIZE) { + if (mouseX > orderIconX && mouseX < orderIconX + scaledITEM_SIZE) { + hoveredOverControl = true; + if (System.currentTimeMillis() - millisLastMouseMove > 400) { + String text = EnumChatFormatting.GRAY + "Order "; + if (i == COMPARE_MODE_ALPHABETICAL) text += "Alphabetically"; + else if (i == COMPARE_MODE_RARITY) text += "by Rarity"; + else if (i == COMPARE_MODE_VALUE) text += "by Item Worth"; + else text = null; + if (text != null) textToDisplay = Utils.createList(text); + } + } + } + } + + for (int i = 0; i < sortIcons.length; i++) { + int sortIconX = rightSide - scaledITEM_SIZE - i * scaledItemPaddedSize; + drawRect(sortIconX, iconTop, scaledITEM_SIZE + sortIconX, iconTop + scaledITEM_SIZE, fg.getRGB()); + Minecraft + .getMinecraft() + .getTextureManager() + .bindTexture(getSortMode() == i ? sortIconsActive[i] : sortIcons[i]); + GlStateManager.color(1f, 1f, 1f, 1f); + Utils.drawTexturedRect(sortIconX, iconTop, scaledITEM_SIZE, scaledITEM_SIZE, 0, 1, 0, 1, GL11.GL_NEAREST); + GlStateManager.bindTexture(0); + + if (mouseY > iconTop && mouseY < iconTop + scaledITEM_SIZE) { + if (mouseX > sortIconX && mouseX < sortIconX + scaledITEM_SIZE) { + hoveredOverControl = true; + if (System.currentTimeMillis() - millisLastMouseMove > 400) { + String text = EnumChatFormatting.GRAY + "Filter "; + if (i == SORT_MODE_ALL) text = EnumChatFormatting.GRAY + "No Filter"; + else if (i == SORT_MODE_MOB) text += "Mobs"; + else if (i == SORT_MODE_PET) text += "Pets"; + else if (i == SORT_MODE_TOOL) text += "Tools"; + else if (i == SORT_MODE_ARMOR) text += "Armor"; + else if (i == SORT_MODE_ACCESSORY) text += "Accessories"; + else text = null; + if (text != null) textToDisplay = Utils.createList(text); + } + } + } + } + + if (!hoveredOverControl) { + millisLastMouseMove = System.currentTimeMillis(); + } + + if (selectedItemGroup != null) { + if (mouseX < selectedItemGroupX - 1 || mouseX > selectedItemGroupX + 17 || + mouseY < selectedItemGroupY - 1 || mouseY > selectedItemGroupY + 17) { + int selectedX = Math.min(selectedItemGroupX, width - getBoxPadding() - 18 * selectedItemGroup.size()); + if (mouseX < selectedX - 1 || mouseX > selectedX - 1 + 18 * selectedItemGroup.size() || + mouseY < selectedItemGroupY + 17 || mouseY > selectedItemGroupY + 35) { + selectedItemGroup = null; + selectedItemMillis = -1; + } + } + } + + if (!hoverInv) { + iterateItemSlots(new ItemSlotConsumer() { + public void consume(int x, int y, int id) { + JsonObject json = getSearchedItemPage(id); + if (json == null) { + return; + } + if (mouseX > x - 1 && mouseX < x + ITEM_SIZE + 1) { + if (mouseY > y - 1 && mouseY < y + ITEM_SIZE + 1) { + String internalname = json.get("internalname").getAsString(); + if (searchedItemsSubgroup.containsKey(internalname)) { + if (selectedItemMillis == -1) selectedItemMillis = System.currentTimeMillis(); + if (System.currentTimeMillis() - selectedItemMillis > 200 && + (selectedItemGroup == null || selectedItemGroup.isEmpty())) { + + ArrayList children = new ArrayList<>(); + children.add(json); + for (String itemname : searchedItemsSubgroup.get(internalname)) { + children.add(manager.getItemInformation().get(itemname)); + } + + selectedItemGroup = children; + selectedItemGroupX = x; + selectedItemGroupY = y; + } + } else { + tooltipToDisplay.set(json); + } + } + } + } + }); + } + + //Iterate through all item slots and display the appropriate item + int itemBoxXPadding = getItemBoxXPadding(); + int xStart = (int) (width * getItemPaneOffsetFactor()) + getBoxPadding() + itemBoxXPadding; + + if (OpenGlHelper.isFramebufferEnabled()) { + renderItemsFromImage(xStart, width, height); + renderEnchOverlay(); + + checkFramebufferSizes(width, height); + + if (redrawItems || !NotEnoughUpdates.INSTANCE.config.hidden.cacheRenderedItempane) { + renderItemsToImage(width, height, fgFavourite2, fgFavourite, fgCustomOpacity, true, true); + redrawItems = false; + } + } else { + renderItems(xStart, true, true, true); + } + + if (selectedItemGroup != null) { + GL11.glTranslatef(0, 0, 10); + + int selectedX = Math.min(selectedItemGroupX, width - getBoxPadding() - 18 * selectedItemGroup.size()); + + GlStateManager.enableDepth(); + GlStateManager.depthFunc(GL11.GL_LESS); + drawRect(selectedX, selectedItemGroupY + 18, + selectedX - 2 + 18 * selectedItemGroup.size(), selectedItemGroupY + 34, fgCustomOpacity.getRGB() + ); + drawRect(selectedX - 1, selectedItemGroupY + 17, + selectedX - 2 + 18 * selectedItemGroup.size(), selectedItemGroupY + 34, new Color(180, 180, 180).getRGB() + ); + drawRect(selectedX, selectedItemGroupY + 18, + selectedX - 1 + 18 * selectedItemGroup.size(), selectedItemGroupY + 35, new Color(30, 30, 30).getRGB() + ); + drawRect(selectedX - 1 + 2, selectedItemGroupY + 17 + 2, + selectedX - 1 + 18 * selectedItemGroup.size() + 2, selectedItemGroupY + 35 + 2, 0xa0000000 + ); + GlStateManager.depthFunc(GL11.GL_LEQUAL); + + GL11.glTranslatef(0, 0, 10); + + tooltipToDisplay.set(null); + if (mouseY > selectedItemGroupY + 17 && mouseY < selectedItemGroupY + 35) { + for (int i = 0; i < selectedItemGroup.size(); i++) { + if (mouseX >= selectedX - 1 + 18 * i && mouseX <= selectedX + 17 + 18 * i) { + tooltipToDisplay.set(selectedItemGroup.get(i)); + } + } + } + for (int i = 0; i < selectedItemGroup.size(); i++) { + JsonObject item = selectedItemGroup.get(i); + Utils.drawItemStack(manager.jsonToStack(item), selectedX + 18 * i, selectedItemGroupY + 18); + } + + GL11.glTranslatef(0, 0, -20); + } + + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate( + GL11.GL_SRC_ALPHA, + GL11.GL_ONE_MINUS_SRC_ALPHA, + GL11.GL_ONE, + GL11.GL_ONE_MINUS_SRC_ALPHA + ); + GlStateManager.enableAlpha(); + GlStateManager.alphaFunc(516, 0.1F); + GlStateManager.disableLighting(); + } + + /* + * Search bar & quickcommand elements + */ + guiGroup.render(0, 0); + resetAnchors(true); + + /* + * Item info (left) gui element rendering + */ + + rightSide = (int) (width * getInfoPaneOffsetFactor()); + leftSide = rightSide - paneWidth; + + if (activeInfoPane != null) { + activeInfoPane.tick(); + activeInfoPane.render(width, height, bg, fg, Utils.peekGuiScale(), mouseX, mouseY); + + GlStateManager.color(1f, 1f, 1f, 1f); + Minecraft.getMinecraft().getTextureManager().bindTexture(close); + Utils.drawTexturedRect(rightSide - getBoxPadding() - 8, getBoxPadding() - 8, 16, 16); + GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0); + } + + //Render tooltip + JsonObject json = tooltipToDisplay.get(); + if (json != null) { + + ItemStack stack = manager.jsonToStack(json); + { + NBTTagCompound tag = stack.getTagCompound(); + tag.setBoolean("DisablePetExp", true); + stack.setTagCompound(tag); + } + + List text = stack.getTooltip(Minecraft.getMinecraft().thePlayer, false); + + String internalname = json.get("internalname").getAsString(); + if (!NotEnoughUpdates.INSTANCE.config.tooltipTweaks.showPriceInfoInvItem) { + ItemPriceInformation.addToTooltip(text, internalname, stack); + } + + boolean hasClick = + (json.has("clickcommand") && !json.get("clickcommand").getAsString().isEmpty()) + || !manager.getAvailableRecipesFor(internalname).isEmpty(); + boolean hasInfo = json.has("info") && json.get("info").getAsJsonArray().size() > 0; + + if (hasClick || hasInfo) text.add(""); + if (hasClick) + text.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "LMB/R : View recipe!"); + if (hasInfo) + text.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "RMB : View additional information!"); + + textToDisplay = text; + } + if (textToDisplay != null) { + Utils.drawHoveringText(textToDisplay, mouseX, mouseY, width, height, -1, fr); + textToDisplay = null; + } + + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.enableAlpha(); + GlStateManager.alphaFunc(516, 0.1F); + GlStateManager.disableLighting(); + + Utils.pushGuiScale(-1); + + if (System.currentTimeMillis() - lastSearchMode > 120000 && + NotEnoughUpdates.INSTANCE.config.toolbar.autoTurnOffSearchMode + || !NotEnoughUpdates.INSTANCE.config.toolbar.searchBar) { + searchMode = false; + } + } + + /** + * Used in SettingsInfoPane to redraw the items when a setting changes. + */ + public void redrawItems() { + redrawItems = true; + } + + /** + * Sets the current page and marks that the itemsPane should be redrawn + */ + public void setPage(int page) { + this.page = page; + redrawItems = true; + } + + private final Framebuffer[] itemFramebuffers = new Framebuffer[2]; + + /** + * Checks whether the screen size has changed, if so it reconstructs the itemPane framebuffer and marks that the + * itemPane should be redrawn. + */ + private void checkFramebufferSizes(int width, int height) { + int sw = width * Utils.peekGuiScale().getScaleFactor(); + int sh = height * Utils.peekGuiScale().getScaleFactor(); + for (int i = 0; i < itemFramebuffers.length; i++) { + if (itemFramebuffers[i] == null || + itemFramebuffers[i].framebufferWidth != sw || + itemFramebuffers[i].framebufferHeight != sh) { + if (itemFramebuffers[i] == null) { + itemFramebuffers[i] = new Framebuffer(sw, sh, true); + } else { + itemFramebuffers[i].createBindFramebuffer(sw, sh); + } + itemFramebuffers[i].setFramebufferFilter(GL11.GL_NEAREST); + redrawItems = true; + } + } + } + + private void prepareFramebuffer(Framebuffer buffer, int sw, int sh) { + buffer.framebufferClear(); + buffer.bindFramebuffer(false); + GL11.glViewport(0, 0, sw, sh); + } + + private void cleanupFramebuffer(Framebuffer buffer, int sw, int sh) { + buffer.unbindFramebuffer(); + Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true); + } + + /** + * Renders all items to a framebuffer so that it can be reused later, drastically improving performance. + * Unfortunately using this feature will mean that animated textures will not work, but oh well. + * Mojang please optimize item rendering thanks. + */ + private void renderItemsToImage( + int width, int height, Color fgFavourite2, + Color fgFavourite, Color fgCustomOpacity, boolean items, boolean entities + ) { + int sw = width * Utils.peekGuiScale().getScaleFactor(); + int sh = height * Utils.peekGuiScale().getScaleFactor(); + + GL11.glPushMatrix(); + prepareFramebuffer(itemFramebuffers[0], sw, sh); + renderItems(10, items, entities, false); + cleanupFramebuffer(itemFramebuffers[0], sw, sh); + GL11.glPopMatrix(); + + GL11.glPushMatrix(); + prepareFramebuffer(itemFramebuffers[1], sw, sh); + renderItemBackgrounds(fgFavourite2, fgFavourite, fgCustomOpacity); + cleanupFramebuffer(itemFramebuffers[1], sw, sh); + GL11.glPopMatrix(); + } + + private static final ResourceLocation RES_ITEM_GLINT = new ResourceLocation("textures/misc/enchanted_item_glint.png"); + + /** + * Renders the framebuffer created by #renderItemsToImage to the screen. + * itemRenderOffset is a magic number that makes the z-level of the rendered items equal to the z-level of + * the item glint overlay model, meaning that a depthFunc of GL_EQUAL can correctly render on to the item. + */ + float itemRenderOffset = 7.5001f; + + private void renderItemsFromImage(int xOffset, int width, int height) { + if (itemFramebuffers[0] != null && itemFramebuffers[1] != null) { + itemFramebuffers[1].bindFramebufferTexture(); + GlStateManager.color(1f, 1f, 1f, 1f); + Utils.drawTexturedRect(xOffset - 10, 0, width, height, 0, 1, 1, 0); + itemFramebuffers[1].unbindFramebufferTexture(); + + GL11.glTranslatef(0, 0, itemRenderOffset); + itemFramebuffers[0].bindFramebufferTexture(); + GlStateManager.color(1f, 1f, 1f, 1f); + Utils.drawTexturedRect(xOffset - 10, 0, width, height, 0, 1, 1, 0); + itemFramebuffers[0].unbindFramebufferTexture(); + GL11.glTranslatef(0, 0, -itemRenderOffset); + } + } + + /** + * Renders the enchant overlay, since only the items have the specific z-offset of 7.5001, this will only apply + * the enchant overlay to the actual items and not anything else. + *

+ * (I tried very hard to replicate the enchant rendering overlay code from vanilla, but I couldn't get it to + * work without rendering with the "ITEM" vertex model like in vanilla, so I choose to render an arbitrary 2D + * item. If a texture pack sets a custom 3D model for an apple, this will probably break.) + */ + private void renderEnchOverlay() { + ItemStack stack = new ItemStack(Items.apple); + IBakedModel model = Minecraft.getMinecraft().getRenderItem().getItemModelMesher() + .getItemModel(stack); + float f = (float) (Minecraft.getSystemTime() % 3000L) / 3000.0F / 8.0F; + float f1 = (float) (Minecraft.getSystemTime() % 4873L) / 4873.0F / 8.0F; + Minecraft.getMinecraft().getTextureManager().bindTexture(RES_ITEM_GLINT); + + GL11.glPushMatrix(); + GL11.glTranslatef(0, 0, -7.5001f + itemRenderOffset); + iterateItemSlots(new ItemSlotConsumer() { + public void consume(int x, int y, int id) { + JsonObject json = getSearchedItemPage(id); + if (json == null) { + return; + } + ItemStack stack = manager.jsonToStack(json, true, true, false); + if (stack == null || !stack.hasEffect()) { + return; + } + + GlStateManager.pushMatrix(); + GlStateManager.enableRescaleNormal(); + GlStateManager.enableAlpha(); + GlStateManager.alphaFunc(516, 0.1F); + GlStateManager.enableBlend(); + + GlStateManager.disableLighting(); + + GlStateManager.translate(x, y, 0); + GlStateManager.scale(16f, 16f, 16f); + + GlStateManager.depthMask(false); + GlStateManager.depthFunc(GL11.GL_EQUAL); + GlStateManager.blendFunc(GL11.GL_SRC_COLOR, GL11.GL_ONE); + GlStateManager.matrixMode(5890); + GlStateManager.pushMatrix(); + GlStateManager.scale(8.0F, 8.0F, 8.0F); + GlStateManager.translate(f, 0.0F, 0.0F); + GlStateManager.rotate(-50.0F, 0.0F, 0.0F, 1.0F); + + renderModel(model, -8372020, null); + + GlStateManager.popMatrix(); + GlStateManager.pushMatrix(); + GlStateManager.scale(8.0F, 8.0F, 8.0F); + GlStateManager.translate(-f1, 0.0F, 0.0F); + GlStateManager.rotate(10.0F, 0.0F, 0.0F, 1.0F); + + renderModel(model, -8372020, null); + + GlStateManager.popMatrix(); + GlStateManager.matrixMode(5888); + GlStateManager.blendFunc(770, 771); + GlStateManager.depthFunc(515); + GlStateManager.depthMask(true); + + GlStateManager.popMatrix(); + } + }); + GlStateManager.disableBlend(); + GlStateManager.disableAlpha(); + GlStateManager.disableRescaleNormal(); + GL11.glTranslatef(0, 0, 7.5001f - itemRenderOffset); + GL11.glPopMatrix(); + + GlStateManager.bindTexture(0); + } + + private void renderModel(IBakedModel model, int color, ItemStack stack) { + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer worldrenderer = tessellator.getWorldRenderer(); + worldrenderer.begin(7, DefaultVertexFormats.ITEM); + + for (EnumFacing enumfacing : EnumFacing.values()) { + this.renderQuads(worldrenderer, model.getFaceQuads(enumfacing), color); + } + + this.renderQuads(worldrenderer, model.getGeneralQuads(), color); + + tessellator.draw(); + } + + private void renderQuads(WorldRenderer renderer, List quads, int color) { + if (quads == null) return; + + for (BakedQuad quad : quads) { + renderer.addVertexData(quad.getVertexData()); + renderer.putColor4(color); + } + } + + /** + * Renders all the item backgrounds, either squares or squircles. + */ + private void renderItemBackgrounds(Color fgFavourite2, Color fgFavourite, Color fgCustomOpacity) { + if (fgCustomOpacity.getAlpha() == 0) return; + iterateItemSlots(new ItemSlotConsumer() { + public void consume(int x, int y, int id) { + JsonObject json = getSearchedItemPage(id); + if (json == null) { + return; + } + + Minecraft.getMinecraft().getTextureManager().bindTexture(item_mask); + if (getFavourites().contains(json.get("internalname").getAsString())) { + if (NotEnoughUpdates.INSTANCE.config.itemlist.itemStyle == 0) { + GlStateManager.color(fgFavourite2.getRed() / 255f, fgFavourite2.getGreen() / 255f, + fgFavourite2.getBlue() / 255f, fgFavourite2.getAlpha() / 255f + ); + Utils.drawTexturedRect(x - 1, y - 1, ITEM_SIZE + 2, ITEM_SIZE + 2, GL11.GL_NEAREST); + + GlStateManager.color(fgFavourite.getRed() / 255f, fgFavourite.getGreen() / 255f, + fgFavourite.getBlue() / 255f, fgFavourite.getAlpha() / 255f + ); + Utils.drawTexturedRect(x, y, ITEM_SIZE, ITEM_SIZE, GL11.GL_NEAREST); + } else { + drawRect(x - 1, y - 1, x + ITEM_SIZE + 1, y + ITEM_SIZE + 1, fgFavourite2.getRGB()); + drawRect(x, y, x + ITEM_SIZE, y + ITEM_SIZE, fgFavourite.getRGB()); + } + } else { + if (NotEnoughUpdates.INSTANCE.config.itemlist.itemStyle == 0) { + GlStateManager.color(fgCustomOpacity.getRed() / 255f, fgCustomOpacity.getGreen() / 255f, + fgCustomOpacity.getBlue() / 255f, fgCustomOpacity.getAlpha() / 255f + ); + Utils.drawTexturedRect(x - 1, y - 1, ITEM_SIZE + 2, ITEM_SIZE + 2, GL11.GL_NEAREST); + } else { + drawRect(x - 1, y - 1, x + ITEM_SIZE + 1, y + ITEM_SIZE + 1, fgCustomOpacity.getRGB()); + } + } + GlStateManager.bindTexture(0); + } + }, 10); + } + + private void renderItems(int xStart, boolean items, boolean entities, boolean glint) { + iterateItemSlots(new ItemSlotConsumer() { + public void consume(int x, int y, int id) { + JsonObject json = getSearchedItemPage(id); + if (json == null) { + return; + } + + if (json.has("entityrender")) { + if (!entities) return; + String name = json.get("displayname").getAsString(); + String[] split = name.split(" \\("); + name = name.substring(0, name.length() - split[split.length - 1].length() - 2); + + Class[] entities = new Class[1]; + if (json.get("entityrender").isJsonArray()) { + JsonArray entityrender = json.get("entityrender").getAsJsonArray(); + entities = new Class[entityrender.size()]; + for (int i = 0; i < entityrender.size(); i++) { + Class clazz = EntityList.stringToClassMapping.get(entityrender.get(i).getAsString()); + if (clazz != null && EntityLivingBase.class.isAssignableFrom(clazz)) { + entities[i] = (Class) clazz; + } + } + } else if (json.get("entityrender").isJsonPrimitive()) { + Class clazz = EntityList.stringToClassMapping.get(json.get("entityrender").getAsString()); + if (clazz != null && EntityLivingBase.class.isAssignableFrom(clazz)) { + entities[0] = (Class) clazz; + } + } + + float scale = 8; + if (json.has("entityscale")) { + scale *= json.get("entityscale").getAsFloat(); + } + + renderEntity(x + ITEM_SIZE / 2, y + ITEM_SIZE, scale, name, entities); + } else { + if (!items) return; + ItemStack stack = manager.jsonToStack(json, true, true, false); + if (stack != null) { + if (glint) { + Utils.drawItemStack(stack, x, y); + } else { + Utils.drawItemStackWithoutGlint(stack, x, y); + } + } + } + + GlStateManager.translate(0, 0, 50); + if (searchedItemsSubgroup.containsKey(json.get("internalname").getAsString())) { + Minecraft.getMinecraft().getTextureManager().bindTexture(item_haschild); + GlStateManager.color(1, 1, 1, 1); + Utils.drawTexturedRect(x - 1, y - 1, ITEM_SIZE + 2, ITEM_SIZE + 2, GL11.GL_NEAREST); + } + GlStateManager.translate(0, 0, -50); + } + }, xStart); + } + + public float getItemPaneOffsetFactor() { + return itemPaneOffsetFactor.getValue() * getWidthMult() + (1 - getWidthMult()); + } + + public float getInfoPaneOffsetFactor() { + return infoPaneOffsetFactor.getValue() * getWidthMult(); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java index 6a0d3ab4a5..b6ac71a42c 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java @@ -1,372 +1,408 @@ package io.github.moulberry.notenoughupdates; -import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import io.github.moulberry.notenoughupdates.auction.CustomAHGui; -import io.github.moulberry.notenoughupdates.collectionlog.GuiCollectionLog; import io.github.moulberry.notenoughupdates.commands.Commands; -import io.github.moulberry.notenoughupdates.commands.SimpleCommand; import io.github.moulberry.notenoughupdates.core.BackgroundBlur; -import io.github.moulberry.notenoughupdates.core.GuiScreenElementWrapper; -import io.github.moulberry.notenoughupdates.core.config.GuiPositionEditor; -import io.github.moulberry.notenoughupdates.core.util.MiscUtils; import io.github.moulberry.notenoughupdates.cosmetics.CapeManager; -import io.github.moulberry.notenoughupdates.cosmetics.GuiCosmetics; import io.github.moulberry.notenoughupdates.dungeons.DungeonMap; -import io.github.moulberry.notenoughupdates.dungeons.DungeonWin; -import io.github.moulberry.notenoughupdates.dungeons.GuiDungeonMapEditor; -import io.github.moulberry.notenoughupdates.gamemodes.GuiGamemodes; import io.github.moulberry.notenoughupdates.miscfeatures.*; -import io.github.moulberry.notenoughupdates.miscgui.*; -import io.github.moulberry.notenoughupdates.miscgui.tutorials.NeuTutorial; +import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.CustomBiomes; +import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.CustomBlockSounds; +import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.DwarvenMinesTextures; +import io.github.moulberry.notenoughupdates.miscgui.CalendarOverlay; +import io.github.moulberry.notenoughupdates.miscgui.InventoryStorageSelector; import io.github.moulberry.notenoughupdates.options.NEUConfig; -import io.github.moulberry.notenoughupdates.options.NEUConfigEditor; import io.github.moulberry.notenoughupdates.overlays.FuelBar; import io.github.moulberry.notenoughupdates.overlays.OverlayManager; -import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer; -import io.github.moulberry.notenoughupdates.profileviewer.PlayerStats; import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer; +import io.github.moulberry.notenoughupdates.recipes.RecipeGenerator; import io.github.moulberry.notenoughupdates.util.SBInfo; -import io.github.moulberry.notenoughupdates.util.Constants; import io.github.moulberry.notenoughupdates.util.Utils; import io.github.moulberry.notenoughupdates.util.XPInformation; -import net.minecraft.block.material.MapColor; import net.minecraft.client.Minecraft; -import net.minecraft.client.entity.AbstractClientPlayer; -import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.client.gui.GuiScreen; -import net.minecraft.client.renderer.OpenGlHelper; import net.minecraft.client.resources.IReloadableResourceManager; import net.minecraft.client.settings.KeyBinding; -import net.minecraft.command.ICommandSender; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.event.ClickEvent; -import net.minecraft.item.ItemMap; -import net.minecraft.item.ItemStack; import net.minecraft.scoreboard.ScoreObjective; import net.minecraft.scoreboard.Scoreboard; -import net.minecraft.util.*; -import net.minecraft.world.storage.MapData; -import net.minecraftforge.client.ClientCommandHandler; -import net.minecraftforge.common.ForgeVersion; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.world.biome.*; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.client.registry.ClientRegistry; -import net.minecraftforge.fml.common.Loader; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventHandler; -import net.minecraftforge.fml.common.ModContainer; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.TickEvent; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.text.WordUtils; -import org.lwjgl.opengl.Display; -import org.lwjgl.opengl.GL11; import java.awt.*; -import java.awt.datatransfer.StringSelection; import java.io.*; -import java.lang.management.ManagementFactory; -import java.net.URI; -import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; -import java.util.*; -import java.util.List; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; +import java.util.HashMap; +import java.util.Set; @Mod(modid = NotEnoughUpdates.MODID, version = NotEnoughUpdates.VERSION, clientSideOnly = true) public class NotEnoughUpdates { - public static final String MODID = "notenoughupdates"; - public static final String VERSION = "2.0.0-REL"; - public static final String PRE_VERSION = "30.2"; - public static final int VERSION_ID = 20000; - public static final int PRE_VERSION_ID = 3002; - - public static NotEnoughUpdates INSTANCE = null; - - public NEUManager manager; - public NEUOverlay overlay; - public NEUConfig config; - - private File configFile; - - public File getConfigFile(){ - return this.configFile; - } - public void newConfigFile(){ - this.configFile = new File(NotEnoughUpdates.INSTANCE.getNeuDir(), "configNew.json"); - } - - private static final long CHAT_MSG_COOLDOWN = 200; - private long lastChatMessage = 0; - private long secondLastChatMessage = 0; - private String currChatMessage = null; - - //Stolen from Biscut and used for detecting whether in skyblock - private static final Set SKYBLOCK_IN_ALL_LANGUAGES = Sets.newHashSet("SKYBLOCK","\u7A7A\u5C9B\u751F\u5B58", "\u7A7A\u5CF6\u751F\u5B58"); - - public GuiScreen openGui = null; - public long lastOpenedGui = 0; - - public Commands commands; - - - - public static HashMap petRarityToColourMap = new HashMap<>(); - static { - petRarityToColourMap.put("UNKNOWN", EnumChatFormatting.RED.toString()); - - petRarityToColourMap.put("COMMON", EnumChatFormatting.WHITE.toString()); - petRarityToColourMap.put("UNCOMMON", EnumChatFormatting.GREEN.toString()); - petRarityToColourMap.put("RARE", EnumChatFormatting.BLUE.toString()); - petRarityToColourMap.put("EPIC", EnumChatFormatting.DARK_PURPLE.toString()); - petRarityToColourMap.put("LEGENDARY", EnumChatFormatting.GOLD.toString()); - petRarityToColourMap.put("MYTHIC", EnumChatFormatting.LIGHT_PURPLE.toString()); - } - - public static ProfileViewer profileViewer; - - public boolean packDevEnabled = false; - - private Gson gson = new GsonBuilder().setPrettyPrinting().excludeFieldsWithoutExposeAnnotation().create(); - private File neuDir; - - public File getNeuDir(){ return this.neuDir;} - - public Color[][] colourMap = null; - - /** - * Instantiates NEUIo, NEUManager and NEUOverlay instances. Registers keybinds and adds a shutdown hook to clear tmp folder. - * @param event - */ - @EventHandler - public void preinit(FMLPreInitializationEvent event) { - INSTANCE = this; - - neuDir = new File(event.getModConfigurationDirectory(), "notenoughupdates"); - neuDir.mkdirs(); - - configFile = new File(neuDir, "configNew.json"); - - if(configFile.exists()) { - try(BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(configFile), StandardCharsets.UTF_8))) { - config = gson.fromJson(reader, NEUConfig.class); - } catch(Exception e) { } - } - - ItemCustomizeManager.loadCustomization(new File(neuDir, "itemCustomization.json")); - StorageManager.getInstance().loadConfig(new File(neuDir, "storageItems.json")); - FairySouls.load(new File(neuDir, "collected_fairy_souls.json"), gson); - PetInfoOverlay.loadConfig(new File(neuDir, "petCache.json")); - SlotLocking.getInstance().loadConfig(new File(neuDir, "slotLocking.json")); - - if(config == null) { - config = new NEUConfig(); - saveConfig(); - } - - MinecraftForge.EVENT_BUS.register(this); - MinecraftForge.EVENT_BUS.register(new NEUEventListener(this)); - MinecraftForge.EVENT_BUS.register(CapeManager.getInstance()); - //MinecraftForge.EVENT_BUS.register(new SBGamemodes()); - MinecraftForge.EVENT_BUS.register(new EnchantingSolvers()); - MinecraftForge.EVENT_BUS.register(new CalendarOverlay()); - MinecraftForge.EVENT_BUS.register(SBInfo.getInstance()); - MinecraftForge.EVENT_BUS.register(CustomItemEffects.INSTANCE); - MinecraftForge.EVENT_BUS.register(new DungeonMap()); - MinecraftForge.EVENT_BUS.register(new SunTzu()); - MinecraftForge.EVENT_BUS.register(new MiningStuff()); - MinecraftForge.EVENT_BUS.register(new FairySouls()); - MinecraftForge.EVENT_BUS.register(new CrystalOverlay()); - MinecraftForge.EVENT_BUS.register(new ItemCooldowns()); - MinecraftForge.EVENT_BUS.register(new DwarvenMinesTextures()); - MinecraftForge.EVENT_BUS.register(new DwarvenMinesWaypoints()); - MinecraftForge.EVENT_BUS.register(new FuelBar()); - //MinecraftForge.EVENT_BUS.register(new FancyPortals()); - MinecraftForge.EVENT_BUS.register(XPInformation.getInstance()); - MinecraftForge.EVENT_BUS.register(OverlayManager.petInfoOverlay); - MinecraftForge.EVENT_BUS.register(OverlayManager.timersOverlay); - MinecraftForge.EVENT_BUS.register(new NullzeeSphere()); - MinecraftForge.EVENT_BUS.register(InventoryStorageSelector.getInstance()); - MinecraftForge.EVENT_BUS.register(SlotLocking.getInstance()); - MinecraftForge.EVENT_BUS.register(FishingHelper.getInstance()); - - if(Minecraft.getMinecraft().getResourceManager() instanceof IReloadableResourceManager) { - ((IReloadableResourceManager)Minecraft.getMinecraft().getResourceManager()).registerReloadListener(CustomSkulls.getInstance()); - ((IReloadableResourceManager)Minecraft.getMinecraft().getResourceManager()).registerReloadListener(NPCRetexturing.getInstance()); - ((IReloadableResourceManager)Minecraft.getMinecraft().getResourceManager()).registerReloadListener(new ItemCustomizeManager.ReloadListener()); - } - - this.commands = new Commands(); - - BackgroundBlur.registerListener(); - - manager = new NEUManager(this, neuDir); - manager.loadItemInformation(); - overlay = new NEUOverlay(manager); - profileViewer = new ProfileViewer(manager); - - for(KeyBinding kb : manager.keybinds) { - ClientRegistry.registerKeyBinding(kb); - } - - Runtime.getRuntime().addShutdownHook(new Thread(() -> { - File tmp = new File(neuDir, "tmp"); - if(tmp.exists()) { - for(File tmpFile : tmp.listFiles()) { - tmpFile.delete(); - } - tmp.delete(); - } - //saveConfig(); - })); - } - - public void saveConfig() { - try { - configFile.createNewFile(); - - try(BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(configFile), StandardCharsets.UTF_8))) { - writer.write(gson.toJson(config)); - } - } catch(Exception ignored) {} - - try { ItemCustomizeManager.saveCustomization(new File(neuDir, "itemCustomization.json")); } catch(Exception ignored) {} - try { StorageManager.getInstance().saveConfig(new File(neuDir, "storageItems.json")); } catch(Exception ignored) {} - try { FairySouls.save(new File(neuDir, "collected_fairy_souls.json"), gson); } catch(Exception ignored) {} - try { PetInfoOverlay.saveConfig(new File(neuDir, "petCache.json")); } catch(Exception ignored) {} - try { SlotLocking.getInstance().saveConfig(new File(neuDir, "slotLocking.json")); } catch(Exception ignored) {} - } - - /** - * If the last chat messages was sent >200ms ago, sends the message. - * If the last chat message was sent <200 ago, will cache the message for #onTick to handle. - */ - public void sendChatMessage(String message) { - if(System.currentTimeMillis() - lastChatMessage > CHAT_MSG_COOLDOWN) { - secondLastChatMessage = lastChatMessage; - lastChatMessage = System.currentTimeMillis(); - Minecraft.getMinecraft().thePlayer.sendChatMessage(message); - currChatMessage = null; - } else { - currChatMessage = message; - } - } - - public void displayLinks(JsonObject update) { - String discord_link = update.get("discord_link").getAsString(); - String youtube_link = update.get("youtube_link").getAsString(); - String twitch_link = update.get("twitch_link").getAsString(); - String update_link = update.get("update_link").getAsString(); - String github_link = update.get("github_link").getAsString(); - String other_text = update.get("other_text").getAsString(); - String other_link = update.get("other_link").getAsString(); - - ChatComponentText other = null; - if(other_text.length() > 0) { - other = new ChatComponentText(EnumChatFormatting.GRAY+"["+EnumChatFormatting.BLUE+other_text+EnumChatFormatting.GRAY+"]"); - other.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, other_link)); - } - ChatComponentText links = new ChatComponentText(""); - ChatComponentText separator = new ChatComponentText( - EnumChatFormatting.GRAY+EnumChatFormatting.BOLD.toString()+EnumChatFormatting.STRIKETHROUGH+(other==null?"--":"-")); - ChatComponentText discord = new ChatComponentText(EnumChatFormatting.GRAY+"["+EnumChatFormatting.BLUE+"Discord"+EnumChatFormatting.GRAY+"]"); - discord.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, discord_link)); - ChatComponentText youtube = new ChatComponentText(EnumChatFormatting.GRAY+"["+EnumChatFormatting.RED+"YouTube"+EnumChatFormatting.GRAY+"]"); - youtube.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, youtube_link)); - ChatComponentText twitch = new ChatComponentText(EnumChatFormatting.GRAY+"["+EnumChatFormatting.DARK_PURPLE+"Twitch"+EnumChatFormatting.GRAY+"]"); - twitch.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, twitch_link)); - ChatComponentText release = new ChatComponentText(EnumChatFormatting.GRAY+"["+EnumChatFormatting.GREEN+"Release"+EnumChatFormatting.GRAY+"]"); - release.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, update_link)); - ChatComponentText github = new ChatComponentText(EnumChatFormatting.GRAY+"["+EnumChatFormatting.DARK_PURPLE+"GitHub"+EnumChatFormatting.GRAY+"]"); - github.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, github_link)); - - links.appendSibling(separator); - links.appendSibling(discord); - links.appendSibling(separator); - links.appendSibling(youtube); - links.appendSibling(separator); - links.appendSibling(twitch); - links.appendSibling(separator); - links.appendSibling(release); - links.appendSibling(separator); - links.appendSibling(github); - links.appendSibling(separator); - if(other != null) { - links.appendSibling(other); - links.appendSibling(separator); - } - - Minecraft.getMinecraft().thePlayer.addChatMessage(links); - } - - @SubscribeEvent - public void onTick(TickEvent.ClientTickEvent event) { - if (event.phase != TickEvent.Phase.START) return; - if(Minecraft.getMinecraft().thePlayer == null) { - openGui = null; - currChatMessage = null; - return; - } - long currentTime = System.currentTimeMillis(); - - if (openGui != null) { - if(Minecraft.getMinecraft().thePlayer.openContainer != null) { - Minecraft.getMinecraft().thePlayer.closeScreen(); - } - Minecraft.getMinecraft().displayGuiScreen(openGui); - openGui = null; - lastOpenedGui = System.currentTimeMillis(); - } - if(currChatMessage != null && currentTime - lastChatMessage > CHAT_MSG_COOLDOWN) { - lastChatMessage = currentTime; - Minecraft.getMinecraft().thePlayer.sendChatMessage(currChatMessage); - currChatMessage = null; - } - } - - public boolean isOnSkyblock() { - if(!config.misc.onlyShowOnSkyblock) return true; - return hasSkyblockScoreboard(); - } - - private boolean hasSkyblockScoreboard; - - public boolean hasSkyblockScoreboard() { - return hasSkyblockScoreboard; - } - - public void updateSkyblockScoreboard() { - Minecraft mc = Minecraft.getMinecraft(); - - if (mc != null && mc.theWorld != null && mc.thePlayer != null) { - if (mc.isSingleplayer() || mc.thePlayer.getClientBrand() == null || - !mc.thePlayer.getClientBrand().toLowerCase().contains("hypixel")) { - hasSkyblockScoreboard = false; - return; - } - - Scoreboard scoreboard = mc.theWorld.getScoreboard(); - ScoreObjective sidebarObjective = scoreboard.getObjectiveInDisplaySlot(1); - if (sidebarObjective != null) { - String objectiveName = sidebarObjective.getDisplayName().replaceAll("(?i)\\u00A7.", ""); - for (String skyblock : SKYBLOCK_IN_ALL_LANGUAGES) { - if (objectiveName.startsWith(skyblock)) { - hasSkyblockScoreboard = true; - return; - } - } - } - - hasSkyblockScoreboard = false; - } - - } + public static final String MODID = "notenoughupdates"; + public static final String VERSION = "2.1.0-REL"; + public static final String PRE_VERSION = "0.0"; + public static final int VERSION_ID = 20100; + public static final int PRE_VERSION_ID = 0; + + public static NotEnoughUpdates INSTANCE = null; + + public NEUManager manager; + public NEUOverlay overlay; + public NEUConfig config; + + private File configFile; + + public File getConfigFile() { + return this.configFile; + } + + public void newConfigFile() { + this.configFile = new File(NotEnoughUpdates.INSTANCE.getNeuDir(), "configNew.json"); + } + + private static final long CHAT_MSG_COOLDOWN = 200; + private long lastChatMessage = 0; + private long secondLastChatMessage = 0; + private String currChatMessage = null; + + //Stolen from Biscut and used for detecting whether in skyblock + private static final Set SKYBLOCK_IN_ALL_LANGUAGES = + Sets.newHashSet("SKYBLOCK", "\u7A7A\u5C9B\u751F\u5B58", "\u7A7A\u5CF6\u751F\u5B58"); + + public GuiScreen openGui = null; + public long lastOpenedGui = 0; + + public Commands commands; + + public static HashMap petRarityToColourMap = new HashMap() {{ + put("UNKNOWN", EnumChatFormatting.RED.toString()); + put("COMMON", EnumChatFormatting.WHITE.toString()); + put("UNCOMMON", EnumChatFormatting.GREEN.toString()); + put("RARE", EnumChatFormatting.BLUE.toString()); + put("EPIC", EnumChatFormatting.DARK_PURPLE.toString()); + put("LEGENDARY", EnumChatFormatting.GOLD.toString()); + put("MYTHIC", EnumChatFormatting.LIGHT_PURPLE.toString()); + }}; + + public static ProfileViewer profileViewer; + + public boolean packDevEnabled = false; + + private final Gson gson = new GsonBuilder().setPrettyPrinting().excludeFieldsWithoutExposeAnnotation().create(); + private File neuDir; + + public File getNeuDir() { + return this.neuDir; + } + + public Color[][] colourMap = null; + + /** + * Registers the biomes for the crystal hollows here so optifine knows they exists + */ + public static final BiomeGenBase crystalHollowsJungle = + (new BiomeGenJungle(101, true)) + .setColor(5470985) + .setBiomeName("NeuCrystalHollowsJungle") + .setFillerBlockMetadata(5470985) + .setTemperatureRainfall(0.95F, 0.9F); + public static final BiomeGenBase crystalHollowsMagmaFields = + (new BiomeGenHell(102)) + .setColor(16711680) + .setBiomeName("NeuCrystalHollowsMagmaFields") + .setDisableRain() + .setTemperatureRainfall(2.0F, 0.0F); + public static final BiomeGenBase crystalHollowsGoblinHoldout = + (new BiomeGenMesa(103, false, false)) + .setColor(13274213) + .setBiomeName("NeuCrystalHollowsGoblinHoldout"); + public static final BiomeGenBase crystalHollowsPrecursorRemnants = + (new BiomeGenMesa(104, false, true)) + .setColor(11573093) + .setBiomeName("NeuCrystalHollowsPrecursorRemnants"); + public static final BiomeGenBase crystalHollowsMithrilDeposit = + (new BiomeGenSnow(105, false)) + .setColor(16777215) + .setBiomeName("NeuCrystalHollowsMithrilDeposits"); + public static final BiomeGenBase crystalHollowsCrystalNucleus = + (new BiomeGenJungle(106, true)) + .setColor(5470985) + .setBiomeName("NeuCrystalHollowsCrystalNucleus") + .setFillerBlockMetadata(5470985) + .setTemperatureRainfall(0.95F, 0.9F); + + /** + * Instantiates NEUIo, NEUManager and NEUOverlay instances. Registers keybinds and adds a shutdown hook to clear tmp folder. + */ + @EventHandler + public void preinit(FMLPreInitializationEvent event) { + INSTANCE = this; + + neuDir = new File(event.getModConfigurationDirectory(), "notenoughupdates"); + neuDir.mkdirs(); + + configFile = new File(neuDir, "configNew.json"); + + if (configFile.exists()) { + try ( + BufferedReader reader = new BufferedReader(new InputStreamReader( + new FileInputStream(configFile), + StandardCharsets.UTF_8 + )) + ) { + config = gson.fromJson(reader, NEUConfig.class); + } catch (Exception ignored) { + } + } + + ItemCustomizeManager.loadCustomization(new File(neuDir, "itemCustomization.json")); + StorageManager.getInstance().loadConfig(new File(neuDir, "storageItems.json")); + FairySouls.load(new File(neuDir, "collected_fairy_souls.json"), gson); + PetInfoOverlay.loadConfig(new File(neuDir, "petCache.json")); + SlotLocking.getInstance().loadConfig(new File(neuDir, "slotLocking.json")); + ItemPriceInformation.init(new File(neuDir, "auctionable_items.json"), gson); + + if (config == null) { + config = new NEUConfig(); + saveConfig(); + } + + MinecraftForge.EVENT_BUS.register(this); + MinecraftForge.EVENT_BUS.register(new NEUEventListener(this)); + MinecraftForge.EVENT_BUS.register(new RecipeGenerator(this)); + MinecraftForge.EVENT_BUS.register(CapeManager.getInstance()); + //MinecraftForge.EVENT_BUS.register(new SBGamemodes()); + MinecraftForge.EVENT_BUS.register(new EnchantingSolvers()); + MinecraftForge.EVENT_BUS.register(new CalendarOverlay()); + MinecraftForge.EVENT_BUS.register(SBInfo.getInstance()); + MinecraftForge.EVENT_BUS.register(CustomItemEffects.INSTANCE); + MinecraftForge.EVENT_BUS.register(new DungeonMap()); + MinecraftForge.EVENT_BUS.register(new SunTzu()); + MinecraftForge.EVENT_BUS.register(new MiningStuff()); + MinecraftForge.EVENT_BUS.register(new FairySouls()); + MinecraftForge.EVENT_BUS.register(new CrystalOverlay()); + MinecraftForge.EVENT_BUS.register(new ItemCooldowns()); + MinecraftForge.EVENT_BUS.register(new DwarvenMinesWaypoints()); + MinecraftForge.EVENT_BUS.register(new FuelBar()); + //MinecraftForge.EVENT_BUS.register(new FancyPortals()); + MinecraftForge.EVENT_BUS.register(XPInformation.getInstance()); + MinecraftForge.EVENT_BUS.register(OverlayManager.petInfoOverlay); + MinecraftForge.EVENT_BUS.register(OverlayManager.timersOverlay); + MinecraftForge.EVENT_BUS.register(new NullzeeSphere()); + MinecraftForge.EVENT_BUS.register(InventoryStorageSelector.getInstance()); + MinecraftForge.EVENT_BUS.register(SlotLocking.getInstance()); + MinecraftForge.EVENT_BUS.register(FishingHelper.getInstance()); + MinecraftForge.EVENT_BUS.register(new DwarvenMinesTextures()); + MinecraftForge.EVENT_BUS.register(CustomBiomes.INSTANCE); + + if (Minecraft.getMinecraft().getResourceManager() instanceof IReloadableResourceManager) { + IReloadableResourceManager manager = (IReloadableResourceManager) Minecraft.getMinecraft().getResourceManager(); + manager.registerReloadListener(CustomSkulls.getInstance()); + manager.registerReloadListener(NPCRetexturing.getInstance()); + manager.registerReloadListener(new ItemCustomizeManager.ReloadListener()); + manager.registerReloadListener(new CustomBlockSounds.ReloaderListener()); + } + + this.commands = new Commands(); + + BackgroundBlur.registerListener(); + + manager = new NEUManager(this, neuDir); + manager.loadItemInformation(); + overlay = new NEUOverlay(manager); + profileViewer = new ProfileViewer(manager); + + for (KeyBinding kb : manager.keybinds) { + ClientRegistry.registerKeyBinding(kb); + } + + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + File tmp = new File(neuDir, "tmp"); + if (tmp.exists()) { + for (File tmpFile : tmp.listFiles()) { + tmpFile.delete(); + } + tmp.delete(); + } + //saveConfig(); + })); + } + + public void saveConfig() { + try { + configFile.createNewFile(); + + try ( + BufferedWriter writer = new BufferedWriter(new OutputStreamWriter( + new FileOutputStream(configFile), + StandardCharsets.UTF_8 + )) + ) { + writer.write(gson.toJson(config)); + } + } catch (Exception ignored) { + } + + try { + ItemCustomizeManager.saveCustomization(new File(neuDir, "itemCustomization.json")); + } catch (Exception ignored) { + } + try { + StorageManager.getInstance().saveConfig(new File(neuDir, "storageItems.json")); + } catch (Exception ignored) { + } + try { + FairySouls.save(new File(neuDir, "collected_fairy_souls.json"), gson); + } catch (Exception ignored) { + } + try { + PetInfoOverlay.saveConfig(new File(neuDir, "petCache.json")); + } catch (Exception ignored) { + } + try { + SlotLocking.getInstance().saveConfig(new File(neuDir, "slotLocking.json")); + } catch (Exception ignored) { + } + } + + /** + * If the last chat messages was sent >200ms ago, sends the message. + * If the last chat message was sent <200 ago, will cache the message for #onTick to handle. + */ + public void sendChatMessage(String message) { + if (System.currentTimeMillis() - lastChatMessage > CHAT_MSG_COOLDOWN) { + secondLastChatMessage = lastChatMessage; + lastChatMessage = System.currentTimeMillis(); + Minecraft.getMinecraft().thePlayer.sendChatMessage(message); + currChatMessage = null; + } else { + currChatMessage = message; + } + } + + public void displayLinks(JsonObject update) { + String discord_link = update.get("discord_link").getAsString(); + String youtube_link = update.get("youtube_link").getAsString(); + String twitch_link = update.get("twitch_link").getAsString(); + String update_link = update.get("update_link").getAsString(); + String github_link = update.get("github_link").getAsString(); + String other_text = update.get("other_text").getAsString(); + String other_link = update.get("other_link").getAsString(); + + ChatComponentText other = null; + if (other_text.length() > 0) { + other = new ChatComponentText( + EnumChatFormatting.GRAY + "[" + EnumChatFormatting.BLUE + other_text + EnumChatFormatting.GRAY + "]"); + other.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, other_link)); + } + ChatComponentText links = new ChatComponentText(""); + ChatComponentText separator = new ChatComponentText( + EnumChatFormatting.GRAY + EnumChatFormatting.BOLD.toString() + EnumChatFormatting.STRIKETHROUGH + + (other == null ? "--" : "-")); + ChatComponentText discord = new ChatComponentText( + EnumChatFormatting.GRAY + "[" + EnumChatFormatting.BLUE + "Discord" + EnumChatFormatting.GRAY + "]"); + discord.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, discord_link)); + ChatComponentText youtube = new ChatComponentText( + EnumChatFormatting.GRAY + "[" + EnumChatFormatting.RED + "YouTube" + EnumChatFormatting.GRAY + "]"); + youtube.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, youtube_link)); + ChatComponentText twitch = new ChatComponentText( + EnumChatFormatting.GRAY + "[" + EnumChatFormatting.DARK_PURPLE + "Twitch" + EnumChatFormatting.GRAY + "]"); + twitch.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, twitch_link)); + ChatComponentText release = new ChatComponentText( + EnumChatFormatting.GRAY + "[" + EnumChatFormatting.GREEN + "Release" + EnumChatFormatting.GRAY + "]"); + release.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, update_link)); + ChatComponentText github = new ChatComponentText( + EnumChatFormatting.GRAY + "[" + EnumChatFormatting.DARK_PURPLE + "GitHub" + EnumChatFormatting.GRAY + "]"); + github.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, github_link)); + + links.appendSibling(separator); + links.appendSibling(discord); + links.appendSibling(separator); + links.appendSibling(youtube); + links.appendSibling(separator); + links.appendSibling(twitch); + links.appendSibling(separator); + links.appendSibling(release); + links.appendSibling(separator); + links.appendSibling(github); + links.appendSibling(separator); + if (other != null) { + links.appendSibling(other); + links.appendSibling(separator); + } + + Minecraft.getMinecraft().thePlayer.addChatMessage(links); + } + + @SubscribeEvent + public void onTick(TickEvent.ClientTickEvent event) { + if (event.phase != TickEvent.Phase.START) return; + if (Minecraft.getMinecraft().thePlayer == null) { + openGui = null; + currChatMessage = null; + return; + } + long currentTime = System.currentTimeMillis(); + + if (openGui != null) { + if (Minecraft.getMinecraft().thePlayer.openContainer != null) { + Minecraft.getMinecraft().thePlayer.closeScreen(); + } + Minecraft.getMinecraft().displayGuiScreen(openGui); + openGui = null; + lastOpenedGui = System.currentTimeMillis(); + } + if (currChatMessage != null && currentTime - lastChatMessage > CHAT_MSG_COOLDOWN) { + lastChatMessage = currentTime; + Minecraft.getMinecraft().thePlayer.sendChatMessage(currChatMessage); + currChatMessage = null; + } + } + + public boolean isOnSkyblock() { + if (!config.misc.onlyShowOnSkyblock) return true; + return hasSkyblockScoreboard(); + } + + private boolean hasSkyblockScoreboard; + + public boolean hasSkyblockScoreboard() { + return hasSkyblockScoreboard; + } + + public void updateSkyblockScoreboard() { + Minecraft mc = Minecraft.getMinecraft(); + + if (mc != null && mc.theWorld != null && mc.thePlayer != null) { + if (mc.isSingleplayer() || mc.thePlayer.getClientBrand() == null || + !mc.thePlayer.getClientBrand().toLowerCase().contains("hypixel")) { + hasSkyblockScoreboard = false; + return; + } + + Scoreboard scoreboard = mc.theWorld.getScoreboard(); + ScoreObjective sidebarObjective = scoreboard.getObjectiveInDisplaySlot(1); + if (sidebarObjective != null) { + String objectiveName = sidebarObjective.getDisplayName().replaceAll("(?i)\\u00A7.", ""); + for (String skyblock : SKYBLOCK_IN_ALL_LANGUAGES) { + if (objectiveName.startsWith(skyblock)) { + hasSkyblockScoreboard = true; + return; + } + } + } + + hasSkyblockScoreboard = false; + } + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java b/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java index 9351b2081b..c47e0844ac 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java @@ -3,8 +3,12 @@ import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.ItemPriceInformation; import io.github.moulberry.notenoughupdates.NEUManager; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.miscgui.GuiPriceGraph; +import io.github.moulberry.notenoughupdates.recipes.Ingredient; +import io.github.moulberry.notenoughupdates.recipes.NeuRecipe; import io.github.moulberry.notenoughupdates.util.Constants; import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; @@ -26,885 +30,920 @@ import java.util.*; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; public class APIManager { - - private NEUManager manager; - public final CustomAH customAH; - - private TreeMap auctionMap = new TreeMap<>(); - public HashMap> internalnameToAucIdMap = new HashMap<>(); - private HashSet playerBids = new HashSet<>(); - private HashSet playerBidsNotified = new HashSet<>(); - private HashSet playerBidsFinishedNotified = new HashSet<>(); - - private JsonObject lowestBins = null; - private JsonObject auctionPricesAvgLowestBinJson = null; - - private LinkedList pagesToDownload = null; - - private JsonObject bazaarJson = null; - private JsonObject auctionPricesJson = null; - private HashMap craftCost = new HashMap<>(); - - public TreeMap>> extrasToAucIdMap = new TreeMap<>(); - - private long lastAuctionUpdate = 0; - private long lastShortAuctionUpdate = 0; - private long lastCustomAHSearch = 0; - private long lastCleanup = 0; - private long lastAuctionAvgUpdate = 0; - private long lastBazaarUpdate = 0; - private long lastLowestBinUpdate = 0; - - private long lastApiUpdate = 0; - private long firstHypixelApiUpdate = 0; - - public int activeAuctions = 0; - public int uniqueItems = 0; - public int totalTags = 0; - public int internalnameTaggedAuctions = 0; - public int taggedAuctions = 0; - public int processMillis = 0; - - public APIManager(NEUManager manager) { - this.manager = manager; - customAH = new CustomAH(manager); - } - - public TreeMap getAuctionItems() { - return auctionMap; - } - - public HashSet getPlayerBids() { - return playerBids; - } - - public HashSet getAuctionsForInternalname(String internalname) { - return internalnameToAucIdMap.computeIfAbsent(internalname, k -> new HashSet<>()); - } - - public class Auction { - public String auctioneerUuid; - public long end; - public int starting_bid; - public int highest_bid_amount; - public int bid_count; - public boolean bin; - public String category; - public String rarity; - public int dungeonTier; - public String item_tag_str; - public NBTTagCompound item_tag = null; - private ItemStack stack; - - public int enchLevel = 0; //0 = clean, 1 = ench, 2 = ench/hpb - - public Auction(String auctioneerUuid, long end, int starting_bid, int highest_bid_amount, int bid_count, - boolean bin, String category, String rarity, int dungeonTier, String item_tag_str) { - this.auctioneerUuid = auctioneerUuid; - this.end = end; - this.starting_bid = starting_bid; - this.highest_bid_amount = highest_bid_amount; - this.bid_count = bid_count; - this.bin = bin; - this.category = category; - this.dungeonTier = dungeonTier; - this.rarity = rarity; - this.item_tag_str = item_tag_str; - } - - public ItemStack getStack() { - if(item_tag == null && item_tag_str != null) { - try { - item_tag = CompressedStreamTools.readCompressed( - new ByteArrayInputStream(Base64.getDecoder().decode(item_tag_str))); - item_tag_str = null; - } catch(IOException e) { - return null; - } - } - if(stack != null) { - return stack; - } else { - JsonObject item = manager.getJsonFromNBT(item_tag); - ItemStack stack = manager.jsonToStack(item, false); - - JsonObject itemDefault = manager.getItemInformation().get(item.get("internalname").getAsString()); - - if(stack != null && itemDefault != null) { - ItemStack stackDefault = manager.jsonToStack(itemDefault, true); - if(stack.isItemEqual(stackDefault)) { - //Item types are the same, compare lore - - String[] stackLore = manager.getLoreFromNBT(stack.getTagCompound()); - String[] defaultLore = manager.getLoreFromNBT(stackDefault.getTagCompound()); - - boolean loreMatches = stackLore != null && defaultLore != null && stackLore.length == defaultLore.length; - if(loreMatches) { - for(int i=0; i 60*1000) { - lastAuctionUpdate = currentTime; - updatePageTick(); - } - if(currentTime - lastShortAuctionUpdate > 10*1000) { - lastShortAuctionUpdate = currentTime; - updatePageTickShort(); - ahNotification(); - } - if(currentTime - lastCleanup > 60*1000) { - lastCleanup = currentTime; - cleanup(); - } - if(currentTime - lastCustomAHSearch > 60*1000) { - lastCustomAHSearch = currentTime; - if(Minecraft.getMinecraft().currentScreen instanceof CustomAHGui || customAH.isRenderOverAuctionView()) { - customAH.updateSearch(); - calculateStats(); - } - } - } - if(currentTime - lastAuctionAvgUpdate > 5*60*1000) { //5 minutes - lastAuctionAvgUpdate = currentTime - 4*60*1000; //Try again in 1 minute if updateAvgPrices doesn't succeed - updateAvgPrices(); - } - if(currentTime - lastBazaarUpdate > 5*60*1000) { //5 minutes - lastBazaarUpdate = currentTime; - updateBazaar(); - } - if(currentTime - lastLowestBinUpdate > 2*60*1000) { - lastLowestBinUpdate = currentTime; - updateLowestBin(); - } - } - - private String niceAucId(String aucId) { - if(aucId.length()!=32) return aucId; - - StringBuilder niceAucId = new StringBuilder(); - niceAucId.append(aucId, 0, 8); - niceAucId.append("-"); - niceAucId.append(aucId, 8, 12); - niceAucId.append("-"); - niceAucId.append(aucId, 12, 16); - niceAucId.append("-"); - niceAucId.append(aucId, 16, 20); - niceAucId.append("-"); - niceAucId.append(aucId, 20, 32); - return niceAucId.toString(); - } - - public Set getLowestBinKeySet() { - if(lowestBins == null) return new HashSet<>(); - HashSet keys = new HashSet<>(); - for(Map.Entry entry : lowestBins.entrySet()) { - keys.add(entry.getKey()); - } - return keys; - } - - public int getLowestBin(String internalname) { - if(lowestBins != null && lowestBins.has(internalname)) { - JsonElement e = lowestBins.get(internalname); - if(e.isJsonPrimitive() && e.getAsJsonPrimitive().isNumber()) { - return e.getAsInt(); - } - } - return -1; - } - - public void updateLowestBin() { - manager.hypixelApi.getMyApiGZIPAsync("lowestbin.json.gz", (jsonObject) -> { - if(lowestBins == null) { - lowestBins = new JsonObject(); - } - for(Map.Entry entry : jsonObject.entrySet()) { - lowestBins.add(entry.getKey(), entry.getValue()); - } - }, () -> {}); - } - - private void ahNotification() { - playerBidsNotified.retainAll(playerBids); - playerBidsFinishedNotified.retainAll(playerBids); - if(NotEnoughUpdates.INSTANCE.config.neuAuctionHouse.ahNotification <= 0) { - return; - } - for(String aucid : playerBids) { - Auction auc = auctionMap.get(aucid); - if(!playerBidsNotified.contains(aucid)) { - if(auc != null && auc.end - System.currentTimeMillis() < 1000*60*NotEnoughUpdates.INSTANCE.config.neuAuctionHouse.ahNotification) { - ChatComponentText message = new ChatComponentText( - EnumChatFormatting.YELLOW+"The " + auc.getStack().getDisplayName() + EnumChatFormatting.YELLOW + " you have bid on is ending soon! Click here to view."); - ChatStyle clickEvent = new ChatStyle().setChatClickEvent( - new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/viewauction " + niceAucId(aucid))); - clickEvent.setChatHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ChatComponentText(EnumChatFormatting.YELLOW+"View auction"))); - message.setChatStyle(clickEvent); - Minecraft.getMinecraft().thePlayer.addChatMessage(message); - - playerBidsNotified.add(aucid); - } - } - if(!playerBidsFinishedNotified.contains(aucid)) { - if(auc != null && auc.end < System.currentTimeMillis()) { - ChatComponentText message = new ChatComponentText( - EnumChatFormatting.YELLOW+"The " + auc.getStack().getDisplayName() + EnumChatFormatting.YELLOW + " you have bid on (might) have ended! Click here to view."); - ChatStyle clickEvent = new ChatStyle().setChatClickEvent( - new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/viewauction " + niceAucId(aucid))); - clickEvent.setChatHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ChatComponentText(EnumChatFormatting.YELLOW+"View auction"))); - message.setChatStyle(clickEvent); - Minecraft.getMinecraft().thePlayer.addChatMessage(message); - - playerBidsFinishedNotified.add(aucid); - } - } - } - } - - private ExecutorService es = Executors.newSingleThreadExecutor(); - private void cleanup() { - es.submit(() -> { - try { - long currTime = System.currentTimeMillis(); - Set toRemove = new HashSet<>(); - for(Map.Entry entry : auctionMap.entrySet()) { - long timeToEnd = entry.getValue().end - currTime; - if(timeToEnd < -120*1000) { //2 minutes - toRemove.add(entry.getKey()); - } - } - toRemove.removeAll(playerBids); - remove(toRemove); - } catch(ConcurrentModificationException e) { - lastCleanup = System.currentTimeMillis() - 110*1000; - } - }); - } - - private void remove(Set toRemove) { - for(String aucid : toRemove) { - auctionMap.remove(aucid); - } - for(HashMap> extrasMap : extrasToAucIdMap.values()) { - for(HashSet aucids : extrasMap.values()) { - for(String aucid : toRemove) { - aucids.remove(aucid); - } - } - } - for(HashSet aucids : internalnameToAucIdMap.values()) { - aucids.removeAll(toRemove); - } - } - - private void updatePageTickShort() { - if(pagesToDownload == null || pagesToDownload.isEmpty()) return; - - if(firstHypixelApiUpdate == 0 || (System.currentTimeMillis() - firstHypixelApiUpdate)%(60*1000) > 15*1000) return; - - JsonObject disable = Constants.DISABLE; - if(disable != null && disable.has("auctions_new") && disable.get("auctions_new").getAsBoolean()) return; - - while(!pagesToDownload.isEmpty()) { - try { - int page = pagesToDownload.pop(); - getPageFromAPI(page); - } catch(NoSuchElementException ignored) {} //Weird race condition? - } - } - - private void updatePageTick() { - JsonObject disable = Constants.DISABLE; - if(disable != null && disable.has("auctions_new") && disable.get("auctions_new").getAsBoolean()) return; - - if(pagesToDownload == null) { - getPageFromAPI(0); - } - - Consumer process = jsonObject -> { - if(jsonObject.get("success").getAsBoolean()) { - JsonArray new_auctions = jsonObject.get("new_auctions").getAsJsonArray(); - for(JsonElement auctionElement : new_auctions) { - JsonObject auction = auctionElement.getAsJsonObject(); - //System.out.println("New auction " + auction); - processAuction(auction); - } - JsonArray new_bids = jsonObject.get("new_bids").getAsJsonArray(); - for(JsonElement newBidElement : new_bids) { - JsonObject newBid = newBidElement.getAsJsonObject(); - String newBidUUID = newBid.get("uuid").getAsString(); - //System.out.println("new bid" + newBidUUID); - int newBidAmount = newBid.get("highest_bid_amount").getAsInt(); - int end = newBid.get("end").getAsInt(); - int bid_count = newBid.get("bid_count").getAsInt(); - - Auction auc = auctionMap.get(newBidUUID); - if(auc != null) { - //System.out.println("Setting auction " + newBidUUID + " price to " + newBidAmount); - auc.highest_bid_amount = newBidAmount; - auc.end = end; - auc.bid_count = bid_count; - } - } - Set toRemove = new HashSet<>(); - JsonArray removed_auctions = jsonObject.get("removed_auctions").getAsJsonArray(); - for(JsonElement removedAuctionsElement : removed_auctions) { - String removed = removedAuctionsElement.getAsString(); - toRemove.add(removed); - } - remove(toRemove); - } - }; - - manager.hypixelApi.getMyApiGZIPAsync("auctionLast.json.gz", process, () -> { - System.out.println("Error downloading auction from Moulberry's jank API. :("); - }); - - manager.hypixelApi.getMyApiGZIPAsync("auction.json.gz", jsonObject -> { - if(jsonObject.get("success").getAsBoolean()) { - long apiUpdate = (long) jsonObject.get("time").getAsFloat(); - if (lastApiUpdate == apiUpdate) { - lastAuctionUpdate -= 30 * 1000; - } - lastApiUpdate = apiUpdate; - - process.accept(jsonObject); - } - }, () -> { - System.out.println("Error downloading auction from Moulberry's jank API. :("); - }); - - } - - public void calculateStats() { - try { - uniqueItems = internalnameToAucIdMap.size(); - Set aucs = new HashSet<>(); - for(HashSet aucids : internalnameToAucIdMap.values()) { - aucs.addAll(aucids); - } - internalnameTaggedAuctions = aucs.size(); - totalTags = extrasToAucIdMap.size(); - aucs = new HashSet<>(); - for(HashMap> extrasMap : extrasToAucIdMap.values()) { - for(HashSet aucids : extrasMap.values()) { - aucs.addAll(aucids); - } - } - taggedAuctions = aucs.size(); - } catch(Exception e) {} - } - -// String[] rarityArr = new String[] { -// "COMMON", "UNCOMMON", "RARE", "EPIC", "LEGENDARY", "MYTHIC", "SPECIAL", "VERY SPECIAL", "SUPREME", -// }; - - public int checkItemType(String lore, boolean contains, String... typeMatches) { - String[] split = lore.split("\n"); - for(int i=split.length-1; i>=0; i--) { - String line = split[i]; - for(String rarity : Utils.rarityArr) { - for(int j=0; j= 1 && enchantlevel <= 20) { - enchantLevelStr = romans[enchantlevel-1]; - } else { - enchantLevelStr = String.valueOf(enchantlevel); - } - extras = extras.replace(enchantname, enchantname + " " + enchantLevelStr); - } - } - } - - int index=0; - for(String str : extras.split(" ")) { - str = Utils.cleanColour(str).toLowerCase(); - if(str.length() > 0) { - HashMap> extrasMap = extrasToAucIdMap.computeIfAbsent(str, k -> new HashMap<>()); - HashSet aucids = extrasMap.computeIfAbsent(index, k -> new HashSet<>()); - aucids.add(auctionUuid); - } - index++; - } - - for(int j=0; j= 0) { - dungeonTier = 0; - for(int i=0; i= 0 && itemType < categoryItemType.length) { - category = categoryItemType[itemType]; - } - if(category.equals("consumables") && extras.contains("enchanted book")) category = "ebook"; - if(category.equals("consumables") && extras.endsWith("potion")) category = "potion"; - if(category.equals("misc") && extras.contains("rune")) category = "rune"; - if(category.equals("misc") && item_lore.split("\n")[0].endsWith("Furniture")) category = "furniture"; - if(item_lore.split("\n")[0].endsWith("Pet") || - item_lore.split("\n")[0].endsWith("Mount")) category = "pet"; - - Auction auction1 = new Auction(auctioneerUuid, end, starting_bid, highest_bid_amount, - bid_count, bin, category, rarity, dungeonTier, item_bytes); - - if(tag.hasKey("ench")) { - auction1.enchLevel = 1; - if(tag.hasKey("ExtraAttributes", 10)) { - NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes"); - - int hotpotatocount = ea.getInteger("hot_potato_count"); - if(hotpotatocount == 10) { - auction1.enchLevel = 2; - } - } - } - - auctionMap.put(auctionUuid, auction1); - internalnameToAucIdMap.computeIfAbsent(internalname, k -> new HashSet<>()).add(auctionUuid); - } catch(Exception e) {e.printStackTrace();} - } - - private void getPageFromAPI(int page) { - //System.out.println("downloading page:"+page); - //System.out.println("Trying to update page: " + page); - HashMap args = new HashMap<>(); - args.put("page", ""+page); - manager.hypixelApi.getHypixelApiAsync(null, "skyblock/auctions", - args, jsonObject -> { - if(jsonObject == null) return; - - if (jsonObject.get("success").getAsBoolean()) { - if(pagesToDownload == null) { - int totalPages = jsonObject.get("totalPages").getAsInt(); - pagesToDownload = new LinkedList<>(); - for(int i=0; i { - pagesToDownload.addLast(page); - } - ); - } - - public void updateBazaar() { - manager.hypixelApi.getHypixelApiAsync(NotEnoughUpdates.INSTANCE.config.apiKey.apiKey, "skyblock/bazaar", new HashMap<>(), (jsonObject) -> { - if(!jsonObject.get("success").getAsBoolean()) return; - - craftCost.clear(); - bazaarJson = new JsonObject(); - JsonObject products = jsonObject.get("products").getAsJsonObject(); - for(Map.Entry entry : products.entrySet()) { - if(entry.getValue().isJsonObject()) { - JsonObject productInfo = new JsonObject(); - - JsonObject product = entry.getValue().getAsJsonObject(); - JsonObject quickStatus = product.get("quick_status").getAsJsonObject(); - productInfo.addProperty("avg_buy", quickStatus.get("buyPrice").getAsFloat()); - productInfo.addProperty("avg_sell", quickStatus.get("sellPrice").getAsFloat()); - - for(JsonElement element : product.get("sell_summary").getAsJsonArray()) { - if(element.isJsonObject()) { - JsonObject sellSummaryFirst = element.getAsJsonObject(); - productInfo.addProperty("curr_sell", sellSummaryFirst.get("pricePerUnit").getAsFloat()); - break; - } - } - - for(JsonElement element : product.get("buy_summary").getAsJsonArray()) { - if(element.isJsonObject()) { - JsonObject sellSummaryFirst = element.getAsJsonObject(); - productInfo.addProperty("curr_buy", sellSummaryFirst.get("pricePerUnit").getAsFloat()); - break; - } - } - - bazaarJson.add(entry.getKey().replace(":", "-"), productInfo); - } - } - }); - } - - public void updateAvgPrices() { - manager.hypixelApi.getMyApiGZIPAsync("auction_averages/3day.json.gz", (jsonObject) -> { - craftCost.clear(); - auctionPricesJson = jsonObject; - lastAuctionAvgUpdate = System.currentTimeMillis(); - }, () -> {}); - manager.hypixelApi.getMyApiGZIPAsync("auction_averages_lbin/1day.json.gz", (jsonObject) -> { - auctionPricesAvgLowestBinJson = jsonObject; - }, () -> {}); - } - - public Set getItemAuctionInfoKeySet() { - if(auctionPricesJson == null) return new HashSet<>(); - HashSet keys = new HashSet<>(); - for(Map.Entry entry : auctionPricesJson.entrySet()) { - keys.add(entry.getKey()); - } - return keys; - } - - public JsonObject getItemAuctionInfo(String internalname) { - if(auctionPricesJson == null) return null; - JsonElement e = auctionPricesJson.get(internalname); - if(e == null) { - return null; - } - return e.getAsJsonObject(); - } - - public float getItemAvgBin(String internalname) { - if(auctionPricesAvgLowestBinJson == null) return -1; - JsonElement e = auctionPricesAvgLowestBinJson.get(internalname); - if(e == null) { - return -1; - } - return Math.round(e.getAsFloat()); - } - - public Set getBazaarKeySet() { - if(bazaarJson == null) return new HashSet<>(); - HashSet keys = new HashSet<>(); - for(Map.Entry entry : bazaarJson.entrySet()) { - keys.add(entry.getKey()); - } - return keys; - } - - public JsonObject getBazaarInfo(String internalname) { - if(bazaarJson == null) return null; - JsonElement e = bazaarJson.get(internalname); - if(e == null) { - return null; - } - return e.getAsJsonObject(); - } - - private static final List hardcodedVanillaItems = Utils.createList( - "WOOD_AXE", "WOOD_HOE", "WOOD_PICKAXE","WOOD_SPADE", "WOOD_SWORD", - "GOLD_AXE", "GOLD_HOE", "GOLD_PICKAXE", "GOLD_SPADE", "GOLD_SWORD", - "ROOKIE_HOE" - ); - public boolean isVanillaItem(String internalname) { - if(hardcodedVanillaItems.contains(internalname)) return true; - - //Removes trailing numbers and underscores, eg. LEAVES_2-3 -> LEAVES - String vanillaName = internalname.split("-")[0]; - if(manager.getItemInformation().containsKey(vanillaName)) { - JsonObject json = manager.getItemInformation().get(vanillaName); - if(json != null && json.has("vanilla") && json.get("vanilla").getAsBoolean()) return true; - } - return Item.itemRegistry.getObject(new ResourceLocation(vanillaName)) != null; - } - - public class CraftInfo { - public boolean fromRecipe = false; - public boolean vanillaItem = false; - public float craftCost = -1; - } - - public CraftInfo getCraftCost(String internalname) { - return getCraftCost(internalname, 0); - } - - /** - * Recursively calculates the cost of crafting an item from raw materials. - */ - public CraftInfo getCraftCost(String internalname, int depth) { - if(craftCost.containsKey(internalname)) { - return craftCost.get(internalname); - } else { - CraftInfo ci = new CraftInfo(); - - ci.vanillaItem = isVanillaItem(internalname); - - JsonObject auctionInfo = getItemAuctionInfo(internalname); - float lowestBin = getLowestBin(internalname); - JsonObject bazaarInfo = getBazaarInfo(internalname); - - if(bazaarInfo != null && bazaarInfo.get("curr_buy") != null) { - float bazaarInstantBuyPrice = bazaarInfo.get("curr_buy").getAsFloat(); - ci.craftCost = bazaarInstantBuyPrice; - } - //Don't use auction prices for vanilla items cuz people like to transfer money, messing up the cost of vanilla items. - if(lowestBin > 0 && !ci.vanillaItem) { - if(ci.craftCost < 0 || lowestBin < ci.craftCost) { - ci.craftCost = lowestBin; - } - } else if(auctionInfo != null && !ci.vanillaItem) { - float auctionPrice = auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat(); - if(ci.craftCost < 0 || auctionPrice < ci.craftCost) { - ci.craftCost = auctionPrice; - } - } - - if(depth > 16) { - craftCost.put(internalname, ci); - return ci; - } - - JsonObject item = manager.getItemInformation().get(internalname); - if(item != null && item.has("recipe")) { - float craftPrice = 0; - JsonObject recipe = item.get("recipe").getAsJsonObject(); - - String[] x = {"1","2","3"}; - String[] y = {"A","B","C"}; - for(int i=0; i<9; i++) { - String name = y[i/3]+x[i%3]; - String itemS = recipe.get(name).getAsString(); - if(itemS == null || itemS.length() == 0) continue; - - int count = 1; - if(itemS.split(":").length == 2) { - count = Integer.parseInt(itemS.split(":")[1]); - itemS = itemS.split(":")[0]; - } - if(itemS.equals(internalname)) { //if item is used a crafting component in its own recipe, return - craftCost.put(internalname, ci); - return ci; - } - - float compCost = getCraftCost(itemS, depth+1).craftCost * count; - if(compCost < 0) { - //If it's a custom item without a cost, return - if(!getCraftCost(itemS).vanillaItem) { - craftCost.put(internalname, ci); - return ci; - } - } else { - craftPrice += compCost; - } - } - - if(ci.craftCost < 0 || craftPrice < ci.craftCost) { - ci.craftCost = craftPrice; - ci.fromRecipe = true; - } - } - craftCost.put(internalname, ci); - return ci; - } - } - - /** - * Calculates the cost of enchants + other price modifiers such as pet xp, midas price, etc. - */ - public float getCostOfEnchants(String internalname, NBTTagCompound tag) { - float costOfEnchants = 0; - if(true) return 0; - - JsonObject info = getItemAuctionInfo(internalname); - if(info == null || !info.has("price")) { - return 0; - } - if(auctionPricesJson == null || !auctionPricesJson.has("ench_prices") || !auctionPricesJson.has("ench_maximums")) { - return 0; - } - JsonObject ench_prices = auctionPricesJson.getAsJsonObject("ench_prices"); - JsonObject ench_maximums = auctionPricesJson.getAsJsonObject("ench_maximums"); - if(!ench_prices.has(internalname) || !ench_maximums.has(internalname)) { - return 0; - } - JsonObject iid_variables = ench_prices.getAsJsonObject(internalname); - float ench_maximum = ench_maximums.get(internalname).getAsFloat(); - - int enchants = 0; - float price = getItemAuctionInfo(internalname).get("price").getAsFloat(); - if(tag.hasKey("ExtraAttributes")) { - NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes"); - if(ea.hasKey("enchantments")) { - - NBTTagCompound enchs = ea.getCompoundTag("enchantments"); - for(String ench : enchs.getKeySet()) { - enchants++; - int level = enchs.getInteger(ench); - - for(Map.Entry entry : iid_variables.entrySet()) { - if(matchEnch(ench, level, entry.getKey())) { - costOfEnchants += entry.getValue().getAsJsonObject().get("A").getAsFloat()*price + - entry.getValue().getAsJsonObject().get("B").getAsFloat(); - break; - } - } - } - } - } - return costOfEnchants; - } - - /** - * Checks whether a certain enchant (ench name + lvl) matches an enchant id - * eg. PROTECTION_GE6 will match -> ench_name = PROTECTION, lvl >= 6 - */ - private boolean matchEnch(String ench, int level, String id) { - if(!id.contains(":")) { - return false; - } - - String idEnch = id.split(":")[0]; - String idLevel = id.split(":")[1]; - - if(!ench.equalsIgnoreCase(idEnch)) { - return false; - } - - if(String.valueOf(level).equalsIgnoreCase(idLevel)) { - return true; - } - - if(idLevel.startsWith("LE")) { - int idLevelI = Integer.valueOf(idLevel.substring(2)); - return level <= idLevelI; - } else if(idLevel.startsWith("GE")) { - int idLevelI = Integer.valueOf(idLevel.substring(2)); - return level >= idLevelI; - } - - return false; - } + private final NEUManager manager; + public final CustomAH customAH; + + private final TreeMap auctionMap = new TreeMap<>(); + public HashMap> internalnameToAucIdMap = new HashMap<>(); + private final HashSet playerBids = new HashSet<>(); + private final HashSet playerBidsNotified = new HashSet<>(); + private final HashSet playerBidsFinishedNotified = new HashSet<>(); + + private JsonObject lowestBins = null; + private JsonObject auctionPricesAvgLowestBinJson = null; + + private LinkedList pagesToDownload = null; + + private JsonObject bazaarJson = null; + private JsonObject auctionPricesJson = null; + private final HashMap craftCost = new HashMap<>(); + + public TreeMap>> extrasToAucIdMap = new TreeMap<>(); + + private boolean didFirstUpdate = false; + private long lastAuctionUpdate = 0; + private long lastShortAuctionUpdate = 0; + private long lastCustomAHSearch = 0; + private long lastCleanup = 0; + private long lastAuctionAvgUpdate = 0; + private long lastBazaarUpdate = 0; + private long lastLowestBinUpdate = 0; + + private long lastApiUpdate = 0; + private long firstHypixelApiUpdate = 0; + + public int activeAuctions = 0; + public int uniqueItems = 0; + public int totalTags = 0; + public int internalnameTaggedAuctions = 0; + public int taggedAuctions = 0; + public int processMillis = 0; + + public APIManager(NEUManager manager) { + this.manager = manager; + customAH = new CustomAH(manager); + } + + public TreeMap getAuctionItems() { + return auctionMap; + } + + public HashSet getPlayerBids() { + return playerBids; + } + + public HashSet getAuctionsForInternalname(String internalname) { + return internalnameToAucIdMap.computeIfAbsent(internalname, k -> new HashSet<>()); + } + + public class Auction { + public String auctioneerUuid; + public long end; + public int starting_bid; + public int highest_bid_amount; + public int bid_count; + public boolean bin; + public String category; + public String rarity; + public int dungeonTier; + public String item_tag_str; + public NBTTagCompound item_tag = null; + private ItemStack stack; + + public int enchLevel = 0; //0 = clean, 1 = ench, 2 = ench/hpb + + public Auction( + String auctioneerUuid, long end, int starting_bid, int highest_bid_amount, int bid_count, + boolean bin, String category, String rarity, int dungeonTier, String item_tag_str + ) { + this.auctioneerUuid = auctioneerUuid; + this.end = end; + this.starting_bid = starting_bid; + this.highest_bid_amount = highest_bid_amount; + this.bid_count = bid_count; + this.bin = bin; + this.category = category; + this.dungeonTier = dungeonTier; + this.rarity = rarity; + this.item_tag_str = item_tag_str; + } + + public ItemStack getStack() { + if (item_tag == null && item_tag_str != null) { + try { + item_tag = CompressedStreamTools.readCompressed( + new ByteArrayInputStream(Base64.getDecoder().decode(item_tag_str))); + item_tag_str = null; + } catch (IOException e) { + return null; + } + } + if (stack != null) { + return stack; + } else { + JsonObject item = manager.getJsonFromNBT(item_tag); + ItemStack stack = manager.jsonToStack(item, false); + + JsonObject itemDefault = manager.getItemInformation().get(item.get("internalname").getAsString()); + + if (stack != null && itemDefault != null) { + ItemStack stackDefault = manager.jsonToStack(itemDefault, true); + if (stack.isItemEqual(stackDefault)) { + //Item types are the same, compare lore + + String[] stackLore = manager.getLoreFromNBT(stack.getTagCompound()); + String[] defaultLore = manager.getLoreFromNBT(stackDefault.getTagCompound()); + + boolean loreMatches = stackLore != null && defaultLore != null && stackLore.length == defaultLore.length; + if (loreMatches) { + for (int i = 0; i < stackLore.length; i++) { + if (!stackLore[i].equals(defaultLore[i])) { + loreMatches = false; + break; + } + } + } + if (loreMatches) { + stack = stackDefault; + } + } + } + this.stack = stack; + return stack; + } + } + } + + public void markNeedsUpdate() { + firstHypixelApiUpdate = 0; + pagesToDownload = null; + + auctionMap.clear(); + internalnameToAucIdMap.clear(); + extrasToAucIdMap.clear(); + } + + public void tick() { + customAH.tick(); + long currentTime = System.currentTimeMillis(); + if (NotEnoughUpdates.INSTANCE.config.neuAuctionHouse.enableNeuAuctionHouse && + NotEnoughUpdates.INSTANCE.config.apiKey.apiKey != null && + !NotEnoughUpdates.INSTANCE.config.apiKey.apiKey.isEmpty()) { + if (currentTime - lastAuctionUpdate > 60 * 1000) { + lastAuctionUpdate = currentTime; + updatePageTick(); + } + if (currentTime - lastShortAuctionUpdate > 10 * 1000) { + lastShortAuctionUpdate = currentTime; + updatePageTickShort(); + ahNotification(); + } + if (currentTime - lastCleanup > 60 * 1000) { + lastCleanup = currentTime; + cleanup(); + } + if (currentTime - lastCustomAHSearch > 60 * 1000) { + lastCustomAHSearch = currentTime; + if (Minecraft.getMinecraft().currentScreen instanceof CustomAHGui || customAH.isRenderOverAuctionView()) { + customAH.updateSearch(); + calculateStats(); + } + } + } + if (currentTime - lastAuctionAvgUpdate > 5 * 60 * 1000) { //5 minutes + lastAuctionAvgUpdate = currentTime - 4 * 60 * 1000; //Try again in 1 minute if updateAvgPrices doesn't succeed + updateAvgPrices(); + } + if (currentTime - lastBazaarUpdate > 5 * 60 * 1000) { //5 minutes + lastBazaarUpdate = currentTime; + updateBazaar(); + } + if (currentTime - lastLowestBinUpdate > 2 * 60 * 1000) { + updateLowestBin(); + } + } + + private String niceAucId(String aucId) { + if (aucId.length() != 32) return aucId; + + StringBuilder niceAucId = new StringBuilder(); + niceAucId.append(aucId, 0, 8); + niceAucId.append("-"); + niceAucId.append(aucId, 8, 12); + niceAucId.append("-"); + niceAucId.append(aucId, 12, 16); + niceAucId.append("-"); + niceAucId.append(aucId, 16, 20); + niceAucId.append("-"); + niceAucId.append(aucId, 20, 32); + return niceAucId.toString(); + } + + public Set getLowestBinKeySet() { + if (lowestBins == null) return new HashSet<>(); + HashSet keys = new HashSet<>(); + for (Map.Entry entry : lowestBins.entrySet()) { + keys.add(entry.getKey()); + } + return keys; + } + + public int getLowestBin(String internalname) { + if (lowestBins != null && lowestBins.has(internalname)) { + JsonElement e = lowestBins.get(internalname); + if (e.isJsonPrimitive() && e.getAsJsonPrimitive().isNumber()) { + return e.getAsInt(); + } + } + return -1; + } + + public void updateLowestBin() { + manager.hypixelApi.getMyApiGZIPAsync("lowestbin.json.gz", (jsonObject) -> { + if (lowestBins == null) { + lowestBins = new JsonObject(); + } + if (!jsonObject.entrySet().isEmpty()) { + lastLowestBinUpdate = System.currentTimeMillis(); + } + for (Map.Entry entry : jsonObject.entrySet()) { + lowestBins.add(entry.getKey(), entry.getValue()); + } + if (!didFirstUpdate) { + ItemPriceInformation.updateAuctionableItemsList(); + didFirstUpdate = true; + } + GuiPriceGraph.addToCache(lowestBins, false); + }, () -> { + }); + } + + private void ahNotification() { + playerBidsNotified.retainAll(playerBids); + playerBidsFinishedNotified.retainAll(playerBids); + if (NotEnoughUpdates.INSTANCE.config.neuAuctionHouse.ahNotification <= 0) { + return; + } + for (String aucid : playerBids) { + Auction auc = auctionMap.get(aucid); + if (!playerBidsNotified.contains(aucid)) { + if (auc != null && + auc.end - System.currentTimeMillis() < + 1000 * 60 * NotEnoughUpdates.INSTANCE.config.neuAuctionHouse.ahNotification) { + ChatComponentText message = new ChatComponentText( + EnumChatFormatting.YELLOW + + "The " + + auc.getStack().getDisplayName() + + EnumChatFormatting.YELLOW + + " you have bid on is ending soon! Click here to view."); + ChatStyle clickEvent = new ChatStyle().setChatClickEvent( + new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/viewauction " + niceAucId(aucid))); + clickEvent.setChatHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ChatComponentText( + EnumChatFormatting.YELLOW + + "View auction"))); + message.setChatStyle(clickEvent); + Minecraft.getMinecraft().thePlayer.addChatMessage(message); + + playerBidsNotified.add(aucid); + } + } + if (!playerBidsFinishedNotified.contains(aucid)) { + if (auc != null && auc.end < System.currentTimeMillis()) { + ChatComponentText message = new ChatComponentText( + EnumChatFormatting.YELLOW + + "The " + + auc.getStack().getDisplayName() + + EnumChatFormatting.YELLOW + + " you have bid on (might) have ended! Click here to view."); + ChatStyle clickEvent = new ChatStyle().setChatClickEvent( + new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/viewauction " + niceAucId(aucid))); + clickEvent.setChatHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ChatComponentText( + EnumChatFormatting.YELLOW + + "View auction"))); + message.setChatStyle(clickEvent); + Minecraft.getMinecraft().thePlayer.addChatMessage(message); + + playerBidsFinishedNotified.add(aucid); + } + } + } + } + + public long getLastLowestBinUpdateTime() { + return lastLowestBinUpdate; + } + + private final ExecutorService es = Executors.newSingleThreadExecutor(); + + private void cleanup() { + es.submit(() -> { + try { + long currTime = System.currentTimeMillis(); + Set toRemove = new HashSet<>(); + for (Map.Entry entry : auctionMap.entrySet()) { + long timeToEnd = entry.getValue().end - currTime; + if (timeToEnd < -120 * 1000) { //2 minutes + toRemove.add(entry.getKey()); + } + } + toRemove.removeAll(playerBids); + remove(toRemove); + } catch (ConcurrentModificationException e) { + lastCleanup = System.currentTimeMillis() - 110 * 1000; + } + }); + } + + private void remove(Set toRemove) { + for (String aucid : toRemove) { + auctionMap.remove(aucid); + } + for (HashMap> extrasMap : extrasToAucIdMap.values()) { + for (HashSet aucids : extrasMap.values()) { + for (String aucid : toRemove) { + aucids.remove(aucid); + } + } + } + for (HashSet aucids : internalnameToAucIdMap.values()) { + aucids.removeAll(toRemove); + } + } + + private void updatePageTickShort() { + if (pagesToDownload == null || pagesToDownload.isEmpty()) return; + + if (firstHypixelApiUpdate == 0 || (System.currentTimeMillis() - firstHypixelApiUpdate) % (60 * 1000) > 15 * 1000) + return; + + JsonObject disable = Constants.DISABLE; + if (disable != null && disable.has("auctions_new") && disable.get("auctions_new").getAsBoolean()) return; + + while (!pagesToDownload.isEmpty()) { + try { + int page = pagesToDownload.pop(); + getPageFromAPI(page); + } catch (NoSuchElementException ignored) { + } //Weird race condition? + } + } + + private void updatePageTick() { + JsonObject disable = Constants.DISABLE; + if (disable != null && disable.has("auctions_new") && disable.get("auctions_new").getAsBoolean()) return; + + if (pagesToDownload == null) { + getPageFromAPI(0); + } + + Consumer process = jsonObject -> { + if (jsonObject.get("success").getAsBoolean()) { + JsonArray new_auctions = jsonObject.get("new_auctions").getAsJsonArray(); + for (JsonElement auctionElement : new_auctions) { + JsonObject auction = auctionElement.getAsJsonObject(); + //System.out.println("New auction " + auction); + processAuction(auction); + } + JsonArray new_bids = jsonObject.get("new_bids").getAsJsonArray(); + for (JsonElement newBidElement : new_bids) { + JsonObject newBid = newBidElement.getAsJsonObject(); + String newBidUUID = newBid.get("uuid").getAsString(); + //System.out.println("new bid" + newBidUUID); + int newBidAmount = newBid.get("highest_bid_amount").getAsInt(); + int end = newBid.get("end").getAsInt(); + int bid_count = newBid.get("bid_count").getAsInt(); + + Auction auc = auctionMap.get(newBidUUID); + if (auc != null) { + //System.out.println("Setting auction " + newBidUUID + " price to " + newBidAmount); + auc.highest_bid_amount = newBidAmount; + auc.end = end; + auc.bid_count = bid_count; + } + } + Set toRemove = new HashSet<>(); + JsonArray removed_auctions = jsonObject.get("removed_auctions").getAsJsonArray(); + for (JsonElement removedAuctionsElement : removed_auctions) { + String removed = removedAuctionsElement.getAsString(); + toRemove.add(removed); + } + remove(toRemove); + } + }; + + manager.hypixelApi.getMyApiGZIPAsync("auctionLast.json.gz", process, () -> + System.out.println("Error downloading auction from Moulberry's jank API. :(")); + + manager.hypixelApi.getMyApiGZIPAsync("auction.json.gz", jsonObject -> { + if (jsonObject.get("success").getAsBoolean()) { + long apiUpdate = (long) jsonObject.get("time").getAsFloat(); + if (lastApiUpdate == apiUpdate) { + lastAuctionUpdate -= 30 * 1000; + } + lastApiUpdate = apiUpdate; + + process.accept(jsonObject); + } + }, () -> System.out.println("Error downloading auction from Moulberry's jank API. :(")); + + } + + public void calculateStats() { + try { + uniqueItems = internalnameToAucIdMap.size(); + Set aucs = new HashSet<>(); + for (HashSet aucids : internalnameToAucIdMap.values()) { + aucs.addAll(aucids); + } + internalnameTaggedAuctions = aucs.size(); + totalTags = extrasToAucIdMap.size(); + aucs = new HashSet<>(); + for (HashMap> extrasMap : extrasToAucIdMap.values()) { + for (HashSet aucids : extrasMap.values()) { + aucs.addAll(aucids); + } + } + taggedAuctions = aucs.size(); + } catch (Exception ignored) { + } + } + + //String[] rarityArr = new String[] { + // "COMMON", "UNCOMMON", "RARE", "EPIC", "LEGENDARY", "MYTHIC", "SPECIAL", "VERY SPECIAL", "SUPREME", + //}; + + public int checkItemType(String lore, boolean contains, String... typeMatches) { + String[] split = lore.split("\n"); + for (int i = split.length - 1; i >= 0; i--) { + String line = split[i]; + for (String rarity : Utils.rarityArr) { + for (int j = 0; j < typeMatches.length; j++) { + if (contains) { + if (line.trim().contains(rarity + " " + typeMatches[j])) { + return j; + } else if (line.trim().contains(rarity + " DUNGEON " + typeMatches[j])) { + return j; + } + } else { + if (line.trim().endsWith(rarity + " " + typeMatches[j])) { + return j; + } else if (line.trim().endsWith(rarity + " DUNGEON " + typeMatches[j])) { + return j; + } + } + } + } + } + return -1; + } + + private final String[] romans = new String[]{ + "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI", + "XII", "XIII", "XIV", "XV", "XVI", "XVII", "XIX", "XX" + }; + + String[] categoryItemType = new String[]{ + "sword", "fishingrod", "pickaxe", "axe", + "shovel", "petitem", "travelscroll", "reforgestone", "bow" + }; + String playerUUID = null; + + private void processAuction(JsonObject auction) { + if (playerUUID == null) + playerUUID = Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replaceAll("-", ""); + + String auctionUuid = auction.get("uuid").getAsString(); + String auctioneerUuid = auction.get("auctioneer").getAsString(); + long end = auction.get("end").getAsLong(); + int starting_bid = auction.get("starting_bid").getAsInt(); + int highest_bid_amount = auction.get("highest_bid_amount").getAsInt(); + int bid_count = auction.get("bids").getAsJsonArray().size(); + boolean bin = false; + if (auction.has("bin")) { + bin = auction.get("bin").getAsBoolean(); + } + String sbCategory = auction.get("category").getAsString(); + String extras = auction.get("extra").getAsString().toLowerCase(); + String item_name = auction.get("item_name").getAsString(); + String item_lore = Utils.fixBrokenAPIColour(auction.get("item_lore").getAsString()); + String item_bytes = auction.get("item_bytes").getAsString(); + String rarity = auction.get("tier").getAsString(); + JsonArray bids = auction.get("bids").getAsJsonArray(); + + try { + NBTTagCompound item_tag; + try { + item_tag = CompressedStreamTools.readCompressed( + new ByteArrayInputStream(Base64.getDecoder().decode(item_bytes))); + } catch (IOException e) { + return; + } + + NBTTagCompound tag = item_tag.getTagList("i", 10).getCompoundTagAt(0).getCompoundTag("tag"); + String internalname = manager.getInternalnameFromNBT(tag); + + NBTTagCompound display = tag.getCompoundTag("display"); + if (display.hasKey("Lore", 9)) { + NBTTagList loreList = new NBTTagList(); + for (String line : item_lore.split("\n")) { + loreList.appendTag(new NBTTagString(line)); + } + display.setTag("Lore", loreList); + } + tag.setTag("display", display); + item_tag.getTagList("i", 10).getCompoundTagAt(0).setTag("tag", tag); + + if (tag.hasKey("ExtraAttributes", 10)) { + NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes"); + + if (ea.hasKey("enchantments", 10)) { + NBTTagCompound enchantments = ea.getCompoundTag("enchantments"); + for (String key : enchantments.getKeySet()) { + String enchantname = key.toLowerCase().replace("ultimate_", "").replace("_", " "); + int enchantlevel = enchantments.getInteger(key); + String enchantLevelStr; + if (enchantlevel >= 1 && enchantlevel <= 20) { + enchantLevelStr = romans[enchantlevel - 1]; + } else { + enchantLevelStr = String.valueOf(enchantlevel); + } + extras = extras.replace(enchantname, enchantname + " " + enchantLevelStr); + } + } + } + + int index = 0; + for (String str : extras.split(" ")) { + str = Utils.cleanColour(str).toLowerCase(); + if (str.length() > 0) { + HashMap> extrasMap = extrasToAucIdMap.computeIfAbsent(str, k -> new HashMap<>()); + HashSet aucids = extrasMap.computeIfAbsent(index, k -> new HashSet<>()); + aucids.add(auctionUuid); + } + index++; + } + + for (int j = 0; j < bids.size(); j++) { + JsonObject bid = bids.get(j).getAsJsonObject(); + if (bid.get("bidder").getAsString().equalsIgnoreCase(playerUUID)) { + playerBids.add(auctionUuid); + } + } + + int dungeonTier = -1; + if (checkItemType(item_lore, true, "DUNGEON") >= 0) { + dungeonTier = 0; + for (int i = 0; i < item_name.length(); i++) { + char c = item_name.charAt(i); + if (c == 0x272A) { + dungeonTier++; + } + } + } + + //Categories + String category = sbCategory; + int itemType = checkItemType(item_lore, true, "SWORD", "FISHING ROD", "PICKAXE", + "AXE", "SHOVEL", "PET ITEM", "TRAVEL SCROLL", "REFORGE STONE", "BOW" + ); + if (itemType >= 0 && itemType < categoryItemType.length) { + category = categoryItemType[itemType]; + } + if (category.equals("consumables") && extras.contains("enchanted book")) category = "ebook"; + if (category.equals("consumables") && extras.endsWith("potion")) category = "potion"; + if (category.equals("misc") && extras.contains("rune")) category = "rune"; + if (category.equals("misc") && item_lore.split("\n")[0].endsWith("Furniture")) category = "furniture"; + if (item_lore.split("\n")[0].endsWith("Pet") || + item_lore.split("\n")[0].endsWith("Mount")) category = "pet"; + + Auction auction1 = new Auction(auctioneerUuid, end, starting_bid, highest_bid_amount, + bid_count, bin, category, rarity, dungeonTier, item_bytes + ); + + if (tag.hasKey("ench")) { + auction1.enchLevel = 1; + if (tag.hasKey("ExtraAttributes", 10)) { + NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes"); + + int hotpotatocount = ea.getInteger("hot_potato_count"); + if (hotpotatocount == 10) { + auction1.enchLevel = 2; + } + } + } + + auctionMap.put(auctionUuid, auction1); + internalnameToAucIdMap.computeIfAbsent(internalname, k -> new HashSet<>()).add(auctionUuid); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void getPageFromAPI(int page) { + //System.out.println("downloading page:"+page); + //System.out.println("Trying to update page: " + page); + HashMap args = new HashMap<>(); + args.put("page", "" + page); + manager.hypixelApi.getHypixelApiAsync(null, "skyblock/auctions", + args, jsonObject -> { + if (jsonObject == null) return; + + if (jsonObject.get("success").getAsBoolean()) { + if (pagesToDownload == null) { + int totalPages = jsonObject.get("totalPages").getAsInt(); + pagesToDownload = new LinkedList<>(); + for (int i = 0; i < totalPages + 2; i++) { + pagesToDownload.add(i); + } + } + if (firstHypixelApiUpdate == 0) { + firstHypixelApiUpdate = jsonObject.get("lastUpdated").getAsLong(); + } + activeAuctions = jsonObject.get("totalAuctions").getAsInt(); + + long startProcess = System.currentTimeMillis(); + JsonArray auctions = jsonObject.get("auctions").getAsJsonArray(); + for (int i = 0; i < auctions.size(); i++) { + JsonObject auction = auctions.get(i).getAsJsonObject(); + + processAuction(auction); + } + processMillis = (int) (System.currentTimeMillis() - startProcess); + } else { + pagesToDownload.addLast(page); + } + }, () -> pagesToDownload.addLast(page) + ); + } + + public void updateBazaar() { + manager.hypixelApi.getHypixelApiAsync( + NotEnoughUpdates.INSTANCE.config.apiKey.apiKey, + "skyblock/bazaar", + new HashMap<>(), + (jsonObject) -> { + if (!jsonObject.get("success").getAsBoolean()) return; + + craftCost.clear(); + bazaarJson = new JsonObject(); + JsonObject products = jsonObject.get("products").getAsJsonObject(); + for (Map.Entry entry : products.entrySet()) { + if (entry.getValue().isJsonObject()) { + JsonObject productInfo = new JsonObject(); + + JsonObject product = entry.getValue().getAsJsonObject(); + JsonObject quickStatus = product.get("quick_status").getAsJsonObject(); + productInfo.addProperty("avg_buy", quickStatus.get("buyPrice").getAsFloat()); + productInfo.addProperty("avg_sell", quickStatus.get("sellPrice").getAsFloat()); + + for (JsonElement element : product.get("sell_summary").getAsJsonArray()) { + if (element.isJsonObject()) { + JsonObject sellSummaryFirst = element.getAsJsonObject(); + productInfo.addProperty("curr_sell", sellSummaryFirst.get("pricePerUnit").getAsFloat()); + break; + } + } + + for (JsonElement element : product.get("buy_summary").getAsJsonArray()) { + if (element.isJsonObject()) { + JsonObject sellSummaryFirst = element.getAsJsonObject(); + productInfo.addProperty("curr_buy", sellSummaryFirst.get("pricePerUnit").getAsFloat()); + break; + } + } + + bazaarJson.add(entry.getKey().replace(":", "-"), productInfo); + } + } + GuiPriceGraph.addToCache(bazaarJson, true); + } + ); + } + + public void updateAvgPrices() { + manager.hypixelApi.getMyApiGZIPAsync("auction_averages/3day.json.gz", (jsonObject) -> { + craftCost.clear(); + auctionPricesJson = jsonObject; + lastAuctionAvgUpdate = System.currentTimeMillis(); + }, () -> { + }); + manager.hypixelApi.getMyApiGZIPAsync("auction_averages_lbin/1day.json.gz", (jsonObject) -> + auctionPricesAvgLowestBinJson = jsonObject, () -> { + }); + } + + public Set getItemAuctionInfoKeySet() { + if (auctionPricesJson == null) return new HashSet<>(); + HashSet keys = new HashSet<>(); + for (Map.Entry entry : auctionPricesJson.entrySet()) { + keys.add(entry.getKey()); + } + return keys; + } + + public JsonObject getItemAuctionInfo(String internalname) { + if (auctionPricesJson == null) return null; + JsonElement e = auctionPricesJson.get(internalname); + if (e == null) { + return null; + } + return e.getAsJsonObject(); + } + + public float getItemAvgBin(String internalname) { + if (auctionPricesAvgLowestBinJson == null) return -1; + JsonElement e = auctionPricesAvgLowestBinJson.get(internalname); + if (e == null) { + return -1; + } + return Math.round(e.getAsFloat()); + } + + public Set getBazaarKeySet() { + if (bazaarJson == null) return new HashSet<>(); + HashSet keys = new HashSet<>(); + for (Map.Entry entry : bazaarJson.entrySet()) { + keys.add(entry.getKey()); + } + return keys; + } + + public JsonObject getBazaarInfo(String internalname) { + if (bazaarJson == null) return null; + JsonElement e = bazaarJson.get(internalname); + if (e == null) { + return null; + } + return e.getAsJsonObject(); + } + + private static final List hardcodedVanillaItems = Utils.createList( + "WOOD_AXE", "WOOD_HOE", "WOOD_PICKAXE", "WOOD_SPADE", "WOOD_SWORD", + "GOLD_AXE", "GOLD_HOE", "GOLD_PICKAXE", "GOLD_SPADE", "GOLD_SWORD", + "ROOKIE_HOE" + ); + + public boolean isVanillaItem(String internalname) { + if (hardcodedVanillaItems.contains(internalname)) return true; + + //Removes trailing numbers and underscores, eg. LEAVES_2-3 -> LEAVES + String vanillaName = internalname.split("-")[0]; + if (manager.getItemInformation().containsKey(vanillaName)) { + JsonObject json = manager.getItemInformation().get(vanillaName); + if (json != null && json.has("vanilla") && json.get("vanilla").getAsBoolean()) return true; + } + return Item.itemRegistry.getObject(new ResourceLocation(vanillaName)) != null; + } + + public static class CraftInfo { + public boolean fromRecipe = false; + public boolean vanillaItem = false; + public float craftCost = -1; + } + + public CraftInfo getCraftCost(String internalname) { + return getCraftCost(internalname, new HashSet<>()); + } + + /** + * Recursively calculates the cost of crafting an item from raw materials. + */ + private CraftInfo getCraftCost(String internalname, Set visited) { + if (craftCost.containsKey(internalname)) return craftCost.get(internalname); + if (visited.contains(internalname)) return null; + visited.add(internalname); + + boolean vanillaItem = isVanillaItem(internalname); + float craftCost = Float.POSITIVE_INFINITY; + + JsonObject auctionInfo = getItemAuctionInfo(internalname); + float lowestBin = getLowestBin(internalname); + JsonObject bazaarInfo = getBazaarInfo(internalname); + + if (bazaarInfo != null && bazaarInfo.get("curr_buy") != null) { + craftCost = bazaarInfo.get("curr_buy").getAsFloat(); + } + //Don't use auction prices for vanilla items cuz people like to transfer money, messing up the cost of vanilla items. + if (!vanillaItem) { + if (lowestBin > 0) { + craftCost = Math.min(lowestBin, craftCost); + } else if (auctionInfo != null) { + float auctionPrice = auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsInt(); + craftCost = Math.min(auctionPrice, craftCost); + } + } + + Set recipes = manager.getRecipesFor(internalname); + boolean fromRecipe = false; + if (recipes != null) + RECIPE_ITER: + for (NeuRecipe recipe : recipes) { + if (recipe.hasVariableCost() || !recipe.shouldUseForCraftCost()) continue; + float craftPrice = 0; + for (Ingredient i : recipe.getIngredients()) { + if (i.isCoins()) { + craftPrice += i.getCount(); + continue; + } + CraftInfo ingredientCraftCost = getCraftCost(i.getInternalItemId(), visited); + if (ingredientCraftCost == null) + continue RECIPE_ITER; // Skip recipes with items further up the chain + craftPrice += ingredientCraftCost.craftCost * i.getCount(); + } + int resultCount = 0; + for (Ingredient item : recipe.getOutputs()) + if (item.getInternalItemId().equals(internalname)) + resultCount += item.getCount(); + + if (resultCount == 0) + continue; + float craftPricePer = craftPrice / resultCount; + if (craftPricePer < craftCost) { + fromRecipe = true; + craftCost = craftPricePer; + } + } + visited.remove(internalname); + if (Float.isInfinite(craftCost)) { + return null; + } + CraftInfo craftInfo = new CraftInfo(); + craftInfo.vanillaItem = vanillaItem; + craftInfo.craftCost = craftCost; + craftInfo.fromRecipe = fromRecipe; + this.craftCost.put(internalname, craftInfo); + return craftInfo; + } + + /** + * Calculates the cost of enchants + other price modifiers such as pet xp, midas price, etc. + */ + public float getCostOfEnchants(String internalname, NBTTagCompound tag) { + float costOfEnchants = 0; + if (true) return 0; + + JsonObject info = getItemAuctionInfo(internalname); + if (info == null || !info.has("price")) { + return 0; + } + if (auctionPricesJson == null || !auctionPricesJson.has("ench_prices") || !auctionPricesJson.has("ench_maximums")) { + return 0; + } + JsonObject ench_prices = auctionPricesJson.getAsJsonObject("ench_prices"); + JsonObject ench_maximums = auctionPricesJson.getAsJsonObject("ench_maximums"); + if (!ench_prices.has(internalname) || !ench_maximums.has(internalname)) { + return 0; + } + JsonObject iid_variables = ench_prices.getAsJsonObject(internalname); + float ench_maximum = ench_maximums.get(internalname).getAsFloat(); + + int enchants = 0; + float price = getItemAuctionInfo(internalname).get("price").getAsFloat(); + if (tag.hasKey("ExtraAttributes")) { + NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes"); + if (ea.hasKey("enchantments")) { + + NBTTagCompound enchs = ea.getCompoundTag("enchantments"); + for (String ench : enchs.getKeySet()) { + enchants++; + int level = enchs.getInteger(ench); + + for (Map.Entry entry : iid_variables.entrySet()) { + if (matchEnch(ench, level, entry.getKey())) { + costOfEnchants += entry.getValue().getAsJsonObject().get("A").getAsFloat() * price + + entry.getValue().getAsJsonObject().get("B").getAsFloat(); + break; + } + } + } + } + } + return costOfEnchants; + } + + /** + * Checks whether a certain enchant (ench name + lvl) matches an enchant id + * eg. PROTECTION_GE6 will match -> ench_name = PROTECTION, lvl >= 6 + */ + private boolean matchEnch(String ench, int level, String id) { + if (!id.contains(":")) { + return false; + } + + String idEnch = id.split(":")[0]; + String idLevel = id.split(":")[1]; + + if (!ench.equalsIgnoreCase(idEnch)) { + return false; + } + + if (String.valueOf(level).equalsIgnoreCase(idLevel)) { + return true; + } + + if (idLevel.startsWith("LE")) { + int idLevelI = Integer.parseInt(idLevel.substring(2)); + return level <= idLevelI; + } else if (idLevel.startsWith("GE")) { + int idLevelI = Integer.parseInt(idLevel.substring(2)); + return level >= idLevelI; + } + + return false; + } /*ScheduledExecutorService auctionUpdateSES = Executors.newSingleThreadScheduledExecutor(); private AtomicInteger auctionUpdateId = new AtomicInteger(0); @@ -989,5 +1028,4 @@ public void run() { } }, 3000L, TimeUnit.MILLISECONDS); }*/ - } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAH.java b/src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAH.java index 25d4d03b6d..123da60a93 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAH.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAH.java @@ -35,8 +35,8 @@ import java.awt.*; import java.awt.datatransfer.StringSelection; import java.text.NumberFormat; -import java.util.*; import java.util.List; +import java.util.*; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.regex.Matcher; @@ -45,861 +45,921 @@ import static io.github.moulberry.notenoughupdates.util.GuiTextures.*; public class CustomAH extends Gui { - - private enum PriceFilter { - Greater, - Less, - Equal - } - - private static final ResourceLocation creativeTabSearch = - new ResourceLocation("textures/gui/container/creative_inventory/tab_item_search.png"); - private static final ResourceLocation creativeInventoryTabs = - new ResourceLocation("textures/gui/container/creative_inventory/tabs.png"); - - private HashSet auctionIds = new HashSet<>(); - private List sortedAuctionIds = new ArrayList<>(); - - private boolean scrollClicked = false; - - private long lastUpdateSearch; - private long lastSearchFieldUpdate; - private boolean shouldUpdateSearch = false; - private boolean shouldSortItems = false; - - private int startingBid = 0; - private String currentAucId = null; - - private int clickedMainCategory = -1; - private int clickedSubCategory = -1; - - private GuiTextField searchField = null; - private GuiTextField priceField = null; - private GuiTextField priceFilterField = null; - private GuiTextField binPriceFilterField = null; - - private final int binPriceFilterYOffset = 86; - - private boolean renderOverAuctionView = false; - private long lastRenderDisable = 0; - - private long currAucIdSetTimer = 0; - private long resetCurrAucIdTimer = 0; - - private int eventButton; - private long lastMouseEvent; - public long lastOpen; - public long lastGuiScreenSwitch; - private PriceFilter currentPriceFilterType = PriceFilter.Greater; - private PriceFilter currentBinPriceFilterType = PriceFilter.Greater; - - private final int splits = 2; - - public String latestBid; - public long latestBidMillis; - - private final int ySplit = 35; - private final int ySplitSize = 18; - - private float scrollAmount; - - public int guiLeft = -1; - public int guiTop = -1; - - private Category CATEGORY_SWORD = new Category("sword", "Swords", "diamond_sword"); - private Category CATEGORY_ARMOR = new Category("armor", "Armor", "diamond_chestplate"); - private Category CATEGORY_BOWS = new Category("bow", "Bows", "bow"); - private Category CATEGORY_ACCESSORIES = new Category("accessories", "Accessories", "diamond"); - - private Category CATEGORY_FISHING_ROD = new Category("fishingrod", "Fishing Rods", "fishing_rod"); - private Category CATEGORY_PICKAXE = new Category("pickaxe", "Pickaxes", "iron_pickaxe"); - private Category CATEGORY_AXE = new Category("axe", "Axes", "iron_axe"); - private Category CATEGORY_SHOVEL = new Category("shovel", "Shovels", "iron_shovel"); - - private Category CATEGORY_PET_ITEM = new Category("petitem", "Pet Items", "lead"); - - private Category CATEGORY_EBOOKS = new Category("ebook", "Enchanted Books", "enchanted_book"); - private Category CATEGORY_POTIONS = new Category("potion", "Potions", "potion"); - private Category CATEGORY_TRAVEL_SCROLLS = new Category("travelscroll", "Travel Scrolls", "map"); - - private Category CATEGORY_REFORGE_STONES = new Category("reforgestone", "Reforge Stones", "anvil"); - private Category CATEGORY_RUNES = new Category("rune", "Runes", "magma_cream"); - private Category CATEGORY_FURNITURE = new Category("furniture", "Furniture", "armor_stand"); - - private Category CATEGORY_COMBAT = new Category("weapon", "Combat", "golden_sword", CATEGORY_SWORD, - CATEGORY_BOWS, CATEGORY_ARMOR, CATEGORY_ACCESSORIES); - private Category CATEGORY_TOOL = new Category("", "Tools", "diamond_pickaxe", CATEGORY_FISHING_ROD, CATEGORY_PICKAXE, - CATEGORY_AXE, CATEGORY_SHOVEL); - private Category CATEGORY_PET = new Category("pet", "Pets", "bone", CATEGORY_PET_ITEM); - private Category CATEGORY_CONSUMABLES = new Category("consumables", "Consumables", "apple", CATEGORY_EBOOKS, CATEGORY_POTIONS, - CATEGORY_TRAVEL_SCROLLS); - private Category CATEGORY_BLOCKS = new Category("blocks", "Blocks", "cobblestone"); - private Category CATEGORY_MISC = new Category("misc", "Misc", "stick", CATEGORY_REFORGE_STONES, CATEGORY_RUNES, - CATEGORY_FURNITURE); - - private Category[] mainCategories = new Category[]{CATEGORY_COMBAT, CATEGORY_TOOL, CATEGORY_PET, - CATEGORY_CONSUMABLES, CATEGORY_BLOCKS, CATEGORY_MISC}; - - private static final int SORT_MODE_HIGH = 0; - private static final int SORT_MODE_LOW = 1; - private static final int SORT_MODE_SOON = 2; - -// private static final String[] rarities = {"COMMON", "UNCOMMON", "RARE", "EPIC", -// "LEGENDARY", "MYTHIC", "SPECIAL", "VERY SPECIAL", "SUPREME"}; - private static final String[] rarityColours = {"" + EnumChatFormatting.WHITE, - "" + EnumChatFormatting.GREEN, "" + EnumChatFormatting.BLUE, "" + EnumChatFormatting.DARK_PURPLE, - "" + EnumChatFormatting.GOLD, "" + EnumChatFormatting.LIGHT_PURPLE, "" + EnumChatFormatting.RED, - "" + EnumChatFormatting.RED, "" + EnumChatFormatting.DARK_RED}; - - private static final int BIN_FILTER_ALL = 0; - private static final int BIN_FILTER_BIN = 1; - private static final int BIN_FILTER_AUC = 2; - - private static final int ENCH_FILTER_ALL = 0; - private static final int ENCH_FILTER_CLEAN = 1; - private static final int ENCH_FILTER_ENCH = 2; - private static final int ENCH_FILTER_ENCHHPB = 3; - - private static final int DUNGEON_FILTER_ALL = 0; - private static final int DUNGEON_FILTER_DUNGEON = 1; - private static final int DUNGEON_FILTER_1 = 2; - private static final int DUNGEON_FILTER_2 = 3; - private static final int DUNGEON_FILTER_3 = 4; - private static final int DUNGEON_FILTER_4 = 5; - private static final int DUNGEON_FILTER_5 = 6; - - private int dungeonFilter = DUNGEON_FILTER_ALL; - private int sortMode = SORT_MODE_HIGH; - private int rarityFilter = -1; - private boolean filterMyAuctions = false; - private int binFilter = BIN_FILTER_ALL; - private int enchFilter = ENCH_FILTER_ALL; - - private static ItemStack DUNGEON_SORT = Utils.createItemStack(Item.getItemFromBlock(Blocks.deadbush), - EnumChatFormatting.GREEN + "Dungeon Sorting"); - private static ItemStack CONTROL_SORT = Utils.createItemStack(Item.getItemFromBlock(Blocks.hopper), - EnumChatFormatting.GREEN + "Sort"); - private static ItemStack CONTROL_TIER = Utils.createItemStack(Items.ender_eye, - EnumChatFormatting.GREEN + "Item Tier"); - private static ItemStack CONTROL_MYAUC = Utils.createItemStack(Items.gold_ingot, - EnumChatFormatting.GREEN + "My Auctions"); - private static ItemStack CONTROL_BIN = Utils.createItemStack(Item.getItemFromBlock(Blocks.golden_rail), - EnumChatFormatting.GREEN + "BIN Filter"); - private static ItemStack CONTROL_ENCH = Utils.createItemStack(Items.enchanted_book, - EnumChatFormatting.GREEN + "Enchant Filter"); - private static ItemStack CONTROL_STATS = Utils.createItemStack(Item.getItemFromBlock(Blocks.command_block), - EnumChatFormatting.GREEN + "Stats for nerds"); - private ItemStack[] controls = {DUNGEON_SORT, CONTROL_SORT, CONTROL_TIER, null, CONTROL_MYAUC, null, CONTROL_BIN, CONTROL_ENCH, CONTROL_STATS}; - - private NEUManager manager; - - public CustomAH(NEUManager manager) { - this.manager = manager; - } - - public void clearSearch() { - if (searchField == null || priceField == null) init(); - if (System.currentTimeMillis() - lastOpen < 1000) Mouse.setGrabbed(false); - - //sortMode = SORT_MODE_HIGH; - rarityFilter = -1; - filterMyAuctions = false; - //binFilter = BIN_FILTER_ALL; - enchFilter = ENCH_FILTER_ALL; - dungeonFilter = DUNGEON_FILTER_ALL; - - searchField.setText(""); - searchField.setFocused(true); - priceField.setText(""); - } - - public void setSearch(String search) { - searchField.setText(search); - updateSearch(); - } - - public void tick() { - if (!NotEnoughUpdates.INSTANCE.config.neuAuctionHouse.enableNeuAuctionHouse) return; - if (Minecraft.getMinecraft().currentScreen instanceof CustomAHGui || renderOverAuctionView) { - if (shouldUpdateSearch) updateSearch(); - if (shouldSortItems) { - sortItems(); - shouldSortItems = false; - } - } - } - - public class Category { - public String categoryMatch; - public Category[] subcategories; - public String displayName; - public ItemStack displayItem; - - public Category(String categoryMatch, String displayName, String displayItem, Category... subcategories) { - this.categoryMatch = categoryMatch; - this.subcategories = subcategories; - this.displayName = displayName; - this.displayItem = new ItemStack(Item.getByNameOrId(displayItem)); - } - - public String[] getTotalCategories() { - String[] categories = new String[1 + subcategories.length]; - categories[0] = categoryMatch; - - for (int i = 0; i < subcategories.length; i++) { - categories[i + 1] = subcategories[i].categoryMatch; - } - return categories; - } - } - - private void init() { - FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; - this.searchField = new GuiTextField(0, fr, this.guiLeft + 82, this.guiTop + 6, - 84, fr.FONT_HEIGHT); - this.priceField = new GuiTextField(1, fr, this.guiLeft + 82, this.guiTop + 6, - 84, fr.FONT_HEIGHT); - this.priceFilterField = new GuiTextField(2, fr, this.guiLeft + 82, this.guiTop + 6, - 84, fr.FONT_HEIGHT); - this.binPriceFilterField = new GuiTextField(3, fr, this.guiLeft + 82, this.guiTop - 6, 84, fr.FONT_HEIGHT); - - this.searchField.setMaxStringLength(30); - this.searchField.setEnableBackgroundDrawing(false); - this.searchField.setTextColor(16777215); - this.searchField.setVisible(true); - this.searchField.setCanLoseFocus(true); - this.searchField.setFocused(true); - this.searchField.setText(""); - - this.priceField.setMaxStringLength(10); - this.priceField.setEnableBackgroundDrawing(false); - this.priceField.setTextColor(16777215); - this.priceField.setVisible(true); - this.priceField.setCanLoseFocus(true); - this.priceField.setFocused(false); - this.priceField.setText(""); - - this.priceFilterField.setMaxStringLength(10); - this.priceFilterField.setEnableBackgroundDrawing(false); - this.priceFilterField.setTextColor(16777215); - this.priceFilterField.setVisible(true); - this.priceFilterField.setCanLoseFocus(true); - this.priceFilterField.setFocused(false); - this.priceFilterField.setText(""); - - this.binPriceFilterField.setMaxStringLength(10); - this.binPriceFilterField.setEnableBackgroundDrawing(false); - this.binPriceFilterField.setTextColor(16777215); - this.binPriceFilterField.setVisible(true); - this.binPriceFilterField.setCanLoseFocus(true); - this.binPriceFilterField.setFocused(false); - this.binPriceFilterField.setText(""); - } - - public boolean isRenderOverAuctionView() { - return renderOverAuctionView || (System.currentTimeMillis() - lastRenderDisable) < 500; - } - - public void setRenderOverAuctionView(boolean renderOverAuctionView) { - if (this.renderOverAuctionView && !renderOverAuctionView) lastRenderDisable = System.currentTimeMillis(); - this.renderOverAuctionView = renderOverAuctionView; - } - - public int getXSize() { - return 195; - } - - public int getYSize() { - return 136 + ySplitSize * splits; - } - - private String prettyTime(long millis) { - long seconds = millis / 1000 % 60; - long minutes = (millis / 1000 / 60) % 60; - long hours = (millis / 1000 / 60 / 60) % 24; - long days = (millis / 1000 / 60 / 60 / 24); - - String endsIn = ""; - if (millis < 0) { - endsIn += "Ended!"; - } else if (minutes == 0 && hours == 0 && days == 0) { - endsIn += seconds + "s"; - } else if (hours == 0 && days == 0) { - endsIn += minutes + "m" + seconds + "s"; - } else if (days == 0) { - if (hours <= 6) { - endsIn += hours + "h" + minutes + "m" + seconds + "s"; - } else { - endsIn += hours + "h"; - } - } else { - endsIn += days + "d" + hours + "h"; - } - - return endsIn; - } - - public List getTooltipForAucId(String aucId) { - APIManager.Auction auc = manager.auctionManager.getAuctionItems().get(aucId); - - List tooltip = new ArrayList<>(); - - for (String line : auc.getStack().getTooltip(Minecraft.getMinecraft().thePlayer, false)) { - tooltip.add(EnumChatFormatting.GRAY + line); - } - - long timeUntilEnd = auc.end - System.currentTimeMillis(); - String endsIn = EnumChatFormatting.YELLOW + prettyTime(timeUntilEnd); - - NumberFormat format = NumberFormat.getInstance(Locale.US); - - tooltip.add(EnumChatFormatting.DARK_GRAY + "" + EnumChatFormatting.STRIKETHROUGH + "-----------------"); - tooltip.add(EnumChatFormatting.GRAY + "Seller: [CLICK TO SEE]"); - - if (auc.bin) { - tooltip.add(EnumChatFormatting.GRAY + "Buy it now: " + - EnumChatFormatting.GOLD + format.format(auc.starting_bid)); - } else { - if (auc.bid_count > 0) { - tooltip.add(EnumChatFormatting.GRAY + "Bids: " + EnumChatFormatting.GREEN + auc.bid_count + " bids"); - tooltip.add(""); - tooltip.add(EnumChatFormatting.GRAY + "Top bid: " + - EnumChatFormatting.GOLD + format.format(auc.highest_bid_amount)); - tooltip.add(EnumChatFormatting.GRAY + "Bidder: [CLICK TO SEE]"); - } else { - tooltip.add(EnumChatFormatting.GRAY + "Starting bid: " + - EnumChatFormatting.GOLD + format.format(auc.starting_bid)); - } - } - - if (NotEnoughUpdates.INSTANCE.config.tooltipTweaks.showPriceInfoAucItem) { - String internalname = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(auc.getStack()); - if (internalname != null) { - if (!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) && !Keyboard.isKeyDown(Keyboard.KEY_RSHIFT)) { - tooltip.add(""); - tooltip.add(EnumChatFormatting.GRAY + "[SHIFT for Price Info]"); - } else { - ItemPriceInformation.addToTooltip(tooltip, internalname, auc.getStack()); - } - } - } - - tooltip.add(""); - tooltip.add(EnumChatFormatting.GRAY + "Ends in: " + endsIn); - tooltip.add(""); - tooltip.add(EnumChatFormatting.YELLOW + "Click to inspect!"); - - return tooltip; - } - - public boolean isEditingPrice() { - return Minecraft.getMinecraft().currentScreen instanceof GuiEditSign; - } - - private boolean isGuiFiller(ItemStack stack) { - return stack == null || !stack.hasTagCompound() || !stack.getTagCompound().hasKey("AttributeModifiers"); - } - - private void drawCategorySide(int i) { - boolean clicked = i == clickedSubCategory; - - int x = guiLeft - 28; - int y = guiTop + 17 + 28 * (i + 1); - float uMin = 28 / 256f; - float uMax = 56 / 256f; - float vMin = 0 + (clicked ? 32 / 256f : 0); - float vMax = 32 / 256f + (clicked ? 32 / 256f : 0); - float catWidth = 32; - float catHeight = 28; - - GlStateManager.enableTexture2D(); - GlStateManager.enableBlend(); - GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); - - GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST); - GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST); - - Tessellator tessellator = Tessellator.getInstance(); - WorldRenderer worldrenderer = tessellator.getWorldRenderer(); - worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX); - worldrenderer - .pos(x, y + catHeight, 0.0D) - .tex(uMax, vMin).endVertex(); - worldrenderer - .pos(x + catWidth, y + catHeight, 0.0D) - .tex(uMax, vMax).endVertex(); - worldrenderer - .pos(x + catWidth, y, 0.0D) - .tex(uMin, vMax).endVertex(); - worldrenderer - .pos(x, y, 0.0D) - .tex(uMin, vMin).endVertex(); - tessellator.draw(); - - GlStateManager.disableBlend(); - } - - private HashMap timeParseMap = new HashMap<>(); - - public long prettyTimeToMillis(String endsInStr) { - if (timeParseMap.isEmpty()) { - Pattern dayPattern = Pattern.compile("([0-9]+)d"); - Pattern hourPattern = Pattern.compile("([0-9]+)h"); - Pattern minutePattern = Pattern.compile("([0-9]+)m"); - Pattern secondPattern = Pattern.compile("([0-9]+)s"); - - timeParseMap.put(dayPattern, 24 * 60 * 60 * 1000L); - timeParseMap.put(hourPattern, 60 * 60 * 1000L); - timeParseMap.put(minutePattern, 60 * 1000L); - timeParseMap.put(secondPattern, 1000L); - } - - if (endsInStr != null) { - long timeUntilEnd = 0; - - String timeStr = Utils.cleanColour(endsInStr); - - for (Map.Entry timeEntry : timeParseMap.entrySet()) { - Matcher matcher = timeEntry.getKey().matcher(timeStr); - if (matcher.find()) { - String days = matcher.group(1); - timeUntilEnd += Long.parseLong(days) * timeEntry.getValue(); - } - } - - return timeUntilEnd; - } - - return -1; - } - - public String findStrStart(ItemStack stack, String toFind) { - if (stack.hasTagCompound()) { - //§7Ends in: - for (String line : manager.getLoreFromNBT(stack.getTagCompound())) { - if (line.trim().startsWith(toFind)) { - return line.substring(toFind.length()); - } - } - } - - return null; - } - - public String findEndsInStr(ItemStack stack) { - return findStrStart(stack, EnumChatFormatting.GRAY + "Ends in: "); - } - - public void drawScreen(int mouseX, int mouseY) { - if (System.currentTimeMillis() - lastOpen < 1000) Mouse.setGrabbed(false); - - ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); - int width = scaledResolution.getScaledWidth(); - int height = scaledResolution.getScaledHeight(); - - boolean hasPopup = false; - - if (searchField == null || priceField == null || priceFilterField == null) init(); - - GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); - - guiLeft = (width - getXSize()) / 2; - guiTop = (height - getYSize()) / 2; - this.searchField.xPosition = guiLeft + 82; - this.searchField.yPosition = guiTop + 6; - - if (!isEditingPrice()) priceField.setText("IAUSHDIUAH"); - - if ((Minecraft.getMinecraft().currentScreen instanceof GuiChest || - Minecraft.getMinecraft().currentScreen instanceof GuiEditSign) && currentAucId == null) { - Minecraft.getMinecraft().displayGuiScreen(null); - } - - List tooltipToRender = null; - if (Minecraft.getMinecraft().currentScreen instanceof GuiChest) { - resetCurrAucIdTimer = System.currentTimeMillis(); - GuiChest auctionView = (GuiChest) Minecraft.getMinecraft().currentScreen; - ContainerChest container = (ContainerChest) auctionView.inventorySlots; - String containerName = container.getLowerChestInventory().getDisplayName().getUnformattedText(); - - float slideAmount = 1 - Math.max(0, Math.min(1, (System.currentTimeMillis() - lastGuiScreenSwitch) / 200f)); - int auctionViewLeft = guiLeft + getXSize() + 4 - (int) (slideAmount * (78 + 4)); - if (containerName.trim().equals("Auction View") || containerName.trim().equals("BIN Auction View")) { - hasPopup = true; - Minecraft.getMinecraft().getTextureManager().bindTexture(auction_view); - this.drawTexturedModalRect(auctionViewLeft, guiTop, 0, 0, 78, 172); - - if (auctionViewLeft + 31 > guiLeft + getXSize()) { - try { - ItemStack topStack = auctionView.inventorySlots.getSlot(13).getStack(); - ItemStack leftStack = auctionView.inventorySlots.getSlot(29).getStack(); - ItemStack middleStack = auctionView.inventorySlots.getSlot(31).getStack(); - ItemStack rightStack = auctionView.inventorySlots.getSlot(33).getStack(); - - boolean isBin = isGuiFiller(leftStack) || isGuiFiller(leftStack); - - if (isBin) { - leftStack = middleStack; - middleStack = null; - } - - String endsInStr = findEndsInStr(topStack); - if (endsInStr != null) { - long auctionViewEndsIn = prettyTimeToMillis(endsInStr); - if (auctionViewEndsIn > 0) { - if (System.currentTimeMillis() - currAucIdSetTimer > 1000) { - APIManager.Auction auc = manager.auctionManager.getAuctionItems().get(currentAucId); - if (auc != null) { - auc.end = auctionViewEndsIn + lastGuiScreenSwitch; - } - } - endsInStr = EnumChatFormatting.DARK_PURPLE + prettyTime( - auctionViewEndsIn + lastGuiScreenSwitch - System.currentTimeMillis()); - } - Utils.drawStringCenteredScaledMaxWidth(endsInStr, Minecraft.getMinecraft().fontRendererObj, - auctionViewLeft + 39, guiTop + 20, false, 70, 4210752); - } - - Utils.drawItemStack(leftStack, auctionViewLeft + 31, guiTop + 100); - - if (!isGuiFiller(leftStack)) { - NBTTagCompound tag = leftStack.getTagCompound(); - NBTTagCompound display = tag.getCompoundTag("display"); - if (display.hasKey("Lore", 9)) { - NBTTagList list = display.getTagList("Lore", 8); - String line2 = list.getStringTagAt(1); - line2 = Utils.cleanColour(line2); - StringBuilder priceNumbers = new StringBuilder(); - for (int i = 0; i < line2.length(); i++) { - char c = line2.charAt(i); - if ((int) c >= 48 && (int) c <= 57) { - priceNumbers.append(c); - } - } - if (priceNumbers.length() > 0) { - startingBid = Integer.parseInt(priceNumbers.toString()); - } - } - } - - Utils.drawItemStack(topStack, auctionViewLeft + 31, guiTop + 35); - - if (!isGuiFiller(middleStack)) { - Minecraft.getMinecraft().getTextureManager().bindTexture(auction_view_buttons); - boolean hover = mouseX > auctionViewLeft + 31 && mouseX < auctionViewLeft + 31 + 16 && - mouseY > guiTop + 126 && mouseY < guiTop + 126 + 16; - this.drawTexturedModalRect(auctionViewLeft + 31, guiTop + 126, hover ? 16 : 0, 0, 16, 16); - } else { - middleStack = null; - } - - if (mouseX > auctionViewLeft + 31 && mouseX < auctionViewLeft + 31 + 16) { - if (mouseY > guiTop + 35 && mouseY < guiTop + 35 + 16) { - if (topStack != null) { - tooltipToRender = topStack.getTooltip(Minecraft.getMinecraft().thePlayer, false); - tooltipToRender.add(""); - tooltipToRender.add(EnumChatFormatting.YELLOW + "Click to copy seller name!"); - } - } else if (mouseY > guiTop + 100 && mouseY < guiTop + 100 + 16) { - if (leftStack != null) - tooltipToRender = leftStack.getTooltip(Minecraft.getMinecraft().thePlayer, false); - } else if (mouseY > guiTop + 61 && mouseY < guiTop + 61 + 16) { - tooltipToRender = new ArrayList<>(); - APIManager.Auction auc = manager.auctionManager.getAuctionItems().get(currentAucId); - if (auc != null) { - tooltipToRender.add(EnumChatFormatting.WHITE + "Price Info"); - - String internalname = manager.getInternalNameForItem(auc.getStack()); - JsonObject auctionInfo = manager.auctionManager.getItemAuctionInfo(internalname); - JsonObject bazaarInfo = manager.auctionManager.getBazaarInfo(internalname); - - boolean hasAuctionPrice = auctionInfo != null; - boolean hasBazaarPrice = bazaarInfo != null; - - int lowestBin = manager.auctionManager.getLowestBin(internalname); - - NumberFormat format = NumberFormat.getInstance(Locale.US); - - APIManager.CraftInfo craftCost = manager.auctionManager.getCraftCost(internalname); - - if (lowestBin > 0) { - tooltipToRender.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "Lowest BIN: " + - EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + format.format(lowestBin) + " coins"); - } - if (hasBazaarPrice) { - int bazaarBuyPrice = (int) bazaarInfo.get("avg_buy").getAsFloat(); - tooltipToRender.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "Bazaar Buy: " + - EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + format.format(bazaarBuyPrice) + " coins"); - int bazaarSellPrice = (int) bazaarInfo.get("avg_sell").getAsFloat(); - tooltipToRender.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "Bazaar Sell: " + - EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + format.format(bazaarSellPrice) + " coins"); - int bazaarInstantBuyPrice = (int) bazaarInfo.get("curr_buy").getAsFloat(); - tooltipToRender.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "Bazaar Insta-Buy: " + - EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + format.format(bazaarInstantBuyPrice) + " coins"); - int bazaarInstantSellPrice = (int) bazaarInfo.get("curr_sell").getAsFloat(); - tooltipToRender.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "Bazaar Insta-Sell: " + - EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + format.format(bazaarInstantSellPrice) + " coins"); - } - if (hasAuctionPrice) { - int auctionPrice = (int) (auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat()); - tooltipToRender.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "AH Price: " + - EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + format.format(auctionPrice) + " coins"); - tooltipToRender.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "AH Sales: " + - EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + format.format(auctionInfo.get("sales").getAsFloat()) + " sales/day"); - if (auctionInfo.has("clean_price")) { - tooltipToRender.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "AH Price (Clean): " + - EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + format.format((int) auctionInfo.get("clean_price").getAsFloat()) + " coins"); - tooltipToRender.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "AH Sales (Clean): " + - EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + format.format(auctionInfo.get("clean_sales").getAsFloat()) + " sales/day"); - } - - } - if (craftCost.fromRecipe) { - tooltipToRender.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "Raw Craft Cost: " + - EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + format.format((int) craftCost.craftCost) + " coins"); - } - tooltipToRender.add(""); - } - if (rightStack != null) - tooltipToRender.addAll(rightStack.getTooltip(Minecraft.getMinecraft().thePlayer, false)); - } else if (mouseY > guiTop + 126 && mouseY < guiTop + 126 + 16) { - if (middleStack != null) - tooltipToRender = middleStack.getTooltip(Minecraft.getMinecraft().thePlayer, false); - } - } - } catch (NullPointerException e) { //i cant be bothered - } - } - } else if (containerName.trim().equals("Confirm Bid") || containerName.trim().equals("Confirm Purchase")) { - Minecraft.getMinecraft().getTextureManager().bindTexture(auction_accept); - this.drawTexturedModalRect(auctionViewLeft, guiTop, 0, 0, 78, 172); - - if (auctionViewLeft + 31 > guiLeft + getXSize()) { - try { - ItemStack leftStack = auctionView.inventorySlots.getSlot(11).getStack(); - ItemStack middleStack = auctionView.inventorySlots.getSlot(13).getStack(); - ItemStack rightStack = auctionView.inventorySlots.getSlot(15).getStack(); - - Utils.drawItemStack(middleStack, auctionViewLeft + 31, guiTop + 78); - - boolean topHovered = false; - boolean bottomHovered = false; - - if (mouseX > auctionViewLeft + 31 && mouseX < auctionViewLeft + 31 + 16) { - if (mouseY > guiTop + 31 && mouseY < guiTop + 31 + 16) { - if (leftStack != null) { - topHovered = true; - tooltipToRender = leftStack.getTooltip(Minecraft.getMinecraft().thePlayer, false); - } - } else if (mouseY > guiTop + 125 && mouseY < guiTop + 125 + 16) { - if (rightStack != null) { - bottomHovered = true; - tooltipToRender = rightStack.getTooltip(Minecraft.getMinecraft().thePlayer, false); - } - } else if (mouseY > guiTop + 78 && mouseY < guiTop + 78 + 16) { - if (middleStack != null) - tooltipToRender = middleStack.getTooltip(Minecraft.getMinecraft().thePlayer, false); - } - } - GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); - Minecraft.getMinecraft().getTextureManager().bindTexture(auction_view_buttons); - this.drawTexturedModalRect(auctionViewLeft + 31, guiTop + 31, topHovered ? 16 : 0, 48, 16, 16); - this.drawTexturedModalRect(auctionViewLeft + 31, guiTop + 125, bottomHovered ? 16 : 0, 64, 16, 16); - } catch (NullPointerException blah) { //i cant be bothered - } - } - } - - Utils.drawStringCenteredScaledMaxWidth(containerName, Minecraft.getMinecraft().fontRendererObj, - auctionViewLeft + 39, guiTop + 10, false, 70, 4210752); - } else if (isEditingPrice()) { - hasPopup = true; - resetCurrAucIdTimer = System.currentTimeMillis(); - float slideAmount = 1 - Math.max(0, Math.min(1, (System.currentTimeMillis() - lastGuiScreenSwitch) / 200f)); - int auctionViewLeft = guiLeft + getXSize() + 4 - (int) (slideAmount * (96 + 4)); - - if (priceField.getText().equals("IAUSHDIUAH")) priceField.setText("" + startingBid); - - searchField.setFocused(false); - priceField.setFocused(true); - priceField.xPosition = auctionViewLeft + 18; - priceField.yPosition = guiTop + 18; - - Minecraft.getMinecraft().getTextureManager().bindTexture(auction_price); - this.drawTexturedModalRect(auctionViewLeft, guiTop, 0, 0, 96, 99); - priceField.drawTextBox(); - - Utils.drawStringCenteredScaledMaxWidth("Bid Amount", Minecraft.getMinecraft().fontRendererObj, - auctionViewLeft + 39, guiTop + 10, false, 70, 4210752); - - GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); - Minecraft.getMinecraft().getTextureManager().bindTexture(auction_view_buttons); - this.drawTexturedModalRect(auctionViewLeft + 16, guiTop + 32, 0, 16, 30, 16); - this.drawTexturedModalRect(auctionViewLeft + 16 + 34, guiTop + 32, 0, 16, 30, 16); - this.drawTexturedModalRect(auctionViewLeft + 16, guiTop + 50, 0, 16, 30, 16); - this.drawTexturedModalRect(auctionViewLeft + 16 + 34, guiTop + 50, 0, 16, 30, 16); - this.drawTexturedModalRect(auctionViewLeft + 16, guiTop + 68, 0, 32, 64, 16); - - FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; - Utils.drawStringCentered("x2", fr, auctionViewLeft + 16 + 15, guiTop + 32 + 8, false, - Color.BLACK.getRGB()); - Utils.drawStringCentered("+50%", fr, auctionViewLeft + 16 + 34 + 15, guiTop + 32 + 8, false, - Color.BLACK.getRGB()); - Utils.drawStringCentered("+25%", fr, auctionViewLeft + 16 + 15, guiTop + 50 + 8, false, - Color.BLACK.getRGB()); - Utils.drawStringCentered("+10%", fr, auctionViewLeft + 16 + 34 + 15, guiTop + 50 + 8, false, - Color.BLACK.getRGB()); - Utils.drawStringCentered("Set Amount", fr, auctionViewLeft + 16 + 32, guiTop + 68 + 8, false, - Color.BLACK.getRGB()); - GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); - - GuiEditSign editSign = (GuiEditSign) Minecraft.getMinecraft().currentScreen; - TileEntitySign tes = (TileEntitySign) Utils.getField(GuiEditSign.class, editSign, - "tileSign", "field_146848_f"); - tes.lineBeingEdited = 0; - tes.signText[0] = new ChatComponentText(priceField.getText()); - } else { - if (System.currentTimeMillis() - resetCurrAucIdTimer > 500 && - System.currentTimeMillis() - currAucIdSetTimer > 500) { - currentAucId = null; - currAucIdSetTimer = System.currentTimeMillis(); - } - } - - Minecraft.getMinecraft().getTextureManager().bindTexture(creativeInventoryTabs); - GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); - if (mouseY > guiTop - 28 && mouseY < guiTop + 4) { - if (mouseX > guiLeft && mouseX < guiLeft + 168) { - int offset = mouseX - guiLeft; - int hoveredCat = offset / 28; - if (hoveredCat >= 0 && hoveredCat < mainCategories.length) { - tooltipToRender = Utils.createList(mainCategories[hoveredCat].displayName); - } - } - } - if (clickedMainCategory == -1) { - this.drawTexturedModalRect(guiLeft, guiTop - 28, 0, 0, 168, 32); - } else { - int selStart = clickedMainCategory * 28; - this.drawTexturedModalRect(guiLeft, guiTop - 28, 0, 0, selStart, 32); - this.drawTexturedModalRect(guiLeft + selStart + 28, guiTop - 28, selStart + 28, 0, - 168 - selStart - 28, 32); - - if (clickedMainCategory >= 0 && clickedMainCategory < mainCategories.length) { - Category mainCategory = mainCategories[clickedMainCategory]; - - if (mouseX > guiLeft - 28 && mouseX < guiLeft) { - int offset = mouseY - (guiTop + 17); - if (offset > 0) { - int hovered = offset / 28 - 1; - if (hovered < 0) { - tooltipToRender = Utils.createList(mainCategory.displayName); - } else if (hovered < mainCategory.subcategories.length) { - tooltipToRender = Utils.createList(mainCategory.subcategories[hovered].displayName); - } - } - } - - for (int i = -1; i < mainCategory.subcategories.length; i++) { - if (i != clickedSubCategory) drawCategorySide(i); - } - } - } - - //Main GUI - Minecraft.getMinecraft().getTextureManager().bindTexture(creativeTabSearch); - GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); - this.drawTexturedModalRect(guiLeft, guiTop, 0, 0, getXSize(), ySplit); - int y = guiTop + ySplit; - for (int i = 0; i < splits; i++) { - this.drawTexturedModalRect(guiLeft, y, 0, ySplit, getXSize(), ySplit + ySplitSize); - y += ySplitSize; - } - this.drawTexturedModalRect(guiLeft, y, 0, ySplit, getXSize(), 136 - ySplit); - - //GUI Name - Utils.drawStringCenteredScaledMaxWidth("Auction House", Minecraft.getMinecraft().fontRendererObj, guiLeft + 42, - guiTop + 10, false, 68, 4210752); - GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); - - //Categories - Minecraft.getMinecraft().getTextureManager().bindTexture(creativeInventoryTabs); - GlStateManager.enableBlend(); - GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); - if (clickedMainCategory != -1) { - int selStart = clickedMainCategory * 28; - - this.drawTexturedModalRect(guiLeft + selStart, guiTop - 28, clickedMainCategory == 0 ? 0 : 28, 32, 28, 32); - - if (clickedMainCategory >= 0 && clickedMainCategory < mainCategories.length) { - Category mainCategory = mainCategories[clickedMainCategory]; - - if (clickedSubCategory >= -1 && clickedSubCategory < mainCategory.subcategories.length) { - drawCategorySide(clickedSubCategory); - } - } - } - - //Category icons - for (int i = 0; i < mainCategories.length; i++) { - Category category = mainCategories[i]; - Utils.drawItemStack(category.displayItem, guiLeft + 28 * i + 6, guiTop - 28 + 9); - } - if (clickedMainCategory >= 0 && clickedMainCategory < mainCategories.length) { - Category mainCategory = mainCategories[clickedMainCategory]; - - Utils.drawItemStack(mainCategory.displayItem, guiLeft - 19, guiTop + 23); - for (int i = 0; i < mainCategory.subcategories.length; i++) { - Utils.drawItemStack(mainCategory.subcategories[i].displayItem, guiLeft - 19, guiTop + 23 + 28 * (i + 1)); - } - } - - for (int i = 0; i < controls.length; i++) { - Utils.drawItemStack(controls[i], guiLeft + 9 + 18 * i, guiTop + 112 + 18 * splits); - if (mouseX > guiLeft + 9 + 18 * i && mouseX < guiLeft + 9 + 18 * i + 16) { - if (mouseY > guiTop + 112 + 18 * splits && mouseY < guiTop + 112 + 18 * splits + 16) { - tooltipToRender = getTooltipForControl(i); - } - } - } - - int totalItems = auctionIds.size(); - int itemsScroll = (int) Math.floor((totalItems * scrollAmount) / 9f) * 9; - - int maxItemScroll = Math.max(0, totalItems - (5 + splits) * 9); - itemsScroll = Math.min(itemsScroll, maxItemScroll); - - if (NotEnoughUpdates.INSTANCE.config.neuAuctionHouse.enableNeuAuctionHouse) { - out: - for (int i = 0; i < 5 + splits; i++) { - int itemY = guiTop + i * 18 + 18; - for (int j = 0; j < 9; j++) { - int itemX = guiLeft + j * 18 + 9; - int id = itemsScroll + i * 9 + j; - if (auctionIds.size() <= id) break out; - - try { - String aucid = sortedAuctionIds.get(id); - - GL11.glTranslatef(0, 0, 100); - ItemStack stack = manager.auctionManager.getAuctionItems().get(aucid).getStack(); - Utils.drawItemStack(stack, itemX, itemY); - GL11.glTranslatef(0, 0, -100); - - if (mouseX > itemX && mouseX < itemX + 16) { - if (mouseY > itemY && mouseY < itemY + 16) { - tooltipToRender = getTooltipForAucId(aucid); - } - } - } catch (Exception e) { - } - } - } - } - - GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); - searchField.drawTextBox(); - GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + private enum PriceFilter { + Greater, + Less, + Equal + } + + private static final ResourceLocation creativeTabSearch = + new ResourceLocation("textures/gui/container/creative_inventory/tab_item_search.png"); + private static final ResourceLocation creativeInventoryTabs = + new ResourceLocation("textures/gui/container/creative_inventory/tabs.png"); + + private HashSet auctionIds = new HashSet<>(); + private List sortedAuctionIds = new ArrayList<>(); + + private boolean scrollClicked = false; + + private long lastUpdateSearch; + private long lastSearchFieldUpdate; + private boolean shouldUpdateSearch = false; + private boolean shouldSortItems = false; + + private int startingBid = 0; + private String currentAucId = null; + + private int clickedMainCategory = -1; + private int clickedSubCategory = -1; + + private GuiTextField searchField = null; + private GuiTextField priceField = null; + private GuiTextField priceFilterField = null; + private GuiTextField binPriceFilterField = null; + + private final int binPriceFilterYOffset = 86; + + private boolean renderOverAuctionView = false; + private long lastRenderDisable = 0; + + private long currAucIdSetTimer = 0; + private long resetCurrAucIdTimer = 0; + + private int eventButton; + private long lastMouseEvent; + public long lastOpen; + public long lastGuiScreenSwitch; + private PriceFilter currentPriceFilterType = PriceFilter.Greater; + private PriceFilter currentBinPriceFilterType = PriceFilter.Greater; + + private final int splits = 2; + + public String latestBid; + public long latestBidMillis; + + private final int ySplit = 35; + private final int ySplitSize = 18; + + private float scrollAmount; + + public int guiLeft = -1; + public int guiTop = -1; + + private final Category CATEGORY_SWORD = new Category("sword", "Swords", "diamond_sword"); + private final Category CATEGORY_ARMOR = new Category("armor", "Armor", "diamond_chestplate"); + private final Category CATEGORY_BOWS = new Category("bow", "Bows", "bow"); + private final Category CATEGORY_ACCESSORIES = new Category("accessories", "Accessories", "diamond"); + + private final Category CATEGORY_FISHING_ROD = new Category("fishingrod", "Fishing Rods", "fishing_rod"); + private final Category CATEGORY_PICKAXE = new Category("pickaxe", "Pickaxes", "iron_pickaxe"); + private final Category CATEGORY_AXE = new Category("axe", "Axes", "iron_axe"); + private final Category CATEGORY_SHOVEL = new Category("shovel", "Shovels", "iron_shovel"); + + private final Category CATEGORY_PET_ITEM = new Category("petitem", "Pet Items", "lead"); + + private final Category CATEGORY_EBOOKS = new Category("ebook", "Enchanted Books", "enchanted_book"); + private final Category CATEGORY_POTIONS = new Category("potion", "Potions", "potion"); + private final Category CATEGORY_TRAVEL_SCROLLS = new Category("travelscroll", "Travel Scrolls", "map"); + + private final Category CATEGORY_REFORGE_STONES = new Category("reforgestone", "Reforge Stones", "anvil"); + private final Category CATEGORY_RUNES = new Category("rune", "Runes", "magma_cream"); + private final Category CATEGORY_FURNITURE = new Category("furniture", "Furniture", "armor_stand"); + + private final Category CATEGORY_COMBAT = new Category("weapon", "Combat", "golden_sword", CATEGORY_SWORD, + CATEGORY_BOWS, CATEGORY_ARMOR, CATEGORY_ACCESSORIES + ); + private final Category CATEGORY_TOOL = new Category( + "", + "Tools", + "diamond_pickaxe", + CATEGORY_FISHING_ROD, + CATEGORY_PICKAXE, + CATEGORY_AXE, + CATEGORY_SHOVEL + ); + private final Category CATEGORY_PET = new Category("pet", "Pets", "bone", CATEGORY_PET_ITEM); + private final Category CATEGORY_CONSUMABLES = new Category( + "consumables", + "Consumables", + "apple", + CATEGORY_EBOOKS, + CATEGORY_POTIONS, + CATEGORY_TRAVEL_SCROLLS + ); + private final Category CATEGORY_BLOCKS = new Category("blocks", "Blocks", "cobblestone"); + private final Category CATEGORY_MISC = new Category("misc", "Misc", "stick", CATEGORY_REFORGE_STONES, CATEGORY_RUNES, + CATEGORY_FURNITURE + ); + + private final Category[] mainCategories = new Category[]{ + CATEGORY_COMBAT, CATEGORY_TOOL, CATEGORY_PET, + CATEGORY_CONSUMABLES, CATEGORY_BLOCKS, CATEGORY_MISC + }; + + private static final int SORT_MODE_HIGH = 0; + private static final int SORT_MODE_LOW = 1; + private static final int SORT_MODE_SOON = 2; + + // private static final String[] rarities = {"COMMON", "UNCOMMON", "RARE", "EPIC", +// "LEGENDARY", "MYTHIC", "SPECIAL", "VERY SPECIAL", "SUPREME", "DIVINE"}; + private static final String[] rarityColours = { + "" + EnumChatFormatting.WHITE, + "" + EnumChatFormatting.GREEN, "" + EnumChatFormatting.BLUE, "" + EnumChatFormatting.DARK_PURPLE, + "" + EnumChatFormatting.GOLD, "" + EnumChatFormatting.LIGHT_PURPLE, "" + EnumChatFormatting.RED, + "" + EnumChatFormatting.RED, "" + EnumChatFormatting.AQUA, "" + EnumChatFormatting.AQUA + }; + + private static final int BIN_FILTER_ALL = 0; + private static final int BIN_FILTER_BIN = 1; + private static final int BIN_FILTER_AUC = 2; + + private static final int ENCH_FILTER_ALL = 0; + private static final int ENCH_FILTER_CLEAN = 1; + private static final int ENCH_FILTER_ENCH = 2; + private static final int ENCH_FILTER_ENCHHPB = 3; + + private static final int DUNGEON_FILTER_ALL = 0; + private static final int DUNGEON_FILTER_DUNGEON = 1; + private static final int DUNGEON_FILTER_1 = 2; + private static final int DUNGEON_FILTER_2 = 3; + private static final int DUNGEON_FILTER_3 = 4; + private static final int DUNGEON_FILTER_4 = 5; + private static final int DUNGEON_FILTER_5 = 6; + + private int dungeonFilter = DUNGEON_FILTER_ALL; + private int sortMode = SORT_MODE_HIGH; + private int rarityFilter = -1; + private boolean filterMyAuctions = false; + private int binFilter = BIN_FILTER_ALL; + private int enchFilter = ENCH_FILTER_ALL; + + private static final ItemStack DUNGEON_SORT = Utils.createItemStack( + Item.getItemFromBlock(Blocks.deadbush), + EnumChatFormatting.GREEN + "Dungeon Sorting" + ); + private static final ItemStack CONTROL_SORT = Utils.createItemStack( + Item.getItemFromBlock(Blocks.hopper), + EnumChatFormatting.GREEN + "Sort" + ); + private static final ItemStack CONTROL_TIER = Utils.createItemStack( + Items.ender_eye, + EnumChatFormatting.GREEN + "Item Tier" + ); + private static final ItemStack CONTROL_MYAUC = Utils.createItemStack( + Items.gold_ingot, + EnumChatFormatting.GREEN + "My Auctions" + ); + private static final ItemStack CONTROL_BIN = Utils.createItemStack( + Item.getItemFromBlock(Blocks.golden_rail), + EnumChatFormatting.GREEN + "BIN Filter" + ); + private static final ItemStack CONTROL_ENCH = Utils.createItemStack( + Items.enchanted_book, + EnumChatFormatting.GREEN + "Enchant Filter" + ); + private static final ItemStack CONTROL_STATS = Utils.createItemStack( + Item.getItemFromBlock(Blocks.command_block), + EnumChatFormatting.GREEN + "Stats for nerds" + ); + private final ItemStack[] controls = + {DUNGEON_SORT, CONTROL_SORT, CONTROL_TIER, null, CONTROL_MYAUC, null, CONTROL_BIN, CONTROL_ENCH, CONTROL_STATS}; + + private final NEUManager manager; + + public CustomAH(NEUManager manager) { + this.manager = manager; + } + + public void clearSearch() { + if (searchField == null || priceField == null) init(); + if (System.currentTimeMillis() - lastOpen < 1000) Mouse.setGrabbed(false); + + //sortMode = SORT_MODE_HIGH; + rarityFilter = -1; + filterMyAuctions = false; + //binFilter = BIN_FILTER_ALL; + enchFilter = ENCH_FILTER_ALL; + dungeonFilter = DUNGEON_FILTER_ALL; + + searchField.setText(""); + searchField.setFocused(true); + priceField.setText(""); + } + + public void setSearch(String search) { + searchField.setText(search); + updateSearch(); + } + + public void tick() { + if (!NotEnoughUpdates.INSTANCE.config.neuAuctionHouse.enableNeuAuctionHouse) return; + if (Minecraft.getMinecraft().currentScreen instanceof CustomAHGui || renderOverAuctionView) { + if (shouldUpdateSearch) updateSearch(); + if (shouldSortItems) { + sortItems(); + shouldSortItems = false; + } + } + } + + public static class Category { + public String categoryMatch; + public Category[] subcategories; + public String displayName; + public ItemStack displayItem; + + public Category(String categoryMatch, String displayName, String displayItem, Category... subcategories) { + this.categoryMatch = categoryMatch; + this.subcategories = subcategories; + this.displayName = displayName; + this.displayItem = new ItemStack(Item.getByNameOrId(displayItem)); + } + + public String[] getTotalCategories() { + String[] categories = new String[1 + subcategories.length]; + categories[0] = categoryMatch; + + for (int i = 0; i < subcategories.length; i++) { + categories[i + 1] = subcategories[i].categoryMatch; + } + return categories; + } + } + + private void init() { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + this.searchField = new GuiTextField(0, fr, this.guiLeft + 82, this.guiTop + 6, + 84, fr.FONT_HEIGHT + ); + this.priceField = new GuiTextField(1, fr, this.guiLeft + 82, this.guiTop + 6, + 84, fr.FONT_HEIGHT + ); + this.priceFilterField = new GuiTextField(2, fr, this.guiLeft + 82, this.guiTop + 6, + 84, fr.FONT_HEIGHT + ); + this.binPriceFilterField = new GuiTextField(3, fr, this.guiLeft + 82, this.guiTop - 6, 84, fr.FONT_HEIGHT); + + this.searchField.setMaxStringLength(30); + this.searchField.setEnableBackgroundDrawing(false); + this.searchField.setTextColor(16777215); + this.searchField.setVisible(true); + this.searchField.setCanLoseFocus(true); + this.searchField.setFocused(true); + this.searchField.setText(""); + + this.priceField.setMaxStringLength(10); + this.priceField.setEnableBackgroundDrawing(false); + this.priceField.setTextColor(16777215); + this.priceField.setVisible(true); + this.priceField.setCanLoseFocus(true); + this.priceField.setFocused(false); + this.priceField.setText(""); + + this.priceFilterField.setMaxStringLength(10); + this.priceFilterField.setEnableBackgroundDrawing(false); + this.priceFilterField.setTextColor(16777215); + this.priceFilterField.setVisible(true); + this.priceFilterField.setCanLoseFocus(true); + this.priceFilterField.setFocused(false); + this.priceFilterField.setText(""); + + this.binPriceFilterField.setMaxStringLength(10); + this.binPriceFilterField.setEnableBackgroundDrawing(false); + this.binPriceFilterField.setTextColor(16777215); + this.binPriceFilterField.setVisible(true); + this.binPriceFilterField.setCanLoseFocus(true); + this.binPriceFilterField.setFocused(false); + this.binPriceFilterField.setText(""); + } + + public boolean isRenderOverAuctionView() { + return renderOverAuctionView || (System.currentTimeMillis() - lastRenderDisable) < 500; + } + + public void setRenderOverAuctionView(boolean renderOverAuctionView) { + if (this.renderOverAuctionView && !renderOverAuctionView) lastRenderDisable = System.currentTimeMillis(); + this.renderOverAuctionView = renderOverAuctionView; + } + + public int getXSize() { + return 195; + } + + public int getYSize() { + return 136 + ySplitSize * splits; + } + + private String prettyTime(long millis) { + long seconds = millis / 1000 % 60; + long minutes = (millis / 1000 / 60) % 60; + long hours = (millis / 1000 / 60 / 60) % 24; + long days = (millis / 1000 / 60 / 60 / 24); + + String endsIn = ""; + if (millis < 0) { + endsIn += "Ended!"; + } else if (minutes == 0 && hours == 0 && days == 0) { + endsIn += seconds + "s"; + } else if (hours == 0 && days == 0) { + endsIn += minutes + "m" + seconds + "s"; + } else if (days == 0) { + if (hours <= 6) { + endsIn += hours + "h" + minutes + "m" + seconds + "s"; + } else { + endsIn += hours + "h"; + } + } else { + endsIn += days + "d" + hours + "h"; + } + + return endsIn; + } + + public List getTooltipForAucId(String aucId) { + APIManager.Auction auc = manager.auctionManager.getAuctionItems().get(aucId); + + List tooltip = new ArrayList<>(); + + for (String line : auc.getStack().getTooltip(Minecraft.getMinecraft().thePlayer, false)) { + tooltip.add(EnumChatFormatting.GRAY + line); + } + + long timeUntilEnd = auc.end - System.currentTimeMillis(); + String endsIn = EnumChatFormatting.YELLOW + prettyTime(timeUntilEnd); + + NumberFormat format = NumberFormat.getInstance(Locale.US); + + tooltip.add(EnumChatFormatting.DARK_GRAY + "" + EnumChatFormatting.STRIKETHROUGH + "-----------------"); + tooltip.add(EnumChatFormatting.GRAY + "Seller: [CLICK TO SEE]"); + + if (auc.bin) { + tooltip.add(EnumChatFormatting.GRAY + "Buy it now: " + + EnumChatFormatting.GOLD + format.format(auc.starting_bid)); + } else { + if (auc.bid_count > 0) { + tooltip.add(EnumChatFormatting.GRAY + "Bids: " + EnumChatFormatting.GREEN + auc.bid_count + " bids"); + tooltip.add(""); + tooltip.add(EnumChatFormatting.GRAY + "Top bid: " + + EnumChatFormatting.GOLD + format.format(auc.highest_bid_amount)); + tooltip.add(EnumChatFormatting.GRAY + "Bidder: [CLICK TO SEE]"); + } else { + tooltip.add(EnumChatFormatting.GRAY + "Starting bid: " + + EnumChatFormatting.GOLD + format.format(auc.starting_bid)); + } + } + + if (NotEnoughUpdates.INSTANCE.config.tooltipTweaks.showPriceInfoAucItem) { + String internalname = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(auc.getStack()); + if (internalname != null) { + if (!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) && !Keyboard.isKeyDown(Keyboard.KEY_RSHIFT)) { + tooltip.add(""); + tooltip.add(EnumChatFormatting.GRAY + "[SHIFT for Price Info]"); + } else { + ItemPriceInformation.addToTooltip(tooltip, internalname, auc.getStack()); + } + } + } + + tooltip.add(""); + tooltip.add(EnumChatFormatting.GRAY + "Ends in: " + endsIn); + tooltip.add(""); + tooltip.add(EnumChatFormatting.YELLOW + "Click to inspect!"); + + return tooltip; + } + + public boolean isEditingPrice() { + return Minecraft.getMinecraft().currentScreen instanceof GuiEditSign; + } + + private boolean isGuiFiller(ItemStack stack) { + return stack == null || !stack.hasTagCompound() || !stack.getTagCompound().hasKey("AttributeModifiers"); + } + + private void drawCategorySide(int i) { + boolean clicked = i == clickedSubCategory; + + int x = guiLeft - 28; + int y = guiTop + 17 + 28 * (i + 1); + float uMin = 28 / 256f; + float uMax = 56 / 256f; + float vMin = 0 + (clicked ? 32 / 256f : 0); + float vMax = 32 / 256f + (clicked ? 32 / 256f : 0); + float catWidth = 32; + float catHeight = 28; + + GlStateManager.enableTexture2D(); + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST); + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST); + + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer worldrenderer = tessellator.getWorldRenderer(); + worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX); + worldrenderer + .pos(x, y + catHeight, 0.0D) + .tex(uMax, vMin).endVertex(); + worldrenderer + .pos(x + catWidth, y + catHeight, 0.0D) + .tex(uMax, vMax).endVertex(); + worldrenderer + .pos(x + catWidth, y, 0.0D) + .tex(uMin, vMax).endVertex(); + worldrenderer + .pos(x, y, 0.0D) + .tex(uMin, vMin).endVertex(); + tessellator.draw(); + + GlStateManager.disableBlend(); + } + + private final HashMap timeParseMap = new HashMap() {{ + Pattern dayPattern = Pattern.compile("([0-9]+)d"); + Pattern hourPattern = Pattern.compile("([0-9]+)h"); + Pattern minutePattern = Pattern.compile("([0-9]+)m"); + Pattern secondPattern = Pattern.compile("([0-9]+)s"); + + put(dayPattern, 24 * 60 * 60 * 1000L); + put(hourPattern, 60 * 60 * 1000L); + put(minutePattern, 60 * 1000L); + put(secondPattern, 1000L); + }}; + + public long prettyTimeToMillis(String endsInStr) { + if (endsInStr != null) { + long timeUntilEnd = 0; + + String timeStr = Utils.cleanColour(endsInStr); + + for (Map.Entry timeEntry : timeParseMap.entrySet()) { + Matcher matcher = timeEntry.getKey().matcher(timeStr); + if (matcher.find()) { + String days = matcher.group(1); + timeUntilEnd += Long.parseLong(days) * timeEntry.getValue(); + } + } + + return timeUntilEnd; + } + + return -1; + } + + public String findStrStart(ItemStack stack, String toFind) { + if (stack.hasTagCompound()) { + //§7Ends in: + for (String line : manager.getLoreFromNBT(stack.getTagCompound())) { + if (line.trim().startsWith(toFind)) { + return line.substring(toFind.length()); + } + } + } + + return null; + } + + public String findEndsInStr(ItemStack stack) { + return findStrStart(stack, EnumChatFormatting.GRAY + "Ends in: "); + } + + public void drawScreen(int mouseX, int mouseY) { + if (System.currentTimeMillis() - lastOpen < 1000) Mouse.setGrabbed(false); + + ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + int width = scaledResolution.getScaledWidth(); + int height = scaledResolution.getScaledHeight(); + + boolean hasPopup = false; + + if (searchField == null || priceField == null || priceFilterField == null) init(); + + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + + guiLeft = (width - getXSize()) / 2; + guiTop = (height - getYSize()) / 2; + this.searchField.xPosition = guiLeft + 82; + this.searchField.yPosition = guiTop + 6; + + if (!isEditingPrice()) priceField.setText("IAUSHDIUAH"); + + if ((Minecraft.getMinecraft().currentScreen instanceof GuiChest || + Minecraft.getMinecraft().currentScreen instanceof GuiEditSign) && currentAucId == null) { + Minecraft.getMinecraft().displayGuiScreen(null); + } + + List tooltipToRender = null; + if (Minecraft.getMinecraft().currentScreen instanceof GuiChest) { + resetCurrAucIdTimer = System.currentTimeMillis(); + GuiChest auctionView = (GuiChest) Minecraft.getMinecraft().currentScreen; + ContainerChest container = (ContainerChest) auctionView.inventorySlots; + String containerName = container.getLowerChestInventory().getDisplayName().getUnformattedText(); + + float slideAmount = 1 - Math.max(0, Math.min(1, (System.currentTimeMillis() - lastGuiScreenSwitch) / 200f)); + int auctionViewLeft = guiLeft + getXSize() + 4 - (int) (slideAmount * (78 + 4)); + if (containerName.trim().equals("Auction View") || containerName.trim().equals("BIN Auction View")) { + hasPopup = true; + Minecraft.getMinecraft().getTextureManager().bindTexture(auction_view); + this.drawTexturedModalRect(auctionViewLeft, guiTop, 0, 0, 78, 172); + + if (auctionViewLeft + 31 > guiLeft + getXSize()) { + try { + ItemStack topStack = auctionView.inventorySlots.getSlot(13).getStack(); + ItemStack leftStack = auctionView.inventorySlots.getSlot(29).getStack(); + ItemStack middleStack = auctionView.inventorySlots.getSlot(31).getStack(); + ItemStack rightStack = auctionView.inventorySlots.getSlot(33).getStack(); + + boolean isBin = isGuiFiller(leftStack) || isGuiFiller(leftStack); + + if (isBin) { + leftStack = middleStack; + middleStack = null; + } + + String endsInStr = findEndsInStr(topStack); + if (endsInStr != null) { + long auctionViewEndsIn = prettyTimeToMillis(endsInStr); + if (auctionViewEndsIn > 0) { + if (System.currentTimeMillis() - currAucIdSetTimer > 1000) { + APIManager.Auction auc = manager.auctionManager.getAuctionItems().get(currentAucId); + if (auc != null) { + auc.end = auctionViewEndsIn + lastGuiScreenSwitch; + } + } + endsInStr = EnumChatFormatting.DARK_PURPLE + prettyTime( + auctionViewEndsIn + lastGuiScreenSwitch - System.currentTimeMillis()); + } + Utils.drawStringCenteredScaledMaxWidth(endsInStr, Minecraft.getMinecraft().fontRendererObj, + auctionViewLeft + 39, guiTop + 20, false, 70, 4210752 + ); + } + + Utils.drawItemStack(leftStack, auctionViewLeft + 31, guiTop + 100); + + if (!isGuiFiller(leftStack)) { + NBTTagCompound tag = leftStack.getTagCompound(); + NBTTagCompound display = tag.getCompoundTag("display"); + if (display.hasKey("Lore", 9)) { + NBTTagList list = display.getTagList("Lore", 8); + String line2 = list.getStringTagAt(1); + line2 = Utils.cleanColour(line2); + StringBuilder priceNumbers = new StringBuilder(); + for (int i = 0; i < line2.length(); i++) { + char c = line2.charAt(i); + if ((int) c >= 48 && (int) c <= 57) { + priceNumbers.append(c); + } + } + if (priceNumbers.length() > 0) { + startingBid = Integer.parseInt(priceNumbers.toString()); + } + } + } + + Utils.drawItemStack(topStack, auctionViewLeft + 31, guiTop + 35); + + if (!isGuiFiller(middleStack)) { + Minecraft.getMinecraft().getTextureManager().bindTexture(auction_view_buttons); + boolean hover = mouseX > auctionViewLeft + 31 && mouseX < auctionViewLeft + 31 + 16 && + mouseY > guiTop + 126 && mouseY < guiTop + 126 + 16; + this.drawTexturedModalRect(auctionViewLeft + 31, guiTop + 126, hover ? 16 : 0, 0, 16, 16); + } else { + middleStack = null; + } + + if (mouseX > auctionViewLeft + 31 && mouseX < auctionViewLeft + 31 + 16) { + if (mouseY > guiTop + 35 && mouseY < guiTop + 35 + 16) { + if (topStack != null) { + tooltipToRender = topStack.getTooltip(Minecraft.getMinecraft().thePlayer, false); + tooltipToRender.add(""); + tooltipToRender.add(EnumChatFormatting.YELLOW + "Click to copy seller name!"); + } + } else if (mouseY > guiTop + 100 && mouseY < guiTop + 100 + 16) { + if (leftStack != null) + tooltipToRender = leftStack.getTooltip(Minecraft.getMinecraft().thePlayer, false); + } else if (mouseY > guiTop + 61 && mouseY < guiTop + 61 + 16) { + tooltipToRender = new ArrayList<>(); + APIManager.Auction auc = manager.auctionManager.getAuctionItems().get(currentAucId); + if (auc != null) { + tooltipToRender.add(EnumChatFormatting.WHITE + "Price Info"); + + String internalname = manager.getInternalNameForItem(auc.getStack()); + JsonObject auctionInfo = manager.auctionManager.getItemAuctionInfo(internalname); + JsonObject bazaarInfo = manager.auctionManager.getBazaarInfo(internalname); + + boolean hasAuctionPrice = auctionInfo != null; + boolean hasBazaarPrice = bazaarInfo != null; + + int lowestBin = manager.auctionManager.getLowestBin(internalname); + + NumberFormat format = NumberFormat.getInstance(Locale.US); + + APIManager.CraftInfo craftCost = manager.auctionManager.getCraftCost(internalname); + + if (lowestBin > 0) { + tooltipToRender.add( + EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "Lowest BIN: " + + EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + format.format(lowestBin) + " coins"); + } + if (hasBazaarPrice) { + int bazaarBuyPrice = (int) bazaarInfo.get("avg_buy").getAsFloat(); + tooltipToRender.add( + EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "Bazaar Buy: " + + EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + format.format(bazaarBuyPrice) + " coins"); + int bazaarSellPrice = (int) bazaarInfo.get("avg_sell").getAsFloat(); + tooltipToRender.add( + EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "Bazaar Sell: " + + EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + format.format(bazaarSellPrice) + " coins"); + int bazaarInstantBuyPrice = (int) bazaarInfo.get("curr_buy").getAsFloat(); + tooltipToRender.add( + EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "Bazaar Insta-Buy: " + + EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + format.format(bazaarInstantBuyPrice) + + " coins"); + int bazaarInstantSellPrice = (int) bazaarInfo.get("curr_sell").getAsFloat(); + tooltipToRender.add( + EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "Bazaar Insta-Sell: " + + EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + format.format(bazaarInstantSellPrice) + + " coins"); + } + if (hasAuctionPrice) { + int auctionPrice = + (int) (auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat()); + tooltipToRender.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "AH Price: " + + EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + format.format(auctionPrice) + " coins"); + tooltipToRender.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "AH Sales: " + + EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + + format.format(auctionInfo.get("sales").getAsFloat()) + " sales/day"); + if (auctionInfo.has("clean_price")) { + tooltipToRender.add( + EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "AH Price (Clean): " + + EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + + format.format((int) auctionInfo.get("clean_price").getAsFloat()) + " coins"); + tooltipToRender.add( + EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "AH Sales (Clean): " + + EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + + format.format(auctionInfo.get("clean_sales").getAsFloat()) + " sales/day"); + } + + } + if (craftCost.fromRecipe) { + tooltipToRender.add( + EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "Raw Craft Cost: " + + EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + format.format((int) craftCost.craftCost) + + " coins"); + } + tooltipToRender.add(""); + } + if (rightStack != null) + tooltipToRender.addAll(rightStack.getTooltip(Minecraft.getMinecraft().thePlayer, false)); + } else if (mouseY > guiTop + 126 && mouseY < guiTop + 126 + 16) { + if (middleStack != null) + tooltipToRender = middleStack.getTooltip(Minecraft.getMinecraft().thePlayer, false); + } + } + } catch (NullPointerException e) { //i cant be bothered + } + } + } else if (containerName.trim().equals("Confirm Bid") || containerName.trim().equals("Confirm Purchase")) { + Minecraft.getMinecraft().getTextureManager().bindTexture(auction_accept); + this.drawTexturedModalRect(auctionViewLeft, guiTop, 0, 0, 78, 172); + + if (auctionViewLeft + 31 > guiLeft + getXSize()) { + try { + ItemStack leftStack = auctionView.inventorySlots.getSlot(11).getStack(); + ItemStack middleStack = auctionView.inventorySlots.getSlot(13).getStack(); + ItemStack rightStack = auctionView.inventorySlots.getSlot(15).getStack(); + + Utils.drawItemStack(middleStack, auctionViewLeft + 31, guiTop + 78); + + boolean topHovered = false; + boolean bottomHovered = false; + + if (mouseX > auctionViewLeft + 31 && mouseX < auctionViewLeft + 31 + 16) { + if (mouseY > guiTop + 31 && mouseY < guiTop + 31 + 16) { + if (leftStack != null) { + topHovered = true; + tooltipToRender = leftStack.getTooltip(Minecraft.getMinecraft().thePlayer, false); + } + } else if (mouseY > guiTop + 125 && mouseY < guiTop + 125 + 16) { + if (rightStack != null) { + bottomHovered = true; + tooltipToRender = rightStack.getTooltip(Minecraft.getMinecraft().thePlayer, false); + } + } else if (mouseY > guiTop + 78 && mouseY < guiTop + 78 + 16) { + if (middleStack != null) + tooltipToRender = middleStack.getTooltip(Minecraft.getMinecraft().thePlayer, false); + } + } + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + Minecraft.getMinecraft().getTextureManager().bindTexture(auction_view_buttons); + this.drawTexturedModalRect(auctionViewLeft + 31, guiTop + 31, topHovered ? 16 : 0, 48, 16, 16); + this.drawTexturedModalRect(auctionViewLeft + 31, guiTop + 125, bottomHovered ? 16 : 0, 64, 16, 16); + } catch (NullPointerException blah) { //i cant be bothered + } + } + } + + Utils.drawStringCenteredScaledMaxWidth(containerName, Minecraft.getMinecraft().fontRendererObj, + auctionViewLeft + 39, guiTop + 10, false, 70, 4210752 + ); + } else if (isEditingPrice()) { + hasPopup = true; + resetCurrAucIdTimer = System.currentTimeMillis(); + float slideAmount = 1 - Math.max(0, Math.min(1, (System.currentTimeMillis() - lastGuiScreenSwitch) / 200f)); + int auctionViewLeft = guiLeft + getXSize() + 4 - (int) (slideAmount * (96 + 4)); + + if (priceField.getText().equals("IAUSHDIUAH")) priceField.setText("" + startingBid); + + searchField.setFocused(false); + priceField.setFocused(true); + priceField.xPosition = auctionViewLeft + 18; + priceField.yPosition = guiTop + 18; + + Minecraft.getMinecraft().getTextureManager().bindTexture(auction_price); + this.drawTexturedModalRect(auctionViewLeft, guiTop, 0, 0, 96, 99); + priceField.drawTextBox(); + + Utils.drawStringCenteredScaledMaxWidth("Bid Amount", Minecraft.getMinecraft().fontRendererObj, + auctionViewLeft + 39, guiTop + 10, false, 70, 4210752 + ); + + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + Minecraft.getMinecraft().getTextureManager().bindTexture(auction_view_buttons); + this.drawTexturedModalRect(auctionViewLeft + 16, guiTop + 32, 0, 16, 30, 16); + this.drawTexturedModalRect(auctionViewLeft + 16 + 34, guiTop + 32, 0, 16, 30, 16); + this.drawTexturedModalRect(auctionViewLeft + 16, guiTop + 50, 0, 16, 30, 16); + this.drawTexturedModalRect(auctionViewLeft + 16 + 34, guiTop + 50, 0, 16, 30, 16); + this.drawTexturedModalRect(auctionViewLeft + 16, guiTop + 68, 0, 32, 64, 16); + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + Utils.drawStringCentered("x2", fr, auctionViewLeft + 16 + 15, guiTop + 32 + 8, false, + Color.BLACK.getRGB() + ); + Utils.drawStringCentered("+50%", fr, auctionViewLeft + 16 + 34 + 15, guiTop + 32 + 8, false, + Color.BLACK.getRGB() + ); + Utils.drawStringCentered("+25%", fr, auctionViewLeft + 16 + 15, guiTop + 50 + 8, false, + Color.BLACK.getRGB() + ); + Utils.drawStringCentered("+10%", fr, auctionViewLeft + 16 + 34 + 15, guiTop + 50 + 8, false, + Color.BLACK.getRGB() + ); + Utils.drawStringCentered("Set Amount", fr, auctionViewLeft + 16 + 32, guiTop + 68 + 8, false, + Color.BLACK.getRGB() + ); + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + + GuiEditSign editSign = (GuiEditSign) Minecraft.getMinecraft().currentScreen; + TileEntitySign tes = (TileEntitySign) Utils.getField(GuiEditSign.class, editSign, + "tileSign", "field_146848_f" + ); + tes.lineBeingEdited = 0; + tes.signText[0] = new ChatComponentText(priceField.getText()); + } else { + if (System.currentTimeMillis() - resetCurrAucIdTimer > 500 && + System.currentTimeMillis() - currAucIdSetTimer > 500) { + currentAucId = null; + currAucIdSetTimer = System.currentTimeMillis(); + } + } + + Minecraft.getMinecraft().getTextureManager().bindTexture(creativeInventoryTabs); + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + if (mouseY > guiTop - 28 && mouseY < guiTop + 4) { + if (mouseX > guiLeft && mouseX < guiLeft + 168) { + int offset = mouseX - guiLeft; + int hoveredCat = offset / 28; + if (hoveredCat >= 0 && hoveredCat < mainCategories.length) { + tooltipToRender = Utils.createList(mainCategories[hoveredCat].displayName); + } + } + } + if (clickedMainCategory == -1) { + this.drawTexturedModalRect(guiLeft, guiTop - 28, 0, 0, 168, 32); + } else { + int selStart = clickedMainCategory * 28; + this.drawTexturedModalRect(guiLeft, guiTop - 28, 0, 0, selStart, 32); + this.drawTexturedModalRect(guiLeft + selStart + 28, guiTop - 28, selStart + 28, 0, + 168 - selStart - 28, 32 + ); + + if (clickedMainCategory >= 0 && clickedMainCategory < mainCategories.length) { + Category mainCategory = mainCategories[clickedMainCategory]; + + if (mouseX > guiLeft - 28 && mouseX < guiLeft) { + int offset = mouseY - (guiTop + 17); + if (offset > 0) { + int hovered = offset / 28 - 1; + if (hovered < 0) { + tooltipToRender = Utils.createList(mainCategory.displayName); + } else if (hovered < mainCategory.subcategories.length) { + tooltipToRender = Utils.createList(mainCategory.subcategories[hovered].displayName); + } + } + } + + for (int i = -1; i < mainCategory.subcategories.length; i++) { + if (i != clickedSubCategory) drawCategorySide(i); + } + } + } + + //Main GUI + Minecraft.getMinecraft().getTextureManager().bindTexture(creativeTabSearch); + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + this.drawTexturedModalRect(guiLeft, guiTop, 0, 0, getXSize(), ySplit); + int y = guiTop + ySplit; + for (int i = 0; i < splits; i++) { + this.drawTexturedModalRect(guiLeft, y, 0, ySplit, getXSize(), ySplit + ySplitSize); + y += ySplitSize; + } + this.drawTexturedModalRect(guiLeft, y, 0, ySplit, getXSize(), 136 - ySplit); + + //GUI Name + Utils.drawStringCenteredScaledMaxWidth("Auction House", Minecraft.getMinecraft().fontRendererObj, guiLeft + 42, + guiTop + 10, false, 68, 4210752 + ); + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + + //Categories + Minecraft.getMinecraft().getTextureManager().bindTexture(creativeInventoryTabs); + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + if (clickedMainCategory != -1) { + int selStart = clickedMainCategory * 28; + + this.drawTexturedModalRect(guiLeft + selStart, guiTop - 28, clickedMainCategory == 0 ? 0 : 28, 32, 28, 32); + + if (clickedMainCategory >= 0 && clickedMainCategory < mainCategories.length) { + Category mainCategory = mainCategories[clickedMainCategory]; + + if (clickedSubCategory >= -1 && clickedSubCategory < mainCategory.subcategories.length) { + drawCategorySide(clickedSubCategory); + } + } + } + + //Category icons + for (int i = 0; i < mainCategories.length; i++) { + Category category = mainCategories[i]; + Utils.drawItemStack(category.displayItem, guiLeft + 28 * i + 6, guiTop - 28 + 9); + } + if (clickedMainCategory >= 0 && clickedMainCategory < mainCategories.length) { + Category mainCategory = mainCategories[clickedMainCategory]; + + Utils.drawItemStack(mainCategory.displayItem, guiLeft - 19, guiTop + 23); + for (int i = 0; i < mainCategory.subcategories.length; i++) { + Utils.drawItemStack(mainCategory.subcategories[i].displayItem, guiLeft - 19, guiTop + 23 + 28 * (i + 1)); + } + } + + for (int i = 0; i < controls.length; i++) { + Utils.drawItemStack(controls[i], guiLeft + 9 + 18 * i, guiTop + 112 + 18 * splits); + if (mouseX > guiLeft + 9 + 18 * i && mouseX < guiLeft + 9 + 18 * i + 16) { + if (mouseY > guiTop + 112 + 18 * splits && mouseY < guiTop + 112 + 18 * splits + 16) { + tooltipToRender = getTooltipForControl(i); + } + } + } + + int totalItems = auctionIds.size(); + int itemsScroll = (int) Math.floor((totalItems * scrollAmount) / 9f) * 9; + + int maxItemScroll = Math.max(0, totalItems - (5 + splits) * 9); + itemsScroll = Math.min(itemsScroll, maxItemScroll); + + if (NotEnoughUpdates.INSTANCE.config.neuAuctionHouse.enableNeuAuctionHouse) { + out: + for (int i = 0; i < 5 + splits; i++) { + int itemY = guiTop + i * 18 + 18; + for (int j = 0; j < 9; j++) { + int itemX = guiLeft + j * 18 + 9; + int id = itemsScroll + i * 9 + j; + if (auctionIds.size() <= id) break out; + + try { + String aucid = sortedAuctionIds.get(id); + + GL11.glTranslatef(0, 0, 100); + ItemStack stack = manager.auctionManager.getAuctionItems().get(aucid).getStack(); + Utils.drawItemStack(stack, itemX, itemY); + GL11.glTranslatef(0, 0, -100); + + if (mouseX > itemX && mouseX < itemX + 16) { + if (mouseY > itemY && mouseY < itemY + 16) { + tooltipToRender = getTooltipForAucId(aucid); + } + } + } catch (Exception ignored) { + } + } + } + } + + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + searchField.drawTextBox(); + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); /*if(auctionIds.size() == 0 && searchField.getText().length() == 0) { drawRect(guiLeft+8, guiTop+17, guiLeft+170, guiTop+107+18*splits, @@ -910,1020 +970,1041 @@ public void drawScreen(int mouseX, int mouseY) { fr.drawString("Loading items...", guiLeft+(8+170-strWidth)/2, guiTop+(17+107+18*splits)/2, Color.BLACK.getRGB()); }*/ - Minecraft.getMinecraft().getTextureManager().bindTexture(creativeInventoryTabs); - GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); - this.drawTexturedModalRect(guiLeft + 175, guiTop + 18 + (int) ((95 + ySplitSize * 2) * scrollAmount), - 256 - (scrollClicked ? 12 : 24), 0, 12, 15); - - if (!NotEnoughUpdates.INSTANCE.config.neuAuctionHouse.enableNeuAuctionHouse) { - Utils.drawStringCentered(EnumChatFormatting.RED + "NEUAH is DISABLED! Enable in /neusettings.", - Minecraft.getMinecraft().fontRendererObj, guiLeft + getXSize() / 2, guiTop + getYSize() / 2 - 5, true, 0); - } - - if (tooltipToRender != null) { - List tooltipGray = new ArrayList<>(); - for (String line : tooltipToRender) { - tooltipGray.add(EnumChatFormatting.GRAY + line); - } - Utils.drawHoveringText(tooltipGray, mouseX, mouseY, width, - height, -1, Minecraft.getMinecraft().fontRendererObj); - } - float slideAmount = 1 - Math.max(0, Math.min(1, (System.currentTimeMillis() - lastGuiScreenSwitch) / 200f)); - int auctionViewLeft = guiLeft + getXSize() + 4 - (int) (slideAmount * (78 + 4)); - - // Price filter - if (!hasPopup && NotEnoughUpdates.INSTANCE.config.neuAuctionHouse.priceFiltering) { - // Price bid filter - priceFilterField.xPosition = auctionViewLeft + 18; - priceFilterField.yPosition = guiTop + 18; - - Minecraft.getMinecraft().getTextureManager().bindTexture(auction_price); - GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); - this.drawTexturedModalRect(auctionViewLeft, guiTop, 0, 0, 96, 83); - if (getPriceFilterAmount() == -1) { - priceFilterField.setTextColor(Color.RED.getRGB()); - } else { - priceFilterField.setTextColor(16777215); - } - priceFilterField.drawTextBox(); - - Utils.drawStringCenteredScaledMaxWidth("Price Filter", Minecraft.getMinecraft().fontRendererObj, - auctionViewLeft + 39, guiTop + 10, false, 70, 4210752); - - GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); - Minecraft.getMinecraft().getTextureManager().bindTexture(auction_view_buttons); - if (currentPriceFilterType == PriceFilter.Less) { - this.drawTexturedModalRect(auctionViewLeft + 16, guiTop + 32, 30, 16, 30, 16); - } else { - this.drawTexturedModalRect(auctionViewLeft + 16, guiTop + 32, 0, 16, 30, 16); - } - if (currentPriceFilterType == PriceFilter.Greater) { - this.drawTexturedModalRect(auctionViewLeft + 16 + 34, guiTop + 32, 30, 16, 30, 16); - } else { - this.drawTexturedModalRect(auctionViewLeft + 16 + 34, guiTop + 32, 0, 16, 30, 16); - } - if (currentPriceFilterType == PriceFilter.Equal) { - this.drawTexturedModalRect(auctionViewLeft + 16, guiTop + 50, 64, 32, 64, 16); - } else { - this.drawTexturedModalRect(auctionViewLeft + 16, guiTop + 50, 0, 32, 64, 16); - } - - FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; - Utils.drawStringCentered("<=", fr, auctionViewLeft + 16 + 15, guiTop + 32 + 8, false, - Color.BLACK.getRGB()); - Utils.drawStringCentered(">=", fr, auctionViewLeft + 16 + 34 + 15, guiTop + 32 + 8, false, - Color.BLACK.getRGB()); - Utils.drawStringCentered("==", fr, auctionViewLeft + 16 + 32, guiTop + 50 + 8, false, - Color.BLACK.getRGB()); - GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); - - // Bin average price filter - binPriceFilterField.xPosition = auctionViewLeft + 18; - binPriceFilterField.yPosition = guiTop + 18 + binPriceFilterYOffset; - - Minecraft.getMinecraft().getTextureManager().bindTexture(auction_price); - this.drawTexturedModalRect(auctionViewLeft, guiTop + binPriceFilterYOffset, 0, 0, 96, 83); - if (getBinPriceFilterAmount() == -1) { - binPriceFilterField.setTextColor(Color.RED.getRGB()); - } else { - binPriceFilterField.setTextColor(16777215); - } - binPriceFilterField.drawTextBox(); - - Utils.drawStringCenteredScaledMaxWidth("BIN Average Filter", Minecraft.getMinecraft().fontRendererObj, - auctionViewLeft + 39, guiTop + 10 + binPriceFilterYOffset, false, 70, 4210752); - - GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); - Minecraft.getMinecraft().getTextureManager().bindTexture(auction_view_buttons); - if (currentBinPriceFilterType == PriceFilter.Less) { - this.drawTexturedModalRect(auctionViewLeft + 16, guiTop + 32 + binPriceFilterYOffset, 30, 16, 30, 16); - } else { - this.drawTexturedModalRect(auctionViewLeft + 16, guiTop + 32 + binPriceFilterYOffset, 0, 16, 30, 16); - } - if (currentBinPriceFilterType == PriceFilter.Greater) { - this.drawTexturedModalRect(auctionViewLeft + 16 + 34, guiTop + 32 + binPriceFilterYOffset, 30, 16, 30, 16); - } else { - this.drawTexturedModalRect(auctionViewLeft + 16 + 34, guiTop + 32 + binPriceFilterYOffset, 0, 16, 30, 16); - } - if (currentBinPriceFilterType == PriceFilter.Equal) { - this.drawTexturedModalRect(auctionViewLeft + 16, guiTop + 50 + binPriceFilterYOffset, 64, 32, 64, 16); - } else { - this.drawTexturedModalRect(auctionViewLeft + 16, guiTop + 50 + binPriceFilterYOffset, 0, 32, 64, 16); - } - - Utils.drawStringCentered("<=", fr, auctionViewLeft + 16 + 15, guiTop + 32 + 8 + binPriceFilterYOffset, false, - Color.BLACK.getRGB()); - Utils.drawStringCentered(">=", fr, auctionViewLeft + 16 + 34 + 15, guiTop + 32 + 8 + binPriceFilterYOffset, false, - Color.BLACK.getRGB()); - Utils.drawStringCentered("==", fr, auctionViewLeft + 16 + 32, guiTop + 50 + 8 + binPriceFilterYOffset, false, - Color.BLACK.getRGB()); - GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); - } - } - - public List getTooltipForControl(int index) { - List lore = new ArrayList<>(); - if (index < 0 || index >= controls.length) return lore; - if (controls[index] == null) return lore; - - lore.add(controls[index].getDisplayName()); - String arrow = "\u25b6"; - String selPrefixNC = " " + arrow + " "; - String selPrefix = EnumChatFormatting.DARK_AQUA + selPrefixNC; - String unselPrefix = EnumChatFormatting.GRAY.toString(); - switch (index) { - case 0: - lore.add(""); - String gold = EnumChatFormatting.GOLD.toString(); - String gray = EnumChatFormatting.GRAY.toString(); - char s = 0x272A; - String[] linesDung = {"Show All", "Any Dungeon", - gold + s + gray + s + s + s + s, - gold + s + s + gray + s + s + s, - gold + s + s + s + gray + s + s, - gold + s + s + s + s + gray + s, - gold + s + s + s + s + s}; - for (int i = 0; i < linesDung.length; i++) { - String line = linesDung[i]; - if (i == dungeonFilter) { - line = selPrefix + line.replace(gray, EnumChatFormatting.DARK_AQUA.toString()); - } else { - line = unselPrefix + line; - } - lore.add(line); - } - lore.add(""); - lore.add(EnumChatFormatting.AQUA + "Right-Click to go backwards!"); - lore.add(EnumChatFormatting.YELLOW + "Click to switch sort!"); - return lore; - case 1: - lore.add(""); - String[] linesSort = {"Highest Bid", "Lowest Bid", "Ending soon"}; - for (int i = 0; i < linesSort.length; i++) { - String line = linesSort[i]; - if (i == sortMode) { - line = selPrefix + line; - } else { - line = unselPrefix + line; - } - lore.add(line); - } - lore.add(""); - lore.add(EnumChatFormatting.YELLOW + "Click to switch sort!"); - return lore; - case 2: - lore.add(""); - lore.add((rarityFilter == -1 ? EnumChatFormatting.DARK_GRAY + selPrefixNC : unselPrefix) + "No Filter"); - - for (int i = 0; i < Utils.rarityArr.length; i++) { - lore.add((rarityFilter == i ? rarityColours[i] + selPrefixNC : unselPrefix) + - Utils.prettyCase(Utils.rarityArr[i])); - } - lore.add(""); - lore.add(EnumChatFormatting.AQUA + "Right-Click to go backwards!"); - lore.add(EnumChatFormatting.YELLOW + "Click to switch filter!"); - return lore; - case 3: - break; - case 4: - lore.add(""); - String off = EnumChatFormatting.RED + "OFF"; - String on = EnumChatFormatting.GREEN + "ON"; - lore.add(unselPrefix + "Filter Own Auctions: " + (filterMyAuctions ? on : off)); - lore.add(""); - lore.add(EnumChatFormatting.YELLOW + "Click to toggle!"); - return lore; - case 5: - break; - case 6: - lore.add(""); - String[] linesBin = {"Show All", "BIN Only", "Auctions Only"}; - for (int i = 0; i < linesBin.length; i++) { - String line = linesBin[i]; - if (i == binFilter) { - line = selPrefix + line; - } else { - line = unselPrefix + line; - } - lore.add(line); - } - lore.add(""); - lore.add(EnumChatFormatting.AQUA + "Right-Click to go backwards!"); - lore.add(EnumChatFormatting.YELLOW + "Click to switch filter!"); - return lore; - case 7: - lore.add(""); - String[] linesEnch = {"Show All", "Clean Only", "Ench Only", "Ench/HPB Only"}; - for (int i = 0; i < linesEnch.length; i++) { - String line = linesEnch[i]; - if (i == enchFilter) { - line = selPrefix + line; - } else { - line = unselPrefix + line; - } - lore.add(line); - } - lore.add(""); - lore.add(EnumChatFormatting.AQUA + "Right-Click to go backwards!"); - lore.add(EnumChatFormatting.YELLOW + "Click to switch filter!"); - return lore; - case 8: - lore.add(""); - lore.add("Current aucid: " + currentAucId); - if (currentAucId != null) { - APIManager.Auction auc = manager.auctionManager.getAuctionItems().get(currentAucId); - if (auc != null) { - lore.add("Current auc category: " + auc.category); - } - } - lore.add(" --- Processing"); - lore.add("Page Process Millis: " + manager.auctionManager.processMillis); - lore.add(" --- Auction Stats"); - lore.add("Active Auctions: " + manager.auctionManager.activeAuctions); - lore.add("Tracked Auctions: " + manager.auctionManager.getAuctionItems().size()); - lore.add("Displayed Auctions: " + auctionIds.size()); - lore.add("Tracked Player Auctions: " + manager.auctionManager.getPlayerBids().size()); - lore.add("Unique Items: " + manager.auctionManager.uniqueItems); - lore.add("ID Tagged Auctions: " + manager.auctionManager.internalnameTaggedAuctions); - lore.add("Total Tags: " + manager.auctionManager.totalTags); - lore.add("Tagged Auctions: " + manager.auctionManager.taggedAuctions); - lore.add(""); - lore.add(EnumChatFormatting.AQUA + "Right-Click to copy current aucid to clipboard!"); - lore.add(EnumChatFormatting.YELLOW + "Click to refresh!"); - return lore; - } - return new ArrayList<>(); - } - - public void handleMouseInput() { - if (!NotEnoughUpdates.INSTANCE.config.neuAuctionHouse.enableNeuAuctionHouse) { - return; - } - - ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); - int width = scaledResolution.getScaledWidth(); - int height = scaledResolution.getScaledHeight(); - - int mouseX = Mouse.getEventX() * width / Minecraft.getMinecraft().displayWidth; - int mouseY = height - Mouse.getEventY() * height / Minecraft.getMinecraft().displayHeight - 1; - int mouseButton = Mouse.getEventButton(); - - if (Mouse.getEventButtonState()) { - this.eventButton = mouseButton; - this.lastMouseEvent = Minecraft.getSystemTime(); - mouseClicked(mouseX, mouseY, this.eventButton); - } else if (mouseButton != -1) { - this.eventButton = -1; - mouseReleased(mouseX, mouseY, mouseButton); - } else if (this.eventButton != -1 && this.lastMouseEvent > 0L) { - long l = Minecraft.getSystemTime() - this.lastMouseEvent; - mouseClickMove(mouseX, mouseY, this.eventButton, l); - } - - if (!NotEnoughUpdates.INSTANCE.config.neuAuctionHouse.disableAhScroll) { - int dWheel = Mouse.getEventDWheel(); - dWheel = Math.max(-1, Math.min(1, dWheel)); - - scrollAmount = scrollAmount - dWheel / (float) (auctionIds.size() / 9 - (5 + splits)); - scrollAmount = Math.max(0, Math.min(1, scrollAmount)); - } - } - - public String niceAucId(String aucId) { - if (aucId.length() != 32) return aucId; - - StringBuilder niceAucId = new StringBuilder(); - niceAucId.append(aucId, 0, 8); - niceAucId.append("-"); - niceAucId.append(aucId, 8, 12); - niceAucId.append("-"); - niceAucId.append(aucId, 12, 16); - niceAucId.append("-"); - niceAucId.append(aucId, 16, 20); - niceAucId.append("-"); - niceAucId.append(aucId, 20, 32); - return niceAucId.toString(); - } - - public Category getCurrentCategory() { - if (clickedMainCategory < 0 || clickedMainCategory >= mainCategories.length) { - return null; - } - Category mainCategory = mainCategories[clickedMainCategory]; - if (clickedSubCategory < 0 || clickedSubCategory >= mainCategory.subcategories.length) { - return mainCategory; - } - return mainCategory.subcategories[clickedSubCategory]; - } - - private boolean doesAucMatch(APIManager.Auction auc) { - if (auc == null) return false; - - Category currentCategory = getCurrentCategory(); - - boolean match = true; - if (currentCategory != null) { - match = false; - String[] categories = currentCategory.getTotalCategories(); - for (String category : categories) { - match |= category.equalsIgnoreCase(auc.category); - } - } - - if (rarityFilter >= 0 && rarityFilter < Utils.rarityArr.length) { - match &= Utils.rarityArr[rarityFilter].equals(auc.rarity); - } - - if (binFilter == BIN_FILTER_BIN) { - match &= auc.bin; - } else if (binFilter == BIN_FILTER_AUC) { - match &= !auc.bin; - } - - if (enchFilter > ENCH_FILTER_ALL) { - switch (enchFilter) { - case ENCH_FILTER_CLEAN: - match &= auc.enchLevel == 0; - break; - case ENCH_FILTER_ENCH: - match &= auc.enchLevel >= 1; - break; - case ENCH_FILTER_ENCHHPB: - match &= auc.enchLevel == 2; - break; - } - } - - if (dungeonFilter > DUNGEON_FILTER_ALL) { - if (dungeonFilter == DUNGEON_FILTER_DUNGEON && auc.dungeonTier < 0) { - match = false; - } else { - match &= dungeonFilter == auc.dungeonTier + 1; - } - } - - if (getPriceFilterAmount() > -1) { - if (currentPriceFilterType == PriceFilter.Greater) { - match &= auc.highest_bid_amount != 0 ? (auc.highest_bid_amount >= getPriceFilterAmount()) : auc.starting_bid >= getPriceFilterAmount(); - } - if (currentPriceFilterType == PriceFilter.Less) { - match &= auc.highest_bid_amount != 0 ? (auc.highest_bid_amount <= getPriceFilterAmount()) : auc.starting_bid <= getPriceFilterAmount(); - } - if (currentPriceFilterType == PriceFilter.Equal) { - match &= auc.highest_bid_amount != 0 ? (auc.highest_bid_amount == getPriceFilterAmount()) : auc.starting_bid == getPriceFilterAmount(); - } - } - if (getBinPriceFilterAmount() > -1) { - int lowestBin = NotEnoughUpdates.INSTANCE.manager.auctionManager.getLowestBin(NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(auc.getStack())); - if (lowestBin > 0) { - if (currentBinPriceFilterType == PriceFilter.Greater) { - match &= lowestBin >= getBinPriceFilterAmount(); - } - if (currentBinPriceFilterType == PriceFilter.Less) { - match &= lowestBin <= getBinPriceFilterAmount(); - } - if (currentBinPriceFilterType == PriceFilter.Equal) { - match &= lowestBin == getBinPriceFilterAmount(); - } - } else { - match = false; - } - } - return match; - } - - private HashSet search(String query, Set dontMatch) { - query = query.trim(); - HashSet matches = new HashSet<>(); - - Set itemMatches = manager.search(query); - for (String internalname : itemMatches) { - for (String aucid : manager.auctionManager.getAuctionsForInternalname(internalname)) { - APIManager.Auction auc = manager.auctionManager.getAuctionItems().get(aucid); - if (doesAucMatch(auc)) { - //matches.add(aucid); - } else { - dontMatch.add(aucid); - } - } - } - - HashMap> extrasMatches = new HashMap<>(); - HashMap> extrasMatchesCurrent = new HashMap<>(); - boolean first = true; - for (String subQuery : query.split(" ")) { - for (HashMap> extrasMap : manager.subMapWithKeysThatAreSuffixes(subQuery.toLowerCase(), - manager.auctionManager.extrasToAucIdMap).values()) { - for (int index : extrasMap.keySet()) { - for (String aucid : extrasMap.get(index)) { - APIManager.Auction auc = manager.auctionManager.getAuctionItems().get(aucid); - if (!dontMatch.contains(aucid) && doesAucMatch(auc)) { - if (first) { - List indexList = extrasMatchesCurrent.computeIfAbsent(aucid, k -> new ArrayList<>()); - indexList.add(index); - } else { - List indexList = extrasMatches.computeIfAbsent(aucid, k -> new ArrayList<>()); - if (indexList.contains(index - 1)) { - List indexListCurrent = extrasMatchesCurrent.computeIfAbsent(aucid, k -> new ArrayList<>()); - indexListCurrent.add(index); - } - } - } else { - dontMatch.add(aucid); - } - } - } - - } - - extrasMatches = (HashMap>) extrasMatchesCurrent.clone(); - extrasMatchesCurrent.clear(); - first = false; - } - matches.addAll(extrasMatches.keySet()); - - return matches; - } - - private ExecutorService es = Executors.newSingleThreadExecutor(); - - public void updateSearch() { - if (!NotEnoughUpdates.INSTANCE.config.neuAuctionHouse.enableNeuAuctionHouse) { - return; - } - - if (searchField == null || priceField == null || priceFilterField == null || binPriceFilterField == null) - init(); - long currentTime = System.currentTimeMillis(); - - es.submit(() -> { - if (currentTime - lastUpdateSearch < 100) { - shouldUpdateSearch = true; - return; - } - - lastUpdateSearch = currentTime; - shouldUpdateSearch = false; - - scrollAmount = 0; - try { - HashSet auctionIdsNew = new HashSet<>(); - auctionIdsNew.clear(); - if (filterMyAuctions) { - for (String aucid : manager.auctionManager.getPlayerBids()) { - APIManager.Auction auc = manager.auctionManager.getAuctionItems().get(aucid); - if (doesAucMatch(auc)) { - auctionIdsNew.add(aucid); - } - } - } else if (searchField.getText().length() == 0) { - for (Map.Entry entry : manager.auctionManager.getAuctionItems().entrySet()) { - if (doesAucMatch(entry.getValue())) { - auctionIdsNew.add(entry.getKey()); - } - } - } else { - String query = searchField.getText(); - Set dontMatch = new HashSet<>(); - - HashSet allMatch = new HashSet<>(); - if (query.contains("!")) { //only used for inverted queries, so dont need to populate unless ! in query - for (Map.Entry entry : manager.auctionManager.getAuctionItems().entrySet()) { - if (doesAucMatch(entry.getValue())) { - allMatch.add(entry.getKey()); - } else { - dontMatch.add(entry.getKey()); - } - } - } - - boolean invert = false; - - StringBuilder query2 = new StringBuilder(); - char lastOp = '|'; - for (char c : query.toCharArray()) { - if (query2.toString().trim().isEmpty() && c == '!') { - invert = true; - } else if (c == '|' || c == '&') { - if (lastOp == '|') { - HashSet result = search(query2.toString(), dontMatch); - if (!invert) { - auctionIdsNew.addAll(result); - } else { - HashSet allClone = (HashSet) allMatch.clone(); - allClone.removeAll(result); - auctionIdsNew.addAll(allClone); - } - } else if (lastOp == '&') { - HashSet result = search(query2.toString(), dontMatch); - if (!invert) { - auctionIdsNew.retainAll(result); - } else { - auctionIdsNew.removeAll(result); - } - } - - query2 = new StringBuilder(); - invert = false; - lastOp = c; - } else { - query2.append(c); - } - } - if (lastOp == '|') { - HashSet result = search(query2.toString(), dontMatch); - if (!invert) { - auctionIdsNew.addAll(result); - } else { - HashSet allClone = (HashSet) allMatch.clone(); - allClone.removeAll(result); - auctionIdsNew.addAll(allClone); - } - } else if (lastOp == '&') { - HashSet result = search(query2.toString(), dontMatch); - if (!invert) { - auctionIdsNew.retainAll(result); - } else { - auctionIdsNew.removeAll(result); - } - } - } - auctionIds = auctionIdsNew; - sortItems(); - } catch (Exception e) { - shouldUpdateSearch = true; - } - }); - } - - public void sortItems() throws ConcurrentModificationException { - if (!NotEnoughUpdates.INSTANCE.config.neuAuctionHouse.enableNeuAuctionHouse) { - return; - } - - try { - List sortedAuctionIdsNew = new ArrayList<>(); - - sortedAuctionIdsNew.addAll(auctionIds); - sortedAuctionIdsNew.sort((o1, o2) -> { - APIManager.Auction auc1 = manager.auctionManager.getAuctionItems().get(o1); - APIManager.Auction auc2 = manager.auctionManager.getAuctionItems().get(o2); - - if (auc1 == null) return 1; - if (auc2 == null) return -1; - - if (sortMode == SORT_MODE_HIGH) { - int price1 = Math.max(auc1.highest_bid_amount, auc1.starting_bid); - int price2 = Math.max(auc2.highest_bid_amount, auc2.starting_bid); - int diff = price2 - price1; - if (diff != 0) { - return diff; - } - } else if (sortMode == SORT_MODE_LOW) { - int price1 = Math.max(auc1.highest_bid_amount, auc1.starting_bid); - int price2 = Math.max(auc2.highest_bid_amount, auc2.starting_bid); - int diff = price1 - price2; - if (diff != 0) { - return diff; - } - } else { - long end1 = auc1.end; - long end2 = auc2.end; - - if (end1 < System.currentTimeMillis()) return 999999; - if (end2 < System.currentTimeMillis()) return -999999; - - int diff = (int) (end1 - end2); - if (diff != 0) { - return diff; - } - } - return o1.compareTo(o2); - }); - - sortedAuctionIds = sortedAuctionIdsNew; - } catch (Exception e) { - shouldSortItems = true; - } - } - - public boolean keyboardInput() { - if (!NotEnoughUpdates.INSTANCE.config.neuAuctionHouse.enableNeuAuctionHouse) { - return false; - } - - Keyboard.enableRepeatEvents(true); - if (isEditingPrice() && Keyboard.getEventKey() == Keyboard.KEY_RETURN) { - Minecraft.getMinecraft().displayGuiScreen(null); - } else if (Keyboard.getEventKey() == Keyboard.KEY_ESCAPE) { - if (Minecraft.getMinecraft().currentScreen instanceof GuiEditSign) { - priceField.setText(""); - GuiEditSign editSign = (GuiEditSign) Minecraft.getMinecraft().currentScreen; - TileEntitySign tes = (TileEntitySign) Utils.getField(GuiEditSign.class, editSign, - "tileSign", "field_146848_f"); - tes.lineBeingEdited = 0; - tes.signText[0] = new ChatComponentText(priceField.getText()); - } - return false; - } - if (Keyboard.getEventKeyState()) return keyTyped(Keyboard.getEventCharacter(), Keyboard.getEventKey()); - return true; - } - - public boolean keyTyped(char typedChar, int keyCode) { - if (searchField == null || priceField == null || priceFilterField == null || binPriceFilterField == null) - init(); - - if (!isEditingPrice()) { - if (this.priceFilterField.textboxKeyTyped(typedChar, keyCode)) { - this.updateSearch(); - return true; - } - if (this.binPriceFilterField.textboxKeyTyped(typedChar, keyCode)) { - this.updateSearch(); - return true; - } - if (this.searchField.textboxKeyTyped(typedChar, keyCode)) { - lastSearchFieldUpdate = System.currentTimeMillis(); - this.updateSearch(); - return true; - } - } else { - if (!priceField.isFocused()) priceField.setFocused(searchField.isFocused() && priceFilterField.isFocused()); - return priceField.textboxKeyTyped(typedChar, keyCode); - } - return false; - } - - private void increasePriceByFactor(float factor) { - String price = priceField.getText().trim(); - StringBuilder priceNumbers = new StringBuilder(); - for (int i = 0; i < price.length(); i++) { - char c = price.charAt(i); - if ((int) c >= 48 && (int) c <= 57) { - priceNumbers.append(c); - } else { - break; - } - } - int priceI = 0; - if (priceNumbers.length() > 0) { - priceI = Integer.parseInt(priceNumbers.toString()); - } - String end = price.substring(priceNumbers.length()); - priceField.setText((int) (priceI * factor) + end); - } - - private int getPriceFilterAmount() { - return getNumberFromTextBox(priceFilterField); - } - - private int getNumberFromTextBox(GuiTextField textField) { - if (textField.getText().equals("")) { - return -2; - } - try { - int parsed = Integer.parseInt(textField.getText()); - if (parsed < 0) { - return -1; - } - return parsed; - } catch (NumberFormatException e) { - return -1; - } - } - - private int getBinPriceFilterAmount() { - return getNumberFromTextBox(binPriceFilterField); - } - - protected void mouseClicked(int mouseX, int mouseY, int mouseButton) { - boolean wasFocused = searchField.isFocused(); - searchField.mouseClicked(mouseX, mouseY, mouseButton); - if (mouseButton == 1 && !wasFocused && searchField.isFocused()) { - searchField.setText(""); - } - priceField.mouseClicked(mouseX, mouseY, mouseButton); - priceFilterField.mouseClicked(mouseX, mouseY, mouseButton); - binPriceFilterField.mouseClicked(mouseX, mouseY, mouseButton); - - int totalItems = auctionIds.size(); - int itemsScroll = (int) Math.floor((totalItems * scrollAmount) / 9f) * 9; - - int maxItemScroll = Math.max(0, totalItems - (5 + splits) * 9); - itemsScroll = Math.min(itemsScroll, maxItemScroll); - - //Categories - if (mouseY > guiTop - 28 && mouseY < guiTop + 4) { - if (mouseX > guiLeft && mouseX < guiLeft + 168) { - int offset = mouseX - guiLeft; - int clickedCat = offset / 28; - if (clickedMainCategory == clickedCat) { - clickedMainCategory = -1; - } else { - clickedMainCategory = clickedCat; - } - clickedSubCategory = -1; - updateSearch(); - Utils.playPressSound(); - return; - } - } - - if (clickedMainCategory >= 0 && clickedMainCategory < mainCategories.length) { - Category mainCategory = mainCategories[clickedMainCategory]; - - if (mouseX > guiLeft - 28 && mouseX < guiLeft) { - int offset = mouseY - (guiTop + 17); - if (offset > 0) { - int clicked = offset / 28 - 1; - if (clicked != clickedSubCategory && clicked < mainCategory.subcategories.length) { - clickedSubCategory = clicked; - updateSearch(); - Utils.playPressSound(); - return; - } - } - } - } - - if (mouseY > guiTop + 112 + 18 * splits && mouseY < guiTop + 112 + 18 * splits + 16) { - if (mouseX > guiLeft + 9 && mouseX < guiLeft + 9 + controls.length * 18 - 2) { - int offset = mouseX - (guiLeft + 9); - int index = offset / 18; - boolean rightClicked = Mouse.getEventButton() == 1; - switch (index) { - case 0: - if (rightClicked) { - dungeonFilter--; - if (dungeonFilter < DUNGEON_FILTER_ALL) dungeonFilter = DUNGEON_FILTER_5; - } else { - dungeonFilter++; - if (dungeonFilter > DUNGEON_FILTER_5) dungeonFilter = DUNGEON_FILTER_ALL; - } - break; - case 1: - if (rightClicked) { - sortMode--; - if (sortMode < SORT_MODE_HIGH) sortMode = SORT_MODE_SOON; - } else { - sortMode++; - if (sortMode > SORT_MODE_SOON) sortMode = SORT_MODE_HIGH; - } - break; - case 2: - if (rightClicked) { - rarityFilter--; - if (rarityFilter < -1) rarityFilter = Utils.rarityArr.length - 1; - } else { - rarityFilter++; - if (rarityFilter >= Utils.rarityArr.length) rarityFilter = -1; - } - break; - case 3: - break; - case 4: - filterMyAuctions = !filterMyAuctions; - break; - case 5: - break; - case 6: - if (rightClicked) { - binFilter--; - if (binFilter < BIN_FILTER_ALL) binFilter = BIN_FILTER_AUC; - } else { - binFilter++; - if (binFilter > BIN_FILTER_AUC) binFilter = BIN_FILTER_ALL; - } - break; - case 7: - if (rightClicked) { - enchFilter--; - if (enchFilter < ENCH_FILTER_ALL) enchFilter = ENCH_FILTER_ENCHHPB; - } else { - enchFilter++; - if (enchFilter > ENCH_FILTER_ENCHHPB) enchFilter = ENCH_FILTER_ALL; - } - break; - case 8: - if (rightClicked) { - if (currentAucId != null) { - StringSelection selection = new StringSelection(niceAucId(currentAucId)); - Toolkit.getDefaultToolkit().getSystemClipboard().setContents(selection, selection); - } - } else { - manager.auctionManager.calculateStats(); - } - } - updateSearch(); - Utils.playPressSound(); - } - } - boolean hasPopup = false; - if (mouseButton == 0 && Minecraft.getMinecraft().currentScreen instanceof GuiChest) { - hasPopup = true; - GuiChest auctionView = (GuiChest) Minecraft.getMinecraft().currentScreen; - ContainerChest container = (ContainerChest) auctionView.inventorySlots; - String containerName = container.getLowerChestInventory().getDisplayName().getUnformattedText(); - - - if (containerName.trim().equals("Auction View") || containerName.trim().equals("BIN Auction View")) { - - if (mouseX > guiLeft + getXSize() + 4 + 31 && mouseX < guiLeft + getXSize() + 4 + 31 + 16) { - boolean leftFiller = isGuiFiller(auctionView.inventorySlots.getSlot(29).getStack());//isBin - if (mouseY > guiTop + 35 && mouseY < guiTop + 35 + 16) { - ItemStack topStack = auctionView.inventorySlots.getSlot(13).getStack(); - if (topStack != null) { - String line = findStrStart(topStack, EnumChatFormatting.GRAY + "Seller: "); - String[] split = line.split(" "); - String seller = split[split.length - 1]; - StringSelection selection = new StringSelection(seller); - Toolkit.getDefaultToolkit().getSystemClipboard().setContents(selection, selection); - } - } else if (mouseY > guiTop + 100 && mouseY < guiTop + 100 + 16) { - int slotClick = leftFiller ? 31 : 29; - Minecraft.getMinecraft().playerController.windowClick(auctionView.inventorySlots.windowId, - slotClick, 2, 3, Minecraft.getMinecraft().thePlayer); - - if (!leftFiller) { - if (auctionView.inventorySlots.getSlot(29).getStack() - .getDisplayName().trim().equals(EnumChatFormatting.GOLD + "Collect Auction")) { - manager.auctionManager.getPlayerBids().remove(currentAucId); - auctionIds.remove(currentAucId); - } - } - - Utils.playPressSound(); - } else if (mouseY > guiTop + 126 && mouseY < guiTop + 126 + 16 && !leftFiller) { - priceField.setFocused(true); - Minecraft.getMinecraft().playerController.windowClick(auctionView.inventorySlots.windowId, - 31, 2, 3, Minecraft.getMinecraft().thePlayer); - Utils.playPressSound(); - } - } - } else if (containerName.trim().equals("Confirm Bid") || containerName.trim().equals("Confirm Purchase")) { - if (mouseX > guiLeft + getXSize() + 4 + 31 && mouseX < guiLeft + getXSize() + 4 + 31 + 16) { - if (mouseY > guiTop + 31 && mouseY < guiTop + 31 + 16) { - if (currentAucId != null) { - manager.auctionManager.getPlayerBids().add(currentAucId); - latestBid = currentAucId; - latestBidMillis = System.currentTimeMillis(); - //reset timer to 2m if below - if (manager.auctionManager.getAuctionItems().get(currentAucId) != null && - manager.auctionManager.getAuctionItems().get(currentAucId).end - - System.currentTimeMillis() < 2 * 60 * 1000) { - manager.auctionManager.getAuctionItems().get(currentAucId).end = - System.currentTimeMillis() + 2 * 60 * 1000; - } - } - Minecraft.getMinecraft().playerController.windowClick(auctionView.inventorySlots.windowId, - 11, 2, 3, Minecraft.getMinecraft().thePlayer); - } else if (mouseY > guiTop + 125 && mouseY < guiTop + 125 + 16) { - Minecraft.getMinecraft().playerController.windowClick(auctionView.inventorySlots.windowId, - 15, 2, 3, Minecraft.getMinecraft().thePlayer); - } - Utils.playPressSound(); - } - } - } - int auctionViewLeft = guiLeft + getXSize() + 4; - - if (mouseButton == 0 && isEditingPrice()) { - - if (mouseX > auctionViewLeft + 16 && mouseX < auctionViewLeft + 16 + 64) { - if (mouseY > guiTop + 32 && mouseY < guiTop + 32 + 16) { - if (mouseX < auctionViewLeft + 16 + 32) { - //top left - increasePriceByFactor(2); - Utils.playPressSound(); - } else { - //top right - increasePriceByFactor(1.5f); - Utils.playPressSound(); - } - } else if (mouseY > guiTop + 50 && mouseY < guiTop + 50 + 16) { - if (mouseX < auctionViewLeft + 16 + 32) { - //mid left - increasePriceByFactor(1.25f); - Utils.playPressSound(); - } else { - //mid right - increasePriceByFactor(1.1f); - Utils.playPressSound(); - } - } else if (mouseY > guiTop + 68 && mouseY < guiTop + 68 + 16) { - //bottom - Utils.playPressSound(); - Minecraft.getMinecraft().displayGuiScreen(null); - } - } - - this.drawTexturedModalRect(auctionViewLeft + 16, guiTop + 32, 0, 16, 30, 16); - this.drawTexturedModalRect(auctionViewLeft + 16 + 34, guiTop + 32, 0, 16, 30, 16); - this.drawTexturedModalRect(auctionViewLeft + 16, guiTop + 50, 0, 16, 30, 16); - this.drawTexturedModalRect(auctionViewLeft + 16 + 34, guiTop + 50, 0, 16, 30, 16); - this.drawTexturedModalRect(auctionViewLeft + 16, guiTop + 68, 0, 32, 64, 16); - } else if (!hasPopup && NotEnoughUpdates.INSTANCE.config.neuAuctionHouse.priceFiltering) { - - if (mouseX > auctionViewLeft + 16 && mouseX < auctionViewLeft + 16 + 64) { - if (mouseY > guiTop + 32 && mouseY < guiTop + 32 + 16) { - if (mouseX < auctionViewLeft + 16 + 32) { - //top left - currentPriceFilterType = PriceFilter.Less; - } else { - //top right - currentPriceFilterType = PriceFilter.Greater; - } - Utils.playPressSound(); - updateSearch(); - } else if (mouseY > guiTop + 50 && mouseY < guiTop + 50 + 16) { - //middle - currentPriceFilterType = PriceFilter.Equal; - Utils.playPressSound(); - updateSearch(); - } - } - - if (mouseX > auctionViewLeft + 16 && mouseX < auctionViewLeft + 16 + 64) { - if (mouseY > guiTop + 32 + binPriceFilterYOffset && mouseY < guiTop + 32 + 16 + binPriceFilterYOffset) { - if (mouseX < auctionViewLeft + 16 + 32) { - //top left - currentBinPriceFilterType = PriceFilter.Less; - } else { - //top right - currentBinPriceFilterType = PriceFilter.Greater; - } - Utils.playPressSound(); - updateSearch(); - } else if (mouseY > guiTop + 50 + binPriceFilterYOffset && mouseY < guiTop + 50 + 16 + binPriceFilterYOffset) { - //middle - currentBinPriceFilterType = PriceFilter.Equal; - Utils.playPressSound(); - updateSearch(); - } - } - } - out: - for (int i = 0; i < 5 + splits; i++) { - int itemY = guiTop + i * 18 + 18; - for (int j = 0; j < 9; j++) { - int itemX = guiLeft + j * 18 + 9; - int id = itemsScroll + i * 9 + j; - if (auctionIds.size() <= id) break out; - - String aucid; - try { - aucid = sortedAuctionIds.get(id); - } catch (IndexOutOfBoundsException e) { - break out; - } - - if (aucid == null) continue; - APIManager.Auction auc = manager.auctionManager.getAuctionItems().get(aucid); - if (auc != null) { - if (mouseX > itemX && mouseX < itemX + 16) { - if (mouseY > itemY && mouseY < itemY + 16) { - if (Minecraft.getMinecraft().currentScreen instanceof GuiEditSign) { - priceField.setText(""); - GuiEditSign editSign = (GuiEditSign) Minecraft.getMinecraft().currentScreen; - TileEntitySign tes = (TileEntitySign) Utils.getField(GuiEditSign.class, editSign, - "tileSign", "field_146848_f"); - tes.lineBeingEdited = 0; - tes.signText[0] = new ChatComponentText(priceField.getText()); - } - startingBid = Math.max(auc.starting_bid, auc.highest_bid_amount); - currAucIdSetTimer = System.currentTimeMillis(); - currentAucId = aucid; - - Minecraft.getMinecraft().thePlayer.sendChatMessage("/viewauction " + niceAucId(aucid)); - Utils.playPressSound(); - } - } - } - } - } - - int y = guiTop + 18 + (int) ((95 + ySplitSize * 2) * scrollAmount); - if (mouseX > guiLeft + 175 && mouseX < guiLeft + 175 + 12) { - if (mouseY > y && mouseY < y + 15) { - scrollClicked = true; - return; - } - } - scrollClicked = false; - } - - protected void mouseReleased(int mouseX, int mouseY, int state) { - scrollClicked = false; - } - - protected void mouseClickMove(int mouseX, int mouseY, int clickedMouseButton, long timeSinceLastClick) { - if (scrollClicked) { - int yMin = guiTop + 18 + 8; - int yMax = guiTop + 18 + (95 + ySplitSize * 2) + 8; - - scrollAmount = (mouseY - yMin) / (float) (yMax - yMin); - scrollAmount = Math.max(0, Math.min(1, scrollAmount)); - } - } + Minecraft.getMinecraft().getTextureManager().bindTexture(creativeInventoryTabs); + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + this.drawTexturedModalRect(guiLeft + 175, guiTop + 18 + (int) ((95 + ySplitSize * 2) * scrollAmount), + 256 - (scrollClicked ? 12 : 24), 0, 12, 15 + ); + + if (!NotEnoughUpdates.INSTANCE.config.neuAuctionHouse.enableNeuAuctionHouse) { + Utils.drawStringCentered(EnumChatFormatting.RED + "NEUAH is DISABLED! Enable in /neu.", + Minecraft.getMinecraft().fontRendererObj, guiLeft + getXSize() / 2, guiTop + getYSize() / 2 - 5, true, 0 + ); + } + + if (tooltipToRender != null) { + List tooltipGray = new ArrayList<>(); + for (String line : tooltipToRender) { + tooltipGray.add(EnumChatFormatting.GRAY + line); + } + Utils.drawHoveringText(tooltipGray, mouseX, mouseY, width, + height, -1, Minecraft.getMinecraft().fontRendererObj + ); + } + float slideAmount = 1 - Math.max(0, Math.min(1, (System.currentTimeMillis() - lastGuiScreenSwitch) / 200f)); + int auctionViewLeft = guiLeft + getXSize() + 4 - (int) (slideAmount * (78 + 4)); + + // Price filter + if (!hasPopup && NotEnoughUpdates.INSTANCE.config.neuAuctionHouse.priceFiltering) { + // Price bid filter + priceFilterField.xPosition = auctionViewLeft + 18; + priceFilterField.yPosition = guiTop + 18; + + Minecraft.getMinecraft().getTextureManager().bindTexture(auction_price); + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + this.drawTexturedModalRect(auctionViewLeft, guiTop, 0, 0, 96, 83); + if (getPriceFilterAmount() == -1) { + priceFilterField.setTextColor(Color.RED.getRGB()); + } else { + priceFilterField.setTextColor(16777215); + } + priceFilterField.drawTextBox(); + + Utils.drawStringCenteredScaledMaxWidth("Price Filter", Minecraft.getMinecraft().fontRendererObj, + auctionViewLeft + 39, guiTop + 10, false, 70, 4210752 + ); + + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + Minecraft.getMinecraft().getTextureManager().bindTexture(auction_view_buttons); + if (currentPriceFilterType == PriceFilter.Less) { + this.drawTexturedModalRect(auctionViewLeft + 16, guiTop + 32, 30, 16, 30, 16); + } else { + this.drawTexturedModalRect(auctionViewLeft + 16, guiTop + 32, 0, 16, 30, 16); + } + if (currentPriceFilterType == PriceFilter.Greater) { + this.drawTexturedModalRect(auctionViewLeft + 16 + 34, guiTop + 32, 30, 16, 30, 16); + } else { + this.drawTexturedModalRect(auctionViewLeft + 16 + 34, guiTop + 32, 0, 16, 30, 16); + } + if (currentPriceFilterType == PriceFilter.Equal) { + this.drawTexturedModalRect(auctionViewLeft + 16, guiTop + 50, 64, 32, 64, 16); + } else { + this.drawTexturedModalRect(auctionViewLeft + 16, guiTop + 50, 0, 32, 64, 16); + } + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + Utils.drawStringCentered("<=", fr, auctionViewLeft + 16 + 15, guiTop + 32 + 8, false, + Color.BLACK.getRGB() + ); + Utils.drawStringCentered(">=", fr, auctionViewLeft + 16 + 34 + 15, guiTop + 32 + 8, false, + Color.BLACK.getRGB() + ); + Utils.drawStringCentered("==", fr, auctionViewLeft + 16 + 32, guiTop + 50 + 8, false, + Color.BLACK.getRGB() + ); + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + + // Bin average price filter + binPriceFilterField.xPosition = auctionViewLeft + 18; + binPriceFilterField.yPosition = guiTop + 18 + binPriceFilterYOffset; + + Minecraft.getMinecraft().getTextureManager().bindTexture(auction_price); + this.drawTexturedModalRect(auctionViewLeft, guiTop + binPriceFilterYOffset, 0, 0, 96, 83); + if (getBinPriceFilterAmount() == -1) { + binPriceFilterField.setTextColor(Color.RED.getRGB()); + } else { + binPriceFilterField.setTextColor(16777215); + } + binPriceFilterField.drawTextBox(); + + Utils.drawStringCenteredScaledMaxWidth("BIN Average Filter", Minecraft.getMinecraft().fontRendererObj, + auctionViewLeft + 39, guiTop + 10 + binPriceFilterYOffset, false, 70, 4210752 + ); + + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + Minecraft.getMinecraft().getTextureManager().bindTexture(auction_view_buttons); + if (currentBinPriceFilterType == PriceFilter.Less) { + this.drawTexturedModalRect(auctionViewLeft + 16, guiTop + 32 + binPriceFilterYOffset, 30, 16, 30, 16); + } else { + this.drawTexturedModalRect(auctionViewLeft + 16, guiTop + 32 + binPriceFilterYOffset, 0, 16, 30, 16); + } + if (currentBinPriceFilterType == PriceFilter.Greater) { + this.drawTexturedModalRect(auctionViewLeft + 16 + 34, guiTop + 32 + binPriceFilterYOffset, 30, 16, 30, 16); + } else { + this.drawTexturedModalRect(auctionViewLeft + 16 + 34, guiTop + 32 + binPriceFilterYOffset, 0, 16, 30, 16); + } + if (currentBinPriceFilterType == PriceFilter.Equal) { + this.drawTexturedModalRect(auctionViewLeft + 16, guiTop + 50 + binPriceFilterYOffset, 64, 32, 64, 16); + } else { + this.drawTexturedModalRect(auctionViewLeft + 16, guiTop + 50 + binPriceFilterYOffset, 0, 32, 64, 16); + } + + Utils.drawStringCentered("<=", fr, auctionViewLeft + 16 + 15, guiTop + 32 + 8 + binPriceFilterYOffset, false, + Color.BLACK.getRGB() + ); + Utils.drawStringCentered(">=", fr, auctionViewLeft + 16 + 34 + 15, guiTop + 32 + 8 + binPriceFilterYOffset, false, + Color.BLACK.getRGB() + ); + Utils.drawStringCentered("==", fr, auctionViewLeft + 16 + 32, guiTop + 50 + 8 + binPriceFilterYOffset, false, + Color.BLACK.getRGB() + ); + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + } + } + + public List getTooltipForControl(int index) { + List lore = new ArrayList<>(); + if (index < 0 || index >= controls.length) return lore; + if (controls[index] == null) return lore; + + lore.add(controls[index].getDisplayName()); + String arrow = "\u25b6"; + String selPrefixNC = " " + arrow + " "; + String selPrefix = EnumChatFormatting.DARK_AQUA + selPrefixNC; + String unselPrefix = EnumChatFormatting.GRAY.toString(); + switch (index) { + case 0: + lore.add(""); + String gold = EnumChatFormatting.GOLD.toString(); + String gray = EnumChatFormatting.GRAY.toString(); + char s = 0x272A; + String[] linesDung = { + "Show All", "Any Dungeon", + gold + s + gray + s + s + s + s, + gold + s + s + gray + s + s + s, + gold + s + s + s + gray + s + s, + gold + s + s + s + s + gray + s, + gold + s + s + s + s + s + }; + for (int i = 0; i < linesDung.length; i++) { + String line = linesDung[i]; + if (i == dungeonFilter) { + line = selPrefix + line.replace(gray, EnumChatFormatting.DARK_AQUA.toString()); + } else { + line = unselPrefix + line; + } + lore.add(line); + } + lore.add(""); + lore.add(EnumChatFormatting.AQUA + "Right-Click to go backwards!"); + lore.add(EnumChatFormatting.YELLOW + "Click to switch sort!"); + return lore; + case 1: + lore.add(""); + String[] linesSort = {"Highest Bid", "Lowest Bid", "Ending soon"}; + for (int i = 0; i < linesSort.length; i++) { + String line = linesSort[i]; + if (i == sortMode) { + line = selPrefix + line; + } else { + line = unselPrefix + line; + } + lore.add(line); + } + lore.add(""); + lore.add(EnumChatFormatting.YELLOW + "Click to switch sort!"); + return lore; + case 2: + lore.add(""); + lore.add((rarityFilter == -1 ? EnumChatFormatting.DARK_GRAY + selPrefixNC : unselPrefix) + "No Filter"); + + for (int i = 0; i < Utils.rarityArr.length; i++) { + lore.add((rarityFilter == i ? rarityColours[i] + selPrefixNC : unselPrefix) + + Utils.prettyCase(Utils.rarityArr[i])); + } + lore.add(""); + lore.add(EnumChatFormatting.AQUA + "Right-Click to go backwards!"); + lore.add(EnumChatFormatting.YELLOW + "Click to switch filter!"); + return lore; + case 3: + break; + case 4: + lore.add(""); + String off = EnumChatFormatting.RED + "OFF"; + String on = EnumChatFormatting.GREEN + "ON"; + lore.add(unselPrefix + "Filter Own Auctions: " + (filterMyAuctions ? on : off)); + lore.add(""); + lore.add(EnumChatFormatting.YELLOW + "Click to toggle!"); + return lore; + case 5: + break; + case 6: + lore.add(""); + String[] linesBin = {"Show All", "BIN Only", "Auctions Only"}; + for (int i = 0; i < linesBin.length; i++) { + String line = linesBin[i]; + if (i == binFilter) { + line = selPrefix + line; + } else { + line = unselPrefix + line; + } + lore.add(line); + } + lore.add(""); + lore.add(EnumChatFormatting.AQUA + "Right-Click to go backwards!"); + lore.add(EnumChatFormatting.YELLOW + "Click to switch filter!"); + return lore; + case 7: + lore.add(""); + String[] linesEnch = {"Show All", "Clean Only", "Ench Only", "Ench/HPB Only"}; + for (int i = 0; i < linesEnch.length; i++) { + String line = linesEnch[i]; + if (i == enchFilter) { + line = selPrefix + line; + } else { + line = unselPrefix + line; + } + lore.add(line); + } + lore.add(""); + lore.add(EnumChatFormatting.AQUA + "Right-Click to go backwards!"); + lore.add(EnumChatFormatting.YELLOW + "Click to switch filter!"); + return lore; + case 8: + lore.add(""); + lore.add("Current aucid: " + currentAucId); + if (currentAucId != null) { + APIManager.Auction auc = manager.auctionManager.getAuctionItems().get(currentAucId); + if (auc != null) { + lore.add("Current auc category: " + auc.category); + } + } + lore.add(" --- Processing"); + lore.add("Page Process Millis: " + manager.auctionManager.processMillis); + lore.add(" --- Auction Stats"); + lore.add("Active Auctions: " + manager.auctionManager.activeAuctions); + lore.add("Tracked Auctions: " + manager.auctionManager.getAuctionItems().size()); + lore.add("Displayed Auctions: " + auctionIds.size()); + lore.add("Tracked Player Auctions: " + manager.auctionManager.getPlayerBids().size()); + lore.add("Unique Items: " + manager.auctionManager.uniqueItems); + lore.add("ID Tagged Auctions: " + manager.auctionManager.internalnameTaggedAuctions); + lore.add("Total Tags: " + manager.auctionManager.totalTags); + lore.add("Tagged Auctions: " + manager.auctionManager.taggedAuctions); + lore.add(""); + lore.add(EnumChatFormatting.AQUA + "Right-Click to copy current aucid to clipboard!"); + lore.add(EnumChatFormatting.YELLOW + "Click to refresh!"); + return lore; + } + return new ArrayList<>(); + } + + public void handleMouseInput() { + if (!NotEnoughUpdates.INSTANCE.config.neuAuctionHouse.enableNeuAuctionHouse) { + return; + } + + ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + int width = scaledResolution.getScaledWidth(); + int height = scaledResolution.getScaledHeight(); + + int mouseX = Mouse.getEventX() * width / Minecraft.getMinecraft().displayWidth; + int mouseY = height - Mouse.getEventY() * height / Minecraft.getMinecraft().displayHeight - 1; + int mouseButton = Mouse.getEventButton(); + + if (Mouse.getEventButtonState()) { + this.eventButton = mouseButton; + this.lastMouseEvent = Minecraft.getSystemTime(); + mouseClicked(mouseX, mouseY, this.eventButton); + } else if (mouseButton != -1) { + this.eventButton = -1; + mouseReleased(mouseX, mouseY, mouseButton); + } else if (this.eventButton != -1 && this.lastMouseEvent > 0L) { + long l = Minecraft.getSystemTime() - this.lastMouseEvent; + mouseClickMove(mouseX, mouseY, this.eventButton, l); + } + + if (!NotEnoughUpdates.INSTANCE.config.neuAuctionHouse.disableAhScroll) { + int dWheel = Mouse.getEventDWheel(); + dWheel = Math.max(-1, Math.min(1, dWheel)); + + scrollAmount = scrollAmount - dWheel / (float) (auctionIds.size() / 9 - (5 + splits)); + scrollAmount = Math.max(0, Math.min(1, scrollAmount)); + } + } + + public String niceAucId(String aucId) { + if (aucId.length() != 32) return aucId; + + return aucId.substring(0, 8) + + "-" + aucId.substring(8, 12) + + "-" + aucId.substring(12, 16) + + "-" + aucId.substring(16, 20) + + "-" + aucId.substring(20, 32); + } + + public Category getCurrentCategory() { + if (clickedMainCategory < 0 || clickedMainCategory >= mainCategories.length) { + return null; + } + Category mainCategory = mainCategories[clickedMainCategory]; + if (clickedSubCategory < 0 || clickedSubCategory >= mainCategory.subcategories.length) { + return mainCategory; + } + return mainCategory.subcategories[clickedSubCategory]; + } + + private boolean doesAucMatch(APIManager.Auction auc) { + if (auc == null) return false; + + Category currentCategory = getCurrentCategory(); + + boolean match = true; + if (currentCategory != null) { + match = false; + String[] categories = currentCategory.getTotalCategories(); + for (String category : categories) { + match |= category.equalsIgnoreCase(auc.category); + } + } + + if (rarityFilter >= 0 && rarityFilter < Utils.rarityArr.length) { + match &= Utils.rarityArr[rarityFilter].equals(auc.rarity); + } + + if (binFilter == BIN_FILTER_BIN) { + match &= auc.bin; + } else if (binFilter == BIN_FILTER_AUC) { + match &= !auc.bin; + } + + if (enchFilter > ENCH_FILTER_ALL) { + switch (enchFilter) { + case ENCH_FILTER_CLEAN: + match &= auc.enchLevel == 0; + break; + case ENCH_FILTER_ENCH: + match &= auc.enchLevel >= 1; + break; + case ENCH_FILTER_ENCHHPB: + match &= auc.enchLevel == 2; + break; + } + } + + if (dungeonFilter > DUNGEON_FILTER_ALL) { + if (dungeonFilter == DUNGEON_FILTER_DUNGEON && auc.dungeonTier < 0) { + match = false; + } else { + match &= dungeonFilter == auc.dungeonTier + 1; + } + } + + if (getPriceFilterAmount() > -1) { + if (currentPriceFilterType == PriceFilter.Greater) { + match &= auc.highest_bid_amount != 0 + ? (auc.highest_bid_amount >= getPriceFilterAmount()) + : auc.starting_bid >= getPriceFilterAmount(); + } + if (currentPriceFilterType == PriceFilter.Less) { + match &= auc.highest_bid_amount != 0 + ? (auc.highest_bid_amount <= getPriceFilterAmount()) + : auc.starting_bid <= getPriceFilterAmount(); + } + if (currentPriceFilterType == PriceFilter.Equal) { + match &= auc.highest_bid_amount != 0 + ? (auc.highest_bid_amount == getPriceFilterAmount()) + : auc.starting_bid == getPriceFilterAmount(); + } + } + if (getBinPriceFilterAmount() > -1) { + int lowestBin = + NotEnoughUpdates.INSTANCE.manager.auctionManager.getLowestBin(NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem( + auc.getStack())); + if (lowestBin > 0) { + if (currentBinPriceFilterType == PriceFilter.Greater) { + match &= lowestBin >= getBinPriceFilterAmount(); + } + if (currentBinPriceFilterType == PriceFilter.Less) { + match &= lowestBin <= getBinPriceFilterAmount(); + } + if (currentBinPriceFilterType == PriceFilter.Equal) { + match &= lowestBin == getBinPriceFilterAmount(); + } + } else { + match = false; + } + } + return match; + } + + private HashSet search(String query, Set dontMatch) { + query = query.trim(); + HashSet matches = new HashSet<>(); + + Set itemMatches = manager.search(query); + for (String internalname : itemMatches) { + for (String aucid : manager.auctionManager.getAuctionsForInternalname(internalname)) { + APIManager.Auction auc = manager.auctionManager.getAuctionItems().get(aucid); + if (doesAucMatch(auc)) { + //matches.add(aucid); + } else { + dontMatch.add(aucid); + } + } + } + + HashMap> extrasMatches = new HashMap<>(); + HashMap> extrasMatchesCurrent = new HashMap<>(); + boolean first = true; + for (String subQuery : query.split(" ")) { + for (HashMap> extrasMap : manager.subMapWithKeysThatAreSuffixes( + subQuery.toLowerCase(), + manager.auctionManager.extrasToAucIdMap + ).values()) { + for (int index : extrasMap.keySet()) { + for (String aucid : extrasMap.get(index)) { + APIManager.Auction auc = manager.auctionManager.getAuctionItems().get(aucid); + if (!dontMatch.contains(aucid) && doesAucMatch(auc)) { + if (first) { + List indexList = extrasMatchesCurrent.computeIfAbsent(aucid, k -> new ArrayList<>()); + indexList.add(index); + } else { + List indexList = extrasMatches.computeIfAbsent(aucid, k -> new ArrayList<>()); + if (indexList.contains(index - 1)) { + List indexListCurrent = extrasMatchesCurrent.computeIfAbsent(aucid, k -> new ArrayList<>()); + indexListCurrent.add(index); + } + } + } else { + dontMatch.add(aucid); + } + } + } + + } + + extrasMatches = (HashMap>) extrasMatchesCurrent.clone(); + extrasMatchesCurrent.clear(); + first = false; + } + matches.addAll(extrasMatches.keySet()); + + return matches; + } + + private final ExecutorService es = Executors.newSingleThreadExecutor(); + + public void updateSearch() { + if (!NotEnoughUpdates.INSTANCE.config.neuAuctionHouse.enableNeuAuctionHouse) { + return; + } + + if (searchField == null || priceField == null || priceFilterField == null || binPriceFilterField == null) + init(); + long currentTime = System.currentTimeMillis(); + + es.submit(() -> { + if (currentTime - lastUpdateSearch < 100) { + shouldUpdateSearch = true; + return; + } + + lastUpdateSearch = currentTime; + shouldUpdateSearch = false; + + scrollAmount = 0; + try { + HashSet auctionIdsNew = new HashSet<>(); + auctionIdsNew.clear(); + if (filterMyAuctions) { + for (String aucid : manager.auctionManager.getPlayerBids()) { + APIManager.Auction auc = manager.auctionManager.getAuctionItems().get(aucid); + if (doesAucMatch(auc)) { + auctionIdsNew.add(aucid); + } + } + } else if (searchField.getText().length() == 0) { + for (Map.Entry entry : manager.auctionManager.getAuctionItems().entrySet()) { + if (doesAucMatch(entry.getValue())) { + auctionIdsNew.add(entry.getKey()); + } + } + } else { + String query = searchField.getText(); + Set dontMatch = new HashSet<>(); + + HashSet allMatch = new HashSet<>(); + if (query.contains("!")) { //only used for inverted queries, so dont need to populate unless ! in query + for (Map.Entry entry : manager.auctionManager.getAuctionItems().entrySet()) { + if (doesAucMatch(entry.getValue())) { + allMatch.add(entry.getKey()); + } else { + dontMatch.add(entry.getKey()); + } + } + } + + boolean invert = false; + + StringBuilder query2 = new StringBuilder(); + char lastOp = '|'; + for (char c : query.toCharArray()) { + if (query2.toString().trim().isEmpty() && c == '!') { + invert = true; + } else if (c == '|' || c == '&') { + if (lastOp == '|') { + HashSet result = search(query2.toString(), dontMatch); + if (!invert) { + auctionIdsNew.addAll(result); + } else { + HashSet allClone = (HashSet) allMatch.clone(); + allClone.removeAll(result); + auctionIdsNew.addAll(allClone); + } + } else if (lastOp == '&') { + HashSet result = search(query2.toString(), dontMatch); + if (!invert) { + auctionIdsNew.retainAll(result); + } else { + auctionIdsNew.removeAll(result); + } + } + + query2 = new StringBuilder(); + invert = false; + lastOp = c; + } else { + query2.append(c); + } + } + if (lastOp == '|') { + HashSet result = search(query2.toString(), dontMatch); + if (!invert) { + auctionIdsNew.addAll(result); + } else { + HashSet allClone = (HashSet) allMatch.clone(); + allClone.removeAll(result); + auctionIdsNew.addAll(allClone); + } + } else if (lastOp == '&') { + HashSet result = search(query2.toString(), dontMatch); + if (!invert) { + auctionIdsNew.retainAll(result); + } else { + auctionIdsNew.removeAll(result); + } + } + } + auctionIds = auctionIdsNew; + sortItems(); + } catch (Exception e) { + shouldUpdateSearch = true; + } + }); + } + + public void sortItems() throws ConcurrentModificationException { + if (!NotEnoughUpdates.INSTANCE.config.neuAuctionHouse.enableNeuAuctionHouse) { + return; + } + + try { + List sortedAuctionIdsNew = new ArrayList<>(); + + sortedAuctionIdsNew.addAll(auctionIds); + sortedAuctionIdsNew.sort((o1, o2) -> { + APIManager.Auction auc1 = manager.auctionManager.getAuctionItems().get(o1); + APIManager.Auction auc2 = manager.auctionManager.getAuctionItems().get(o2); + + if (auc1 == null) return 1; + if (auc2 == null) return -1; + + if (sortMode == SORT_MODE_HIGH) { + int price1 = Math.max(auc1.highest_bid_amount, auc1.starting_bid); + int price2 = Math.max(auc2.highest_bid_amount, auc2.starting_bid); + int diff = price2 - price1; + if (diff != 0) { + return diff; + } + } else if (sortMode == SORT_MODE_LOW) { + int price1 = Math.max(auc1.highest_bid_amount, auc1.starting_bid); + int price2 = Math.max(auc2.highest_bid_amount, auc2.starting_bid); + int diff = price1 - price2; + if (diff != 0) { + return diff; + } + } else { + long end1 = auc1.end; + long end2 = auc2.end; + + if (end1 < System.currentTimeMillis()) return 999999; + if (end2 < System.currentTimeMillis()) return -999999; + + int diff = (int) (end1 - end2); + if (diff != 0) { + return diff; + } + } + return o1.compareTo(o2); + }); + + sortedAuctionIds = sortedAuctionIdsNew; + } catch (Exception e) { + shouldSortItems = true; + } + } + + public boolean keyboardInput() { + if (!NotEnoughUpdates.INSTANCE.config.neuAuctionHouse.enableNeuAuctionHouse) { + return false; + } + + Keyboard.enableRepeatEvents(true); + if (isEditingPrice() && Keyboard.getEventKey() == Keyboard.KEY_RETURN) { + Minecraft.getMinecraft().displayGuiScreen(null); + } else if (Keyboard.getEventKey() == Keyboard.KEY_ESCAPE) { + if (Minecraft.getMinecraft().currentScreen instanceof GuiEditSign) { + priceField.setText(""); + GuiEditSign editSign = (GuiEditSign) Minecraft.getMinecraft().currentScreen; + TileEntitySign tes = (TileEntitySign) Utils.getField(GuiEditSign.class, editSign, + "tileSign", "field_146848_f" + ); + tes.lineBeingEdited = 0; + tes.signText[0] = new ChatComponentText(priceField.getText()); + } + return false; + } + if (Keyboard.getEventKeyState()) return keyTyped(Keyboard.getEventCharacter(), Keyboard.getEventKey()); + return true; + } + + public boolean keyTyped(char typedChar, int keyCode) { + if (searchField == null || priceField == null || priceFilterField == null || binPriceFilterField == null) + init(); + + if (!isEditingPrice()) { + if (this.priceFilterField.textboxKeyTyped(typedChar, keyCode)) { + this.updateSearch(); + return true; + } + if (this.binPriceFilterField.textboxKeyTyped(typedChar, keyCode)) { + this.updateSearch(); + return true; + } + if (this.searchField.textboxKeyTyped(typedChar, keyCode)) { + lastSearchFieldUpdate = System.currentTimeMillis(); + this.updateSearch(); + return true; + } + } else { + if (!priceField.isFocused()) priceField.setFocused(searchField.isFocused() && priceFilterField.isFocused()); + return priceField.textboxKeyTyped(typedChar, keyCode); + } + return false; + } + + private void increasePriceByFactor(float factor) { + String price = priceField.getText().trim(); + StringBuilder priceNumbers = new StringBuilder(); + for (int i = 0; i < price.length(); i++) { + char c = price.charAt(i); + if ((int) c >= 48 && (int) c <= 57) { + priceNumbers.append(c); + } else { + break; + } + } + int priceI = 0; + if (priceNumbers.length() > 0) { + priceI = Integer.parseInt(priceNumbers.toString()); + } + String end = price.substring(priceNumbers.length()); + priceField.setText((int) (priceI * factor) + end); + } + + private int getPriceFilterAmount() { + return getNumberFromTextBox(priceFilterField); + } + + private int getNumberFromTextBox(GuiTextField textField) { + if (textField.getText().equals("")) { + return -2; + } + try { + int parsed = Integer.parseInt(textField.getText()); + if (parsed < 0) { + return -1; + } + return parsed; + } catch (NumberFormatException e) { + return -1; + } + } + + private int getBinPriceFilterAmount() { + return getNumberFromTextBox(binPriceFilterField); + } + + protected void mouseClicked(int mouseX, int mouseY, int mouseButton) { + boolean wasFocused = searchField.isFocused(); + searchField.mouseClicked(mouseX, mouseY, mouseButton); + if (mouseButton == 1 && !wasFocused && searchField.isFocused()) { + searchField.setText(""); + } + priceField.mouseClicked(mouseX, mouseY, mouseButton); + priceFilterField.mouseClicked(mouseX, mouseY, mouseButton); + binPriceFilterField.mouseClicked(mouseX, mouseY, mouseButton); + + int totalItems = auctionIds.size(); + int itemsScroll = (int) Math.floor((totalItems * scrollAmount) / 9f) * 9; + + int maxItemScroll = Math.max(0, totalItems - (5 + splits) * 9); + itemsScroll = Math.min(itemsScroll, maxItemScroll); + + //Categories + if (mouseY > guiTop - 28 && mouseY < guiTop + 4) { + if (mouseX > guiLeft && mouseX < guiLeft + 168) { + int offset = mouseX - guiLeft; + int clickedCat = offset / 28; + if (clickedMainCategory == clickedCat) { + clickedMainCategory = -1; + } else { + clickedMainCategory = clickedCat; + } + clickedSubCategory = -1; + updateSearch(); + Utils.playPressSound(); + return; + } + } + + if (clickedMainCategory >= 0 && clickedMainCategory < mainCategories.length) { + Category mainCategory = mainCategories[clickedMainCategory]; + + if (mouseX > guiLeft - 28 && mouseX < guiLeft) { + int offset = mouseY - (guiTop + 17); + if (offset > 0) { + int clicked = offset / 28 - 1; + if (clicked != clickedSubCategory && clicked < mainCategory.subcategories.length) { + clickedSubCategory = clicked; + updateSearch(); + Utils.playPressSound(); + return; + } + } + } + } + + if (mouseY > guiTop + 112 + 18 * splits && mouseY < guiTop + 112 + 18 * splits + 16) { + if (mouseX > guiLeft + 9 && mouseX < guiLeft + 9 + controls.length * 18 - 2) { + int offset = mouseX - (guiLeft + 9); + int index = offset / 18; + boolean rightClicked = Mouse.getEventButton() == 1; + switch (index) { + case 0: + if (rightClicked) { + dungeonFilter--; + if (dungeonFilter < DUNGEON_FILTER_ALL) dungeonFilter = DUNGEON_FILTER_5; + } else { + dungeonFilter++; + if (dungeonFilter > DUNGEON_FILTER_5) dungeonFilter = DUNGEON_FILTER_ALL; + } + break; + case 1: + if (rightClicked) { + sortMode--; + if (sortMode < SORT_MODE_HIGH) sortMode = SORT_MODE_SOON; + } else { + sortMode++; + if (sortMode > SORT_MODE_SOON) sortMode = SORT_MODE_HIGH; + } + break; + case 2: + if (rightClicked) { + rarityFilter--; + if (rarityFilter < -1) rarityFilter = Utils.rarityArr.length - 1; + } else { + rarityFilter++; + if (rarityFilter >= Utils.rarityArr.length) rarityFilter = -1; + } + break; + case 3: + break; + case 4: + filterMyAuctions = !filterMyAuctions; + break; + case 5: + break; + case 6: + if (rightClicked) { + binFilter--; + if (binFilter < BIN_FILTER_ALL) binFilter = BIN_FILTER_AUC; + } else { + binFilter++; + if (binFilter > BIN_FILTER_AUC) binFilter = BIN_FILTER_ALL; + } + break; + case 7: + if (rightClicked) { + enchFilter--; + if (enchFilter < ENCH_FILTER_ALL) enchFilter = ENCH_FILTER_ENCHHPB; + } else { + enchFilter++; + if (enchFilter > ENCH_FILTER_ENCHHPB) enchFilter = ENCH_FILTER_ALL; + } + break; + case 8: + if (rightClicked) { + if (currentAucId != null) { + StringSelection selection = new StringSelection(niceAucId(currentAucId)); + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(selection, selection); + } + } else { + manager.auctionManager.calculateStats(); + } + } + updateSearch(); + Utils.playPressSound(); + } + } + boolean hasPopup = false; + if (mouseButton == 0 && Minecraft.getMinecraft().currentScreen instanceof GuiChest) { + hasPopup = true; + GuiChest auctionView = (GuiChest) Minecraft.getMinecraft().currentScreen; + ContainerChest container = (ContainerChest) auctionView.inventorySlots; + String containerName = container.getLowerChestInventory().getDisplayName().getUnformattedText(); + + if (containerName.trim().equals("Auction View") || containerName.trim().equals("BIN Auction View")) { + + if (mouseX > guiLeft + getXSize() + 4 + 31 && mouseX < guiLeft + getXSize() + 4 + 31 + 16) { + boolean leftFiller = isGuiFiller(auctionView.inventorySlots.getSlot(29).getStack());//isBin + if (mouseY > guiTop + 35 && mouseY < guiTop + 35 + 16) { + ItemStack topStack = auctionView.inventorySlots.getSlot(13).getStack(); + if (topStack != null) { + String line = findStrStart(topStack, EnumChatFormatting.GRAY + "Seller: "); + String[] split = line.split(" "); + String seller = split[split.length - 1]; + StringSelection selection = new StringSelection(seller); + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(selection, selection); + } + } else if (mouseY > guiTop + 100 && mouseY < guiTop + 100 + 16) { + int slotClick = leftFiller ? 31 : 29; + Minecraft.getMinecraft().playerController.windowClick(auctionView.inventorySlots.windowId, + slotClick, 2, 3, Minecraft.getMinecraft().thePlayer + ); + + if (!leftFiller) { + if (auctionView.inventorySlots.getSlot(29).getStack() + .getDisplayName().trim().equals( + EnumChatFormatting.GOLD + "Collect Auction")) { + manager.auctionManager.getPlayerBids().remove(currentAucId); + auctionIds.remove(currentAucId); + } + } + + Utils.playPressSound(); + } else if (mouseY > guiTop + 126 && mouseY < guiTop + 126 + 16 && !leftFiller) { + priceField.setFocused(true); + Minecraft.getMinecraft().playerController.windowClick(auctionView.inventorySlots.windowId, + 31, 2, 3, Minecraft.getMinecraft().thePlayer + ); + Utils.playPressSound(); + } + } + } else if (containerName.trim().equals("Confirm Bid") || containerName.trim().equals("Confirm Purchase")) { + if (mouseX > guiLeft + getXSize() + 4 + 31 && mouseX < guiLeft + getXSize() + 4 + 31 + 16) { + if (mouseY > guiTop + 31 && mouseY < guiTop + 31 + 16) { + if (currentAucId != null) { + manager.auctionManager.getPlayerBids().add(currentAucId); + latestBid = currentAucId; + latestBidMillis = System.currentTimeMillis(); + //reset timer to 2m if below + if (manager.auctionManager.getAuctionItems().get(currentAucId) != null && + manager.auctionManager.getAuctionItems().get(currentAucId).end - + System.currentTimeMillis() < 2 * 60 * 1000) { + manager.auctionManager.getAuctionItems().get(currentAucId).end = + System.currentTimeMillis() + 2 * 60 * 1000; + } + } + Minecraft.getMinecraft().playerController.windowClick(auctionView.inventorySlots.windowId, + 11, 2, 3, Minecraft.getMinecraft().thePlayer + ); + } else if (mouseY > guiTop + 125 && mouseY < guiTop + 125 + 16) { + Minecraft.getMinecraft().playerController.windowClick(auctionView.inventorySlots.windowId, + 15, 2, 3, Minecraft.getMinecraft().thePlayer + ); + } + Utils.playPressSound(); + } + } + } + int auctionViewLeft = guiLeft + getXSize() + 4; + + if (mouseButton == 0 && isEditingPrice()) { + + if (mouseX > auctionViewLeft + 16 && mouseX < auctionViewLeft + 16 + 64) { + if (mouseY > guiTop + 32 && mouseY < guiTop + 32 + 16) { + if (mouseX < auctionViewLeft + 16 + 32) { + //top left + increasePriceByFactor(2); + } else { + //top right + increasePriceByFactor(1.5f); + } + Utils.playPressSound(); + } else if (mouseY > guiTop + 50 && mouseY < guiTop + 50 + 16) { + if (mouseX < auctionViewLeft + 16 + 32) { + //mid left + increasePriceByFactor(1.25f); + } else { + //mid right + increasePriceByFactor(1.1f); + } + Utils.playPressSound(); + } else if (mouseY > guiTop + 68 && mouseY < guiTop + 68 + 16) { + //bottom + Utils.playPressSound(); + Minecraft.getMinecraft().displayGuiScreen(null); + } + } + + this.drawTexturedModalRect(auctionViewLeft + 16, guiTop + 32, 0, 16, 30, 16); + this.drawTexturedModalRect(auctionViewLeft + 16 + 34, guiTop + 32, 0, 16, 30, 16); + this.drawTexturedModalRect(auctionViewLeft + 16, guiTop + 50, 0, 16, 30, 16); + this.drawTexturedModalRect(auctionViewLeft + 16 + 34, guiTop + 50, 0, 16, 30, 16); + this.drawTexturedModalRect(auctionViewLeft + 16, guiTop + 68, 0, 32, 64, 16); + } else if (!hasPopup && NotEnoughUpdates.INSTANCE.config.neuAuctionHouse.priceFiltering) { + + if (mouseX > auctionViewLeft + 16 && mouseX < auctionViewLeft + 16 + 64) { + if (mouseY > guiTop + 32 && mouseY < guiTop + 32 + 16) { + if (mouseX < auctionViewLeft + 16 + 32) { + //top left + currentPriceFilterType = PriceFilter.Less; + } else { + //top right + currentPriceFilterType = PriceFilter.Greater; + } + Utils.playPressSound(); + updateSearch(); + } else if (mouseY > guiTop + 50 && mouseY < guiTop + 50 + 16) { + //middle + currentPriceFilterType = PriceFilter.Equal; + Utils.playPressSound(); + updateSearch(); + } + } + + if (mouseX > auctionViewLeft + 16 && mouseX < auctionViewLeft + 16 + 64) { + if (mouseY > guiTop + 32 + binPriceFilterYOffset && mouseY < guiTop + 32 + 16 + binPriceFilterYOffset) { + if (mouseX < auctionViewLeft + 16 + 32) { + //top left + currentBinPriceFilterType = PriceFilter.Less; + } else { + //top right + currentBinPriceFilterType = PriceFilter.Greater; + } + Utils.playPressSound(); + updateSearch(); + } else if (mouseY > guiTop + 50 + binPriceFilterYOffset && mouseY < guiTop + 50 + 16 + binPriceFilterYOffset) { + //middle + currentBinPriceFilterType = PriceFilter.Equal; + Utils.playPressSound(); + updateSearch(); + } + } + } + out: + for (int i = 0; i < 5 + splits; i++) { + int itemY = guiTop + i * 18 + 18; + for (int j = 0; j < 9; j++) { + int itemX = guiLeft + j * 18 + 9; + int id = itemsScroll + i * 9 + j; + if (auctionIds.size() <= id) break out; + + String aucid; + try { + aucid = sortedAuctionIds.get(id); + } catch (IndexOutOfBoundsException e) { + break out; + } + + if (aucid == null) continue; + APIManager.Auction auc = manager.auctionManager.getAuctionItems().get(aucid); + if (auc != null) { + if (mouseX > itemX && mouseX < itemX + 16) { + if (mouseY > itemY && mouseY < itemY + 16) { + if (Minecraft.getMinecraft().currentScreen instanceof GuiEditSign) { + priceField.setText(""); + GuiEditSign editSign = (GuiEditSign) Minecraft.getMinecraft().currentScreen; + TileEntitySign tes = (TileEntitySign) Utils.getField(GuiEditSign.class, editSign, + "tileSign", "field_146848_f" + ); + tes.lineBeingEdited = 0; + tes.signText[0] = new ChatComponentText(priceField.getText()); + } + startingBid = Math.max(auc.starting_bid, auc.highest_bid_amount); + currAucIdSetTimer = System.currentTimeMillis(); + currentAucId = aucid; + + Minecraft.getMinecraft().thePlayer.sendChatMessage("/viewauction " + niceAucId(aucid)); + Utils.playPressSound(); + } + } + } + } + } + + int y = guiTop + 18 + (int) ((95 + ySplitSize * 2) * scrollAmount); + if (mouseX > guiLeft + 175 && mouseX < guiLeft + 175 + 12) { + if (mouseY > y && mouseY < y + 15) { + scrollClicked = true; + return; + } + } + scrollClicked = false; + } + + protected void mouseReleased(int mouseX, int mouseY, int state) { + scrollClicked = false; + } + + protected void mouseClickMove(int mouseX, int mouseY, int clickedMouseButton, long timeSinceLastClick) { + if (scrollClicked) { + int yMin = guiTop + 18 + 8; + int yMax = guiTop + 18 + (95 + ySplitSize * 2) + 8; + + scrollAmount = (mouseY - yMin) / (float) (yMax - yMin); + scrollAmount = Math.max(0, Math.min(1, scrollAmount)); + } + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAHGui.java b/src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAHGui.java index bb36d363dd..9311040d7c 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAHGui.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAHGui.java @@ -1,16 +1,13 @@ package io.github.moulberry.notenoughupdates.auction; import net.minecraft.client.gui.GuiScreen; -import org.lwjgl.input.Mouse; public class CustomAHGui extends GuiScreen { + public CustomAHGui() { + this.allowUserInput = true; + } - public CustomAHGui() { - this.allowUserInput = true; - } - - public boolean doesGuiPauseGame() { - return false; - } - + public boolean doesGuiPauseGame() { + return false; + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/collectionlog/CollectionConstant.java b/src/main/java/io/github/moulberry/notenoughupdates/collectionlog/CollectionConstant.java index 25f6cfcaff..e789e88294 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/collectionlog/CollectionConstant.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/collectionlog/CollectionConstant.java @@ -5,13 +5,11 @@ import java.util.regex.Pattern; public class CollectionConstant { + public static class DropEntry { + public String type; + public Pattern regex; + public HashMap items; + } - public static class DropEntry { - public String type; - public Pattern regex; - public HashMap items; - } - - public List dropdata; - + public List dropdata; } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/collectionlog/GuiCollectionLog.java b/src/main/java/io/github/moulberry/notenoughupdates/collectionlog/GuiCollectionLog.java index a2c8bfa9ad..dac104c602 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/collectionlog/GuiCollectionLog.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/collectionlog/GuiCollectionLog.java @@ -12,92 +12,100 @@ import org.lwjgl.opengl.GL11; public class GuiCollectionLog extends GuiScreen { - - private static final ResourceLocation COLLECTION_LOG_TEX = new ResourceLocation("notenoughupdates:collectionlog.png"); - - @Override - public void drawScreen(int mouseX, int mouseY, float partialTicks) { - ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); - int width = scaledResolution.getScaledWidth(); - int height = scaledResolution.getScaledHeight(); - - int colwidth = 307; - int colheight = 187; - - int left = width/2 - colwidth/2; - int top = height/2 - colheight/2; - - BackgroundBlur.renderBlurredBackground(10, width, height, left, top, colwidth, colheight); - super.drawDefaultBackground(); - - Utils.drawStringCentered("\u00a7lCollection Log", fontRendererObj, width/2, top - 27, true, 0xfff5aa00); - - String[] cats = {"Bosses", "Dragons", "Slayer", "Dungeons"}; - - GlStateManager.enableDepth(); - - GlStateManager.translate(0, 0, 2); - for(int i=0; i<4; i++) { - if(i == 0) { - int offset = i == 0 ? 1 : 2; - - Minecraft.getMinecraft().getTextureManager().bindTexture(COLLECTION_LOG_TEX); - GlStateManager.color(1, 1, 1, 1); - Utils.drawTexturedRect(left+i*71, top-21, 71, 25, - (71*offset)/512f, (71+71*offset)/512f, 211/512f, (211+25)/512f, GL11.GL_NEAREST); - - Utils.drawStringCentered(cats[i], fontRendererObj, left+i*71+71/2, top - 8, true, 0xfff5aa00); - } - } - - GlStateManager.translate(0, 0, -1); - Minecraft.getMinecraft().getTextureManager().bindTexture(COLLECTION_LOG_TEX); - GlStateManager.color(1, 1, 1, 1); - Utils.drawTexturedRect(left, top, colwidth, colheight, - 0, colwidth/512f, 0, colheight/512f, GL11.GL_NEAREST); - - GlScissorStack.push(0, top+3, width, top+colheight-6, scaledResolution); - int catIndex = 0; - for(int h=top+3; h neuHelpMessages = Lists.newArrayList( - "\u00a75\u00a7lNotEnoughUpdates commands", - "\u00a76/neu \u00a77- Opens the main neu GUI.", - "\u00a76/pv \u00a7b?{name} \u00a72\u2D35 \u00a7r\u00a77- Opens the profile viewer", - "\u00a76/neusouls {on/off/clear/unclear} \u00a7r\u00a77- Shows waypoints to fairy souls.", - "\u00a76/neubuttons \u00a7r\u00a77- Opens a GUI which allows you to customize inventory buttons.", - "\u00a76/neuec \u00a7r\u00a77- Opens the enchant colour GUI.", - - "\u00a76/join {floor} \u00a7r\u00a77- Short Command to join a Dungeon. \u00a7lNeed a Party of 5 People\u00a7r\u00a77 {4/f7/m5}.", - "\u00a76/neucosmetics \u00a7r\u00a77- Opens the cosmetic GUI.", - "\u00a76/neurename \u00a7r\u00a77- Opens the NEU Item Customizer.", - "\u00a76/cata \u00a7b?{name} \u00a72\u2D35 \u00a7r\u00a77- Opens the profile viewer's catacombs page.", - "\u00a76/neulinks \u00a7r\u00a77- Shows links to neu/moulberry.", - "\u00a76/neuoverlay \u00a7r\u00a77- Opens GUI Editor for quickcommands and searchbar.", - "\u00a76/neuah \u00a7r\u00a77- Opens neu's custom ah GUI.", - "\u00a76/neumap \u00a7r\u00a77- Opens the dungeon map GUI.", - "\u00a76/neucalendar \u00a7r\u00a77- Opens neu's custom calendar GUI.", - "", - "\u00a76\u00a7lOld commands:", - "\u00a76/peek \u00a7b?{user} \u00a72\u2D35 \u00a7r\u00a77- Shows quickly stats for a user.", - "", - "\u00a76\u00a7lDebug commands:", - "\u00a76/neustats \u00a7r\u00a77- Copies helpful info to the clipboard.", - "\u00a76/neustats modlist \u00a7r\u00a77- Copies modlist info to clipboard.", - "\u00a76/neuresetrepo \u00a7r\u00a77- Deletes all repo files.", - "\u00a76/neureloadrepo \u00a7r\u00a77- Debug command with repo.", - "", - "\u00a76\u00a7lDev commands:", - "\u00a76/neupackdev \u00a7r\u00a77- pack creator command - getnpc"); - for (int i = 0; i < neuHelpMessages.size(); i++) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(neuHelpMessages.get(i) - )); - - } - if(NotEnoughUpdates.INSTANCE.config.hidden.dev) { - ArrayList neuDevHelpMessages = Lists.newArrayList( - "\u00a76/neudevtest \u00a7r\u00a77- dev test command", - "\u00a76/neuzeephere \u00a7r\u00a77- sphere", - "\u00a76/neudungeonwintest \u00a7r\u00a77- displays the dungeon win screen"); - - for (int i = 0; i < neuDevHelpMessages.size(); i++) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(neuDevHelpMessages.get(i) - )); - - } - } - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("\u00a77Commands marked with a \u00a72\"\u2D35\"\u00a77 require are api key. You can set your api key via \"/api new\" or by manually putting it in the api field in \"/neu\"")); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("\u00a77Arguments marked with a \u00a7b\"?\"\u00a77 are optional.")); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("\u00a76\u00a7lScroll up to see everything")); - } - }); - - SimpleCommand neuFeatures = new SimpleCommand("neufeatures", new SimpleCommand.ProcessCommandRunnable() { - public void processCommand(ICommandSender sender, String[] args) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); - if(Constants.MISC == null || !Constants.MISC.has("featureslist")){ - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(""+EnumChatFormatting.DARK_RED+EnumChatFormatting.BOLD+"WARNING: "+EnumChatFormatting.RESET+EnumChatFormatting.RED+"Could not load URL from repo.")); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(""+EnumChatFormatting.RED+ "Please run "+EnumChatFormatting.BOLD+"/neuresetrepo"+EnumChatFormatting.RESET+EnumChatFormatting.RED+" and "+EnumChatFormatting.BOLD+"restart your game"+EnumChatFormatting.RESET+EnumChatFormatting.RED+" in order to fix. "+EnumChatFormatting.DARK_RED+EnumChatFormatting.BOLD+"If that doesn't fix it"+EnumChatFormatting.RESET+EnumChatFormatting.RED+", please join discord.gg/moulberry and post in #neu-support")); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); - return; - } - String url = Constants.MISC.get("featureslist").getAsString(); - - Desktop desk = Desktop.getDesktop(); - try { - desk.browse(new URI(url)); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.DARK_PURPLE+""+EnumChatFormatting.BOLD+"NEU"+EnumChatFormatting.RESET+EnumChatFormatting.GOLD+"> Opening Feature List in browser.")); - } catch (URISyntaxException | IOException ignored){ - - ChatComponentText clickTextFeatures = new ChatComponentText( - EnumChatFormatting.DARK_PURPLE+""+EnumChatFormatting.BOLD+"NEU"+EnumChatFormatting.RESET+EnumChatFormatting.GOLD+"> Click here to open the Feature List in your browser."); - clickTextFeatures.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, url)); - Minecraft.getMinecraft().thePlayer.addChatMessage(clickTextFeatures); - - } - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); - - } - }); - - - SimpleCommand stWhyCommand = new SimpleCommand("neustwhy", new SimpleCommand.ProcessCommandRunnable() { - public void processCommand(ICommandSender sender, String[] args) { - NEUEventListener.displayNotification(Lists.newArrayList( - "\u00a7eStorage Viewer", - "\u00a77Currently, the storage viewer requires you to click twice", - "\u00a77in order to switch between pages. This is because Hypixel", - "\u00a77has not yet added a shortcut command to go to any enderchest/", - "\u00a77storage page.", - "\u00a77While it is possible to send the second click", - "\u00a77automatically, doing so violates Hypixel's new mod rules."), true); - } - }); - - SimpleCommand gamemodesCommand = new SimpleCommand("neugamemodes", new SimpleCommand.ProcessCommandRunnable() { - public void processCommand(ICommandSender sender, String[] args) { - boolean upgradeOverride = args.length == 1 && args[0].equals("upgradeOverride"); - NotEnoughUpdates.INSTANCE.openGui = new GuiGamemodes(upgradeOverride); - } - }); - - SimpleCommand buttonsCommand = new SimpleCommand("neubuttons", new SimpleCommand.ProcessCommandRunnable() { - public void processCommand(ICommandSender sender, String[] args) { - NotEnoughUpdates.INSTANCE.openGui = new GuiInvButtonEditor(); - } - }); - - SimpleCommand enchantColourCommand = new SimpleCommand("neuec", new SimpleCommand.ProcessCommandRunnable() { - public void processCommand(ICommandSender sender, String[] args) { - NotEnoughUpdates.INSTANCE.openGui = new GuiEnchantColour(); - } - }); - - SimpleCommand resetRepoCommand = new SimpleCommand("neuresetrepo", new SimpleCommand.ProcessCommandRunnable() { - public void processCommand(ICommandSender sender, String[] args) { - NotEnoughUpdates.INSTANCE.manager.resetRepo(); - } - }); - - SimpleCommand dungeonWinTest = new SimpleCommand("neudungeonwintest", new SimpleCommand.ProcessCommandRunnable() { - public void processCommand(ICommandSender sender, String[] args) { - if(args.length > 0) { - DungeonWin.TEAM_SCORE = new ResourceLocation("notenoughupdates:dungeon_win/"+args[0].toLowerCase()+".png"); - } - - DungeonWin.displayWin(); - } - }); - - SimpleCommand reloadRepoCommand = new SimpleCommand("neureloadrepo", new SimpleCommand.ProcessCommandRunnable() { - public void processCommand(ICommandSender sender, String[] args) { - File items = new File(NotEnoughUpdates.INSTANCE.manager.repoLocation, "items"); - if(items.exists()) { - File[] itemFiles = new File(NotEnoughUpdates.INSTANCE.manager.repoLocation, "items").listFiles(); - if(itemFiles != null) { - for(File f : itemFiles) { - String internalname = f.getName().substring(0, f.getName().length()-5); - NotEnoughUpdates.INSTANCE.manager.loadItem(internalname); - } - } - } - Constants.reload(); - - NotEnoughUpdates.INSTANCE.newConfigFile(); - if(NotEnoughUpdates.INSTANCE.getConfigFile().exists()) { - try(BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(NotEnoughUpdates.INSTANCE.getConfigFile()), StandardCharsets.UTF_8))) { - NotEnoughUpdates.INSTANCE.config = NotEnoughUpdates.INSTANCE.manager.gson.fromJson(reader, NEUConfig.class); - } catch(Exception e) { } - } - } - }); - - ScheduledExecutorService peekCommandExecutorService = null; - - SimpleCommand peekCommand = new SimpleCommand("peek", new SimpleCommand.ProcessCommandRunnable() { - public void processCommand(ICommandSender sender, String[] args) { - String name; - if(args.length == 0) { - name = Minecraft.getMinecraft().thePlayer.getName(); - } else { - name = args[0]; - } - int id = new Random().nextInt(Integer.MAX_VALUE/2)+Integer.MAX_VALUE/2; - - Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessageWithOptionalDeletion(new ChatComponentText( - EnumChatFormatting.YELLOW+"[PEEK] Getting player information..."), id); - NotEnoughUpdates.INSTANCE.profileViewer.getProfileByName(name, profile -> { - if (profile == null) { - Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessageWithOptionalDeletion(new ChatComponentText( - EnumChatFormatting.RED+"[PEEK] Unknown player or api is down."), id); - } else { - profile.resetCache(); - - if(peekCommandExecutorService == null || peekCommandExecutorService.isShutdown()) { - peekCommandExecutorService = Executors.newSingleThreadScheduledExecutor(); - } else { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.RED+"[PEEK] New peek command run, cancelling old one.")); - peekCommandExecutorService.shutdownNow(); - peekCommandExecutorService = Executors.newSingleThreadScheduledExecutor(); - } - - Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessageWithOptionalDeletion(new ChatComponentText( - EnumChatFormatting.YELLOW+"[PEEK] Getting player skyblock profiles..."), id); - - long startTime = System.currentTimeMillis(); - peekCommandExecutorService.schedule(new Runnable() { - public void run() { - if(System.currentTimeMillis() - startTime > 10*1000) { - - Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessageWithOptionalDeletion(new ChatComponentText( - EnumChatFormatting.RED+"[PEEK] Getting profile info took too long, aborting."), id); - return; - } - - String g = EnumChatFormatting.GRAY.toString(); - - JsonObject profileInfo = profile.getProfileInformation(null); - if(profileInfo != null) { - float overallScore = 0; - - boolean isMe = name.equalsIgnoreCase("moulberry"); - - PlayerStats.Stats stats = profile.getStats(null); - JsonObject skill = profile.getSkillInfo(null); - - Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessageWithOptionalDeletion(new ChatComponentText(EnumChatFormatting.GREEN+" "+ - EnumChatFormatting.STRIKETHROUGH+"-=-" +EnumChatFormatting.RESET+EnumChatFormatting.GREEN+" "+ - Utils.getElementAsString(profile.getHypixelProfile().get("displayname"), name) + "'s Info " + - EnumChatFormatting.STRIKETHROUGH+"-=-"), id); - - if(skill == null) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW+"Skills api disabled!")); - } else { - float totalSkillLVL = 0; - float totalSkillCount = 0; - - for(Map.Entry entry : skill.entrySet()) { - if(entry.getKey().startsWith("level_skill")) { - if(entry.getKey().contains("runecrafting")) continue; - if(entry.getKey().contains("carpentry")) continue; - totalSkillLVL += entry.getValue().getAsFloat(); - totalSkillCount++; - } - } - - float combat = Utils.getElementAsFloat(skill.get("level_skill_combat"), 0); - float zombie = Utils.getElementAsFloat(skill.get("level_slayer_zombie"), 0); - float spider = Utils.getElementAsFloat(skill.get("level_slayer_spider"), 0); - float wolf = Utils.getElementAsFloat(skill.get("level_slayer_wolf"), 0); - float enderman = Utils.getElementAsFloat(skill.get("level_slayer_enderman"), 0); - - float avgSkillLVL = totalSkillLVL/totalSkillCount; - - if(isMe) { - avgSkillLVL = 6; - combat = 4; - zombie = 2; - spider = 1; - wolf = 2; - enderman = 0; - } - - EnumChatFormatting combatPrefix = combat>20?(combat>35?EnumChatFormatting.GREEN:EnumChatFormatting.YELLOW):EnumChatFormatting.RED; - EnumChatFormatting zombiePrefix = zombie>3?(zombie>6?EnumChatFormatting.GREEN:EnumChatFormatting.YELLOW):EnumChatFormatting.RED; - EnumChatFormatting spiderPrefix = spider>3?(spider>6?EnumChatFormatting.GREEN:EnumChatFormatting.YELLOW):EnumChatFormatting.RED; - EnumChatFormatting wolfPrefix = wolf>3?(wolf>6?EnumChatFormatting.GREEN:EnumChatFormatting.YELLOW):EnumChatFormatting.RED; - EnumChatFormatting endermanPrefix = enderman>3?(enderman>6?EnumChatFormatting.GREEN:EnumChatFormatting.YELLOW):EnumChatFormatting.RED; - EnumChatFormatting avgPrefix = avgSkillLVL>20?(avgSkillLVL>35?EnumChatFormatting.GREEN:EnumChatFormatting.YELLOW):EnumChatFormatting.RED; - - overallScore += zombie*zombie/81f; - overallScore += spider*spider/81f; - overallScore += wolf*wolf/81f; - overallScore += enderman*enderman/81f; - overallScore += avgSkillLVL/20f; - - int cata = (int)Utils.getElementAsFloat(skill.get("level_skill_catacombs"), 0); - EnumChatFormatting cataPrefix = cata>15?(cata>25?EnumChatFormatting.GREEN:EnumChatFormatting.YELLOW):EnumChatFormatting.RED; - - overallScore += cata*cata/2000f; - - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - g+"Combat: "+combatPrefix+(int)Math.floor(combat) + - (cata > 0 ? g+" - Cata: "+cataPrefix+cata : "")+ - g+" - AVG: " + avgPrefix+(int)Math.floor(avgSkillLVL))); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - g+"Slayer: "+zombiePrefix+(int)Math.floor(zombie)+g+"-"+ - spiderPrefix+(int)Math.floor(spider)+g+"-"+ - wolfPrefix+(int)Math.floor(wolf)+"-"+ - endermanPrefix+(int)Math.floor(enderman))); - } - if (stats == null) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.YELLOW+"Skills, collection and/or inventory apis disabled!")); - } else { - int health = (int)stats.get("health"); - int defence = (int)stats.get("defence"); - int strength = (int)stats.get("strength"); - int intelligence = (int)stats.get("intelligence"); - - EnumChatFormatting healthPrefix = health>800?(health>1600?EnumChatFormatting.GREEN:EnumChatFormatting.YELLOW):EnumChatFormatting.RED; - EnumChatFormatting defencePrefix = defence>200?(defence>600?EnumChatFormatting.GREEN:EnumChatFormatting.YELLOW):EnumChatFormatting.RED; - EnumChatFormatting strengthPrefix = strength>100?(strength>300?EnumChatFormatting.GREEN:EnumChatFormatting.YELLOW):EnumChatFormatting.RED; - EnumChatFormatting intelligencePrefix = intelligence>300?(intelligence>900?EnumChatFormatting.GREEN:EnumChatFormatting.YELLOW):EnumChatFormatting.RED; - - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - g+"Stats : "+healthPrefix+health+EnumChatFormatting.RED+"\u2764 "+ - defencePrefix+defence+EnumChatFormatting.GREEN+"\u2748 "+ - strengthPrefix+strength+EnumChatFormatting.RED+"\u2741 "+ - intelligencePrefix+intelligence+EnumChatFormatting.AQUA+"\u270e ")); - } - float bankBalance = Utils.getElementAsFloat(Utils.getElement(profileInfo, "banking.balance"), -1); - float purseBalance = Utils.getElementAsFloat(Utils.getElement(profileInfo, "coin_purse"), 0); - - long networth = profile.getNetWorth(null); - float money = Math.max(bankBalance+purseBalance, networth); - EnumChatFormatting moneyPrefix = money>50*1000*1000? - (money>200*1000*1000?EnumChatFormatting.GREEN:EnumChatFormatting.YELLOW):EnumChatFormatting.RED; - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - g+"Purse: "+moneyPrefix+Utils.shortNumberFormat(purseBalance, 0) + g+" - Bank: " + - (bankBalance == -1 ? EnumChatFormatting.YELLOW+"N/A" : moneyPrefix+ - (isMe?"4.8b":Utils.shortNumberFormat(bankBalance, 0))) + - (networth > 0 ? g+" - Net: "+moneyPrefix+Utils.shortNumberFormat(networth, 0) : ""))); - - overallScore += Math.min(2, money/(100f*1000*1000)); - - String activePet = Utils.getElementAsString(Utils.getElement(profile.getPetsInfo(null), "active_pet.type"), - "None Active"); - String activePetTier = Utils.getElementAsString(Utils.getElement(profile.getPetsInfo(null), "active_pet.tier"), "UNKNOWN"); - - String col = NotEnoughUpdates.petRarityToColourMap.get(activePetTier); - if(col == null) col = EnumChatFormatting.LIGHT_PURPLE.toString(); - - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(g+"Pet : " + - col + WordUtils.capitalizeFully(activePet.replace("_", " ")))); - - String overall = "Skywars Main"; - if(isMe) { - overall = Utils.chromaString("Literally the best player to exist"); // ego much - } else if(overallScore < 5 && (bankBalance+purseBalance) > 500*1000*1000) { - overall = EnumChatFormatting.GOLD+"Bill Gates"; - } else if(overallScore > 9) { - overall = Utils.chromaString("Didn't even think this score was possible"); - } else if(overallScore > 8) { - overall = Utils.chromaString("Mentally unstable"); - } else if(overallScore > 7) { - overall = EnumChatFormatting.GOLD+"Why though 0.0"; - } else if(overallScore > 5.5) { - overall = EnumChatFormatting.GOLD+"Bro stop playing"; - } else if(overallScore > 4) { - overall = EnumChatFormatting.GREEN+"Kinda sweaty"; - } else if(overallScore > 3) { - overall = EnumChatFormatting.YELLOW+"Alright I guess"; - } else if(overallScore > 2) { - overall = EnumChatFormatting.YELLOW+"Ender Non"; - } else if(overallScore > 1) { - overall = EnumChatFormatting.RED+"Played Skyblock"; - } - - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(g+"Overall score: " + - overall + g + " (" + Math.round(overallScore*10)/10f + ")")); - - peekCommandExecutorService.shutdownNow(); - } else { - peekCommandExecutorService.schedule(this, 200, TimeUnit.MILLISECONDS); - } - } - }, 200, TimeUnit.MILLISECONDS); - } - }); - } - }, new SimpleCommand.TabCompleteRunnable() { - @Override - public java.util.List tabComplete(ICommandSender sender, String[] args, BlockPos pos) { - if (args.length != 1) return null; - - String lastArg = args[args.length - 1]; - List playerMatches = new ArrayList<>(); - for (EntityPlayer player : Minecraft.getMinecraft().theWorld.playerEntities) { - String playerName = player.getName(); - if (playerName.toLowerCase().startsWith(lastArg.toLowerCase())) { - playerMatches.add(playerName); - } - } - return playerMatches; - } - }); - - public SimpleCommand.ProcessCommandRunnable viewProfileRunnable = new SimpleCommand.ProcessCommandRunnable() { - public void processCommand(ICommandSender sender, String[] args) { - if(!OpenGlHelper.isFramebufferEnabled()) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + - "Some parts of the profile viewer do not work with OF Fast Render. Go to ESC > Options > Video Settings > Performance > Fast Render to disable it.")); - - } - if (NotEnoughUpdates.INSTANCE.config.apiKey.apiKey == null || NotEnoughUpdates.INSTANCE.config.apiKey.apiKey.trim().isEmpty()) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + - "Can't view profile, apikey is not set. Run /api new and put the result in settings.")); - } else if (args.length == 0) { - NotEnoughUpdates.INSTANCE.profileViewer.getProfileByName(Minecraft.getMinecraft().thePlayer.getName(), profile -> { - if(profile == null) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + - "Invalid player name/api key. Maybe api is down? Try /api new.")); - } else { - profile.resetCache(); - NotEnoughUpdates.INSTANCE.openGui = new GuiProfileViewer(profile); - } - }); - } else if (args.length > 1) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + - "Too many arguments. Usage: /neuprofile [name]")); - } else { - NotEnoughUpdates.INSTANCE.profileViewer.getProfileByName(args[0], profile -> { - if(profile == null) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + - "Invalid player name/api key. Maybe api is down? Try /api new.")); - } else { - profile.resetCache(); - NotEnoughUpdates.INSTANCE.openGui = new GuiProfileViewer(profile); - } - }); - } - } - }; - - - SimpleCommand joinDungeonCommand = new SimpleCommand("join", new SimpleCommand.ProcessCommandRunnable() { - @Override - public void processCommand(ICommandSender sender, String[] args) { - if (!NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) { - Minecraft.getMinecraft().thePlayer.sendChatMessage("/join " + StringUtils.join(args, " ")); - } else { - if(args.length != 1) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.RED+"Example Usage: /join f7, /join m6 or /join 7")); - } else { - String cataPrefix = "catacombs"; - if(args[0].startsWith("m")){ - cataPrefix = "master_catacombs"; - } - String cmd = "/joindungeon "+cataPrefix+" " + args[0].charAt(args[0].length()-1); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.YELLOW+"Running command: "+cmd)); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.YELLOW+"The dungeon should start soon. If it doesn't, make sure you have a party of 5 people")); - Minecraft.getMinecraft().thePlayer.sendChatMessage(cmd); - } - } - } - }); - - SimpleCommand viewProfileCommand = new SimpleCommand("neuprofile", viewProfileRunnable, new SimpleCommand.TabCompleteRunnable() { - @Override - public List tabComplete(ICommandSender sender, String[] args, BlockPos pos) { - if(args.length != 1) return null; - - String lastArg = args[args.length-1]; - List playerMatches = new ArrayList<>(); - for(EntityPlayer player : Minecraft.getMinecraft().theWorld.playerEntities) { - String playerName = player.getName(); - if(playerName.toLowerCase().startsWith(lastArg.toLowerCase())) { - playerMatches.add(playerName); - } - } - return playerMatches; - } - }); - - SimpleCommand viewProfileShortCommand = new SimpleCommand("pv", new SimpleCommand.ProcessCommandRunnable() { - @Override - public void processCommand(ICommandSender sender, String[] args) { - if(!NotEnoughUpdates.INSTANCE.isOnSkyblock()) { - Minecraft.getMinecraft().thePlayer.sendChatMessage("/pv " + StringUtils.join(args, " ")); - } else { - viewProfileRunnable.processCommand(sender, args); - } - } - }, new SimpleCommand.TabCompleteRunnable() { - @Override - public List tabComplete(ICommandSender sender, String[] args, BlockPos pos) { - if (args.length != 1) return null; - - String lastArg = args[args.length - 1]; - List playerMatches = new ArrayList<>(); - for (EntityPlayer player : Minecraft.getMinecraft().theWorld.playerEntities) { - String playerName = player.getName(); - if (playerName.toLowerCase().startsWith(lastArg.toLowerCase())) { - playerMatches.add(playerName); - } - } - return playerMatches; - } - }); - - SimpleCommand dhCommand = new SimpleCommand("dh", new SimpleCommand.ProcessCommandRunnable() { - @Override - public void processCommand(ICommandSender sender, String[] args) { - Minecraft.getMinecraft().thePlayer.sendChatMessage("/warp dungeon_hub"); - } - }); - - private ScheduledExecutorService devES = Executors.newSingleThreadScheduledExecutor(); - private static final String[] devFailStrings = {"No.", "I said no.", "You aren't allowed to use this.", - "Are you sure you want to use this? Type 'Yes' in chat.", "Are you sure you want to use this? Type 'Yes' in chat.", - "Lmao you thought", "Ok please stop", "What do you want from me?", - "This command almost certainly does nothing useful for you", - "Ok, this is the last message, after this it will repeat", "No.", "I said no.", "Dammit. I thought that would work. Uhh...", - "\u00a7dFrom \u00a7c[ADMIN] Minikloon\u00a77: If you use that command again, I'll have to ban you", "", - "Ok, this is actually the last message, use the command again and you'll crash I promise"}; - private int devFailIndex = 0; - - private static final List devTestUsers = new ArrayList<>(Arrays.asList("moulberry", "lucycoconut", "ironm00n", "ariyio")); - SimpleCommand devTestCommand = new SimpleCommand("neudevtest", new SimpleCommand.ProcessCommandRunnable() { - @Override - public void processCommand(ICommandSender sender, String[] args) { - if(!devTestUsers.contains(Minecraft.getMinecraft().thePlayer.getName().toLowerCase())) { - if(devFailIndex >= devFailStrings.length) { - throw new Error("L") { - @Override - public void printStackTrace() { - throw new Error("L"); - } - }; - } - if(devFailIndex == devFailStrings.length-2) { - devFailIndex++; - - ChatComponentText component = new ChatComponentText("\u00a7cYou are permanently banned from this server!"); - component.appendText("\n"); - component.appendText("\n\u00a77Reason: \u00a7rI told you not to run the command - Moulberry"); - component.appendText("\n\u00a77Find out more: \u00a7b\u00a7nhttps://www.hypixel.net/appeal"); - component.appendText("\n"); - component.appendText("\n\u00a77Ban ID: \u00a7r#49871982"); - component.appendText("\n\u00a77Sharing your Ban ID may affect the processing of your appeal!"); - Minecraft.getMinecraft().getNetHandler().getNetworkManager().closeChannel(component); - return; - } - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED+devFailStrings[devFailIndex++])); - return; - } - /*if(args.length == 1) { - DupePOC.doDupe(args[0]); - return; - }*/ - if(args.length == 1 && args[0].equalsIgnoreCase("positiontest")) { - NotEnoughUpdates.INSTANCE.openGui = new GuiPositionEditor(); - return; - } - - if(args.length == 2 && args[0].equalsIgnoreCase("pt")) { - EnumParticleTypes t = EnumParticleTypes.valueOf(args[1]); - FishingHelper.type = t; - return; - } - if(args.length == 1 && args[0].equalsIgnoreCase("dev")) { - NotEnoughUpdates.INSTANCE.config.hidden.dev = true; - return; - } - if(args.length == 1 && args[0].equalsIgnoreCase("saveconfig")) { - NotEnoughUpdates.INSTANCE.saveConfig(); - return; - } - if(args.length == 1 && args[0].equalsIgnoreCase("center")) { - double x = Math.floor(Minecraft.getMinecraft().thePlayer.posX) + 0.5f; - double z = Math.floor(Minecraft.getMinecraft().thePlayer.posZ) + 0.5f; - Minecraft.getMinecraft().thePlayer.setPosition(x, Minecraft.getMinecraft().thePlayer.posY, z); - return; - } - if(args.length == 1 && args[0].equalsIgnoreCase("pansc")) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.GREEN+"Taking panorama screenshot")); - - AtomicInteger perspective = new AtomicInteger(0); - FancyPortals.perspectiveId = 0; - - EntityPlayerSP p = Minecraft.getMinecraft().thePlayer; - p.prevRotationYaw = p.rotationYaw = 0; - p.prevRotationPitch = p.rotationPitch = 90; - devES.schedule(new Runnable() { - @Override - public void run() { - Minecraft.getMinecraft().addScheduledTask(() -> { - ScreenShotHelper.saveScreenshot(new File("C:/Users/James/Desktop/"), "pansc-"+perspective.get()+".png", - Minecraft.getMinecraft().displayWidth, Minecraft.getMinecraft().displayHeight, - Minecraft.getMinecraft().getFramebuffer()); - }); - if(perspective.incrementAndGet() >= 6) { - FancyPortals.perspectiveId = -1; - return; - } - devES.schedule(() -> { - FancyPortals.perspectiveId = perspective.get(); - if(FancyPortals.perspectiveId == 5) { - p.prevRotationYaw = p.rotationYaw = 0; - p.prevRotationPitch = p.rotationPitch = -90; - } else if(FancyPortals.perspectiveId >= 1 && FancyPortals.perspectiveId <= 4) { - float yaw = 90*FancyPortals.perspectiveId-180; - if(yaw > 180) yaw -= 360; - p.prevRotationYaw = p.rotationYaw = yaw; - p.prevRotationPitch = p.rotationPitch = 0; - } - devES.schedule(this, 3000L, TimeUnit.MILLISECONDS); - }, 100L, TimeUnit.MILLISECONDS); - } - }, 3000L, TimeUnit.MILLISECONDS); - - return; - } - - /* if(args.length == 1 && args[0].equalsIgnoreCase("update")) { - NEUEventListener.displayUpdateMessageIfOutOfDate(); - } */ - - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.GREEN+"Executing dubious code")); - /*Minecraft.getMinecraft().thePlayer.rotationYaw = 0; - Minecraft.getMinecraft().thePlayer.rotationPitch = 0; - Minecraft.getMinecraft().thePlayer.setPosition( - Math.floor(Minecraft.getMinecraft().thePlayer.posX) + Float.parseFloat(args[0]), - Minecraft.getMinecraft().thePlayer.posY, - Minecraft.getMinecraft().thePlayer.posZ);*/ - //Hot reload me yay! - } - }); - - SimpleCommand packDevCommand = new SimpleCommand("neupackdev", new SimpleCommand.ProcessCommandRunnable() { - @Override - public void processCommand(ICommandSender sender, String[] args) { - if(args.length == 1 && args[0].equalsIgnoreCase("getnpc")) { - double distSq = 25; - EntityPlayer closestNPC = null; - EntityPlayerSP p = Minecraft.getMinecraft().thePlayer; - for(EntityPlayer player : Minecraft.getMinecraft().theWorld.playerEntities) { - if(player instanceof AbstractClientPlayer && p != player && player.getUniqueID().version() != 4) { - double dSq = player.getDistanceSq(p.posX, p.posY, p.posZ); - if(dSq < distSq) { - distSq = dSq; - closestNPC = player; - } - } - } - - if(closestNPC == null) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED+"No NPCs found within 5 blocks :(")); - } else { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.GREEN+"Copied entity texture id to clipboard")); - MiscUtils.copyToClipboard(((AbstractClientPlayer)closestNPC).getLocationSkin().getResourcePath().replace("skins/", "")); - } - return; - } - NotEnoughUpdates.INSTANCE.packDevEnabled = !NotEnoughUpdates.INSTANCE.packDevEnabled; - if(NotEnoughUpdates.INSTANCE.packDevEnabled) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.GREEN+"Enabled pack developer mode.")); - } else { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED+"Disabled pack developer mode.")); - } - } - }); - - SimpleCommand dnCommand = new SimpleCommand("dn", new SimpleCommand.ProcessCommandRunnable() { - @Override - public void processCommand(ICommandSender sender, String[] args) { - Minecraft.getMinecraft().thePlayer.sendChatMessage("/warp dungeon_hub"); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.AQUA+"Warping to:"+EnumChatFormatting.YELLOW+" Deez Nuts lmao")); - } - }); - - SimpleCommand viewCataCommand = new SimpleCommand("cata", new SimpleCommand.ProcessCommandRunnable() { - @Override - public void processCommand(ICommandSender sender, String[] args) { - GuiProfileViewer.currentPage = GuiProfileViewer.ProfileViewerPage.DUNG; - viewProfileRunnable.processCommand(sender, args); - } - }, new SimpleCommand.TabCompleteRunnable() { - @Override - public List tabComplete(ICommandSender sender, String[] args, BlockPos pos) { - if (args.length != 1) return null; - - String lastArg = args[args.length - 1]; - List playerMatches = new ArrayList<>(); - for (EntityPlayer player : Minecraft.getMinecraft().theWorld.playerEntities) { - String playerName = player.getName(); - if (playerName.toLowerCase().startsWith(lastArg.toLowerCase())) { - playerMatches.add(playerName); - } - } - return playerMatches; - } - }); - - SimpleCommand linksCommand = new SimpleCommand("neulinks", new SimpleCommand.ProcessCommandRunnable() { - public void processCommand(ICommandSender sender, String[] args) { - File repo = NotEnoughUpdates.INSTANCE.manager.repoLocation; - if(repo.exists()) { - File updateJson = new File(repo, "update.json"); - try { - JsonObject update = NotEnoughUpdates.INSTANCE.manager.getJsonFromFile(updateJson); - - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); - NotEnoughUpdates.INSTANCE.displayLinks(update); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); - } catch (Exception ignored) { - } - } - } - }); - - SimpleCommand overlayPlacementsCommand = new SimpleCommand("neuoverlay", new SimpleCommand.ProcessCommandRunnable() { - public void processCommand(ICommandSender sender, String[] args) { - NotEnoughUpdates.INSTANCE.openGui = new NEUOverlayPlacements(); - } - }); - - SimpleCommand tutorialCommand = new SimpleCommand("neututorial", new SimpleCommand.ProcessCommandRunnable() { - public void processCommand(ICommandSender sender, String[] args) { - NotEnoughUpdates.INSTANCE.openGui = new NeuTutorial(); - } - }); - - - SimpleCommand neumapCommand = new SimpleCommand("neumap", new SimpleCommand.ProcessCommandRunnable() { - public void processCommand(ICommandSender sender, String[] args) { - if(NotEnoughUpdates.INSTANCE.colourMap == null) { - try(BufferedReader reader = new BufferedReader(new InputStreamReader(Minecraft.getMinecraft().getResourceManager().getResource( - new ResourceLocation("notenoughupdates:maps/F1Full.json")).getInputStream(), StandardCharsets.UTF_8))) { - JsonObject json = NotEnoughUpdates.INSTANCE.manager.gson.fromJson(reader, JsonObject.class); - - NotEnoughUpdates.INSTANCE.colourMap = new Color[128][128]; - for(int x=0; x<128; x++) { - for(int y=0; y<128; y++) { - NotEnoughUpdates.INSTANCE.colourMap[x][y] = new Color(0, 0, 0, 0); - } - } - for(Map.Entry entry : json.entrySet()) { - int x = Integer.parseInt(entry.getKey().split(":")[0]); - int y = Integer.parseInt(entry.getKey().split(":")[1]); - - NotEnoughUpdates.INSTANCE.colourMap[x][y] = new Color(entry.getValue().getAsInt(), true); - } - } catch(Exception ignored) { } - } - - if(!NotEnoughUpdates.INSTANCE.config.hidden.dev) { - NotEnoughUpdates.INSTANCE.openGui = new GuiDungeonMapEditor(); - return; - } - - if(args.length == 1 && args[0].equals("reset")) { - NotEnoughUpdates.INSTANCE.colourMap = null; - return; - } - - if(args.length != 2) { - NotEnoughUpdates.INSTANCE.openGui = new GuiDungeonMapEditor(); - return; - } - - if(args[0].equals("save")) { - ItemStack stack = Minecraft.getMinecraft().thePlayer.getHeldItem(); - if(stack != null && stack.getItem() instanceof ItemMap) { - ItemMap map = (ItemMap) stack.getItem(); - MapData mapData = map.getMapData(stack, Minecraft.getMinecraft().theWorld); - - if (mapData == null) return; - - JsonObject json = new JsonObject(); - for (int i = 0; i < 16384; ++i) { - int x = i % 128; - int y = i / 128; - - int j = mapData.colors[i] & 255; - - Color c; - if (j / 4 == 0) { - c = new Color((i + i / 128 & 1) * 8 + 16 << 24, true); - } else { - c = new Color(MapColor.mapColorArray[j / 4].getMapColor(j & 3), true); - } - - json.addProperty(x+":"+y, c.getRGB()); - } - - try { - new File(NotEnoughUpdates.INSTANCE.manager.configLocation, "maps").mkdirs(); - NotEnoughUpdates.INSTANCE.manager.writeJson(json, new File(NotEnoughUpdates.INSTANCE.manager.configLocation, "maps/"+args[1]+".json")); - } catch(Exception e) { - e.printStackTrace(); - } - - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.GREEN+ - "Saved to file.")); - } - - return; - } - - if(args[0].equals("load")) { - JsonObject json = NotEnoughUpdates.INSTANCE.manager.getJsonFromFile(new File(NotEnoughUpdates.INSTANCE.manager.configLocation, "maps/"+args[1]+".json")); - - NotEnoughUpdates.INSTANCE.colourMap = new Color[128][128]; - for(int x=0; x<128; x++) { - for(int y=0; y<128; y++) { - NotEnoughUpdates.INSTANCE.colourMap[x][y] = new Color(0, 0, 0, 0); - } - } - for(Map.Entry entry : json.entrySet()) { - int x = Integer.parseInt(entry.getKey().split(":")[0]); - int y = Integer.parseInt(entry.getKey().split(":")[1]); - - NotEnoughUpdates.INSTANCE.colourMap[x][y] = new Color(entry.getValue().getAsInt(), true); - } - - return; - } - - NotEnoughUpdates.INSTANCE.openGui = new GuiDungeonMapEditor(); - } - }); - - SimpleCommand cosmeticsCommand = new SimpleCommand("neucosmetics", new SimpleCommand.ProcessCommandRunnable() { - public void processCommand(ICommandSender sender, String[] args) { - if(!OpenGlHelper.isFramebufferEnabled()) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + - "NEU cosmetics do not work with OF Fast Render. Go to ESC > Options > Video Settings > Performance > Fast Render to disable it.")); - - } - - NotEnoughUpdates.INSTANCE.openGui = new GuiCosmetics(); - } - }); - - SimpleCommand.ProcessCommandRunnable customizeRunnable = new SimpleCommand.ProcessCommandRunnable() { - public void processCommand(ICommandSender sender, String[] args) { - ItemStack held = Minecraft.getMinecraft().thePlayer.getHeldItem(); - - if(held == null) { - sender.addChatMessage(new ChatComponentText("\u00a7cYou can't customize your hand...")); - return; - } - - String heldUUID = NotEnoughUpdates.INSTANCE.manager.getUUIDForItem(held); - - if(heldUUID == null) { - sender.addChatMessage(new ChatComponentText("\u00a7cHeld item does not have UUID, cannot be customized")); - return; - } - - NotEnoughUpdates.INSTANCE.openGui = new GuiItemCustomize(held, heldUUID); - } - }; - - SimpleCommand customizeCommand = new SimpleCommand("neucustomize", customizeRunnable); - SimpleCommand customizeCommand2 = new SimpleCommand("neurename", customizeRunnable); - - SimpleCommand.ProcessCommandRunnable settingsRunnable = new SimpleCommand.ProcessCommandRunnable() { - public void processCommand(ICommandSender sender, String[] args) { - if(args.length > 0) { - NotEnoughUpdates.INSTANCE.openGui = new GuiScreenElementWrapper(new NEUConfigEditor(NotEnoughUpdates.INSTANCE.config, StringUtils.join(args, " "))); - } else { - NotEnoughUpdates.INSTANCE.openGui = new GuiScreenElementWrapper(NEUConfigEditor.editor); - } - } - }; - - SimpleCommand settingsCommand = new SimpleCommand("neu", settingsRunnable); - SimpleCommand settingsCommand2 = new SimpleCommand("neusettings", settingsRunnable); - SimpleCommand settingsCommand3 = new SimpleCommand("neuconfig", settingsRunnable); - - SimpleCommand calendarCommand = new SimpleCommand("neucalendar", new SimpleCommand.ProcessCommandRunnable() { - public void processCommand(ICommandSender sender, String[] args) { - Minecraft.getMinecraft().thePlayer.closeScreen(); - CalendarOverlay.setEnabled(true); - NotEnoughUpdates.INSTANCE.sendChatMessage("/calendar"); - } - }); - - SimpleCommand neuAhCommand = new SimpleCommand("neuah", new SimpleCommand.ProcessCommandRunnable() { - public void processCommand(ICommandSender sender, String[] args) { - if(!NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED+ - "You must be on Skyblock to use this feature.")); - } else if(NotEnoughUpdates.INSTANCE.config.apiKey.apiKey == null || NotEnoughUpdates.INSTANCE.config.apiKey.apiKey.trim().isEmpty()) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED+ - "Can't open NeuAH, apikey is not set. Run /api new and put the result in settings.")); - } else { - NotEnoughUpdates.INSTANCE.openGui = new CustomAHGui(); - NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.lastOpen = System.currentTimeMillis(); - NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.clearSearch(); - NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.updateSearch(); - - if(args.length > 0) NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.setSearch(StringUtils.join(args, " ")); - } - } - }); + public Commands() { + + // Help Commands + ClientCommandHandler.instance.registerCommand(new LinksCommand()); + ClientCommandHandler.instance.registerCommand(new HelpCommand()); + ClientCommandHandler.instance.registerCommand(new StorageViewerWhyCommand()); + ClientCommandHandler.instance.registerCommand(new FeaturesCommand()); + ClientCommandHandler.instance.registerCommand(new SettingsCommand()); + + // Dev Commands + ClientCommandHandler.instance.registerCommand(new PackDevCommand()); + ClientCommandHandler.instance.registerCommand(new DungeonWinTestCommand()); + ClientCommandHandler.instance.registerCommand(new StatsCommand()); + ClientCommandHandler.instance.registerCommand(new DevTestCommand()); + ClientCommandHandler.instance.registerCommand(new NullzeeSphereCommand()); + + // Repo Commands + ClientCommandHandler.instance.registerCommand(new ResetRepoCommand()); + ClientCommandHandler.instance.registerCommand(new RepoModeCommand()); + ClientCommandHandler.instance.registerCommand(new ReloadRepoCommand()); + + // Profile Commands + ClientCommandHandler.instance.registerCommand(new PeekCommand()); + ClientCommandHandler.instance.registerCommand(new ViewProfileCommand()); + ClientCommandHandler.instance.registerCommand(new PvCommand()); + if (!Loader.isModLoaded("skyblockextras")) ClientCommandHandler.instance.registerCommand(new CataCommand()); + + // Dungeon Commands + ClientCommandHandler.instance.registerCommand(new MapCommand()); + ClientCommandHandler.instance.registerCommand(new JoinDungeonCommand()); + ClientCommandHandler.instance.registerCommand(new DnCommand()); + ClientCommandHandler.instance.registerCommand(new DhCommand()); + + // Misc Commands + ClientCommandHandler.instance.registerCommand(new CosmeticsCommand()); + ClientCommandHandler.instance.registerCommand(new CustomizeCommand()); + ClientCommandHandler.instance.registerCommand(new ScreenCommand("neubuttons", GuiInvButtonEditor::new)); + ClientCommandHandler.instance.registerCommand(new ScreenCommand("neuec", GuiEnchantColour::new)); + ClientCommandHandler.instance.registerCommand(new ScreenCommand("neuoverlay", NEUOverlayPlacements::new)); + //ClientCommandHandler.instance.registerCommand(new ScreenCommand("neututorial", NeuTutorial::new)); + ClientCommandHandler.instance.registerCommand(new AhCommand()); + ClientCommandHandler.instance.registerCommand(new CalendarCommand()); + + // Fairy Soul Commands + ClientCommandHandler.instance.registerCommand(new FairySouls.FairySoulsCommand()); + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/ScreenCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/ScreenCommand.java new file mode 100644 index 0000000000..29dd9d55a7 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/ScreenCommand.java @@ -0,0 +1,26 @@ +package io.github.moulberry.notenoughupdates.commands; + +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; + +public class ScreenCommand extends ClientCommandBase { + + private final ScreenOpener opener; + + protected ScreenCommand(String name, ScreenOpener opener) { + super(name); + this.opener = opener; + } + + @Override + public void processCommand(ICommandSender sender, String[] args) throws CommandException { + NotEnoughUpdates.INSTANCE.openGui = opener.open(); + } + + @FunctionalInterface + public interface ScreenOpener { + GuiScreen open(); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/SimpleCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/SimpleCommand.java deleted file mode 100644 index 029e24dbe4..0000000000 --- a/src/main/java/io/github/moulberry/notenoughupdates/commands/SimpleCommand.java +++ /dev/null @@ -1,56 +0,0 @@ -package io.github.moulberry.notenoughupdates.commands; - -import net.minecraft.command.CommandBase; -import net.minecraft.command.CommandException; -import net.minecraft.command.ICommandSender; -import net.minecraft.util.BlockPos; - -import java.util.ArrayList; -import java.util.List; - -public class SimpleCommand extends CommandBase { - - private String commandName; - private ProcessCommandRunnable runnable; - private TabCompleteRunnable tabRunnable; - - public SimpleCommand(String commandName, ProcessCommandRunnable runnable) { - this.commandName = commandName; - this.runnable = runnable; - } - - public SimpleCommand(String commandName, ProcessCommandRunnable runnable, TabCompleteRunnable tabRunnable) { - this.commandName = commandName; - this.runnable = runnable; - this.tabRunnable = tabRunnable; - } - - public abstract static class ProcessCommandRunnable { - public abstract void processCommand(ICommandSender sender, String[] args); - } - - public abstract static class TabCompleteRunnable { - public abstract List tabComplete(ICommandSender sender, String[] args, BlockPos pos); - } - - public boolean canCommandSenderUseCommand(ICommandSender sender) { - return true; - } - - public String getCommandName() { - return commandName; - } - - public String getCommandUsage(ICommandSender sender) { - return "/" + commandName; - } - - public void processCommand(ICommandSender sender, String[] args) throws CommandException { - runnable.processCommand(sender, args); - } - - public List addTabCompletionOptions(ICommandSender sender, String[] args, BlockPos pos) { - if(tabRunnable != null) return tabRunnable.tabComplete(sender, args, pos); - return null; - } -} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/StatsCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/StatsCommand.java deleted file mode 100644 index b61c58ede6..0000000000 --- a/src/main/java/io/github/moulberry/notenoughupdates/commands/StatsCommand.java +++ /dev/null @@ -1,146 +0,0 @@ -package io.github.moulberry.notenoughupdates.commands; - -import io.github.moulberry.notenoughupdates.NotEnoughUpdates; -import io.github.moulberry.notenoughupdates.util.DiscordMarkdownBuilder; -import io.github.moulberry.notenoughupdates.util.HastebinUploader; -import io.github.moulberry.notenoughupdates.util.SBInfo; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.OpenGlHelper; -import net.minecraft.command.ICommandSender; -import net.minecraft.util.BlockPos; -import net.minecraft.util.ChatComponentText; -import net.minecraft.util.EnumChatFormatting; -import net.minecraftforge.common.ForgeVersion; -import net.minecraftforge.fml.common.Loader; -import org.lwjgl.opengl.Display; -import org.lwjgl.opengl.GL11; - -import javax.management.JMX; -import javax.management.MBeanServer; -import javax.management.ObjectName; -import java.awt.*; -import java.awt.datatransfer.StringSelection; -import java.lang.management.ManagementFactory; -import java.util.List; -import java.util.Locale; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -public class StatsCommand extends ClientCommandBase { - - private final ExecutorService threadPool = Executors.newFixedThreadPool(1); - - public StatsCommand() { - super("neustats"); - } - - @Override - public void processCommand(ICommandSender sender, String[] args) { - if (args.length > 0){ - switch (args[0].toLowerCase(Locale.ROOT)) { - case "modlist": - clipboardAndSendMessage(createModList(new DiscordMarkdownBuilder()).toString()); - break; - case "dump": - modPrefixedMessage(EnumChatFormatting.GREEN + "This will upload a dump of the java classes your game has loaded how big they are and how many there are. This can take a few seconds as it is uploading to HasteBin."); - threadPool.submit(() -> { - try { - final MBeanServer server = ManagementFactory.getPlatformMBeanServer(); - final ObjectName objectName = ObjectName.getInstance("com.sun.management:type=DiagnosticCommand"); - final DiagnosticCommandMXBean proxy = JMX.newMXBeanProxy(server, objectName, DiagnosticCommandMXBean.class); - clipboardAndSendMessage(HastebinUploader.upload(proxy.gcClassHistogram(new String[0]).replace("[", "[]"), HastebinUploader.Mode.NORMAL)); - }catch (Exception e){ - clipboardAndSendMessage(null); - } - }); - break; - } - } else { - clipboardAndSendMessage(createStats()); - } - - } - - @Override - public List addTabCompletionOptions(ICommandSender sender, String[] args, BlockPos pos) { - return args.length == 1 ? getListOfStringsMatchingLastWord(args, "modlist", "dump") : null; - } - - public interface DiagnosticCommandMXBean { - String gcClassHistogram(String[] array); - } - - private static void clipboardAndSendMessage(String data) { - if (data == null) { - modPrefixedMessage(EnumChatFormatting.DARK_RED + "Error occurred trying to perform command."); - return; - } - try { - StringSelection clipboard = new StringSelection(data); - Toolkit.getDefaultToolkit().getSystemClipboard().setContents(clipboard, clipboard); - modPrefixedMessage(EnumChatFormatting.GREEN + "Dev info copied to clipboard."); - } catch (Exception ignored) { - modPrefixedMessage(EnumChatFormatting.DARK_RED + "Could not copy to clipboard."); - } - } - - private static void modPrefixedMessage(String message) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.GOLD + "[" + EnumChatFormatting.RED + "NotEnoughUpdates" + EnumChatFormatting.GOLD + "]: " + message)); - - } - - private static String createStats() { - DiscordMarkdownBuilder builder = new DiscordMarkdownBuilder(); - long maxMemory = Runtime.getRuntime().maxMemory(); - long totalMemory = Runtime.getRuntime().totalMemory(); - long freeMemory = Runtime.getRuntime().freeMemory(); - long currentMemory = totalMemory - freeMemory; - int activeModCount = Loader.instance().getActiveModList().size(); - - builder.category("System Stats"); - builder.append("OS", System.getProperty("os.name")); - builder.append("CPU", OpenGlHelper.getCpu()); - builder.append("Display", String.format("%dx%d (%s)", Display.getWidth(), Display.getHeight(), GL11.glGetString(GL11.GL_VENDOR))); - builder.append("GPU", GL11.glGetString(GL11.GL_RENDERER)); - builder.append("GPU Driver", GL11.glGetString(GL11.GL_VERSION)); - if(getMemorySize() > 0) builder.append("Maximum Memory", (getMemorySize() / 1024L / 1024L) + "MB"); - builder.append("Shaders", (""+OpenGlHelper.isFramebufferEnabled()).toUpperCase()); - builder.category("Java Stats"); - builder.append("Java", String.format("%s %dbit", System.getProperty("java.version"), Minecraft.getMinecraft().isJava64bit() ? 64 : 32)); - builder.append("Memory", String.format("% 2d%% %03d/%03dMB", currentMemory * 100L / maxMemory, currentMemory / 1024L / 1024L, maxMemory / 1024L / 1024L)); - builder.append("Memory Allocated", String.format("% 2d%% %03dMB", totalMemory * 100L / maxMemory, totalMemory / 1024L / 1024L)); - builder.category("Game Stats"); - builder.append("FPS", String.valueOf(Minecraft.getDebugFPS())); - builder.append("Loaded Mods", String.valueOf(activeModCount)); - builder.append("Forge", ForgeVersion.getVersion()); - builder.category("Neu Settings"); - builder.append("API Key", NotEnoughUpdates.INSTANCE.config.apiKey.apiKey.isEmpty() ? "FALSE" : "TRUE"); - builder.append("On Skyblock", NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() ? "TRUE" : "FALSE"); - builder.append("Mod Version", Loader.instance().getIndexedModList().get(NotEnoughUpdates.MODID).getSource().getName()); - builder.append("SB Profile", SBInfo.getInstance().currentProfile); - builder.category("Repo Stats"); - builder.append("Last Commit", NotEnoughUpdates.INSTANCE.manager.latestRepoCommit); - builder.append("Loaded Items", String.valueOf(NotEnoughUpdates.INSTANCE.manager.getItemInformation().size())); - if (activeModCount <= 15) createModList(builder); - - return builder.toString(); - } - - private static DiscordMarkdownBuilder createModList(DiscordMarkdownBuilder builder) { - builder.category("Mods Loaded"); - Loader.instance().getActiveModList().forEach(mod -> builder.append(mod.getName(), mod.getSource().getName())); - return builder; - } - - private static long getMemorySize(){ - try { - return ((com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean()).getTotalPhysicalMemorySize(); - } catch(Exception e){ - try { - return ((com.sun.management.UnixOperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean()).getTotalPhysicalMemorySize(); - } catch(Exception ignored){/*IGNORE*/} - } - return -1; - } - -} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DevTestCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DevTestCommand.java new file mode 100644 index 0000000000..66da4f9f32 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DevTestCommand.java @@ -0,0 +1,207 @@ +package io.github.moulberry.notenoughupdates.commands.dev; + +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; +import io.github.moulberry.notenoughupdates.core.config.GuiPositionEditor; +import io.github.moulberry.notenoughupdates.miscfeatures.FancyPortals; +import io.github.moulberry.notenoughupdates.miscfeatures.FishingHelper; +import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.CustomBiomes; +import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.LocationChangeEvent; +import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.SpecialBlockZone; +import io.github.moulberry.notenoughupdates.miscgui.GuiPriceGraph; +import io.github.moulberry.notenoughupdates.util.SBInfo; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.util.*; +import net.minecraftforge.common.MinecraftForge; + +import java.io.File; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +public class DevTestCommand extends ClientCommandBase { + + private static final List DEV_TESTERS = + Arrays.asList("moulberry", "lucycoconut", "ironm00n", "ariyio", "throwpo", "lrg89", "dediamondpro"); + + private static final String[] DEV_FAIL_STRINGS = { + "No.", + "I said no.", + "You aren't allowed to use this.", + "Are you sure you want to use this? Type 'Yes' in chat.", + "Are you sure you want to use this? Type 'Yes' in chat.", + "Lmao you thought", + "Ok please stop", + "What do you want from me?", + "This command almost certainly does nothing useful for you", + "Ok, this is the last message, after this it will repeat", + "No.", + "I said no.", + "Dammit. I thought that would work. Uhh...", + "\u00a7dFrom \u00a7c[ADMIN] Minikloon\u00a77: If you use that command again, I'll have to ban you", + "", + "Ok, this is actually the last message, use the command again and you'll crash I promise" + }; + + private int devFailIndex = 0; + private final ScheduledExecutorService devES = Executors.newSingleThreadScheduledExecutor(); + + public DevTestCommand() { + super("neudevtest"); + } + + @Override + public void processCommand(ICommandSender sender, String[] args) throws CommandException { + if (!DEV_TESTERS.contains(Minecraft.getMinecraft().thePlayer.getName().toLowerCase())) { + if (devFailIndex >= DEV_FAIL_STRINGS.length) { + throw new Error("L") { + @Override + public void printStackTrace() { + throw new Error("L"); + } + }; + } + if (devFailIndex == DEV_FAIL_STRINGS.length - 2) { + devFailIndex++; + + ChatComponentText component = new ChatComponentText("\u00a7cYou are permanently banned from this server!"); + component.appendText("\n"); + component.appendText("\n\u00a77Reason: \u00a7rI told you not to run the command - Moulberry"); + component.appendText("\n\u00a77Find out more: \u00a7b\u00a7nhttps://www.hypixel.net/appeal"); + component.appendText("\n"); + component.appendText("\n\u00a77Ban ID: \u00a7r#49871982"); + component.appendText("\n\u00a77Sharing your Ban ID may affect the processing of your appeal!"); + Minecraft.getMinecraft().getNetHandler().getNetworkManager().closeChannel(component); + return; + } + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + + DEV_FAIL_STRINGS[devFailIndex++])); + return; + } + /*if(args.length == 1) { + DupePOC.doDupe(args[0]); + return; + }*/ + if (args.length >= 1 && args[0].equalsIgnoreCase("profileinfo")) { + String currentProfile = SBInfo.getInstance().currentProfile; + SBInfo.Gamemode gamemode = SBInfo.getInstance().getGamemodeForProfile(currentProfile); + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.GOLD + + "You are on Profile " + + currentProfile + + " with the mode " + + gamemode)); + } + if (args.length >= 1 && args[0].equalsIgnoreCase("pricetest")) { + if (args.length == 1) { + NotEnoughUpdates.INSTANCE.manager.auctionManager.updateBazaar(); + } else { + NotEnoughUpdates.INSTANCE.openGui = new GuiPriceGraph(args[1]); + } + } + if (args.length == 1 && args[0].equalsIgnoreCase("zone")) { + BlockPos target = Minecraft.getMinecraft().objectMouseOver.getBlockPos(); + if (target == null) target = Minecraft.getMinecraft().thePlayer.getPosition(); + SpecialBlockZone zone = CustomBiomes.INSTANCE.getSpecialZone(target); + Arrays.asList( + new ChatComponentText("Showing Zone Info for: " + target), + new ChatComponentText("Zone: " + (zone != null ? zone.name() : "null")), + new ChatComponentText("Location: " + SBInfo.getInstance().getLocation()), + new ChatComponentText("Biome: " + CustomBiomes.INSTANCE.getCustomBiome(target)) + ).forEach(Minecraft.getMinecraft().thePlayer::addChatMessage); + MinecraftForge.EVENT_BUS.post(new LocationChangeEvent(SBInfo.getInstance().getLocation(), SBInfo + .getInstance() + .getLocation())); + } + if (args.length == 1 && args[0].equalsIgnoreCase("positiontest")) { + NotEnoughUpdates.INSTANCE.openGui = new GuiPositionEditor(); + return; + } + + if (args.length == 2 && args[0].equalsIgnoreCase("pt")) { + EnumParticleTypes t = EnumParticleTypes.valueOf(args[1]); + FishingHelper.type = t; + return; + } + if (args.length == 1 && args[0].equalsIgnoreCase("dev")) { + NotEnoughUpdates.INSTANCE.config.hidden.dev = true; + return; + } + if (args.length == 1 && args[0].equalsIgnoreCase("saveconfig")) { + NotEnoughUpdates.INSTANCE.saveConfig(); + return; + } + if (args.length == 1 && args[0].equalsIgnoreCase("searchmode")) { + NotEnoughUpdates.INSTANCE.config.hidden.firstTimeSearchFocus = true; + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.AQUA + + "I would never search")); + return; + } + if (args.length == 1 && args[0].equalsIgnoreCase("center")) { + double x = Math.floor(Minecraft.getMinecraft().thePlayer.posX) + 0.5f; + double z = Math.floor(Minecraft.getMinecraft().thePlayer.posZ) + 0.5f; + Minecraft.getMinecraft().thePlayer.setPosition(x, Minecraft.getMinecraft().thePlayer.posY, z); + return; + } + if (args.length == 1 && args[0].equalsIgnoreCase("pansc")) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.GREEN + + "Taking panorama screenshot")); + + AtomicInteger perspective = new AtomicInteger(0); + FancyPortals.perspectiveId = 0; + + EntityPlayerSP p = Minecraft.getMinecraft().thePlayer; + p.prevRotationYaw = p.rotationYaw = 0; + p.prevRotationPitch = p.rotationPitch = 90; + devES.schedule(new Runnable() { + @Override + public void run() { + Minecraft.getMinecraft().addScheduledTask(() -> { + ScreenShotHelper.saveScreenshot(new File("C:/Users/James/Desktop/"), "pansc-" + perspective.get() + ".png", + Minecraft.getMinecraft().displayWidth, Minecraft.getMinecraft().displayHeight, + Minecraft.getMinecraft().getFramebuffer() + ); + }); + if (perspective.incrementAndGet() >= 6) { + FancyPortals.perspectiveId = -1; + return; + } + devES.schedule(() -> { + FancyPortals.perspectiveId = perspective.get(); + if (FancyPortals.perspectiveId == 5) { + p.prevRotationYaw = p.rotationYaw = 0; + p.prevRotationPitch = p.rotationPitch = -90; + } else if (FancyPortals.perspectiveId >= 1 && FancyPortals.perspectiveId <= 4) { + float yaw = 90 * FancyPortals.perspectiveId - 180; + if (yaw > 180) yaw -= 360; + p.prevRotationYaw = p.rotationYaw = yaw; + p.prevRotationPitch = p.rotationPitch = 0; + } + devES.schedule(this, 3000L, TimeUnit.MILLISECONDS); + }, 100L, TimeUnit.MILLISECONDS); + } + }, 3000L, TimeUnit.MILLISECONDS); + + return; + } + + /* if(args.length == 1 && args[0].equalsIgnoreCase("update")) { + NEUEventListener.displayUpdateMessageIfOutOfDate(); + } */ + + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.GREEN + + "Executing dubious code")); + /*Minecraft.getMinecraft().thePlayer.rotationYaw = 0; + Minecraft.getMinecraft().thePlayer.rotationPitch = 0; + Minecraft.getMinecraft().thePlayer.setPosition( + Math.floor(Minecraft.getMinecraft().thePlayer.posX) + Float.parseFloat(args[0]), + Minecraft.getMinecraft().thePlayer.posY, + Minecraft.getMinecraft().thePlayer.posZ);*/ + //Hot reload me yay! + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DungeonWinTestCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DungeonWinTestCommand.java new file mode 100644 index 0000000000..223e154a2c --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DungeonWinTestCommand.java @@ -0,0 +1,23 @@ +package io.github.moulberry.notenoughupdates.commands.dev; + +import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; +import io.github.moulberry.notenoughupdates.dungeons.DungeonWin; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.util.ResourceLocation; + +public class DungeonWinTestCommand extends ClientCommandBase { + + public DungeonWinTestCommand() { + super("neudungeonwintest"); + } + + @Override + public void processCommand(ICommandSender sender, String[] args) throws CommandException { + if (args.length > 0) { + DungeonWin.TEAM_SCORE = new ResourceLocation("notenoughupdates:dungeon_win/" + args[0].toLowerCase() + ".png"); + } + + DungeonWin.displayWin(); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/NullzeeSphereCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/NullzeeSphereCommand.java new file mode 100644 index 0000000000..64d645451a --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/NullzeeSphereCommand.java @@ -0,0 +1,42 @@ +package io.github.moulberry.notenoughupdates.commands.dev; + +import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; +import io.github.moulberry.notenoughupdates.miscfeatures.NullzeeSphere; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.util.BlockPos; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.EnumChatFormatting; + +public class NullzeeSphereCommand extends ClientCommandBase { + + public NullzeeSphereCommand() { + super("neuzeesphere"); + } + + @Override + public void processCommand(ICommandSender sender, String[] args) throws CommandException { + if (args.length != 1) { + sender.addChatMessage(new ChatComponentText( + EnumChatFormatting.RED + "Usage: /neuzeesphere [on/off] or /neuzeesphere (radius) or /neuzeesphere setCenter")); + return; + } + if (args[0].equalsIgnoreCase("on")) { + NullzeeSphere.enabled = true; + } else if (args[0].equalsIgnoreCase("off")) { + NullzeeSphere.enabled = false; + } else if (args[0].equalsIgnoreCase("setCenter")) { + EntityPlayerSP p = ((EntityPlayerSP) sender); + NullzeeSphere.centerPos = new BlockPos(p.posX, p.posY, p.posZ); + NullzeeSphere.overlayVBO = null; + } else { + try { + NullzeeSphere.size = Float.parseFloat(args[0]); + NullzeeSphere.overlayVBO = null; + } catch (Exception e) { + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + "Can't parse radius: " + args[0])); + } + } + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/PackDevCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/PackDevCommand.java new file mode 100644 index 0000000000..e809ed7234 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/PackDevCommand.java @@ -0,0 +1,59 @@ +package io.github.moulberry.notenoughupdates.commands.dev; + +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; +import io.github.moulberry.notenoughupdates.core.util.MiscUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.AbstractClientPlayer; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.EnumChatFormatting; + +public class PackDevCommand extends ClientCommandBase { + + public PackDevCommand() { + super("neupackdev"); + } + + @Override + public void processCommand(ICommandSender sender, String[] args) throws CommandException { + if (args.length == 1 && args[0].equalsIgnoreCase("getnpc")) { + double distSq = 25; + EntityPlayer closestNPC = null; + EntityPlayerSP p = Minecraft.getMinecraft().thePlayer; + for (EntityPlayer player : Minecraft.getMinecraft().theWorld.playerEntities) { + if (player instanceof AbstractClientPlayer && p != player && player.getUniqueID().version() != 4) { + double dSq = player.getDistanceSq(p.posX, p.posY, p.posZ); + if (dSq < distSq) { + distSq = dSq; + closestNPC = player; + } + } + } + + if (closestNPC == null) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( + EnumChatFormatting.RED + "No NPCs found within 5 blocks :(")); + } else { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( + EnumChatFormatting.GREEN + "Copied entity texture id to clipboard")); + MiscUtils.copyToClipboard(((AbstractClientPlayer) closestNPC) + .getLocationSkin() + .getResourcePath() + .replace("skins/", "")); + } + return; + } + NotEnoughUpdates.INSTANCE.packDevEnabled = !NotEnoughUpdates.INSTANCE.packDevEnabled; + if (NotEnoughUpdates.INSTANCE.packDevEnabled) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( + EnumChatFormatting.GREEN + "Enabled pack developer mode.")); + } else { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( + EnumChatFormatting.RED + "Disabled pack developer mode.")); + } + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/StatsCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/StatsCommand.java new file mode 100644 index 0000000000..38eafe3946 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/StatsCommand.java @@ -0,0 +1,181 @@ +package io.github.moulberry.notenoughupdates.commands.dev; + +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; +import io.github.moulberry.notenoughupdates.util.DiscordMarkdownBuilder; +import io.github.moulberry.notenoughupdates.util.HastebinUploader; +import io.github.moulberry.notenoughupdates.util.SBInfo; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.command.ICommandSender; +import net.minecraft.util.BlockPos; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.EnumChatFormatting; +import net.minecraftforge.common.ForgeVersion; +import net.minecraftforge.fml.common.Loader; +import org.lwjgl.opengl.Display; +import org.lwjgl.opengl.GL11; + +import javax.management.JMX; +import javax.management.MBeanServer; +import javax.management.ObjectName; +import java.awt.*; +import java.awt.datatransfer.StringSelection; +import java.lang.management.ManagementFactory; +import java.util.List; +import java.util.Locale; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class StatsCommand extends ClientCommandBase { + private final ExecutorService threadPool = Executors.newFixedThreadPool(1); + + public StatsCommand() { + super("neustats"); + } + + private static final int activeModCount = Loader.instance().getActiveModList().size(); + + @Override + public void processCommand(ICommandSender sender, String[] args) { + if (args.length > 0) { + switch (args[0].toLowerCase(Locale.ROOT)) { + case "modlist": + if (activeModCount > 15) { + clipboardAndSendMessage(createModList(new DiscordMarkdownBuilder()).toString()); + } else { + clipboardAndSendMessage(createStats()); + } + break; + case "dump": + modPrefixedMessage(EnumChatFormatting.GREEN + + "This will upload a dump of the java classes your game has loaded how big they are and how many there are. This can take a few seconds as it is uploading to HasteBin."); + threadPool.submit(() -> { + try { + final MBeanServer server = ManagementFactory.getPlatformMBeanServer(); + final ObjectName objectName = ObjectName.getInstance("com.sun.management:type=DiagnosticCommand"); + final DiagnosticCommandMXBean proxy = JMX.newMXBeanProxy( + server, + objectName, + DiagnosticCommandMXBean.class + ); + clipboardAndSendMessage(HastebinUploader.upload( + proxy.gcClassHistogram(new String[0]).replace("[", "[]"), + HastebinUploader.Mode.NORMAL + )); + } catch (Exception e) { + clipboardAndSendMessage(null); + } + }); + break; + } + } else { + clipboardAndSendMessage(createStats()); + } + + } + + @Override + public List addTabCompletionOptions(ICommandSender sender, String[] args, BlockPos pos) { + return args.length == 1 ? getListOfStringsMatchingLastWord(args, "modlist", "dump") : null; + } + + public interface DiagnosticCommandMXBean { + String gcClassHistogram(String[] array); + } + + private static void clipboardAndSendMessage(String data) { + if (data == null) { + modPrefixedMessage(EnumChatFormatting.DARK_RED + "Error occurred trying to perform command."); + return; + } + try { + StringSelection clipboard = new StringSelection(data); + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(clipboard, clipboard); + modPrefixedMessage(EnumChatFormatting.GREEN + "Dev info copied to clipboard."); + } catch (Exception ignored) { + modPrefixedMessage(EnumChatFormatting.DARK_RED + "Could not copy to clipboard."); + } + } + + private static void modPrefixedMessage(String message) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( + EnumChatFormatting.GOLD + "[" + EnumChatFormatting.RED + "NotEnoughUpdates" + EnumChatFormatting.GOLD + "]: " + + message)); + + } + + private static String createStats() { + DiscordMarkdownBuilder builder = new DiscordMarkdownBuilder(); + long maxMemory = Runtime.getRuntime().maxMemory(); + long totalMemory = Runtime.getRuntime().totalMemory(); + long freeMemory = Runtime.getRuntime().freeMemory(); + long currentMemory = totalMemory - freeMemory; + + builder.category("System Stats"); + builder.append("OS", System.getProperty("os.name")); + builder.append("CPU", OpenGlHelper.getCpu()); + builder.append( + "Display", + String.format("%dx%d (%s)", Display.getWidth(), Display.getHeight(), GL11.glGetString(GL11.GL_VENDOR)) + ); + builder.append("GPU", GL11.glGetString(GL11.GL_RENDERER)); + builder.append("GPU Driver", GL11.glGetString(GL11.GL_VERSION)); + if (getMemorySize() > 0) builder.append("Maximum Memory", (getMemorySize() / 1024L / 1024L) + "MB"); + builder.append("Shaders", ("" + OpenGlHelper.isFramebufferEnabled()).toUpperCase()); + builder.category("Java Stats"); + builder.append( + "Java", + String.format("%s %dbit", System.getProperty("java.version"), Minecraft.getMinecraft().isJava64bit() ? 64 : 32) + ); + builder.append( + "Memory", + String.format( + "% 2d%% %03d/%03dMB", + currentMemory * 100L / maxMemory, + currentMemory / 1024L / 1024L, + maxMemory / 1024L / 1024L + ) + ); + builder.append( + "Memory Allocated", + String.format("% 2d%% %03dMB", totalMemory * 100L / maxMemory, totalMemory / 1024L / 1024L) + ); + builder.category("Game Stats"); + builder.append("FPS", String.valueOf(Minecraft.getDebugFPS())); + builder.append("Loaded Mods", String.valueOf(activeModCount)); + builder.append("Forge", ForgeVersion.getVersion()); + builder.category("Neu Settings"); + builder.append("API Key", NotEnoughUpdates.INSTANCE.config.apiKey.apiKey.isEmpty() ? "FALSE" : "TRUE"); + builder.append("On Skyblock", NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() ? "TRUE" : "FALSE"); + builder.append( + "Mod Version", + Loader.instance().getIndexedModList().get(NotEnoughUpdates.MODID).getDisplayVersion() + ); + builder.append("SB Profile", SBInfo.getInstance().currentProfile); + builder.append("Has Advanced Tab", SBInfo.getInstance().hasNewTab ? "TRUE" : "FALSE"); + builder.category("Repo Stats"); + builder.append("Last Commit", NotEnoughUpdates.INSTANCE.manager.latestRepoCommit); + builder.append("Loaded Items", String.valueOf(NotEnoughUpdates.INSTANCE.manager.getItemInformation().size())); + if (activeModCount <= 15) createModList(builder); + + return builder.toString(); + } + + private static DiscordMarkdownBuilder createModList(DiscordMarkdownBuilder builder) { + builder.category("Mods Loaded"); + Loader.instance().getActiveModList().forEach(mod -> builder.append(mod.getName(), mod.getSource().getName())); + return builder; + } + + private static long getMemorySize() { + try { + return ((com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean()).getTotalPhysicalMemorySize(); + } catch (Exception e) { + try { + return ((com.sun.management.UnixOperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean()).getTotalPhysicalMemorySize(); + } catch (Exception ignored) {/*IGNORE*/} + } + return -1; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/DhCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/DhCommand.java new file mode 100644 index 0000000000..89299a36ed --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/DhCommand.java @@ -0,0 +1,18 @@ +package io.github.moulberry.notenoughupdates.commands.dungeon; + +import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; +import net.minecraft.client.Minecraft; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; + +public class DhCommand extends ClientCommandBase { + + public DhCommand() { + super("dh"); + } + + @Override + public void processCommand(ICommandSender sender, String[] args) throws CommandException { + Minecraft.getMinecraft().thePlayer.sendChatMessage("/warp dungeon_hub"); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/DnCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/DnCommand.java new file mode 100644 index 0000000000..8fbbceba08 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/DnCommand.java @@ -0,0 +1,22 @@ +package io.github.moulberry.notenoughupdates.commands.dungeon; + +import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; +import net.minecraft.client.Minecraft; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.EnumChatFormatting; + +public class DnCommand extends ClientCommandBase { + + public DnCommand() { + super("dn"); + } + + @Override + public void processCommand(ICommandSender sender, String[] args) throws CommandException { + Minecraft.getMinecraft().thePlayer.sendChatMessage("/warp dungeon_hub"); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( + EnumChatFormatting.AQUA + "Warping to:" + EnumChatFormatting.YELLOW + " Deez Nuts lmao")); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/JoinDungeonCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/JoinDungeonCommand.java new file mode 100644 index 0000000000..874e81dbad --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/JoinDungeonCommand.java @@ -0,0 +1,41 @@ +package io.github.moulberry.notenoughupdates.commands.dungeon; + +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; +import net.minecraft.client.Minecraft; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.EnumChatFormatting; +import org.apache.commons.lang3.StringUtils; + +public class JoinDungeonCommand extends ClientCommandBase { + + public JoinDungeonCommand() { + super("join"); + } + + @Override + public void processCommand(ICommandSender sender, String[] args) throws CommandException { + if (!NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) { + Minecraft.getMinecraft().thePlayer.sendChatMessage("/join " + StringUtils.join(args, " ")); + } else { + if (args.length != 1) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( + EnumChatFormatting.RED + "Example Usage: /join f7, /join m6 or /join 7")); + } else { + String cataPrefix = "catacombs"; + if (args[0].startsWith("m")) { + cataPrefix = "master_catacombs"; + } + String cmd = "/joindungeon " + cataPrefix + " " + args[0].charAt(args[0].length() - 1); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( + EnumChatFormatting.YELLOW + "Running command: " + cmd)); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( + EnumChatFormatting.YELLOW + + "The dungeon should start soon. If it doesn't, make sure you have a party of 5 people")); + Minecraft.getMinecraft().thePlayer.sendChatMessage(cmd); + } + } + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/MapCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/MapCommand.java new file mode 100644 index 0000000000..ae06a34615 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/MapCommand.java @@ -0,0 +1,142 @@ +package io.github.moulberry.notenoughupdates.commands.dungeon; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; +import io.github.moulberry.notenoughupdates.dungeons.GuiDungeonMapEditor; +import net.minecraft.block.material.MapColor; +import net.minecraft.client.Minecraft; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.item.ItemMap; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.storage.MapData; + +import java.awt.*; +import java.io.BufferedReader; +import java.io.File; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.Map; + +public class MapCommand extends ClientCommandBase { + + public MapCommand() { + super("neumap"); + } + + @Override + public void processCommand(ICommandSender sender, String[] args) throws CommandException { + if (NotEnoughUpdates.INSTANCE.colourMap == null) { + try ( + BufferedReader reader = new BufferedReader(new InputStreamReader(Minecraft + .getMinecraft() + .getResourceManager() + .getResource( + new ResourceLocation("notenoughupdates:maps/F1Full.json")) + .getInputStream(), StandardCharsets.UTF_8)) + ) { + JsonObject json = NotEnoughUpdates.INSTANCE.manager.gson.fromJson(reader, JsonObject.class); + + NotEnoughUpdates.INSTANCE.colourMap = new Color[128][128]; + for (int x = 0; x < 128; x++) { + for (int y = 0; y < 128; y++) { + NotEnoughUpdates.INSTANCE.colourMap[x][y] = new Color(0, 0, 0, 0); + } + } + for (Map.Entry entry : json.entrySet()) { + int x = Integer.parseInt(entry.getKey().split(":")[0]); + int y = Integer.parseInt(entry.getKey().split(":")[1]); + + NotEnoughUpdates.INSTANCE.colourMap[x][y] = new Color(entry.getValue().getAsInt(), true); + } + } catch (Exception ignored) { + } + } + + if (!NotEnoughUpdates.INSTANCE.config.hidden.dev) { + NotEnoughUpdates.INSTANCE.openGui = new GuiDungeonMapEditor(); + return; + } + + if (args.length == 1 && args[0].equals("reset")) { + NotEnoughUpdates.INSTANCE.colourMap = null; + return; + } + + if (args.length != 2) { + NotEnoughUpdates.INSTANCE.openGui = new GuiDungeonMapEditor(); + return; + } + + if (args[0].equals("save")) { + ItemStack stack = Minecraft.getMinecraft().thePlayer.getHeldItem(); + if (stack != null && stack.getItem() instanceof ItemMap) { + ItemMap map = (ItemMap) stack.getItem(); + MapData mapData = map.getMapData(stack, Minecraft.getMinecraft().theWorld); + + if (mapData == null) return; + + JsonObject json = new JsonObject(); + for (int i = 0; i < 16384; ++i) { + int x = i % 128; + int y = i / 128; + + int j = mapData.colors[i] & 255; + + Color c; + if (j / 4 == 0) { + c = new Color((i + i / 128 & 1) * 8 + 16 << 24, true); + } else { + c = new Color(MapColor.mapColorArray[j / 4].getMapColor(j & 3), true); + } + + json.addProperty(x + ":" + y, c.getRGB()); + } + + try { + new File(NotEnoughUpdates.INSTANCE.manager.configLocation, "maps").mkdirs(); + NotEnoughUpdates.INSTANCE.manager.writeJson( + json, + new File(NotEnoughUpdates.INSTANCE.manager.configLocation, "maps/" + args[1] + ".json") + ); + } catch (Exception e) { + e.printStackTrace(); + } + + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.GREEN + + "Saved to file.")); + } + + return; + } + + if (args[0].equals("load")) { + JsonObject json = NotEnoughUpdates.INSTANCE.manager.getJsonFromFile(new File( + NotEnoughUpdates.INSTANCE.manager.configLocation, + "maps/" + args[1] + ".json" + )); + + NotEnoughUpdates.INSTANCE.colourMap = new Color[128][128]; + for (int x = 0; x < 128; x++) { + for (int y = 0; y < 128; y++) { + NotEnoughUpdates.INSTANCE.colourMap[x][y] = new Color(0, 0, 0, 0); + } + } + for (Map.Entry entry : json.entrySet()) { + int x = Integer.parseInt(entry.getKey().split(":")[0]); + int y = Integer.parseInt(entry.getKey().split(":")[1]); + + NotEnoughUpdates.INSTANCE.colourMap[x][y] = new Color(entry.getValue().getAsInt(), true); + } + + return; + } + + NotEnoughUpdates.INSTANCE.openGui = new GuiDungeonMapEditor(); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/help/FeaturesCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/help/FeaturesCommand.java new file mode 100644 index 0000000000..593f257554 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/help/FeaturesCommand.java @@ -0,0 +1,58 @@ +package io.github.moulberry.notenoughupdates.commands.help; + +import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; +import io.github.moulberry.notenoughupdates.util.Constants; +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.event.ClickEvent; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.EnumChatFormatting; + +import java.awt.*; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +public class FeaturesCommand extends ClientCommandBase { + public FeaturesCommand() { + super("neufeatures"); + } + + @Override + public void processCommand(ICommandSender sender, String[] args) throws CommandException { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); + if (Constants.MISC == null || !Constants.MISC.has("featureslist")) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( + "" + EnumChatFormatting.DARK_RED + EnumChatFormatting.BOLD + "WARNING: " + EnumChatFormatting.RESET + + EnumChatFormatting.RED + "Could not load URL from repo.")); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( + "" + EnumChatFormatting.RED + "Please run " + EnumChatFormatting.BOLD + "/neuresetrepo" + + EnumChatFormatting.RESET + EnumChatFormatting.RED + " and " + EnumChatFormatting.BOLD + "restart your game" + + EnumChatFormatting.RESET + EnumChatFormatting.RED + " in order to fix. " + EnumChatFormatting.DARK_RED + + EnumChatFormatting.BOLD + "If that doesn't fix it" + EnumChatFormatting.RESET + EnumChatFormatting.RED + + ", please join discord.gg/moulberry and post in #neu-support")); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); + return; + } + String url = Constants.MISC.get("featureslist").getAsString(); + + Desktop desk = Desktop.getDesktop(); + try { + desk.browse(new URI(url)); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( + EnumChatFormatting.DARK_PURPLE + "" + EnumChatFormatting.BOLD + "NEU" + EnumChatFormatting.RESET + + EnumChatFormatting.GOLD + "> Opening Feature List in browser.")); + } catch (URISyntaxException | IOException ignored) { + + ChatComponentText clickTextFeatures = new ChatComponentText( + EnumChatFormatting.DARK_PURPLE + "" + EnumChatFormatting.BOLD + "NEU" + EnumChatFormatting.RESET + + EnumChatFormatting.GOLD + "> Click here to open the Feature List in your browser."); + clickTextFeatures.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, url)); + Minecraft.getMinecraft().thePlayer.addChatMessage(clickTextFeatures); + + } + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/help/HelpCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/help/HelpCommand.java new file mode 100644 index 0000000000..9669be60e4 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/help/HelpCommand.java @@ -0,0 +1,79 @@ +package io.github.moulberry.notenoughupdates.commands.help; + +import com.google.common.collect.Lists; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; +import net.minecraft.client.Minecraft; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.util.ChatComponentText; + +import java.util.ArrayList; +import java.util.List; + +public class HelpCommand extends ClientCommandBase { + + public HelpCommand() { + super("neuhelp"); + } + + @Override + public void processCommand(ICommandSender sender, String[] args) { + ArrayList neuHelpMessages = Lists.newArrayList( + "\u00a75\u00a7lNotEnoughUpdates commands", + "\u00a76/neu \u00a77- Opens the main neu GUI.", + "\u00a76/pv \u00a7b?{name} \u00a72\u2D35 \u00a7r\u00a77- Opens the profile viewer", + "\u00a76/neusouls {on/off/clear/unclear} \u00a7r\u00a77- Shows waypoints to fairy souls.", + "\u00a76/neubuttons \u00a7r\u00a77- Opens a GUI which allows you to customize inventory buttons.", + "\u00a76/neuec \u00a7r\u00a77- Opens the enchant colour GUI.", + "\u00a76/join {floor} \u00a7r\u00a77- Short Command to join a Dungeon. \u00a7lNeed a Party of 5 People\u00a7r\u00a77 {4/f7/m5}.", + "\u00a76/neucosmetics \u00a7r\u00a77- Opens the cosmetic GUI.", + "\u00a76/neurename \u00a7r\u00a77- Opens the NEU Item Customizer.", + "\u00a76/cata \u00a7b?{name} \u00a72\u2D35 \u00a7r\u00a77- Opens the profile viewer's catacombs page.", + "\u00a76/neulinks \u00a7r\u00a77- Shows links to neu/moulberry.", + "\u00a76/neuoverlay \u00a7r\u00a77- Opens GUI Editor for quickcommands and searchbar.", + "\u00a76/neuah \u00a7r\u00a77- Opens neu's custom ah GUI.", + "\u00a76/neumap \u00a7r\u00a77- Opens the dungeon map GUI.", + "\u00a76/neucalendar \u00a7r\u00a77- Opens neu's custom calendar GUI.", + "", + "\u00a76\u00a7lOld commands:", + "\u00a76/peek \u00a7b?{user} \u00a72\u2D35 \u00a7r\u00a77- Shows quickly stats for a user.", + "", + "\u00a76\u00a7lDebug commands:", + "\u00a76/neustats \u00a7r\u00a77- Copies helpful info to the clipboard.", + "\u00a76/neustats modlist \u00a7r\u00a77- Copies modlist info to clipboard.", + "\u00a76/neuresetrepo \u00a7r\u00a77- Deletes all repo files.", + "\u00a76/neureloadrepo \u00a7r\u00a77- Debug command with repo.", + "", + "\u00a76\u00a7lDev commands:", + "\u00a76/neupackdev \u00a7r\u00a77- pack creator command - getnpc" + ); + for (String neuHelpMessage : neuHelpMessages) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(neuHelpMessage)); + } + if (NotEnoughUpdates.INSTANCE.config.hidden.dev) { + ArrayList neuDevHelpMessages = Lists.newArrayList( + "\u00a76/neudevtest \u00a7r\u00a77- dev test command", + "\u00a76/neuzeephere \u00a7r\u00a77- sphere", + "\u00a76/neudungeonwintest \u00a7r\u00a77- displays the dungeon win screen" + ); + + for (String neuDevHelpMessage : neuDevHelpMessages) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(neuDevHelpMessage)); + } + } + String[] helpInfo = { + "", + "\u00a77Commands marked with a \u00a72\"\u2D35\"\u00a77 require are api key. You can set your api key via \"/api new\" or by manually putting it in the api field in \"/neu\"", + "", + "\u00a77Arguments marked with a \u00a7b\"?\"\u00a77 are optional.", + "", + "\u00a76\u00a7lScroll up to see everything" + }; + + for (String message : helpInfo) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(message)); + } + + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/help/LinksCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/help/LinksCommand.java new file mode 100644 index 0000000000..c81f44a8f5 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/help/LinksCommand.java @@ -0,0 +1,34 @@ +package io.github.moulberry.notenoughupdates.commands.help; + +import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; +import net.minecraft.client.Minecraft; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.util.ChatComponentText; + +import java.io.File; + +public class LinksCommand extends ClientCommandBase { + + public LinksCommand() { + super("neulinks"); + } + + @Override + public void processCommand(ICommandSender sender, String[] args) throws CommandException { + File repo = NotEnoughUpdates.INSTANCE.manager.repoLocation; + if (repo.exists()) { + File updateJson = new File(repo, "update.json"); + try { + JsonObject update = NotEnoughUpdates.INSTANCE.manager.getJsonFromFile(updateJson); + + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); + NotEnoughUpdates.INSTANCE.displayLinks(update); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); + } catch (Exception ignored) { + } + } + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/help/SettingsCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/help/SettingsCommand.java new file mode 100644 index 0000000000..08350be9d5 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/help/SettingsCommand.java @@ -0,0 +1,34 @@ +package io.github.moulberry.notenoughupdates.commands.help; + +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; +import io.github.moulberry.notenoughupdates.core.GuiScreenElementWrapper; +import io.github.moulberry.notenoughupdates.options.NEUConfigEditor; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import org.apache.commons.lang3.StringUtils; + +import java.util.Arrays; +import java.util.List; + +public class SettingsCommand extends ClientCommandBase { + + public SettingsCommand() { + super("neu"); + } + + @Override + public List getCommandAliases() { + return Arrays.asList("neusettings", "neuconfig"); + } + + @Override + public void processCommand(ICommandSender sender, String[] args) throws CommandException { + if (args.length > 0) { + NotEnoughUpdates.INSTANCE.openGui = + new GuiScreenElementWrapper(new NEUConfigEditor(NotEnoughUpdates.INSTANCE.config, StringUtils.join(args, " "))); + } else { + NotEnoughUpdates.INSTANCE.openGui = new GuiScreenElementWrapper(NEUConfigEditor.editor); + } + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/help/StorageViewerWhyCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/help/StorageViewerWhyCommand.java new file mode 100644 index 0000000000..4f85c26efb --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/help/StorageViewerWhyCommand.java @@ -0,0 +1,26 @@ +package io.github.moulberry.notenoughupdates.commands.help; + +import com.google.common.collect.Lists; +import io.github.moulberry.notenoughupdates.NEUEventListener; +import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; +import net.minecraft.command.ICommandSender; + +public class StorageViewerWhyCommand extends ClientCommandBase { + + public StorageViewerWhyCommand() { + super("neustwhy"); + } + + @Override + public void processCommand(ICommandSender sender, String[] args) { + NEUEventListener.displayNotification(Lists.newArrayList( + "\u00a7eStorage Viewer", + "\u00a77Currently, the storage viewer requires you to click twice", + "\u00a77in order to switch between pages. This is because Hypixel", + "\u00a77has not yet added a shortcut command to go to any enderchest/", + "\u00a77storage page.", + "\u00a77While it is possible to send the second click", + "\u00a77automatically, doing so violates Hypixel's new mod rules." + ), true); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/AhCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/AhCommand.java new file mode 100644 index 0000000000..0b2c155ec4 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/AhCommand.java @@ -0,0 +1,38 @@ +package io.github.moulberry.notenoughupdates.commands.misc; + +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.auction.CustomAHGui; +import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; +import net.minecraft.client.Minecraft; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.EnumChatFormatting; +import org.apache.commons.lang3.StringUtils; + +public class AhCommand extends ClientCommandBase { + + public AhCommand() { + super("neuah"); + } + + @Override + public void processCommand(ICommandSender sender, String[] args) throws CommandException { + if (!NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + + "You must be on Skyblock to use this feature.")); + } else if (NotEnoughUpdates.INSTANCE.config.apiKey.apiKey == null || + NotEnoughUpdates.INSTANCE.config.apiKey.apiKey.trim().isEmpty()) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + + "Can't open NeuAH, apikey is not set. Run /api new and put the result in settings.")); + } else { + NotEnoughUpdates.INSTANCE.openGui = new CustomAHGui(); + NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.lastOpen = System.currentTimeMillis(); + NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.clearSearch(); + NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.updateSearch(); + + if (args.length > 0) + NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.setSearch(StringUtils.join(args, " ")); + } + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/ButtonsCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/ButtonsCommand.java new file mode 100644 index 0000000000..63d5c327c2 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/ButtonsCommand.java @@ -0,0 +1,16 @@ +package io.github.moulberry.notenoughupdates.commands.misc; + +import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; + +public class ButtonsCommand extends ClientCommandBase { + protected ButtonsCommand(String name) { + super(name); + } + + @Override + public void processCommand(ICommandSender sender, String[] args) throws CommandException { + + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CalendarCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CalendarCommand.java new file mode 100644 index 0000000000..d3c472bd84 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CalendarCommand.java @@ -0,0 +1,22 @@ +package io.github.moulberry.notenoughupdates.commands.misc; + +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; +import io.github.moulberry.notenoughupdates.miscgui.CalendarOverlay; +import net.minecraft.client.Minecraft; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; + +public class CalendarCommand extends ClientCommandBase { + + public CalendarCommand() { + super("neucalendar"); + } + + @Override + public void processCommand(ICommandSender sender, String[] args) throws CommandException { + Minecraft.getMinecraft().thePlayer.closeScreen(); + CalendarOverlay.setEnabled(true); + NotEnoughUpdates.INSTANCE.sendChatMessage("/calendar"); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CollectionLogCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CollectionLogCommand.java new file mode 100644 index 0000000000..1bde763139 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CollectionLogCommand.java @@ -0,0 +1,20 @@ +package io.github.moulberry.notenoughupdates.commands.misc; + +import io.github.moulberry.notenoughupdates.collectionlog.GuiCollectionLog; +import io.github.moulberry.notenoughupdates.commands.ScreenCommand; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class CollectionLogCommand extends ScreenCommand { + + public CollectionLogCommand() { + super("neucl", GuiCollectionLog::new); + } + + @Override + public List getCommandAliases() { + return Collections.singletonList("collectionlog"); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CosmeticsCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CosmeticsCommand.java new file mode 100644 index 0000000000..9ccb7cf0e4 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CosmeticsCommand.java @@ -0,0 +1,29 @@ +package io.github.moulberry.notenoughupdates.commands.misc; + +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; +import io.github.moulberry.notenoughupdates.cosmetics.GuiCosmetics; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.EnumChatFormatting; + +public class CosmeticsCommand extends ClientCommandBase { + + public CosmeticsCommand() { + super("neucosmetics"); + } + + @Override + public void processCommand(ICommandSender sender, String[] args) throws CommandException { + if (!OpenGlHelper.isFramebufferEnabled()) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + + "NEU cosmetics do not work with OF Fast Render. Go to ESC > Options > Video Settings > Performance > Fast Render to disable it.")); + + } + + NotEnoughUpdates.INSTANCE.openGui = new GuiCosmetics(); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CustomizeCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CustomizeCommand.java new file mode 100644 index 0000000000..6bce4f5a5f --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CustomizeCommand.java @@ -0,0 +1,130 @@ +package io.github.moulberry.notenoughupdates.commands.misc; + +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; +import io.github.moulberry.notenoughupdates.miscgui.GuiItemCustomize; +import net.minecraft.client.Minecraft; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ChatComponentText; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class CustomizeCommand extends ClientCommandBase { + + public CustomizeCommand() { + super("neucustomize"); + } + + @Override + public List getCommandAliases() { + return Collections.singletonList("neurename"); + } + + @Override + public void processCommand(ICommandSender sender, String[] args) throws CommandException { + ItemStack held = Minecraft.getMinecraft().thePlayer.getHeldItem(); + + if (held == null) { + sender.addChatMessage(new ChatComponentText("\u00a7cYou can't customize your hand...")); + return; + } + + String heldUUID = NotEnoughUpdates.INSTANCE.manager.getUUIDForItem(held); + + if (heldUUID == null) { + sender.addChatMessage(new ChatComponentText("\u00a7cHeld item does not have UUID, cannot be customized")); + return; + } + + NotEnoughUpdates.INSTANCE.openGui = new GuiItemCustomize(held, heldUUID); + } + + /*SimpleCommand itemRenameCommand = new SimpleCommand("neurename", new SimpleCommand.ProcessCommandRunnable() { + public void processCommand(ICommandSender sender, String[] args) { + if (args.length == 0) { + args = new String[]{"help"}; + } + String heldUUID = NotEnoughUpdates.INSTANCE.manager.getUUIDForItem(Minecraft.getMinecraft().thePlayer.getHeldItem()); + switch (args[0].toLowerCase()) { + case "clearall": + NotEnoughUpdates.INSTANCE.manager.itemRenameJson = new JsonObject(); + NotEnoughUpdates.INSTANCE.manager.saveItemRenameConfig(); + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.GREEN + "[NEU] Cleared custom name for all items")); + break; + case "clear": + if (heldUUID == null) { + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + "[NEU] Can't clear rename - no UUID")); + return; + } + NotEnoughUpdates.INSTANCE.manager.itemRenameJson.remove(heldUUID); + NotEnoughUpdates.INSTANCE.manager.saveItemRenameConfig(); + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.GREEN + "[NEU] Cleared custom name for held item")); + break; + case "copyuuid": + if (heldUUID == null) { + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + "[NEU] Can't clear rename - no UUID")); + return; + } + StringSelection selection = new StringSelection(heldUUID); + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(selection, selection); + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.GREEN + "[NEU] UUID copied to clipboard")); + break; + case "uuid": + if (heldUUID == null) { + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + "[NEU] Can't get UUID - no UUID")); + return; + } + ChatStyle style = new ChatStyle(); + style.setChatHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, + new ChatComponentText(EnumChatFormatting.GRAY + "Click to copy to clipboard"))); + style.setChatClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/neurename copyuuid")); + + ChatComponentText text = new ChatComponentText(EnumChatFormatting.YELLOW + "[NEU] The UUID of your currently held item is: " + + EnumChatFormatting.GREEN + heldUUID); + text.setChatStyle(style); + sender.addChatMessage(text); + break; + case "set": + if (heldUUID == null) { + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + "[NEU] Can't rename item - no UUID")); + return; + } + if (args.length == 1) { + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + "[NEU] Usage: /neurename set [name...]")); + return; + } + StringBuilder sb = new StringBuilder(); + for (int i = 1; i < args.length; i++) { + sb.append(args[i]); + if (i < args.length - 1) sb.append(" "); + } + String name = sb.toString() + .replace("\\&", "{amp}") + .replace("&", "\u00a7") + .replace("{amp}", "&"); + name = new UnicodeUnescaper().translate(name); + NotEnoughUpdates.INSTANCE.manager.itemRenameJson.addProperty(heldUUID, name); + NotEnoughUpdates.INSTANCE.manager.saveItemRenameConfig(); + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.GREEN + "[NEU] Set custom name for held item")); + break; + default: + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + "[NEU] Unknown subcommand \"" + args[0] + "\"")); + case "help": + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "[NEU] Available commands:")); + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "help: Print this message")); + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "clearall: Clears all custom names " + + EnumChatFormatting.BOLD + "(Cannot be undone)")); + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "clear: Clears held item name " + + EnumChatFormatting.BOLD + "(Cannot be undone)")); + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "uuid: Returns the UUID of the currently held item")); + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "set: Sets the custom name of the currently held item")); + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "Usage: /neurename set [name...]")); + + } + } + });*/ +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/GamemodesCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/GamemodesCommand.java new file mode 100644 index 0000000000..d33e560a57 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/GamemodesCommand.java @@ -0,0 +1,20 @@ +package io.github.moulberry.notenoughupdates.commands.misc; + +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; +import io.github.moulberry.notenoughupdates.gamemodes.GuiGamemodes; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; + +public class GamemodesCommand extends ClientCommandBase { + + public GamemodesCommand() { + super("neugamemodes"); + } + + @Override + public void processCommand(ICommandSender sender, String[] args) throws CommandException { + boolean upgradeOverride = args.length == 1 && args[0].equals("upgradeOverride"); + NotEnoughUpdates.INSTANCE.openGui = new GuiGamemodes(upgradeOverride); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/CataCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/CataCommand.java new file mode 100644 index 0000000000..09253e503a --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/CataCommand.java @@ -0,0 +1,17 @@ +package io.github.moulberry.notenoughupdates.commands.profile; + +import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer; +import net.minecraft.command.ICommandSender; + +public class CataCommand extends ViewProfileCommand { + + public CataCommand() { + super("cata"); + } + + @Override + public void processCommand(ICommandSender sender, String[] args) { + GuiProfileViewer.currentPage = GuiProfileViewer.ProfileViewerPage.DUNG; + super.processCommand(sender, args); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/PeekCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/PeekCommand.java new file mode 100644 index 0000000000..d69139aaf2 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/PeekCommand.java @@ -0,0 +1,291 @@ +package io.github.moulberry.notenoughupdates.commands.profile; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; +import io.github.moulberry.notenoughupdates.profileviewer.PlayerStats; +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.BlockPos; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.EnumChatFormatting; +import org.apache.commons.lang3.text.WordUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +public class PeekCommand extends ClientCommandBase { + + private ScheduledExecutorService peekCommandExecutorService = null; + + public PeekCommand() { + super("peek"); + } + + @Override + public void processCommand(ICommandSender sender, String[] args) throws CommandException { + String name; + if (args.length == 0) { + name = Minecraft.getMinecraft().thePlayer.getName(); + } else { + name = args[0]; + } + int id = new Random().nextInt(Integer.MAX_VALUE / 2) + Integer.MAX_VALUE / 2; + + Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessageWithOptionalDeletion(new ChatComponentText( + EnumChatFormatting.YELLOW + "[PEEK] Getting player information..."), id); + NotEnoughUpdates.profileViewer.getProfileByName(name, profile -> { + if (profile == null) { + Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessageWithOptionalDeletion(new ChatComponentText( + EnumChatFormatting.RED + "[PEEK] Unknown player or the api is down."), id); + } else { + profile.resetCache(); + + if (peekCommandExecutorService == null || peekCommandExecutorService.isShutdown()) { + peekCommandExecutorService = Executors.newSingleThreadScheduledExecutor(); + } else { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( + EnumChatFormatting.RED + "[PEEK] New peek command run, cancelling old one.")); + peekCommandExecutorService.shutdownNow(); + peekCommandExecutorService = Executors.newSingleThreadScheduledExecutor(); + } + + Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessageWithOptionalDeletion(new ChatComponentText( + EnumChatFormatting.YELLOW + "[PEEK] Getting the player's Skyblock profile(s)..."), id); + + long startTime = System.currentTimeMillis(); + peekCommandExecutorService.schedule(new Runnable() { + public void run() { + if (System.currentTimeMillis() - startTime > 10 * 1000) { + + Minecraft.getMinecraft().ingameGUI + .getChatGUI() + .printChatMessageWithOptionalDeletion(new ChatComponentText( + EnumChatFormatting.RED + "[PEEK] Getting profile info took too long, aborting."), id); + return; + } + + String g = EnumChatFormatting.GRAY.toString(); + + JsonObject profileInfo = profile.getProfileInformation(null); + if (profileInfo != null) { + float overallScore = 0; + + boolean isMe = name.equalsIgnoreCase("moulberry"); + + PlayerStats.Stats stats = profile.getStats(null); + JsonObject skill = profile.getSkillInfo(null); + + Minecraft.getMinecraft().ingameGUI + .getChatGUI() + .printChatMessageWithOptionalDeletion(new ChatComponentText(EnumChatFormatting.GREEN + " " + + EnumChatFormatting.STRIKETHROUGH + "-=-" + EnumChatFormatting.RESET + EnumChatFormatting.GREEN + " " + + Utils.getElementAsString(profile.getHypixelProfile().get("displayname"), name) + "'s Info " + + EnumChatFormatting.STRIKETHROUGH + "-=-"), id); + + if (skill == null) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( + EnumChatFormatting.YELLOW + "Skills api disabled!")); + } else { + float totalSkillLVL = 0; + float totalSkillCount = 0; + + for (Map.Entry entry : skill.entrySet()) { + if (entry.getKey().startsWith("level_skill")) { + if (entry.getKey().contains("runecrafting")) continue; + if (entry.getKey().contains("carpentry")) continue; + totalSkillLVL += entry.getValue().getAsFloat(); + totalSkillCount++; + } + } + + float combat = Utils.getElementAsFloat(skill.get("level_skill_combat"), 0); + float zombie = Utils.getElementAsFloat(skill.get("level_slayer_zombie"), 0); + float spider = Utils.getElementAsFloat(skill.get("level_slayer_spider"), 0); + float wolf = Utils.getElementAsFloat(skill.get("level_slayer_wolf"), 0); + float enderman = Utils.getElementAsFloat(skill.get("level_slayer_enderman"), 0); + + float avgSkillLVL = totalSkillLVL / totalSkillCount; + + if (isMe) { + avgSkillLVL = 6; + combat = 4; + zombie = 2; + spider = 1; + wolf = 2; + enderman = 0; + } + + EnumChatFormatting combatPrefix = combat > 20 + ? (combat > 35 ? EnumChatFormatting.GREEN : EnumChatFormatting.YELLOW) + : EnumChatFormatting.RED; + EnumChatFormatting zombiePrefix = zombie > 3 + ? (zombie > 6 ? EnumChatFormatting.GREEN : EnumChatFormatting.YELLOW) + : EnumChatFormatting.RED; + EnumChatFormatting spiderPrefix = spider > 3 + ? (spider > 6 ? EnumChatFormatting.GREEN : EnumChatFormatting.YELLOW) + : EnumChatFormatting.RED; + EnumChatFormatting wolfPrefix = + wolf > 3 ? (wolf > 6 ? EnumChatFormatting.GREEN : EnumChatFormatting.YELLOW) : EnumChatFormatting.RED; + EnumChatFormatting endermanPrefix = enderman > 3 + ? (enderman > 6 + ? EnumChatFormatting.GREEN + : EnumChatFormatting.YELLOW) + : EnumChatFormatting.RED; + EnumChatFormatting avgPrefix = avgSkillLVL > 20 + ? (avgSkillLVL > 35 + ? EnumChatFormatting.GREEN + : EnumChatFormatting.YELLOW) + : EnumChatFormatting.RED; + + overallScore += zombie * zombie / 81f; + overallScore += spider * spider / 81f; + overallScore += wolf * wolf / 81f; + overallScore += enderman * enderman / 81f; + overallScore += avgSkillLVL / 20f; + + int cata = (int) Utils.getElementAsFloat(skill.get("level_skill_catacombs"), 0); + EnumChatFormatting cataPrefix = cata > 15 + ? (cata > 25 ? EnumChatFormatting.GREEN : EnumChatFormatting.YELLOW) + : EnumChatFormatting.RED; + + overallScore += cata * cata / 2000f; + + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( + g + "Combat: " + combatPrefix + (int) Math.floor(combat) + + (cata > 0 ? g + " - Cata: " + cataPrefix + cata : "") + + g + " - AVG: " + avgPrefix + (int) Math.floor(avgSkillLVL))); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( + g + "Slayer: " + zombiePrefix + (int) Math.floor(zombie) + g + "-" + + spiderPrefix + (int) Math.floor(spider) + g + "-" + + wolfPrefix + (int) Math.floor(wolf) + "-" + + endermanPrefix + (int) Math.floor(enderman))); + } + if (stats == null) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( + EnumChatFormatting.YELLOW + "Skills, collection and/or inventory apis disabled!")); + } else { + int health = (int) stats.get("health"); + int defence = (int) stats.get("defence"); + int strength = (int) stats.get("strength"); + int intelligence = (int) stats.get("intelligence"); + + EnumChatFormatting healthPrefix = health > 800 + ? (health > 1600 + ? EnumChatFormatting.GREEN + : EnumChatFormatting.YELLOW) + : EnumChatFormatting.RED; + EnumChatFormatting defencePrefix = defence > 200 + ? (defence > 600 + ? EnumChatFormatting.GREEN + : EnumChatFormatting.YELLOW) + : EnumChatFormatting.RED; + EnumChatFormatting strengthPrefix = strength > 100 + ? (strength > 300 + ? EnumChatFormatting.GREEN + : EnumChatFormatting.YELLOW) + : EnumChatFormatting.RED; + EnumChatFormatting intelligencePrefix = intelligence > 300 + ? (intelligence > 900 + ? EnumChatFormatting.GREEN + : EnumChatFormatting.YELLOW) + : EnumChatFormatting.RED; + + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( + g + "Stats : " + healthPrefix + health + EnumChatFormatting.RED + "\u2764 " + + defencePrefix + defence + EnumChatFormatting.GREEN + "\u2748 " + + strengthPrefix + strength + EnumChatFormatting.RED + "\u2741 " + + intelligencePrefix + intelligence + EnumChatFormatting.AQUA + "\u270e ")); + } + float bankBalance = Utils.getElementAsFloat(Utils.getElement(profileInfo, "banking.balance"), -1); + float purseBalance = Utils.getElementAsFloat(Utils.getElement(profileInfo, "coin_purse"), 0); + + long networth = profile.getNetWorth(null); + float money = Math.max(bankBalance + purseBalance, networth); + EnumChatFormatting moneyPrefix = money > 50 * 1000 * 1000 ? + (money > 200 * 1000 * 1000 + ? EnumChatFormatting.GREEN + : EnumChatFormatting.YELLOW) : EnumChatFormatting.RED; + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( + g + "Purse: " + moneyPrefix + Utils.shortNumberFormat(purseBalance, 0) + g + " - Bank: " + + (bankBalance == -1 ? EnumChatFormatting.YELLOW + "N/A" : moneyPrefix + + (isMe ? "4.8b" : Utils.shortNumberFormat(bankBalance, 0))) + + (networth > 0 ? g + " - Net: " + moneyPrefix + Utils.shortNumberFormat(networth, 0) : ""))); + + overallScore += Math.min(2, money / (100f * 1000 * 1000)); + + String activePet = Utils.getElementAsString( + Utils.getElement(profile.getPetsInfo(null), "active_pet.type"), + "None Active" + ); + String activePetTier = Utils.getElementAsString(Utils.getElement( + profile.getPetsInfo(null), + "active_pet.tier" + ), "UNKNOWN"); + + String col = NotEnoughUpdates.petRarityToColourMap.get(activePetTier); + if (col == null) col = EnumChatFormatting.LIGHT_PURPLE.toString(); + + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(g + "Pet : " + + col + WordUtils.capitalizeFully(activePet.replace("_", " ")))); + + String overall = "Skywars Main"; + if (isMe) { + overall = Utils.chromaString("Literally the best player to exist"); // ego much + } else if (overallScore < 5 && (bankBalance + purseBalance) > 500 * 1000 * 1000) { + overall = EnumChatFormatting.GOLD + "Bill Gates"; + } else if (overallScore > 9) { + overall = Utils.chromaString("Didn't even think this score was possible"); + } else if (overallScore > 8) { + overall = Utils.chromaString("Mentally unstable"); + } else if (overallScore > 7) { + overall = EnumChatFormatting.GOLD + "Why though 0.0"; + } else if (overallScore > 5.5) { + overall = EnumChatFormatting.GOLD + "Bro stop playing"; + } else if (overallScore > 4) { + overall = EnumChatFormatting.GREEN + "Kinda sweaty"; + } else if (overallScore > 3) { + overall = EnumChatFormatting.YELLOW + "Alright I guess"; + } else if (overallScore > 2) { + overall = EnumChatFormatting.YELLOW + "Ender Non"; + } else if (overallScore > 1) { + overall = EnumChatFormatting.RED + "Played Skyblock"; + } + + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(g + "Overall score: " + + overall + g + " (" + Math.round(overallScore * 10) / 10f + ")")); + + peekCommandExecutorService.shutdownNow(); + } else { + peekCommandExecutorService.schedule(this, 200, TimeUnit.MILLISECONDS); + } + } + }, 200, TimeUnit.MILLISECONDS); + } + }); + } + + @Override + public List addTabCompletionOptions(ICommandSender sender, String[] args, BlockPos pos) { + if (args.length != 1) return null; + + String lastArg = args[args.length - 1]; + List playerMatches = new ArrayList<>(); + for (EntityPlayer player : Minecraft.getMinecraft().theWorld.playerEntities) { + String playerName = player.getName(); + if (playerName.toLowerCase().startsWith(lastArg.toLowerCase())) { + playerMatches.add(playerName); + } + } + return playerMatches; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/PvCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/PvCommand.java new file mode 100644 index 0000000000..07394ffd30 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/PvCommand.java @@ -0,0 +1,22 @@ +package io.github.moulberry.notenoughupdates.commands.profile; + +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import net.minecraft.client.Minecraft; +import net.minecraft.command.ICommandSender; +import org.apache.commons.lang3.StringUtils; + +public class PvCommand extends ViewProfileCommand { + + public PvCommand() { + super("pv"); + } + + @Override + public void processCommand(ICommandSender sender, String[] args) { + if (!NotEnoughUpdates.INSTANCE.isOnSkyblock()) { + Minecraft.getMinecraft().thePlayer.sendChatMessage("/pv " + StringUtils.join(args, " ")); + } else { + super.processCommand(sender, args); + } + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/ViewProfileCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/ViewProfileCommand.java new file mode 100644 index 0000000000..371db3944d --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/ViewProfileCommand.java @@ -0,0 +1,83 @@ +package io.github.moulberry.notenoughupdates.commands.profile; + +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; +import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.command.ICommandSender; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.BlockPos; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.EnumChatFormatting; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +public class ViewProfileCommand extends ClientCommandBase { + + public static final Consumer RUNNABLE = (args) -> { + if (!OpenGlHelper.isFramebufferEnabled()) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + + "Some parts of the profile viewer do not work with OF Fast Render. Go to ESC > Options > Video Settings > Performance > Fast Render to disable it.")); + + } + if (NotEnoughUpdates.INSTANCE.config.apiKey.apiKey == null || + NotEnoughUpdates.INSTANCE.config.apiKey.apiKey.trim().isEmpty()) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + + "Can't view profile, apikey is not set. Run /api new and put the result in settings.")); + } else if (args.length == 0) { + NotEnoughUpdates.profileViewer.getProfileByName(Minecraft.getMinecraft().thePlayer.getName(), profile -> { + if (profile == null) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + + "Invalid player name/api key. Maybe api is down? Try /api new.")); + } else { + profile.resetCache(); + NotEnoughUpdates.INSTANCE.openGui = new GuiProfileViewer(profile); + } + }); + } else if (args.length > 1) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + + "Too many arguments. Usage: /neuprofile [name]")); + } else { + NotEnoughUpdates.profileViewer.getProfileByName(args[0], profile -> { + if (profile == null) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + + "Invalid player name/api key. Maybe api is down? Try /api new.")); + } else { + profile.resetCache(); + NotEnoughUpdates.INSTANCE.openGui = new GuiProfileViewer(profile); + } + }); + } + }; + + public ViewProfileCommand() { + this("neuprofile"); + } + + public ViewProfileCommand(String name) { + super(name); + } + + @Override + public void processCommand(ICommandSender sender, String[] args) { + RUNNABLE.accept(args); + } + + @Override + public List addTabCompletionOptions(ICommandSender sender, String[] args, BlockPos pos) { + if (args.length != 1) return null; + + String lastArg = args[args.length - 1]; + List playerMatches = new ArrayList<>(); + for (EntityPlayer player : Minecraft.getMinecraft().theWorld.playerEntities) { + String playerName = player.getName(); + if (playerName.toLowerCase().startsWith(lastArg.toLowerCase())) { + playerMatches.add(playerName); + } + } + return playerMatches; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/repo/ReloadRepoCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/repo/ReloadRepoCommand.java new file mode 100644 index 0000000000..e363b59f62 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/repo/ReloadRepoCommand.java @@ -0,0 +1,39 @@ +package io.github.moulberry.notenoughupdates.commands.repo; + +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; +import io.github.moulberry.notenoughupdates.options.NEUConfig; +import io.github.moulberry.notenoughupdates.util.Constants; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; + +public class ReloadRepoCommand extends ClientCommandBase { + + public ReloadRepoCommand() { + super("neureloadrepo"); + } + + @Override + public void processCommand(ICommandSender sender, String[] args) throws CommandException { + NotEnoughUpdates.INSTANCE.manager.reloadRepository(); + Constants.reload(); + + NotEnoughUpdates.INSTANCE.newConfigFile(); + if (NotEnoughUpdates.INSTANCE.getConfigFile().exists()) { + try ( + BufferedReader reader = new BufferedReader(new InputStreamReader( + new FileInputStream(NotEnoughUpdates.INSTANCE.getConfigFile()), + StandardCharsets.UTF_8 + )) + ) { + NotEnoughUpdates.INSTANCE.config = NotEnoughUpdates.INSTANCE.manager.gson.fromJson(reader, NEUConfig.class); + } catch (Exception ignored) { + } + } + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/repo/RepoModeCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/repo/RepoModeCommand.java new file mode 100644 index 0000000000..bb6e1675e1 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/repo/RepoModeCommand.java @@ -0,0 +1,23 @@ +package io.github.moulberry.notenoughupdates.commands.repo; + +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; +import net.minecraft.client.Minecraft; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.util.ChatComponentText; + +public class RepoModeCommand extends ClientCommandBase { + + public RepoModeCommand() { + super("neurepomode"); + } + + @Override + public void processCommand(ICommandSender sender, String[] args) throws CommandException { + NotEnoughUpdates.INSTANCE.config.hidden.dev = !NotEnoughUpdates.INSTANCE.config.hidden.dev; + NotEnoughUpdates.INSTANCE.config.hidden.enableItemEditing = + !NotEnoughUpdates.INSTANCE.config.hidden.enableItemEditing; + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("\u00a75Toggled NEU repo dev mode.")); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/repo/ResetRepoCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/repo/ResetRepoCommand.java new file mode 100644 index 0000000000..b9a0d7cd4d --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/repo/ResetRepoCommand.java @@ -0,0 +1,18 @@ +package io.github.moulberry.notenoughupdates.commands.repo; + +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; + +public class ResetRepoCommand extends ClientCommandBase { + + public ResetRepoCommand() { + super("neuresetrepo"); + } + + @Override + public void processCommand(ICommandSender sender, String[] args) throws CommandException { + NotEnoughUpdates.INSTANCE.manager.resetRepo(); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/BackgroundBlur.java b/src/main/java/io/github/moulberry/notenoughupdates/core/BackgroundBlur.java index 8a8655f966..c85841b3f0 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/BackgroundBlur.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/BackgroundBlur.java @@ -2,7 +2,6 @@ import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils; -import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Gui; import net.minecraft.client.renderer.GlStateManager; @@ -15,8 +14,6 @@ import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.common.eventhandler.EventPriority; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import net.minecraftforge.fml.common.gameevent.TickEvent; -import org.lwjgl.input.Keyboard; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL30; @@ -26,240 +23,249 @@ import java.util.Set; public class BackgroundBlur { - - private static class OutputStuff { - public Framebuffer framebuffer; - public Shader blurShaderHorz = null; - public Shader blurShaderVert = null; - - public OutputStuff(Framebuffer framebuffer, Shader blurShaderHorz, Shader blurShaderVert) { - this.framebuffer = framebuffer; - this.blurShaderHorz = blurShaderHorz; - this.blurShaderVert = blurShaderVert; - } - } - - private static HashMap blurOutput = new HashMap<>(); - private static HashMap lastBlurUse = new HashMap<>(); - private static long lastBlur = 0; - private static HashSet requestedBlurs = new HashSet<>(); - - private static int fogColour = 0; - private static boolean registered = false; - public static void registerListener() { - if(!registered) { - registered = true; - MinecraftForge.EVENT_BUS.register(new BackgroundBlur()); - } - } - - private static boolean shouldBlur = true; - - public static void markDirty() { - if(Minecraft.getMinecraft().theWorld != null) { - shouldBlur = true; - } - } - - public static void processBlurs() { - if(shouldBlur) { - shouldBlur = false; - - long currentTime = System.currentTimeMillis(); - - for(float blur : requestedBlurs) { - lastBlur = currentTime; - lastBlurUse.put(blur, currentTime); - - int width = Minecraft.getMinecraft().displayWidth; - int height = Minecraft.getMinecraft().displayHeight; - - OutputStuff output = blurOutput.computeIfAbsent(blur, k -> { - Framebuffer fb = new Framebuffer(width, height, false); - fb.setFramebufferFilter(GL11.GL_NEAREST); - return new OutputStuff(fb, null, null); - }); - - if(output.framebuffer.framebufferWidth != width || output.framebuffer.framebufferHeight != height) { - output.framebuffer.createBindFramebuffer(width, height); - if(output.blurShaderHorz != null) { - output.blurShaderHorz.setProjectionMatrix(createProjectionMatrix(width, height)); - } - if(output.blurShaderVert != null) { - output.blurShaderVert.setProjectionMatrix(createProjectionMatrix(width, height)); - } - } - - blurBackground(output, blur); - } - - Set remove = new HashSet<>(); - for(Map.Entry entry : lastBlurUse.entrySet()) { - if(currentTime - entry.getValue() > 30*1000) { - remove.add(entry.getKey()); - } - } - remove.remove((float)NotEnoughUpdates.INSTANCE.config.itemlist.bgBlurFactor); - - for(Map.Entry entry : blurOutput.entrySet()) { - if(remove.contains(entry.getKey())) { - entry.getValue().framebuffer.deleteFramebuffer(); - entry.getValue().blurShaderHorz.deleteShader(); - entry.getValue().blurShaderVert.deleteShader(); - } - } - - lastBlurUse.keySet().removeAll(remove); - blurOutput.keySet().removeAll(remove); - - requestedBlurs.clear(); - } - } - - @SubscribeEvent(priority = EventPriority.HIGHEST) - public void onScreenRender(RenderGameOverlayEvent.Pre event) { - if(event.type == RenderGameOverlayEvent.ElementType.ALL) { - processBlurs(); - } - Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false); - } - - @SubscribeEvent - public void onFogColour(EntityViewRenderEvent.FogColors event) { - fogColour = 0xff000000; - fogColour |= ((int)(event.red*255) & 0xFF) << 16; - fogColour |= ((int)(event.green*255) & 0xFF) << 8; - fogColour |= (int)(event.blue*255) & 0xFF; - } - - private static Framebuffer blurOutputHorz = null; - - /** - * Creates a projection matrix that projects from our coordinate space [0->width; 0->height] to OpenGL coordinate - * space [-1 -> 1; 1 -> -1] (Note: flipped y-axis). - * - * This is so that we can render to and from the framebuffer in a way that is familiar to us, instead of needing to - * apply scales and translations manually. - */ - private static Matrix4f createProjectionMatrix(int width, int height) { - Matrix4f projMatrix = new Matrix4f(); - projMatrix.setIdentity(); - projMatrix.m00 = 2.0F / (float)width; - projMatrix.m11 = 2.0F / (float)(-height); - projMatrix.m22 = -0.0020001999F; - projMatrix.m33 = 1.0F; - projMatrix.m03 = -1.0F; - projMatrix.m13 = 1.0F; - projMatrix.m23 = -1.0001999F; - return projMatrix; - } - - private static double lastBgBlurFactor = -1; - private static void blurBackground(OutputStuff output, float blurFactor) { - if(!OpenGlHelper.isFramebufferEnabled() || !OpenGlHelper.areShadersSupported()) return; - - int width = Minecraft.getMinecraft().displayWidth; - int height = Minecraft.getMinecraft().displayHeight; - - GlStateManager.matrixMode(GL11.GL_PROJECTION); - GlStateManager.loadIdentity(); - GlStateManager.ortho(0.0D, width, height, 0.0D, 1000.0D, 3000.0D); - GlStateManager.matrixMode(GL11.GL_MODELVIEW); - GlStateManager.loadIdentity(); - GlStateManager.translate(0.0F, 0.0F, -2000.0F); - - if(blurOutputHorz == null) { - blurOutputHorz = new Framebuffer(width, height, false); - blurOutputHorz.setFramebufferFilter(GL11.GL_NEAREST); - } - if(blurOutputHorz == null || output == null) { - return; - } - if(blurOutputHorz.framebufferWidth != width || blurOutputHorz.framebufferHeight != height) { - blurOutputHorz.createBindFramebuffer(width, height); - Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false); - } - - if(output.blurShaderHorz == null) { - try { - output.blurShaderHorz = new Shader(Minecraft.getMinecraft().getResourceManager(), "blur", - output.framebuffer, blurOutputHorz); - output.blurShaderHorz.getShaderManager().getShaderUniform("BlurDir").set(1, 0); - output.blurShaderHorz.setProjectionMatrix(createProjectionMatrix(width, height)); - } catch(Exception e) { } - } - if(output.blurShaderVert == null) { - try { - output.blurShaderVert = new Shader(Minecraft.getMinecraft().getResourceManager(), "blur", - blurOutputHorz, output.framebuffer); - output.blurShaderVert.getShaderManager().getShaderUniform("BlurDir").set(0, 1); - output.blurShaderVert.setProjectionMatrix(createProjectionMatrix(width, height)); - } catch(Exception e) { } - } - if(output.blurShaderHorz != null && output.blurShaderVert != null) { - if(output.blurShaderHorz.getShaderManager().getShaderUniform("Radius") == null) { - //Corrupted shader? - return; - } - - output.blurShaderHorz.getShaderManager().getShaderUniform("Radius").set(blurFactor); - output.blurShaderVert.getShaderManager().getShaderUniform("Radius").set(blurFactor); - - GL11.glPushMatrix(); - GL30.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, Minecraft.getMinecraft().getFramebuffer().framebufferObject); - GL30.glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, output.framebuffer.framebufferObject); - GL30.glBlitFramebuffer(0, 0, width, height, - 0, 0, output.framebuffer.framebufferWidth, output.framebuffer.framebufferHeight, - GL11.GL_COLOR_BUFFER_BIT, GL11.GL_NEAREST); - - output.blurShaderHorz.loadShader(0); - output.blurShaderVert.loadShader(0); - GlStateManager.enableDepth(); - GL11.glPopMatrix(); - } - Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false); - } - - public static void renderBlurredBackground(float blurStrength, int screenWidth, int screenHeight, - int x, int y, int blurWidth, int blurHeight) { - renderBlurredBackground(blurStrength, screenWidth, screenHeight, x, y, blurWidth, blurHeight, false); - } - - /** - * Renders a subsection of the blurred framebuffer on to the corresponding section of the screen. - * Essentially, this method will "blur" the background inside the bounds specified by [x->x+blurWidth, y->y+blurHeight] - */ - public static void renderBlurredBackground(float blurStrength, int screenWidth, int screenHeight, - int x, int y, int blurWidth, int blurHeight, boolean forcedUpdate) { - if(!OpenGlHelper.isFramebufferEnabled() || !OpenGlHelper.areShadersSupported()) return; - if(blurStrength < 0.5) return; - requestedBlurs.add(blurStrength); - - long currentTime = System.currentTimeMillis(); - if(currentTime - lastBlur > 300) { - shouldBlur = true; - if(currentTime - lastBlur > 400 && forcedUpdate) return; - } - - if(blurOutput.isEmpty()) return; - - OutputStuff out = blurOutput.get(blurStrength); - if(out == null) { - out = blurOutput.values().iterator().next(); - } - - float uMin = x/(float)screenWidth; - float uMax = (x+blurWidth)/(float)screenWidth; - float vMin = (screenHeight-y)/(float)screenHeight; - float vMax = (screenHeight-y-blurHeight)/(float)screenHeight; - - GlStateManager.depthMask(false); - Gui.drawRect(x, y, x+blurWidth, y+blurHeight, fogColour); - out.framebuffer.bindFramebufferTexture(); - GlStateManager.color(1f, 1f, 1f, 1f); - RenderUtils.drawTexturedRect(x, y, blurWidth, blurHeight, uMin, uMax, vMin, vMax); - out.framebuffer.unbindFramebufferTexture(); - GlStateManager.depthMask(true); - } - + private static class OutputStuff { + public Framebuffer framebuffer; + public Shader blurShaderHorz = null; + public Shader blurShaderVert = null; + + public OutputStuff(Framebuffer framebuffer, Shader blurShaderHorz, Shader blurShaderVert) { + this.framebuffer = framebuffer; + this.blurShaderHorz = blurShaderHorz; + this.blurShaderVert = blurShaderVert; + } + } + + private static final HashMap blurOutput = new HashMap<>(); + private static final HashMap lastBlurUse = new HashMap<>(); + private static long lastBlur = 0; + private static final HashSet requestedBlurs = new HashSet<>(); + + private static int fogColour = 0; + private static boolean registered = false; + + public static void registerListener() { + if (!registered) { + registered = true; + MinecraftForge.EVENT_BUS.register(new BackgroundBlur()); + } + } + + private static boolean shouldBlur = true; + + public static void markDirty() { + if (Minecraft.getMinecraft().theWorld != null) { + shouldBlur = true; + } + } + + public static void processBlurs() { + if (shouldBlur) { + shouldBlur = false; + + long currentTime = System.currentTimeMillis(); + + for (float blur : requestedBlurs) { + lastBlur = currentTime; + lastBlurUse.put(blur, currentTime); + + int width = Minecraft.getMinecraft().displayWidth; + int height = Minecraft.getMinecraft().displayHeight; + + OutputStuff output = blurOutput.computeIfAbsent(blur, k -> { + Framebuffer fb = new Framebuffer(width, height, false); + fb.setFramebufferFilter(GL11.GL_NEAREST); + return new OutputStuff(fb, null, null); + }); + + if (output.framebuffer.framebufferWidth != width || output.framebuffer.framebufferHeight != height) { + output.framebuffer.createBindFramebuffer(width, height); + if (output.blurShaderHorz != null) { + output.blurShaderHorz.setProjectionMatrix(createProjectionMatrix(width, height)); + } + if (output.blurShaderVert != null) { + output.blurShaderVert.setProjectionMatrix(createProjectionMatrix(width, height)); + } + } + + blurBackground(output, blur); + } + + Set remove = new HashSet<>(); + for (Map.Entry entry : lastBlurUse.entrySet()) { + if (currentTime - entry.getValue() > 30 * 1000) { + remove.add(entry.getKey()); + } + } + remove.remove((float) NotEnoughUpdates.INSTANCE.config.itemlist.bgBlurFactor); + + for (Map.Entry entry : blurOutput.entrySet()) { + if (remove.contains(entry.getKey())) { + entry.getValue().framebuffer.deleteFramebuffer(); + entry.getValue().blurShaderHorz.deleteShader(); + entry.getValue().blurShaderVert.deleteShader(); + } + } + + lastBlurUse.keySet().removeAll(remove); + blurOutput.keySet().removeAll(remove); + + requestedBlurs.clear(); + } + } + + @SubscribeEvent(priority = EventPriority.HIGHEST) + public void onScreenRender(RenderGameOverlayEvent.Pre event) { + if (event.type == RenderGameOverlayEvent.ElementType.ALL) { + processBlurs(); + } + Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false); + } + + @SubscribeEvent + public void onFogColour(EntityViewRenderEvent.FogColors event) { + fogColour = 0xff000000; + fogColour |= ((int) (event.red * 255) & 0xFF) << 16; + fogColour |= ((int) (event.green * 255) & 0xFF) << 8; + fogColour |= (int) (event.blue * 255) & 0xFF; + } + + private static Framebuffer blurOutputHorz = null; + + /** + * Creates a projection matrix that projects from our coordinate space [0->width; 0->height] to OpenGL coordinate + * space [-1 -> 1; 1 -> -1] (Note: flipped y-axis). + *

+ * This is so that we can render to and from the framebuffer in a way that is familiar to us, instead of needing to + * apply scales and translations manually. + */ + private static Matrix4f createProjectionMatrix(int width, int height) { + Matrix4f projMatrix = new Matrix4f(); + projMatrix.setIdentity(); + projMatrix.m00 = 2.0F / (float) width; + projMatrix.m11 = 2.0F / (float) (-height); + projMatrix.m22 = -0.0020001999F; + projMatrix.m33 = 1.0F; + projMatrix.m03 = -1.0F; + projMatrix.m13 = 1.0F; + projMatrix.m23 = -1.0001999F; + return projMatrix; + } + + private static final double lastBgBlurFactor = -1; + + private static void blurBackground(OutputStuff output, float blurFactor) { + if (!OpenGlHelper.isFramebufferEnabled() || !OpenGlHelper.areShadersSupported()) return; + + int width = Minecraft.getMinecraft().displayWidth; + int height = Minecraft.getMinecraft().displayHeight; + + GlStateManager.matrixMode(GL11.GL_PROJECTION); + GlStateManager.loadIdentity(); + GlStateManager.ortho(0.0D, width, height, 0.0D, 1000.0D, 3000.0D); + GlStateManager.matrixMode(GL11.GL_MODELVIEW); + GlStateManager.loadIdentity(); + GlStateManager.translate(0.0F, 0.0F, -2000.0F); + + if (blurOutputHorz == null) { + blurOutputHorz = new Framebuffer(width, height, false); + blurOutputHorz.setFramebufferFilter(GL11.GL_NEAREST); + } + if (blurOutputHorz == null || output == null) { + return; + } + if (blurOutputHorz.framebufferWidth != width || blurOutputHorz.framebufferHeight != height) { + blurOutputHorz.createBindFramebuffer(width, height); + Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false); + } + + if (output.blurShaderHorz == null) { + try { + output.blurShaderHorz = new Shader(Minecraft.getMinecraft().getResourceManager(), "blur", + output.framebuffer, blurOutputHorz + ); + output.blurShaderHorz.getShaderManager().getShaderUniform("BlurDir").set(1, 0); + output.blurShaderHorz.setProjectionMatrix(createProjectionMatrix(width, height)); + } catch (Exception ignored) { + } + } + if (output.blurShaderVert == null) { + try { + output.blurShaderVert = new Shader(Minecraft.getMinecraft().getResourceManager(), "blur", + blurOutputHorz, output.framebuffer + ); + output.blurShaderVert.getShaderManager().getShaderUniform("BlurDir").set(0, 1); + output.blurShaderVert.setProjectionMatrix(createProjectionMatrix(width, height)); + } catch (Exception ignored) { + } + } + if (output.blurShaderHorz != null && output.blurShaderVert != null) { + if (output.blurShaderHorz.getShaderManager().getShaderUniform("Radius") == null) { + //Corrupted shader? + return; + } + + output.blurShaderHorz.getShaderManager().getShaderUniform("Radius").set(blurFactor); + output.blurShaderVert.getShaderManager().getShaderUniform("Radius").set(blurFactor); + + GL11.glPushMatrix(); + GL30.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, Minecraft.getMinecraft().getFramebuffer().framebufferObject); + GL30.glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, output.framebuffer.framebufferObject); + GL30.glBlitFramebuffer(0, 0, width, height, + 0, 0, output.framebuffer.framebufferWidth, output.framebuffer.framebufferHeight, + GL11.GL_COLOR_BUFFER_BIT, GL11.GL_NEAREST + ); + + output.blurShaderHorz.loadShader(0); + output.blurShaderVert.loadShader(0); + GlStateManager.enableDepth(); + GL11.glPopMatrix(); + } + Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false); + } + + public static void renderBlurredBackground( + float blurStrength, int screenWidth, int screenHeight, + int x, int y, int blurWidth, int blurHeight + ) { + renderBlurredBackground(blurStrength, screenWidth, screenHeight, x, y, blurWidth, blurHeight, false); + } + + /** + * Renders a subsection of the blurred framebuffer on to the corresponding section of the screen. + * Essentially, this method will "blur" the background inside the bounds specified by [x->x+blurWidth, y->y+blurHeight] + */ + public static void renderBlurredBackground( + float blurStrength, int screenWidth, int screenHeight, + int x, int y, int blurWidth, int blurHeight, boolean forcedUpdate + ) { + if (!OpenGlHelper.isFramebufferEnabled() || !OpenGlHelper.areShadersSupported()) return; + if (blurStrength < 0.5) return; + requestedBlurs.add(blurStrength); + + long currentTime = System.currentTimeMillis(); + if (currentTime - lastBlur > 300) { + shouldBlur = true; + if (currentTime - lastBlur > 400 && forcedUpdate) return; + } + + if (blurOutput.isEmpty()) return; + + OutputStuff out = blurOutput.get(blurStrength); + if (out == null) { + out = blurOutput.values().iterator().next(); + } + + float uMin = x / (float) screenWidth; + float uMax = (x + blurWidth) / (float) screenWidth; + float vMin = (screenHeight - y) / (float) screenHeight; + float vMax = (screenHeight - y - blurHeight) / (float) screenHeight; + + GlStateManager.depthMask(false); + Gui.drawRect(x, y, x + blurWidth, y + blurHeight, fogColour); + out.framebuffer.bindFramebufferTexture(); + GlStateManager.color(1f, 1f, 1f, 1f); + RenderUtils.drawTexturedRect(x, y, blurWidth, blurHeight, uMin, uMax, vMin, vMax); + out.framebuffer.unbindFramebufferTexture(); + GlStateManager.depthMask(true); + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/ChromaColour.java b/src/main/java/io/github/moulberry/notenoughupdates/core/ChromaColour.java index 9509c332b3..8f4dd87dee 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/ChromaColour.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/ChromaColour.java @@ -3,93 +3,90 @@ import java.awt.*; public class ChromaColour { - - public static String special(int chromaSpeed, int alpha, int rgb) { - return special(chromaSpeed, alpha, (rgb & 0xFF0000) >> 16, (rgb & 0x00FF00) >> 8, (rgb & 0x0000FF)); - } - - private static final int RADIX = 10; - - public static String special(int chromaSpeed, int alpha, int r, int g, int b) { - StringBuilder sb = new StringBuilder(); - sb.append(Integer.toString(chromaSpeed, RADIX)).append(":"); - sb.append(Integer.toString(alpha, RADIX)).append(":"); - sb.append(Integer.toString(r, RADIX)).append(":"); - sb.append(Integer.toString(g, RADIX)).append(":"); - sb.append(Integer.toString(b, RADIX)); - return sb.toString(); - } - - private static int[] decompose(String csv) { - String[] split = csv.split(":"); - - int[] arr = new int[split.length]; - - - for(int i=0; i 0) { - float seconds = getSecondsForSpeed(chr); - hsv[0] += (System.currentTimeMillis()-startTime)/1000f/seconds; - hsv[0] %= 1; - if(hsv[0] < 0) hsv[0] += 1; - } - - return (a & 0xFF) << 24 | (Color.HSBtoRGB(hsv[0], hsv[1], hsv[2]) & 0x00FFFFFF); - } - - public static int rotateHue(int argb, int degrees) { - int a = (argb >> 24) & 0xFF; - int r = (argb >> 16) & 0xFF; - int g = (argb >> 8) & 0xFF; - int b = (argb) & 0xFF; - - float[] hsv = Color.RGBtoHSB(r, g, b, null); - - hsv[0] += degrees/360f; - hsv[0] %= 1; - - return (a & 0xFF) << 24 | (Color.HSBtoRGB(hsv[0], hsv[1], hsv[2]) & 0x00FFFFFF); - } - - + public static String special(int chromaSpeed, int alpha, int rgb) { + return special(chromaSpeed, alpha, (rgb & 0xFF0000) >> 16, (rgb & 0x00FF00) >> 8, (rgb & 0x0000FF)); + } + + private static final int RADIX = 10; + + public static String special(int chromaSpeed, int alpha, int r, int g, int b) { + StringBuilder sb = new StringBuilder(); + sb.append(Integer.toString(chromaSpeed, RADIX)).append(":"); + sb.append(Integer.toString(alpha, RADIX)).append(":"); + sb.append(Integer.toString(r, RADIX)).append(":"); + sb.append(Integer.toString(g, RADIX)).append(":"); + sb.append(Integer.toString(b, RADIX)); + return sb.toString(); + } + + private static int[] decompose(String csv) { + String[] split = csv.split(":"); + + int[] arr = new int[split.length]; + + for (int i = 0; i < split.length; i++) { + arr[i] = Integer.parseInt(split[split.length - 1 - i], RADIX); + } + return arr; + } + + public static int specialToSimpleRGB(String special) { + int[] d = decompose(special); + int r = d[2]; + int g = d[1]; + int b = d[0]; + int a = d[3]; + int chr = d[4]; + + return (a & 0xFF) << 24 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF); + } + + public static int getSpeed(String special) { + return decompose(special)[4]; + } + + public static float getSecondsForSpeed(int speed) { + return (255 - speed) / 254f * (MAX_CHROMA_SECS - MIN_CHROMA_SECS) + MIN_CHROMA_SECS; + } + + private static final int MIN_CHROMA_SECS = 1; + private static final int MAX_CHROMA_SECS = 60; + + public static long startTime = -1; + + public static int specialToChromaRGB(String special) { + if (startTime < 0) startTime = System.currentTimeMillis(); + + int[] d = decompose(special); + int chr = d[4]; + int a = d[3]; + int r = d[2]; + int g = d[1]; + int b = d[0]; + + float[] hsv = Color.RGBtoHSB(r, g, b, null); + + if (chr > 0) { + float seconds = getSecondsForSpeed(chr); + hsv[0] += (System.currentTimeMillis() - startTime) / 1000f / seconds; + hsv[0] %= 1; + if (hsv[0] < 0) hsv[0] += 1; + } + + return (a & 0xFF) << 24 | (Color.HSBtoRGB(hsv[0], hsv[1], hsv[2]) & 0x00FFFFFF); + } + + public static int rotateHue(int argb, int degrees) { + int a = (argb >> 24) & 0xFF; + int r = (argb >> 16) & 0xFF; + int g = (argb >> 8) & 0xFF; + int b = (argb) & 0xFF; + + float[] hsv = Color.RGBtoHSB(r, g, b, null); + + hsv[0] += degrees / 360f; + hsv[0] %= 1; + + return (a & 0xFF) << 24 | (Color.HSBtoRGB(hsv[0], hsv[1], hsv[2]) & 0x00FFFFFF); + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/GlScissorStack.java b/src/main/java/io/github/moulberry/notenoughupdates/core/GlScissorStack.java index f70bec40e8..7cc8893fff 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/GlScissorStack.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/GlScissorStack.java @@ -7,81 +7,79 @@ import java.util.LinkedList; public class GlScissorStack { + private static class Bounds { + int left; + int top; + int right; + int bottom; - private static class Bounds { - int left; - int top; - int right; - int bottom; + public Bounds(int left, int top, int right, int bottom) { + this.left = left; + this.top = top; + this.right = right; + this.bottom = bottom; + } - public Bounds(int left, int top, int right, int bottom) { - this.left = left; - this.top = top; - this.right = right; - this.bottom = bottom; - } + public Bounds createSubBound(int left, int top, int right, int bottom) { + left = Math.max(left, this.left); + top = Math.max(top, this.top); + right = Math.min(right, this.right); + bottom = Math.min(bottom, this.bottom); - public Bounds createSubBound(int left, int top, int right, int bottom) { - left = Math.max(left, this.left); - top = Math.max(top, this.top); - right = Math.min(right, this.right); - bottom = Math.min(bottom, this.bottom); + if (top > bottom) { + top = bottom; + } + if (left > right) { + left = right; + } - if(top > bottom) { - top = bottom; - } - if(left > right) { - left = right; - } + return new Bounds(left, top, right, bottom); + } - return new Bounds(left, top, right, bottom); - } + public void set(ScaledResolution scaledResolution) { + int height = Minecraft.getMinecraft().displayHeight; + int scale = scaledResolution.getScaleFactor(); + GL11.glScissor(left * scale, height - bottom * scale, (right - left) * scale, (bottom - top) * scale); + } + } - public void set(ScaledResolution scaledResolution) { - int height = Minecraft.getMinecraft().displayHeight; - int scale = scaledResolution.getScaleFactor(); - GL11.glScissor(left*scale, height-bottom*scale, (right-left)*scale, (bottom-top)*scale); - } - } + private static final LinkedList boundsStack = new LinkedList<>(); - private static LinkedList boundsStack = new LinkedList<>(); + public static void push(int left, int top, int right, int bottom, ScaledResolution scaledResolution) { + if (right < left) { + int temp = right; + right = left; + left = temp; + } + if (bottom < top) { + int temp = bottom; + bottom = top; + top = temp; + } + if (boundsStack.isEmpty()) { + boundsStack.push(new Bounds(left, top, right, bottom)); + } else { + boundsStack.push(boundsStack.peek().createSubBound(left, top, right, bottom)); + } + if (!boundsStack.isEmpty()) { + boundsStack.peek().set(scaledResolution); + } + GL11.glEnable(GL11.GL_SCISSOR_TEST); + } - public static void push(int left, int top, int right, int bottom, ScaledResolution scaledResolution) { - if(right < left) { - int temp = right; - right = left; - left = temp; - } - if(bottom < top) { - int temp = bottom; - bottom = top; - top = temp; - } - if(boundsStack.isEmpty()) { - boundsStack.push(new Bounds(left, top, right, bottom)); - } else { - boundsStack.push(boundsStack.peek().createSubBound(left, top, right, bottom)); - } - if(!boundsStack.isEmpty()) { - boundsStack.peek().set(scaledResolution); - } - GL11.glEnable(GL11.GL_SCISSOR_TEST); - } - - public static void pop(ScaledResolution scaledResolution) { - if(!boundsStack.isEmpty()) { - boundsStack.pop(); - } - if(boundsStack.isEmpty()) { - GL11.glDisable(GL11.GL_SCISSOR_TEST); - } else { - boundsStack.peek().set(scaledResolution); - } - } - - public static void clear() { - boundsStack.clear(); - GL11.glDisable(GL11.GL_SCISSOR_TEST); - } + public static void pop(ScaledResolution scaledResolution) { + if (!boundsStack.isEmpty()) { + boundsStack.pop(); + } + if (boundsStack.isEmpty()) { + GL11.glDisable(GL11.GL_SCISSOR_TEST); + } else { + boundsStack.peek().set(scaledResolution); + } + } + public static void clear() { + boundsStack.clear(); + GL11.glDisable(GL11.GL_SCISSOR_TEST); + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElement.java b/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElement.java index 5969c6912e..c1c76675e0 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElement.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElement.java @@ -2,9 +2,10 @@ import net.minecraft.client.gui.Gui; -public abstract class GuiElement extends Gui { +public abstract class GuiElement extends Gui { + public abstract void render(); - public abstract void render(); - public abstract boolean mouseInput(int mouseX, int mouseY); - public abstract boolean keyboardInput(); + public abstract boolean mouseInput(int mouseX, int mouseY); + + public abstract boolean keyboardInput(); } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementBoolean.java b/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementBoolean.java index bfd9561284..d5cbb3ad66 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementBoolean.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementBoolean.java @@ -7,115 +7,122 @@ import net.minecraft.client.renderer.GlStateManager; import net.minecraft.util.ResourceLocation; import org.lwjgl.input.Mouse; +import org.lwjgl.opengl.GL11; import java.util.function.Consumer; public class GuiElementBoolean extends GuiElement { - - public int x; - public int y; - private boolean value; - private int clickRadius; - private Consumer toggleCallback; - - private boolean previewValue; - private int animation = 0; - private long lastMillis = 0; - - private static final int xSize = 48; - private static final int ySize = 14; - - public GuiElementBoolean(int x, int y, boolean value, Consumer toggleCallback) { - this(x, y, value, 0, toggleCallback); - } - - public GuiElementBoolean(int x, int y, boolean value, int clickRadius, Consumer toggleCallback) { - this.x = x; - this.y = y; - this.value = value; - this.previewValue = value; - this.clickRadius = clickRadius; - this.toggleCallback = toggleCallback; - this.lastMillis = System.currentTimeMillis(); - - if(value) animation = 36; - } - - @Override - public void render() { - GlStateManager.color(1, 1, 1, 1); - Minecraft.getMinecraft().getTextureManager().bindTexture(GuiTextures.BAR); - RenderUtils.drawTexturedRect(x, y, xSize, ySize); - - ResourceLocation buttonLoc = GuiTextures.ON; - long currentMillis = System.currentTimeMillis(); - long deltaMillis = currentMillis - lastMillis; - lastMillis = currentMillis; - boolean passedLimit = false; - if(previewValue != value) { - if((previewValue && animation > 12) || - (!previewValue && animation < 24)) { - passedLimit = true; - } - } - if(previewValue != passedLimit) { - animation += deltaMillis/10; - } else { - animation -= deltaMillis/10; - } - lastMillis -= deltaMillis%10; - - if(previewValue == value) { - animation = Math.max(0, Math.min(36, animation)); - } else if(!passedLimit) { - if(previewValue) { - animation = Math.max(0, Math.min(12, animation)); - } else { - animation = Math.max(24, Math.min(36, animation)); - } - } else { - if(previewValue) { - animation = Math.max(12, animation); - } else { - animation = Math.min(24, animation); - } - } - - int animation = (int)(LerpUtils.sigmoidZeroOne(this.animation/36f)*36); - if(animation < 3) { - buttonLoc = GuiTextures.OFF; - } else if(animation < 13) { - buttonLoc = GuiTextures.ONE; - } else if(animation < 23) { - buttonLoc = GuiTextures.TWO; - } else if(animation < 33) { - buttonLoc = GuiTextures.THREE; - } - - Minecraft.getMinecraft().getTextureManager().bindTexture(buttonLoc); - RenderUtils.drawTexturedRect(x+animation, y, 12, 14); - } - - @Override - public boolean mouseInput(int mouseX, int mouseY) { - if(mouseX > x-clickRadius && mouseX < x+xSize+clickRadius && - mouseY > y-clickRadius && mouseY < y+ySize+clickRadius) { - if(Mouse.getEventButton() == 0) { - if(Mouse.getEventButtonState()) { - previewValue = !value; - } else if(previewValue == !value) { - value = !value; - toggleCallback.accept(value); - } - } - } else { - previewValue = value; - } - return false; - } - - @Override - public boolean keyboardInput() { - return false; - } + public int x; + public int y; + private boolean value; + private final int clickRadius; + private final Consumer toggleCallback; + + private boolean previewValue; + private int animation = 0; + private long lastMillis = 0; + + private static final int xSize = 48; + private static final int ySize = 14; + + public GuiElementBoolean(int x, int y, boolean value, Consumer toggleCallback) { + this(x, y, value, 0, toggleCallback); + } + + public GuiElementBoolean(int x, int y, boolean value, int clickRadius, Consumer toggleCallback) { + this.x = x; + this.y = y; + this.value = value; + this.previewValue = value; + this.clickRadius = clickRadius; + this.toggleCallback = toggleCallback; + this.lastMillis = System.currentTimeMillis(); + + if (value) animation = 36; + } + + @Override + public void render() { + GlStateManager.color(1, 1, 1, 1); + ResourceLocation buttonLoc = GuiTextures.ON; + ResourceLocation barLoc = GuiTextures.BAR_ON; + long currentMillis = System.currentTimeMillis(); + long deltaMillis = currentMillis - lastMillis; + lastMillis = currentMillis; + boolean passedLimit = false; + if (previewValue != value) { + if ((previewValue && animation > 12) || + (!previewValue && animation < 24)) { + passedLimit = true; + } + } + if (previewValue != passedLimit) { + animation += deltaMillis / 10; + } else { + animation -= deltaMillis / 10; + } + lastMillis -= deltaMillis % 10; + + if (previewValue == value) { + animation = Math.max(0, Math.min(36, animation)); + } else if (!passedLimit) { + if (previewValue) { + animation = Math.max(0, Math.min(12, animation)); + } else { + animation = Math.max(24, Math.min(36, animation)); + } + } else { + if (previewValue) { + animation = Math.max(12, animation); + } else { + animation = Math.min(24, animation); + } + } + + int animation = (int) (LerpUtils.sigmoidZeroOne(this.animation / 36f) * 36); + if (animation < 3) { + buttonLoc = GuiTextures.OFF; + barLoc = GuiTextures.BAR; + } else if (animation < 13) { + buttonLoc = GuiTextures.ONE; + barLoc = GuiTextures.BAR_ONE; + } else if (animation < 23) { + buttonLoc = GuiTextures.TWO; + barLoc = GuiTextures.BAR_TWO; + } else if (animation < 33) { + buttonLoc = GuiTextures.THREE; + barLoc = GuiTextures.BAR_THREE; + } + + GL11.glTranslatef(0, 0, 100); + Minecraft.getMinecraft().getTextureManager().bindTexture(buttonLoc); + RenderUtils.drawTexturedRect(x + animation, y, 12, 14); + GL11.glTranslatef(0, 0, -100); + + Minecraft.getMinecraft().getTextureManager().bindTexture(barLoc); + RenderUtils.drawTexturedRect(x, y, xSize, ySize); + } + + @Override + public boolean mouseInput(int mouseX, int mouseY) { + if (mouseX > x - clickRadius && mouseX < x + xSize + clickRadius && + mouseY > y - clickRadius && mouseY < y + ySize + clickRadius) { + if (Mouse.getEventButton() == 0) { + if (Mouse.getEventButtonState()) { + previewValue = !value; + } else if (previewValue == !value) { + value = !value; + toggleCallback.accept(value); + } + } + } else { + previewValue = value; + } + return false; + } + + @Override + public boolean keyboardInput() { + return false; + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementColour.java b/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementColour.java index 3ab47531d3..48996c8d41 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementColour.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementColour.java @@ -18,383 +18,413 @@ import java.util.function.Consumer; public class GuiElementColour extends GuiElement { - - public static final ResourceLocation colour_selector_dot = new ResourceLocation("notenoughupdates:core/colour_selector_dot.png"); - public static final ResourceLocation colour_selector_bar = new ResourceLocation("notenoughupdates:core/colour_selector_bar.png"); - public static final ResourceLocation colour_selector_bar_alpha = new ResourceLocation("notenoughupdates:core/colour_selector_bar_alpha.png"); - public static final ResourceLocation colour_selector_chroma = new ResourceLocation("notenoughupdates:core/colour_selector_chroma.png"); - - private static final ResourceLocation colourPickerLocation = new ResourceLocation("mbcore:dynamic/colourpicker"); - private static final ResourceLocation colourPickerBarValueLocation = new ResourceLocation("mbcore:dynamic/colourpickervalue"); - private static final ResourceLocation colourPickerBarOpacityLocation = new ResourceLocation("mbcore:dynamic/colourpickeropacity"); - private final GuiElementTextField hexField = new GuiElementTextField("", - GuiElementTextField.SCALE_TEXT | GuiElementTextField.FORCE_CAPS | GuiElementTextField.NO_SPACE); - - private int x; - private int y; - private int xSize = 119; - private int ySize = 89; - - private float wheelAngle = 0; - private float wheelRadius = 0; - - private int clickedComponent = -1; - - private Consumer colourChangedCallback; - private Runnable closeCallback; - private String colour; - - private final boolean opacitySlider; - private final boolean valueSlider; - - public GuiElementColour(int x, int y, String initialColour, Consumer colourChangedCallback, - Runnable closeCallback) { - this(x, y, initialColour, colourChangedCallback, closeCallback, true, true); - } - - public GuiElementColour(int x, int y, String initialColour, Consumer colourChangedCallback, - Runnable closeCallback, boolean opacitySlider, boolean valueSlider) { - final ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); - - this.y = Math.max(10, Math.min(scaledResolution.getScaledHeight()-ySize-10, y)); - this.x = Math.max(10, Math.min(scaledResolution.getScaledWidth()-xSize-10, x)); - - this.colour = initialColour; - this.colourChangedCallback = colourChangedCallback; - this.closeCallback = closeCallback; - - int colour = ChromaColour.specialToSimpleRGB(initialColour); - Color c = new Color(colour); - float[] hsv = Color.RGBtoHSB(c.getRed(), c.getGreen(), c.getBlue(), null); - updateAngleAndRadius(hsv); - - this.opacitySlider = opacitySlider; - this.valueSlider = valueSlider; - - if(!valueSlider) xSize -= 15; - if(!opacitySlider) xSize -= 15; - } - - public void updateAngleAndRadius(float[] hsv) { - this.wheelRadius = hsv[1]; - this.wheelAngle = hsv[0]*360; - } - - public void render() { - RenderUtils.drawFloatingRectDark(x, y, xSize, ySize); - - int currentColour = ChromaColour.specialToSimpleRGB(colour); - Color c = new Color(currentColour, true); - float[] hsv = Color.RGBtoHSB(c.getRed(), c.getGreen(), c.getBlue(), null); - - BufferedImage bufferedImage = new BufferedImage(288, 288, BufferedImage.TYPE_INT_ARGB); - float borderRadius = 0.05f; - if(Keyboard.isKeyDown(Keyboard.KEY_N)) borderRadius = 0; - for(int x=-16; x<272; x++) { - for(int y=-16; y<272; y++) { - float radius = (float) Math.sqrt(((x-128)*(x-128)+(y-128)*(y-128))/16384f); - float angle = (float) Math.toDegrees(Math.atan((128-x)/(y-128+1E-5))+Math.PI/2); - if(y < 128) angle += 180; - if(radius <= 1) { - int rgb = Color.getHSBColor(angle/360f, (float)Math.pow(radius, 1.5f), hsv[2]).getRGB(); - bufferedImage.setRGB(x+16, y+16, rgb); - } else if(radius <= 1+borderRadius) { - float invBlackAlpha = Math.abs(radius-1-borderRadius/2)/borderRadius*2; - float blackAlpha = 1-invBlackAlpha; - - if(radius > 1+borderRadius/2) { - bufferedImage.setRGB(x+16, y+16, (int)(blackAlpha*255) << 24); - } else { - Color col = Color.getHSBColor(angle/360f, 1, hsv[2]); - int rgb = (int)(col.getRed()*invBlackAlpha) << 16 | - (int)(col.getGreen()*invBlackAlpha) << 8 | - (int)(col.getBlue()*invBlackAlpha); - bufferedImage.setRGB(x+16, y+16, 0xff000000 | rgb); - } - - } - } - } - - BufferedImage bufferedImageValue = new BufferedImage(10, 64, BufferedImage.TYPE_INT_ARGB); - for(int x=0; x<10; x++) { - for(int y=0; y<64; y++) { - if((x == 0 || x == 9) && (y == 0 || y == 63)) continue; - - int rgb = Color.getHSBColor(wheelAngle/360, wheelRadius, (64-y)/64f).getRGB(); - bufferedImageValue.setRGB(x, y, rgb); - } - } - - BufferedImage bufferedImageOpacity = new BufferedImage(10, 64, BufferedImage.TYPE_INT_ARGB); - for(int x=0; x<10; x++) { - for(int y=0; y<64; y++) { - if((x == 0 || x == 9) && (y == 0 || y == 63)) continue; - - int rgb = (currentColour & 0x00FFFFFF) | (Math.min(255, (64-y)*4) << 24); - bufferedImageOpacity.setRGB(x, y, rgb); - } - } - - float selradius = (float)Math.pow(wheelRadius, 1/1.5f)*32; - int selx = (int)(Math.cos(Math.toRadians(wheelAngle))*selradius); - int sely = (int)(Math.sin(Math.toRadians(wheelAngle))*selradius); - - int valueOffset = 0; - if(valueSlider) { - valueOffset = 15; - - Minecraft.getMinecraft().getTextureManager().loadTexture(colourPickerBarValueLocation, new DynamicTexture(bufferedImageValue)); - Minecraft.getMinecraft().getTextureManager().bindTexture(colourPickerBarValueLocation); - GlStateManager.color(1, 1, 1, 1); - RenderUtils.drawTexturedRect(x+5+64+5, y+5, 10, 64, GL11.GL_NEAREST); - } - - int opacityOffset = 0; - if(opacitySlider) { - opacityOffset = 15; - - Minecraft.getMinecraft().getTextureManager().bindTexture(colour_selector_bar_alpha); - GlStateManager.color(1, 1, 1, 1); - RenderUtils.drawTexturedRect(x+5+64+5+valueOffset, y+5, 10, 64, GL11.GL_NEAREST); - - Minecraft.getMinecraft().getTextureManager().loadTexture(colourPickerBarOpacityLocation, new DynamicTexture(bufferedImageOpacity)); - Minecraft.getMinecraft().getTextureManager().bindTexture(colourPickerBarOpacityLocation); - GlStateManager.color(1, 1, 1, 1); - RenderUtils.drawTexturedRect(x+5+64+5+valueOffset, y+5, 10, 64, GL11.GL_NEAREST); - } - - int chromaSpeed = ChromaColour.getSpeed(colour); - int currentColourChroma = ChromaColour.specialToChromaRGB(colour); - Color cChroma = new Color(currentColourChroma, true); - float hsvChroma[] = Color.RGBtoHSB(cChroma.getRed(), cChroma.getGreen(), cChroma.getBlue(), null); - - if(chromaSpeed > 0) { - Gui.drawRect(x+5+64+valueOffset+opacityOffset+5+1, y+5+1, - x+5+64+valueOffset+opacityOffset+5+10-1, y+5+64-1, - Color.HSBtoRGB(hsvChroma[0], 0.8f, 0.8f)); - } else { - Gui.drawRect(x+5+64+valueOffset+opacityOffset+5+1, y+5+27+1, - x+5+64+valueOffset+opacityOffset+5+10-1, y+5+37-1, - Color.HSBtoRGB((hsvChroma[0]+(System.currentTimeMillis()-ChromaColour.startTime)/1000f)%1, 0.8f, 0.8f)); - } - - Minecraft.getMinecraft().getTextureManager().bindTexture(colour_selector_bar); - GlStateManager.color(1, 1, 1, 1); - if(valueSlider) RenderUtils.drawTexturedRect(x+5+64+5, y+5, 10, 64, GL11.GL_NEAREST); - if(opacitySlider) RenderUtils.drawTexturedRect(x+5+64+5+valueOffset, y+5, 10, 64, GL11.GL_NEAREST); - - if(chromaSpeed > 0) { - RenderUtils.drawTexturedRect(x+5+64+valueOffset+opacityOffset+5, y+5, 10, 64, GL11.GL_NEAREST); - } else { - Minecraft.getMinecraft().getTextureManager().bindTexture(colour_selector_chroma); - RenderUtils.drawTexturedRect(x+5+64+valueOffset+opacityOffset+5, y+5+27, 10, 10, GL11.GL_NEAREST); - } - - if(valueSlider) Gui.drawRect(x+5+64+5, y+5+64-(int)(64*hsv[2]), - x+5+64+valueOffset, y+5+64-(int)(64*hsv[2])+1, 0xFF000000); - if(opacitySlider) Gui.drawRect(x+5+64+5+valueOffset, y+5+64-c.getAlpha()/4, - x+5+64+valueOffset+opacityOffset, y+5+64-c.getAlpha()/4-1, 0xFF000000); - if(chromaSpeed > 0) { - Gui.drawRect(x+5+64+valueOffset+opacityOffset+5, - y+5+64-(int)(chromaSpeed/255f*64), - x+5+64+valueOffset+opacityOffset+5+10, - y+5+64-(int)(chromaSpeed/255f*64)+1, 0xFF000000); - } - - Minecraft.getMinecraft().getTextureManager().loadTexture(colourPickerLocation, new DynamicTexture(bufferedImage)); - Minecraft.getMinecraft().getTextureManager().bindTexture(colourPickerLocation); - GlStateManager.color(1, 1, 1, 1); - RenderUtils.drawTexturedRect(x+1, y+1, 72, 72, GL11.GL_LINEAR); - - Minecraft.getMinecraft().getTextureManager().bindTexture(colour_selector_dot); - GlStateManager.color(1, 1, 1, 1); - RenderUtils.drawTexturedRect(x+5+32+selx-4, y+5+32+sely-4, 8, 8, GL11.GL_NEAREST); - - TextRenderUtils.drawStringCenteredScaledMaxWidth(EnumChatFormatting.GRAY.toString()+Math.round(hsv[2]*100)+"", - Minecraft.getMinecraft().fontRendererObj, - x+5+64+5+5-(Math.round(hsv[2]*100)==100?1:0), y+5+64+5+5, true, 13, -1); - if(opacitySlider) { - TextRenderUtils.drawStringCenteredScaledMaxWidth(EnumChatFormatting.GRAY.toString()+Math.round(c.getAlpha()/255f*100)+"", - Minecraft.getMinecraft().fontRendererObj, - x+5+64+5+valueOffset+5, y+5+64+5+5, true, 13, -1); - } - if(chromaSpeed > 0) { - TextRenderUtils.drawStringCenteredScaledMaxWidth(EnumChatFormatting.GRAY.toString()+ - (int)ChromaColour.getSecondsForSpeed(chromaSpeed)+"s", - Minecraft.getMinecraft().fontRendererObj, - x+5+64+5+valueOffset+opacityOffset+6, y+5+64+5+5, true, 13, -1); - } - - hexField.setSize(48, 10); - if(!hexField.getFocus()) hexField.setText(Integer.toHexString(c.getRGB() & 0xFFFFFF).toUpperCase()); - - StringBuilder sb = new StringBuilder(EnumChatFormatting.GRAY+"#"); - for(int i=0; i<6-hexField.getText().length(); i++) { - sb.append("0"); - } - sb.append(EnumChatFormatting.WHITE); - - hexField.setPrependText(sb.toString()); - hexField.render(x+5+8, y+5+64+5); - } - - public boolean mouseInput(int mouseX, int mouseY) { - ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); - float mouseXF = (float)(Mouse.getX() * scaledResolution.getScaledWidth_double() / - Minecraft.getMinecraft().displayWidth); - float mouseYF = (float)(scaledResolution.getScaledHeight_double() - Mouse.getY() * - scaledResolution.getScaledHeight_double() / Minecraft.getMinecraft().displayHeight - 1); - - if((Mouse.getEventButton() == 0 || Mouse.getEventButton() == 1) && Mouse.getEventButtonState()) { - if(mouseX > x+5+8 && mouseX < x+5+8+48) { - if(mouseY > y+5+64+5 && mouseY < y+5+64+5+10) { - hexField.mouseClicked(mouseX, mouseY, Mouse.getEventButton()); - clickedComponent = -1; - return true; - } - } - } - if(!Mouse.getEventButtonState() && Mouse.getEventButton() == 0) { - clickedComponent = -1; - } - if(Mouse.getEventButtonState() && Mouse.getEventButton() == 0) { - if(mouseX >= x && mouseX <= x+119 && - mouseY >= y && mouseY <= y+89) { - hexField.unfocus(); - - int xWheel = mouseX - x - 5; - int yWheel = mouseY - y - 5; - - if(xWheel > 0 && xWheel < 64) { - if(yWheel > 0 && yWheel < 64) { - clickedComponent = 0; - } - } - - int xValue = mouseX - (x+5+64+5); - int y = mouseY - this.y - 5; - - int opacityOffset = opacitySlider ? 15 : 0; - int valueOffset = valueSlider ? 15 : 0; - - if(y > -5 && y <= 69) { - if(valueSlider) { - if(xValue > 0 && xValue < 10) { - clickedComponent = 1; - } - } - - if(opacitySlider) { - int xOpacity = mouseX - (x+5+64+5+valueOffset); - - if(xOpacity > 0 && xOpacity < 10) { - clickedComponent = 2; - } - } - } - - int chromaSpeed = ChromaColour.getSpeed(colour); - int xChroma = mouseX - (x+5+64+valueOffset+opacityOffset+5); - if(xChroma > 0 && xChroma < 10) { - if(chromaSpeed > 0) { - if(y > -5 && y <= 69) { - clickedComponent = 3; - } - } else if(mouseY > this.y+5+27 && mouseY < this.y+5+37) { - int currentColour = ChromaColour.specialToSimpleRGB(colour); - Color c = new Color(currentColour, true); - colour = ChromaColour.special(200, c.getAlpha(), currentColour); - colourChangedCallback.accept(colour); - } - } - } else { - hexField.unfocus(); - closeCallback.run(); - return false; - } - } - if(Mouse.isButtonDown(0) && clickedComponent >= 0) { - int currentColour = ChromaColour.specialToSimpleRGB(colour); - Color c = new Color(currentColour, true); - float[] hsv = Color.RGBtoHSB(c.getRed(), c.getGreen(), c.getBlue(), null); - - float xWheel = mouseXF - x - 5; - float yWheel = mouseYF - y - 5; - - if(clickedComponent == 0) { - float angle = (float) Math.toDegrees(Math.atan((32-xWheel)/(yWheel-32+1E-5))+Math.PI/2); - xWheel = Math.max(0, Math.min(64, xWheel)); - yWheel = Math.max(0, Math.min(64, yWheel)); - float radius = (float) Math.sqrt(((xWheel-32)*(xWheel-32)+(yWheel-32)*(yWheel-32))/1024f); - if(yWheel < 32) angle += 180; - - this.wheelAngle = angle; - this.wheelRadius = (float)Math.pow(Math.min(1, radius), 1.5f); - int rgb = Color.getHSBColor(angle/360f, wheelRadius, hsv[2]).getRGB(); - colour = ChromaColour.special(ChromaColour.getSpeed(colour), c.getAlpha(), rgb); - colourChangedCallback.accept(colour); - return true; - } - - float y = mouseYF - this.y - 5; - y = Math.max(0, Math.min(64, y)); - System.out.println(y); - - if(clickedComponent == 1) { - int rgb = Color.getHSBColor(wheelAngle/360, wheelRadius, 1-y/64f).getRGB(); - colour = ChromaColour.special(ChromaColour.getSpeed(colour), c.getAlpha(), rgb); - colourChangedCallback.accept(colour); - return true; - } - - if(clickedComponent == 2) { - colour = ChromaColour.special(ChromaColour.getSpeed(colour), - 255-Math.round(y/64f*255), currentColour); - colourChangedCallback.accept(colour); - return true; - } - - if(clickedComponent == 3) { - colour = ChromaColour.special(255-Math.round(y/64f*255), c.getAlpha(), currentColour); - colourChangedCallback.accept(colour); - } - return true; - } - return false; - } - - public boolean keyboardInput() { - if(Keyboard.getEventKeyState() && hexField.getFocus()) { - if (Keyboard.getEventKey() == Keyboard.KEY_ESCAPE) { - hexField.unfocus(); - return true; - } - String old = hexField.getText(); - - hexField.keyTyped(Keyboard.getEventCharacter(), Keyboard.getEventKey()); - - if(hexField.getText().length() > 6) { - hexField.setText(old); - } else { - try { - String text = hexField.getText().toLowerCase(); - - int rgb = Integer.parseInt(text, 16); - int alpha = (ChromaColour.specialToSimpleRGB(colour) >> 24) & 0xFF; - colour = ChromaColour.special(ChromaColour.getSpeed(colour), alpha, rgb); - colourChangedCallback.accept(colour); - - Color c = new Color(rgb); - float[] hsv = Color.RGBtoHSB(c.getRed(), c.getGreen(), c.getBlue(), null); - updateAngleAndRadius(hsv); - } catch(Exception e) {}; - } - - return true; - } - return false; - } - - + public static final ResourceLocation colour_selector_dot = new ResourceLocation( + "notenoughupdates:core/colour_selector_dot.png"); + public static final ResourceLocation colour_selector_bar = new ResourceLocation( + "notenoughupdates:core/colour_selector_bar.png"); + public static final ResourceLocation colour_selector_bar_alpha = new ResourceLocation( + "notenoughupdates:core/colour_selector_bar_alpha.png"); + public static final ResourceLocation colour_selector_chroma = new ResourceLocation( + "notenoughupdates:core/colour_selector_chroma.png"); + + private static final ResourceLocation colourPickerLocation = new ResourceLocation("mbcore:dynamic/colourpicker"); + private static final ResourceLocation colourPickerBarValueLocation = new ResourceLocation( + "mbcore:dynamic/colourpickervalue"); + private static final ResourceLocation colourPickerBarOpacityLocation = new ResourceLocation( + "mbcore:dynamic/colourpickeropacity"); + private final GuiElementTextField hexField = new GuiElementTextField( + "", + GuiElementTextField.SCALE_TEXT | GuiElementTextField.FORCE_CAPS | GuiElementTextField.NO_SPACE + ); + + private final int x; + private final int y; + private int xSize = 119; + private final int ySize = 89; + + private float wheelAngle = 0; + private float wheelRadius = 0; + + private int clickedComponent = -1; + + private final Consumer colourChangedCallback; + private final Runnable closeCallback; + private String colour; + + private final boolean opacitySlider; + private final boolean valueSlider; + + public GuiElementColour( + int x, int y, String initialColour, Consumer colourChangedCallback, + Runnable closeCallback + ) { + this(x, y, initialColour, colourChangedCallback, closeCallback, true, true); + } + + public GuiElementColour( + int x, int y, String initialColour, Consumer colourChangedCallback, + Runnable closeCallback, boolean opacitySlider, boolean valueSlider + ) { + final ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + + this.y = Math.max(10, Math.min(scaledResolution.getScaledHeight() - ySize - 10, y)); + this.x = Math.max(10, Math.min(scaledResolution.getScaledWidth() - xSize - 10, x)); + + this.colour = initialColour; + this.colourChangedCallback = colourChangedCallback; + this.closeCallback = closeCallback; + + int colour = ChromaColour.specialToSimpleRGB(initialColour); + Color c = new Color(colour); + float[] hsv = Color.RGBtoHSB(c.getRed(), c.getGreen(), c.getBlue(), null); + updateAngleAndRadius(hsv); + + this.opacitySlider = opacitySlider; + this.valueSlider = valueSlider; + + if (!valueSlider) xSize -= 15; + if (!opacitySlider) xSize -= 15; + } + + public void updateAngleAndRadius(float[] hsv) { + this.wheelRadius = hsv[1]; + this.wheelAngle = hsv[0] * 360; + } + + public void render() { + RenderUtils.drawFloatingRectDark(x, y, xSize, ySize); + + int currentColour = ChromaColour.specialToSimpleRGB(colour); + Color c = new Color(currentColour, true); + float[] hsv = Color.RGBtoHSB(c.getRed(), c.getGreen(), c.getBlue(), null); + + BufferedImage bufferedImage = new BufferedImage(288, 288, BufferedImage.TYPE_INT_ARGB); + float borderRadius = 0.05f; + if (Keyboard.isKeyDown(Keyboard.KEY_N)) borderRadius = 0; + for (int x = -16; x < 272; x++) { + for (int y = -16; y < 272; y++) { + float radius = (float) Math.sqrt(((x - 128) * (x - 128) + (y - 128) * (y - 128)) / 16384f); + float angle = (float) Math.toDegrees(Math.atan((128 - x) / (y - 128 + 1E-5)) + Math.PI / 2); + if (y < 128) angle += 180; + if (radius <= 1) { + int rgb = Color.getHSBColor(angle / 360f, (float) Math.pow(radius, 1.5f), hsv[2]).getRGB(); + bufferedImage.setRGB(x + 16, y + 16, rgb); + } else if (radius <= 1 + borderRadius) { + float invBlackAlpha = Math.abs(radius - 1 - borderRadius / 2) / borderRadius * 2; + float blackAlpha = 1 - invBlackAlpha; + + if (radius > 1 + borderRadius / 2) { + bufferedImage.setRGB(x + 16, y + 16, (int) (blackAlpha * 255) << 24); + } else { + Color col = Color.getHSBColor(angle / 360f, 1, hsv[2]); + int rgb = (int) (col.getRed() * invBlackAlpha) << 16 | + (int) (col.getGreen() * invBlackAlpha) << 8 | + (int) (col.getBlue() * invBlackAlpha); + bufferedImage.setRGB(x + 16, y + 16, 0xff000000 | rgb); + } + + } + } + } + + BufferedImage bufferedImageValue = new BufferedImage(10, 64, BufferedImage.TYPE_INT_ARGB); + for (int x = 0; x < 10; x++) { + for (int y = 0; y < 64; y++) { + if ((x == 0 || x == 9) && (y == 0 || y == 63)) continue; + + int rgb = Color.getHSBColor(wheelAngle / 360, wheelRadius, (64 - y) / 64f).getRGB(); + bufferedImageValue.setRGB(x, y, rgb); + } + } + + BufferedImage bufferedImageOpacity = new BufferedImage(10, 64, BufferedImage.TYPE_INT_ARGB); + for (int x = 0; x < 10; x++) { + for (int y = 0; y < 64; y++) { + if ((x == 0 || x == 9) && (y == 0 || y == 63)) continue; + + int rgb = (currentColour & 0x00FFFFFF) | (Math.min(255, (64 - y) * 4) << 24); + bufferedImageOpacity.setRGB(x, y, rgb); + } + } + + float selradius = (float) Math.pow(wheelRadius, 1 / 1.5f) * 32; + int selx = (int) (Math.cos(Math.toRadians(wheelAngle)) * selradius); + int sely = (int) (Math.sin(Math.toRadians(wheelAngle)) * selradius); + + int valueOffset = 0; + if (valueSlider) { + valueOffset = 15; + + Minecraft.getMinecraft().getTextureManager().loadTexture( + colourPickerBarValueLocation, + new DynamicTexture(bufferedImageValue) + ); + Minecraft.getMinecraft().getTextureManager().bindTexture(colourPickerBarValueLocation); + GlStateManager.color(1, 1, 1, 1); + RenderUtils.drawTexturedRect(x + 5 + 64 + 5, y + 5, 10, 64, GL11.GL_NEAREST); + } + + int opacityOffset = 0; + if (opacitySlider) { + opacityOffset = 15; + + Minecraft.getMinecraft().getTextureManager().bindTexture(colour_selector_bar_alpha); + GlStateManager.color(1, 1, 1, 1); + RenderUtils.drawTexturedRect(x + 5 + 64 + 5 + valueOffset, y + 5, 10, 64, GL11.GL_NEAREST); + + Minecraft.getMinecraft().getTextureManager().loadTexture( + colourPickerBarOpacityLocation, + new DynamicTexture(bufferedImageOpacity) + ); + Minecraft.getMinecraft().getTextureManager().bindTexture(colourPickerBarOpacityLocation); + GlStateManager.color(1, 1, 1, 1); + RenderUtils.drawTexturedRect(x + 5 + 64 + 5 + valueOffset, y + 5, 10, 64, GL11.GL_NEAREST); + } + + int chromaSpeed = ChromaColour.getSpeed(colour); + int currentColourChroma = ChromaColour.specialToChromaRGB(colour); + Color cChroma = new Color(currentColourChroma, true); + float[] hsvChroma = Color.RGBtoHSB(cChroma.getRed(), cChroma.getGreen(), cChroma.getBlue(), null); + + if (chromaSpeed > 0) { + Gui.drawRect(x + 5 + 64 + valueOffset + opacityOffset + 5 + 1, y + 5 + 1, + x + 5 + 64 + valueOffset + opacityOffset + 5 + 10 - 1, y + 5 + 64 - 1, + Color.HSBtoRGB(hsvChroma[0], 0.8f, 0.8f) + ); + } else { + Gui.drawRect(x + 5 + 64 + valueOffset + opacityOffset + 5 + 1, y + 5 + 27 + 1, + x + 5 + 64 + valueOffset + opacityOffset + 5 + 10 - 1, y + 5 + 37 - 1, + Color.HSBtoRGB((hsvChroma[0] + (System.currentTimeMillis() - ChromaColour.startTime) / 1000f) % 1, 0.8f, 0.8f) + ); + } + + Minecraft.getMinecraft().getTextureManager().bindTexture(colour_selector_bar); + GlStateManager.color(1, 1, 1, 1); + if (valueSlider) RenderUtils.drawTexturedRect(x + 5 + 64 + 5, y + 5, 10, 64, GL11.GL_NEAREST); + if (opacitySlider) RenderUtils.drawTexturedRect(x + 5 + 64 + 5 + valueOffset, y + 5, 10, 64, GL11.GL_NEAREST); + + if (chromaSpeed > 0) { + RenderUtils.drawTexturedRect(x + 5 + 64 + valueOffset + opacityOffset + 5, y + 5, 10, 64, GL11.GL_NEAREST); + } else { + Minecraft.getMinecraft().getTextureManager().bindTexture(colour_selector_chroma); + RenderUtils.drawTexturedRect(x + 5 + 64 + valueOffset + opacityOffset + 5, y + 5 + 27, 10, 10, GL11.GL_NEAREST); + } + + if (valueSlider) Gui.drawRect(x + 5 + 64 + 5, y + 5 + 64 - (int) (64 * hsv[2]), + x + 5 + 64 + valueOffset, y + 5 + 64 - (int) (64 * hsv[2]) + 1, 0xFF000000 + ); + if (opacitySlider) Gui.drawRect(x + 5 + 64 + 5 + valueOffset, y + 5 + 64 - c.getAlpha() / 4, + x + 5 + 64 + valueOffset + opacityOffset, y + 5 + 64 - c.getAlpha() / 4 - 1, 0xFF000000 + ); + if (chromaSpeed > 0) { + Gui.drawRect(x + 5 + 64 + valueOffset + opacityOffset + 5, + y + 5 + 64 - (int) (chromaSpeed / 255f * 64), + x + 5 + 64 + valueOffset + opacityOffset + 5 + 10, + y + 5 + 64 - (int) (chromaSpeed / 255f * 64) + 1, 0xFF000000 + ); + } + + Minecraft.getMinecraft().getTextureManager().loadTexture(colourPickerLocation, new DynamicTexture(bufferedImage)); + Minecraft.getMinecraft().getTextureManager().bindTexture(colourPickerLocation); + GlStateManager.color(1, 1, 1, 1); + RenderUtils.drawTexturedRect(x + 1, y + 1, 72, 72, GL11.GL_LINEAR); + + Minecraft.getMinecraft().getTextureManager().bindTexture(colour_selector_dot); + GlStateManager.color(1, 1, 1, 1); + RenderUtils.drawTexturedRect(x + 5 + 32 + selx - 4, y + 5 + 32 + sely - 4, 8, 8, GL11.GL_NEAREST); + + TextRenderUtils.drawStringCenteredScaledMaxWidth(EnumChatFormatting.GRAY.toString() + Math.round(hsv[2] * 100) + "", + Minecraft.getMinecraft().fontRendererObj, + x + 5 + 64 + 5 + 5 - (Math.round(hsv[2] * 100) == 100 ? 1 : 0), y + 5 + 64 + 5 + 5, true, 13, -1 + ); + if (opacitySlider) { + TextRenderUtils.drawStringCenteredScaledMaxWidth( + EnumChatFormatting.GRAY.toString() + Math.round(c.getAlpha() / 255f * 100) + "", + Minecraft.getMinecraft().fontRendererObj, + x + 5 + 64 + 5 + valueOffset + 5, + y + 5 + 64 + 5 + 5, + true, + 13, + -1 + ); + } + if (chromaSpeed > 0) { + TextRenderUtils.drawStringCenteredScaledMaxWidth(EnumChatFormatting.GRAY.toString() + + (int) ChromaColour.getSecondsForSpeed(chromaSpeed) + "s", + Minecraft.getMinecraft().fontRendererObj, + x + 5 + 64 + 5 + valueOffset + opacityOffset + 6, y + 5 + 64 + 5 + 5, true, 13, -1 + ); + } + + hexField.setSize(48, 10); + if (!hexField.getFocus()) hexField.setText(Integer.toHexString(c.getRGB() & 0xFFFFFF).toUpperCase()); + + StringBuilder sb = new StringBuilder(EnumChatFormatting.GRAY + "#"); + for (int i = 0; i < 6 - hexField.getText().length(); i++) { + sb.append("0"); + } + sb.append(EnumChatFormatting.WHITE); + + hexField.setPrependText(sb.toString()); + hexField.render(x + 5 + 8, y + 5 + 64 + 5); + } + + public boolean mouseInput(int mouseX, int mouseY) { + ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + float mouseXF = (float) (Mouse.getX() * scaledResolution.getScaledWidth_double() / + Minecraft.getMinecraft().displayWidth); + float mouseYF = (float) (scaledResolution.getScaledHeight_double() - Mouse.getY() * + scaledResolution.getScaledHeight_double() / Minecraft.getMinecraft().displayHeight - 1); + + if ((Mouse.getEventButton() == 0 || Mouse.getEventButton() == 1) && Mouse.getEventButtonState()) { + if (mouseX > x + 5 + 8 && mouseX < x + 5 + 8 + 48) { + if (mouseY > y + 5 + 64 + 5 && mouseY < y + 5 + 64 + 5 + 10) { + hexField.mouseClicked(mouseX, mouseY, Mouse.getEventButton()); + clickedComponent = -1; + return true; + } + } + } + if (!Mouse.getEventButtonState() && Mouse.getEventButton() == 0) { + clickedComponent = -1; + } + if (Mouse.getEventButtonState() && Mouse.getEventButton() == 0) { + if (mouseX >= x && mouseX <= x + 119 && + mouseY >= y && mouseY <= y + 89) { + hexField.unfocus(); + + int xWheel = mouseX - x - 5; + int yWheel = mouseY - y - 5; + + if (xWheel > 0 && xWheel < 64) { + if (yWheel > 0 && yWheel < 64) { + clickedComponent = 0; + } + } + + int xValue = mouseX - (x + 5 + 64 + 5); + int y = mouseY - this.y - 5; + + int opacityOffset = opacitySlider ? 15 : 0; + int valueOffset = valueSlider ? 15 : 0; + + if (y > -5 && y <= 69) { + if (valueSlider) { + if (xValue > 0 && xValue < 10) { + clickedComponent = 1; + } + } + + if (opacitySlider) { + int xOpacity = mouseX - (x + 5 + 64 + 5 + valueOffset); + + if (xOpacity > 0 && xOpacity < 10) { + clickedComponent = 2; + } + } + } + + int chromaSpeed = ChromaColour.getSpeed(colour); + int xChroma = mouseX - (x + 5 + 64 + valueOffset + opacityOffset + 5); + if (xChroma > 0 && xChroma < 10) { + if (chromaSpeed > 0) { + if (y > -5 && y <= 69) { + clickedComponent = 3; + } + } else if (mouseY > this.y + 5 + 27 && mouseY < this.y + 5 + 37) { + int currentColour = ChromaColour.specialToSimpleRGB(colour); + Color c = new Color(currentColour, true); + colour = ChromaColour.special(200, c.getAlpha(), currentColour); + colourChangedCallback.accept(colour); + } + } + } else { + hexField.unfocus(); + closeCallback.run(); + return false; + } + } + if (Mouse.isButtonDown(0) && clickedComponent >= 0) { + int currentColour = ChromaColour.specialToSimpleRGB(colour); + Color c = new Color(currentColour, true); + float[] hsv = Color.RGBtoHSB(c.getRed(), c.getGreen(), c.getBlue(), null); + + float xWheel = mouseXF - x - 5; + float yWheel = mouseYF - y - 5; + + if (clickedComponent == 0) { + float angle = (float) Math.toDegrees(Math.atan((32 - xWheel) / (yWheel - 32 + 1E-5)) + Math.PI / 2); + xWheel = Math.max(0, Math.min(64, xWheel)); + yWheel = Math.max(0, Math.min(64, yWheel)); + float radius = (float) Math.sqrt(((xWheel - 32) * (xWheel - 32) + (yWheel - 32) * (yWheel - 32)) / 1024f); + if (yWheel < 32) angle += 180; + + this.wheelAngle = angle; + this.wheelRadius = (float) Math.pow(Math.min(1, radius), 1.5f); + int rgb = Color.getHSBColor(angle / 360f, wheelRadius, hsv[2]).getRGB(); + colour = ChromaColour.special(ChromaColour.getSpeed(colour), c.getAlpha(), rgb); + colourChangedCallback.accept(colour); + return true; + } + + float y = mouseYF - this.y - 5; + y = Math.max(0, Math.min(64, y)); + System.out.println(y); + + if (clickedComponent == 1) { + int rgb = Color.getHSBColor(wheelAngle / 360, wheelRadius, 1 - y / 64f).getRGB(); + colour = ChromaColour.special(ChromaColour.getSpeed(colour), c.getAlpha(), rgb); + colourChangedCallback.accept(colour); + return true; + } + + if (clickedComponent == 2) { + colour = ChromaColour.special(ChromaColour.getSpeed(colour), + 255 - Math.round(y / 64f * 255), currentColour + ); + colourChangedCallback.accept(colour); + return true; + } + + if (clickedComponent == 3) { + colour = ChromaColour.special(255 - Math.round(y / 64f * 255), c.getAlpha(), currentColour); + colourChangedCallback.accept(colour); + } + return true; + } + return false; + } + + public boolean keyboardInput() { + if (Keyboard.getEventKeyState() && hexField.getFocus()) { + if (Keyboard.getEventKey() == Keyboard.KEY_ESCAPE) { + hexField.unfocus(); + return true; + } + String old = hexField.getText(); + + hexField.keyTyped(Keyboard.getEventCharacter(), Keyboard.getEventKey()); + + if (hexField.getText().length() > 6) { + hexField.setText(old); + } else { + try { + String text = hexField.getText().toLowerCase(); + + int rgb = Integer.parseInt(text, 16); + int alpha = (ChromaColour.specialToSimpleRGB(colour) >> 24) & 0xFF; + colour = ChromaColour.special(ChromaColour.getSpeed(colour), alpha, rgb); + colourChangedCallback.accept(colour); + + Color c = new Color(rgb); + float[] hsv = Color.RGBtoHSB(c.getRed(), c.getGreen(), c.getBlue(), null); + updateAngleAndRadius(hsv); + } catch (Exception ignored) { + } + } + + return true; + } + return false; + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementTextField.java b/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementTextField.java index d221b37eb9..51a4654c3c 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementTextField.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementTextField.java @@ -15,569 +15,601 @@ import java.util.regex.Pattern; public class GuiElementTextField { - - public static final int SCISSOR_TEXT = 0b10000000; - public static final int DISABLE_BG = 0b1000000; - public static final int SCALE_TEXT = 0b100000; - public static final int NUM_ONLY = 0b10000; - public static final int NO_SPACE = 0b01000; - public static final int FORCE_CAPS = 0b00100; - public static final int COLOUR = 0b00010; - public static final int MULTILINE = 0b00001; - - private int searchBarYSize; - private int searchBarXSize; - private static final int searchBarPadding = 2; - - private int options; - - private boolean focus = false; - - private int x; - private int y; - - private String prependText = ""; - private int customTextColour = 0xffffffff; - - private final GuiTextField textField = new GuiTextField(0, Minecraft.getMinecraft().fontRendererObj, - 0 , 0, 0, 0); - - private int customBorderColour = -1; - - public GuiElementTextField(String initialText, int options) { - this(initialText, 100, 20, options); - } - - public GuiElementTextField(String initialText, int sizeX, int sizeY, int options) { - textField.setFocused(true); - textField.setCanLoseFocus(false); - textField.setMaxStringLength(999); - textField.setText(initialText); - this.searchBarXSize = sizeX; - this.searchBarYSize = sizeY; - this.options = options; - } - - public void setMaxStringLength(int len) { - textField.setMaxStringLength(len); - } - - public void setCustomBorderColour(int colour) { - this.customBorderColour = colour; - } - - public void setCustomTextColour(int colour) { - this.customTextColour = colour; - } - - public String getText() { - return textField.getText(); - } - - public String getTextDisplay() { - String textNoColour = getText(); - while(true) { - Matcher matcher = PATTERN_CONTROL_CODE.matcher(textNoColour); - if(!matcher.find()) break; - String code = matcher.group(1); - textNoColour = matcher.replaceFirst("\u00B6"+code); - } - - return textNoColour; - } - - public void setPrependText(String text) { - this.prependText = text; - } - - public void setText(String text) { - if(textField.getText() == null || !textField.getText().equals(text)) { - textField.setText(text); - } - } - - public void setSize(int searchBarXSize, int searchBarYSize) { - this.searchBarXSize = searchBarXSize; - this.searchBarYSize = searchBarYSize; - } - - public void setOptions(int options) { - this.options = options; - } - - @Override - public String toString() { - return textField.getText(); - } - - public void setFocus(boolean focus) { - this.focus = focus; - if(!focus) { - textField.setCursorPosition(textField.getCursorPosition()); - } - } - public boolean getFocus() { - return focus; - } - - public int getHeight() { - ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft()); - int paddingUnscaled = searchBarPadding/scaledresolution.getScaleFactor(); - - int numLines = org.apache.commons.lang3.StringUtils.countMatches(textField.getText(), "\n")+1; - int extraSize = (searchBarYSize-8)/2+8; - int bottomTextBox = searchBarYSize + extraSize*(numLines-1); - - return bottomTextBox + paddingUnscaled*2; - } - - public int getWidth() { - ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft()); - int paddingUnscaled = searchBarPadding/scaledresolution.getScaleFactor(); - - return searchBarXSize + paddingUnscaled*2; - } - - private float getScaleFactor(String str) { - return Math.min(1, (searchBarXSize-2)/(float)Minecraft.getMinecraft().fontRendererObj.getStringWidth(str)); - } - - private boolean isScaling() { - return (options & SCALE_TEXT) != 0; - } - - private static final Pattern PATTERN_CONTROL_CODE = Pattern.compile("(?i)\\u00A7([^\\u00B6]|$)(?!\\u00B6)"); - - public int getCursorPos(int mouseX, int mouseY) { - int xComp = mouseX - x; - int yComp = mouseY - y; - - int extraSize = (searchBarYSize-8)/2+8; - - String renderText = prependText + textField.getText(); - - int lineNum = Math.round(((yComp - (searchBarYSize-8)/2))/extraSize); - - String text = renderText; - String textNoColour = renderText; - if((options & COLOUR) != 0) { - while(true) { - Matcher matcher = PATTERN_CONTROL_CODE.matcher(text); - if(!matcher.find() || matcher.groupCount() < 1) break; - String code = matcher.group(1); - if(code.isEmpty()) { - text = matcher.replaceFirst("\u00A7r\u00B6"); - } else { - text = matcher.replaceFirst("\u00A7"+code+"\u00B6"+code); - } - } - } - while(true) { - Matcher matcher = PATTERN_CONTROL_CODE.matcher(textNoColour); - if(!matcher.find() || matcher.groupCount() < 1) break; - String code = matcher.group(1); - textNoColour = matcher.replaceFirst("\u00B6"+code); - } - - int currentLine = 0; - int cursorIndex = 0; - for(; cursorIndex 0) { - textBeforeCursorWidth = 0; - lineBefore = split[split.length-1]; - thisLineBeforeCursor = ""; - } else if(split.length > 1) { - thisLineBeforeCursor = split[split.length-1]; - lineBefore = split[split.length-2]; - textBeforeCursorWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth(thisLineBeforeCursor); - } else { - return; - } - String trimmed = Minecraft.getMinecraft().fontRendererObj - .trimStringToWidth(lineBefore, textBeforeCursorWidth); - int linePos = strLenNoColor(trimmed); - if(linePos != strLenNoColor(lineBefore)) { - char after = lineBefore.charAt(linePos); - int trimmedWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth(trimmed); - int charWidth = Minecraft.getMinecraft().fontRendererObj.getCharWidth(after); - if(trimmedWidth + charWidth/2 < textBeforeCursorWidth) { - linePos++; - } - } - int newPos = textField.getSelectionEnd()-strLenNoColor(thisLineBeforeCursor) - -strLenNoColor(lineBefore)-1+linePos; - - if(GuiScreen.isShiftKeyDown()) { - textField.setSelectionPos(newPos); - } else { - textField.setCursorPosition(newPos); - } - } else if(keyCode == 208) { //Down - String textNCBeforeCursor = textNoColour.substring(0, textField.getSelectionEnd()); - int colorCodes = org.apache.commons.lang3.StringUtils.countMatches(textNCBeforeCursor, "\u00B6"); - String textBeforeCursor = text.substring(0, textField.getSelectionEnd()+colorCodes*2); - - int numLinesBeforeCursor = org.apache.commons.lang3.StringUtils.countMatches(textBeforeCursor, "\n"); - - String[] split = textBeforeCursor.split("\n"); - String thisLineBeforeCursor; - int textBeforeCursorWidth; - if(split.length == numLinesBeforeCursor) { - thisLineBeforeCursor = ""; - textBeforeCursorWidth = 0; - } else if(split.length > 0) { - thisLineBeforeCursor = split[split.length-1]; - textBeforeCursorWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth(thisLineBeforeCursor); - } else { - return; - } - - String[] split2 = textNoColour.split("\n"); - if(split2.length > numLinesBeforeCursor+1) { - String lineAfter = split2[numLinesBeforeCursor+1]; - String trimmed = Minecraft.getMinecraft().fontRendererObj - .trimStringToWidth(lineAfter, textBeforeCursorWidth); - int linePos = strLenNoColor(trimmed); - if(linePos != strLenNoColor(lineAfter)) { - char after = lineAfter.charAt(linePos); - int trimmedWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth(trimmed); - int charWidth = Minecraft.getMinecraft().fontRendererObj.getCharWidth(after); - if(trimmedWidth + charWidth/2 < textBeforeCursorWidth) { - linePos++; - } - } - int newPos = textField.getSelectionEnd()-strLenNoColor(thisLineBeforeCursor) - +strLenNoColor(split2[numLinesBeforeCursor])+1+linePos; - - if(GuiScreen.isShiftKeyDown()) { - textField.setSelectionPos(newPos); - } else { - textField.setCursorPosition(newPos); - } - } - } - } - - String old = textField.getText(); - if((options & FORCE_CAPS) != 0) typedChar = Character.toUpperCase(typedChar); - if((options & NO_SPACE) != 0 && typedChar == ' ') return; - - if(typedChar == '\u00B6') { - typedChar = '\u00A7'; - } - - textField.setFocused(true); - textField.textboxKeyTyped(typedChar, keyCode); - - if((options & COLOUR) != 0) { - if(typedChar == '&') { - int pos = textField.getCursorPosition()-2; - if(pos >= 0 && pos < textField.getText().length()) { - if(textField.getText().charAt(pos) == '&') { - String before = textField.getText().substring(0, pos); - String after = ""; - if(pos+2 < textField.getText().length()) { - after = textField.getText().substring(pos+2); - } - textField.setText(before + "\u00A7" + after); - textField.setCursorPosition(pos+1); - } - } - } else if(typedChar == '*') { - int pos = textField.getCursorPosition()-2; - if(pos >= 0 && pos < textField.getText().length()) { - if(textField.getText().charAt(pos) == '*') { - String before = textField.getText().substring(0, pos); - String after = ""; - if(pos+2 < textField.getText().length()) { - after = textField.getText().substring(pos+2); - } - textField.setText(before + "\u272A" + after); - textField.setCursorPosition(pos+1); - } - } - } - } - - if((options & NUM_ONLY) != 0 && textField.getText().matches("[^0-9.]")) textField.setText(old); - } - } - - public void render(int x, int y) { - this.x = x; - this.y = y; - drawTextbox(x, y, searchBarXSize, searchBarYSize, searchBarPadding, textField, focus); - } - - private void drawTextbox(int x, int y, int searchBarXSize, int searchBarYSize, int searchBarPadding, - GuiTextField textField, boolean focus) { - ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft()); - String renderText = prependText + textField.getText(); - - GlStateManager.disableLighting(); - - /** - * Search bar - */ - int paddingUnscaled = searchBarPadding/scaledresolution.getScaleFactor(); - if(paddingUnscaled < 1) paddingUnscaled = 1; - - int numLines = org.apache.commons.lang3.StringUtils.countMatches(renderText, "\n")+1; - int extraSize = (searchBarYSize-8)/2+8; - int bottomTextBox = y + searchBarYSize + extraSize*(numLines-1); - - int borderColour = focus ? Color.GREEN.getRGB() : Color.WHITE.getRGB(); - if(customBorderColour != -1) { - borderColour = customBorderColour; - } - if((options & DISABLE_BG) == 0) { - //bar background - Gui.drawRect(x - paddingUnscaled, - y - paddingUnscaled, - x + searchBarXSize + paddingUnscaled, - bottomTextBox + paddingUnscaled, borderColour); - Gui.drawRect(x, - y, - x + searchBarXSize, - bottomTextBox, Color.BLACK.getRGB()); - } - - //bar text - String text = renderText; - String textNoColor = renderText; - if((options & COLOUR) != 0) { - while(true) { - Matcher matcher = PATTERN_CONTROL_CODE.matcher(text); - if(!matcher.find() || matcher.groupCount() < 1) break; - String code = matcher.group(1); - if(code.isEmpty()) { - text = matcher.replaceFirst("\u00A7r\u00B6"); - } else { - text = matcher.replaceFirst("\u00A7"+code+"\u00B6"+code); - } - } - } - while(true) { - Matcher matcher = PATTERN_CONTROL_CODE.matcher(textNoColor); - if(!matcher.find() || matcher.groupCount() < 1) break; - String code = matcher.group(1); - textNoColor = matcher.replaceFirst("\u00B6"+code); - } - - int xStartOffset = 5; - float scale = 1; - String[] texts = text.split("\n"); - for(int yOffI = 0; yOffI < texts.length; yOffI++) { - int yOff = yOffI*extraSize; - - if(isScaling() && Minecraft.getMinecraft().fontRendererObj.getStringWidth(texts[yOffI])>searchBarXSize-10) { - scale = (searchBarXSize-2)/(float)Minecraft.getMinecraft().fontRendererObj.getStringWidth(texts[yOffI]); - if(scale > 1) scale=1; - float newLen = Minecraft.getMinecraft().fontRendererObj.getStringWidth(texts[yOffI])*scale; - xStartOffset = (int)((searchBarXSize-newLen)/2f); - - TextRenderUtils.drawStringCenteredScaledMaxWidth(Utils.chromaStringByColourCode(texts[yOffI]), Minecraft.getMinecraft().fontRendererObj, x+searchBarXSize/2f, - y+searchBarYSize/2f+yOff, false, - searchBarXSize-2, customTextColour); - } else { - if((options & SCISSOR_TEXT) != 0) { - GlScissorStack.push(x+5, 0, x+searchBarXSize, scaledresolution.getScaledHeight(), scaledresolution); - Minecraft.getMinecraft().fontRendererObj.drawString(Utils.chromaStringByColourCode(texts[yOffI]), x + 5, - y+(searchBarYSize-8)/2+yOff, customTextColour); - GlScissorStack.pop(scaledresolution); - } else { - String toRender = Minecraft.getMinecraft().fontRendererObj.trimStringToWidth(Utils.chromaStringByColourCode(texts[yOffI]), searchBarXSize-10); - Minecraft.getMinecraft().fontRendererObj.drawString(toRender, x + 5, - y+(searchBarYSize-8)/2+yOff, customTextColour); - } - - } - } - - if(focus && System.currentTimeMillis()%1000>500) { - String textNCBeforeCursor = textNoColor.substring(0, textField.getCursorPosition()+prependText.length()); - int colorCodes = org.apache.commons.lang3.StringUtils.countMatches(textNCBeforeCursor, "\u00B6"); - String textBeforeCursor = text.substring(0, Math.min(text.length(), textField.getCursorPosition()+prependText.length()+(((options & COLOUR) != 0) ? colorCodes*2 : 0))); - - int numLinesBeforeCursor = org.apache.commons.lang3.StringUtils.countMatches(textBeforeCursor, "\n"); - int yOff = numLinesBeforeCursor*extraSize; - - String[] split = textBeforeCursor.split("\n"); - int textBeforeCursorWidth; - if(split.length <= numLinesBeforeCursor || split.length == 0) { - textBeforeCursorWidth = 0; - } else { - textBeforeCursorWidth = (int)(Minecraft.getMinecraft().fontRendererObj.getStringWidth(split[split.length-1])*scale); - } - Gui.drawRect(x + xStartOffset + textBeforeCursorWidth, - y+(searchBarYSize-8)/2-1 + yOff, - x + xStartOffset + textBeforeCursorWidth+1, - y+(searchBarYSize-8)/2+9 + yOff, Color.WHITE.getRGB()); - } - - String selectedText = textField.getSelectedText(); - if(!selectedText.isEmpty()) { - int leftIndex = Math.min(textField.getCursorPosition()+prependText.length(), textField.getSelectionEnd()+prependText.length()); - int rightIndex = Math.max(textField.getCursorPosition()+prependText.length(), textField.getSelectionEnd()+prependText.length()); - - float texX = 0; - int texY = 0; - boolean sectionSignPrev = false; - boolean ignoreNext = false; - boolean bold = false; - for(int i=0; i= leftIndex && i < rightIndex) { - Gui.drawRect(x + xStartOffset + (int)texX, - y+(searchBarYSize-8)/2-1 + texY, - x + xStartOffset + (int)texX + 3, - y+(searchBarYSize-8)/2+9 + texY, Color.LIGHT_GRAY.getRGB()); - } - - texX = 0; - texY += extraSize; - continue; - } - - int len = Minecraft.getMinecraft().fontRendererObj.getStringWidth(String.valueOf(c)); - if(bold) len++; - if(i >= leftIndex && i < rightIndex) { - Gui.drawRect(x + xStartOffset + (int)texX, - y+(searchBarYSize-8)/2-1 + texY, - x + xStartOffset + (int)(texX + len*scale), - y+(searchBarYSize-8)/2+9 + texY, Color.LIGHT_GRAY.getRGB()); - - TextRenderUtils.drawStringScaled(String.valueOf(c), Minecraft.getMinecraft().fontRendererObj, - x + xStartOffset + texX, - y+searchBarYSize/2f-scale*8/2f + texY, false, Color.BLACK.getRGB(), scale); - if(bold) { - TextRenderUtils.drawStringScaled(String.valueOf(c), Minecraft.getMinecraft().fontRendererObj, - x + xStartOffset + texX + 1, - y+searchBarYSize/2f-scale*8/2f + texY, false, Color.BLACK.getRGB(), scale); - } - } - - texX += len*scale; - } - } - } + public static final int SCISSOR_TEXT = 0b10000000; + public static final int DISABLE_BG = 0b1000000; + public static final int SCALE_TEXT = 0b100000; + public static final int NUM_ONLY = 0b10000; + public static final int NO_SPACE = 0b01000; + public static final int FORCE_CAPS = 0b00100; + public static final int COLOUR = 0b00010; + public static final int MULTILINE = 0b00001; + + private int searchBarYSize; + private int searchBarXSize; + private static final int searchBarPadding = 2; + + private int options; + + private boolean focus = false; + + private int x; + private int y; + + private String prependText = ""; + private int customTextColour = 0xffffffff; + + private final GuiTextField textField = new GuiTextField(0, Minecraft.getMinecraft().fontRendererObj, + 0, 0, 0, 0 + ); + + private int customBorderColour = -1; + + public GuiElementTextField(String initialText, int options) { + this(initialText, 100, 20, options); + } + + public GuiElementTextField(String initialText, int sizeX, int sizeY, int options) { + textField.setFocused(true); + textField.setCanLoseFocus(false); + textField.setMaxStringLength(999); + textField.setText(initialText); + this.searchBarXSize = sizeX; + this.searchBarYSize = sizeY; + this.options = options; + } + + public void setMaxStringLength(int len) { + textField.setMaxStringLength(len); + } + + public void setCustomBorderColour(int colour) { + this.customBorderColour = colour; + } + + public void setCustomTextColour(int colour) { + this.customTextColour = colour; + } + + public String getText() { + return textField.getText(); + } + + public String getTextDisplay() { + String textNoColour = getText(); + while (true) { + Matcher matcher = PATTERN_CONTROL_CODE.matcher(textNoColour); + if (!matcher.find()) break; + String code = matcher.group(1); + textNoColour = matcher.replaceFirst("\u00B6" + code); + } + + return textNoColour; + } + + public void setPrependText(String text) { + this.prependText = text; + } + + public void setText(String text) { + if (textField.getText() == null || !textField.getText().equals(text)) { + textField.setText(text); + } + } + + public void setSize(int searchBarXSize, int searchBarYSize) { + this.searchBarXSize = searchBarXSize; + this.searchBarYSize = searchBarYSize; + } + + public void setOptions(int options) { + this.options = options; + } + + @Override + public String toString() { + return textField.getText(); + } + + public void setFocus(boolean focus) { + this.focus = focus; + if (!focus) { + textField.setCursorPosition(textField.getCursorPosition()); + } + } + + public boolean getFocus() { + return focus; + } + + public int getHeight() { + ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft()); + int paddingUnscaled = searchBarPadding / scaledresolution.getScaleFactor(); + + int numLines = org.apache.commons.lang3.StringUtils.countMatches(textField.getText(), "\n") + 1; + int extraSize = (searchBarYSize - 8) / 2 + 8; + int bottomTextBox = searchBarYSize + extraSize * (numLines - 1); + + return bottomTextBox + paddingUnscaled * 2; + } + + public int getWidth() { + ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft()); + int paddingUnscaled = searchBarPadding / scaledresolution.getScaleFactor(); + + return searchBarXSize + paddingUnscaled * 2; + } + + private float getScaleFactor(String str) { + return Math.min(1, (searchBarXSize - 2) / (float) Minecraft.getMinecraft().fontRendererObj.getStringWidth(str)); + } + + private boolean isScaling() { + return (options & SCALE_TEXT) != 0; + } + + private static final Pattern PATTERN_CONTROL_CODE = Pattern.compile("(?i)\\u00A7([^\\u00B6]|$)(?!\\u00B6)"); + + public int getCursorPos(int mouseX, int mouseY) { + int xComp = mouseX - x; + int yComp = mouseY - y; + + int extraSize = (searchBarYSize - 8) / 2 + 8; + + String renderText = prependText + textField.getText(); + + int lineNum = Math.round(((yComp - (searchBarYSize - 8) / 2)) / extraSize); + + String text = renderText; + String textNoColour = renderText; + if ((options & COLOUR) != 0) { + while (true) { + Matcher matcher = PATTERN_CONTROL_CODE.matcher(text); + if (!matcher.find() || matcher.groupCount() < 1) break; + String code = matcher.group(1); + if (code.isEmpty()) { + text = matcher.replaceFirst("\u00A7r\u00B6"); + } else { + text = matcher.replaceFirst("\u00A7" + code + "\u00B6" + code); + } + } + } + while (true) { + Matcher matcher = PATTERN_CONTROL_CODE.matcher(textNoColour); + if (!matcher.find() || matcher.groupCount() < 1) break; + String code = matcher.group(1); + textNoColour = matcher.replaceFirst("\u00B6" + code); + } + + int currentLine = 0; + int cursorIndex = 0; + for (; cursorIndex < textNoColour.length(); cursorIndex++) { + if (currentLine == lineNum) break; + if (textNoColour.charAt(cursorIndex) == '\n') { + currentLine++; + } + } + + String textNC = textNoColour.substring(0, cursorIndex); + int colorCodes = org.apache.commons.lang3.StringUtils.countMatches(textNC, "\u00B6"); + String line = text.substring(cursorIndex + (((options & COLOUR) != 0) ? colorCodes * 2 : 0)).split("\n")[0]; + int padding = Math.min(5, searchBarXSize - strLenNoColor(line)) / 2; + String trimmed = Minecraft.getMinecraft().fontRendererObj.trimStringToWidth(line, xComp - padding); + int linePos = strLenNoColor(trimmed); + if (linePos != strLenNoColor(line)) { + char after = line.charAt(linePos); + int trimmedWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth(trimmed); + int charWidth = Minecraft.getMinecraft().fontRendererObj.getCharWidth(after); + if (trimmedWidth + charWidth / 2 < xComp - padding) { + linePos++; + } + } + cursorIndex += linePos; + + int pre = StringUtils.cleanColour(prependText).length(); + if (cursorIndex < pre) { + cursorIndex = 0; + } else { + cursorIndex -= pre; + } + + return cursorIndex; + } + + public void mouseClicked(int mouseX, int mouseY, int mouseButton) { + if (mouseButton == 1) { + textField.setText(""); + } else { + textField.setCursorPosition(getCursorPos(mouseX, mouseY)); + } + focus = true; + } + + public void unfocus() { + focus = false; + textField.setSelectionPos(textField.getCursorPosition()); + } + + public int strLenNoColor(String str) { + return str.replaceAll("(?i)\\u00A7.", "").length(); + } + + public void mouseClickMove(int mouseX, int mouseY, int clickedMouseButton, long timeSinceLastClick) { + if (focus) { + textField.setSelectionPos(getCursorPos(mouseX, mouseY)); + } + } + + public void keyTyped(char typedChar, int keyCode) { + if (focus) { + if ((options & MULTILINE) != 0) { //Carriage return + Pattern patternControlCode = Pattern.compile("(?i)\\u00A7([^\\u00B6\n]|$)(?!\\u00B6)"); + + String text = textField.getText(); + String textNoColour = textField.getText(); + while (true) { + Matcher matcher = patternControlCode.matcher(text); + if (!matcher.find() || matcher.groupCount() < 1) break; + String code = matcher.group(1); + if (code.isEmpty()) { + text = matcher.replaceFirst("\u00A7r\u00B6"); + } else { + text = matcher.replaceFirst("\u00A7" + code + "\u00B6" + code); + } + } + while (true) { + Matcher matcher = patternControlCode.matcher(textNoColour); + if (!matcher.find() || matcher.groupCount() < 1) break; + String code = matcher.group(1); + textNoColour = matcher.replaceFirst("\u00B6" + code); + } + + if (keyCode == 28) { + String before = textField.getText().substring(0, textField.getCursorPosition()); + String after = textField.getText().substring(textField.getCursorPosition()); + int pos = textField.getCursorPosition(); + textField.setText(before + "\n" + after); + textField.setCursorPosition(pos + 1); + return; + } else if (keyCode == 200) { //Up + String textNCBeforeCursor = textNoColour.substring(0, textField.getSelectionEnd()); + int colorCodes = org.apache.commons.lang3.StringUtils.countMatches(textNCBeforeCursor, "\u00B6"); + String textBeforeCursor = text.substring(0, textField.getSelectionEnd() + colorCodes * 2); + + int numLinesBeforeCursor = org.apache.commons.lang3.StringUtils.countMatches(textBeforeCursor, "\n"); + + String[] split = textBeforeCursor.split("\n"); + int textBeforeCursorWidth; + String lineBefore; + String thisLineBeforeCursor; + if (split.length == numLinesBeforeCursor && split.length > 0) { + textBeforeCursorWidth = 0; + lineBefore = split[split.length - 1]; + thisLineBeforeCursor = ""; + } else if (split.length > 1) { + thisLineBeforeCursor = split[split.length - 1]; + lineBefore = split[split.length - 2]; + textBeforeCursorWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth(thisLineBeforeCursor); + } else { + return; + } + String trimmed = Minecraft.getMinecraft().fontRendererObj + .trimStringToWidth(lineBefore, textBeforeCursorWidth); + int linePos = strLenNoColor(trimmed); + if (linePos != strLenNoColor(lineBefore)) { + char after = lineBefore.charAt(linePos); + int trimmedWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth(trimmed); + int charWidth = Minecraft.getMinecraft().fontRendererObj.getCharWidth(after); + if (trimmedWidth + charWidth / 2 < textBeforeCursorWidth) { + linePos++; + } + } + int newPos = textField.getSelectionEnd() - strLenNoColor(thisLineBeforeCursor) + - strLenNoColor(lineBefore) - 1 + linePos; + + if (GuiScreen.isShiftKeyDown()) { + textField.setSelectionPos(newPos); + } else { + textField.setCursorPosition(newPos); + } + } else if (keyCode == 208) { //Down + String textNCBeforeCursor = textNoColour.substring(0, textField.getSelectionEnd()); + int colorCodes = org.apache.commons.lang3.StringUtils.countMatches(textNCBeforeCursor, "\u00B6"); + String textBeforeCursor = text.substring(0, textField.getSelectionEnd() + colorCodes * 2); + + int numLinesBeforeCursor = org.apache.commons.lang3.StringUtils.countMatches(textBeforeCursor, "\n"); + + String[] split = textBeforeCursor.split("\n"); + String thisLineBeforeCursor; + int textBeforeCursorWidth; + if (split.length == numLinesBeforeCursor) { + thisLineBeforeCursor = ""; + textBeforeCursorWidth = 0; + } else if (split.length > 0) { + thisLineBeforeCursor = split[split.length - 1]; + textBeforeCursorWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth(thisLineBeforeCursor); + } else { + return; + } + + String[] split2 = textNoColour.split("\n"); + if (split2.length > numLinesBeforeCursor + 1) { + String lineAfter = split2[numLinesBeforeCursor + 1]; + String trimmed = Minecraft.getMinecraft().fontRendererObj + .trimStringToWidth(lineAfter, textBeforeCursorWidth); + int linePos = strLenNoColor(trimmed); + if (linePos != strLenNoColor(lineAfter)) { + char after = lineAfter.charAt(linePos); + int trimmedWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth(trimmed); + int charWidth = Minecraft.getMinecraft().fontRendererObj.getCharWidth(after); + if (trimmedWidth + charWidth / 2 < textBeforeCursorWidth) { + linePos++; + } + } + int newPos = textField.getSelectionEnd() - strLenNoColor(thisLineBeforeCursor) + + strLenNoColor(split2[numLinesBeforeCursor]) + 1 + linePos; + + if (GuiScreen.isShiftKeyDown()) { + textField.setSelectionPos(newPos); + } else { + textField.setCursorPosition(newPos); + } + } + } + } + + String old = textField.getText(); + if ((options & FORCE_CAPS) != 0) typedChar = Character.toUpperCase(typedChar); + if ((options & NO_SPACE) != 0 && typedChar == ' ') return; + + if (typedChar == '\u00B6') { + typedChar = '\u00A7'; + } + + textField.setFocused(true); + textField.textboxKeyTyped(typedChar, keyCode); + + if ((options & COLOUR) != 0) { + if (typedChar == '&') { + int pos = textField.getCursorPosition() - 2; + if (pos >= 0 && pos < textField.getText().length()) { + if (textField.getText().charAt(pos) == '&') { + String before = textField.getText().substring(0, pos); + String after = ""; + if (pos + 2 < textField.getText().length()) { + after = textField.getText().substring(pos + 2); + } + textField.setText(before + "\u00A7" + after); + textField.setCursorPosition(pos + 1); + } + } + } else if (typedChar == '*') { + int pos = textField.getCursorPosition() - 2; + if (pos >= 0 && pos < textField.getText().length()) { + if (textField.getText().charAt(pos) == '*') { + String before = textField.getText().substring(0, pos); + String after = ""; + if (pos + 2 < textField.getText().length()) { + after = textField.getText().substring(pos + 2); + } + textField.setText(before + "\u272A" + after); + textField.setCursorPosition(pos + 1); + } + } + } + } + + if ((options & NUM_ONLY) != 0 && textField.getText().matches("[^0-9.]")) textField.setText(old); + } + } + + public void render(int x, int y) { + this.x = x; + this.y = y; + drawTextbox(x, y, searchBarXSize, searchBarYSize, searchBarPadding, textField, focus); + } + + private void drawTextbox( + int x, int y, int searchBarXSize, int searchBarYSize, int searchBarPadding, + GuiTextField textField, boolean focus + ) { + ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft()); + String renderText = prependText + textField.getText(); + + GlStateManager.disableLighting(); + + /* + * Search bar + */ + int paddingUnscaled = searchBarPadding / scaledresolution.getScaleFactor(); + if (paddingUnscaled < 1) paddingUnscaled = 1; + + int numLines = org.apache.commons.lang3.StringUtils.countMatches(renderText, "\n") + 1; + int extraSize = (searchBarYSize - 8) / 2 + 8; + int bottomTextBox = y + searchBarYSize + extraSize * (numLines - 1); + + int borderColour = focus ? Color.GREEN.getRGB() : Color.WHITE.getRGB(); + if (customBorderColour != -1) { + borderColour = customBorderColour; + } + if ((options & DISABLE_BG) == 0) { + //bar background + Gui.drawRect(x - paddingUnscaled, + y - paddingUnscaled, + x + searchBarXSize + paddingUnscaled, + bottomTextBox + paddingUnscaled, borderColour + ); + Gui.drawRect(x, + y, + x + searchBarXSize, + bottomTextBox, Color.BLACK.getRGB() + ); + } + + //bar text + String text = renderText; + String textNoColor = renderText; + if ((options & COLOUR) != 0) { + while (true) { + Matcher matcher = PATTERN_CONTROL_CODE.matcher(text); + if (!matcher.find() || matcher.groupCount() < 1) break; + String code = matcher.group(1); + if (code.isEmpty()) { + text = matcher.replaceFirst("\u00A7r\u00B6"); + } else { + text = matcher.replaceFirst("\u00A7" + code + "\u00B6" + code); + } + } + } + while (true) { + Matcher matcher = PATTERN_CONTROL_CODE.matcher(textNoColor); + if (!matcher.find() || matcher.groupCount() < 1) break; + String code = matcher.group(1); + textNoColor = matcher.replaceFirst("\u00B6" + code); + } + + int xStartOffset = 5; + float scale = 1; + String[] texts = text.split("\n"); + for (int yOffI = 0; yOffI < texts.length; yOffI++) { + int yOff = yOffI * extraSize; + + if (isScaling() && Minecraft.getMinecraft().fontRendererObj.getStringWidth(texts[yOffI]) > searchBarXSize - 10) { + scale = (searchBarXSize - 2) / (float) Minecraft.getMinecraft().fontRendererObj.getStringWidth(texts[yOffI]); + if (scale > 1) scale = 1; + float newLen = Minecraft.getMinecraft().fontRendererObj.getStringWidth(texts[yOffI]) * scale; + xStartOffset = (int) ((searchBarXSize - newLen) / 2f); + + TextRenderUtils.drawStringCenteredScaledMaxWidth( + Utils.chromaStringByColourCode(texts[yOffI]), + Minecraft.getMinecraft().fontRendererObj, + x + searchBarXSize / 2f, + y + searchBarYSize / 2f + yOff, + false, + searchBarXSize - 2, + customTextColour + ); + } else { + if ((options & SCISSOR_TEXT) != 0) { + GlScissorStack.push(x + 5, 0, x + searchBarXSize, scaledresolution.getScaledHeight(), scaledresolution); + Minecraft.getMinecraft().fontRendererObj.drawString(Utils.chromaStringByColourCode(texts[yOffI]), x + 5, + y + (searchBarYSize - 8) / 2 + yOff, customTextColour + ); + GlScissorStack.pop(scaledresolution); + } else { + String toRender = Minecraft.getMinecraft().fontRendererObj.trimStringToWidth(Utils.chromaStringByColourCode( + texts[yOffI]), searchBarXSize - 10); + Minecraft.getMinecraft().fontRendererObj.drawString(toRender, x + 5, + y + (searchBarYSize - 8) / 2 + yOff, customTextColour + ); + } + + } + } + + if (focus && System.currentTimeMillis() % 1000 > 500) { + String textNCBeforeCursor = textNoColor.substring(0, textField.getCursorPosition() + prependText.length()); + int colorCodes = org.apache.commons.lang3.StringUtils.countMatches(textNCBeforeCursor, "\u00B6"); + String textBeforeCursor = text.substring( + 0, + Math.min( + text.length(), + textField.getCursorPosition() + prependText.length() + (((options & COLOUR) != 0) ? colorCodes * 2 : 0) + ) + ); + + int numLinesBeforeCursor = org.apache.commons.lang3.StringUtils.countMatches(textBeforeCursor, "\n"); + int yOff = numLinesBeforeCursor * extraSize; + + String[] split = textBeforeCursor.split("\n"); + int textBeforeCursorWidth; + if (split.length <= numLinesBeforeCursor || split.length == 0) { + textBeforeCursorWidth = 0; + } else { + textBeforeCursorWidth = (int) (Minecraft.getMinecraft().fontRendererObj.getStringWidth(split[split.length - + 1]) * scale); + } + Gui.drawRect(x + xStartOffset + textBeforeCursorWidth, + y + (searchBarYSize - 8) / 2 - 1 + yOff, + x + xStartOffset + textBeforeCursorWidth + 1, + y + (searchBarYSize - 8) / 2 + 9 + yOff, Color.WHITE.getRGB() + ); + } + + String selectedText = textField.getSelectedText(); + if (!selectedText.isEmpty()) { + int leftIndex = Math.min( + textField.getCursorPosition() + prependText.length(), + textField.getSelectionEnd() + prependText.length() + ); + int rightIndex = Math.max( + textField.getCursorPosition() + prependText.length(), + textField.getSelectionEnd() + prependText.length() + ); + + float texX = 0; + int texY = 0; + boolean sectionSignPrev = false; + boolean ignoreNext = false; + boolean bold = false; + for (int i = 0; i < textNoColor.length(); i++) { + if (ignoreNext) { + ignoreNext = false; + continue; + } + + char c = textNoColor.charAt(i); + if (sectionSignPrev) { + if (c != 'k' && c != 'K' + && c != 'm' && c != 'M' + && c != 'n' && c != 'N' + && c != 'o' && c != 'O') { + bold = c == 'l' || c == 'L'; + } + sectionSignPrev = false; + if (i < prependText.length()) continue; + } + if (c == '\u00B6') { + sectionSignPrev = true; + if (i < prependText.length()) continue; + } + + if (c == '\n') { + if (i >= leftIndex && i < rightIndex) { + Gui.drawRect(x + xStartOffset + (int) texX, + y + (searchBarYSize - 8) / 2 - 1 + texY, + x + xStartOffset + (int) texX + 3, + y + (searchBarYSize - 8) / 2 + 9 + texY, Color.LIGHT_GRAY.getRGB() + ); + } + + texX = 0; + texY += extraSize; + continue; + } + + int len = Minecraft.getMinecraft().fontRendererObj.getStringWidth(String.valueOf(c)); + if (bold) len++; + if (i >= leftIndex && i < rightIndex) { + Gui.drawRect(x + xStartOffset + (int) texX, + y + (searchBarYSize - 8) / 2 - 1 + texY, + x + xStartOffset + (int) (texX + len * scale), + y + (searchBarYSize - 8) / 2 + 9 + texY, Color.LIGHT_GRAY.getRGB() + ); + + TextRenderUtils.drawStringScaled(String.valueOf(c), Minecraft.getMinecraft().fontRendererObj, + x + xStartOffset + texX, + y + searchBarYSize / 2f - scale * 8 / 2f + texY, false, Color.BLACK.getRGB(), scale + ); + if (bold) { + TextRenderUtils.drawStringScaled(String.valueOf(c), Minecraft.getMinecraft().fontRendererObj, + x + xStartOffset + texX + 1, + y + searchBarYSize / 2f - scale * 8 / 2f + texY, false, Color.BLACK.getRGB(), scale + ); + } + } + + texX += len * scale; + } + } + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/GuiScreenElementWrapper.java b/src/main/java/io/github/moulberry/notenoughupdates/core/GuiScreenElementWrapper.java index 8d32d6c354..c7c4517bd1 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/GuiScreenElementWrapper.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/GuiScreenElementWrapper.java @@ -6,30 +6,29 @@ import java.io.IOException; public class GuiScreenElementWrapper extends GuiScreen { - - public final GuiElement element; - - public GuiScreenElementWrapper(GuiElement element) { - this.element = element; - } - - @Override - public void drawScreen(int mouseX, int mouseY, float partialTicks) { - super.drawScreen(mouseX, mouseY, partialTicks); - element.render(); - } - - @Override - public void handleMouseInput() throws IOException { - super.handleMouseInput(); - int i = Mouse.getEventX() * this.width / this.mc.displayWidth; - int j = this.height - Mouse.getEventY() * this.height / this.mc.displayHeight - 1; - element.mouseInput(i, j); - } - - @Override - public void handleKeyboardInput() throws IOException { - super.handleKeyboardInput(); - element.keyboardInput(); - } + public final GuiElement element; + + public GuiScreenElementWrapper(GuiElement element) { + this.element = element; + } + + @Override + public void drawScreen(int mouseX, int mouseY, float partialTicks) { + super.drawScreen(mouseX, mouseY, partialTicks); + element.render(); + } + + @Override + public void handleMouseInput() throws IOException { + super.handleMouseInput(); + int i = Mouse.getEventX() * this.width / this.mc.displayWidth; + int j = this.height - Mouse.getEventY() * this.height / this.mc.displayHeight - 1; + element.mouseInput(i, j); + } + + @Override + public void handleKeyboardInput() throws IOException { + super.handleKeyboardInput(); + element.keyboardInput(); + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/Config.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/Config.java index 8be828bd91..2a696a44ed 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/Config.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/Config.java @@ -1,8 +1,5 @@ package io.github.moulberry.notenoughupdates.core.config; public class Config { - - public void executeRunnable(int runnableId) { - } - + public void executeRunnable(int runnableId) {} } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/GuiPositionEditor.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/GuiPositionEditor.java index a48f3f1abd..9d0133cb45 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/GuiPositionEditor.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/GuiPositionEditor.java @@ -8,108 +8,113 @@ import java.io.IOException; public class GuiPositionEditor extends GuiScreen { - - public PositionNew position = new PositionNew(); - - public int clickedX; - public int clickedY; - - @Override - public void drawScreen(int mouseX, int mouseY, float partialTicks) { - super.drawDefaultBackground(); - - ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); - int width = scaledResolution.getScaledWidth(); - int height = scaledResolution.getScaledHeight(); - - int x = position.resolveX(scaledResolution, 200); - int y = position.resolveY(scaledResolution, 100); - - int centerWidth = 176; - int centerHeight = 166; - - float centerWF = centerWidth/2f / (float)width; - float centerHF = centerHeight/2f / (float)height; - - float left = 0; - float top = 0; - float right = 0; - float bottom = 0; - - switch(position.getAnchorX()) { - case MIN: { - left = 0; - right = 0.5f - centerWF; - break; - } - case MID: { - left = 0.5f - centerWF; - right = 0.5f + centerWF; - break; - } - case MAX: { - left = 0.5f + centerWF; - right = 1; - break; - } - } - switch(position.getAnchorY()) { - case MIN: { - top = 0; - bottom = 0.5f - centerHF; - break; - } - case MID: { - top = 0.5f - centerHF; - bottom = 0.5f + centerHF; - break; - } - case MAX: { - top = 0.5f + centerHF; - bottom = 1; - break; - } - } - - Gui.drawRect((int)(left*width), (int)(top*height), (int)(right*width), (int)(bottom*height), 0x40404040); - Gui.drawRect(x, y, x+200, y+100, 0x80404040); - } - - @Override - protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { - ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); - int x = position.resolveX(scaledResolution, 200); - int y = position.resolveY(scaledResolution, 100); - - if(mouseX > x && mouseX < x+200 && - mouseY > y && mouseY < y+100) { - clickedX = mouseX; - clickedY = mouseY; - } else { - clickedX = -1; - clickedY = -1; - } - } - - @Override - protected void mouseReleased(int mouseX, int mouseY, int state) { - clickedX = -1; - clickedY = -1; - } - - @Override - protected void mouseClickMove(int mouseX, int mouseY, int clickedMouseButton, long timeSinceLastClick) { - if(clickedX >= 0 && clickedY >= 0) { - int deltaX = mouseX - clickedX; - int deltaY = mouseY - clickedY; - - ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); - - deltaX = position.moveX(scaledResolution, deltaX, 200); - deltaY = position.moveY(scaledResolution, deltaY, 100); - - clickedX += deltaX; - clickedY += deltaY; - } - } + public PositionNew position = new PositionNew(); + + public int clickedX; + public int clickedY; + + @Override + public void drawScreen(int mouseX, int mouseY, float partialTicks) { + super.drawDefaultBackground(); + + ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + int width = scaledResolution.getScaledWidth(); + int height = scaledResolution.getScaledHeight(); + + int x = position.resolveX(scaledResolution, 200); + int y = position.resolveY(scaledResolution, 100); + + int centerWidth = 176; + int centerHeight = 166; + + float centerWF = centerWidth / 2f / (float) width; + float centerHF = centerHeight / 2f / (float) height; + + float left = 0; + float top = 0; + float right = 0; + float bottom = 0; + + switch (position.getAnchorX()) { + case MIN: { + left = 0; + right = 0.5f - centerWF; + break; + } + case MID: { + left = 0.5f - centerWF; + right = 0.5f + centerWF; + break; + } + case MAX: { + left = 0.5f + centerWF; + right = 1; + break; + } + } + switch (position.getAnchorY()) { + case MIN: { + top = 0; + bottom = 0.5f - centerHF; + break; + } + case MID: { + top = 0.5f - centerHF; + bottom = 0.5f + centerHF; + break; + } + case MAX: { + top = 0.5f + centerHF; + bottom = 1; + break; + } + } + + Gui.drawRect( + (int) (left * width), + (int) (top * height), + (int) (right * width), + (int) (bottom * height), + 0x40404040 + ); + Gui.drawRect(x, y, x + 200, y + 100, 0x80404040); + } + + @Override + protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { + ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + int x = position.resolveX(scaledResolution, 200); + int y = position.resolveY(scaledResolution, 100); + + if (mouseX > x && mouseX < x + 200 && + mouseY > y && mouseY < y + 100) { + clickedX = mouseX; + clickedY = mouseY; + } else { + clickedX = -1; + clickedY = -1; + } + } + + @Override + protected void mouseReleased(int mouseX, int mouseY, int state) { + clickedX = -1; + clickedY = -1; + } + + @Override + protected void mouseClickMove(int mouseX, int mouseY, int clickedMouseButton, long timeSinceLastClick) { + if (clickedX >= 0 && clickedY >= 0) { + int deltaX = mouseX - clickedX; + int deltaY = mouseY - clickedY; + + ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + + deltaX = position.moveX(scaledResolution, deltaX, 200); + deltaY = position.moveY(scaledResolution, deltaY, 100); + + clickedX += deltaX; + clickedY += deltaY; + } + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/KeybindHelper.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/KeybindHelper.java index 7ebacac1bc..30226a22e5 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/KeybindHelper.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/KeybindHelper.java @@ -1,51 +1,48 @@ package io.github.moulberry.notenoughupdates.core.config; -import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import org.lwjgl.input.Keyboard; import org.lwjgl.input.Mouse; public class KeybindHelper { + public static String getKeyName(int keyCode) { + if (keyCode == 0) { + return "NONE"; + } else if (keyCode < 0) { + return "Button " + (keyCode + 101); + } else { + String keyName = Keyboard.getKeyName(keyCode); + if (keyName == null) { + keyName = "???"; + } else if (keyName.equalsIgnoreCase("LMENU")) { + keyName = "LALT"; + } else if (keyName.equalsIgnoreCase("RMENU")) { + keyName = "RALT"; + } + return keyName; + } + } - public static String getKeyName(int keyCode) { - if(keyCode == 0) { - return "NONE"; - } else if(keyCode < 0) { - return "Button "+(keyCode+101); - } else { - String keyName = Keyboard.getKeyName(keyCode); - if(keyName == null) { - keyName = "???"; - } else if(keyName.equalsIgnoreCase("LMENU")) { - keyName = "LALT"; - } else if(keyName.equalsIgnoreCase("RMENU")) { - keyName = "RALT"; - } - return keyName; - } - } + public static boolean isKeyValid(int keyCode) { + return keyCode != 0; + } - public static boolean isKeyValid(int keyCode) { - return keyCode != 0; - } - - public static boolean isKeyDown(int keyCode) { - if(!isKeyValid(keyCode)) { - return false; - } else if(keyCode < 0) { - return Mouse.isButtonDown(keyCode+100); - } else { - return Keyboard.isKeyDown(keyCode); - } - } - - public static boolean isKeyPressed(int keyCode) { - if(!isKeyValid(keyCode)) { - return false; - } else if(keyCode < 0) { - return Mouse.getEventButtonState() && Mouse.getEventButton() == keyCode+100; - } else { - return Keyboard.getEventKeyState() && Keyboard.getEventKey() == keyCode; - } - } + public static boolean isKeyDown(int keyCode) { + if (!isKeyValid(keyCode)) { + return false; + } else if (keyCode < 0) { + return Mouse.isButtonDown(keyCode + 100); + } else { + return Keyboard.isKeyDown(keyCode); + } + } + public static boolean isKeyPressed(int keyCode) { + if (!isKeyValid(keyCode)) { + return false; + } else if (keyCode < 0) { + return Mouse.getEventButtonState() && Mouse.getEventButton() == keyCode + 100; + } else { + return Keyboard.getEventKeyState() && Keyboard.getEventKey() == keyCode; + } + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/Position.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/Position.java index 66df27c662..cf94664964 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/Position.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/Position.java @@ -4,188 +4,186 @@ import net.minecraft.client.gui.ScaledResolution; public class Position { - - @Expose - private int x; - @Expose - private int y; - @Expose - private boolean centerX; - @Expose - private boolean centerY; - - private static final int EDGE_OFFSET = 0; - - public Position(int x, int y) { - this(x, y, false, false); - } - - public Position(int x, int y, boolean centerX, boolean centerY) { - this.x = x; - this.y = y; - this.centerX = centerX; - this.centerY = centerY; - } - - public void set(Position other) { - this.x = other.x; - this.y = other.y; - this.centerX = other.centerX; - this.centerY = other.centerY; - } - - public Position clone() { - return new Position(x, y, centerX, centerY); - } - - public boolean isCenterX() { - return centerX; - } - - public boolean isCenterY() { - return centerY; - } - - public int getRawX() { - return x; - } - - public int getRawY() { - return y; - } - - public int getAbsX(ScaledResolution scaledResolution, int objWidth) { - int width = scaledResolution.getScaledWidth(); - - if(centerX) { - return width/2 + x; - } - - int ret = x; - if(x < 0) { - ret = width + x - objWidth; - } - - if(ret < 0) ret = 0; - if(ret > width - objWidth) ret = width - objWidth; - - return ret; - } - - public int getAbsY(ScaledResolution scaledResolution, int objHeight) { - int height = scaledResolution.getScaledHeight(); - - if(centerY) { - return height/2 + y; - } - - int ret = y; - if(y < 0) { - ret = height + y - objHeight; - } - - if(ret < 0) ret = 0; - if(ret > height - objHeight) ret = height - objHeight; - - return ret; - } - - public int moveX(int deltaX, int objWidth, ScaledResolution scaledResolution) { - int screenWidth = scaledResolution.getScaledWidth(); - boolean wasPositiveX = this.x >= 0; - this.x += deltaX; - - if(centerX) { - if(wasPositiveX) { - if(this.x > screenWidth/2-objWidth/2) { - deltaX += screenWidth/2-objWidth/2-this.x; - this.x = screenWidth/2-objWidth/2; - } - } else { - if(this.x < -screenWidth/2+objWidth/2) { - deltaX += -screenWidth/2+objWidth/2-this.x; - this.x = -screenWidth/2+objWidth/2; - } - } - return deltaX; - } - - if(wasPositiveX) { - if(this.x < EDGE_OFFSET) { - deltaX += EDGE_OFFSET-this.x; - this.x = EDGE_OFFSET; - } - if(this.x > screenWidth-EDGE_OFFSET) { - deltaX += screenWidth-EDGE_OFFSET-this.x; - this.x = screenWidth-EDGE_OFFSET; - } - } else { - if(this.x+1 > -EDGE_OFFSET) { - deltaX += -EDGE_OFFSET-1-this.x; - this.x = -EDGE_OFFSET-1; - } - if(this.x+screenWidth < EDGE_OFFSET) { - deltaX += EDGE_OFFSET-screenWidth-this.x; - this.x = EDGE_OFFSET-screenWidth; - } - } - - if(this.x >= 0 && this.x+objWidth/2 > screenWidth/2) { - this.x -= screenWidth - objWidth; - } - if(this.x < 0 && this.x+objWidth/2 <= -screenWidth/2) { - this.x += screenWidth - objWidth; - } - return deltaX; - } - - public int moveY(int deltaY, int objHeight, ScaledResolution scaledResolution) { - int screenHeight = scaledResolution.getScaledHeight(); - boolean wasPositiveY = this.y >= 0; - this.y += deltaY; - - if(centerY) { - if(wasPositiveY) { - if(this.y > screenHeight/2-objHeight/2) { - deltaY += screenHeight/2-objHeight/2-this.y; - this.y = screenHeight/2-objHeight/2; - } - } else { - if(this.y < -screenHeight/2+objHeight/2) { - deltaY += -screenHeight/2+objHeight/2-this.y; - this.y = -screenHeight/2+objHeight/2; - } - } - return deltaY; - } - - if(wasPositiveY) { - if(this.y < EDGE_OFFSET) { - deltaY += EDGE_OFFSET-this.y; - this.y = EDGE_OFFSET; - } - if(this.y > screenHeight-EDGE_OFFSET) { - deltaY += screenHeight-EDGE_OFFSET-this.y; - this.y = screenHeight-EDGE_OFFSET; - } - } else { - if(this.y+1 > -EDGE_OFFSET) { - deltaY += -EDGE_OFFSET-1-this.y; - this.y = -EDGE_OFFSET-1; - } - if(this.y+screenHeight < EDGE_OFFSET) { - deltaY += EDGE_OFFSET-screenHeight-this.y; - this.y = EDGE_OFFSET-screenHeight; - } - } - - if(this.y >= 0 && this.y-objHeight/2 > screenHeight/2) { - this.y -= screenHeight - objHeight; - } - if(this.y < 0 && this.y-objHeight/2 <= -screenHeight/2) { - this.y += screenHeight - objHeight; - } - return deltaY; - } - + @Expose + private int x; + @Expose + private int y; + @Expose + private boolean centerX; + @Expose + private boolean centerY; + + private static final int EDGE_OFFSET = 0; + + public Position(int x, int y) { + this(x, y, false, false); + } + + public Position(int x, int y, boolean centerX, boolean centerY) { + this.x = x; + this.y = y; + this.centerX = centerX; + this.centerY = centerY; + } + + public void set(Position other) { + this.x = other.x; + this.y = other.y; + this.centerX = other.centerX; + this.centerY = other.centerY; + } + + public Position clone() { + return new Position(x, y, centerX, centerY); + } + + public boolean isCenterX() { + return centerX; + } + + public boolean isCenterY() { + return centerY; + } + + public int getRawX() { + return x; + } + + public int getRawY() { + return y; + } + + public int getAbsX(ScaledResolution scaledResolution, int objWidth) { + int width = scaledResolution.getScaledWidth(); + + if (centerX) { + return width / 2 + x; + } + + int ret = x; + if (x < 0) { + ret = width + x - objWidth; + } + + if (ret < 0) ret = 0; + if (ret > width - objWidth) ret = width - objWidth; + + return ret; + } + + public int getAbsY(ScaledResolution scaledResolution, int objHeight) { + int height = scaledResolution.getScaledHeight(); + + if (centerY) { + return height / 2 + y; + } + + int ret = y; + if (y < 0) { + ret = height + y - objHeight; + } + + if (ret < 0) ret = 0; + if (ret > height - objHeight) ret = height - objHeight; + + return ret; + } + + public int moveX(int deltaX, int objWidth, ScaledResolution scaledResolution) { + int screenWidth = scaledResolution.getScaledWidth(); + boolean wasPositiveX = this.x >= 0; + this.x += deltaX; + + if (centerX) { + if (wasPositiveX) { + if (this.x > screenWidth / 2 - objWidth / 2) { + deltaX += screenWidth / 2 - objWidth / 2 - this.x; + this.x = screenWidth / 2 - objWidth / 2; + } + } else { + if (this.x < -screenWidth / 2 + objWidth / 2) { + deltaX += -screenWidth / 2 + objWidth / 2 - this.x; + this.x = -screenWidth / 2 + objWidth / 2; + } + } + return deltaX; + } + + if (wasPositiveX) { + if (this.x < EDGE_OFFSET) { + deltaX += EDGE_OFFSET - this.x; + this.x = EDGE_OFFSET; + } + if (this.x > screenWidth - EDGE_OFFSET) { + deltaX += screenWidth - EDGE_OFFSET - this.x; + this.x = screenWidth - EDGE_OFFSET; + } + } else { + if (this.x + 1 > -EDGE_OFFSET) { + deltaX += -EDGE_OFFSET - 1 - this.x; + this.x = -EDGE_OFFSET - 1; + } + if (this.x + screenWidth < EDGE_OFFSET) { + deltaX += EDGE_OFFSET - screenWidth - this.x; + this.x = EDGE_OFFSET - screenWidth; + } + } + + if (this.x >= 0 && this.x + objWidth / 2 > screenWidth / 2) { + this.x -= screenWidth - objWidth; + } + if (this.x < 0 && this.x + objWidth / 2 <= -screenWidth / 2) { + this.x += screenWidth - objWidth; + } + return deltaX; + } + + public int moveY(int deltaY, int objHeight, ScaledResolution scaledResolution) { + int screenHeight = scaledResolution.getScaledHeight(); + boolean wasPositiveY = this.y >= 0; + this.y += deltaY; + + if (centerY) { + if (wasPositiveY) { + if (this.y > screenHeight / 2 - objHeight / 2) { + deltaY += screenHeight / 2 - objHeight / 2 - this.y; + this.y = screenHeight / 2 - objHeight / 2; + } + } else { + if (this.y < -screenHeight / 2 + objHeight / 2) { + deltaY += -screenHeight / 2 + objHeight / 2 - this.y; + this.y = -screenHeight / 2 + objHeight / 2; + } + } + return deltaY; + } + + if (wasPositiveY) { + if (this.y < EDGE_OFFSET) { + deltaY += EDGE_OFFSET - this.y; + this.y = EDGE_OFFSET; + } + if (this.y > screenHeight - EDGE_OFFSET) { + deltaY += screenHeight - EDGE_OFFSET - this.y; + this.y = screenHeight - EDGE_OFFSET; + } + } else { + if (this.y + 1 > -EDGE_OFFSET) { + deltaY += -EDGE_OFFSET - 1 - this.y; + this.y = -EDGE_OFFSET - 1; + } + if (this.y + screenHeight < EDGE_OFFSET) { + deltaY += EDGE_OFFSET - screenHeight - this.y; + this.y = EDGE_OFFSET - screenHeight; + } + } + + if (this.y >= 0 && this.y - objHeight / 2 > screenHeight / 2) { + this.y -= screenHeight - objHeight; + } + if (this.y < 0 && this.y - objHeight / 2 <= -screenHeight / 2) { + this.y += screenHeight - objHeight; + } + return deltaY; + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/PositionNew.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/PositionNew.java index 842df73d33..8f2b02d85a 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/PositionNew.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/PositionNew.java @@ -7,154 +7,186 @@ import java.util.concurrent.atomic.AtomicReference; public class PositionNew { - - public enum Anchor { - MIN(0, 0, 0), - MID(0.5f, -0.5f, 0), - MAX(1f, -1f, 0), - GUI_MIN(0.5f, -1f, -0.5f), - GUI_MAX(0.5f, 0, 0.5f); - - float screenMult; - float elementMult; - float guiMult; - - Anchor(float screenMult, float elementMult, float guiMult) { - this.screenMult = screenMult; - this.elementMult = elementMult; - this.guiMult = guiMult; - } - } - - @Expose - private int x = 0; - @Expose - private int y = 0; - @Expose - private float scaleX = 1; - @Expose - private float scaleY = 1; - - @Expose - private Anchor anchorX = Anchor.MIN; - @Expose - private Anchor anchorY = Anchor.MIN; - - @Expose - private boolean pinned = false; - @Expose - private boolean allowPinToggle = true; - @Expose - private boolean allowResize = true; - - public PositionNew(int x, int y, int scaleX, int scaleY, Anchor anchorX, Anchor anchorY, boolean pinned, boolean allowPinToggle, boolean allowResize) { - this.x = x; - this.y = y; - this.scaleX = scaleX; - this.scaleY = scaleY; - this.anchorX = anchorX; - this.anchorY = anchorY; - this.pinned = pinned; - this.allowPinToggle = allowPinToggle; - this.allowResize = allowResize; - } - - protected PositionNew() { - } - - public int moveX(ScaledResolution scaledResolution, int deltaX, int sizeX) { - int originalX = resolveX(scaledResolution, sizeX); - AtomicInteger atomicInteger = new AtomicInteger(x+deltaX); - AtomicReference atomicReference = new AtomicReference<>(anchorX); - move(atomicInteger, atomicReference, anchorY, (int)Math.ceil(sizeX*scaleX), scaledResolution.getScaledWidth(), 176); - x = atomicInteger.get(); - anchorX = atomicReference.get(); - return resolveX(scaledResolution, sizeX) - originalX; - } - - public int moveY(ScaledResolution scaledResolution, int deltaY, int sizeY) { - int originalY = resolveY(scaledResolution, sizeY); - AtomicInteger atomicInteger = new AtomicInteger(y+deltaY); - AtomicReference atomicReference = new AtomicReference<>(anchorY); - move(atomicInteger, atomicReference, anchorY, (int)Math.ceil(sizeY*scaleY), scaledResolution.getScaledHeight(), 166); - y = atomicInteger.get(); - anchorY = atomicReference.get(); - return resolveY(scaledResolution, sizeY) - originalY; - } - - private void move(AtomicInteger coord, AtomicReference anchor, Anchor oppositeAnchor, int elementSize, int screenSize, int guiSize) { - int centerCoord = resolve(coord.get(), anchor.get(), elementSize, screenSize, guiSize) + elementSize/2; - - if(centerCoord < screenSize/2-guiSize/2) { - if(pinned && centerCoord > screenSize/4-guiSize/4 && oppositeAnchor == Anchor.MID) { - anchor.set(Anchor.GUI_MIN); - } else { - anchor.set(Anchor.MIN); - } - } else if(centerCoord > screenSize/2+guiSize/2) { - if(pinned && centerCoord < screenSize-(screenSize/4-guiSize/4) && oppositeAnchor == Anchor.MID) { - anchor.set(Anchor.GUI_MAX); - } else { - anchor.set(Anchor.MAX); - } - } else { - anchor.set(Anchor.MID); - } - - if(centerCoord - elementSize/2 < 0) centerCoord = elementSize/2; - if(centerCoord + elementSize/2 > screenSize) centerCoord = screenSize - elementSize/2; - - Anchor newAnchor = anchor.get(); - coord.set(Math.round(centerCoord - (elementSize*(newAnchor.elementMult+0.5f)) - screenSize*newAnchor.screenMult - guiSize*newAnchor.guiMult)); - } - - public int resolveX(ScaledResolution scaledResolution, int sizeX) { - return resolve(x, anchorX, (int)Math.ceil(sizeX*scaleX), scaledResolution.getScaledWidth(), 176); - } - - public int resolveY(ScaledResolution scaledResolution, int sizeY) { - return resolve(y, anchorY, (int)Math.ceil(sizeY*scaleY), scaledResolution.getScaledHeight(), 166); - } - - private int resolve(int coord, Anchor anchor, int elementSize, int screenSize, int guiSize) { - return Math.round(screenSize*anchor.screenMult + elementSize*anchor.elementMult + guiSize*anchor.guiMult + coord); - } - - public void setScaleX(float scaleX) { - if(allowResize) { - this.scaleX = scaleX; - } - } - - public void setScaleY(float scaleY) { - if(allowResize) { - this.scaleY = scaleY; - } - } - - public float getScaleX() { - return scaleX; - } - - public float getScaleY() { - return scaleY; - } - - public void setPinned(boolean pinned) { - if(allowPinToggle) { - this.pinned = pinned; - } - } - - public boolean isPinned() { - return pinned; - } - - public Anchor getAnchorX() { - return anchorX; - } - - public Anchor getAnchorY() { - return anchorY; - } + public enum Anchor { + MIN(0, 0, 0), + MID(0.5f, -0.5f, 0), + MAX(1f, -1f, 0), + GUI_MIN(0.5f, -1f, -0.5f), + GUI_MAX(0.5f, 0, 0.5f); + + float screenMult; + float elementMult; + float guiMult; + + Anchor(float screenMult, float elementMult, float guiMult) { + this.screenMult = screenMult; + this.elementMult = elementMult; + this.guiMult = guiMult; + } + } + + @Expose + private int x = 0; + @Expose + private int y = 0; + @Expose + private float scaleX = 1; + @Expose + private float scaleY = 1; + + @Expose + private Anchor anchorX = Anchor.MIN; + @Expose + private Anchor anchorY = Anchor.MIN; + + @Expose + private boolean pinned = false; + @Expose + private boolean allowPinToggle = true; + @Expose + private boolean allowResize = true; + + public PositionNew( + int x, + int y, + int scaleX, + int scaleY, + Anchor anchorX, + Anchor anchorY, + boolean pinned, + boolean allowPinToggle, + boolean allowResize + ) { + this.x = x; + this.y = y; + this.scaleX = scaleX; + this.scaleY = scaleY; + this.anchorX = anchorX; + this.anchorY = anchorY; + this.pinned = pinned; + this.allowPinToggle = allowPinToggle; + this.allowResize = allowResize; + } + + protected PositionNew() {} + + public int moveX(ScaledResolution scaledResolution, int deltaX, int sizeX) { + int originalX = resolveX(scaledResolution, sizeX); + AtomicInteger atomicInteger = new AtomicInteger(x + deltaX); + AtomicReference atomicReference = new AtomicReference<>(anchorX); + move( + atomicInteger, + atomicReference, + anchorY, + (int) Math.ceil(sizeX * scaleX), + scaledResolution.getScaledWidth(), + 176 + ); + x = atomicInteger.get(); + anchorX = atomicReference.get(); + return resolveX(scaledResolution, sizeX) - originalX; + } + + public int moveY(ScaledResolution scaledResolution, int deltaY, int sizeY) { + int originalY = resolveY(scaledResolution, sizeY); + AtomicInteger atomicInteger = new AtomicInteger(y + deltaY); + AtomicReference atomicReference = new AtomicReference<>(anchorY); + move( + atomicInteger, + atomicReference, + anchorY, + (int) Math.ceil(sizeY * scaleY), + scaledResolution.getScaledHeight(), + 166 + ); + y = atomicInteger.get(); + anchorY = atomicReference.get(); + return resolveY(scaledResolution, sizeY) - originalY; + } + + private void move( + AtomicInteger coord, + AtomicReference anchor, + Anchor oppositeAnchor, + int elementSize, + int screenSize, + int guiSize + ) { + int centerCoord = resolve(coord.get(), anchor.get(), elementSize, screenSize, guiSize) + elementSize / 2; + + if (centerCoord < screenSize / 2 - guiSize / 2) { + if (pinned && centerCoord > screenSize / 4 - guiSize / 4 && oppositeAnchor == Anchor.MID) { + anchor.set(Anchor.GUI_MIN); + } else { + anchor.set(Anchor.MIN); + } + } else if (centerCoord > screenSize / 2 + guiSize / 2) { + if (pinned && centerCoord < screenSize - (screenSize / 4 - guiSize / 4) && oppositeAnchor == Anchor.MID) { + anchor.set(Anchor.GUI_MAX); + } else { + anchor.set(Anchor.MAX); + } + } else { + anchor.set(Anchor.MID); + } + + if (centerCoord - elementSize / 2 < 0) centerCoord = elementSize / 2; + if (centerCoord + elementSize / 2 > screenSize) centerCoord = screenSize - elementSize / 2; + + Anchor newAnchor = anchor.get(); + coord.set(Math.round( + centerCoord - (elementSize * (newAnchor.elementMult + 0.5f)) - screenSize * newAnchor.screenMult - + guiSize * newAnchor.guiMult)); + } + + public int resolveX(ScaledResolution scaledResolution, int sizeX) { + return resolve(x, anchorX, (int) Math.ceil(sizeX * scaleX), scaledResolution.getScaledWidth(), 176); + } + + public int resolveY(ScaledResolution scaledResolution, int sizeY) { + return resolve(y, anchorY, (int) Math.ceil(sizeY * scaleY), scaledResolution.getScaledHeight(), 166); + } + + private int resolve(int coord, Anchor anchor, int elementSize, int screenSize, int guiSize) { + return Math.round( + screenSize * anchor.screenMult + elementSize * anchor.elementMult + guiSize * anchor.guiMult + coord); + } + + public void setScaleX(float scaleX) { + if (allowResize) { + this.scaleX = scaleX; + } + } + + public void setScaleY(float scaleY) { + if (allowResize) { + this.scaleY = scaleY; + } + } + + public float getScaleX() { + return scaleX; + } + + public float getScaleY() { + return scaleY; + } + + public void setPinned(boolean pinned) { + if (allowPinToggle) { + this.pinned = pinned; + } + } + + public boolean isPinned() { + return pinned; + } + + public Anchor getAnchorX() { + return anchorX; + } + + public Anchor getAnchorY() { + return anchorY; + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/Category.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/Category.java index 6a91cae5b6..b67d038363 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/Category.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/Category.java @@ -8,8 +8,7 @@ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Category { + String name(); - String name(); - String desc(); - + String desc(); } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigAccordionId.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigAccordionId.java index 54d3e3456e..1c84785127 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigAccordionId.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigAccordionId.java @@ -8,7 +8,5 @@ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface ConfigAccordionId { - - int id(); - + int id(); } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorAccordion.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorAccordion.java index 47948985d8..11b798f9cf 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorAccordion.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorAccordion.java @@ -8,7 +8,5 @@ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface ConfigEditorAccordion { - - int id(); - + int id(); } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorBoolean.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorBoolean.java index 3c6465e6b3..a0ca1f386e 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorBoolean.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorBoolean.java @@ -7,6 +7,4 @@ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) -public @interface ConfigEditorBoolean { - -} +public @interface ConfigEditorBoolean {} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorButton.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorButton.java index 5fe7fcb4a4..455df65fb4 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorButton.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorButton.java @@ -8,8 +8,7 @@ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface ConfigEditorButton { + int runnableId(); - int runnableId(); - String buttonText() default ""; - + String buttonText() default ""; } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorColour.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorColour.java index d1dd5808ab..6640ade911 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorColour.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorColour.java @@ -1,6 +1,5 @@ package io.github.moulberry.notenoughupdates.core.config.annotations; - import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -8,6 +7,4 @@ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) -public @interface ConfigEditorColour { - -} +public @interface ConfigEditorColour {} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorDraggableList.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorDraggableList.java index 8689bda8f4..e171e0ae43 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorDraggableList.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorDraggableList.java @@ -8,7 +8,5 @@ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface ConfigEditorDraggableList { - - String[] exampleText(); - + String[] exampleText(); } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorDropdown.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorDropdown.java index d9d2235bd2..ac766e934e 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorDropdown.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorDropdown.java @@ -1,6 +1,5 @@ package io.github.moulberry.notenoughupdates.core.config.annotations; - import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -9,8 +8,7 @@ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface ConfigEditorDropdown { + String[] values(); - String[] values(); - int initialIndex() default 0; - + int initialIndex() default 0; } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorFSR.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorFSR.java new file mode 100644 index 0000000000..217df0c59a --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorFSR.java @@ -0,0 +1,14 @@ +package io.github.moulberry.notenoughupdates.core.config.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface ConfigEditorFSR { + int runnableId(); + + String buttonText() default ""; +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorKeybind.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorKeybind.java index 527171f2a2..8d8de2ebed 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorKeybind.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorKeybind.java @@ -8,7 +8,5 @@ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface ConfigEditorKeybind { - - int defaultKey(); - + int defaultKey(); } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorSlider.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorSlider.java index d671f65c03..abab37f914 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorSlider.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorSlider.java @@ -1,6 +1,5 @@ package io.github.moulberry.notenoughupdates.core.config.annotations; - import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -9,10 +8,9 @@ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface ConfigEditorSlider { + float minValue(); - float minValue(); - float maxValue(); - - float minStep(); + float maxValue(); + float minStep(); } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorText.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorText.java index 9227cf50b0..1ff7e39e50 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorText.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorText.java @@ -1,6 +1,5 @@ package io.github.moulberry.notenoughupdates.core.config.annotations; - import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -8,6 +7,4 @@ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) -public @interface ConfigEditorText { - -} +public @interface ConfigEditorText {} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigOption.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigOption.java index 63c3366acc..2ee23dcf42 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigOption.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigOption.java @@ -1,6 +1,5 @@ package io.github.moulberry.notenoughupdates.core.config.annotations; - import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -9,9 +8,9 @@ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface ConfigOption { + String name(); - String name(); - String desc(); - int subcategoryId() default -1; + String desc(); + int subcategoryId() default -1; } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditor.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditor.java index e28c5a32bd..d62c7ec7cf 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditor.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditor.java @@ -8,55 +8,56 @@ import net.minecraft.client.renderer.GlStateManager; public abstract class GuiOptionEditor { + protected final ConfigProcessor.ProcessedOption option; + private static final int HEIGHT = 45; - protected final ConfigProcessor.ProcessedOption option; - private static final int HEIGHT = 45; + public GuiOptionEditor(ConfigProcessor.ProcessedOption option) { + this.option = option; + } - public GuiOptionEditor(ConfigProcessor.ProcessedOption option) { - this.option = option; - } + public void render(int x, int y, int width) { + int height = getHeight(); - public void render(int x, int y, int width) { - int height = getHeight(); + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + RenderUtils.drawFloatingRectDark(x, y, width, height, true); + TextRenderUtils.drawStringCenteredScaledMaxWidth(option.name, + fr, x + width / 6, y + 13, true, width / 3 - 10, 0xc0c0c0 + ); - FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; - RenderUtils.drawFloatingRectDark(x, y, width, height, true); - TextRenderUtils.drawStringCenteredScaledMaxWidth(option.name, - fr, x+width/6, y+13, true, width/3-10, 0xc0c0c0); + int maxLines = 5; + float scale = 1; + int lineCount = fr.listFormattedStringToWidth(option.desc, width * 2 / 3 - 10).size(); - int maxLines = 5; - float scale = 1; - int lineCount = fr.listFormattedStringToWidth(option.desc, width*2/3-10).size(); + if (lineCount <= 0) return; - if(lineCount <= 0) return; + float paraHeight = 9 * lineCount - 1; - float paraHeight = 9 * lineCount - 1; + while (paraHeight >= HEIGHT - 10) { + scale -= 1 / 8f; + lineCount = fr.listFormattedStringToWidth(option.desc, (int) (width * 2 / 3 / scale - 10)).size(); + paraHeight = (int) (9 * scale * lineCount - 1 * scale); + } - while(paraHeight >= HEIGHT-10) { - scale -= 1/8f; - lineCount = fr.listFormattedStringToWidth(option.desc, (int)(width*2/3/scale-10)).size(); - paraHeight = (int)(9*scale * lineCount - 1*scale); - } + GlStateManager.pushMatrix(); + GlStateManager.translate(x + 5 + width / 3f, y + HEIGHT / 2f - paraHeight / 2, 0); + GlStateManager.scale(scale, scale, 1); - GlStateManager.pushMatrix(); - GlStateManager.translate(x+5+width/3f, y+HEIGHT/2f-paraHeight/2, 0); - GlStateManager.scale(scale, scale, 1); + fr.drawSplitString(option.desc, 0, 0, (int) (width * 2 / 3 / scale - 10), 0xc0c0c0); - fr.drawSplitString(option.desc, 0, 0, (int)(width*2/3/scale-10), 0xc0c0c0); + GlStateManager.popMatrix(); + } - GlStateManager.popMatrix(); - } + public int getHeight() { + return HEIGHT; + } - public int getHeight() { - return HEIGHT; - } + public abstract boolean mouseInput(int x, int y, int width, int mouseX, int mouseY); - public abstract boolean mouseInput(int x, int y, int width, int mouseX, int mouseY); - public abstract boolean keyboardInput(); + public abstract boolean keyboardInput(); - public boolean mouseInputOverlay(int x, int y, int width, int mouseX, int mouseY) { - return false; - } - public void renderOverlay(int x, int y, int width) {}; + public boolean mouseInputOverlay(int x, int y, int width, int mouseX, int mouseY) { + return false; + } + public void renderOverlay(int x, int y, int width) {} } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorAccordion.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorAccordion.java index 79667ff8be..8877cd03bd 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorAccordion.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorAccordion.java @@ -1,11 +1,9 @@ package io.github.moulberry.notenoughupdates.core.config.gui; -import io.github.moulberry.notenoughupdates.core.config.Config; import io.github.moulberry.notenoughupdates.core.config.struct.ConfigProcessor; import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils; import io.github.moulberry.notenoughupdates.core.util.render.TextRenderUtils; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.Gui; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.WorldRenderer; @@ -13,74 +11,72 @@ import org.lwjgl.input.Mouse; import org.lwjgl.opengl.GL11; -import static io.github.moulberry.notenoughupdates.util.GuiTextures.button_tex; - public class GuiOptionEditorAccordion extends GuiOptionEditor { + private final int accordionId; + private boolean accordionToggled; - private int accordionId; - private boolean accordionToggled; - - public GuiOptionEditorAccordion(ConfigProcessor.ProcessedOption option, int accordionId) { - super(option); - this.accordionToggled = (boolean) option.get(); - this.accordionId = accordionId; - } + public GuiOptionEditorAccordion(ConfigProcessor.ProcessedOption option, int accordionId) { + super(option); + this.accordionToggled = (boolean) option.get(); + this.accordionId = accordionId; + } - @Override - public int getHeight() { - return 20; - } + @Override + public int getHeight() { + return 20; + } - public int getAccordionId() { - return accordionId; - } + public int getAccordionId() { + return accordionId; + } - public boolean getToggled() { - return accordionToggled; - } + public boolean getToggled() { + return accordionToggled; + } - @Override - public void render(int x, int y, int width) { - int height = getHeight(); - RenderUtils.drawFloatingRectDark(x, y, width, height, true); + @Override + public void render(int x, int y, int width) { + int height = getHeight(); + RenderUtils.drawFloatingRectDark(x, y, width, height, true); - Tessellator tessellator = Tessellator.getInstance(); - WorldRenderer worldrenderer = tessellator.getWorldRenderer(); - GlStateManager.enableBlend(); - GlStateManager.disableTexture2D(); - GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); - GlStateManager.color(1, 1, 1, 1); - worldrenderer.begin(GL11.GL_TRIANGLES, DefaultVertexFormats.POSITION); - if(accordionToggled) { - worldrenderer.pos((double)x+6, (double)y+6, 0.0D).endVertex(); - worldrenderer.pos((double)x+9.75f, (double)y+13.5f, 0.0D).endVertex(); - worldrenderer.pos((double)x+13.5f, (double)y+6, 0.0D).endVertex(); - } else { - worldrenderer.pos((double)x+6, (double)y+13.5f, 0.0D).endVertex(); - worldrenderer.pos((double)x+13.5f, (double)y+9.75f, 0.0D).endVertex(); - worldrenderer.pos((double)x+6, (double)y+6, 0.0D).endVertex(); - } - tessellator.draw(); - GlStateManager.enableTexture2D(); - GlStateManager.disableBlend(); + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer worldrenderer = tessellator.getWorldRenderer(); + GlStateManager.enableBlend(); + GlStateManager.disableTexture2D(); + GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); + GlStateManager.color(1, 1, 1, 1); + worldrenderer.begin(GL11.GL_TRIANGLES, DefaultVertexFormats.POSITION); + if (accordionToggled) { + worldrenderer.pos((double) x + 6, (double) y + 6, 0.0D).endVertex(); + worldrenderer.pos((double) x + 9.75f, (double) y + 13.5f, 0.0D).endVertex(); + worldrenderer.pos((double) x + 13.5f, (double) y + 6, 0.0D).endVertex(); + } else { + worldrenderer.pos((double) x + 6, (double) y + 13.5f, 0.0D).endVertex(); + worldrenderer.pos((double) x + 13.5f, (double) y + 9.75f, 0.0D).endVertex(); + worldrenderer.pos((double) x + 6, (double) y + 6, 0.0D).endVertex(); + } + tessellator.draw(); + GlStateManager.enableTexture2D(); + GlStateManager.disableBlend(); - TextRenderUtils.drawStringScaledMaxWidth(option.name, Minecraft.getMinecraft().fontRendererObj, - x+18, y+6, false, width-10, 0xc0c0c0); - } + TextRenderUtils.drawStringScaledMaxWidth(option.name, Minecraft.getMinecraft().fontRendererObj, + x + 18, y + 6, false, width - 10, 0xc0c0c0 + ); + } - @Override - public boolean mouseInput(int x, int y, int width, int mouseX, int mouseY) { - if(Mouse.getEventButtonState() && mouseX > x && mouseX < x+ width && - mouseY > y && mouseY < y+getHeight()) { - accordionToggled = !accordionToggled; - return true; - } + @Override + public boolean mouseInput(int x, int y, int width, int mouseX, int mouseY) { + if (Mouse.getEventButtonState() && mouseX > x && mouseX < x + width && + mouseY > y && mouseY < y + getHeight()) { + accordionToggled = !accordionToggled; + return true; + } - return false; - } + return false; + } - @Override - public boolean keyboardInput() { - return false; - } + @Override + public boolean keyboardInput() { + return false; + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorBoolean.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorBoolean.java index ba2c9be974..9e2c912a2e 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorBoolean.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorBoolean.java @@ -4,35 +4,34 @@ import io.github.moulberry.notenoughupdates.core.config.struct.ConfigProcessor; public class GuiOptionEditorBoolean extends GuiOptionEditor { - - private final GuiElementBoolean bool; - - public GuiOptionEditorBoolean(ConfigProcessor.ProcessedOption option) { - super(option); - - bool = new GuiElementBoolean(0, 0, (boolean)option.get(), 10, option::set); - } - - @Override - public void render(int x, int y, int width) { - super.render(x, y, width); - int height = getHeight(); - - bool.x = x+width/6-24; - bool.y = y+height-7-14; - bool.render(); - } - - @Override - public boolean mouseInput(int x, int y, int width, int mouseX, int mouseY) { - int height = getHeight(); - bool.x = x+width/6-24; - bool.y = y+height-7-14; - return bool.mouseInput(mouseX, mouseY); - } - - @Override - public boolean keyboardInput() { - return false; - } + private final GuiElementBoolean bool; + + public GuiOptionEditorBoolean(ConfigProcessor.ProcessedOption option) { + super(option); + + bool = new GuiElementBoolean(0, 0, (boolean) option.get(), 10, option::set); + } + + @Override + public void render(int x, int y, int width) { + super.render(x, y, width); + int height = getHeight(); + + bool.x = x + width / 6 - 24; + bool.y = y + height - 7 - 14; + bool.render(); + } + + @Override + public boolean mouseInput(int x, int y, int width, int mouseX, int mouseY) { + int height = getHeight(); + bool.x = x + width / 6 - 24; + bool.y = y + height - 7 - 14; + return bool.mouseInput(mouseX, mouseY); + } + + @Override + public boolean keyboardInput() { + return false; + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorButton.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorButton.java index 03a01ef27f..76944efad7 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorButton.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorButton.java @@ -1,66 +1,68 @@ package io.github.moulberry.notenoughupdates.core.config.gui; -import io.github.moulberry.notenoughupdates.core.ChromaColour; import io.github.moulberry.notenoughupdates.core.config.Config; import io.github.moulberry.notenoughupdates.core.config.struct.ConfigProcessor; import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils; import io.github.moulberry.notenoughupdates.core.util.render.TextRenderUtils; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GlStateManager; -import net.minecraftforge.client.ClientCommandHandler; import org.lwjgl.input.Mouse; import static io.github.moulberry.notenoughupdates.util.GuiTextures.button_tex; -import static io.github.moulberry.notenoughupdates.util.GuiTextures.button_white; public class GuiOptionEditorButton extends GuiOptionEditor { + private final int runnableId; + private String buttonText; + private final Config config; - private int runnableId; - private String buttonText; - private Config config; + public GuiOptionEditorButton( + ConfigProcessor.ProcessedOption option, + int runnableId, + String buttonText, + Config config + ) { + super(option); + this.runnableId = runnableId; + this.config = config; - public GuiOptionEditorButton(ConfigProcessor.ProcessedOption option, int runnableId, String buttonText, Config config) { - super(option); - this.runnableId = runnableId; - this.config = config; + this.buttonText = buttonText; + if (this.buttonText != null && this.buttonText.isEmpty()) this.buttonText = null; + } - this.buttonText = buttonText; - if(this.buttonText != null && this.buttonText.isEmpty()) this.buttonText = null; - } + @Override + public void render(int x, int y, int width) { + super.render(x, y, width); - @Override - public void render(int x, int y, int width) { - super.render(x, y, width); + int height = getHeight(); - int height = getHeight(); + GlStateManager.color(1, 1, 1, 1); + Minecraft.getMinecraft().getTextureManager().bindTexture(button_tex); + RenderUtils.drawTexturedRect(x + width / 6 - 24, y + height - 7 - 14, 48, 16); - GlStateManager.color(1, 1, 1, 1); - Minecraft.getMinecraft().getTextureManager().bindTexture(button_tex); - RenderUtils.drawTexturedRect(x+width/6-24, y+height-7-14, 48, 16); + if (buttonText != null) { + TextRenderUtils.drawStringCenteredScaledMaxWidth(buttonText, Minecraft.getMinecraft().fontRendererObj, + x + width / 6, y + height - 7 - 6, + false, 44, 0xFF303030 + ); + } + } - if(buttonText != null) { - TextRenderUtils.drawStringCenteredScaledMaxWidth(buttonText, Minecraft.getMinecraft().fontRendererObj, - x+width/6, y+height-7-6, - false, 44, 0xFF303030); - } - } + @Override + public boolean mouseInput(int x, int y, int width, int mouseX, int mouseY) { + if (Mouse.getEventButtonState()) { + int height = getHeight(); + if (mouseX > x + width / 6 - 24 && mouseX < x + width / 6 + 24 && + mouseY > y + height - 7 - 14 && mouseY < y + height - 7 + 2) { + config.executeRunnable(runnableId); + return true; + } + } - @Override - public boolean mouseInput(int x, int y, int width, int mouseX, int mouseY) { - if(Mouse.getEventButtonState()) { - int height = getHeight(); - if(mouseX > x+width/6-24 && mouseX < x+width/6+24 && - mouseY > y+height-7-14 && mouseY < y+height-7+2) { - config.executeRunnable(runnableId); - return true; - } - } + return false; + } - return false; - } - - @Override - public boolean keyboardInput() { - return false; - } + @Override + public boolean keyboardInput() { + return false; + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorColour.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorColour.java index d9e8f5a91e..80d2af4246 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorColour.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorColour.java @@ -1,81 +1,69 @@ package io.github.moulberry.notenoughupdates.core.config.gui; import io.github.moulberry.notenoughupdates.core.ChromaColour; -import io.github.moulberry.notenoughupdates.core.GlScissorStack; -import io.github.moulberry.notenoughupdates.core.GuiElementBoolean; import io.github.moulberry.notenoughupdates.core.GuiElementColour; import io.github.moulberry.notenoughupdates.core.config.struct.ConfigProcessor; import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GlStateManager; import org.lwjgl.input.Mouse; -import org.lwjgl.opengl.GL11; -import static io.github.moulberry.notenoughupdates.util.GuiTextures.*; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.button_white; public class GuiOptionEditorColour extends GuiOptionEditor { - - private String chromaColour; - private GuiElementColour colourElement = null; - - public GuiOptionEditorColour(ConfigProcessor.ProcessedOption option) { - super(option); - - this.chromaColour = (String)option.get(); - } - - @Override - public void render(int x, int y, int width) { - super.render(x, y, width); - int height = getHeight(); - - int argb = ChromaColour.specialToChromaRGB(chromaColour); - int r = (argb >> 16) & 0xFF; - int g = (argb >> 8) & 0xFF; - int b = argb & 0xFF; - GlStateManager.color(r/255f, g/255f, b/255f, 1); - Minecraft.getMinecraft().getTextureManager().bindTexture(button_white); - RenderUtils.drawTexturedRect(x+width/6-24, y+height-7-14, 48, 16); - } - - @Override - public void renderOverlay(int x, int y, int width) { - if(colourElement != null) { - colourElement.render(); - } - } - - @Override - public boolean mouseInputOverlay(int x, int y, int width, int mouseX, int mouseY) { - if(colourElement != null && colourElement.mouseInput(mouseX, mouseY)) { - return true; - } - return false; - } - - @Override - public boolean mouseInput(int x, int y, int width, int mouseX, int mouseY) { - int height = getHeight(); - - if(Mouse.getEventButtonState() && Mouse.getEventButton() == 0 && - mouseX > x+width/6-24 && mouseX < x+width/6+24 && - mouseY > y+height-7-14 && mouseY < y+height-7+2) { - colourElement = new GuiElementColour(mouseX, mouseY, (String) option.get(), (val) -> { - option.set(val); - chromaColour = val; - }, () -> colourElement = null); - } - - return false; - } - - @Override - public boolean keyboardInput() { - if(colourElement != null && colourElement.keyboardInput()) { - return true; - } - - return false; - } - + private String chromaColour; + private GuiElementColour colourElement = null; + + public GuiOptionEditorColour(ConfigProcessor.ProcessedOption option) { + super(option); + + this.chromaColour = (String) option.get(); + } + + @Override + public void render(int x, int y, int width) { + super.render(x, y, width); + int height = getHeight(); + + int argb = ChromaColour.specialToChromaRGB(chromaColour); + int r = (argb >> 16) & 0xFF; + int g = (argb >> 8) & 0xFF; + int b = argb & 0xFF; + GlStateManager.color(r / 255f, g / 255f, b / 255f, 1); + Minecraft.getMinecraft().getTextureManager().bindTexture(button_white); + RenderUtils.drawTexturedRect(x + width / 6 - 24, y + height - 7 - 14, 48, 16); + } + + @Override + public void renderOverlay(int x, int y, int width) { + if (colourElement != null) { + colourElement.render(); + } + } + + @Override + public boolean mouseInputOverlay(int x, int y, int width, int mouseX, int mouseY) { + return colourElement != null && colourElement.mouseInput(mouseX, mouseY); + } + + @Override + public boolean mouseInput(int x, int y, int width, int mouseX, int mouseY) { + int height = getHeight(); + + if (Mouse.getEventButtonState() && Mouse.getEventButton() == 0 && + mouseX > x + width / 6 - 24 && mouseX < x + width / 6 + 24 && + mouseY > y + height - 7 - 14 && mouseY < y + height - 7 + 2) { + colourElement = new GuiElementColour(mouseX, mouseY, (String) option.get(), (val) -> { + option.set(val); + chromaColour = val; + }, () -> colourElement = null); + } + + return false; + } + + @Override + public boolean keyboardInput() { + return colourElement != null && colourElement.keyboardInput(); + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorDraggableList.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorDraggableList.java index 03c5bc6cc5..08a1024f90 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorDraggableList.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorDraggableList.java @@ -1,6 +1,5 @@ package io.github.moulberry.notenoughupdates.core.config.gui; -import io.github.moulberry.notenoughupdates.core.config.Config; import io.github.moulberry.notenoughupdates.core.config.struct.ConfigProcessor; import io.github.moulberry.notenoughupdates.core.util.lerp.LerpUtils; import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils; @@ -13,7 +12,6 @@ import net.minecraft.client.renderer.GlStateManager; import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.ResourceLocation; -import org.lwjgl.input.Keyboard; import org.lwjgl.input.Mouse; import org.lwjgl.opengl.GL11; @@ -23,269 +21,292 @@ import static io.github.moulberry.notenoughupdates.util.GuiTextures.button_tex; public class GuiOptionEditorDraggableList extends GuiOptionEditor { - - private static final ResourceLocation DELETE = new ResourceLocation("notenoughupdates:core/delete.png"); - - private String[] exampleText; - private List activeText; - private int currentDragging = -1; - private int dragStartIndex = -1; - - private long trashHoverTime = -1; - - private int dragOffsetX = -1; - private int dragOffsetY = -1; - - private boolean dropdownOpen = false; - - public GuiOptionEditorDraggableList(ConfigProcessor.ProcessedOption option, String[] exampleText) { - super(option); - - this.exampleText = exampleText; - this.activeText = (List) option.get(); - } - - @Override - public int getHeight() { - int height = super.getHeight() + 13; - - for(int strIndex : activeText) { - String str = exampleText[strIndex]; - height += 10 * str.split("\n").length; - } - - return height; - } - - @Override - public void render(int x, int y, int width) { - super.render(x, y, width); - - int height = getHeight(); - - GlStateManager.color(1, 1, 1, 1); - Minecraft.getMinecraft().getTextureManager().bindTexture(button_tex); - RenderUtils.drawTexturedRect(x+width/6-24, y+45-7-14, 48, 16); - - TextRenderUtils.drawStringCenteredScaledMaxWidth("Add", Minecraft.getMinecraft().fontRendererObj, - x+width/6, y+45-7-6, - false, 44, 0xFF303030); - - long currentTime = System.currentTimeMillis(); - if(trashHoverTime < 0) { - float greenBlue = LerpUtils.clampZeroOne((currentTime + trashHoverTime)/250f); - GlStateManager.color(1, greenBlue, greenBlue, 1); - } else { - float greenBlue = LerpUtils.clampZeroOne((250 + trashHoverTime - currentTime)/250f); - GlStateManager.color(1, greenBlue, greenBlue, 1); - } - Minecraft.getMinecraft().getTextureManager().bindTexture(DELETE); - Utils.drawTexturedRect(x+width/6+27, y+45-7-13, 11, 14, GL11.GL_NEAREST); - - Gui.drawRect(x+5, y+45, x+width-5, y+height-5, 0xffdddddd); - Gui.drawRect(x+6, y+46, x+width-6, y+height-6, 0xff000000); - - int i = 0; - int yOff=0; - for(int strIndex : activeText) { - String str = exampleText[strIndex]; - - String[] multilines = str.split("\n"); - - int ySize = multilines.length * 10; - - if(i++ != dragStartIndex) { - for(int multilineIndex=0; multilineIndex remaining = new ArrayList<>(); - for(int i=0; i= 0) { - int opacity = 0x80; - long currentTime = System.currentTimeMillis(); - if(trashHoverTime < 0) { - float greenBlue = LerpUtils.clampZeroOne((currentTime + trashHoverTime)/250f); - opacity = (int)(opacity * greenBlue); - } else { - float greenBlue = LerpUtils.clampZeroOne((250 + trashHoverTime - currentTime)/250f); - opacity = (int)(opacity * greenBlue); - } - - if(opacity < 20) return; - - ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); - int mouseX = Mouse.getX() * scaledResolution.getScaledWidth() / Minecraft.getMinecraft().displayWidth; - int mouseY = scaledResolution.getScaledHeight() - Mouse.getY() * scaledResolution.getScaledHeight() / Minecraft.getMinecraft().displayHeight - 1; - - String str = exampleText[currentDragging]; - - String[] multilines = str.split("\n"); - - GlStateManager.enableBlend(); - for(int multilineIndex=0; multilineIndex= 0 && Mouse.getEventButton() == 0 && - mouseX >= x+width/6+27-3 && mouseX <= x+width/6+27+11+3 && - mouseY >= y+45-7-13-3 && mouseY <= y+45-7-13+14+3) { - activeText.remove(dragStartIndex); - currentDragging = -1; - dragStartIndex = -1; - return false; - } - - if(!Mouse.isButtonDown(0) || dropdownOpen) { - currentDragging = -1; - dragStartIndex = -1; - if(trashHoverTime > 0) trashHoverTime = -System.currentTimeMillis(); - } else if(currentDragging >= 0 && - mouseX >= x+width/6+27-3 && mouseX <= x+width/6+27+11+3 && - mouseY >= y+45-7-13-3 && mouseY <= y+45-7-13+14+3) { - if(trashHoverTime < 0) trashHoverTime = System.currentTimeMillis(); - } else { - if(trashHoverTime > 0) trashHoverTime = -System.currentTimeMillis(); - } - - if(Mouse.getEventButtonState()) { - int height = getHeight(); - - if(dropdownOpen) { - List remaining = new ArrayList<>(); - for(int i=0; i left && mouseX < left+dropdownWidth && - mouseY > top && mouseY < top + dropdownHeight) { - int dropdownY = -1; - for(int strIndex : remaining) { - if(mouseY < top+dropdownY+12) { - activeText.add(0, strIndex); - if(remaining.size() == 1) dropdownOpen = false; - return true; - } - - dropdownY += 12; - } - } - - dropdownOpen = false; - return true; - } - - if(activeText.size() < exampleText.length && - mouseX > x+width/6-24 && mouseX < x+width/6+24 && - mouseY > y+45-7-14 && mouseY < y+45-7+2) { - dropdownOpen = !dropdownOpen; - dragOffsetX = mouseX; - dragOffsetY = mouseY; - return true; - } - - if(Mouse.getEventButton() == 0 && - mouseX > x+5 && mouseX < x+width-5 && - mouseY > y+45 && mouseY < y+height-6) { - int yOff=0; - int i = 0; - for(int strIndex : activeText) { - int ySize = 10 * exampleText[strIndex].split("\n").length; - if(mouseY < y+50+yOff+ySize) { - dragOffsetX = x+10 - mouseX; - dragOffsetY = y+50+yOff - mouseY; - - currentDragging = strIndex; - dragStartIndex = i; - break; - } - yOff += ySize; - i++; - } - } - } else if(Mouse.getEventButton() == -1 && currentDragging >= 0) { - int yOff=0; - int i = 0; - for(int strIndex : activeText) { - if(dragOffsetY + mouseY + 4 < y+50+yOff+10) { - activeText.remove(dragStartIndex); - activeText.add(i, currentDragging); - - dragStartIndex = i; - break; - } - yOff += 10 * exampleText[strIndex].split("\n").length; - i++; - } - } - - return false; - } - - @Override - public boolean keyboardInput() { - return false; - } + private static final ResourceLocation DELETE = new ResourceLocation("notenoughupdates:core/delete.png"); + + private final String[] exampleText; + private final List activeText; + private int currentDragging = -1; + private int dragStartIndex = -1; + + private long trashHoverTime = -1; + + private int dragOffsetX = -1; + private int dragOffsetY = -1; + + private boolean dropdownOpen = false; + + public GuiOptionEditorDraggableList(ConfigProcessor.ProcessedOption option, String[] exampleText) { + super(option); + + this.exampleText = exampleText; + this.activeText = (List) option.get(); + } + + @Override + public int getHeight() { + int height = super.getHeight() + 13; + + for (int strIndex : activeText) { + String str = exampleText[strIndex]; + height += 10 * str.split("\n").length; + } + + return height; + } + + @Override + public void render(int x, int y, int width) { + super.render(x, y, width); + + int height = getHeight(); + + GlStateManager.color(1, 1, 1, 1); + Minecraft.getMinecraft().getTextureManager().bindTexture(button_tex); + RenderUtils.drawTexturedRect(x + width / 6 - 24, y + 45 - 7 - 14, 48, 16); + + TextRenderUtils.drawStringCenteredScaledMaxWidth("Add", Minecraft.getMinecraft().fontRendererObj, + x + width / 6, y + 45 - 7 - 6, + false, 44, 0xFF303030 + ); + + long currentTime = System.currentTimeMillis(); + if (trashHoverTime < 0) { + float greenBlue = LerpUtils.clampZeroOne((currentTime + trashHoverTime) / 250f); + GlStateManager.color(1, greenBlue, greenBlue, 1); + } else { + float greenBlue = LerpUtils.clampZeroOne((250 + trashHoverTime - currentTime) / 250f); + GlStateManager.color(1, greenBlue, greenBlue, 1); + } + Minecraft.getMinecraft().getTextureManager().bindTexture(DELETE); + Utils.drawTexturedRect(x + width / 6 + 27, y + 45 - 7 - 13, 11, 14, GL11.GL_NEAREST); + + Gui.drawRect(x + 5, y + 45, x + width - 5, y + height - 5, 0xffdddddd); + Gui.drawRect(x + 6, y + 46, x + width - 6, y + height - 6, 0xff000000); + + int i = 0; + int yOff = 0; + for (int strIndex : activeText) { + String str = exampleText[strIndex]; + + String[] multilines = str.split("\n"); + + int ySize = multilines.length * 10; + + if (i++ != dragStartIndex) { + for (int multilineIndex = 0; multilineIndex < multilines.length; multilineIndex++) { + String line = multilines[multilineIndex]; + Utils.drawStringScaledMaxWidth(line + EnumChatFormatting.RESET, Minecraft.getMinecraft().fontRendererObj, + x + 20, y + 50 + yOff + multilineIndex * 10, true, width - 20, 0xffffffff + ); + } + Minecraft.getMinecraft().fontRendererObj.drawString( + "\u2261", + x + 10, + y + 50 + yOff + ySize / 2 - 4, + 0xffffff, + true + ); + } + + yOff += ySize; + } + } + + @Override + public void renderOverlay(int x, int y, int width) { + super.renderOverlay(x, y, width); + + if (dropdownOpen) { + List remaining = new ArrayList<>(); + for (int i = 0; i < exampleText.length; i++) { + remaining.add(i); + } + remaining.removeAll(activeText); + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + int dropdownWidth = Math.min(width / 2 - 10, 150); + int left = dragOffsetX; + int top = dragOffsetY; + + int dropdownHeight = -1 + 12 * remaining.size(); + + int main = 0xff202026; + int outline = 0xff404046; + Gui.drawRect(left, top, left + 1, top + dropdownHeight, outline); //Left + Gui.drawRect(left + 1, top, left + dropdownWidth, top + 1, outline); //Top + Gui.drawRect(left + dropdownWidth - 1, top + 1, left + dropdownWidth, top + dropdownHeight, outline); //Right + Gui.drawRect( + left + 1, + top + dropdownHeight - 1, + left + dropdownWidth - 1, + top + dropdownHeight, + outline + ); //Bottom + Gui.drawRect(left + 1, top + 1, left + dropdownWidth - 1, top + dropdownHeight - 1, main); //Middle + + int dropdownY = -1; + for (int strIndex : remaining) { + String str = exampleText[strIndex]; + if (str.isEmpty()) { + str = ""; + } + TextRenderUtils.drawStringScaledMaxWidth(str.replaceAll("(\n.*)+", " ..."), + fr, left + 3, top + 3 + dropdownY, false, dropdownWidth - 6, 0xffa0a0a0 + ); + dropdownY += 12; + } + } else if (currentDragging >= 0) { + int opacity = 0x80; + long currentTime = System.currentTimeMillis(); + if (trashHoverTime < 0) { + float greenBlue = LerpUtils.clampZeroOne((currentTime + trashHoverTime) / 250f); + opacity = (int) (opacity * greenBlue); + } else { + float greenBlue = LerpUtils.clampZeroOne((250 + trashHoverTime - currentTime) / 250f); + opacity = (int) (opacity * greenBlue); + } + + if (opacity < 20) return; + + ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + int mouseX = Mouse.getX() * scaledResolution.getScaledWidth() / Minecraft.getMinecraft().displayWidth; + int mouseY = scaledResolution.getScaledHeight() - + Mouse.getY() * scaledResolution.getScaledHeight() / Minecraft.getMinecraft().displayHeight - 1; + + String str = exampleText[currentDragging]; + + String[] multilines = str.split("\n"); + + GlStateManager.enableBlend(); + for (int multilineIndex = 0; multilineIndex < multilines.length; multilineIndex++) { + String line = multilines[multilineIndex]; + Utils.drawStringScaledMaxWidth( + line + EnumChatFormatting.RESET, + Minecraft.getMinecraft().fontRendererObj, + dragOffsetX + mouseX + 10, + dragOffsetY + mouseY + multilineIndex * 10, + true, + width - 20, + 0xffffff | (opacity << 24) + ); + } + + int ySize = multilines.length * 10; + + Minecraft.getMinecraft().fontRendererObj.drawString("\u2261", + dragOffsetX + mouseX, + dragOffsetY + mouseY + ySize / 2 - 4, 0xffffff, true + ); + } + } + + @Override + public boolean mouseInput(int x, int y, int width, int mouseX, int mouseY) { + if (!Mouse.getEventButtonState() && !dropdownOpen && + dragStartIndex >= 0 && Mouse.getEventButton() == 0 && + mouseX >= x + width / 6 + 27 - 3 && mouseX <= x + width / 6 + 27 + 11 + 3 && + mouseY >= y + 45 - 7 - 13 - 3 && mouseY <= y + 45 - 7 - 13 + 14 + 3) { + activeText.remove(dragStartIndex); + currentDragging = -1; + dragStartIndex = -1; + return false; + } + + if (!Mouse.isButtonDown(0) || dropdownOpen) { + currentDragging = -1; + dragStartIndex = -1; + if (trashHoverTime > 0) trashHoverTime = -System.currentTimeMillis(); + } else if (currentDragging >= 0 && + mouseX >= x + width / 6 + 27 - 3 && mouseX <= x + width / 6 + 27 + 11 + 3 && + mouseY >= y + 45 - 7 - 13 - 3 && mouseY <= y + 45 - 7 - 13 + 14 + 3) { + if (trashHoverTime < 0) trashHoverTime = System.currentTimeMillis(); + } else { + if (trashHoverTime > 0) trashHoverTime = -System.currentTimeMillis(); + } + + if (Mouse.getEventButtonState()) { + int height = getHeight(); + + if (dropdownOpen) { + List remaining = new ArrayList<>(); + for (int i = 0; i < exampleText.length; i++) { + remaining.add(i); + } + remaining.removeAll(activeText); + + int dropdownWidth = Math.min(width / 2 - 10, 150); + int left = dragOffsetX; + int top = dragOffsetY; + + int dropdownHeight = -1 + 12 * remaining.size(); + + if (mouseX > left && mouseX < left + dropdownWidth && + mouseY > top && mouseY < top + dropdownHeight) { + int dropdownY = -1; + for (int strIndex : remaining) { + if (mouseY < top + dropdownY + 12) { + activeText.add(0, strIndex); + if (remaining.size() == 1) dropdownOpen = false; + return true; + } + + dropdownY += 12; + } + } + + dropdownOpen = false; + return true; + } + + if (activeText.size() < exampleText.length && + mouseX > x + width / 6 - 24 && mouseX < x + width / 6 + 24 && + mouseY > y + 45 - 7 - 14 && mouseY < y + 45 - 7 + 2) { + dropdownOpen = !dropdownOpen; + dragOffsetX = mouseX; + dragOffsetY = mouseY; + return true; + } + + if (Mouse.getEventButton() == 0 && + mouseX > x + 5 && mouseX < x + width - 5 && + mouseY > y + 45 && mouseY < y + height - 6) { + int yOff = 0; + int i = 0; + for (int strIndex : activeText) { + int ySize = 10 * exampleText[strIndex].split("\n").length; + if (mouseY < y + 50 + yOff + ySize) { + dragOffsetX = x + 10 - mouseX; + dragOffsetY = y + 50 + yOff - mouseY; + + currentDragging = strIndex; + dragStartIndex = i; + break; + } + yOff += ySize; + i++; + } + } + } else if (Mouse.getEventButton() == -1 && currentDragging >= 0) { + int yOff = 0; + int i = 0; + for (int strIndex : activeText) { + if (dragOffsetY + mouseY + 4 < y + 50 + yOff + 10) { + activeText.remove(dragStartIndex); + activeText.add(i, currentDragging); + + dragStartIndex = i; + break; + } + yOff += 10 * exampleText[strIndex].split("\n").length; + i++; + } + } + + return false; + } + + @Override + public boolean keyboardInput() { + return false; + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorDropdown.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorDropdown.java index 0451b4590a..a17737e3a7 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorDropdown.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorDropdown.java @@ -11,142 +11,173 @@ import org.lwjgl.opengl.GL11; public class GuiOptionEditorDropdown extends GuiOptionEditor { - - private final String[] values; - private final boolean useOrdinal; - private int selected; - private boolean open = false; - - public GuiOptionEditorDropdown(ConfigProcessor.ProcessedOption option, String[] values, int selected, boolean useOrdinal) { - super(option); - if(selected >= values.length) selected = values.length; - this.values = values; - this.selected = selected; - this.useOrdinal = useOrdinal; - } - - @Override - public void render(int x, int y, int width) { - super.render(x, y, width); - - if(!open) { - int height = getHeight(); - - FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; - int dropdownWidth = Math.min(width/3-10, 80); - int left = x+width/6-dropdownWidth/2; - int top = y+height-7-14; - - String selectedString = " - Select - "; - if(selected >= 0 && selected < values.length) { - selectedString = values[selected]; - } - - RenderUtils.drawFloatingRectDark(left, top, dropdownWidth, 14, false); - TextRenderUtils.drawStringScaled("\u25BC", fr, left+dropdownWidth-10, y+height-7-15, false, 0xffa0a0a0, 2); - - TextRenderUtils.drawStringScaledMaxWidth(selectedString, fr, left+3, top+3, false, - dropdownWidth-16, 0xffa0a0a0); - } - } - - @Override - public void renderOverlay(int x, int y, int width) { - if(open) { - String selectedString = " - Select - "; - if(selected >= 0 && selected < values.length) { - selectedString = values[selected]; - } - - int height = getHeight(); - - FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; - int dropdownWidth = Math.min(width/3-10, 80); - int left = x+width/6-dropdownWidth/2; - int top = y+height-7-14; - - int dropdownHeight = 13 + 12*values.length; - - int main = 0xff202026; - int blue = 0xff2355ad; - Gui.drawRect(left, top, left+1, top+dropdownHeight, blue); //Left - Gui.drawRect(left+1, top, left+dropdownWidth, top+1, blue); //Top - Gui.drawRect(left+dropdownWidth-1, top+1, left+dropdownWidth, top+dropdownHeight, blue); //Right - Gui.drawRect(left+1, top+dropdownHeight-1, left+dropdownWidth-1, top+dropdownHeight, blue); //Bottom - Gui.drawRect(left+1, top+1, left+dropdownWidth-1, top+dropdownHeight-1, main); //Middle - - Gui.drawRect(left+1, top+14-1, left+dropdownWidth-1, top+14, blue); //Bar - - int dropdownY = 13; - for(String option : values) { - if(option.isEmpty()) { - option = ""; - } - TextRenderUtils.drawStringScaledMaxWidth(option, fr, left+3, top+3+dropdownY, false, dropdownWidth-6, 0xffa0a0a0); - dropdownY += 12; - } - - TextRenderUtils.drawStringScaled("\u25B2", fr, left+dropdownWidth-10, y+height-7-15, false, 0xffa0a0a0, 2); - - - TextRenderUtils.drawStringScaledMaxWidth(selectedString, fr, left+3, top+3, false, - dropdownWidth-16, 0xffa0a0a0); - } - } - - @Override - public boolean mouseInput(int x, int y, int width, int mouseX, int mouseY) { - int height = getHeight(); - - int left = x+width/6-40; - int top = y+height-7-14; - - if(Mouse.getEventButtonState() && Mouse.getEventButton() == 0) { - if(mouseX >= left && mouseX <= left+80 && - mouseY >= top && mouseY <= top+14) { - open = !open; - return true; - } - } - - return false; - } - - @Override - public boolean mouseInputOverlay(int x, int y, int width, int mouseX, int mouseY) { - int height = getHeight(); - - int left = x+width/6-40; - int top = y+height-7-14; - - if(Mouse.getEventButtonState() && Mouse.getEventButton() == 0) { - if(!(mouseX >= left && mouseX <= left+80 && - mouseY >= top && mouseY <= top+14) && open) { - open = false; - if(mouseX >= left && mouseX <= left+80) { - int dropdownY = 13; - for(int ordinal=0; ordinal < values.length; ordinal++) { - if(mouseY >= top+3+dropdownY && mouseY <= top+3+dropdownY+12) { - selected = ordinal; - if(useOrdinal) { - option.set(selected); - } else { - option.set(values[selected]); - } - return true; - } - dropdownY += 12; - } - } - return true; - } - } - - return false; - } - - @Override - public boolean keyboardInput() { - return false; - } + private final String[] values; + private final boolean useOrdinal; + private int selected; + private boolean open = false; + + public GuiOptionEditorDropdown( + ConfigProcessor.ProcessedOption option, + String[] values, + int selected, + boolean useOrdinal + ) { + super(option); + if (selected >= values.length) selected = values.length; + this.values = values; + this.selected = selected; + this.useOrdinal = useOrdinal; + } + + @Override + public void render(int x, int y, int width) { + super.render(x, y, width); + if (!open) { + int height = getHeight(); + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + int dropdownWidth = Math.min(width / 3 - 10, 80); + int left = x + width / 6 - dropdownWidth / 2; + int top = y + height - 7 - 14; + + String selectedString = " - Select - "; + if (selected >= 0 && selected < values.length) { + selectedString = values[selected]; + } + + RenderUtils.drawFloatingRectDark(left, top, dropdownWidth, 14, false); + TextRenderUtils.drawStringScaled( + "\u25BC", + fr, + left + dropdownWidth - 10, + y + height - 7 - 15, + false, + 0xffa0a0a0, + 2 + ); + + TextRenderUtils.drawStringScaledMaxWidth(selectedString, fr, left + 3, top + 3, false, + dropdownWidth - 16, 0xffa0a0a0 + ); + } + } + + @Override + public void renderOverlay(int x, int y, int width) { + if (open) { + String selectedString = " - Select - "; + if (selected >= 0 && selected < values.length) { + selectedString = values[selected]; + } + + int height = getHeight(); + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + int dropdownWidth = Math.min(width / 3 - 10, 80); + int left = x + width / 6 - dropdownWidth / 2; + int top = y + height - 7 - 14; + + int dropdownHeight = 13 + 12 * values.length; + + int main = 0xff202026; + int blue = 0xff2355ad; + + GlStateManager.pushMatrix(); + GL11.glTranslated(0, 0, 100); + Gui.drawRect(left, top, left + 1, top + dropdownHeight, blue); //Left + Gui.drawRect(left + 1, top, left + dropdownWidth, top + 1, blue); //Top + Gui.drawRect(left + dropdownWidth - 1, top + 1, left + dropdownWidth, top + dropdownHeight, blue); //Right + Gui.drawRect(left + 1, top + dropdownHeight - 1, left + dropdownWidth - 1, top + dropdownHeight, blue); //Bottom + Gui.drawRect(left + 1, top + 1, left + dropdownWidth - 1, top + dropdownHeight - 1, main); //Middle + + Gui.drawRect(left + 1, top + 14 - 1, left + dropdownWidth - 1, top + 14, blue); //Bar + int dropdownY = 13; + for (String option : values) { + if (option.isEmpty()) { + option = ""; + } + TextRenderUtils.drawStringScaledMaxWidth( + option, + fr, + left + 3, + top + 3 + dropdownY, + false, + dropdownWidth - 6, + 0xffa0a0a0 + ); + dropdownY += 12; + } + + TextRenderUtils.drawStringScaled( + "\u25B2", + fr, + left + dropdownWidth - 10, + y + height - 7 - 15, + false, + 0xffa0a0a0, + 2 + ); + + TextRenderUtils.drawStringScaledMaxWidth(selectedString, fr, left + 3, top + 3, false, + dropdownWidth - 16, 0xffa0a0a0 + ); + GlStateManager.popMatrix(); + } + } + + @Override + public boolean mouseInput(int x, int y, int width, int mouseX, int mouseY) { + int height = getHeight(); + + int left = x + width / 6 - 40; + int top = y + height - 7 - 14; + + if (Mouse.getEventButtonState() && Mouse.getEventButton() == 0) { + if (mouseX >= left && mouseX <= left + 80 && + mouseY >= top && mouseY <= top + 14) { + open = !open; + return true; + } + } + + return false; + } + + @Override + public boolean mouseInputOverlay(int x, int y, int width, int mouseX, int mouseY) { + int height = getHeight(); + + int left = x + width / 6 - 40; + int top = y + height - 7 - 14; + + if (Mouse.getEventButtonState() && Mouse.getEventButton() == 0) { + if (!(mouseX >= left && mouseX <= left + 80 && + mouseY >= top && mouseY <= top + 14) && open) { + open = false; + if (mouseX >= left && mouseX <= left + 80) { + int dropdownY = 13; + for (int ordinal = 0; ordinal < values.length; ordinal++) { + if (mouseY >= top + 3 + dropdownY && mouseY <= top + 3 + dropdownY + 12) { + selected = ordinal; + if (useOrdinal) { + option.set(selected); + } else { + option.set(values[selected]); + } + return true; + } + dropdownY += 12; + } + } + return true; + } + } + + return false; + } + + @Override + public boolean keyboardInput() { + return false; + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorFSR.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorFSR.java new file mode 100644 index 0000000000..b443b5f66d --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorFSR.java @@ -0,0 +1,63 @@ +package io.github.moulberry.notenoughupdates.core.config.gui; + +import io.github.moulberry.notenoughupdates.core.config.Config; +import io.github.moulberry.notenoughupdates.core.config.struct.ConfigProcessor; +import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils; +import io.github.moulberry.notenoughupdates.core.util.render.TextRenderUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GlStateManager; +import org.lwjgl.input.Mouse; + +import static io.github.moulberry.notenoughupdates.util.GuiTextures.button_fsr; + +public class GuiOptionEditorFSR extends GuiOptionEditor { + private final int runnableId; + private String buttonText; + private final Config config; + + public GuiOptionEditorFSR(ConfigProcessor.ProcessedOption option, int runnableId, String buttonText, Config config) { + super(option); + this.runnableId = runnableId; + this.config = config; + + this.buttonText = buttonText; + if (this.buttonText != null && this.buttonText.isEmpty()) this.buttonText = null; + } + + @Override + public void render(int x, int y, int width) { + super.render(x, y, width); + + int height = getHeight(); + + GlStateManager.color(1, 1, 1, 1); + Minecraft.getMinecraft().getTextureManager().bindTexture(button_fsr); + RenderUtils.drawTexturedRect(x + width / 6 - 24, y + height - 7 - 14, 48, 16); + + if (buttonText != null) { + TextRenderUtils.drawStringCenteredScaledMaxWidth(buttonText, Minecraft.getMinecraft().fontRendererObj, + x + width / 6, y + height - 7 - 6, + false, 44, 0xFF303030 + ); + } + } + + @Override + public boolean mouseInput(int x, int y, int width, int mouseX, int mouseY) { + if (Mouse.getEventButtonState()) { + int height = getHeight(); + if (mouseX > x + width / 6 - 24 && mouseX < x + width / 6 + 24 && + mouseY > y + height - 7 - 14 && mouseY < y + height - 7 + 2) { + config.executeRunnable(runnableId); + return true; + } + } + + return false; + } + + @Override + public boolean keyboardInput() { + return false; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorKeybind.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorKeybind.java index 601cc6b11b..5ff961a72c 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorKeybind.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorKeybind.java @@ -1,6 +1,5 @@ package io.github.moulberry.notenoughupdates.core.config.gui; -import io.github.moulberry.notenoughupdates.core.config.Config; import io.github.moulberry.notenoughupdates.core.config.KeybindHelper; import io.github.moulberry.notenoughupdates.core.config.struct.ConfigProcessor; import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils; @@ -15,81 +14,81 @@ import static io.github.moulberry.notenoughupdates.util.GuiTextures.button_tex; public class GuiOptionEditorKeybind extends GuiOptionEditor { + private static final ResourceLocation RESET = new ResourceLocation("notenoughupdates:itemcustomize/reset.png"); - private static final ResourceLocation RESET = new ResourceLocation("notenoughupdates:itemcustomize/reset.png"); + private int keyCode; + private final int defaultKeyCode; + private boolean editingKeycode; - private int keyCode; - private int defaultKeyCode; - private boolean editingKeycode; + public GuiOptionEditorKeybind(ConfigProcessor.ProcessedOption option, int keyCode, int defaultKeyCode) { + super(option); + this.keyCode = keyCode; + this.defaultKeyCode = defaultKeyCode; + } - public GuiOptionEditorKeybind(ConfigProcessor.ProcessedOption option, int keyCode, int defaultKeyCode) { - super(option); - this.keyCode = keyCode; - this.defaultKeyCode = defaultKeyCode; - } + @Override + public void render(int x, int y, int width) { + super.render(x, y, width); - @Override - public void render(int x, int y, int width) { - super.render(x, y, width); + int height = getHeight(); - int height = getHeight(); + GlStateManager.color(1, 1, 1, 1); + Minecraft.getMinecraft().getTextureManager().bindTexture(button_tex); + RenderUtils.drawTexturedRect(x + width / 6 - 24, y + height - 7 - 14, 48, 16); - GlStateManager.color(1, 1, 1, 1); - Minecraft.getMinecraft().getTextureManager().bindTexture(button_tex); - RenderUtils.drawTexturedRect(x+width/6-24, y+height-7-14, 48, 16); + String keyName = KeybindHelper.getKeyName(keyCode); + String text = editingKeycode ? "> " + keyName + " <" : keyName; + TextRenderUtils.drawStringCenteredScaledMaxWidth(text, + Minecraft.getMinecraft().fontRendererObj, + x + width / 6, y + height - 7 - 6, + false, 40, 0xFF303030 + ); - String keyName = KeybindHelper.getKeyName(keyCode); - String text = editingKeycode ? "> "+keyName+" <" : keyName; - TextRenderUtils.drawStringCenteredScaledMaxWidth(text, - Minecraft.getMinecraft().fontRendererObj, - x+width/6, y+height-7-6, - false, 40, 0xFF303030); + Minecraft.getMinecraft().getTextureManager().bindTexture(RESET); + GlStateManager.color(1, 1, 1, 1); + RenderUtils.drawTexturedRect(x + width / 6 - 24 + 48 + 3, y + height - 7 - 14 + 3, 10, 11, GL11.GL_NEAREST); + } - Minecraft.getMinecraft().getTextureManager().bindTexture(RESET); - GlStateManager.color(1, 1, 1, 1); - RenderUtils.drawTexturedRect(x+width/6-24+48+3, y+height-7-14+3, 10, 11, GL11.GL_NEAREST); - } + @Override + public boolean mouseInput(int x, int y, int width, int mouseX, int mouseY) { + if (Mouse.getEventButtonState() && Mouse.getEventButton() != -1 && editingKeycode) { + editingKeycode = false; + keyCode = Mouse.getEventButton() - 100; + option.set(keyCode); + return true; + } - @Override - public boolean mouseInput(int x, int y, int width, int mouseX, int mouseY) { - if(Mouse.getEventButtonState() && Mouse.getEventButton() != -1 && editingKeycode) { - editingKeycode = false; - keyCode = Mouse.getEventButton()-100; - option.set(keyCode); - return true; - } + if (Mouse.getEventButtonState() && Mouse.getEventButton() == 0) { + int height = getHeight(); + if (mouseX > x + width / 6 - 24 && mouseX < x + width / 6 + 24 && + mouseY > y + height - 7 - 14 && mouseY < y + height - 7 + 2) { + editingKeycode = true; + return true; + } + if (mouseX > x + width / 6 - 24 + 48 + 3 && mouseX < x + width / 6 - 24 + 48 + 13 && + mouseY > y + height - 7 - 14 + 3 && mouseY < y + height - 7 - 14 + 3 + 11) { + keyCode = defaultKeyCode; + option.set(keyCode); + return true; + } + } - if(Mouse.getEventButtonState() && Mouse.getEventButton() == 0) { - int height = getHeight(); - if(mouseX > x+width/6-24 && mouseX < x+width/6+24 && - mouseY > y+height-7-14 && mouseY < y+height-7+2) { - editingKeycode = true; - return true; - } - if(mouseX > x+width/6-24+48+3 && mouseX < x+width/6-24+48+13 && - mouseY > y+height-7-14+3 && mouseY < y+height-7-14+3+11) { - keyCode = defaultKeyCode; - option.set(keyCode); - return true; - } - } + return false; + } - return false; - } - - @Override - public boolean keyboardInput() { - if(editingKeycode) { - editingKeycode = false; - if(Keyboard.getEventKey() == Keyboard.KEY_ESCAPE) { - keyCode = 0; - } else if(Keyboard.getEventKey() != 0) { - keyCode = Keyboard.getEventKey(); - } - if(keyCode > 256) keyCode = 0; - option.set(keyCode); - return true; - } - return false; - } + @Override + public boolean keyboardInput() { + if (editingKeycode) { + editingKeycode = false; + if (Keyboard.getEventKey() == Keyboard.KEY_ESCAPE) { + keyCode = 0; + } else if (Keyboard.getEventKey() != 0) { + keyCode = Keyboard.getEventKey(); + } + if (keyCode > 256) keyCode = 0; + option.set(keyCode); + return true; + } + return false; + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorSlider.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorSlider.java index a3665436f9..45ae70d96c 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorSlider.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorSlider.java @@ -1,6 +1,5 @@ package io.github.moulberry.notenoughupdates.core.config.gui; -import io.github.moulberry.notenoughupdates.core.GuiElementBoolean; import io.github.moulberry.notenoughupdates.core.GuiElementTextField; import io.github.moulberry.notenoughupdates.core.config.struct.ConfigProcessor; import io.github.moulberry.notenoughupdates.core.util.GuiElementSlider; @@ -9,124 +8,126 @@ import org.lwjgl.input.Mouse; public class GuiOptionEditorSlider extends GuiOptionEditor { - - private final GuiElementSlider slider; - private final GuiElementTextField textField; - - public GuiOptionEditorSlider(ConfigProcessor.ProcessedOption option, float minValue, float maxValue, float minStep) { - super(option); - if(minStep < 0) minStep = 0.01f; - - float floatVal = ((Number)option.get()).floatValue(); - { - String strVal; - if(floatVal % 1 == 0) { - strVal = Integer.toString((int)floatVal); - } else { - strVal = Float.toString(floatVal); - } - textField = new GuiElementTextField(strVal, - GuiElementTextField.NO_SPACE | GuiElementTextField.NUM_ONLY | GuiElementTextField.SCALE_TEXT); - } - - slider = new GuiElementSlider(0, 0, 80, minValue, maxValue, minStep, floatVal, (val) -> { - option.set(val); - - String strVal; - if(val % 1 == 0) { - strVal = Integer.toString(val.intValue()); - } else { - strVal = Float.toString(val); - strVal = strVal.replaceAll("(\\.\\d\\d\\d)(?:\\d)+", "$1"); - strVal = strVal.replaceAll("0+$", ""); - } - textField.setText(strVal); - }); - } - - @Override - public void render(int x, int y, int width) { - super.render(x, y, width); - int height = getHeight(); - - int fullWidth = Math.min(width/3-10, 80); - int sliderWidth = (fullWidth-5)*3/4; - int textFieldWidth = (fullWidth-5)/4; - - slider.x = x+width/6-fullWidth/2; - slider.y = y+height-7-14; - slider.width = sliderWidth; - slider.render(); - - if(textField.getFocus()) { - textField.setOptions(GuiElementTextField.NO_SPACE | GuiElementTextField.NUM_ONLY); - textField.setSize(Minecraft.getMinecraft().fontRendererObj.getStringWidth(textField.getText())+10, - 16); - } else { - textField.setSize(textFieldWidth, 16); - textField.setOptions(GuiElementTextField.NO_SPACE | GuiElementTextField.NUM_ONLY | GuiElementTextField.SCALE_TEXT); - } - - textField.render(x+width/6-fullWidth/2+sliderWidth+5, y+height-7-14); - } - - @Override - public boolean mouseInput(int x, int y, int width, int mouseX, int mouseY) { - int height = getHeight(); - - int fullWidth = Math.min(width/3-10, 80); - int sliderWidth = (fullWidth-5)*3/4; - int textFieldWidth = (fullWidth-5)/4; - - slider.x = x+width/6-fullWidth/2; - slider.y = y+height-7-14; - slider.width = sliderWidth; - if(slider.mouseInput(mouseX, mouseY)) { - textField.unfocus(); - return true; - } - - if(textField.getFocus()) { - textFieldWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth(textField.getText())+10; - } - - int textFieldX = x+width/6-fullWidth/2+sliderWidth+5; - int textFieldY = y+height-7-14; - textField.setSize(textFieldWidth, 16); - - if(Mouse.getEventButtonState() && (Mouse.getEventButton() == 0 || Mouse.getEventButton() == 1)) { - if(mouseX > textFieldX && mouseX < textFieldX+textFieldWidth && - mouseY > textFieldY && mouseY < textFieldY+16) { - textField.mouseClicked(mouseX, mouseY, Mouse.getEventButton()); - return true; - } - textField.unfocus(); - } - - return false; - } - - @Override - public boolean keyboardInput() { - if(Keyboard.getEventKeyState() && textField.getFocus()) { - textField.keyTyped(Keyboard.getEventCharacter(), Keyboard.getEventKey()); - - try { - textField.setCustomBorderColour(0xffffffff); - float f = Float.parseFloat(textField.getText()); - if(option.set(f)) { - slider.setValue(f); - } else { - textField.setCustomBorderColour(0xff0000ff); - } - } catch(Exception e) { - textField.setCustomBorderColour(0xffff0000); - } - - return true; - } - return false; - } - - + private final GuiElementSlider slider; + private final GuiElementTextField textField; + + public GuiOptionEditorSlider(ConfigProcessor.ProcessedOption option, float minValue, float maxValue, float minStep) { + super(option); + if (minStep < 0) minStep = 0.01f; + + float floatVal = ((Number) option.get()).floatValue(); + { + String strVal; + if (floatVal % 1 == 0) { + strVal = Integer.toString((int) floatVal); + } else { + strVal = Float.toString(floatVal); + } + textField = new GuiElementTextField( + strVal, + GuiElementTextField.NO_SPACE | GuiElementTextField.NUM_ONLY | GuiElementTextField.SCALE_TEXT + ); + } + + slider = new GuiElementSlider(0, 0, 80, minValue, maxValue, minStep, floatVal, (val) -> { + option.set(val); + + String strVal; + if (val % 1 == 0) { + strVal = Integer.toString(val.intValue()); + } else { + strVal = Float.toString(val); + strVal = strVal.replaceAll("(\\.\\d\\d\\d)(?:\\d)+", "$1"); + strVal = strVal.replaceAll("0+$", ""); + } + textField.setText(strVal); + }); + } + + @Override + public void render(int x, int y, int width) { + super.render(x, y, width); + int height = getHeight(); + + int fullWidth = Math.min(width / 3 - 10, 80); + int sliderWidth = (fullWidth - 5) * 3 / 4; + int textFieldWidth = (fullWidth - 5) / 4; + + slider.x = x + width / 6 - fullWidth / 2; + slider.y = y + height - 7 - 14; + slider.width = sliderWidth; + slider.render(); + + if (textField.getFocus()) { + textField.setOptions(GuiElementTextField.NO_SPACE | GuiElementTextField.NUM_ONLY); + textField.setSize( + Minecraft.getMinecraft().fontRendererObj.getStringWidth(textField.getText()) + 10, + 16 + ); + } else { + textField.setSize(textFieldWidth, 16); + textField.setOptions( + GuiElementTextField.NO_SPACE | GuiElementTextField.NUM_ONLY | GuiElementTextField.SCALE_TEXT); + } + + textField.render(x + width / 6 - fullWidth / 2 + sliderWidth + 5, y + height - 7 - 14); + } + + @Override + public boolean mouseInput(int x, int y, int width, int mouseX, int mouseY) { + int height = getHeight(); + + int fullWidth = Math.min(width / 3 - 10, 80); + int sliderWidth = (fullWidth - 5) * 3 / 4; + int textFieldWidth = (fullWidth - 5) / 4; + + slider.x = x + width / 6 - fullWidth / 2; + slider.y = y + height - 7 - 14; + slider.width = sliderWidth; + if (slider.mouseInput(mouseX, mouseY)) { + textField.unfocus(); + return true; + } + + if (textField.getFocus()) { + textFieldWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth(textField.getText()) + 10; + } + + int textFieldX = x + width / 6 - fullWidth / 2 + sliderWidth + 5; + int textFieldY = y + height - 7 - 14; + textField.setSize(textFieldWidth, 16); + + if (Mouse.getEventButtonState() && (Mouse.getEventButton() == 0 || Mouse.getEventButton() == 1)) { + if (mouseX > textFieldX && mouseX < textFieldX + textFieldWidth && + mouseY > textFieldY && mouseY < textFieldY + 16) { + textField.mouseClicked(mouseX, mouseY, Mouse.getEventButton()); + return true; + } + textField.unfocus(); + } + + return false; + } + + @Override + public boolean keyboardInput() { + if (Keyboard.getEventKeyState() && textField.getFocus()) { + textField.keyTyped(Keyboard.getEventCharacter(), Keyboard.getEventKey()); + + try { + textField.setCustomBorderColour(0xffffffff); + float f = Float.parseFloat(textField.getText()); + if (option.set(f)) { + slider.setValue(f); + } else { + textField.setCustomBorderColour(0xff0000ff); + } + } catch (Exception e) { + textField.setCustomBorderColour(0xffff0000); + } + + return true; + } + return false; + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorText.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorText.java index bf50bda8aa..f98c87eeae 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorText.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorText.java @@ -1,84 +1,85 @@ package io.github.moulberry.notenoughupdates.core.config.gui; -import io.github.moulberry.notenoughupdates.core.GuiElementBoolean; import io.github.moulberry.notenoughupdates.core.GuiElementTextField; import io.github.moulberry.notenoughupdates.core.config.struct.ConfigProcessor; -import io.github.moulberry.notenoughupdates.core.util.GuiElementSlider; import net.minecraft.client.Minecraft; import org.lwjgl.input.Keyboard; import org.lwjgl.input.Mouse; public class GuiOptionEditorText extends GuiOptionEditor { - - private final GuiElementTextField textField; - - public GuiOptionEditorText(ConfigProcessor.ProcessedOption option) { - super(option); - - textField = new GuiElementTextField((String)option.get(), 0); - } - - @Override - public void render(int x, int y, int width) { - super.render(x, y, width); - int height = getHeight(); - - int fullWidth = Math.min(width/3-10, 80); - - int textFieldX = x+width/6-fullWidth/2; - if(textField.getFocus()) { - fullWidth = Math.max(fullWidth, Minecraft.getMinecraft().fontRendererObj.getStringWidth(textField.getText())+10); - } - - textField.setSize(fullWidth, 16); - - textField.render(textFieldX, y+height-7-14); - } - - @Override - public boolean mouseInput(int x, int y, int width, int mouseX, int mouseY) { - int height = getHeight(); - - int fullWidth = Math.min(width/3-10, 80); - - int textFieldX = x+width/6-fullWidth/2; - - if(textField.getFocus()) { - fullWidth = Math.max(fullWidth, Minecraft.getMinecraft().fontRendererObj.getStringWidth(textField.getText())+10); - } - - int textFieldY = y+height-7-14; - textField.setSize(fullWidth, 16); - - if(Mouse.getEventButtonState() && (Mouse.getEventButton() == 0 || Mouse.getEventButton() == 1)) { - if(mouseX > textFieldX && mouseX < textFieldX+fullWidth && - mouseY > textFieldY && mouseY < textFieldY+16) { - textField.mouseClicked(mouseX, mouseY, Mouse.getEventButton()); - return true; - } - textField.unfocus(); - } - - return false; - } - - @Override - public boolean keyboardInput() { - if(Keyboard.getEventKeyState() && textField.getFocus()) { - Keyboard.enableRepeatEvents(true); - textField.keyTyped(Keyboard.getEventCharacter(), Keyboard.getEventKey()); - - try { - textField.setCustomBorderColour(0xffffffff); - option.set(textField.getText()); - } catch(Exception e) { - textField.setCustomBorderColour(0xffff0000); - } - - return true; - } - return false; - } - - + private final GuiElementTextField textField; + + public GuiOptionEditorText(ConfigProcessor.ProcessedOption option) { + super(option); + + textField = new GuiElementTextField((String) option.get(), 0); + } + + @Override + public void render(int x, int y, int width) { + super.render(x, y, width); + int height = getHeight(); + + int fullWidth = Math.min(width / 3 - 10, 80); + + int textFieldX = x + width / 6 - fullWidth / 2; + if (textField.getFocus()) { + fullWidth = Math.max( + fullWidth, + Minecraft.getMinecraft().fontRendererObj.getStringWidth(textField.getText()) + 10 + ); + } + + textField.setSize(fullWidth, 16); + + textField.render(textFieldX, y + height - 7 - 14); + } + + @Override + public boolean mouseInput(int x, int y, int width, int mouseX, int mouseY) { + int height = getHeight(); + + int fullWidth = Math.min(width / 3 - 10, 80); + + int textFieldX = x + width / 6 - fullWidth / 2; + + if (textField.getFocus()) { + fullWidth = Math.max( + fullWidth, + Minecraft.getMinecraft().fontRendererObj.getStringWidth(textField.getText()) + 10 + ); + } + + int textFieldY = y + height - 7 - 14; + textField.setSize(fullWidth, 16); + + if (Mouse.getEventButtonState() && (Mouse.getEventButton() == 0 || Mouse.getEventButton() == 1)) { + if (mouseX > textFieldX && mouseX < textFieldX + fullWidth && + mouseY > textFieldY && mouseY < textFieldY + 16) { + textField.mouseClicked(mouseX, mouseY, Mouse.getEventButton()); + return true; + } + textField.unfocus(); + } + + return false; + } + + @Override + public boolean keyboardInput() { + if (Keyboard.getEventKeyState() && textField.getFocus()) { + Keyboard.enableRepeatEvents(true); + textField.keyTyped(Keyboard.getEventCharacter(), Keyboard.getEventKey()); + + try { + textField.setCustomBorderColour(0xffffffff); + option.set(textField.getText()); + } catch (Exception e) { + textField.setCustomBorderColour(0xffff0000); + } + + return true; + } + return false; + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiPositionEditor.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiPositionEditor.java index e979e832d5..651335ed3e 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiPositionEditor.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiPositionEditor.java @@ -12,167 +12,170 @@ import java.io.IOException; public class GuiPositionEditor extends GuiScreen { - - private final Position position; - private Position originalPosition; - private final int elementWidth; - private final int elementHeight; - private final Runnable renderCallback; - private final Runnable positionChangedCallback; - private final Runnable closedCallback; - private boolean clicked = false; - private int grabbedX = 0; - private int grabbedY = 0; - - private int guiScaleOverride = -1; - - public GuiPositionEditor(Position position, int elementWidth, int elementHeight, - Runnable renderCallback, - Runnable positionChangedCallback, - Runnable closedCallback) { - this.position = position; - this.originalPosition = position.clone(); - this.elementWidth = elementWidth; - this.elementHeight = elementHeight; - this.renderCallback = renderCallback; - this.positionChangedCallback = positionChangedCallback; - this.closedCallback = closedCallback; - } - - public GuiPositionEditor withScale(int scale) { - this.guiScaleOverride = scale; - return this; - } - - @Override - public void onGuiClosed() { - super.onGuiClosed(); - closedCallback.run(); - } - - @Override - public void drawScreen(int mouseX, int mouseY, float partialTicks) { - super.drawScreen(mouseX, mouseY, partialTicks); - ScaledResolution scaledResolution; - if(guiScaleOverride >= 0) { - scaledResolution = Utils.pushGuiScale(guiScaleOverride); - } else { - scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); - } - - this.width = scaledResolution.getScaledWidth(); - this.height = scaledResolution.getScaledHeight(); - mouseX = Mouse.getX() * width / Minecraft.getMinecraft().displayWidth; - mouseY = height - Mouse.getY() * height / Minecraft.getMinecraft().displayHeight - 1; - - drawDefaultBackground(); - - if(clicked) { - grabbedX += position.moveX(mouseX - grabbedX, elementWidth, scaledResolution); - grabbedY += position.moveY(mouseY - grabbedY, elementHeight, scaledResolution); - } - - renderCallback.run(); - - int x = position.getAbsX(scaledResolution, elementWidth); - int y = position.getAbsY(scaledResolution, elementHeight); - - if(position.isCenterX()) x -= elementWidth/2; - if(position.isCenterY()) y -= elementHeight/2; - Gui.drawRect(x, y, x+elementWidth, y+elementHeight, 0x80404040); - - if(guiScaleOverride >= 0) { - Utils.pushGuiScale(-1); - } - - scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); - Utils.drawStringCentered("Position Editor", Minecraft.getMinecraft().fontRendererObj, - scaledResolution.getScaledWidth()/2, 8, true, 0xffffff); - Utils.drawStringCentered("R to Reset - Arrow keys/mouse to move", Minecraft.getMinecraft().fontRendererObj, - scaledResolution.getScaledWidth()/2, 18, true, 0xffffff); - } - - @Override - protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { - super.mouseClicked(mouseX, mouseY, mouseButton); - - if(mouseButton == 0) { - ScaledResolution scaledResolution; - if(guiScaleOverride >= 0) { - scaledResolution = Utils.pushGuiScale(guiScaleOverride); - } else { - scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); - } - mouseX = Mouse.getX() * width / Minecraft.getMinecraft().displayWidth; - mouseY = height - Mouse.getY() * height / Minecraft.getMinecraft().displayHeight - 1; - - int x = position.getAbsX(scaledResolution, elementWidth); - int y = position.getAbsY(scaledResolution, elementHeight); - if(position.isCenterX()) x -= elementWidth/2; - if(position.isCenterY()) y -= elementHeight/2; - - if(mouseX >= x && mouseY >= y && - mouseX <= x+elementWidth && mouseY <= y+elementHeight) { - clicked = true; - grabbedX = mouseX; - grabbedY = mouseY; - } - - if(guiScaleOverride >= 0) { - Utils.pushGuiScale(-1); - } - } - } - - @Override - protected void keyTyped(char typedChar, int keyCode) throws IOException { - Keyboard.enableRepeatEvents(true); - - if(keyCode == Keyboard.KEY_R) { - position.set(originalPosition); - } else if(!clicked) { - boolean shiftHeld = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT); - int dist = shiftHeld ? 10 : 1; - if(keyCode == Keyboard.KEY_DOWN) { - position.moveY(dist, elementHeight, new ScaledResolution(Minecraft.getMinecraft())); - } else if(keyCode == Keyboard.KEY_UP) { - position.moveY(-dist, elementHeight, new ScaledResolution(Minecraft.getMinecraft())); - } else if(keyCode == Keyboard.KEY_LEFT) { - position.moveX(-dist, elementWidth, new ScaledResolution(Minecraft.getMinecraft())); - } else if(keyCode == Keyboard.KEY_RIGHT) { - position.moveX(dist, elementWidth, new ScaledResolution(Minecraft.getMinecraft())); - } - } - super.keyTyped(typedChar, keyCode); - } - - @Override - protected void mouseReleased(int mouseX, int mouseY, int state) { - super.mouseReleased(mouseX, mouseY, state); - clicked = false; - } - - @Override - protected void mouseClickMove(int mouseX, int mouseY, int clickedMouseButton, long timeSinceLastClick) { - super.mouseClickMove(mouseX, mouseY, clickedMouseButton, timeSinceLastClick); - - if(clicked) { - ScaledResolution scaledResolution; - if(guiScaleOverride >= 0) { - scaledResolution = Utils.pushGuiScale(guiScaleOverride); - } else { - scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); - } - mouseX = Mouse.getX() * width / Minecraft.getMinecraft().displayWidth; - mouseY = height - Mouse.getY() * height / Minecraft.getMinecraft().displayHeight - 1; - - grabbedX += position.moveX(mouseX - grabbedX, elementWidth, scaledResolution); - grabbedY += position.moveY(mouseY - grabbedY, elementHeight, scaledResolution); - positionChangedCallback.run(); - - if(guiScaleOverride >= 0) { - Utils.pushGuiScale(-1); - } - } - } + private final Position position; + private final Position originalPosition; + private final int elementWidth; + private final int elementHeight; + private final Runnable renderCallback; + private final Runnable positionChangedCallback; + private final Runnable closedCallback; + private boolean clicked = false; + private int grabbedX = 0; + private int grabbedY = 0; + + private int guiScaleOverride = -1; + + public GuiPositionEditor( + Position position, int elementWidth, int elementHeight, + Runnable renderCallback, + Runnable positionChangedCallback, + Runnable closedCallback + ) { + this.position = position; + this.originalPosition = position.clone(); + this.elementWidth = elementWidth; + this.elementHeight = elementHeight; + this.renderCallback = renderCallback; + this.positionChangedCallback = positionChangedCallback; + this.closedCallback = closedCallback; + } + + public GuiPositionEditor withScale(int scale) { + this.guiScaleOverride = scale; + return this; + } + + @Override + public void onGuiClosed() { + super.onGuiClosed(); + closedCallback.run(); + } + + @Override + public void drawScreen(int mouseX, int mouseY, float partialTicks) { + super.drawScreen(mouseX, mouseY, partialTicks); + ScaledResolution scaledResolution; + if (guiScaleOverride >= 0) { + scaledResolution = Utils.pushGuiScale(guiScaleOverride); + } else { + scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + } + + this.width = scaledResolution.getScaledWidth(); + this.height = scaledResolution.getScaledHeight(); + mouseX = Mouse.getX() * width / Minecraft.getMinecraft().displayWidth; + mouseY = height - Mouse.getY() * height / Minecraft.getMinecraft().displayHeight - 1; + + drawDefaultBackground(); + + if (clicked) { + grabbedX += position.moveX(mouseX - grabbedX, elementWidth, scaledResolution); + grabbedY += position.moveY(mouseY - grabbedY, elementHeight, scaledResolution); + } + + renderCallback.run(); + + int x = position.getAbsX(scaledResolution, elementWidth); + int y = position.getAbsY(scaledResolution, elementHeight); + + if (position.isCenterX()) x -= elementWidth / 2; + if (position.isCenterY()) y -= elementHeight / 2; + Gui.drawRect(x, y, x + elementWidth, y + elementHeight, 0x80404040); + + if (guiScaleOverride >= 0) { + Utils.pushGuiScale(-1); + } + + scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + Utils.drawStringCentered("Position Editor", Minecraft.getMinecraft().fontRendererObj, + scaledResolution.getScaledWidth() / 2, 8, true, 0xffffff + ); + Utils.drawStringCentered("R to Reset - Arrow keys/mouse to move", Minecraft.getMinecraft().fontRendererObj, + scaledResolution.getScaledWidth() / 2, 18, true, 0xffffff + ); + } + + @Override + protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { + super.mouseClicked(mouseX, mouseY, mouseButton); + + if (mouseButton == 0) { + ScaledResolution scaledResolution; + if (guiScaleOverride >= 0) { + scaledResolution = Utils.pushGuiScale(guiScaleOverride); + } else { + scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + } + mouseX = Mouse.getX() * width / Minecraft.getMinecraft().displayWidth; + mouseY = height - Mouse.getY() * height / Minecraft.getMinecraft().displayHeight - 1; + + int x = position.getAbsX(scaledResolution, elementWidth); + int y = position.getAbsY(scaledResolution, elementHeight); + if (position.isCenterX()) x -= elementWidth / 2; + if (position.isCenterY()) y -= elementHeight / 2; + + if (mouseX >= x && mouseY >= y && + mouseX <= x + elementWidth && mouseY <= y + elementHeight) { + clicked = true; + grabbedX = mouseX; + grabbedY = mouseY; + } + + if (guiScaleOverride >= 0) { + Utils.pushGuiScale(-1); + } + } + } + + @Override + protected void keyTyped(char typedChar, int keyCode) throws IOException { + Keyboard.enableRepeatEvents(true); + + if (keyCode == Keyboard.KEY_R) { + position.set(originalPosition); + } else if (!clicked) { + boolean shiftHeld = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT); + int dist = shiftHeld ? 10 : 1; + if (keyCode == Keyboard.KEY_DOWN) { + position.moveY(dist, elementHeight, new ScaledResolution(Minecraft.getMinecraft())); + } else if (keyCode == Keyboard.KEY_UP) { + position.moveY(-dist, elementHeight, new ScaledResolution(Minecraft.getMinecraft())); + } else if (keyCode == Keyboard.KEY_LEFT) { + position.moveX(-dist, elementWidth, new ScaledResolution(Minecraft.getMinecraft())); + } else if (keyCode == Keyboard.KEY_RIGHT) { + position.moveX(dist, elementWidth, new ScaledResolution(Minecraft.getMinecraft())); + } + } + super.keyTyped(typedChar, keyCode); + } + + @Override + protected void mouseReleased(int mouseX, int mouseY, int state) { + super.mouseReleased(mouseX, mouseY, state); + clicked = false; + } + + @Override + protected void mouseClickMove(int mouseX, int mouseY, int clickedMouseButton, long timeSinceLastClick) { + super.mouseClickMove(mouseX, mouseY, clickedMouseButton, timeSinceLastClick); + + if (clicked) { + ScaledResolution scaledResolution; + if (guiScaleOverride >= 0) { + scaledResolution = Utils.pushGuiScale(guiScaleOverride); + } else { + scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + } + mouseX = Mouse.getX() * width / Minecraft.getMinecraft().displayWidth; + mouseY = height - Mouse.getY() * height / Minecraft.getMinecraft().displayHeight - 1; + + grabbedX += position.moveX(mouseX - grabbedX, elementWidth, scaledResolution); + grabbedY += position.moveY(mouseY - grabbedY, elementHeight, scaledResolution); + positionChangedCallback.run(); + + if (guiScaleOverride >= 0) { + Utils.pushGuiScale(-1); + } + } + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/struct/ConfigProcessor.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/struct/ConfigProcessor.java index 4ce1016283..b5aa6ba875 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/struct/ConfigProcessor.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/struct/ConfigProcessor.java @@ -4,178 +4,192 @@ import io.github.moulberry.notenoughupdates.core.config.Config; import io.github.moulberry.notenoughupdates.core.config.annotations.*; import io.github.moulberry.notenoughupdates.core.config.gui.*; -import io.github.moulberry.notenoughupdates.core.config.Config; import java.lang.reflect.Field; import java.util.LinkedHashMap; import java.util.List; public class ConfigProcessor { - - public static class ProcessedCategory { - public final String name; - public final String desc; - public final LinkedHashMap options = new LinkedHashMap<>(); - - public ProcessedCategory(String name, String desc) { - this.name = name; - this.desc = desc; - } - } - - public static class ProcessedOption { - public final String name; - public final String desc; - public final int subcategoryId; - public GuiOptionEditor editor; - - public int accordionId = -1; - - private final Field field; - private final Object container; - - public ProcessedOption(String name, String desc, int subcategoryId, Field field, Object container) { - this.name = name; - this.desc = desc; - this.subcategoryId = subcategoryId; - - this.field = field; - this.container = container; - } - - public Object get() { - try { - return field.get(container); - } catch(Exception e) { - return null; - } - } - - public boolean set(Object value) { - try { - if(field.getType() == int.class && value instanceof Number) { - field.set(container, ((Number)value).intValue()); - } else { - field.set(container, value); - } - return true; - } catch(Exception e) { - e.printStackTrace(); - return false; - } - } - } - - public static LinkedHashMap create(Config config) { - LinkedHashMap processedConfig = new LinkedHashMap<>(); - for(Field categoryField : config.getClass().getDeclaredFields()) { - boolean exposePresent = categoryField.isAnnotationPresent(Expose.class); - boolean categoryPresent = categoryField.isAnnotationPresent(Category.class); - - if(exposePresent && categoryPresent) { - Object categoryObj; - try { - categoryObj = categoryField.get(config); - } catch(Exception e) { - //System.err.printf("Failed to load config category %s. Field was not accessible.\n", categoryField.getName()); - continue; - } - - Category categoryAnnotation = categoryField.getAnnotation(Category.class); - ProcessedCategory cat = new ProcessedCategory( - categoryAnnotation.name(), - categoryAnnotation.desc() - ); - processedConfig.put(categoryField.getName(), cat); - - for(Field optionField : categoryObj.getClass().getDeclaredFields()) { - boolean optionPresent = optionField.isAnnotationPresent(ConfigOption.class); - - if(optionPresent) { - ConfigOption optionAnnotation = optionField.getAnnotation(ConfigOption.class); - ProcessedOption option = new ProcessedOption( - optionAnnotation.name(), - optionAnnotation.desc(), - optionAnnotation.subcategoryId(), - optionField, - categoryObj - ); - if(optionField.isAnnotationPresent(ConfigAccordionId.class)) { - ConfigAccordionId annotation = optionField.getAnnotation(ConfigAccordionId.class); - option.accordionId = annotation.id(); - } - - GuiOptionEditor editor = null; - Class optionType = optionField.getType(); - if(optionType.isAssignableFrom(int.class) && - optionField.isAnnotationPresent(ConfigEditorKeybind.class)) { - ConfigEditorKeybind configEditorAnnotation = optionField.getAnnotation(ConfigEditorKeybind.class); - editor = new GuiOptionEditorKeybind(option, (int)option.get(), configEditorAnnotation.defaultKey()); - } - if(optionField.isAnnotationPresent(ConfigEditorButton.class)) { - ConfigEditorButton configEditorAnnotation = optionField.getAnnotation(ConfigEditorButton.class); - editor = new GuiOptionEditorButton(option, configEditorAnnotation.runnableId(), configEditorAnnotation.buttonText(), config); - } - if(optionType.isAssignableFrom(boolean.class) && - optionField.isAnnotationPresent(ConfigEditorBoolean.class)) { - editor = new GuiOptionEditorBoolean(option); - } - if(optionType.isAssignableFrom(boolean.class) && - optionField.isAnnotationPresent(ConfigEditorAccordion.class)) { - ConfigEditorAccordion configEditorAnnotation = optionField.getAnnotation(ConfigEditorAccordion.class); - editor = new GuiOptionEditorAccordion(option, configEditorAnnotation.id()); - } - if(optionType.isAssignableFrom(int.class)) { - if(optionField.isAnnotationPresent(ConfigEditorDropdown.class)) { - ConfigEditorDropdown configEditorAnnotation = optionField.getAnnotation(ConfigEditorDropdown.class); - editor = new GuiOptionEditorDropdown(option, configEditorAnnotation.values(), (int)option.get(), true); - } - } - if(optionType.isAssignableFrom(List.class)) { - if(optionField.isAnnotationPresent(ConfigEditorDraggableList.class)) { - ConfigEditorDraggableList configEditorAnnotation = optionField.getAnnotation(ConfigEditorDraggableList.class); - editor = new GuiOptionEditorDraggableList(option, configEditorAnnotation.exampleText()); - } - } - if(optionType.isAssignableFrom(String.class)) { - if(optionField.isAnnotationPresent(ConfigEditorDropdown.class)) { - ConfigEditorDropdown configEditorAnnotation = optionField.getAnnotation(ConfigEditorDropdown.class); - editor = new GuiOptionEditorDropdown(option, configEditorAnnotation.values(), - configEditorAnnotation.initialIndex(), false); - } else if(optionField.isAnnotationPresent(ConfigEditorColour.class)) { - editor = new GuiOptionEditorColour(option); - } else if(optionField.isAnnotationPresent(ConfigEditorText.class)) { - editor = new GuiOptionEditorText(option); - } - } - if(optionType.isAssignableFrom(int.class) || - optionType.isAssignableFrom(float.class) || - optionType.isAssignableFrom(double.class)) { - if(optionField.isAnnotationPresent(ConfigEditorSlider.class)) { - ConfigEditorSlider configEditorAnnotation = optionField.getAnnotation(ConfigEditorSlider.class); - editor = new GuiOptionEditorSlider(option, configEditorAnnotation.minValue(), - configEditorAnnotation.maxValue(), configEditorAnnotation.minStep()); - } - } - if(optionType.isAssignableFrom(String.class)) { - if(optionField.isAnnotationPresent(ConfigEditorDropdown.class)) { - ConfigEditorDropdown configEditorAnnotation = optionField.getAnnotation(ConfigEditorDropdown.class); - editor = new GuiOptionEditorDropdown(option, configEditorAnnotation.values(), 0,false); - } - } - if(editor == null) { - //System.err.printf("Failed to load config option %s. Could not find suitable editor.\n", optionField.getName()); - continue; - } - option.editor = editor; - cat.options.put(optionField.getName(), option); - } - } - } else if(exposePresent || categoryPresent) { - //System.err.printf("Failed to load config category %s. Both @Expose and @Category must be present.\n", categoryField.getName()); - } - } - return processedConfig; - } - + public static class ProcessedCategory { + public final String name; + public final String desc; + public final LinkedHashMap options = new LinkedHashMap<>(); + + public ProcessedCategory(String name, String desc) { + this.name = name; + this.desc = desc; + } + } + + public static class ProcessedOption { + public final String name; + public final String desc; + public final int subcategoryId; + public GuiOptionEditor editor; + + public int accordionId = -1; + + private final Field field; + private final Object container; + + public ProcessedOption(String name, String desc, int subcategoryId, Field field, Object container) { + this.name = name; + this.desc = desc; + this.subcategoryId = subcategoryId; + + this.field = field; + this.container = container; + } + + public Object get() { + try { + return field.get(container); + } catch (Exception e) { + return null; + } + } + + public boolean set(Object value) { + try { + if (field.getType() == int.class && value instanceof Number) { + field.set(container, ((Number) value).intValue()); + } else { + field.set(container, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + } + + public static LinkedHashMap create(Config config) { + LinkedHashMap processedConfig = new LinkedHashMap<>(); + for (Field categoryField : config.getClass().getDeclaredFields()) { + boolean exposePresent = categoryField.isAnnotationPresent(Expose.class); + boolean categoryPresent = categoryField.isAnnotationPresent(Category.class); + + if (exposePresent && categoryPresent) { + Object categoryObj; + try { + categoryObj = categoryField.get(config); + } catch (Exception e) { + //System.err.printf("Failed to load config category %s. Field was not accessible.\n", categoryField.getName()); + continue; + } + + Category categoryAnnotation = categoryField.getAnnotation(Category.class); + ProcessedCategory cat = new ProcessedCategory( + categoryAnnotation.name(), + categoryAnnotation.desc() + ); + processedConfig.put(categoryField.getName(), cat); + + for (Field optionField : categoryObj.getClass().getDeclaredFields()) { + boolean optionPresent = optionField.isAnnotationPresent(ConfigOption.class); + + if (optionPresent) { + ConfigOption optionAnnotation = optionField.getAnnotation(ConfigOption.class); + ProcessedOption option = new ProcessedOption( + optionAnnotation.name(), + optionAnnotation.desc(), + optionAnnotation.subcategoryId(), + optionField, + categoryObj + ); + if (optionField.isAnnotationPresent(ConfigAccordionId.class)) { + ConfigAccordionId annotation = optionField.getAnnotation(ConfigAccordionId.class); + option.accordionId = annotation.id(); + } + + GuiOptionEditor editor = null; + Class optionType = optionField.getType(); + if (optionType.isAssignableFrom(int.class) && + optionField.isAnnotationPresent(ConfigEditorKeybind.class)) { + ConfigEditorKeybind configEditorAnnotation = optionField.getAnnotation(ConfigEditorKeybind.class); + editor = new GuiOptionEditorKeybind(option, (int) option.get(), configEditorAnnotation.defaultKey()); + } + if (optionField.isAnnotationPresent(ConfigEditorButton.class)) { + ConfigEditorButton configEditorAnnotation = optionField.getAnnotation(ConfigEditorButton.class); + editor = new GuiOptionEditorButton( + option, + configEditorAnnotation.runnableId(), + configEditorAnnotation.buttonText(), + config + ); + } + if (optionField.isAnnotationPresent(ConfigEditorFSR.class)) { + ConfigEditorFSR configEditorAnnotation = optionField.getAnnotation(ConfigEditorFSR.class); + editor = new GuiOptionEditorFSR( + option, + configEditorAnnotation.runnableId(), + configEditorAnnotation.buttonText(), + config + ); + } + if (optionType.isAssignableFrom(boolean.class) && + optionField.isAnnotationPresent(ConfigEditorBoolean.class)) { + editor = new GuiOptionEditorBoolean(option); + } + if (optionType.isAssignableFrom(boolean.class) && + optionField.isAnnotationPresent(ConfigEditorAccordion.class)) { + ConfigEditorAccordion configEditorAnnotation = optionField.getAnnotation(ConfigEditorAccordion.class); + editor = new GuiOptionEditorAccordion(option, configEditorAnnotation.id()); + } + if (optionType.isAssignableFrom(int.class)) { + if (optionField.isAnnotationPresent(ConfigEditorDropdown.class)) { + ConfigEditorDropdown configEditorAnnotation = optionField.getAnnotation(ConfigEditorDropdown.class); + editor = new GuiOptionEditorDropdown(option, configEditorAnnotation.values(), (int) option.get(), true); + } + } + if (optionType.isAssignableFrom(List.class)) { + if (optionField.isAnnotationPresent(ConfigEditorDraggableList.class)) { + ConfigEditorDraggableList configEditorAnnotation = + optionField.getAnnotation(ConfigEditorDraggableList.class); + editor = new GuiOptionEditorDraggableList(option, configEditorAnnotation.exampleText()); + } + } + if (optionType.isAssignableFrom(String.class)) { + if (optionField.isAnnotationPresent(ConfigEditorDropdown.class)) { + ConfigEditorDropdown configEditorAnnotation = optionField.getAnnotation(ConfigEditorDropdown.class); + editor = new GuiOptionEditorDropdown(option, configEditorAnnotation.values(), + configEditorAnnotation.initialIndex(), false + ); + } else if (optionField.isAnnotationPresent(ConfigEditorColour.class)) { + editor = new GuiOptionEditorColour(option); + } else if (optionField.isAnnotationPresent(ConfigEditorText.class)) { + editor = new GuiOptionEditorText(option); + } + } + if (optionType.isAssignableFrom(int.class) || + optionType.isAssignableFrom(float.class) || + optionType.isAssignableFrom(double.class)) { + if (optionField.isAnnotationPresent(ConfigEditorSlider.class)) { + ConfigEditorSlider configEditorAnnotation = optionField.getAnnotation(ConfigEditorSlider.class); + editor = new GuiOptionEditorSlider(option, configEditorAnnotation.minValue(), + configEditorAnnotation.maxValue(), configEditorAnnotation.minStep() + ); + } + } + if (optionType.isAssignableFrom(String.class)) { + if (optionField.isAnnotationPresent(ConfigEditorDropdown.class)) { + ConfigEditorDropdown configEditorAnnotation = optionField.getAnnotation(ConfigEditorDropdown.class); + editor = new GuiOptionEditorDropdown(option, configEditorAnnotation.values(), 0, false); + } + } + if (editor == null) { + //System.err.printf("Failed to load config option %s. Could not find suitable editor.\n", optionField.getName()); + continue; + } + option.editor = editor; + cat.options.put(optionField.getName(), option); + } + } + } else if (exposePresent || categoryPresent) { + //System.err.printf("Failed to load config category %s. Both @Expose and @Category must be present.\n", categoryField.getName()); + } + } + return processedConfig; + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/util/GuiElementSlider.java b/src/main/java/io/github/moulberry/notenoughupdates/core/util/GuiElementSlider.java index 89feaf17ca..c2252a97f8 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/util/GuiElementSlider.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/util/GuiElementSlider.java @@ -13,111 +13,112 @@ import static io.github.moulberry.notenoughupdates.util.GuiTextures.*; public class GuiElementSlider extends GuiElement { - - public int x; - public int y; - public int width; - private static final int HEIGHT = 16; - - private float minValue; - private float maxValue; - private float minStep; - - private float value; - private Consumer setCallback; - - private boolean clicked = false; - - public GuiElementSlider(int x, int y, int width, float minValue, float maxValue, float minStep, - float value, Consumer setCallback) { - if(minStep < 0) minStep = 0.01f; - - this.x = x; - this.y = y; - this.width = width; - this.minValue = minValue; - this.maxValue = maxValue; - this.minStep = minStep; - this.value = value; - this.setCallback = setCallback; - } - - public void setValue(float value) { - this.value = value; - } - - @Override - public void render() { - final ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); - int mouseX = Mouse.getX() * scaledResolution.getScaledWidth() / Minecraft.getMinecraft().displayWidth; - - float value = this.value; - if(clicked) { - value = (mouseX-x)*(maxValue-minValue)/width+minValue; - value = Math.max(minValue, Math.min(maxValue, value)); - value = Math.round(value/minStep)*minStep; - } - - float sliderAmount = Math.max(0, Math.min(1, (value-minValue)/(maxValue-minValue))); - int sliderAmountI = (int)(width*sliderAmount); - - GlStateManager.color(1f, 1f, 1f, 1f); - Minecraft.getMinecraft().getTextureManager().bindTexture(slider_on_cap); - Utils.drawTexturedRect(x, y, 4, HEIGHT, GL11.GL_NEAREST); - Minecraft.getMinecraft().getTextureManager().bindTexture(slider_off_cap); - Utils.drawTexturedRect(x+width-4, y, 4, HEIGHT, GL11.GL_NEAREST); - - if(sliderAmountI > 5) { - Minecraft.getMinecraft().getTextureManager().bindTexture(slider_on_segment); - Utils.drawTexturedRect(x+4, y, sliderAmountI-4, HEIGHT, GL11.GL_NEAREST); - } - - if(sliderAmountI < width-5) { - Minecraft.getMinecraft().getTextureManager().bindTexture(slider_off_segment); - Utils.drawTexturedRect(x+sliderAmountI, y, width-4-sliderAmountI, HEIGHT, GL11.GL_NEAREST); - } - - for(int i=1; i<4; i++) { - int notchX = x+width*i/4-1; - Minecraft.getMinecraft().getTextureManager().bindTexture(notchX > x+sliderAmountI ? slider_off_notch : slider_on_notch); - Utils.drawTexturedRect(notchX, y+(HEIGHT-4)/2, 2, 4, GL11.GL_NEAREST); - } - - Minecraft.getMinecraft().getTextureManager().bindTexture(slider_button_new); - Utils.drawTexturedRect(x+sliderAmountI-4, y, 8, HEIGHT, GL11.GL_NEAREST); - } - - @Override - public boolean mouseInput(int mouseX, int mouseY) { - if(!Mouse.isButtonDown(0)) { - clicked = false; - } - - if(Mouse.getEventButton() == 0) { - clicked = Mouse.getEventButtonState() && mouseX > x && mouseX < x+width && mouseY > y && mouseY < y+HEIGHT; - if(clicked) { - value = (mouseX-x)*(maxValue-minValue)/width+minValue; - value = Math.max(minValue, Math.min(maxValue, value)); - value = (float)(Math.round(value/minStep)*(double)minStep); - setCallback.accept(value); - return true; - } - } - - if(!Mouse.getEventButtonState() && Mouse.getEventButton() == -1 && clicked) { - value = (mouseX-x)*(maxValue-minValue)/width+minValue; - value = Math.max(minValue, Math.min(maxValue, value)); - value = Math.round(value/minStep)*minStep; - setCallback.accept(value); - return true; - } - - return false; - } - - @Override - public boolean keyboardInput() { - return false; - } - + public int x; + public int y; + public int width; + private static final int HEIGHT = 16; + + private final float minValue; + private final float maxValue; + private final float minStep; + + private float value; + private final Consumer setCallback; + + private boolean clicked = false; + + public GuiElementSlider( + int x, int y, int width, float minValue, float maxValue, float minStep, + float value, Consumer setCallback + ) { + if (minStep < 0) minStep = 0.01f; + + this.x = x; + this.y = y; + this.width = width; + this.minValue = minValue; + this.maxValue = maxValue; + this.minStep = minStep; + this.value = value; + this.setCallback = setCallback; + } + + public void setValue(float value) { + this.value = value; + } + + @Override + public void render() { + final ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + int mouseX = Mouse.getX() * scaledResolution.getScaledWidth() / Minecraft.getMinecraft().displayWidth; + + float value = this.value; + if (clicked) { + value = (mouseX - x) * (maxValue - minValue) / width + minValue; + value = Math.max(minValue, Math.min(maxValue, value)); + value = Math.round(value / minStep) * minStep; + } + + float sliderAmount = Math.max(0, Math.min(1, (value - minValue) / (maxValue - minValue))); + int sliderAmountI = (int) (width * sliderAmount); + + GlStateManager.color(1f, 1f, 1f, 1f); + Minecraft.getMinecraft().getTextureManager().bindTexture(slider_on_cap); + Utils.drawTexturedRect(x, y, 4, HEIGHT, GL11.GL_NEAREST); + Minecraft.getMinecraft().getTextureManager().bindTexture(slider_off_cap); + Utils.drawTexturedRect(x + width - 4, y, 4, HEIGHT, GL11.GL_NEAREST); + + if (sliderAmountI > 5) { + Minecraft.getMinecraft().getTextureManager().bindTexture(slider_on_segment); + Utils.drawTexturedRect(x + 4, y, sliderAmountI - 4, HEIGHT, GL11.GL_NEAREST); + } + + if (sliderAmountI < width - 5) { + Minecraft.getMinecraft().getTextureManager().bindTexture(slider_off_segment); + Utils.drawTexturedRect(x + sliderAmountI, y, width - 4 - sliderAmountI, HEIGHT, GL11.GL_NEAREST); + } + + for (int i = 1; i < 4; i++) { + int notchX = x + width * i / 4 - 1; + Minecraft.getMinecraft().getTextureManager().bindTexture( + notchX > x + sliderAmountI ? slider_off_notch : slider_on_notch); + Utils.drawTexturedRect(notchX, y + (HEIGHT - 4) / 2, 2, 4, GL11.GL_NEAREST); + } + + Minecraft.getMinecraft().getTextureManager().bindTexture(slider_button_new); + Utils.drawTexturedRect(x + sliderAmountI - 4, y, 8, HEIGHT, GL11.GL_NEAREST); + } + + @Override + public boolean mouseInput(int mouseX, int mouseY) { + if (!Mouse.isButtonDown(0)) { + clicked = false; + } + + if (Mouse.getEventButton() == 0) { + clicked = Mouse.getEventButtonState() && mouseX > x && mouseX < x + width && mouseY > y && mouseY < y + HEIGHT; + if (clicked) { + value = (mouseX - x) * (maxValue - minValue) / width + minValue; + value = Math.max(minValue, Math.min(maxValue, value)); + value = (float) (Math.round(value / minStep) * (double) minStep); + setCallback.accept(value); + return true; + } + } + + if (!Mouse.getEventButtonState() && Mouse.getEventButton() == -1 && clicked) { + value = (mouseX - x) * (maxValue - minValue) / width + minValue; + value = Math.max(minValue, Math.min(maxValue, value)); + value = Math.round(value / minStep) * minStep; + setCallback.accept(value); + return true; + } + + return false; + } + + @Override + public boolean keyboardInput() { + return false; + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/util/MiscUtils.java b/src/main/java/io/github/moulberry/notenoughupdates/core/util/MiscUtils.java index 3e9fc4ca55..03a9483b89 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/util/MiscUtils.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/util/MiscUtils.java @@ -20,85 +20,89 @@ import java.util.zip.ZipInputStream; public class MiscUtils { + public static void copyToClipboard(String str) { + Toolkit.getDefaultToolkit().getSystemClipboard() + .setContents(new StringSelection(str), null); + } - public static void copyToClipboard(String str) { - Toolkit.getDefaultToolkit().getSystemClipboard() - .setContents(new StringSelection(str), null); - } - private static void unzip(InputStream src, File dest) { - //buffer for read and write data to file - byte[] buffer = new byte[1024]; - try { - ZipInputStream zis = new ZipInputStream(src); - ZipEntry ze = zis.getNextEntry(); - while(ze != null){ - if(!ze.isDirectory()) { - String fileName = ze.getName(); - File newFile = new File(dest, fileName); - //create directories for sub directories in zip - new File(newFile.getParent()).mkdirs(); - FileOutputStream fos = new FileOutputStream(newFile); - int len; - while ((len = zis.read(buffer)) > 0) { - fos.write(buffer, 0, len); - } - fos.close(); - } - //close this ZipEntry - zis.closeEntry(); - ze = zis.getNextEntry(); - } - //close last ZipEntry - zis.closeEntry(); - zis.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } + private static void unzip(InputStream src, File dest) { + //buffer for read and write data to file + byte[] buffer = new byte[1024]; + try { + ZipInputStream zis = new ZipInputStream(src); + ZipEntry ze = zis.getNextEntry(); + while (ze != null) { + if (!ze.isDirectory()) { + String fileName = ze.getName(); + File newFile = new File(dest, fileName); + //create directories for sub directories in zip + new File(newFile.getParent()).mkdirs(); + FileOutputStream fos = new FileOutputStream(newFile); + int len; + while ((len = zis.read(buffer)) > 0) { + fos.write(buffer, 0, len); + } + fos.close(); + } + //close this ZipEntry + zis.closeEntry(); + ze = zis.getNextEntry(); + } + //close last ZipEntry + zis.closeEntry(); + zis.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } - public static void recursiveDelete(File file) { - if(file.isDirectory() && !Files.isSymbolicLink(file.toPath())) { - for(File child : file.listFiles()) { - recursiveDelete(child); - } - } - file.delete(); - } + public static void recursiveDelete(File file) { + if (file.isDirectory() && !Files.isSymbolicLink(file.toPath())) { + for (File child : file.listFiles()) { + recursiveDelete(child); + } + } + file.delete(); + } - private static String currentCursor = null; + private static String currentCursor = null; - public static void resetCursor() { - if(currentCursor == null) { - return; - } - currentCursor = null; - try { Mouse.setNativeCursor(null); } catch(Exception ignored) {} - } + public static void resetCursor() { + if (currentCursor == null) { + return; + } + currentCursor = null; + try { + Mouse.setNativeCursor(null); + } catch (Exception ignored) { + } + } - public static void setCursor(ResourceLocation loc, int hotspotX, int hotspotY) { - if(currentCursor != null && loc.getResourcePath().equals(currentCursor)) { - return; - } - currentCursor = loc.getResourcePath(); - try { - BufferedImage image = ImageIO.read(Minecraft.getMinecraft() - .getResourceManager().getResource(loc).getInputStream()); - int maxSize = Cursor.getMaxCursorSize(); - IntBuffer buffer = BufferUtils.createIntBuffer(maxSize*maxSize); - for(int i=0; i= image.getWidth() || cursorY >= image.getHeight()) { - buffer.put(0x00000000); - } else { - buffer.put(image.getRGB(cursorX, image.getHeight()-1-cursorY)); - } - } - buffer.flip(); - Mouse.setNativeCursor(new Cursor(maxSize, maxSize, hotspotX, hotspotY, 1, - buffer, null)); - } catch(Exception e) { - e.printStackTrace(); - } - } + public static void setCursor(ResourceLocation loc, int hotspotX, int hotspotY) { + if (currentCursor != null && loc.getResourcePath().equals(currentCursor)) { + return; + } + currentCursor = loc.getResourcePath(); + try { + BufferedImage image = ImageIO.read(Minecraft.getMinecraft() + .getResourceManager().getResource(loc).getInputStream()); + int maxSize = Cursor.getMaxCursorSize(); + IntBuffer buffer = BufferUtils.createIntBuffer(maxSize * maxSize); + for (int i = 0; i < maxSize * maxSize; i++) { + int cursorX = i % maxSize; + int cursorY = i / maxSize; + if (cursorX >= image.getWidth() || cursorY >= image.getHeight()) { + buffer.put(0x00000000); + } else { + buffer.put(image.getRGB(cursorX, image.getHeight() - 1 - cursorY)); + } + } + buffer.flip(); + Mouse.setNativeCursor(new Cursor(maxSize, maxSize, hotspotX, hotspotY, 1, + buffer, null + )); + } catch (Exception e) { + e.printStackTrace(); + } + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/util/Splitters.java b/src/main/java/io/github/moulberry/notenoughupdates/core/util/Splitters.java index 555e0d79c4..0bb858db1a 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/util/Splitters.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/util/Splitters.java @@ -3,8 +3,5 @@ import com.google.common.base.Splitter; public class Splitters { - - public static final Splitter NEWLINE_SPLITTER = Splitter.on('\n'); - - + public static final Splitter NEWLINE_SPLITTER = Splitter.on('\n'); } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/util/StringUtils.java b/src/main/java/io/github/moulberry/notenoughupdates/core/util/StringUtils.java index a3d8204a21..b0deadd25e 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/util/StringUtils.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/util/StringUtils.java @@ -7,33 +7,31 @@ import java.util.Set; public class StringUtils { - - public static final Set PROTOCOLS = Sets.newHashSet("http", "https"); - - public static String cleanColour(String in) { - return in.replaceAll("(?i)\\u00A7.", ""); - } - - public static String cleanColourNotModifiers(String in) { - return in.replaceAll("(?i)\\u00A7[0-9a-f]", "\u00A7r"); - } - - public static String trimToWidth(String str, int len) { - FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; - String trim = fr.trimStringToWidth(str, len); - - if(str.length() != trim.length() && !trim.endsWith(" ")) { - char next = str.charAt(trim.length()); - if(next != ' ') { - String[] split = trim.split(" "); - String last = split[split.length-1]; - if(last.length() < 8) { - trim = trim.substring(0, trim.length()-last.length()); - } - } - } - - return trim; - } - + public static final Set PROTOCOLS = Sets.newHashSet("http", "https"); + + public static String cleanColour(String in) { + return in.replaceAll("(?i)\\u00A7.", ""); + } + + public static String cleanColourNotModifiers(String in) { + return in.replaceAll("(?i)\\u00A7[0-9a-f]", "\u00A7r"); + } + + public static String trimToWidth(String str, int len) { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + String trim = fr.trimStringToWidth(str, len); + + if (str.length() != trim.length() && !trim.endsWith(" ")) { + char next = str.charAt(trim.length()); + if (next != ' ') { + String[] split = trim.split(" "); + String last = split[split.length - 1]; + if (last.length() < 8) { + trim = trim.substring(0, trim.length() - last.length()); + } + } + } + + return trim; + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/util/lerp/LerpUtils.java b/src/main/java/io/github/moulberry/notenoughupdates/core/util/lerp/LerpUtils.java index 73287f05f8..7e40195925 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/util/lerp/LerpUtils.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/util/lerp/LerpUtils.java @@ -1,26 +1,24 @@ package io.github.moulberry.notenoughupdates.core.util.lerp; public class LerpUtils { + public static float clampZeroOne(float f) { + return Math.max(0, Math.min(1, f)); + } - public static float clampZeroOne(float f) { - return Math.max(0, Math.min(1, f)); - } + public static float sigmoid(float val) { + return (float) (1 / (1 + Math.exp(-val))); + } - public static float sigmoid(float val) { - return (float)(1/(1 + Math.exp(-val))); - } - - private static final float sigmoidStr = 8; - private static final float sigmoidA = -1/(sigmoid(-0.5f * sigmoidStr) - sigmoid(0.5f * sigmoidStr)); - private static final float sigmoidB = sigmoidA*sigmoid(-0.5f * sigmoidStr); - public static float sigmoidZeroOne(float f) { - f = clampZeroOne(f); - return sigmoidA*sigmoid(sigmoidStr*(f-0.5f))-sigmoidB; - } - - public static float lerp(float a, float b, float amount) { - return b + (a - b) * clampZeroOne(amount); - } + private static final float sigmoidStr = 8; + private static final float sigmoidA = -1 / (sigmoid(-0.5f * sigmoidStr) - sigmoid(0.5f * sigmoidStr)); + private static final float sigmoidB = sigmoidA * sigmoid(-0.5f * sigmoidStr); + public static float sigmoidZeroOne(float f) { + f = clampZeroOne(f); + return sigmoidA * sigmoid(sigmoidStr * (f - 0.5f)) - sigmoidB; + } + public static float lerp(float a, float b, float amount) { + return b + (a - b) * clampZeroOne(amount); + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/util/lerp/LerpingFloat.java b/src/main/java/io/github/moulberry/notenoughupdates/core/util/lerp/LerpingFloat.java index 250facfc93..3d9e778759 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/util/lerp/LerpingFloat.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/util/lerp/LerpingFloat.java @@ -1,68 +1,67 @@ package io.github.moulberry.notenoughupdates.core.util.lerp; public class LerpingFloat { - - private int timeSpent; - private long lastMillis; - private int timeToReachTarget; - - private float targetValue; - private float lerpValue; - - public LerpingFloat(float initialValue, int timeToReachTarget) { - this.targetValue = this.lerpValue = initialValue; - this.timeToReachTarget = timeToReachTarget; - } - - public LerpingFloat(int initialValue) { - this(initialValue, 200); - } - - public void tick() { - int lastTimeSpent = timeSpent; - this.timeSpent += System.currentTimeMillis() - lastMillis; - - float lastDistPercentToTarget = lastTimeSpent/(float)timeToReachTarget; - float distPercentToTarget = timeSpent/(float)timeToReachTarget; - float fac = (1-lastDistPercentToTarget)/lastDistPercentToTarget; - - float startValue = lerpValue - (targetValue - lerpValue)/fac; - - float dist = targetValue - startValue; - if(dist == 0) return; - - float oldLerpValue = lerpValue; - if(distPercentToTarget >= 1) { - lerpValue = targetValue; - } else { - lerpValue = startValue + dist*distPercentToTarget; - } - - if(lerpValue == oldLerpValue) { - timeSpent = lastTimeSpent; - } else { - this.lastMillis = System.currentTimeMillis(); - } - } - - public void resetTimer() { - this.timeSpent = 0; - this.lastMillis = System.currentTimeMillis(); - } - - public void setTarget(float targetValue) { - this.targetValue = targetValue; - } - - public void setValue(float value) { - this.targetValue = this.lerpValue = value; - } - - public float getValue() { - return lerpValue; - } - - public float getTarget() { - return targetValue; - } + private int timeSpent; + private long lastMillis; + private final int timeToReachTarget; + + private float targetValue; + private float lerpValue; + + public LerpingFloat(float initialValue, int timeToReachTarget) { + this.targetValue = this.lerpValue = initialValue; + this.timeToReachTarget = timeToReachTarget; + } + + public LerpingFloat(int initialValue) { + this(initialValue, 200); + } + + public void tick() { + int lastTimeSpent = timeSpent; + this.timeSpent += System.currentTimeMillis() - lastMillis; + + float lastDistPercentToTarget = lastTimeSpent / (float) timeToReachTarget; + float distPercentToTarget = timeSpent / (float) timeToReachTarget; + float fac = (1 - lastDistPercentToTarget) / lastDistPercentToTarget; + + float startValue = lerpValue - (targetValue - lerpValue) / fac; + + float dist = targetValue - startValue; + if (dist == 0) return; + + float oldLerpValue = lerpValue; + if (distPercentToTarget >= 1) { + lerpValue = targetValue; + } else { + lerpValue = startValue + dist * distPercentToTarget; + } + + if (lerpValue == oldLerpValue) { + timeSpent = lastTimeSpent; + } else { + this.lastMillis = System.currentTimeMillis(); + } + } + + public void resetTimer() { + this.timeSpent = 0; + this.lastMillis = System.currentTimeMillis(); + } + + public void setTarget(float targetValue) { + this.targetValue = targetValue; + } + + public void setValue(float value) { + this.targetValue = this.lerpValue = value; + } + + public float getValue() { + return lerpValue; + } + + public float getTarget() { + return targetValue; + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/util/lerp/LerpingInteger.java b/src/main/java/io/github/moulberry/notenoughupdates/core/util/lerp/LerpingInteger.java index b3dd9d6f42..024455fd66 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/util/lerp/LerpingInteger.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/util/lerp/LerpingInteger.java @@ -1,76 +1,75 @@ package io.github.moulberry.notenoughupdates.core.util.lerp; public class LerpingInteger { - - private int timeSpent; - private long lastMillis; - private int timeToReachTarget; - - private int targetValue; - private int lerpValue; - - public LerpingInteger(int initialValue, int timeToReachTarget) { - this.targetValue = this.lerpValue = initialValue; - this.timeToReachTarget = timeToReachTarget; - } - - public LerpingInteger(int initialValue) { - this(initialValue, 200); - } - - public void tick() { - int lastTimeSpent = timeSpent; - this.timeSpent += System.currentTimeMillis() - lastMillis; - - float lastDistPercentToTarget = lastTimeSpent/(float)timeToReachTarget; - float distPercentToTarget = timeSpent/(float)timeToReachTarget; - float fac = (1-lastDistPercentToTarget)/lastDistPercentToTarget; - - int startValue = lerpValue - (int)((targetValue - lerpValue)/fac); - - int dist = targetValue - startValue; - if(dist == 0) return; - - int oldLerpValue = lerpValue; - if(distPercentToTarget >= 1) { - lerpValue = targetValue; - } else { - lerpValue = startValue + (int)(dist*distPercentToTarget); - } - - if(lerpValue == oldLerpValue) { - timeSpent = lastTimeSpent; - } else { - this.lastMillis = System.currentTimeMillis(); - } - } - - public int getTimeSpent() { - return timeSpent; - } - - public void resetTimer() { - this.timeSpent = 0; - this.lastMillis = System.currentTimeMillis(); - } - - public void setTimeToReachTarget(int timeToReachTarget) { - this.timeToReachTarget = timeToReachTarget; - } - - public void setTarget(int targetValue) { - this.targetValue = targetValue; - } - - public void setValue(int value) { - this.targetValue = this.lerpValue = value; - } - - public int getValue() { - return lerpValue; - } - - public int getTarget() { - return targetValue; - } + private int timeSpent; + private long lastMillis; + private int timeToReachTarget; + + private int targetValue; + private int lerpValue; + + public LerpingInteger(int initialValue, int timeToReachTarget) { + this.targetValue = this.lerpValue = initialValue; + this.timeToReachTarget = timeToReachTarget; + } + + public LerpingInteger(int initialValue) { + this(initialValue, 200); + } + + public void tick() { + int lastTimeSpent = timeSpent; + this.timeSpent += System.currentTimeMillis() - lastMillis; + + float lastDistPercentToTarget = lastTimeSpent / (float) timeToReachTarget; + float distPercentToTarget = timeSpent / (float) timeToReachTarget; + float fac = (1 - lastDistPercentToTarget) / lastDistPercentToTarget; + + int startValue = lerpValue - (int) ((targetValue - lerpValue) / fac); + + int dist = targetValue - startValue; + if (dist == 0) return; + + int oldLerpValue = lerpValue; + if (distPercentToTarget >= 1) { + lerpValue = targetValue; + } else { + lerpValue = startValue + (int) (dist * distPercentToTarget); + } + + if (lerpValue == oldLerpValue) { + timeSpent = lastTimeSpent; + } else { + this.lastMillis = System.currentTimeMillis(); + } + } + + public int getTimeSpent() { + return timeSpent; + } + + public void resetTimer() { + this.timeSpent = 0; + this.lastMillis = System.currentTimeMillis(); + } + + public void setTimeToReachTarget(int timeToReachTarget) { + this.timeToReachTarget = timeToReachTarget; + } + + public void setTarget(int targetValue) { + this.targetValue = targetValue; + } + + public void setValue(int value) { + this.targetValue = this.lerpValue = value; + } + + public int getValue() { + return lerpValue; + } + + public int getTarget() { + return targetValue; + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/util/render/RenderUtils.java b/src/main/java/io/github/moulberry/notenoughupdates/core/util/render/RenderUtils.java index 5f0ad94fc7..9a4607edba 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/util/render/RenderUtils.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/util/render/RenderUtils.java @@ -19,376 +19,410 @@ import org.lwjgl.util.vector.Vector3f; public class RenderUtils { - - public static void drawFloatingRectDark(int x, int y, int width, int height) { - drawFloatingRectDark(x, y, width, height, true); - } - - public static void drawFloatingRectDark(int x, int y, int width, int height, boolean shadow) { - int alpha = 0xf0000000; - - if(OpenGlHelper.isFramebufferEnabled()) { - ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); - BackgroundBlur.renderBlurredBackground(15, scaledResolution.getScaledWidth(), - scaledResolution.getScaledHeight(), x, y, width, height, true); - } else { - alpha = 0xff000000; - } - - int main = alpha | 0x202026; - int light = 0xff303036; - int dark = 0xff101016; - Gui.drawRect(x, y, x+1, y+height, light); //Left - Gui.drawRect(x+1, y, x+width, y+1, light); //Top - Gui.drawRect(x+width-1, y+1, x+width, y+height, dark); //Right - Gui.drawRect(x+1, y+height-1, x+width-1, y+height, dark); //Bottom - Gui.drawRect(x+1, y+1, x+width-1, y+height-1, main); //Middle - if(shadow) { - Gui.drawRect(x+width, y+2, x+width+2, y+height+2, 0x70000000); //Right shadow - Gui.drawRect(x+2, y+height, x+width, y+height+2, 0x70000000); //Bottom shadow - } - } - - public static void drawFloatingRect(int x, int y, int width, int height) { - drawFloatingRectWithAlpha(x, y, width, height, 0xFF, true); - } - - public static void drawFloatingRectWithAlpha(int x, int y, int width, int height, int alpha, boolean shadow) { - int main = (alpha << 24) | 0xc0c0c0; - int light = (alpha << 24) | 0xf0f0f0; - int dark = (alpha << 24) | 0x909090; - Gui.drawRect(x, y, x+1, y+height, light); //Left - Gui.drawRect(x+1, y, x+width, y+1, light); //Top - Gui.drawRect(x+width-1, y+1, x+width, y+height, dark); //Right - Gui.drawRect(x+1, y+height-1, x+width-1, y+height, dark); //Bottom - Gui.drawRect(x+1, y+1, x+width-1, y+height-1, main); //Middle - if(shadow) { - Gui.drawRect(x+width, y+2, x+width+2, y+height+2, (alpha*3/5) << 24); //Right shadow - Gui.drawRect(x+2, y+height, x+width, y+height+2, (alpha*3/5) << 24); //Bottom shadow - } - } - - public static void drawTexturedRect(float x, float y, float width, float height) { - drawTexturedRect(x, y, width, height, 0, 1, 0 , 1); - } - - public static void drawTexturedRect(float x, float y, float width, float height, int filter) { - drawTexturedRect(x, y, width, height, 0, 1, 0 , 1, filter); - } - - public static void drawTexturedRect(float x, float y, float width, float height, float uMin, float uMax, float vMin, float vMax) { - drawTexturedRect(x, y, width, height, uMin, uMax, vMin , vMax, GL11.GL_NEAREST); - } - - public static void drawTexturedRect(float x, float y, float width, float height, float uMin, float uMax, float vMin, float vMax, int filter) { - GlStateManager.enableBlend(); - GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); - - drawTexturedRectNoBlend(x, y, width, height, uMin, uMax, vMin, vMax, filter); - - GlStateManager.disableBlend(); - } - - public static void drawTexturedRectNoBlend(float x, float y, float width, float height, float uMin, float uMax, float vMin, float vMax, int filter) { - GlStateManager.enableTexture2D(); - - GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, filter); - GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, filter); - - Tessellator tessellator = Tessellator.getInstance(); - WorldRenderer worldrenderer = tessellator.getWorldRenderer(); - worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX); - worldrenderer - .pos(x, y+height, 0.0D) - .tex(uMin, vMax).endVertex(); - worldrenderer - .pos(x+width, y+height, 0.0D) - .tex(uMax, vMax).endVertex(); - worldrenderer - .pos(x+width, y, 0.0D) - .tex(uMax, vMin).endVertex(); - worldrenderer - .pos(x, y, 0.0D) - .tex(uMin, vMin).endVertex(); - tessellator.draw(); - - GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST); - GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST); - } - - public static void drawGradientRect(int zLevel, int left, int top, int right, int bottom, int startColor, int endColor) { - float startAlpha = (float)(startColor >> 24 & 255) / 255.0F; - float startRed = (float)(startColor >> 16 & 255) / 255.0F; - float startGreen = (float)(startColor >> 8 & 255) / 255.0F; - float startBlue = (float)(startColor & 255) / 255.0F; - float endAlpha = (float)(endColor >> 24 & 255) / 255.0F; - float endRed = (float)(endColor >> 16 & 255) / 255.0F; - float endGreen = (float)(endColor >> 8 & 255) / 255.0F; - float endBlue = (float)(endColor & 255) / 255.0F; - - GlStateManager.disableTexture2D(); - GlStateManager.enableBlend(); - GlStateManager.disableAlpha(); - GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); - GlStateManager.shadeModel(7425); - - Tessellator tessellator = Tessellator.getInstance(); - WorldRenderer worldrenderer = tessellator.getWorldRenderer(); - worldrenderer.begin(7, DefaultVertexFormats.POSITION_COLOR); - worldrenderer.pos(right, top, zLevel).color(startRed, startGreen, startBlue, startAlpha).endVertex(); - worldrenderer.pos(left, top, zLevel).color(startRed, startGreen, startBlue, startAlpha).endVertex(); - worldrenderer.pos(left, bottom, zLevel).color(endRed, endGreen, endBlue, endAlpha).endVertex(); - worldrenderer.pos(right, bottom, zLevel).color(endRed, endGreen, endBlue, endAlpha).endVertex(); - tessellator.draw(); - - GlStateManager.shadeModel(7424); - GlStateManager.disableBlend(); - GlStateManager.enableAlpha(); - GlStateManager.enableTexture2D(); - } - - private static final ResourceLocation beaconBeam = new ResourceLocation("textures/entity/beacon_beam.png"); - - private static void renderBeaconBeam(double x, double y, double z, int rgb, float alphaMult, - float partialTicks, Boolean disableDepth) { - int height = 300; - int bottomOffset = 0; - int topOffset = bottomOffset + height; - - Tessellator tessellator = Tessellator.getInstance(); - WorldRenderer worldrenderer = tessellator.getWorldRenderer(); - - if (disableDepth) { - GlStateManager.disableDepth(); - } - - Minecraft.getMinecraft().getTextureManager().bindTexture(beaconBeam); - GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT); - GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT); - GlStateManager.disableLighting(); - GlStateManager.enableCull(); - GlStateManager.enableTexture2D(); - GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE, GL11.GL_ZERO); - GlStateManager.enableBlend(); - GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO); - - double time = Minecraft.getMinecraft().theWorld.getTotalWorldTime() + (double)partialTicks; - double d1 = MathHelper.func_181162_h(-time * 0.2D - (double)MathHelper.floor_double(-time * 0.1D)); - - float r = ((rgb >> 16) & 0xFF) / 255f; - float g = ((rgb >> 8) & 0xFF) / 255f; - float b = (rgb & 0xFF) / 255f; - double d2 = time * 0.025D * -1.5D; - double d4 = 0.5D + Math.cos(d2 + 2.356194490192345D) * 0.2D; - double d5 = 0.5D + Math.sin(d2 + 2.356194490192345D) * 0.2D; - double d6 = 0.5D + Math.cos(d2 + (Math.PI / 4D)) * 0.2D; - double d7 = 0.5D + Math.sin(d2 + (Math.PI / 4D)) * 0.2D; - double d8 = 0.5D + Math.cos(d2 + 3.9269908169872414D) * 0.2D; - double d9 = 0.5D + Math.sin(d2 + 3.9269908169872414D) * 0.2D; - double d10 = 0.5D + Math.cos(d2 + 5.497787143782138D) * 0.2D; - double d11 = 0.5D + Math.sin(d2 + 5.497787143782138D) * 0.2D; - double d14 = -1.0D + d1; - double d15 = (double)(height) * 2.5D + d14; - worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR); - worldrenderer.pos(x + d4, y + topOffset, z + d5).tex(1.0D, d15).color(r, g, b, 1.0F*alphaMult).endVertex(); - worldrenderer.pos(x + d4, y + bottomOffset, z + d5).tex(1.0D, d14).color(r, g, b, 1.0F).endVertex(); - worldrenderer.pos(x + d6, y + bottomOffset, z + d7).tex(0.0D, d14).color(r, g, b, 1.0F).endVertex(); - worldrenderer.pos(x + d6, y + topOffset, z + d7).tex(0.0D, d15).color(r, g, b, 1.0F*alphaMult).endVertex(); - worldrenderer.pos(x + d10, y + topOffset, z + d11).tex(1.0D, d15).color(r, g, b, 1.0F*alphaMult).endVertex(); - worldrenderer.pos(x + d10, y + bottomOffset, z + d11).tex(1.0D, d14).color(r, g, b, 1.0F).endVertex(); - worldrenderer.pos(x + d8, y + bottomOffset, z + d9).tex(0.0D, d14).color(r, g, b, 1.0F).endVertex(); - worldrenderer.pos(x + d8, y + topOffset, z + d9).tex(0.0D, d15).color(r, g, b, 1.0F*alphaMult).endVertex(); - worldrenderer.pos(x + d6, y + topOffset, z + d7).tex(1.0D, d15).color(r, g, b, 1.0F*alphaMult).endVertex(); - worldrenderer.pos(x + d6, y + bottomOffset, z + d7).tex(1.0D, d14).color(r, g, b, 1.0F).endVertex(); - worldrenderer.pos(x + d10, y + bottomOffset, z + d11).tex(0.0D, d14).color(r, g, b, 1.0F).endVertex(); - worldrenderer.pos(x + d10, y + topOffset, z + d11).tex(0.0D, d15).color(r, g, b, 1.0F*alphaMult).endVertex(); - worldrenderer.pos(x + d8, y + topOffset, z + d9).tex(1.0D, d15).color(r, g, b, 1.0F*alphaMult).endVertex(); - worldrenderer.pos(x + d8, y + bottomOffset, z + d9).tex(1.0D, d14).color(r, g, b, 1.0F).endVertex(); - worldrenderer.pos(x + d4, y + bottomOffset, z + d5).tex(0.0D, d14).color(r, g, b, 1.0F).endVertex(); - worldrenderer.pos(x + d4, y + topOffset, z + d5).tex(0.0D, d15).color(r, g, b, 1.0F*alphaMult).endVertex(); - tessellator.draw(); - - GlStateManager.disableCull(); - double d12 = -1.0D + d1; - double d13 = height + d12; - - worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR); - worldrenderer.pos(x + 0.2D, y + topOffset, z + 0.2D).tex(1.0D, d13).color(r, g, b, 0.25F*alphaMult).endVertex(); - worldrenderer.pos(x + 0.2D, y + bottomOffset, z + 0.2D).tex(1.0D, d12).color(r, g, b, 0.25F).endVertex(); - worldrenderer.pos(x + 0.8D, y + bottomOffset, z + 0.2D).tex(0.0D, d12).color(r, g, b, 0.25F).endVertex(); - worldrenderer.pos(x + 0.8D, y + topOffset, z + 0.2D).tex(0.0D, d13).color(r, g, b, 0.25F*alphaMult).endVertex(); - worldrenderer.pos(x + 0.8D, y + topOffset, z + 0.8D).tex(1.0D, d13).color(r, g, b, 0.25F*alphaMult).endVertex(); - worldrenderer.pos(x + 0.8D, y + bottomOffset, z + 0.8D).tex(1.0D, d12).color(r, g, b, 0.25F).endVertex(); - worldrenderer.pos(x + 0.2D, y + bottomOffset, z + 0.8D).tex(0.0D, d12).color(r, g, b, 0.25F).endVertex(); - worldrenderer.pos(x + 0.2D, y + topOffset, z + 0.8D).tex(0.0D, d13).color(r, g, b, 0.25F*alphaMult).endVertex(); - worldrenderer.pos(x + 0.8D, y + topOffset, z + 0.2D).tex(1.0D, d13).color(r, g, b, 0.25F*alphaMult).endVertex(); - worldrenderer.pos(x + 0.8D, y + bottomOffset, z + 0.2D).tex(1.0D, d12).color(r, g, b, 0.25F).endVertex(); - worldrenderer.pos(x + 0.8D, y + bottomOffset, z + 0.8D).tex(0.0D, d12).color(r, g, b, 0.25F).endVertex(); - worldrenderer.pos(x + 0.8D, y + topOffset, z + 0.8D).tex(0.0D, d13).color(r, g, b, 0.25F*alphaMult).endVertex(); - worldrenderer.pos(x + 0.2D, y + topOffset, z + 0.8D).tex(1.0D, d13).color(r, g, b, 0.25F*alphaMult).endVertex(); - worldrenderer.pos(x + 0.2D, y + bottomOffset, z + 0.8D).tex(1.0D, d12).color(r, g, b, 0.25F).endVertex(); - worldrenderer.pos(x + 0.2D, y + bottomOffset, z + 0.2D).tex(0.0D, d12).color(r, g, b, 0.25F).endVertex(); - worldrenderer.pos(x + 0.2D, y + topOffset, z + 0.2D).tex(0.0D, d13).color(r, g, b, 0.25F*alphaMult).endVertex(); - tessellator.draw(); - - GlStateManager.disableLighting(); - GlStateManager.enableTexture2D(); - if (disableDepth) { - GlStateManager.enableDepth(); - } - } - - private static void renderBoundingBox(double x, double y, double z, int rgb, float alphaMult, float partialTicks) { - AxisAlignedBB bb = new AxisAlignedBB(x, y, z, x+1, y+1, z+1); - - GlStateManager.disableDepth(); - GlStateManager.disableCull(); - GlStateManager.disableTexture2D(); - CustomItemEffects.drawFilledBoundingBox(bb, 1f, SpecialColour.special(0, 100, rgb)); - GlStateManager.enableTexture2D(); - GlStateManager.enableCull(); - GlStateManager.enableDepth(); - } - - public static void renderBeaconBeam(BlockPos block, int rgb, float alphaMult, float partialTicks) { - double viewerX; - double viewerY; - double viewerZ; - - Vector3f aoteInterpPos = CustomItemEffects.INSTANCE.getCurrentPosition(); - if(aoteInterpPos != null) { - viewerX = aoteInterpPos.x; - viewerY = aoteInterpPos.y; - viewerZ = aoteInterpPos.z; - } else { - Entity viewer = Minecraft.getMinecraft().getRenderViewEntity(); - viewerX = viewer.lastTickPosX + (viewer.posX - viewer.lastTickPosX) * partialTicks; - viewerY = viewer.lastTickPosY + (viewer.posY - viewer.lastTickPosY) * partialTicks; - viewerZ = viewer.lastTickPosZ + (viewer.posZ - viewer.lastTickPosZ) * partialTicks; - } - - double x = block.getX() - viewerX; - double y = block.getY() - viewerY; - double z = block.getZ() - viewerZ; - - double distSq = x*x + y*y + z*z; - - if(distSq > 10*10) { - RenderUtils.renderBeaconBeam(x, y, z, rgb, 1.0f, partialTicks, true); - } else { - RenderUtils.renderBeaconBeam(x, y, z, rgb, 1.0f, partialTicks, false); - } - } - - public static void renderBeaconBeamOrBoundingBox(BlockPos block, int rgb, float alphaMult, float partialTicks) { - double viewerX; - double viewerY; - double viewerZ; - - Vector3f aoteInterpPos = CustomItemEffects.INSTANCE.getCurrentPosition(); - if(aoteInterpPos != null) { - viewerX = aoteInterpPos.x; - viewerY = aoteInterpPos.y; - viewerZ = aoteInterpPos.z; - } else { - Entity viewer = Minecraft.getMinecraft().getRenderViewEntity(); - viewerX = viewer.lastTickPosX + (viewer.posX - viewer.lastTickPosX) * partialTicks; - viewerY = viewer.lastTickPosY + (viewer.posY - viewer.lastTickPosY) * partialTicks; - viewerZ = viewer.lastTickPosZ + (viewer.posZ - viewer.lastTickPosZ) * partialTicks; - } - - double x = block.getX() - viewerX; - double y = block.getY() - viewerY; - double z = block.getZ() - viewerZ; - - double distSq = x*x + y*y + z*z; - - if(distSq > 10*10) { - RenderUtils.renderBeaconBeam(x, y, z, rgb, 1.0f, partialTicks, true); - } else { - RenderUtils.renderBoundingBox(x, y, z, rgb, 1.0f, partialTicks); - } - } - - public static void renderWayPoint(String str, BlockPos loc, float partialTicks) { - renderWayPoint(str, new Vector3f(loc.getX(), loc.getY(), loc.getZ()), partialTicks); - } - - public static void renderWayPoint(String str, Vector3f loc, float partialTicks) { - GlStateManager.alphaFunc(516, 0.1F); - - GlStateManager.pushMatrix(); - - Entity viewer = Minecraft.getMinecraft().getRenderViewEntity(); - double viewerX = viewer.lastTickPosX + (viewer.posX - viewer.lastTickPosX) * partialTicks; - double viewerY = viewer.lastTickPosY + (viewer.posY - viewer.lastTickPosY) * partialTicks; - double viewerZ = viewer.lastTickPosZ + (viewer.posZ - viewer.lastTickPosZ) * partialTicks; - - double x = loc.x-viewerX+0.5f; - double y = loc.y-viewerY-viewer.getEyeHeight(); - double z = loc.z-viewerZ+0.5f; - - double distSq = x*x + y*y + z*z; - double dist = Math.sqrt(distSq); - if(distSq > 144) { - x *= 12/dist; - y *= 12/dist; - z *= 12/dist; - } - GlStateManager.translate(x, y, z); - GlStateManager.translate(0, viewer.getEyeHeight(), 0); - - renderNametag(str); - - GlStateManager.rotate(-Minecraft.getMinecraft().getRenderManager().playerViewY, 0.0F, 1.0F, 0.0F); - GlStateManager.rotate(Minecraft.getMinecraft().getRenderManager().playerViewX, 1.0F, 0.0F, 0.0F); - GlStateManager.translate(0, -0.25f, 0); - GlStateManager.rotate(-Minecraft.getMinecraft().getRenderManager().playerViewX, 1.0F, 0.0F, 0.0F); - GlStateManager.rotate(Minecraft.getMinecraft().getRenderManager().playerViewY, 0.0F, 1.0F, 0.0F); - - renderNametag(EnumChatFormatting.YELLOW.toString()+Math.round(dist)+"m"); - - GlStateManager.popMatrix(); - - GlStateManager.disableLighting(); - } - - public static void renderNametag(String str) { - FontRenderer fontrenderer = Minecraft.getMinecraft().fontRendererObj; - float f = 1.6F; - float f1 = 0.016666668F * f; - GlStateManager.pushMatrix(); - GL11.glNormal3f(0.0F, 1.0F, 0.0F); - GlStateManager.rotate(-Minecraft.getMinecraft().getRenderManager().playerViewY, 0.0F, 1.0F, 0.0F); - GlStateManager.rotate(Minecraft.getMinecraft().getRenderManager().playerViewX, 1.0F, 0.0F, 0.0F); - GlStateManager.scale(-f1, -f1, f1); - GlStateManager.disableLighting(); - GlStateManager.depthMask(false); - GlStateManager.disableDepth(); - GlStateManager.enableBlend(); - GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); - Tessellator tessellator = Tessellator.getInstance(); - WorldRenderer worldrenderer = tessellator.getWorldRenderer(); - int i = 0; - - int j = fontrenderer.getStringWidth(str) / 2; - GlStateManager.disableTexture2D(); - worldrenderer.begin(7, DefaultVertexFormats.POSITION_COLOR); - worldrenderer.pos((double)(-j - 1), (double)(-1 + i), 0.0D).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex(); - worldrenderer.pos((double)(-j - 1), (double)(8 + i), 0.0D).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex(); - worldrenderer.pos((double)(j + 1), (double)(8 + i), 0.0D).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex(); - worldrenderer.pos((double)(j + 1), (double)(-1 + i), 0.0D).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex(); - tessellator.draw(); - GlStateManager.enableTexture2D(); - fontrenderer.drawString(str, -fontrenderer.getStringWidth(str) / 2, i, 553648127); - GlStateManager.depthMask(true); - - fontrenderer.drawString(str, -fontrenderer.getStringWidth(str) / 2, i, -1); - - GlStateManager.enableDepth(); - GlStateManager.enableBlend(); - GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); - GlStateManager.popMatrix(); - } - + public static void drawFloatingRectDark(int x, int y, int width, int height) { + drawFloatingRectDark(x, y, width, height, true); + } + + public static void drawFloatingRectDark(int x, int y, int width, int height, boolean shadow) { + int alpha = 0xf0000000; + + if (OpenGlHelper.isFramebufferEnabled()) { + ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + BackgroundBlur.renderBlurredBackground(15, scaledResolution.getScaledWidth(), + scaledResolution.getScaledHeight(), x, y, width, height, true + ); + } else { + alpha = 0xff000000; + } + + int main = alpha | 0x202026; + int light = 0xff303036; + int dark = 0xff101016; + Gui.drawRect(x, y, x + 1, y + height, light); //Left + Gui.drawRect(x + 1, y, x + width, y + 1, light); //Top + Gui.drawRect(x + width - 1, y + 1, x + width, y + height, dark); //Right + Gui.drawRect(x + 1, y + height - 1, x + width - 1, y + height, dark); //Bottom + Gui.drawRect(x + 1, y + 1, x + width - 1, y + height - 1, main); //Middle + if (shadow) { + Gui.drawRect(x + width, y + 2, x + width + 2, y + height + 2, 0x70000000); //Right shadow + Gui.drawRect(x + 2, y + height, x + width, y + height + 2, 0x70000000); //Bottom shadow + } + } + + public static void drawFloatingRect(int x, int y, int width, int height) { + drawFloatingRectWithAlpha(x, y, width, height, 0xFF, true); + } + + public static void drawFloatingRectWithAlpha(int x, int y, int width, int height, int alpha, boolean shadow) { + int main = (alpha << 24) | 0xc0c0c0; + int light = (alpha << 24) | 0xf0f0f0; + int dark = (alpha << 24) | 0x909090; + Gui.drawRect(x, y, x + 1, y + height, light); //Left + Gui.drawRect(x + 1, y, x + width, y + 1, light); //Top + Gui.drawRect(x + width - 1, y + 1, x + width, y + height, dark); //Right + Gui.drawRect(x + 1, y + height - 1, x + width - 1, y + height, dark); //Bottom + Gui.drawRect(x + 1, y + 1, x + width - 1, y + height - 1, main); //Middle + if (shadow) { + Gui.drawRect(x + width, y + 2, x + width + 2, y + height + 2, (alpha * 3 / 5) << 24); //Right shadow + Gui.drawRect(x + 2, y + height, x + width, y + height + 2, (alpha * 3 / 5) << 24); //Bottom shadow + } + } + + public static void drawTexturedRect(float x, float y, float width, float height) { + drawTexturedRect(x, y, width, height, 0, 1, 0, 1); + } + + public static void drawTexturedRect(float x, float y, float width, float height, int filter) { + drawTexturedRect(x, y, width, height, 0, 1, 0, 1, filter); + } + + public static void drawTexturedRect( + float x, + float y, + float width, + float height, + float uMin, + float uMax, + float vMin, + float vMax + ) { + drawTexturedRect(x, y, width, height, uMin, uMax, vMin, vMax, GL11.GL_NEAREST); + } + + public static void drawTexturedRect( + float x, + float y, + float width, + float height, + float uMin, + float uMax, + float vMin, + float vMax, + int filter + ) { + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + + drawTexturedRectNoBlend(x, y, width, height, uMin, uMax, vMin, vMax, filter); + + GlStateManager.disableBlend(); + } + + public static void drawTexturedRectNoBlend( + float x, + float y, + float width, + float height, + float uMin, + float uMax, + float vMin, + float vMax, + int filter + ) { + GlStateManager.enableTexture2D(); + + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, filter); + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, filter); + + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer worldrenderer = tessellator.getWorldRenderer(); + worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX); + worldrenderer + .pos(x, y + height, 0.0D) + .tex(uMin, vMax).endVertex(); + worldrenderer + .pos(x + width, y + height, 0.0D) + .tex(uMax, vMax).endVertex(); + worldrenderer + .pos(x + width, y, 0.0D) + .tex(uMax, vMin).endVertex(); + worldrenderer + .pos(x, y, 0.0D) + .tex(uMin, vMin).endVertex(); + tessellator.draw(); + + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST); + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST); + } + + public static void drawGradientRect( + int zLevel, + int left, + int top, + int right, + int bottom, + int startColor, + int endColor + ) { + float startAlpha = (float) (startColor >> 24 & 255) / 255.0F; + float startRed = (float) (startColor >> 16 & 255) / 255.0F; + float startGreen = (float) (startColor >> 8 & 255) / 255.0F; + float startBlue = (float) (startColor & 255) / 255.0F; + float endAlpha = (float) (endColor >> 24 & 255) / 255.0F; + float endRed = (float) (endColor >> 16 & 255) / 255.0F; + float endGreen = (float) (endColor >> 8 & 255) / 255.0F; + float endBlue = (float) (endColor & 255) / 255.0F; + + GlStateManager.disableTexture2D(); + GlStateManager.enableBlend(); + GlStateManager.disableAlpha(); + GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); + GlStateManager.shadeModel(7425); + + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer worldrenderer = tessellator.getWorldRenderer(); + worldrenderer.begin(7, DefaultVertexFormats.POSITION_COLOR); + worldrenderer.pos(right, top, zLevel).color(startRed, startGreen, startBlue, startAlpha).endVertex(); + worldrenderer.pos(left, top, zLevel).color(startRed, startGreen, startBlue, startAlpha).endVertex(); + worldrenderer.pos(left, bottom, zLevel).color(endRed, endGreen, endBlue, endAlpha).endVertex(); + worldrenderer.pos(right, bottom, zLevel).color(endRed, endGreen, endBlue, endAlpha).endVertex(); + tessellator.draw(); + + GlStateManager.shadeModel(7424); + GlStateManager.disableBlend(); + GlStateManager.enableAlpha(); + GlStateManager.enableTexture2D(); + } + + private static final ResourceLocation beaconBeam = new ResourceLocation("textures/entity/beacon_beam.png"); + + private static void renderBeaconBeam( + double x, double y, double z, int rgb, float alphaMult, + float partialTicks, Boolean disableDepth + ) { + int height = 300; + int bottomOffset = 0; + int topOffset = bottomOffset + height; + + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer worldrenderer = tessellator.getWorldRenderer(); + + if (disableDepth) { + GlStateManager.disableDepth(); + } + + Minecraft.getMinecraft().getTextureManager().bindTexture(beaconBeam); + GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT); + GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT); + GlStateManager.disableLighting(); + GlStateManager.enableCull(); + GlStateManager.enableTexture2D(); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE, GL11.GL_ZERO); + GlStateManager.enableBlend(); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO); + + double time = Minecraft.getMinecraft().theWorld.getTotalWorldTime() + (double) partialTicks; + double d1 = MathHelper.func_181162_h(-time * 0.2D - (double) MathHelper.floor_double(-time * 0.1D)); + + float r = ((rgb >> 16) & 0xFF) / 255f; + float g = ((rgb >> 8) & 0xFF) / 255f; + float b = (rgb & 0xFF) / 255f; + double d2 = time * 0.025D * -1.5D; + double d4 = 0.5D + Math.cos(d2 + 2.356194490192345D) * 0.2D; + double d5 = 0.5D + Math.sin(d2 + 2.356194490192345D) * 0.2D; + double d6 = 0.5D + Math.cos(d2 + (Math.PI / 4D)) * 0.2D; + double d7 = 0.5D + Math.sin(d2 + (Math.PI / 4D)) * 0.2D; + double d8 = 0.5D + Math.cos(d2 + 3.9269908169872414D) * 0.2D; + double d9 = 0.5D + Math.sin(d2 + 3.9269908169872414D) * 0.2D; + double d10 = 0.5D + Math.cos(d2 + 5.497787143782138D) * 0.2D; + double d11 = 0.5D + Math.sin(d2 + 5.497787143782138D) * 0.2D; + double d14 = -1.0D + d1; + double d15 = (double) (height) * 2.5D + d14; + worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR); + worldrenderer.pos(x + d4, y + topOffset, z + d5).tex(1.0D, d15).color(r, g, b, 1.0F * alphaMult).endVertex(); + worldrenderer.pos(x + d4, y + bottomOffset, z + d5).tex(1.0D, d14).color(r, g, b, 1.0F).endVertex(); + worldrenderer.pos(x + d6, y + bottomOffset, z + d7).tex(0.0D, d14).color(r, g, b, 1.0F).endVertex(); + worldrenderer.pos(x + d6, y + topOffset, z + d7).tex(0.0D, d15).color(r, g, b, 1.0F * alphaMult).endVertex(); + worldrenderer.pos(x + d10, y + topOffset, z + d11).tex(1.0D, d15).color(r, g, b, 1.0F * alphaMult).endVertex(); + worldrenderer.pos(x + d10, y + bottomOffset, z + d11).tex(1.0D, d14).color(r, g, b, 1.0F).endVertex(); + worldrenderer.pos(x + d8, y + bottomOffset, z + d9).tex(0.0D, d14).color(r, g, b, 1.0F).endVertex(); + worldrenderer.pos(x + d8, y + topOffset, z + d9).tex(0.0D, d15).color(r, g, b, 1.0F * alphaMult).endVertex(); + worldrenderer.pos(x + d6, y + topOffset, z + d7).tex(1.0D, d15).color(r, g, b, 1.0F * alphaMult).endVertex(); + worldrenderer.pos(x + d6, y + bottomOffset, z + d7).tex(1.0D, d14).color(r, g, b, 1.0F).endVertex(); + worldrenderer.pos(x + d10, y + bottomOffset, z + d11).tex(0.0D, d14).color(r, g, b, 1.0F).endVertex(); + worldrenderer.pos(x + d10, y + topOffset, z + d11).tex(0.0D, d15).color(r, g, b, 1.0F * alphaMult).endVertex(); + worldrenderer.pos(x + d8, y + topOffset, z + d9).tex(1.0D, d15).color(r, g, b, 1.0F * alphaMult).endVertex(); + worldrenderer.pos(x + d8, y + bottomOffset, z + d9).tex(1.0D, d14).color(r, g, b, 1.0F).endVertex(); + worldrenderer.pos(x + d4, y + bottomOffset, z + d5).tex(0.0D, d14).color(r, g, b, 1.0F).endVertex(); + worldrenderer.pos(x + d4, y + topOffset, z + d5).tex(0.0D, d15).color(r, g, b, 1.0F * alphaMult).endVertex(); + tessellator.draw(); + + GlStateManager.disableCull(); + double d12 = -1.0D + d1; + double d13 = height + d12; + + worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR); + worldrenderer.pos(x + 0.2D, y + topOffset, z + 0.2D).tex(1.0D, d13).color(r, g, b, 0.25F * alphaMult).endVertex(); + worldrenderer.pos(x + 0.2D, y + bottomOffset, z + 0.2D).tex(1.0D, d12).color(r, g, b, 0.25F).endVertex(); + worldrenderer.pos(x + 0.8D, y + bottomOffset, z + 0.2D).tex(0.0D, d12).color(r, g, b, 0.25F).endVertex(); + worldrenderer.pos(x + 0.8D, y + topOffset, z + 0.2D).tex(0.0D, d13).color(r, g, b, 0.25F * alphaMult).endVertex(); + worldrenderer.pos(x + 0.8D, y + topOffset, z + 0.8D).tex(1.0D, d13).color(r, g, b, 0.25F * alphaMult).endVertex(); + worldrenderer.pos(x + 0.8D, y + bottomOffset, z + 0.8D).tex(1.0D, d12).color(r, g, b, 0.25F).endVertex(); + worldrenderer.pos(x + 0.2D, y + bottomOffset, z + 0.8D).tex(0.0D, d12).color(r, g, b, 0.25F).endVertex(); + worldrenderer.pos(x + 0.2D, y + topOffset, z + 0.8D).tex(0.0D, d13).color(r, g, b, 0.25F * alphaMult).endVertex(); + worldrenderer.pos(x + 0.8D, y + topOffset, z + 0.2D).tex(1.0D, d13).color(r, g, b, 0.25F * alphaMult).endVertex(); + worldrenderer.pos(x + 0.8D, y + bottomOffset, z + 0.2D).tex(1.0D, d12).color(r, g, b, 0.25F).endVertex(); + worldrenderer.pos(x + 0.8D, y + bottomOffset, z + 0.8D).tex(0.0D, d12).color(r, g, b, 0.25F).endVertex(); + worldrenderer.pos(x + 0.8D, y + topOffset, z + 0.8D).tex(0.0D, d13).color(r, g, b, 0.25F * alphaMult).endVertex(); + worldrenderer.pos(x + 0.2D, y + topOffset, z + 0.8D).tex(1.0D, d13).color(r, g, b, 0.25F * alphaMult).endVertex(); + worldrenderer.pos(x + 0.2D, y + bottomOffset, z + 0.8D).tex(1.0D, d12).color(r, g, b, 0.25F).endVertex(); + worldrenderer.pos(x + 0.2D, y + bottomOffset, z + 0.2D).tex(0.0D, d12).color(r, g, b, 0.25F).endVertex(); + worldrenderer.pos(x + 0.2D, y + topOffset, z + 0.2D).tex(0.0D, d13).color(r, g, b, 0.25F * alphaMult).endVertex(); + tessellator.draw(); + + GlStateManager.disableLighting(); + GlStateManager.enableTexture2D(); + if (disableDepth) { + GlStateManager.enableDepth(); + } + } + + private static void renderBoundingBox(double x, double y, double z, int rgb, float alphaMult, float partialTicks) { + AxisAlignedBB bb = new AxisAlignedBB(x, y, z, x + 1, y + 1, z + 1); + + GlStateManager.disableDepth(); + GlStateManager.disableCull(); + GlStateManager.disableTexture2D(); + CustomItemEffects.drawFilledBoundingBox(bb, 1f, SpecialColour.special(0, 100, rgb)); + GlStateManager.enableTexture2D(); + GlStateManager.enableCull(); + GlStateManager.enableDepth(); + } + + public static void renderBeaconBeam(BlockPos block, int rgb, float alphaMult, float partialTicks) { + double viewerX; + double viewerY; + double viewerZ; + + Vector3f aoteInterpPos = CustomItemEffects.INSTANCE.getCurrentPosition(); + if (aoteInterpPos != null) { + viewerX = aoteInterpPos.x; + viewerY = aoteInterpPos.y; + viewerZ = aoteInterpPos.z; + } else { + Entity viewer = Minecraft.getMinecraft().getRenderViewEntity(); + viewerX = viewer.lastTickPosX + (viewer.posX - viewer.lastTickPosX) * partialTicks; + viewerY = viewer.lastTickPosY + (viewer.posY - viewer.lastTickPosY) * partialTicks; + viewerZ = viewer.lastTickPosZ + (viewer.posZ - viewer.lastTickPosZ) * partialTicks; + } + + double x = block.getX() - viewerX; + double y = block.getY() - viewerY; + double z = block.getZ() - viewerZ; + + double distSq = x * x + y * y + z * z; + + RenderUtils.renderBeaconBeam(x, y, z, rgb, 1.0f, partialTicks, distSq > 10 * 10); + } + + public static void renderBeaconBeamOrBoundingBox(BlockPos block, int rgb, float alphaMult, float partialTicks) { + double viewerX; + double viewerY; + double viewerZ; + + Vector3f aoteInterpPos = CustomItemEffects.INSTANCE.getCurrentPosition(); + if (aoteInterpPos != null) { + viewerX = aoteInterpPos.x; + viewerY = aoteInterpPos.y; + viewerZ = aoteInterpPos.z; + } else { + Entity viewer = Minecraft.getMinecraft().getRenderViewEntity(); + viewerX = viewer.lastTickPosX + (viewer.posX - viewer.lastTickPosX) * partialTicks; + viewerY = viewer.lastTickPosY + (viewer.posY - viewer.lastTickPosY) * partialTicks; + viewerZ = viewer.lastTickPosZ + (viewer.posZ - viewer.lastTickPosZ) * partialTicks; + } + + double x = block.getX() - viewerX; + double y = block.getY() - viewerY; + double z = block.getZ() - viewerZ; + + double distSq = x * x + y * y + z * z; + + if (distSq > 10 * 10) { + RenderUtils.renderBeaconBeam(x, y, z, rgb, 1.0f, partialTicks, true); + } else { + RenderUtils.renderBoundingBox(x, y, z, rgb, 1.0f, partialTicks); + } + } + + public static void renderWayPoint(String str, BlockPos loc, float partialTicks) { + renderWayPoint(str, new Vector3f(loc.getX(), loc.getY(), loc.getZ()), partialTicks); + } + + public static void renderWayPoint(String str, Vector3f loc, float partialTicks) { + GlStateManager.alphaFunc(516, 0.1F); + + GlStateManager.pushMatrix(); + + Entity viewer = Minecraft.getMinecraft().getRenderViewEntity(); + double viewerX = viewer.lastTickPosX + (viewer.posX - viewer.lastTickPosX) * partialTicks; + double viewerY = viewer.lastTickPosY + (viewer.posY - viewer.lastTickPosY) * partialTicks; + double viewerZ = viewer.lastTickPosZ + (viewer.posZ - viewer.lastTickPosZ) * partialTicks; + + double x = loc.x - viewerX + 0.5f; + double y = loc.y - viewerY - viewer.getEyeHeight(); + double z = loc.z - viewerZ + 0.5f; + + double distSq = x * x + y * y + z * z; + double dist = Math.sqrt(distSq); + if (distSq > 144) { + x *= 12 / dist; + y *= 12 / dist; + z *= 12 / dist; + } + GlStateManager.translate(x, y, z); + GlStateManager.translate(0, viewer.getEyeHeight(), 0); + + renderNametag(str); + + GlStateManager.rotate(-Minecraft.getMinecraft().getRenderManager().playerViewY, 0.0F, 1.0F, 0.0F); + GlStateManager.rotate(Minecraft.getMinecraft().getRenderManager().playerViewX, 1.0F, 0.0F, 0.0F); + GlStateManager.translate(0, -0.25f, 0); + GlStateManager.rotate(-Minecraft.getMinecraft().getRenderManager().playerViewX, 1.0F, 0.0F, 0.0F); + GlStateManager.rotate(Minecraft.getMinecraft().getRenderManager().playerViewY, 0.0F, 1.0F, 0.0F); + + renderNametag(EnumChatFormatting.YELLOW.toString() + Math.round(dist) + "m"); + + GlStateManager.popMatrix(); + + GlStateManager.disableLighting(); + } + + public static void renderNametag(String str) { + FontRenderer fontrenderer = Minecraft.getMinecraft().fontRendererObj; + float f = 1.6F; + float f1 = 0.016666668F * f; + GlStateManager.pushMatrix(); + GL11.glNormal3f(0.0F, 1.0F, 0.0F); + GlStateManager.rotate(-Minecraft.getMinecraft().getRenderManager().playerViewY, 0.0F, 1.0F, 0.0F); + GlStateManager.rotate(Minecraft.getMinecraft().getRenderManager().playerViewX, 1.0F, 0.0F, 0.0F); + GlStateManager.scale(-f1, -f1, f1); + GlStateManager.disableLighting(); + GlStateManager.depthMask(false); + GlStateManager.disableDepth(); + GlStateManager.enableBlend(); + GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer worldrenderer = tessellator.getWorldRenderer(); + int i = 0; + + int j = fontrenderer.getStringWidth(str) / 2; + GlStateManager.disableTexture2D(); + worldrenderer.begin(7, DefaultVertexFormats.POSITION_COLOR); + worldrenderer.pos(-j - 1, -1 + i, 0.0D).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex(); + worldrenderer.pos(-j - 1, 8 + i, 0.0D).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex(); + worldrenderer.pos(j + 1, 8 + i, 0.0D).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex(); + worldrenderer.pos(j + 1, -1 + i, 0.0D).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex(); + tessellator.draw(); + GlStateManager.enableTexture2D(); + fontrenderer.drawString(str, -fontrenderer.getStringWidth(str) / 2, i, 553648127); + GlStateManager.depthMask(true); + + fontrenderer.drawString(str, -fontrenderer.getStringWidth(str) / 2, i, -1); + + GlStateManager.enableDepth(); + GlStateManager.enableBlend(); + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + GlStateManager.popMatrix(); + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/util/render/TextRenderUtils.java b/src/main/java/io/github/moulberry/notenoughupdates/core/util/render/TextRenderUtils.java index 541fd67a0f..ff7ac53ac7 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/util/render/TextRenderUtils.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/util/render/TextRenderUtils.java @@ -13,203 +13,314 @@ import java.util.List; public class TextRenderUtils { - - public static int getCharVertLen(char c) { - if("acegmnopqrsuvwxyz".indexOf(c) >= 0) { - return 5; - } else { - return 7; - } - } - - public static float getVerticalHeight(String str) { - str = StringUtils.cleanColour(str); - float height = 0; - for(int i=0; i list = stack.getTooltip(Minecraft.getMinecraft().thePlayer, - Minecraft.getMinecraft().gameSettings.advancedItemTooltips); - - for (int i = 0; i < list.size(); ++i) { - if (i == 0) { - list.set(i, stack.getRarity().rarityColor + list.get(i)); - } else { - list.set(i, EnumChatFormatting.GRAY + list.get(i)); - } - } - - FontRenderer font = stack.getItem().getFontRenderer(stack); - drawHoveringText(list, mouseX, mouseY, screenWidth, screenHeight, -1, font == null ? fontStd : font); - } - - public static void drawHoveringText(List textLines, final int mouseX, final int mouseY, final int screenWidth, final int screenHeight, final int maxTextWidth, FontRenderer font) { - if (!textLines.isEmpty()) { - GlStateManager.disableRescaleNormal(); - RenderHelper.disableStandardItemLighting(); - GlStateManager.disableLighting(); - GlStateManager.disableDepth(); - int tooltipTextWidth = 0; - - for (String textLine : textLines) { - int textLineWidth = font.getStringWidth(textLine); - - if (textLineWidth > tooltipTextWidth) { - tooltipTextWidth = textLineWidth; - } - } - - boolean needsWrap = false; - - int titleLinesCount = 1; - int tooltipX = mouseX + 12; - if (tooltipX + tooltipTextWidth + 4 > screenWidth) { - tooltipX = mouseX - 16 - tooltipTextWidth; - if (tooltipX < 4) // if the tooltip doesn't fit on the screen - { - if (mouseX > screenWidth / 2) { - tooltipTextWidth = mouseX - 12 - 8; - } else { - tooltipTextWidth = screenWidth - 16 - mouseX; - } - needsWrap = true; - } - } - - if (maxTextWidth > 0 && tooltipTextWidth > maxTextWidth) { - tooltipTextWidth = maxTextWidth; - needsWrap = true; - } - - if (needsWrap) { - int wrappedTooltipWidth = 0; - List wrappedTextLines = new ArrayList(); - for (int i = 0; i < textLines.size(); i++) { - String textLine = textLines.get(i); - List wrappedLine = font.listFormattedStringToWidth(textLine, tooltipTextWidth); - if (i == 0) { - titleLinesCount = wrappedLine.size(); - } - - for (String line : wrappedLine) { - int lineWidth = font.getStringWidth(line); - if (lineWidth > wrappedTooltipWidth) { - wrappedTooltipWidth = lineWidth; - } - wrappedTextLines.add(line); - } - } - tooltipTextWidth = wrappedTooltipWidth; - textLines = wrappedTextLines; - - if (mouseX > screenWidth / 2) { - tooltipX = mouseX - 16 - tooltipTextWidth; - } else { - tooltipX = mouseX + 12; - } - } - - int tooltipY = mouseY - 12; - int tooltipHeight = 8; - - if (textLines.size() > 1) { - tooltipHeight += (textLines.size() - 1) * 10; - if (textLines.size() > titleLinesCount) { - tooltipHeight += 2; // gap between title lines and next lines - } - } - - if (tooltipY + tooltipHeight + 6 > screenHeight) { - tooltipY = screenHeight - tooltipHeight - 6; - } - - final int zLevel = 300; - final int backgroundColor = 0xF0100010; - RenderUtils.drawGradientRect(zLevel, tooltipX - 3, tooltipY - 4, tooltipX + tooltipTextWidth + 3, tooltipY - 3, backgroundColor, backgroundColor); - RenderUtils.drawGradientRect(zLevel, tooltipX - 3, tooltipY + tooltipHeight + 3, tooltipX + tooltipTextWidth + 3, tooltipY + tooltipHeight + 4, backgroundColor, backgroundColor); - RenderUtils.drawGradientRect(zLevel, tooltipX - 3, tooltipY - 3, tooltipX + tooltipTextWidth + 3, tooltipY + tooltipHeight + 3, backgroundColor, backgroundColor); - RenderUtils.drawGradientRect(zLevel, tooltipX - 4, tooltipY - 3, tooltipX - 3, tooltipY + tooltipHeight + 3, backgroundColor, backgroundColor); - RenderUtils.drawGradientRect(zLevel, tooltipX + tooltipTextWidth + 3, tooltipY - 3, tooltipX + tooltipTextWidth + 4, tooltipY + tooltipHeight + 3, backgroundColor, backgroundColor); - final int borderColorStart = 0x505000FF; - final int borderColorEnd = (borderColorStart & 0xFEFEFE) >> 1 | borderColorStart & 0xFF000000; - RenderUtils.drawGradientRect(zLevel, tooltipX - 3, tooltipY - 3 + 1, tooltipX - 3 + 1, tooltipY + tooltipHeight + 3 - 1, borderColorStart, borderColorEnd); - RenderUtils.drawGradientRect(zLevel, tooltipX + tooltipTextWidth + 2, tooltipY - 3 + 1, tooltipX + tooltipTextWidth + 3, tooltipY + tooltipHeight + 3 - 1, borderColorStart, borderColorEnd); - RenderUtils.drawGradientRect(zLevel, tooltipX - 3, tooltipY - 3, tooltipX + tooltipTextWidth + 3, tooltipY - 3 + 1, borderColorStart, borderColorStart); - RenderUtils.drawGradientRect(zLevel, tooltipX - 3, tooltipY + tooltipHeight + 2, tooltipX + tooltipTextWidth + 3, tooltipY + tooltipHeight + 3, borderColorEnd, borderColorEnd); - - for (int lineNumber = 0; lineNumber < textLines.size(); ++lineNumber) { - String line = textLines.get(lineNumber); - font.drawStringWithShadow(line, (float) tooltipX, (float) tooltipY, -1); - - if (lineNumber + 1 == titleLinesCount) { - tooltipY += 2; - } - - tooltipY += 10; - } - - GlStateManager.enableLighting(); - GlStateManager.enableDepth(); - RenderHelper.enableStandardItemLighting(); - GlStateManager.enableRescaleNormal(); - } - GlStateManager.disableLighting(); - } - + public static int getCharVertLen(char c) { + if ("acegmnopqrsuvwxyz".indexOf(c) >= 0) { + return 5; + } else { + return 7; + } + } + + public static float getVerticalHeight(String str) { + str = StringUtils.cleanColour(str); + float height = 0; + for (int i = 0; i < str.length(); i++) { + char c = str.charAt(i); + int charHeight = getCharVertLen(c); + height += charHeight + 1.5f; + } + return height; + } + + public static void drawStringVertical(String str, FontRenderer fr, float x, float y, boolean shadow, int colour) { + String format = FontRenderer.getFormatFromString(str); + str = StringUtils.cleanColour(str); + for (int i = 0; i < str.length(); i++) { + char c = str.charAt(i); + + int charHeight = getCharVertLen(c); + int charWidth = fr.getCharWidth(c); + fr.drawString(format + c, x + (5 - charWidth) / 2f, y - 7 + charHeight, colour, shadow); + + y += charHeight + 1.5f; + } + } + + public static void drawStringScaledMaxWidth( + String str, + FontRenderer fr, + float x, + float y, + boolean shadow, + int len, + int colour + ) { + int strLen = fr.getStringWidth(str); + float factor = len / (float) strLen; + factor = Math.min(1, factor); + + drawStringScaled(str, fr, x, y, shadow, colour, factor); + } + + public static void drawStringCentered(String str, FontRenderer fr, float x, float y, boolean shadow, int colour) { + int strLen = fr.getStringWidth(str); + + float x2 = x - strLen / 2f; + float y2 = y - fr.FONT_HEIGHT / 2f; + + GL11.glTranslatef(x2, y2, 0); + fr.drawString(str, 0, 0, colour, shadow); + GL11.glTranslatef(-x2, -y2, 0); + } + + public static void drawStringScaled( + String str, + FontRenderer fr, + float x, + float y, + boolean shadow, + int colour, + float factor + ) { + GlStateManager.scale(factor, factor, 1); + fr.drawString(str, x / factor, y / factor, colour, shadow); + GlStateManager.scale(1 / factor, 1 / factor, 1); + } + + public static void drawStringCenteredScaledMaxWidth( + String str, + FontRenderer fr, + float x, + float y, + boolean shadow, + int len, + int colour + ) { + int strLen = fr.getStringWidth(str); + float factor = len / (float) strLen; + factor = Math.min(1, factor); + int newLen = Math.min(strLen, len); + + float fontHeight = 8 * factor; + + drawStringScaled(str, fr, x - newLen / 2, y - fontHeight / 2, shadow, colour, factor); + } + + public static void renderToolTip( + ItemStack stack, + int mouseX, + int mouseY, + int screenWidth, + int screenHeight, + FontRenderer fontStd + ) { + List list = stack.getTooltip( + Minecraft.getMinecraft().thePlayer, + Minecraft.getMinecraft().gameSettings.advancedItemTooltips + ); + + for (int i = 0; i < list.size(); ++i) { + if (i == 0) { + list.set(i, stack.getRarity().rarityColor + list.get(i)); + } else { + list.set(i, EnumChatFormatting.GRAY + list.get(i)); + } + } + + FontRenderer font = stack.getItem().getFontRenderer(stack); + drawHoveringText(list, mouseX, mouseY, screenWidth, screenHeight, -1, font == null ? fontStd : font); + } + + public static void drawHoveringText( + List textLines, + final int mouseX, + final int mouseY, + final int screenWidth, + final int screenHeight, + final int maxTextWidth, + FontRenderer font + ) { + if (!textLines.isEmpty()) { + GlStateManager.disableRescaleNormal(); + RenderHelper.disableStandardItemLighting(); + GlStateManager.disableLighting(); + GlStateManager.disableDepth(); + int tooltipTextWidth = 0; + + for (String textLine : textLines) { + int textLineWidth = font.getStringWidth(textLine); + + if (textLineWidth > tooltipTextWidth) { + tooltipTextWidth = textLineWidth; + } + } + + boolean needsWrap = false; + + int titleLinesCount = 1; + int tooltipX = mouseX + 12; + if (tooltipX + tooltipTextWidth + 4 > screenWidth) { + tooltipX = mouseX - 16 - tooltipTextWidth; + if (tooltipX < 4) // if the tooltip doesn't fit on the screen + { + if (mouseX > screenWidth / 2) { + tooltipTextWidth = mouseX - 12 - 8; + } else { + tooltipTextWidth = screenWidth - 16 - mouseX; + } + needsWrap = true; + } + } + + if (maxTextWidth > 0 && tooltipTextWidth > maxTextWidth) { + tooltipTextWidth = maxTextWidth; + needsWrap = true; + } + + if (needsWrap) { + int wrappedTooltipWidth = 0; + List wrappedTextLines = new ArrayList<>(); + for (int i = 0; i < textLines.size(); i++) { + String textLine = textLines.get(i); + List wrappedLine = font.listFormattedStringToWidth(textLine, tooltipTextWidth); + if (i == 0) { + titleLinesCount = wrappedLine.size(); + } + + for (String line : wrappedLine) { + int lineWidth = font.getStringWidth(line); + if (lineWidth > wrappedTooltipWidth) { + wrappedTooltipWidth = lineWidth; + } + wrappedTextLines.add(line); + } + } + tooltipTextWidth = wrappedTooltipWidth; + textLines = wrappedTextLines; + + if (mouseX > screenWidth / 2) { + tooltipX = mouseX - 16 - tooltipTextWidth; + } else { + tooltipX = mouseX + 12; + } + } + + int tooltipY = mouseY - 12; + int tooltipHeight = 8; + + if (textLines.size() > 1) { + tooltipHeight += (textLines.size() - 1) * 10; + if (textLines.size() > titleLinesCount) { + tooltipHeight += 2; // gap between title lines and next lines + } + } + + if (tooltipY + tooltipHeight + 6 > screenHeight) { + tooltipY = screenHeight - tooltipHeight - 6; + } + + final int zLevel = 300; + final int backgroundColor = 0xF0100010; + RenderUtils.drawGradientRect( + zLevel, + tooltipX - 3, + tooltipY - 4, + tooltipX + tooltipTextWidth + 3, + tooltipY - 3, + backgroundColor, + backgroundColor + ); + RenderUtils.drawGradientRect( + zLevel, + tooltipX - 3, + tooltipY + tooltipHeight + 3, + tooltipX + tooltipTextWidth + 3, + tooltipY + tooltipHeight + 4, + backgroundColor, + backgroundColor + ); + RenderUtils.drawGradientRect( + zLevel, + tooltipX - 3, + tooltipY - 3, + tooltipX + tooltipTextWidth + 3, + tooltipY + tooltipHeight + 3, + backgroundColor, + backgroundColor + ); + RenderUtils.drawGradientRect( + zLevel, + tooltipX - 4, + tooltipY - 3, + tooltipX - 3, + tooltipY + tooltipHeight + 3, + backgroundColor, + backgroundColor + ); + RenderUtils.drawGradientRect( + zLevel, + tooltipX + tooltipTextWidth + 3, + tooltipY - 3, + tooltipX + tooltipTextWidth + 4, + tooltipY + tooltipHeight + 3, + backgroundColor, + backgroundColor + ); + final int borderColorStart = 0x505000FF; + final int borderColorEnd = (borderColorStart & 0xFEFEFE) >> 1 | borderColorStart & 0xFF000000; + RenderUtils.drawGradientRect( + zLevel, + tooltipX - 3, + tooltipY - 3 + 1, + tooltipX - 3 + 1, + tooltipY + tooltipHeight + 3 - 1, + borderColorStart, + borderColorEnd + ); + RenderUtils.drawGradientRect( + zLevel, + tooltipX + tooltipTextWidth + 2, + tooltipY - 3 + 1, + tooltipX + tooltipTextWidth + 3, + tooltipY + tooltipHeight + 3 - 1, + borderColorStart, + borderColorEnd + ); + RenderUtils.drawGradientRect( + zLevel, + tooltipX - 3, + tooltipY - 3, + tooltipX + tooltipTextWidth + 3, + tooltipY - 3 + 1, + borderColorStart, + borderColorStart + ); + RenderUtils.drawGradientRect( + zLevel, + tooltipX - 3, + tooltipY + tooltipHeight + 2, + tooltipX + tooltipTextWidth + 3, + tooltipY + tooltipHeight + 3, + borderColorEnd, + borderColorEnd + ); + + for (int lineNumber = 0; lineNumber < textLines.size(); ++lineNumber) { + String line = textLines.get(lineNumber); + font.drawStringWithShadow(line, (float) tooltipX, (float) tooltipY, -1); + + if (lineNumber + 1 == titleLinesCount) { + tooltipY += 2; + } + + tooltipY += 10; + } + + GlStateManager.enableLighting(); + GlStateManager.enableDepth(); + RenderHelper.enableStandardItemLighting(); + GlStateManager.enableRescaleNormal(); + } + GlStateManager.disableLighting(); + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java index 0ec52ec8f3..3f7476bd57 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java @@ -2,33 +2,23 @@ import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; -import com.google.common.collect.Maps; import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import io.github.moulberry.notenoughupdates.NEUManager; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; -import io.github.moulberry.notenoughupdates.util.HypixelApi; import net.minecraft.client.Minecraft; -import net.minecraft.client.entity.EntityPlayerSP; -import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.OpenGlHelper; import net.minecraft.client.shader.Framebuffer; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.potion.Potion; import net.minecraftforge.client.event.RenderPlayerEvent; -import net.minecraftforge.client.event.RenderWorldEvent; -import net.minecraftforge.client.event.RenderWorldLastEvent; import net.minecraftforge.event.world.WorldEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.TickEvent; -import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.tuple.MutablePair; import org.apache.commons.lang3.tuple.Pair; -import org.lwjgl.input.Keyboard; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL30; -import java.io.IOException; import java.util.HashMap; import java.util.HashSet; import java.util.Set; @@ -36,352 +26,334 @@ import java.util.concurrent.Executors; public class CapeManager { - - public static final CapeManager INSTANCE = new CapeManager(); - public long lastCapeUpdate = 0; - public long lastCapeSynced = 0; - - public Pair localCape = null; - private HashMap> capeMap = new HashMap<>(); - - private int permSyncTries = 5; - private boolean allAvailable = false; - private HashSet availableCapes = new HashSet<>(); - - public JsonObject lastJsonSync = null; - - public static class CapeData { - public String capeName; - public boolean special; - public boolean hidden; - - public boolean canShow() { - return !special && !hidden; - } - - public CapeData(String capeName, boolean special, boolean hidden) { - this.capeName = capeName; - this.special = special; - this.hidden = hidden; - } - } - - public CapeData[] capes = new CapeData[]{ - - //Admins - new CapeData("nullzee", true, false), - new CapeData("ironmoon", true, false), - new CapeData("gravy", true, false), - - //Special Other - new CapeData("contrib", true, false), - new CapeData("mbstaff", true, false), - - //Partner - new CapeData("thebakery", true, false), - new CapeData("furf", true, false), - new CapeData("dsm", true, false), - new CapeData("skyclient", true, false), - new CapeData("subreddit_dark", true, false), - new CapeData("subreddit_light", true, false), - new CapeData("packshq", true, false), - new CapeData("skytils", true, false), - new CapeData("sbp", true, false), - new CapeData("sharex", true, false), - new CapeData("sharex_white", true, false), - - //Content Creator - new CapeData("jakethybro", false, true), - new CapeData("krusty", false, true), - new CapeData("krusty_day", false, true), - new CapeData("krusty_sunset", false, true), - new CapeData("krusty_night", false, true), - new CapeData("zera", false, true), - new CapeData("soldier", false, true), - new CapeData("alexxoffi", false, true), - new CapeData("secondpfirsisch", false, true), - new CapeData("stormy_lh", false, true), - - //Patreon - new CapeData("patreon1", false, false), - new CapeData("patreon2", false, false), - new CapeData("fade", false, false), - new CapeData("space", false, false), - new CapeData("mcworld", false, false), - new CapeData("negative", false, false), - new CapeData("void", false, false), - new CapeData("lava", false, false), - new CapeData("tunnel", false, false), - new CapeData("planets", false, false) - - - }; - - /*private String[] capes = new String[]{"patreon1", "patreon2", "fade", "contrib", "nullzee", - "gravy", "space", "mcworld", "lava", "packshq", "mbstaff", "thebakery", "negative", - "void", "ironmoon", "krusty", "furf", "soldier", "dsm", "zera", "tunnel", "alexxoffi", "parallax", "jakethybro", "planets", "skytils" }; - public Boolean[] specialCapes = new Boolean[] {true, true, false, true, true, - true, false, false, false, true, true, true, false, - false, true, false, true, true, true, true, false, true, true, true, true, true };*/ - - public static CapeManager getInstance() { - return INSTANCE; - } - - public void tryUnlockCape(String unlock) { - for(CapeData data : capes) { - if(data.capeName.equalsIgnoreCase(unlock)) { - data.hidden = false; - } - } - } - - public void tick() { - long currentTime = System.currentTimeMillis(); - if(currentTime - lastCapeUpdate > 60*1000) { - lastCapeUpdate = currentTime; - updateCapes(); - } - } - - private void updateCapes() { - - NotEnoughUpdates.INSTANCE.manager.hypixelApi.getMyApiAsync("activecapes.json", (jsonObject) -> { - if(jsonObject.get("success").getAsBoolean()) { - lastJsonSync = jsonObject; - - lastCapeSynced = System.currentTimeMillis(); - capeMap.clear(); - for(JsonElement active : jsonObject.get("active").getAsJsonArray()) { - if(active.isJsonObject()) { - JsonObject activeObj = (JsonObject) active; - setCape(activeObj.get("_id").getAsString(), activeObj.get("capeType").getAsString(), false); - } - } - } - }, () -> { - System.out.println("[MBAPI] Update capes errored"); - }); - - if(Minecraft.getMinecraft().thePlayer != null && permSyncTries > 0) { - String uuid = Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", ""); - permSyncTries--; - NotEnoughUpdates.INSTANCE.manager.hypixelApi.getMyApiAsync("permscapes.json", (jsonObject) -> { - if(jsonObject.get("success").getAsBoolean()) { - permSyncTries = 0; - - availableCapes.clear(); - for(JsonElement permPlayer : jsonObject.get("perms").getAsJsonArray()) { - if(permPlayer.isJsonObject()) { - String playerUuid = permPlayer.getAsJsonObject().get("_id").getAsString(); - if(playerUuid != null && playerUuid.equals(uuid)) { - for(JsonElement perm : permPlayer.getAsJsonObject().get("perms").getAsJsonArray()) { - if(perm.isJsonPrimitive()) { - String cape = perm.getAsString(); - if(cape.equals("*")) { - allAvailable = true; - } else { - availableCapes.add(cape); - } - } - } - return; - } - } - } - } - }, () -> { - System.out.println("[MBAPI] Update capes errored - perms"); - }); - } - } - - public HashSet getAvailableCapes() { - return allAvailable ? null : availableCapes; - } - - public void setCape(String playerUUID, String capename, boolean updateConfig) { - boolean none = capename == null || capename.equals("null"); - - updateConfig = updateConfig && playerUUID.equals(Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", "")); - if(updateConfig) { - NotEnoughUpdates.INSTANCE.config.hidden.selectedCape = String.valueOf(capename); - } - - if(updateConfig) { - if(none) { - localCape = null; - } else { - localCape = new MutablePair<>(new NEUCape(capename), capename); - } - } else if(capeMap.containsKey(playerUUID)) { - if(none) { - capeMap.remove(playerUUID); - } else { - Pair capePair = capeMap.get(playerUUID); - capePair.setValue(capename); - } - } else if(!none) { - capeMap.put(playerUUID, new MutablePair<>(new NEUCape(capename), capename)); - } - } - - public String getCape(String player) { - if(capeMap.containsKey(player)) { - return capeMap.get(player).getRight(); - } - return null; - } - - private static BiMap playerMap = null; - - public EntityPlayer getPlayerForUUID(String uuid) { - if(playerMap == null) { - return null; - } - if(playerMap.containsKey(uuid)) { - return playerMap.get(uuid); - } - return null; - } - - private static Framebuffer checkFramebufferSizes(Framebuffer framebuffer, int width, int height) { - if(framebuffer == null || framebuffer.framebufferWidth != width || framebuffer.framebufferHeight != height) { - if(framebuffer == null) { - framebuffer = new Framebuffer(width, height, true); - } else { - framebuffer.createBindFramebuffer(width, height); - } - framebuffer.setFramebufferFilter(GL11.GL_NEAREST); - } - return framebuffer; - } - - public boolean updateWorldFramebuffer = false; - public Framebuffer backgroundFramebuffer = null; - - public void postRenderBlocks() { - int width = Minecraft.getMinecraft().displayWidth; - int height = Minecraft.getMinecraft().displayHeight; - backgroundFramebuffer = checkFramebufferSizes(backgroundFramebuffer, - width, height); - - if(OpenGlHelper.isFramebufferEnabled() && updateWorldFramebuffer) { - GL30.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, Minecraft.getMinecraft().getFramebuffer().framebufferObject); - GL30.glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, backgroundFramebuffer.framebufferObject); - GL30.glBlitFramebuffer(0, 0, width, height, - 0, 0, width, height, - GL11.GL_COLOR_BUFFER_BIT, GL11.GL_NEAREST); - - Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true); - } - - updateWorldFramebuffer = false; - } - - @SubscribeEvent - public void onWorldLoad(WorldEvent.Unload event) { - if(playerMap != null) playerMap.clear(); - } - - @SubscribeEvent - public void onRenderPlayer(RenderPlayerEvent.Post e) { - if(e.partialRenderTick == 1.0F) return; //rendering in inventory - - try { - String uuid = e.entityPlayer.getUniqueID().toString().replace("-", ""); - String clientUuid = Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", ""); - - if(Minecraft.getMinecraft().thePlayer != null && uuid.equals(clientUuid)) { - String selCape = NotEnoughUpdates.INSTANCE.config.hidden.selectedCape; - if(selCape != null && !selCape.isEmpty()) { - if(localCape == null) { - localCape = new MutablePair<>(new NEUCape(selCape), selCape); - } else { - localCape.setValue(selCape); - } - } - } - if(uuid.equals(clientUuid) && localCape != null && localCape.getRight() != null && !localCape.getRight().equals("null")) { - localCape.getLeft().onRenderPlayer(e); - } else if(!Minecraft.getMinecraft().thePlayer.isPotionActive(Potion.blindness) && capeMap.containsKey(uuid)) { - capeMap.get(uuid).getLeft().onRenderPlayer(e); - } - } catch(Exception ignored) {} - } - - public static void onTickSlow() { - if(Minecraft.getMinecraft().theWorld == null) return; - - if(playerMap == null) { - playerMap = HashBiMap.create(Minecraft.getMinecraft().theWorld.playerEntities.size()); - } - playerMap.clear(); - for(EntityPlayer player : Minecraft.getMinecraft().theWorld.playerEntities) { - String uuid = player.getUniqueID().toString().replace("-", ""); - try { - playerMap.put(uuid, player); - } catch(IllegalArgumentException ignored){} - } - } - - private static final ExecutorService capeTicker = Executors.newCachedThreadPool(); - - @SubscribeEvent - public void onTick(TickEvent.ClientTickEvent event) { - if (event.phase != TickEvent.Phase.END) return; - if(Minecraft.getMinecraft().theWorld == null) return; - - if(playerMap == null) { - return; - } - - String clientUuid = null; - if(Minecraft.getMinecraft().thePlayer != null) { - clientUuid = Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", ""); - } - - boolean hasLocalCape = localCape != null && localCape.getRight() != null && !localCape.getRight().equals("null"); - - Set toRemove = new HashSet<>(); - try { - for(String playerUUID : capeMap.keySet()) { - EntityPlayer player; - if(playerUUID.equals(clientUuid)) { - player = Minecraft.getMinecraft().thePlayer; - } else { - player = getPlayerForUUID(playerUUID); - } - if(player != null) { - String capeName = capeMap.get(playerUUID).getRight(); - if(capeName != null && !capeName.equals("null")) { - if(player == Minecraft.getMinecraft().thePlayer && hasLocalCape) { - continue; - } - capeMap.get(playerUUID).getLeft().setCapeTexture(capeName); - capeTicker.submit(() -> { - capeMap.get(playerUUID).getLeft().onTick(event, player); - }); - } else { - toRemove.add(playerUUID); - } - } - } - } catch(Exception e) {} - - if(hasLocalCape) { - localCape.getLeft().setCapeTexture(localCape.getValue()); - capeTicker.submit(() -> { - localCape.getLeft().onTick(event, Minecraft.getMinecraft().thePlayer); - }); - } - for(String playerName : toRemove) { - capeMap.remove(playerName); - } - } - - public CapeData[] getCapes() { - return capes; - } - + public static final CapeManager INSTANCE = new CapeManager(); + public long lastCapeUpdate = 0; + public long lastCapeSynced = 0; + + public Pair localCape = null; + private final HashMap> capeMap = new HashMap<>(); + + private int permSyncTries = 5; + private boolean allAvailable = false; + private final HashSet availableCapes = new HashSet<>(); + + public JsonObject lastJsonSync = null; + + public static class CapeData { + public String capeName; + public boolean special; + public boolean hidden; + + public boolean canShow() { + return !special && !hidden; + } + + public CapeData(String capeName, boolean special, boolean hidden) { + this.capeName = capeName; + this.special = special; + this.hidden = hidden; + } + } + + public CapeData[] capes = new CapeData[]{ + //Patreon + new CapeData("patreon1", false, false), + new CapeData("patreon2", false, false), + new CapeData("fade", false, false), + new CapeData("space", false, false), + new CapeData("mcworld", false, false), + new CapeData("negative", false, false), + new CapeData("void", false, false), + new CapeData("lava", false, false), + new CapeData("tunnel", false, false), + new CapeData("planets", false, false), + + //Admins + new CapeData("nullzee", true, false), + new CapeData("ironmoon", true, false), + new CapeData("gravy", true, false), + + //Special Other + new CapeData("contrib", true, false), + new CapeData("mbstaff", true, false), + + //Partner + new CapeData("thebakery", true, false), + new CapeData("furf", true, false), + new CapeData("dsm", true, false), + new CapeData("skyclient", true, false), + new CapeData("subreddit_dark", true, false), + new CapeData("subreddit_light", true, false), + new CapeData("packshq", true, false), + new CapeData("skytils", true, false), + new CapeData("sbp", true, false), + new CapeData("sharex", true, false), + new CapeData("sharex_white", true, false), + new CapeData("dg", true, false), + + //Content Creator + new CapeData("jakethybro", false, true), + new CapeData("krusty", false, true), + new CapeData("krusty_day", false, true), + new CapeData("krusty_sunset", false, true), + new CapeData("krusty_night", false, true), + new CapeData("zera", false, true), + new CapeData("soldier", false, true), + new CapeData("alexxoffi", false, true), + new CapeData("secondpfirsisch", false, true), + new CapeData("stormy_lh", false, true), + }; + + public static CapeManager getInstance() { + return INSTANCE; + } + + public void tryUnlockCape(String unlock) { + for (CapeData data : capes) { + if (data.capeName.equalsIgnoreCase(unlock)) { + data.hidden = false; + } + } + } + + public void tick() { + long currentTime = System.currentTimeMillis(); + if (currentTime - lastCapeUpdate > 60 * 1000) { + lastCapeUpdate = currentTime; + updateCapes(); + } + } + + private void updateCapes() { + NotEnoughUpdates.INSTANCE.manager.hypixelApi.getMyApiAsync("activecapes.json", (jsonObject) -> { + if (jsonObject.get("success").getAsBoolean()) { + lastJsonSync = jsonObject; + + lastCapeSynced = System.currentTimeMillis(); + capeMap.clear(); + for (JsonElement active : jsonObject.get("active").getAsJsonArray()) { + if (active.isJsonObject()) { + JsonObject activeObj = (JsonObject) active; + setCape(activeObj.get("_id").getAsString(), activeObj.get("capeType").getAsString(), false); + } + } + } + }, () -> System.out.println("[MBAPI] Update capes errored")); + + if (Minecraft.getMinecraft().thePlayer != null && permSyncTries > 0) { + String uuid = Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", ""); + permSyncTries--; + NotEnoughUpdates.INSTANCE.manager.hypixelApi.getMyApiAsync("permscapes.json", (jsonObject) -> { + if (!jsonObject.get("success").getAsBoolean()) return; + + permSyncTries = 0; + availableCapes.clear(); + for (JsonElement permPlayer : jsonObject.get("perms").getAsJsonArray()) { + if (!permPlayer.isJsonObject()) continue; + String playerUuid = permPlayer.getAsJsonObject().get("_id").getAsString(); + if (!(playerUuid != null && playerUuid.equals(uuid))) continue; + for (JsonElement perm : permPlayer.getAsJsonObject().get("perms").getAsJsonArray()) { + if (!perm.isJsonPrimitive()) continue; + String cape = perm.getAsString(); + if (cape.equals("*")) { + allAvailable = true; + } else { + availableCapes.add(cape); + } + + } + return; + } + }, () -> System.out.println("[MBAPI] Update capes errored - perms")); + } + } + + public HashSet getAvailableCapes() { + return allAvailable ? null : availableCapes; + } + + public void setCape(String playerUUID, String capename, boolean updateConfig) { + boolean none = capename == null || capename.equals("null"); + + updateConfig = updateConfig && playerUUID.equals(Minecraft.getMinecraft().thePlayer + .getUniqueID() + .toString() + .replace("-", "")); + if (updateConfig) { + NotEnoughUpdates.INSTANCE.config.hidden.selectedCape = String.valueOf(capename); + } + + if (updateConfig) { + localCape = none ? null : new MutablePair<>(new NEUCape(capename), capename); + } else if (capeMap.containsKey(playerUUID)) { + if (none) { + capeMap.remove(playerUUID); + } else { + Pair capePair = capeMap.get(playerUUID); + capePair.setValue(capename); + } + } else if (!none) { + capeMap.put(playerUUID, new MutablePair<>(new NEUCape(capename), capename)); + } + } + + public String getCape(String player) { + if (capeMap.containsKey(player)) { + return capeMap.get(player).getRight(); + } + return null; + } + + private static BiMap playerMap = null; + + public EntityPlayer getPlayerForUUID(String uuid) { + if (playerMap == null) { + return null; + } + if (playerMap.containsKey(uuid)) { + return playerMap.get(uuid); + } + return null; + } + + private static Framebuffer checkFramebufferSizes(Framebuffer framebuffer, int width, int height) { + if (framebuffer == null || framebuffer.framebufferWidth != width || framebuffer.framebufferHeight != height) { + if (framebuffer == null) { + framebuffer = new Framebuffer(width, height, true); + } else { + framebuffer.createBindFramebuffer(width, height); + } + framebuffer.setFramebufferFilter(GL11.GL_NEAREST); + } + return framebuffer; + } + + public boolean updateWorldFramebuffer = false; + public Framebuffer backgroundFramebuffer = null; + + public void postRenderBlocks() { + int width = Minecraft.getMinecraft().displayWidth; + int height = Minecraft.getMinecraft().displayHeight; + backgroundFramebuffer = checkFramebufferSizes(backgroundFramebuffer, + width, height + ); + + if (OpenGlHelper.isFramebufferEnabled() && updateWorldFramebuffer) { + GL30.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, Minecraft.getMinecraft().getFramebuffer().framebufferObject); + GL30.glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, backgroundFramebuffer.framebufferObject); + GL30.glBlitFramebuffer(0, 0, width, height, + 0, 0, width, height, + GL11.GL_COLOR_BUFFER_BIT, GL11.GL_NEAREST + ); + + Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true); + } + + updateWorldFramebuffer = false; + } + + @SubscribeEvent + public void onWorldLoad(WorldEvent.Unload event) { + if (playerMap != null) playerMap.clear(); + } + + @SubscribeEvent + public void onRenderPlayer(RenderPlayerEvent.Post e) { + if (e.partialRenderTick == 1.0F) return; //rendering in inventory + + try { + String uuid = e.entityPlayer.getUniqueID().toString().replace("-", ""); + String clientUuid = Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", ""); + + if (Minecraft.getMinecraft().thePlayer != null && uuid.equals(clientUuid)) { + String selCape = NotEnoughUpdates.INSTANCE.config.hidden.selectedCape; + if (selCape != null && !selCape.isEmpty()) { + if (localCape == null) { + localCape = new MutablePair<>(new NEUCape(selCape), selCape); + } else { + localCape.setValue(selCape); + } + } + } + if (uuid.equals(clientUuid) && localCape != null && localCape.getRight() != null && !localCape.getRight().equals( + "null")) { + localCape.getLeft().onRenderPlayer(e); + } else if (!Minecraft.getMinecraft().thePlayer.isPotionActive(Potion.blindness) && capeMap.containsKey(uuid)) { + capeMap.get(uuid).getLeft().onRenderPlayer(e); + } + } catch (Exception ignored) { + } + } + + public static void onTickSlow() { + if (Minecraft.getMinecraft().theWorld == null) return; + + if (playerMap == null) { + playerMap = HashBiMap.create(Minecraft.getMinecraft().theWorld.playerEntities.size()); + } + playerMap.clear(); + for (EntityPlayer player : Minecraft.getMinecraft().theWorld.playerEntities) { + String uuid = player.getUniqueID().toString().replace("-", ""); + try { + playerMap.put(uuid, player); + } catch (IllegalArgumentException ignored) { + } + } + } + + private static final ExecutorService capeTicker = Executors.newCachedThreadPool(); + + @SubscribeEvent + public void onTick(TickEvent.ClientTickEvent event) { + if (event.phase != TickEvent.Phase.END) return; + if (Minecraft.getMinecraft().theWorld == null) return; + + if (playerMap == null) { + return; + } + + String clientUuid = null; + if (Minecraft.getMinecraft().thePlayer != null) { + clientUuid = Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", ""); + } + + boolean hasLocalCape = localCape != null && localCape.getRight() != null && !localCape.getRight().equals("null"); + + Set toRemove = new HashSet<>(); + try { + for (String playerUUID : capeMap.keySet()) { + EntityPlayer player; + if (playerUUID.equals(clientUuid)) { + player = Minecraft.getMinecraft().thePlayer; + } else { + player = getPlayerForUUID(playerUUID); + } + if (player != null) { + String capeName = capeMap.get(playerUUID).getRight(); + if (capeName != null && !capeName.equals("null")) { + if (player == Minecraft.getMinecraft().thePlayer && hasLocalCape) { + continue; + } + capeMap.get(playerUUID).getLeft().setCapeTexture(capeName); + capeTicker.submit(() -> capeMap.get(playerUUID).getLeft().onTick(event, player)); + } else { + toRemove.add(playerUUID); + } + } + } + } catch (Exception ignored) { + } + + if (hasLocalCape) { + localCape.getLeft().setCapeTexture(localCape.getValue()); + capeTicker.submit(() -> localCape.getLeft().onTick(event, Minecraft.getMinecraft().thePlayer)); + } + for (String playerName : toRemove) { + capeMap.remove(playerName); + } + } + + public CapeData[] getCapes() { + return capes; + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeNode.java b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeNode.java index 06bc6db402..c32cc98f69 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeNode.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeNode.java @@ -1,14 +1,8 @@ package io.github.moulberry.notenoughupdates.cosmetics; -import net.minecraft.block.Block; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; -import net.minecraft.util.BlockPos; -import net.minecraft.util.MathHelper; -import org.lwjgl.input.Keyboard; import org.lwjgl.opengl.GL11; import org.lwjgl.util.vector.Vector2f; import org.lwjgl.util.vector.Vector3f; @@ -19,101 +13,108 @@ import java.util.List; public class CapeNode { - - private static final NEUCape.Direction[] cardinals = new NEUCape.Direction[]{NEUCape.Direction.UP, NEUCape.Direction.RIGHT, NEUCape.Direction.DOWN, NEUCape.Direction.LEFT}; - - public Vector3f position; - public Vector3f lastPosition = new Vector3f(); - public Vector3f renderPosition = new Vector3f(); - public final Vector3f[] oldRenderPosition = new Vector3f[5]; - public final Vector3f velocity = new Vector3f(); - public Vector3f normal = null; - public Vector3f sideNormal = null; - public boolean fixed = false; - - public static final int DRAW_MASK_FRONT = 0b1; - public static final int DRAW_MASK_BACK = 0b10; - public static final int DRAW_MASK_SIDES = 0b100; - - public HashMap neighbors = new HashMap<>(); - - public float texU = 0; - public float texV = 0; - - public float horzDistMult = 2f; - public float vertDistMult = 0.5f; - - public float horzSideTexU = 0; - public float horzSideTexVTop = 0; - - public float vertSideTexU = 0; - public float vertSideTexVTop = 0; - - public final float gravity = 0.1f; - public final float resistance = 0.5f; - - public static final int FLOAT_NUM = 20; - - public CapeNode(float x, float y, float z) { - this.position = new Vector3f(x, y, z); - } - - private List getConstaints() { - List constaints = new ArrayList<>(); - for(NEUCape.Direction cardinal : cardinals) { - for(int i=1; i<=2; i++) { - NEUCape.Offset offset = new NEUCape.Offset(cardinal, i); - CapeNode other = neighbors.get(offset); - if(other != null) { - int iOffset = offset.getXOffset() + NEUCape.HORZ_NODES * offset.getYOffset(); - constaints.add(new Vector2f(iOffset, i*NEUCape.targetDist*(cardinal.yOff==0?horzDistMult:vertDistMult))); - } - } - - } - return constaints; - } - - public void loadIntoBuffer(FloatBuffer buffer) { - loadVec3IntoBuffer(buffer, position); - List containts = getConstaints(); - buffer.put(containts.size()); - for(int i=0; i<8; i++) { - if(i < containts.size()) { - loadVec2IntoBuffer(buffer, containts.get(i)); - } else { - loadVec2IntoBuffer(buffer, new Vector2f()); - } - } - } - - public void readFromBuffer(FloatBuffer buffer) { - readVec3FromBuffer(buffer, position); - buffer.position(buffer.position()+17); - } - - private void readVec3FromBuffer(FloatBuffer buffer, Vector3f vec) { - vec.x = buffer.get(); - vec.y = buffer.get(); - vec.z = buffer.get(); - } - - private void loadVec2IntoBuffer(FloatBuffer buffer, Vector2f vec) { - buffer.put(vec.x); - buffer.put(vec.y); - } - - private void loadVec3IntoBuffer(FloatBuffer buffer, Vector3f vec) { - buffer.put(vec.x); - buffer.put(vec.y); - buffer.put(vec.z); - } - - public void update() { - if(!fixed) { - velocity.y -= gravity * (resistance)/(1-resistance); - - float actualResistance = resistance; + private static final NEUCape.Direction[] cardinals = new NEUCape.Direction[]{ + NEUCape.Direction.UP, + NEUCape.Direction.RIGHT, + NEUCape.Direction.DOWN, + NEUCape.Direction.LEFT + }; + + public Vector3f position; + public Vector3f lastPosition = new Vector3f(); + public Vector3f renderPosition = new Vector3f(); + public final Vector3f[] oldRenderPosition = new Vector3f[5]; + public final Vector3f velocity = new Vector3f(); + public Vector3f normal = null; + public Vector3f sideNormal = null; + public boolean fixed = false; + + public static final int DRAW_MASK_FRONT = 0b1; + public static final int DRAW_MASK_BACK = 0b10; + public static final int DRAW_MASK_SIDES = 0b100; + + public HashMap neighbors = new HashMap<>(); + + public float texU = 0; + public float texV = 0; + + public float horzDistMult = 2f; + public float vertDistMult = 0.5f; + + public float horzSideTexU = 0; + public float horzSideTexVTop = 0; + + public float vertSideTexU = 0; + public float vertSideTexVTop = 0; + + public final float gravity = 0.1f; + public final float resistance = 0.5f; + + public static final int FLOAT_NUM = 20; + + public CapeNode(float x, float y, float z) { + this.position = new Vector3f(x, y, z); + } + + private List getConstaints() { + List constaints = new ArrayList<>(); + for (NEUCape.Direction cardinal : cardinals) { + for (int i = 1; i <= 2; i++) { + NEUCape.Offset offset = new NEUCape.Offset(cardinal, i); + CapeNode other = neighbors.get(offset); + if (other != null) { + int iOffset = offset.getXOffset() + NEUCape.HORZ_NODES * offset.getYOffset(); + constaints.add(new Vector2f( + iOffset, + i * NEUCape.targetDist * (cardinal.yOff == 0 ? horzDistMult : vertDistMult) + )); + } + } + + } + return constaints; + } + + public void loadIntoBuffer(FloatBuffer buffer) { + loadVec3IntoBuffer(buffer, position); + List containts = getConstaints(); + buffer.put(containts.size()); + for (int i = 0; i < 8; i++) { + if (i < containts.size()) { + loadVec2IntoBuffer(buffer, containts.get(i)); + } else { + loadVec2IntoBuffer(buffer, new Vector2f()); + } + } + } + + public void readFromBuffer(FloatBuffer buffer) { + readVec3FromBuffer(buffer, position); + buffer.position(buffer.position() + 17); + } + + private void readVec3FromBuffer(FloatBuffer buffer, Vector3f vec) { + vec.x = buffer.get(); + vec.y = buffer.get(); + vec.z = buffer.get(); + } + + private void loadVec2IntoBuffer(FloatBuffer buffer, Vector2f vec) { + buffer.put(vec.x); + buffer.put(vec.y); + } + + private void loadVec3IntoBuffer(FloatBuffer buffer, Vector3f vec) { + buffer.put(vec.x); + buffer.put(vec.y); + buffer.put(vec.z); + } + + public void update() { + if (!fixed) { + velocity.y -= gravity * (resistance) / (1 - resistance); + + float actualResistance = resistance; /*BlockPos pos = new BlockPos( MathHelper.floor_double(position.x), MathHelper.floor_double(position.y), @@ -123,249 +124,271 @@ public void update() { actualResistance = 0.8f; }*/ - velocity.scale(1-actualResistance); - - Vector3f.add(position, velocity, position); - } - } - - public final CapeNode getNeighbor(NEUCape.Offset offset) { - return neighbors.get(offset); - } - - public final void setNeighbor(NEUCape.Offset offset, CapeNode node) { - neighbors.put(offset, node); - } - - public void applyForce(float dX, float dY, float dZ) { - velocity.x += dX; - velocity.y += dY; - velocity.z += dZ; - } - - public void move(float dX, float dY, float dZ) { - position.x += dX; - position.y += dY; - position.z += dZ; - lastPosition.x = position.x; - lastPosition.y = position.y; - lastPosition.z = position.z; - } - - public void resetNormal() { - normal = null; - sideNormal = null; - } - - public void resolveAll(float horzDistMult, boolean opt) { - resolveBend(horzDistMult, opt); - //resolveShear(); - resolveStruct(horzDistMult, opt); - } - - public void resolve(CapeNode other, float targetDist, float strength, boolean opt) { - double dX = position.x - other.position.x; - double dY = position.y - other.position.y; - double dZ = position.z - other.position.z; - - double distSq = dX*dX + dY*dY + dZ*dZ; - - double factor = (distSq - targetDist*targetDist)/(40*distSq)*strength; - - factor = Math.max(-0.5f, factor); - dX *= factor; - dY *= factor; - dZ *= factor; - - if(fixed || other.fixed) { - dX *= 2; - dY *= 2; - dZ *= 2; - } - - if(!fixed) { - position.x -= dX; - position.y -= dY; - position.z -= dZ; - } - - if(!other.fixed) { - other.position.x += dX; - other.position.y += dY; - other.position.z += dZ; - } - } - - public void resolveStruct(float horzDistMult, boolean opt) { - for(NEUCape.Direction cardinal : cardinals) { - NEUCape.Offset offset = new NEUCape.Offset(cardinal, 1); - CapeNode other = neighbors.get(offset); - if(other != null) { - resolve(other, NEUCape.targetDist*(cardinal.yOff==0?horzDistMult:1), 2f*7.5f, opt); - } - } - } - - public void resolveShear(float horzDistMult, boolean opt) { - for(NEUCape.Direction d : new NEUCape.Direction[]{NEUCape.Direction.DOWNLEFT, NEUCape.Direction.UPLEFT, NEUCape.Direction.DOWNRIGHT, NEUCape.Direction.DOWNLEFT}) { - NEUCape.Offset o = new NEUCape.Offset(d, 1); - CapeNode neighbor = getNeighbor(o); - if(neighbor != null) { - resolve(neighbor, 1f*NEUCape.targetDist*(d.yOff==0?horzDistMult:1f), 0.5f*7.5f, opt); - } - } - } - - public void resolveBend(float horzDistMult, boolean opt) { - for(NEUCape.Direction cardinal : cardinals) { - NEUCape.Offset offset = new NEUCape.Offset(cardinal, 2); - CapeNode other = neighbors.get(offset); - if(other != null) { - resolve(other, 2f*NEUCape.targetDist*(cardinal.yOff==0?horzDistMult:1), 1f*7.5f, opt); - } - } - } - - public Vector3f normal() { - if(normal != null) return normal; - - normal = new Vector3f(); - for(int i=0; i cosmeticsInfoTooltip = null; - - - - public GuiCosmetics(){ - Gson gson = new Gson(); - - JsonElement cosmeticHelpTextElement = Utils.getElement(Constants.MISC, "cosmeticsinfo.lore"); - if(cosmeticHelpTextElement.isJsonArray()) { - cosmeticsInfoTooltip = gson.fromJson(cosmeticHelpTextElement, new TypeToken>(){}.getType()); - } - - } - - public enum CosmeticsPage { - CAPES(new ItemStack(Items.chainmail_chestplate)); - - public final ItemStack stack; - - CosmeticsPage(ItemStack stack) { - this.stack = stack; - } - } - - @Override - public void drawScreen(int mouseX, int mouseY, float partialTicks) { - this.sizeX = 431; - this.sizeY = 202; - this.guiLeft = (this.width-this.sizeX)/2; - this.guiTop = (this.height-this.sizeY)/2; - - super.drawScreen(mouseX, mouseY, partialTicks); - drawDefaultBackground(); - - blurBackground(); - renderBlurredBackground(width, height, guiLeft+2, guiTop+2, sizeX-4, sizeY-4); - - GlStateManager.enableDepth(); - GlStateManager.translate(0, 0, 5); - renderTabs(true); - GlStateManager.translate(0, 0, -3); - - GlStateManager.disableDepth(); - GlStateManager.translate(0, 0, -2); - renderTabs(false); - GlStateManager.translate(0, 0, 2); - - GlStateManager.disableLighting(); - GlStateManager.enableDepth(); - GlStateManager.enableBlend(); - GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); - GlStateManager.enableAlpha(); - GlStateManager.alphaFunc(516, 0.1F); - - Minecraft.getMinecraft().getTextureManager().bindTexture(pv_bg); - Utils.drawTexturedRect(guiLeft, guiTop, sizeX, sizeY, GL11.GL_NEAREST); - - GlStateManager.color(1, 1, 1, 1); - switch (currentPage) { - case CAPES: - drawCapesPage(mouseX, mouseY, partialTicks); - break; - } - int helpX = guiLeft+sizeX-20; - if(mouseX >= helpX && mouseX <= helpX+20 && mouseY >= guiTop-20 && mouseY <= guiTop) { - if(cosmeticsInfoTooltip != null) { - List grayTooltip = new ArrayList<>(cosmeticsInfoTooltip.size()); - for (String line : cosmeticsInfoTooltip) { - grayTooltip.add(EnumChatFormatting.GRAY + line); - } - Utils.drawHoveringText(grayTooltip, mouseX, mouseY, width, height, -1, Minecraft.getMinecraft().fontRendererObj); - - } - } - - StringBuilder statusMsg = new StringBuilder("Last Sync: "); - if(CapeManager.INSTANCE.lastCapeSynced == 0) { - statusMsg.append("Not Synced"); - } else { - statusMsg.append((System.currentTimeMillis() - CapeManager.INSTANCE.lastCapeSynced)/1000).append("s ago"); - } - statusMsg.append(" - Next Sync: "); - if(CapeManager.INSTANCE.lastCapeUpdate == 0) { - statusMsg.append("ASAP"); - } else { - statusMsg.append(60 - (System.currentTimeMillis() - CapeManager.INSTANCE.lastCapeUpdate)/1000).append("s"); - } - - Minecraft.getMinecraft().fontRendererObj.drawString(EnumChatFormatting.AQUA+statusMsg.toString(), - guiLeft+sizeX-Minecraft.getMinecraft().fontRendererObj.getStringWidth(statusMsg.toString())-20, guiTop-12, 0, true); - - if(currentPage == CosmeticsPage.CAPES) { - GlStateManager.color(1, 1, 1, 1); - Minecraft.getMinecraft().getTextureManager().bindTexture(pv_dropdown); - Utils.drawTexturedRect(guiLeft+sizeX/2f-50, guiTop+sizeY+5, 100, 20, 0, 100/200f, 0, 20/185f, GL11.GL_NEAREST); - - String equipMsg; - if(wantToEquipCape != null) { - equipMsg = EnumChatFormatting.GREEN + "Equip Cape"; - if(System.currentTimeMillis() - lastCapeEquip < 20*1000) { - equipMsg += " - " + (20 - (System.currentTimeMillis() - lastCapeEquip)/1000) + "s"; - } - } else { - equipMsg = EnumChatFormatting.GREEN + "Unequip"; - if(System.currentTimeMillis() - lastCapeEquip < 20*1000) { - equipMsg += " - " + (20 - (System.currentTimeMillis() - lastCapeEquip)/1000) + "s"; - } - } - - Utils.drawStringCenteredScaledMaxWidth(equipMsg, Minecraft.getMinecraft().fontRendererObj, - guiLeft+sizeX/2f, guiTop+sizeY+5+10, false, 90, 0); - } - - if(unlockTextField.getFocus() || !unlockTextField.getText().isEmpty()) { - unlockTextField.setPrependText(""); - } else { - unlockTextField.setPrependText("\u00a77Creator Code"); - } - - unlockTextField.setSize(80, 20); - unlockTextField.render(guiLeft+sizeX-80, guiTop+sizeY+2); - - - - - Minecraft.getMinecraft().getTextureManager().bindTexture(GuiTextures.help); - GlStateManager.color(1, 1, 1, 1); - Utils.drawTexturedRect(helpX, guiTop-20, 20, 20, GL11.GL_LINEAR); - - - - - } - - private void renderTabs(boolean renderPressed) { - int ignoredTabs = 0; - for(int i = 0; i< CosmeticsPage.values().length; i++) { - CosmeticsPage page = CosmeticsPage.values()[i]; - if(page.stack == null) { - ignoredTabs++; - continue; - } - boolean pressed = page == currentPage; - if(pressed == renderPressed) { - renderTab(page.stack, i-ignoredTabs, pressed); - } - } - } - - private void renderTab(ItemStack stack, int xIndex, boolean pressed) { - GlStateManager.disableLighting(); - GlStateManager.enableBlend(); - GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); - GlStateManager.enableAlpha(); - GlStateManager.alphaFunc(516, 0.1F); - - int x = guiLeft+xIndex*28; - int y = guiTop-28; - - float uMin = 0; - float uMax = 28/256f; - float vMin = 20/256f; - float vMax = 51/256f; - if(pressed) { - vMin = 52/256f; - vMax = 84/256f; - - if(xIndex != 0) { - uMin = 28/256f; - uMax = 56/256f; - } - - renderBlurredBackground(width, height, x+2, y+2, 28-4, 28-4); - } else { - renderBlurredBackground(width, height, x+2, y+4, 28-4, 28-4); - } - - GlStateManager.disableLighting(); - GlStateManager.enableBlend(); - GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); - GlStateManager.enableAlpha(); - GlStateManager.alphaFunc(516, 0.1F); - - Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements); - Utils.drawTexturedRect(x, y, 28, pressed?32:31, uMin, uMax, vMin, vMax, GL11.GL_NEAREST); - - GlStateManager.enableDepth(); - Utils.drawItemStack(stack, x+6, y+9); - } - - @Override - protected void keyTyped(char typedChar, int keyCode) throws IOException { - if(unlockTextField.getFocus()) { - if(keyCode == Keyboard.KEY_ESCAPE || keyCode == Keyboard.KEY_RETURN) { - CapeManager.INSTANCE.tryUnlockCape(unlockTextField.getText().trim()); - unlockTextField.setText(""); - unlockTextField.setFocus(false); - } else { - unlockTextField.keyTyped(typedChar, keyCode); - } - } else { - super.keyTyped(typedChar, keyCode); - } - } - - @Override - protected void mouseClicked(int mouseX, int mouseY, int mouseButton) { - //guiLeft+sizeX-140, guiTop+sizeY+2 - - if(mouseX > guiLeft+sizeX-140 & mouseX < guiLeft+sizeX && - mouseY > guiTop+sizeY && mouseY < guiTop+sizeY+22) { - unlockTextField.mouseClicked(mouseX, mouseY, mouseButton); - } - - for (int i = 0; i < CosmeticsPage.values().length; i++) { - CosmeticsPage page = CosmeticsPage.values()[i]; - int x = guiLeft + i * 28; - int y = guiTop - 28; - - if (mouseX > x && mouseX < x + 28) { - if (mouseY > y && mouseY < y + 32) { - if (currentPage != page) Utils.playPressSound(); - currentPage = page; - return; - } - } - } - if(mouseY > guiTop+177 && mouseY < guiTop+177+12) { - if(mouseX > guiLeft+15+371*scroll && mouseX < guiLeft+15+371*scroll+32) { - scrollClickedX = mouseX - (int)(guiLeft+15+371*scroll); - return; - } - } - - int index = 0; - int displayingCapes = 0; - for(CapeManager.CapeData cape : CapeManager.INSTANCE.getCapes()) { - boolean equipable = CapeManager.INSTANCE.getAvailableCapes() == null || CapeManager.INSTANCE.getAvailableCapes().contains(cape.capeName); - if (cape.canShow() || equipable) { - displayingCapes++; - } - } - - float totalNeeded = 91*displayingCapes; - float totalAvail = sizeX-20; - float xOffset = scroll*(totalNeeded-totalAvail); - - index = 0; - int displayIndex = 0; - for(CapeManager.CapeData cape : CapeManager.INSTANCE.getCapes()) { - boolean equipable = CapeManager.INSTANCE.getAvailableCapes() == null || CapeManager.INSTANCE.getAvailableCapes().contains(cape.capeName); - if(!cape.canShow() && !equipable) continue; - - GlStateManager.color(1, 1, 1, 1); - Utils.drawTexturedRect(guiLeft + 20 + 91 * displayIndex - xOffset, guiTop + 123, 81, 20, - 0, 81 / 256f, 216 / 256f, 236 / 256f, GL11.GL_NEAREST); - - if(mouseX > guiLeft + 20 + 91 * displayIndex - xOffset && mouseX < guiLeft + 20 + 91 * displayIndex - xOffset+81) { - if(mouseY > guiTop + 123 && mouseY < guiTop + 123 + 20) { - if(CapeManager.INSTANCE.localCape != null && CapeManager.INSTANCE.localCape.getRight().equals(cape.capeName)) { - CapeManager.INSTANCE.setCape(Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", ""), - "null", true); - } else { - CapeManager.INSTANCE.setCape(Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", ""), - cape.capeName, true); - } - - return; - } else if(equipable && mouseY > guiTop + 149 && mouseY < guiTop + 149 + 20) { - if(cape.capeName.equals(wantToEquipCape)) { - wantToEquipCape = null; - } else { - wantToEquipCape = cape.capeName; - } - return; - } - } - - displayIndex++; - } - - if(currentPage == CosmeticsPage.CAPES) { - Minecraft.getMinecraft().getTextureManager().bindTexture(pv_dropdown); - Utils.drawTexturedRect(guiLeft+sizeX/2f-50, guiTop+sizeY+5, 100, 20, 0, 100/200f, 0, 20/185f, GL11.GL_NEAREST); - - if(mouseX > guiLeft+sizeX/2f-50 && mouseX < guiLeft+sizeX/2f+50) { - if(mouseY > guiTop+sizeY+5 && mouseY < guiTop+sizeY+25) { - if(System.currentTimeMillis() - lastCapeEquip > 20*1000) { - CapeManager.INSTANCE.setCape(Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", ""), - wantToEquipCape, true); - - lastCapeEquip = System.currentTimeMillis(); - - try { - String userName = Minecraft.getMinecraft().thePlayer.getName(); - String accessToken = Minecraft.getMinecraft().getSession().getToken(); - Random r1 = new Random(); - Random r2 = new Random(System.identityHashCode(new Object())); - BigInteger random1Bi = new BigInteger(128, r1); - BigInteger random2Bi = new BigInteger(128, r2); - BigInteger serverBi = random1Bi.xor(random2Bi); - String serverId = serverBi.toString(16); - Minecraft.getMinecraft().getSessionService().joinServer(Minecraft.getMinecraft().getSession().getProfile(), accessToken, serverId); - - if(wantToEquipCape == null) { - NotEnoughUpdates.INSTANCE.manager.hypixelApi.getMyApiAsync("cgi-bin/changecape.py?capeType=null&serverId="+ - serverId+"&username="+userName, (jsonObject) -> { System.out.println(jsonObject); }, () -> { - System.out.println("Change cape error"); - }); - } else { - NotEnoughUpdates.INSTANCE.manager.hypixelApi.getMyApiAsync("cgi-bin/changecape.py?capeType="+wantToEquipCape+"&serverId="+ - serverId+"&username="+userName, (jsonObject) -> { System.out.println(jsonObject); }, () -> { - System.out.println("Change cape error"); - }); - } - } catch(Exception e) { - System.out.println("Exception while generating mojang shared secret"); - e.printStackTrace(); - } - - - } - } - } - } - } - - @Override - protected void mouseReleased(int mouseX, int mouseY, int state) { - super.mouseReleased(mouseX, mouseY, state); - - scrollClickedX = -1; - } - - @Override - protected void mouseClickMove(int mouseX, int mouseY, int clickedMouseButton, long timeSinceLastClick) { - super.mouseClickMove(mouseX, mouseY, clickedMouseButton, timeSinceLastClick); - - if(scrollClickedX >= 0) { - float scrollStartX = mouseX - scrollClickedX; - scroll = (scrollStartX-(guiLeft+15))/371f; - scroll = Math.max(0, Math.min(1, scroll)); - } - } - - private HashMap capesLocation = new HashMap<>(); - private float scroll = 0f; - private int scrollClickedX = -1; - private void drawCapesPage(int mouseX, int mouseY, float partialTicks) { - Minecraft.getMinecraft().getTextureManager().bindTexture(cosmetics_fg); - Utils.drawTexturedRect(guiLeft, guiTop, sizeX, sizeY, GL11.GL_NEAREST); - - Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements); - Utils.drawTexturedRect(guiLeft+15+371*scroll, guiTop+177, 32, 12, - 0, 32/256f, 192/256f, 204/256f, GL11.GL_NEAREST); - - GL11.glEnable(GL11.GL_SCISSOR_TEST); - GL11.glScissor(Minecraft.getMinecraft().displayWidth*(guiLeft+3)/width, 0, - Minecraft.getMinecraft().displayWidth*(sizeX-6)/width, Minecraft.getMinecraft().displayHeight); - - int index = 0; - int displayingCapes = 0; - for(CapeManager.CapeData capeData : CapeManager.INSTANCE.getCapes()) { - boolean equipable = CapeManager.INSTANCE.getAvailableCapes() == null || CapeManager.INSTANCE.getAvailableCapes().contains(capeData.capeName); - if (capeData.canShow() || equipable) { - displayingCapes++; - } - } - - float totalNeeded = 91*displayingCapes; - float totalAvail = sizeX-20; - float xOffset = scroll*(totalNeeded-totalAvail); - - index = 0; - int displayIndex = 0; - for(CapeManager.CapeData capeData : CapeManager.INSTANCE.getCapes()) { - boolean equipable = CapeManager.INSTANCE.getAvailableCapes() == null || CapeManager.INSTANCE.getAvailableCapes().contains(capeData.capeName); - if(!capeData.canShow() && !equipable) continue; - - if(capeData.capeName.equals(CapeManager.INSTANCE.getCape(Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", "")))) { - GlStateManager.color(250 / 255f, 200 / 255f, 0 / 255f, 1); - Utils.drawGradientRect(guiLeft + 20 + 91 * displayIndex - (int) xOffset, guiTop + 10, - guiLeft + 20 + 91 * displayIndex - (int) xOffset + 81, guiTop + 10 + 108, - new Color(150, 100, 0, 40).getRGB(), new Color(250, 200, 0, 40).getRGB()); - } else if(capeData.capeName.equals(wantToEquipCape)) { - GlStateManager.color(0, 200 / 255f, 250 / 255f, 1); - Utils.drawGradientRect(guiLeft + 20 + 91 * displayIndex - (int) xOffset, guiTop + 10, - guiLeft + 20 + 91 * displayIndex - (int) xOffset + 81, guiTop + 10 + 108, - new Color(0, 100, 150, 40).getRGB(), new Color(0, 200, 250, 40).getRGB()); - } else if(CapeManager.INSTANCE.localCape != null && CapeManager.INSTANCE.localCape.getRight().equals(capeData.capeName)) { - GlStateManager.color(100/255f, 250/255f, 150/255f, 1); - Utils.drawGradientRect(guiLeft+20+91*displayIndex-(int)xOffset, guiTop+10, - guiLeft+20+91*displayIndex-(int)xOffset+81, guiTop+10+108, - new Color(50, 100, 75, 40).getRGB(), new Color(100, 250, 150, 40).getRGB()); - } - Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements); - Utils.drawTexturedRect(guiLeft+20+91*displayIndex-xOffset, guiTop+10, 81, 108, - 0, 81/256f, 84/256f, 192/256f, GL11.GL_NEAREST); - GlStateManager.color(1, 1, 1, 1); - - Utils.drawTexturedRect(guiLeft+20+91*displayIndex-xOffset, guiTop+123, 81, 20, - 0, 81/256f, 216/256f, 236/256f, GL11.GL_NEAREST); - - boolean equipPressed = capeData.capeName.equals(wantToEquipCape); - if(!equipable) GlStateManager.color(1, 1, 1, 0.5f); - Utils.drawTexturedRect(guiLeft+20+91*displayIndex-xOffset, guiTop+149, 81, 20, - equipPressed?81/256f:0, equipPressed?0:81/256f, equipPressed?236/256f:216/256f, equipPressed?216/256f:236/256f, GL11.GL_NEAREST); - - Utils.drawStringCenteredScaledMaxWidth("Try it out", Minecraft.getMinecraft().fontRendererObj, - guiLeft+20+91*displayIndex+81/2f-xOffset, guiTop+123+10, false, 75, new Color(100, 250, 150).getRGB()); - if(equipable) { - Utils.drawStringCenteredScaledMaxWidth("Equip", Minecraft.getMinecraft().fontRendererObj, - guiLeft+20+91*displayIndex+81/2f-xOffset, guiTop+149+10, false, 75, new Color(100, 250, 150).getRGB()); - } else { - Utils.drawStringCenteredScaledMaxWidth("Not Unlocked", Minecraft.getMinecraft().fontRendererObj, - guiLeft+20+91*displayIndex+81/2f-xOffset, guiTop+149+10, false, 75, new Color(200, 50, 50, 100).getRGB()); - } - GlStateManager.color(1, 1, 1, 1); - - ResourceLocation capeTexture = capesLocation.computeIfAbsent(capeData.capeName, - k -> new ResourceLocation("notenoughupdates", "capes/"+capeData.capeName+"_preview.png")); - Minecraft.getMinecraft().getTextureManager().bindTexture(capeTexture); - Utils.drawTexturedRect(guiLeft+31+91*displayIndex-xOffset, guiTop+24, 59, 84, GL11.GL_NEAREST); - - displayIndex++; - } - - GL11.glScissor(0, 0, Minecraft.getMinecraft().displayWidth, Minecraft.getMinecraft().displayHeight); - GL11.glDisable(GL11.GL_SCISSOR_TEST); - - Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements); - } - - Shader blurShaderHorz = null; - Framebuffer blurOutputHorz = null; - Shader blurShaderVert = null; - Framebuffer blurOutputVert = null; - - /** - * Creates a projection matrix that projects from our coordinate space [0->width; 0->height] to OpenGL coordinate - * space [-1 -> 1; 1 -> -1] (Note: flipped y-axis). - * - * This is so that we can render to and from the framebuffer in a way that is familiar to us, instead of needing to - * apply scales and translations manually. - */ - private Matrix4f createProjectionMatrix(int width, int height) { - Matrix4f projMatrix = new Matrix4f(); - projMatrix.setIdentity(); - projMatrix.m00 = 2.0F / (float)width; - projMatrix.m11 = 2.0F / (float)(-height); - projMatrix.m22 = -0.0020001999F; - projMatrix.m33 = 1.0F; - projMatrix.m03 = -1.0F; - projMatrix.m13 = 1.0F; - projMatrix.m23 = -1.0001999F; - return projMatrix; - } - - /** - * Renders whatever is currently in the Minecraft framebuffer to our two framebuffers, applying a horizontal - * and vertical blur separately in order to significantly save computation time. - * This is only possible if framebuffers are supported by the system, so this method will exit prematurely - * if framebuffers are not available. (Apple machines, for example, have poor framebuffer support). - */ - private double lastBgBlurFactor = -1; - private void blurBackground() { - int width = Minecraft.getMinecraft().displayWidth; - int height = Minecraft.getMinecraft().displayHeight; - - if(blurOutputHorz == null) { - blurOutputHorz = new Framebuffer(width, height, false); - blurOutputHorz.setFramebufferFilter(GL11.GL_NEAREST); - } - if(blurOutputVert == null) { - blurOutputVert = new Framebuffer(width, height, false); - blurOutputVert.setFramebufferFilter(GL11.GL_NEAREST); - } - if(blurOutputHorz.framebufferWidth != width || blurOutputHorz.framebufferHeight != height) { - blurOutputHorz.createBindFramebuffer(width, height); - blurShaderHorz.setProjectionMatrix(createProjectionMatrix(width, height)); - Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false); - } - if(blurOutputVert.framebufferWidth != width || blurOutputVert.framebufferHeight != height) { - blurOutputVert.createBindFramebuffer(width, height); - blurShaderVert.setProjectionMatrix(createProjectionMatrix(width, height)); - Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false); - } - - if(blurShaderHorz == null) { - try { - blurShaderHorz = new Shader(Minecraft.getMinecraft().getResourceManager(), "blur", - Minecraft.getMinecraft().getFramebuffer(), blurOutputHorz); - blurShaderHorz.getShaderManager().getShaderUniform("BlurDir").set(1, 0); - blurShaderHorz.setProjectionMatrix(createProjectionMatrix(width, height)); - } catch(Exception e) { } - } - if(blurShaderVert == null) { - try { - blurShaderVert = new Shader(Minecraft.getMinecraft().getResourceManager(), "blur", - blurOutputHorz, blurOutputVert); - blurShaderVert.getShaderManager().getShaderUniform("BlurDir").set(0, 1); - blurShaderVert.setProjectionMatrix(createProjectionMatrix(width, height)); - } catch(Exception e) { } - } - if(blurShaderHorz != null && blurShaderVert != null) { - if(15 != lastBgBlurFactor) { - blurShaderHorz.getShaderManager().getShaderUniform("Radius").set((float)15); - blurShaderVert.getShaderManager().getShaderUniform("Radius").set((float)15); - lastBgBlurFactor = 15; - } - GL11.glPushMatrix(); - blurShaderHorz.loadShader(0); - blurShaderVert.loadShader(0); - GlStateManager.enableDepth(); - GL11.glPopMatrix(); - - Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false); - } - } - - /** - * Renders a subsection of the blurred framebuffer on to the corresponding section of the screen. - * Essentially, this method will "blur" the background inside the bounds specified by [x->x+blurWidth, y->y+blurHeight] - */ - public void renderBlurredBackground(int width, int height, int x, int y, int blurWidth, int blurHeight) { - float uMin = x/(float)width; - float uMax = (x+blurWidth)/(float)width; - float vMin = (height-y)/(float)height; - float vMax = (height-y-blurHeight)/(float)height; - - blurOutputVert.bindFramebufferTexture(); - GlStateManager.color(1f, 1f, 1f, 1f); - //Utils.setScreen(width*f, height*f, f); - Utils.drawTexturedRect(x, y, blurWidth, blurHeight, uMin, uMax, vMin, vMax); - //Utils.setScreen(width, height, f); - blurOutputVert.unbindFramebufferTexture(); - } + public static final ResourceLocation pv_bg = new ResourceLocation("notenoughupdates:pv_bg.png"); + public static final ResourceLocation pv_dropdown = new ResourceLocation("notenoughupdates:pv_dropdown.png"); + public static final ResourceLocation cosmetics_fg = new ResourceLocation("notenoughupdates:cosmetics_fg.png"); + public static final ResourceLocation pv_elements = new ResourceLocation("notenoughupdates:pv_elements.png"); + + private final GuiElementTextField unlockTextField = new GuiElementTextField("", GuiElementTextField.SCALE_TEXT); + + private CosmeticsPage currentPage = CosmeticsPage.CAPES; + private int sizeX; + private int sizeY; + private int guiLeft; + private int guiTop; + + private String wantToEquipCape = null; + private long lastCapeEquip = 0; + + private List cosmeticsInfoTooltip = null; + + public GuiCosmetics() { + Gson gson = new Gson(); + + JsonElement cosmeticHelpTextElement = Utils.getElement(Constants.MISC, "cosmeticsinfo.lore"); + if (cosmeticHelpTextElement.isJsonArray()) { + cosmeticsInfoTooltip = gson.fromJson(cosmeticHelpTextElement, new TypeToken>() {}.getType()); + } + + } + + public enum CosmeticsPage { + CAPES(new ItemStack(Items.chainmail_chestplate)); + + public final ItemStack stack; + + CosmeticsPage(ItemStack stack) { + this.stack = stack; + } + } + + @Override + public void drawScreen(int mouseX, int mouseY, float partialTicks) { + this.sizeX = 431; + this.sizeY = 202; + this.guiLeft = (this.width - this.sizeX) / 2; + this.guiTop = (this.height - this.sizeY) / 2; + + super.drawScreen(mouseX, mouseY, partialTicks); + drawDefaultBackground(); + + blurBackground(); + renderBlurredBackground(width, height, guiLeft + 2, guiTop + 2, sizeX - 4, sizeY - 4); + + GlStateManager.enableDepth(); + GlStateManager.translate(0, 0, 5); + renderTabs(true); + GlStateManager.translate(0, 0, -3); + + GlStateManager.disableDepth(); + GlStateManager.translate(0, 0, -2); + renderTabs(false); + GlStateManager.translate(0, 0, 2); + + GlStateManager.disableLighting(); + GlStateManager.enableDepth(); + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.enableAlpha(); + GlStateManager.alphaFunc(516, 0.1F); + + Minecraft.getMinecraft().getTextureManager().bindTexture(pv_bg); + Utils.drawTexturedRect(guiLeft, guiTop, sizeX, sizeY, GL11.GL_NEAREST); + + GlStateManager.color(1, 1, 1, 1); + switch (currentPage) { + case CAPES: + drawCapesPage(mouseX, mouseY, partialTicks); + break; + } + int helpX = guiLeft + sizeX - 20; + if (mouseX >= helpX && mouseX <= helpX + 20 && mouseY >= guiTop - 20 && mouseY <= guiTop) { + if (cosmeticsInfoTooltip != null) { + List grayTooltip = new ArrayList<>(cosmeticsInfoTooltip.size()); + for (String line : cosmeticsInfoTooltip) { + grayTooltip.add(EnumChatFormatting.GRAY + line); + } + Utils.drawHoveringText( + grayTooltip, + mouseX, + mouseY, + width, + height, + -1, + Minecraft.getMinecraft().fontRendererObj + ); + + } + } + + StringBuilder statusMsg = new StringBuilder("Last Sync: "); + if (CapeManager.INSTANCE.lastCapeSynced == 0) { + statusMsg.append("Not Synced"); + } else { + statusMsg.append((System.currentTimeMillis() - CapeManager.INSTANCE.lastCapeSynced) / 1000).append("s ago"); + } + statusMsg.append(" - Next Sync: "); + if (CapeManager.INSTANCE.lastCapeUpdate == 0) { + statusMsg.append("ASAP"); + } else { + statusMsg.append(60 - (System.currentTimeMillis() - CapeManager.INSTANCE.lastCapeUpdate) / 1000).append("s"); + } + + Minecraft.getMinecraft().fontRendererObj.drawString( + EnumChatFormatting.AQUA + statusMsg.toString(), + guiLeft + sizeX - Minecraft.getMinecraft().fontRendererObj.getStringWidth(statusMsg.toString()) - 20, + guiTop - 12, + 0, + true + ); + + if (currentPage == CosmeticsPage.CAPES) { + GlStateManager.color(1, 1, 1, 1); + Minecraft.getMinecraft().getTextureManager().bindTexture(pv_dropdown); + Utils.drawTexturedRect( + guiLeft + sizeX / 2f - 50, + guiTop + sizeY + 5, + 100, + 20, + 0, + 100 / 200f, + 0, + 20 / 185f, + GL11.GL_NEAREST + ); + + String equipMsg; + if (wantToEquipCape != null) { + equipMsg = EnumChatFormatting.GREEN + "Equip Cape"; + } else { + equipMsg = EnumChatFormatting.GREEN + "Unequip"; + } + if (System.currentTimeMillis() - lastCapeEquip < 20 * 1000) { + equipMsg += " - " + (20 - (System.currentTimeMillis() - lastCapeEquip) / 1000) + "s"; + } + + Utils.drawStringCenteredScaledMaxWidth(equipMsg, Minecraft.getMinecraft().fontRendererObj, + guiLeft + sizeX / 2f, guiTop + sizeY + 5 + 10, false, 90, 0 + ); + } + + if (unlockTextField.getFocus() || !unlockTextField.getText().isEmpty()) { + unlockTextField.setPrependText(""); + } else { + unlockTextField.setPrependText("\u00a77Creator Code"); + } + + unlockTextField.setSize(80, 20); + unlockTextField.render(guiLeft + sizeX - 80, guiTop + sizeY + 2); + + Minecraft.getMinecraft().getTextureManager().bindTexture(GuiTextures.help); + GlStateManager.color(1, 1, 1, 1); + Utils.drawTexturedRect(helpX, guiTop - 20, 20, 20, GL11.GL_LINEAR); + + } + + private void renderTabs(boolean renderPressed) { + int ignoredTabs = 0; + for (int i = 0; i < CosmeticsPage.values().length; i++) { + CosmeticsPage page = CosmeticsPage.values()[i]; + if (page.stack == null) { + ignoredTabs++; + continue; + } + boolean pressed = page == currentPage; + if (pressed == renderPressed) { + renderTab(page.stack, i - ignoredTabs, pressed); + } + } + } + + private void renderTab(ItemStack stack, int xIndex, boolean pressed) { + GlStateManager.disableLighting(); + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.enableAlpha(); + GlStateManager.alphaFunc(516, 0.1F); + + int x = guiLeft + xIndex * 28; + int y = guiTop - 28; + + float uMin = 0; + float uMax = 28 / 256f; + float vMin = 20 / 256f; + float vMax = 51 / 256f; + if (pressed) { + vMin = 52 / 256f; + vMax = 84 / 256f; + + if (xIndex != 0) { + uMin = 28 / 256f; + uMax = 56 / 256f; + } + + renderBlurredBackground(width, height, x + 2, y + 2, 28 - 4, 28 - 4); + } else { + renderBlurredBackground(width, height, x + 2, y + 4, 28 - 4, 28 - 4); + } + + GlStateManager.disableLighting(); + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.enableAlpha(); + GlStateManager.alphaFunc(516, 0.1F); + + Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements); + Utils.drawTexturedRect(x, y, 28, pressed ? 32 : 31, uMin, uMax, vMin, vMax, GL11.GL_NEAREST); + + GlStateManager.enableDepth(); + Utils.drawItemStack(stack, x + 6, y + 9); + } + + @Override + protected void keyTyped(char typedChar, int keyCode) throws IOException { + if (unlockTextField.getFocus()) { + if (keyCode == Keyboard.KEY_ESCAPE || keyCode == Keyboard.KEY_RETURN) { + CapeManager.INSTANCE.tryUnlockCape(unlockTextField.getText().trim()); + unlockTextField.setText(""); + unlockTextField.setFocus(false); + } else { + unlockTextField.keyTyped(typedChar, keyCode); + } + } else { + super.keyTyped(typedChar, keyCode); + } + } + + @Override + protected void mouseClicked(int mouseX, int mouseY, int mouseButton) { + //guiLeft+sizeX-140, guiTop+sizeY+2 + + if (mouseX > guiLeft + sizeX - 140 & mouseX < guiLeft + sizeX && + mouseY > guiTop + sizeY && mouseY < guiTop + sizeY + 22) { + unlockTextField.mouseClicked(mouseX, mouseY, mouseButton); + } + + for (int i = 0; i < CosmeticsPage.values().length; i++) { + CosmeticsPage page = CosmeticsPage.values()[i]; + int x = guiLeft + i * 28; + int y = guiTop - 28; + + if (mouseX > x && mouseX < x + 28) { + if (mouseY > y && mouseY < y + 32) { + if (currentPage != page) Utils.playPressSound(); + currentPage = page; + return; + } + } + } + if (mouseY > guiTop + 177 && mouseY < guiTop + 177 + 12) { + if (mouseX > guiLeft + 15 + 371 * scroll && mouseX < guiLeft + 15 + 371 * scroll + 32) { + scrollClickedX = mouseX - (int) (guiLeft + 15 + 371 * scroll); + return; + } + } + + int index = 0; + int displayingCapes = 0; + for (CapeManager.CapeData cape : CapeManager.INSTANCE.getCapes()) { + boolean equipable = CapeManager.INSTANCE.getAvailableCapes() == null || + CapeManager.INSTANCE.getAvailableCapes().contains(cape.capeName); + if (cape.canShow() || equipable) { + displayingCapes++; + } + } + + float totalNeeded = 91 * displayingCapes; + float totalAvail = sizeX - 20; + float xOffset = scroll * (totalNeeded - totalAvail); + + index = 0; + int displayIndex = 0; + for (CapeManager.CapeData cape : CapeManager.INSTANCE.getCapes()) { + boolean equipable = CapeManager.INSTANCE.getAvailableCapes() == null || + CapeManager.INSTANCE.getAvailableCapes().contains(cape.capeName); + if (!cape.canShow() && !equipable) continue; + + GlStateManager.color(1, 1, 1, 1); + Utils.drawTexturedRect(guiLeft + 20 + 91 * displayIndex - xOffset, guiTop + 123, 81, 20, + 0, 81 / 256f, 216 / 256f, 236 / 256f, GL11.GL_NEAREST + ); + + if (mouseX > guiLeft + 20 + 91 * displayIndex - xOffset && + mouseX < guiLeft + 20 + 91 * displayIndex - xOffset + 81) { + if (mouseY > guiTop + 123 && mouseY < guiTop + 123 + 20) { + if (CapeManager.INSTANCE.localCape != null && + CapeManager.INSTANCE.localCape.getRight().equals(cape.capeName)) { + CapeManager.INSTANCE.setCape(Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", ""), + "null", true + ); + } else { + CapeManager.INSTANCE.setCape(Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", ""), + cape.capeName, true + ); + } + + return; + } else if (equipable && mouseY > guiTop + 149 && mouseY < guiTop + 149 + 20) { + if (cape.capeName.equals(wantToEquipCape)) { + wantToEquipCape = null; + } else { + wantToEquipCape = cape.capeName; + } + return; + } + } + + displayIndex++; + } + + if (currentPage == CosmeticsPage.CAPES) { + Minecraft.getMinecraft().getTextureManager().bindTexture(pv_dropdown); + Utils.drawTexturedRect( + guiLeft + sizeX / 2f - 50, + guiTop + sizeY + 5, + 100, + 20, + 0, + 100 / 200f, + 0, + 20 / 185f, + GL11.GL_NEAREST + ); + + if (mouseX > guiLeft + sizeX / 2f - 50 && mouseX < guiLeft + sizeX / 2f + 50) { + if (mouseY > guiTop + sizeY + 5 && mouseY < guiTop + sizeY + 25) { + if (System.currentTimeMillis() - lastCapeEquip > 20 * 1000) { + CapeManager.INSTANCE.setCape(Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", ""), + wantToEquipCape, true + ); + + lastCapeEquip = System.currentTimeMillis(); + + try { + String userName = Minecraft.getMinecraft().thePlayer.getName(); + String accessToken = Minecraft.getMinecraft().getSession().getToken(); + Random r1 = new Random(); + Random r2 = new Random(System.identityHashCode(new Object())); + BigInteger random1Bi = new BigInteger(128, r1); + BigInteger random2Bi = new BigInteger(128, r2); + BigInteger serverBi = random1Bi.xor(random2Bi); + String serverId = serverBi.toString(16); + Minecraft.getMinecraft().getSessionService().joinServer(Minecraft + .getMinecraft() + .getSession() + .getProfile(), accessToken, serverId); + + if (wantToEquipCape == null) { + NotEnoughUpdates.INSTANCE.manager.hypixelApi.getMyApiAsync( + "cgi-bin/changecape.py?capeType=null&serverId=" + + serverId + "&username=" + userName, + System.out::println, + () -> System.out.println("Change cape error") + ); + } else { + NotEnoughUpdates.INSTANCE.manager.hypixelApi.getMyApiAsync( + "cgi-bin/changecape.py?capeType=" + wantToEquipCape + "&serverId=" + + serverId + "&username=" + userName, + System.out::println, + () -> System.out.println("Change cape error") + ); + } + } catch (Exception e) { + System.out.println("Exception while generating mojang shared secret"); + e.printStackTrace(); + } + + } + } + } + } + } + + @Override + protected void mouseReleased(int mouseX, int mouseY, int state) { + super.mouseReleased(mouseX, mouseY, state); + + scrollClickedX = -1; + } + + @Override + protected void mouseClickMove(int mouseX, int mouseY, int clickedMouseButton, long timeSinceLastClick) { + super.mouseClickMove(mouseX, mouseY, clickedMouseButton, timeSinceLastClick); + + if (scrollClickedX >= 0) { + float scrollStartX = mouseX - scrollClickedX; + scroll = (scrollStartX - (guiLeft + 15)) / 371f; + scroll = Math.max(0, Math.min(1, scroll)); + } + } + + private final HashMap capesLocation = new HashMap<>(); + private float scroll = 0f; + private int scrollClickedX = -1; + + private void drawCapesPage(int mouseX, int mouseY, float partialTicks) { + Minecraft.getMinecraft().getTextureManager().bindTexture(cosmetics_fg); + Utils.drawTexturedRect(guiLeft, guiTop, sizeX, sizeY, GL11.GL_NEAREST); + + Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements); + Utils.drawTexturedRect(guiLeft + 15 + 371 * scroll, guiTop + 177, 32, 12, + 0, 32 / 256f, 192 / 256f, 204 / 256f, GL11.GL_NEAREST + ); + + GL11.glEnable(GL11.GL_SCISSOR_TEST); + GL11.glScissor(Minecraft.getMinecraft().displayWidth * (guiLeft + 3) / width, 0, + Minecraft.getMinecraft().displayWidth * (sizeX - 6) / width, Minecraft.getMinecraft().displayHeight + ); + + int index = 0; + int displayingCapes = 0; + for (CapeManager.CapeData capeData : CapeManager.INSTANCE.getCapes()) { + boolean equipable = CapeManager.INSTANCE.getAvailableCapes() == null || + CapeManager.INSTANCE.getAvailableCapes().contains(capeData.capeName); + if (capeData.canShow() || equipable) { + displayingCapes++; + } + } + + float totalNeeded = 91 * displayingCapes; + float totalAvail = sizeX - 20; + float xOffset = scroll * (totalNeeded - totalAvail); + + index = 0; + int displayIndex = 0; + for (CapeManager.CapeData capeData : CapeManager.INSTANCE.getCapes()) { + boolean equipable = CapeManager.INSTANCE.getAvailableCapes() == null || + CapeManager.INSTANCE.getAvailableCapes().contains(capeData.capeName); + if (!capeData.canShow() && !equipable) continue; + + if (capeData.capeName.equals(CapeManager.INSTANCE.getCape(Minecraft.getMinecraft().thePlayer + .getUniqueID() + .toString() + .replace("-", "")))) { + GlStateManager.color(250 / 255f, 200 / 255f, 0 / 255f, 1); + Utils.drawGradientRect(guiLeft + 20 + 91 * displayIndex - (int) xOffset, guiTop + 10, + guiLeft + 20 + 91 * displayIndex - (int) xOffset + 81, guiTop + 10 + 108, + new Color(150, 100, 0, 40).getRGB(), new Color(250, 200, 0, 40).getRGB() + ); + } else if (capeData.capeName.equals(wantToEquipCape)) { + GlStateManager.color(0, 200 / 255f, 250 / 255f, 1); + Utils.drawGradientRect(guiLeft + 20 + 91 * displayIndex - (int) xOffset, guiTop + 10, + guiLeft + 20 + 91 * displayIndex - (int) xOffset + 81, guiTop + 10 + 108, + new Color(0, 100, 150, 40).getRGB(), new Color(0, 200, 250, 40).getRGB() + ); + } else if (CapeManager.INSTANCE.localCape != null && + CapeManager.INSTANCE.localCape.getRight().equals(capeData.capeName)) { + GlStateManager.color(100 / 255f, 250 / 255f, 150 / 255f, 1); + Utils.drawGradientRect(guiLeft + 20 + 91 * displayIndex - (int) xOffset, guiTop + 10, + guiLeft + 20 + 91 * displayIndex - (int) xOffset + 81, guiTop + 10 + 108, + new Color(50, 100, 75, 40).getRGB(), new Color(100, 250, 150, 40).getRGB() + ); + } + Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements); + Utils.drawTexturedRect(guiLeft + 20 + 91 * displayIndex - xOffset, guiTop + 10, 81, 108, + 0, 81 / 256f, 84 / 256f, 192 / 256f, GL11.GL_NEAREST + ); + GlStateManager.color(1, 1, 1, 1); + + Utils.drawTexturedRect(guiLeft + 20 + 91 * displayIndex - xOffset, guiTop + 123, 81, 20, + 0, 81 / 256f, 216 / 256f, 236 / 256f, GL11.GL_NEAREST + ); + + boolean equipPressed = capeData.capeName.equals(wantToEquipCape); + if (!equipable) GlStateManager.color(1, 1, 1, 0.5f); + Utils.drawTexturedRect( + guiLeft + 20 + 91 * displayIndex - xOffset, + guiTop + 149, + 81, + 20, + equipPressed ? 81 / 256f : 0, + equipPressed ? 0 : 81 / 256f, + equipPressed ? 236 / 256f : 216 / 256f, + equipPressed ? 216 / 256f : 236 / 256f, + GL11.GL_NEAREST + ); + + Utils.drawStringCenteredScaledMaxWidth( + "Try it out", + Minecraft.getMinecraft().fontRendererObj, + guiLeft + 20 + 91 * displayIndex + 81 / 2f - xOffset, + guiTop + 123 + 10, + false, + 75, + new Color(100, 250, 150).getRGB() + ); + if (equipable) { + Utils.drawStringCenteredScaledMaxWidth( + "Equip", + Minecraft.getMinecraft().fontRendererObj, + guiLeft + 20 + 91 * displayIndex + 81 / 2f - xOffset, + guiTop + 149 + 10, + false, + 75, + new Color(100, 250, 150).getRGB() + ); + } else { + Utils.drawStringCenteredScaledMaxWidth( + "Not Unlocked", + Minecraft.getMinecraft().fontRendererObj, + guiLeft + 20 + 91 * displayIndex + 81 / 2f - xOffset, + guiTop + 149 + 10, + false, + 75, + new Color(200, 50, 50, 100).getRGB() + ); + } + GlStateManager.color(1, 1, 1, 1); + + ResourceLocation capeTexture = capesLocation.computeIfAbsent( + capeData.capeName, + k -> new ResourceLocation("notenoughupdates", "capes/" + capeData.capeName + "_preview.png") + ); + Minecraft.getMinecraft().getTextureManager().bindTexture(capeTexture); + Utils.drawTexturedRect(guiLeft + 31 + 91 * displayIndex - xOffset, guiTop + 24, 59, 84, GL11.GL_NEAREST); + + displayIndex++; + } + + GL11.glScissor(0, 0, Minecraft.getMinecraft().displayWidth, Minecraft.getMinecraft().displayHeight); + GL11.glDisable(GL11.GL_SCISSOR_TEST); + + Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements); + } + + Shader blurShaderHorz = null; + Framebuffer blurOutputHorz = null; + Shader blurShaderVert = null; + Framebuffer blurOutputVert = null; + + /** + * Creates a projection matrix that projects from our coordinate space [0->width; 0->height] to OpenGL coordinate + * space [-1 -> 1; 1 -> -1] (Note: flipped y-axis). + *

+ * This is so that we can render to and from the framebuffer in a way that is familiar to us, instead of needing to + * apply scales and translations manually. + */ + private Matrix4f createProjectionMatrix(int width, int height) { + Matrix4f projMatrix = new Matrix4f(); + projMatrix.setIdentity(); + projMatrix.m00 = 2.0F / (float) width; + projMatrix.m11 = 2.0F / (float) (-height); + projMatrix.m22 = -0.0020001999F; + projMatrix.m33 = 1.0F; + projMatrix.m03 = -1.0F; + projMatrix.m13 = 1.0F; + projMatrix.m23 = -1.0001999F; + return projMatrix; + } + + /** + * Renders whatever is currently in the Minecraft framebuffer to our two framebuffers, applying a horizontal + * and vertical blur separately in order to significantly save computation time. + * This is only possible if framebuffers are supported by the system, so this method will exit prematurely + * if framebuffers are not available. (Apple machines, for example, have poor framebuffer support). + */ + private double lastBgBlurFactor = -1; + + private void blurBackground() { + int width = Minecraft.getMinecraft().displayWidth; + int height = Minecraft.getMinecraft().displayHeight; + + if (blurOutputHorz == null) { + blurOutputHorz = new Framebuffer(width, height, false); + blurOutputHorz.setFramebufferFilter(GL11.GL_NEAREST); + } + if (blurOutputVert == null) { + blurOutputVert = new Framebuffer(width, height, false); + blurOutputVert.setFramebufferFilter(GL11.GL_NEAREST); + } + if (blurOutputHorz.framebufferWidth != width || blurOutputHorz.framebufferHeight != height) { + blurOutputHorz.createBindFramebuffer(width, height); + blurShaderHorz.setProjectionMatrix(createProjectionMatrix(width, height)); + Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false); + } + if (blurOutputVert.framebufferWidth != width || blurOutputVert.framebufferHeight != height) { + blurOutputVert.createBindFramebuffer(width, height); + blurShaderVert.setProjectionMatrix(createProjectionMatrix(width, height)); + Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false); + } + + if (blurShaderHorz == null) { + try { + blurShaderHorz = new Shader(Minecraft.getMinecraft().getResourceManager(), "blur", + Minecraft.getMinecraft().getFramebuffer(), blurOutputHorz + ); + blurShaderHorz.getShaderManager().getShaderUniform("BlurDir").set(1, 0); + blurShaderHorz.setProjectionMatrix(createProjectionMatrix(width, height)); + } catch (Exception ignored) { + } + } + if (blurShaderVert == null) { + try { + blurShaderVert = new Shader(Minecraft.getMinecraft().getResourceManager(), "blur", + blurOutputHorz, blurOutputVert + ); + blurShaderVert.getShaderManager().getShaderUniform("BlurDir").set(0, 1); + blurShaderVert.setProjectionMatrix(createProjectionMatrix(width, height)); + } catch (Exception ignored) { + } + } + if (blurShaderHorz != null && blurShaderVert != null) { + if (15 != lastBgBlurFactor) { + blurShaderHorz.getShaderManager().getShaderUniform("Radius").set((float) 15); + blurShaderVert.getShaderManager().getShaderUniform("Radius").set((float) 15); + lastBgBlurFactor = 15; + } + GL11.glPushMatrix(); + blurShaderHorz.loadShader(0); + blurShaderVert.loadShader(0); + GlStateManager.enableDepth(); + GL11.glPopMatrix(); + + Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false); + } + } + + /** + * Renders a subsection of the blurred framebuffer on to the corresponding section of the screen. + * Essentially, this method will "blur" the background inside the bounds specified by [x->x+blurWidth, y->y+blurHeight] + */ + public void renderBlurredBackground(int width, int height, int x, int y, int blurWidth, int blurHeight) { + float uMin = x / (float) width; + float uMax = (x + blurWidth) / (float) width; + float vMin = (height - y) / (float) height; + float vMax = (height - y - blurHeight) / (float) height; + + blurOutputVert.bindFramebufferTexture(); + GlStateManager.color(1f, 1f, 1f, 1f); + //Utils.setScreen(width*f, height*f, f); + Utils.drawTexturedRect(x, y, blurWidth, blurHeight, uMin, uMax, vMin, vMax); + //Utils.setScreen(width, height, f); + blurOutputVert.unbindFramebufferTexture(); + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/NEUCape.java b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/NEUCape.java index 3b0e092864..da9d1f682a 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/NEUCape.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/NEUCape.java @@ -1,14 +1,8 @@ package io.github.moulberry.notenoughupdates.cosmetics; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; -import io.github.moulberry.notenoughupdates.core.util.lerp.LerpUtils; -import io.github.moulberry.notenoughupdates.util.ReverseWorldRenderer; -import io.github.moulberry.notenoughupdates.util.TexLoc; -import io.github.moulberry.notenoughupdates.util.Utils; -import net.minecraft.block.Block; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.client.renderer.OpenGlHelper; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; @@ -18,16 +12,11 @@ import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.potion.Potion; -import net.minecraft.util.BlockPos; import net.minecraft.util.MathHelper; import net.minecraft.util.ResourceLocation; -import net.minecraft.util.Vec3; -import net.minecraft.world.gen.NoiseGeneratorSimplex; import net.minecraftforge.client.event.RenderPlayerEvent; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.TickEvent; import org.lwjgl.BufferUtils; -import org.lwjgl.Sys; import org.lwjgl.input.Keyboard; import org.lwjgl.opengl.*; import org.lwjgl.util.vector.Vector2f; @@ -35,1271 +24,1299 @@ import java.nio.ByteBuffer; import java.nio.FloatBuffer; -import java.nio.IntBuffer; -import java.security.Key; import java.util.*; public class NEUCape { - - private int currentFrame = 0; - private int displayFrame = 0; - private String capeName; - public ResourceLocation[] capeTextures = null; - - private long lastFrameUpdate = 0; - - private static int ANIM_MODE_LOOP = 0; - private static int ANIM_MODE_PINGPONG = 1; - private int animMode = ANIM_MODE_LOOP; - - private CapeNode[] nodes = null; - - private Random random = new Random(); - - private long eventMillis; - private float eventLength; - private float eventRandom; - - private static double vertOffset = 1.4; - private static double shoulderLength = 0.24; - private static double shoulderWidth = 0.13; - - public static final int HORZ_NODES = 6; - public static final int VERT_NODES = 22; - - public static float targetDist = 1 / 20f; - - private EntityPlayer currentPlayer; - private boolean keepCurrentPlayer = false; - - private String shaderName = "cape"; - - public NEUCape(String capeName) { - setCapeTexture(capeName); - } - - public void setCapeTexture(String capeName) { - if(this.capeName != null && this.capeName.equalsIgnoreCase(capeName)) return; - - startTime = System.currentTimeMillis(); - boolean defaultBehaviour = true; - - if(NotEnoughUpdates.INSTANCE.config.hidden.disableBrokenCapes){ - if(capeName.equals("negative")){ - defaultBehaviour = false; - this.capeName = "fade"; - this.shaderName = "fade_cape"; - } - - } - if(defaultBehaviour){ - this.capeName = capeName; - - if (capeName.equalsIgnoreCase("fade")) { - shaderName = "fade_cape"; - } else if (capeName.equalsIgnoreCase("space")) { - shaderName = "space_cape"; - } else if (capeName.equalsIgnoreCase("mcworld")) { - shaderName = "mcworld_cape"; - } else if(capeName.equalsIgnoreCase("lava") || capeName.equalsIgnoreCase("skyclient")) { - shaderName = "lava_cape"; - } else if (capeName.equalsIgnoreCase("lightning")) { - shaderName = "lightning_cape"; - } else if (capeName.equalsIgnoreCase("thebakery")) { - shaderName = "biscuit_cape"; - } else if (capeName.equalsIgnoreCase("negative")) { - shaderName = "negative"; - } else if (capeName.equalsIgnoreCase("void")) { - shaderName = "void"; - } else if (capeName.equalsIgnoreCase("tunnel")) { - shaderName = "tunnel"; - } else if (capeName.equalsIgnoreCase("planets")) { - shaderName = "planets"; - } else { - shaderName = "shiny_cape"; - } - } - - ResourceLocation staticCapeTex = new ResourceLocation("notenoughupdates:capes/" + capeName + ".png"); - capeTextures = new ResourceLocation[1]; - capeTextures[0] = staticCapeTex; - } - - private void bindTexture() { - if(capeName.equalsIgnoreCase("negative")) { - CapeManager.getInstance().updateWorldFramebuffer = true; - if(CapeManager.getInstance().backgroundFramebuffer != null) { - CapeManager.getInstance().backgroundFramebuffer.bindFramebufferTexture(); - } - } else if(capeTextures != null && capeTextures.length > 0) { - long currentTime = System.currentTimeMillis(); - if(currentTime - lastFrameUpdate > 100) { - lastFrameUpdate = currentTime / 100 * 100; - currentFrame++; - - if(animMode == ANIM_MODE_PINGPONG) { - if(capeTextures.length == 1) { - currentFrame = displayFrame = 0; - } else { - int frameCount = 2 * capeTextures.length - 2; - currentFrame %= frameCount; - displayFrame = currentFrame; - if(currentFrame >= capeTextures.length) { - displayFrame = frameCount - displayFrame; - } - } - } else if(animMode == ANIM_MODE_LOOP) { - currentFrame %= capeTextures.length; - displayFrame = currentFrame; - } - } - Minecraft.getMinecraft().getTextureManager().bindTexture(capeTextures[displayFrame]); - } - } - - private CapeNode getNode(int x, int y) { - return nodes[x + y * HORZ_NODES]; - } - - public void createCapeNodes(EntityPlayer player) { - nodes = new CapeNode[HORZ_NODES * VERT_NODES]; - - float pX = (float) player.posX % 7789; - float pY = (float) player.posY; - float pZ = (float) player.posZ % 7789; - - float uMinTop = 48 / 1024f; - float uMaxTop = 246 / 1024f; - float uMinBottom = 0 / 1024f; - float uMaxBottom = 293 / 1024f; - - float vMaxSide = 404 / 1024f; - float vMaxCenter = 419 / 1024f; - - for(int i = 0; i < VERT_NODES; i++) { - float uMin = uMinTop + (uMinBottom - uMinTop) * i / (float) (VERT_NODES - 1); - float uMax = uMaxTop + (uMaxBottom - uMaxTop) * i / (float) (VERT_NODES - 1); - - for(int j = 0; j < HORZ_NODES; j++) { - float vMin = 0f; - float centerMult = 1 - Math.abs(j - (HORZ_NODES - 1) / 2f) / ((HORZ_NODES - 1) / 2f);//0-(horzCapeNodes) -> 0-1-0 - float vMax = vMaxSide + (vMaxCenter - vMaxSide) * centerMult; - - CapeNode node = new CapeNode(pX, pY, pZ);//pX-1, pY+2-i*targetDist, pZ+(j-(horzCapeNodes-1)/2f)*targetDist*2 - node.texU = uMin + (uMax - uMin) * j / (float) (HORZ_NODES - 1); - node.texV = vMin + (vMax - vMin) * i / (float) (VERT_NODES - 1); - - node.horzDistMult = 2f + 1f * i / (float) (VERT_NODES - 1); - - if(j == 0 || j == HORZ_NODES - 1) { - node.horzSideTexU = 406 / 1024f * i / (float) (VERT_NODES - 1); - if(j == 0) { - node.horzSideTexVTop = 1 - 20 / 1024f; - } else { - node.horzSideTexVTop = 1 - 40 / 1024f; - } - } - if(i == 0) { - node.vertSideTexU = 198 / 1024f * j / (float) (HORZ_NODES - 1); - node.vertSideTexVTop = 1 - 60 / 1024f; - } else if(i == VERT_NODES - 1) { - node.vertSideTexU = 300 / 1024f * j / (float) (HORZ_NODES - 1); - node.vertSideTexVTop = 1 - 80 / 1024f; - } - nodes[j + i * HORZ_NODES] = node; - } - } - for(int y = 0; y < VERT_NODES; y++) { - for(int x = 0; x < HORZ_NODES; x++) { - CapeNode node = nodes[x + y * HORZ_NODES]; - - for(Direction dir : Direction.values()) { - for(int i = 1; i <= 2; i++) { - Offset offset = new Offset(dir, i); - - int xNeighbor = x + offset.getXOffset(); - int yNeighbor = y + offset.getYOffset(); - - if(xNeighbor >= 0 && xNeighbor < HORZ_NODES - && yNeighbor >= 0 && yNeighbor < VERT_NODES) { - CapeNode neighbor = nodes[xNeighbor + yNeighbor * HORZ_NODES]; - node.setNeighbor(offset, neighbor); - } - } - } - } - } - } - - public void ensureCapeNodesCreated(EntityPlayer player) { - if(nodes == null) createCapeNodes(player); - } - - public enum Direction { - LEFT(-1, 0), - UP(0, 1), - RIGHT(1, 0), - DOWN(0, -1), - UPLEFT(-1, 1), - UPRIGHT(1, 1), - DOWNLEFT(-1, -1), - DOWNRIGHT(1, -1); - - int xOff; - int yOff; - - Direction(int xOff, int yOff) { - this.xOff = xOff; - this.yOff = yOff; - } - - public Direction rotateRight90() { - int wantXOff = -yOff; - int wantYOff = xOff; - for(Direction dir : values()) { - if(dir.xOff == wantXOff && dir.yOff == wantYOff) { - return dir; - } - } - return this; - } - - public Direction rotateLeft90() { - int wantXOff = yOff; - int wantYOff = -xOff; - for(Direction dir : values()) { - if(dir.xOff == wantXOff && dir.yOff == wantYOff) { - return dir; - } - } - return this; - } - } - - public static class Offset { - Direction direction; - int steps; - - public Offset(Direction direction, int steps) { - this.direction = direction; - this.steps = steps; - } - - public int getXOffset() { - return direction.xOff * steps; - } - - public int getYOffset() { - return direction.yOff * steps; - } - - public boolean equals(Object obj) { - if(obj instanceof Offset) { - Offset other = (Offset) obj; - return other.direction == direction && other.steps == steps; - } - return false; - } - - @Override - public int hashCode() { - return 13 * direction.ordinal() + 7 * steps; - } - } - - private void loadShaderUniforms(ShaderManager shaderManager) { - String shaderId = "capes/" + shaderName + "/" + shaderName; - if(shaderName.equalsIgnoreCase("fade_cape") || shaderName.equalsIgnoreCase("planets")) { - shaderManager.loadData(shaderId, "millis", (int) (System.currentTimeMillis() - startTime)); - } else if(shaderName.equalsIgnoreCase("space_cape")) { - shaderManager.loadData(shaderId, "millis", (int) (System.currentTimeMillis() - startTime)); - shaderManager.loadData(shaderId, "eventMillis", (int) (System.currentTimeMillis() - eventMillis)); - shaderManager.loadData(shaderId, "eventRand", eventRandom); - } else if(shaderName.equalsIgnoreCase("mcworld_cape")) { - shaderManager.loadData(shaderId, "millis", (int) (System.currentTimeMillis() - startTime)); - } else if(shaderName.equalsIgnoreCase("lava_cape")) { - shaderManager.loadData(shaderId, "millis", (int) (System.currentTimeMillis() - startTime)); - } else if(shaderName.equalsIgnoreCase("tunnel")) { - shaderManager.loadData(shaderId, "millis", (int) (System.currentTimeMillis() - startTime)); - } else if(shaderName.equalsIgnoreCase("biscuit_cape") || shaderName.equalsIgnoreCase("shiny_cape")) { - shaderManager.loadData(shaderId, "millis", (int) (System.currentTimeMillis() - startTime)); - shaderManager.loadData(shaderId, "eventMillis", (int) (System.currentTimeMillis() - eventMillis)); - } else if(shaderName.equalsIgnoreCase("negative")) { - shaderManager.loadData(shaderId, "screensize", new Vector2f( - Minecraft.getMinecraft().displayWidth, - Minecraft.getMinecraft().displayHeight - )); - } else if(shaderName.equalsIgnoreCase("void")) { - shaderManager.loadData(shaderId, "millis", (int) (System.currentTimeMillis() - startTime)); - shaderManager.loadData(shaderId, "screensize", new Vector2f( - Minecraft.getMinecraft().displayWidth, - Minecraft.getMinecraft().displayHeight - )); - } - } - - long lastRender = 0; - - public void onRenderPlayer(RenderPlayerEvent.Post e) { - EntityPlayer player = e.entityPlayer; - - if(currentPlayer != null && keepCurrentPlayer && currentPlayer != player) return; - - if(player.getActivePotionEffect(Potion.invisibility) != null) return; - if(player.isSpectator() || player.isInvisible()) return; - - ensureCapeNodesCreated(player); - - Entity viewer = Minecraft.getMinecraft().getRenderViewEntity(); - double viewerX = (viewer.lastTickPosX + (viewer.posX - viewer.lastTickPosX) * e.partialRenderTick) % 7789; - double viewerY = viewer.lastTickPosY + (viewer.posY - viewer.lastTickPosY) * e.partialRenderTick; - double viewerZ = (viewer.lastTickPosZ + (viewer.posZ - viewer.lastTickPosZ) * e.partialRenderTick) % 7789; - - GlStateManager.pushMatrix(); - GlStateManager.enableBlend(); - GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, - GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO); - bindTexture(); - GlStateManager.enableTexture2D(); - GlStateManager.enableDepth(); - GlStateManager.disableCull(); - GlStateManager.disableLighting(); - GlStateManager.color(1, 1, 1, 1); - - if(shaderName.equals("mcworld_cape")) { - GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR); - GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR); - } else { - GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST); - GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST); - } - - GL11.glTranslatef(-(float) viewerX, -(float) viewerY, -(float) viewerZ); - - ShaderManager shaderManager = ShaderManager.getInstance(); - shaderManager.loadShader("capes/" + shaderName + "/" + shaderName); - loadShaderUniforms(shaderManager); - - renderCape(player, e.partialRenderTick); - - GL11.glTranslatef((float) viewerX, (float) viewerY, (float) viewerZ); - - GL20.glUseProgram(0); - - GlStateManager.enableCull(); - GlStateManager.enableTexture2D(); - GlStateManager.disableBlend(); - GlStateManager.enableDepth(); - GlStateManager.enableLighting(); - GlStateManager.popMatrix(); - - lastRender = System.currentTimeMillis(); - } - - public void onTick(TickEvent.ClientTickEvent event, EntityPlayer player) { - if(player == null) return; - if(Minecraft.getMinecraft().isGamePaused()) return; - - if(System.currentTimeMillis() - lastRender < 500) { - if(currentPlayer == null || !keepCurrentPlayer) { - keepCurrentPlayer = true; - currentPlayer = player; - } else if(currentPlayer != player) { - return; - } - - ensureCapeNodesCreated(player); - - for(int y = 0; y < VERT_NODES; y++) { - for(int x = 0; x < HORZ_NODES; x++) { - CapeNode node = nodes[x + y * HORZ_NODES]; - node.lastPosition.x = node.position.x; - node.lastPosition.y = node.position.y; - node.lastPosition.z = node.position.z; - } - } - updateCape(player); - } else { - keepCurrentPlayer = false; - } - } - - private static double interpolateRotation(float a, float b, float amount) { - double f; - - for(f = b - a; f < -180.0F; f += 360.0F) { - ; - } - - while(f >= 180.0F) { - f -= 360.0F; - } - - return a + amount * f; - } - - private double getPlayerRenderAngle(EntityPlayer player, float partialRenderTick) { - double angle = interpolateRotation(player.prevRenderYawOffset, player.renderYawOffset, partialRenderTick); - - if(player.isRiding() && player.ridingEntity instanceof EntityLivingBase && player.ridingEntity.shouldRiderSit()) { - - EntityLivingBase entitylivingbase = (EntityLivingBase) player.ridingEntity; - double head = interpolateRotation(player.prevRotationYawHead, player.rotationYawHead, partialRenderTick); - angle = interpolateRotation(entitylivingbase.prevRenderYawOffset, entitylivingbase.renderYawOffset, partialRenderTick); - double wrapped = MathHelper.wrapAngleTo180_double(head - angle); - - if(wrapped < -85.0F) { - wrapped = -85.0F; - } - - if(wrapped >= 85.0F) { - wrapped = 85.0F; - } - - angle = head - wrapped; - - if(wrapped * wrapped > 2500.0F) { - angle += wrapped * 0.2F; - } - } - - return Math.toRadians(angle); - } - - private Vector3f updateFixedCapeNodes(EntityPlayer player) { - double pX = player.posX % 7789;//player.lastTickPosX + (player.posX - player.lastTickPosX) * partialRenderTick; - double pY = player.posY;//player.lastTickPosY + (player.posY - player.lastTickPosY) * partialRenderTick; - double pZ = player.posZ % 7789;//player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * partialRenderTick; - double angle = getPlayerRenderAngle(player, 0); - - double vertOffset2 = vertOffset + (player.isSneaking() ? -0.22f : 0) + (player.getCurrentArmor(2) != null ? 0.06f : 0); - double shoulderWidth2 = shoulderWidth + (player.getCurrentArmor(2) != null ? 0.08f : 0); - - float xOff = (float) (Math.cos(angle) * shoulderLength); - float zOff = (float) (Math.sin(angle) * shoulderLength); - - float totalDX = 0; - float totalDY = 0; - float totalDZ = 0; - int totalMovements = 0; - - for(int i = 0; i < HORZ_NODES; i++) { - float mult = 1 - 2f * i / (HORZ_NODES - 1); //1 -> -1 - float widthMult = 1.25f - (1.414f * i / (HORZ_NODES - 1) - 0.707f) * (1.414f * i / (HORZ_NODES - 1) - 0.707f); - CapeNode node = nodes[i]; - float x = (float) pX + (float) (xOff * mult - widthMult * Math.cos(angle + Math.PI / 2) * shoulderWidth2); - float y = (float) pY + (float) (vertOffset2); - float z = (float) pZ + (float) (zOff * mult - widthMult * Math.sin(angle + Math.PI / 2) * shoulderWidth2); - totalDX += x - node.position.x; - totalDY += y - node.position.y; - totalDZ += z - node.position.z; - totalMovements++; - node.position.x = x; - node.position.y = y; - node.position.z = z; - node.fixed = true; - } - - float avgDX = totalDX / totalMovements; - float avgDY = totalDY / totalMovements; - float avgDZ = totalDZ / totalMovements; - - return new Vector3f(avgDX, avgDY, avgDZ); - } - - private void updateFixedCapeNodesPartial(EntityPlayer player, float partialRenderTick) { - double pX = (player.lastTickPosX + (player.posX - player.lastTickPosX) * partialRenderTick) % 7789; - double pY = player.lastTickPosY + (player.posY - player.lastTickPosY) * partialRenderTick; - double pZ = (player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * partialRenderTick) % 7789; - double angle = getPlayerRenderAngle(player, partialRenderTick); - - double vertOffset2 = vertOffset + (player.isSneaking() ? -0.22f : 0) + (player.getCurrentArmor(2) != null ? 0.06f : 0); - double shoulderWidth2 = shoulderWidth + (player.getCurrentArmor(2) != null ? 0.08f : 0); - - float xOff = (float) (Math.cos(angle) * shoulderLength); - float zOff = (float) (Math.sin(angle) * shoulderLength); - - for(int i = 0; i < HORZ_NODES; i++) { - float mult = 1 - 2f * i / (HORZ_NODES - 1); //1 -> -1 - float widthMult = 1.25f - (1.414f * i / (HORZ_NODES - 1) - 0.707f) * (1.414f * i / (HORZ_NODES - 1) - 0.707f); - CapeNode node = nodes[i]; - node.renderPosition.x = (float) pX + (float) (xOff * mult - widthMult * Math.cos(angle + Math.PI / 2) * shoulderWidth2); - node.renderPosition.y = (float) pY + (float) (vertOffset2); - node.renderPosition.z = (float) pZ + (float) (zOff * mult - widthMult * Math.sin(angle + Math.PI / 2) * shoulderWidth2); - node.fixed = true; - } - } - - private double deltaAngleAccum; - private double oldPlayerAngle; - private int crouchTicks = 0; - long startTime = 0; - - private void updateCape(EntityPlayer player) { - Vector3f capeTranslation = updateFixedCapeNodes(player); - - if(shaderName.equals("space_cape")) { - long currentTime = System.currentTimeMillis(); - if(currentTime - startTime > eventMillis - startTime + eventLength) { - eventMillis = currentTime; - eventLength = random.nextFloat() * 2000 + 4000; - eventRandom = random.nextFloat(); - } - } else if(shaderName.equals("biscuit_cape") || shaderName.equals("shiny_cape")) { - long currentTime = System.currentTimeMillis(); - if(currentTime - startTime > eventMillis - startTime + eventLength) { - eventMillis = currentTime; - eventLength = random.nextFloat() * 3000 + 3000; - } - } - - double playerAngle = getPlayerRenderAngle(player, 0); - double deltaAngle = playerAngle - oldPlayerAngle; - if(deltaAngle > Math.PI) { - deltaAngle = 2 * Math.PI - deltaAngle; - } - if(deltaAngle < -Math.PI) { - deltaAngle = 2 * Math.PI + deltaAngle; - } - deltaAngleAccum *= 0.5f; - deltaAngleAccum += deltaAngle; - - float dX = (float) Math.cos(playerAngle + Math.PI / 2f); - float dZ = (float) Math.sin(playerAngle + Math.PI / 2f); - - float factor = (float) (deltaAngleAccum * deltaAngleAccum); - - float capeTransLength = capeTranslation.length(); - - float capeTranslationFactor = 0f; - if(capeTransLength > 0.5f) { - capeTranslationFactor = (capeTransLength - 0.5f) / capeTransLength; - } - Vector3f lookDir = new Vector3f(dX, 0, dZ); - Vector3f lookDirNorm = lookDir.normalise(null); - float dot = Vector3f.dot(capeTranslation, lookDirNorm); - if(dot < 0) { //Moving backwards - for(int y = 0; y < VERT_NODES; y++) { - for(int x = 0; x < HORZ_NODES; x++) { - CapeNode node = nodes[x + y * HORZ_NODES]; - if(!node.fixed) { - node.position.x += lookDirNorm.x * dot; - node.position.y += lookDirNorm.y * dot; - node.position.z += lookDirNorm.z * dot; - } - } - } - //Apply small backwards force - factor = 0.05f; - } - - if(factor > 0) { - for(int y = 0; y < VERT_NODES; y++) { - for(int x = 0; x < HORZ_NODES; x++) { - nodes[x + y * HORZ_NODES].applyForce(-dX * factor, 0, -dZ * factor); - } - } - } - - if(capeTranslationFactor > 0f) { - float capeDX = capeTranslation.x * capeTranslationFactor; - float capeDY = capeTranslation.y * capeTranslationFactor; - float capeDZ = capeTranslation.z * capeTranslationFactor; - - for(int y = 0; y < VERT_NODES; y++) { - for(int x = 0; x < HORZ_NODES; x++) { - CapeNode node = nodes[x + y * HORZ_NODES]; - if(!node.fixed) { - node.position.x += capeDX; - node.position.y += capeDY; - node.position.z += capeDZ; - } - } - } - } - - //Wind - float currTime = (System.currentTimeMillis() - startTime) / 1000f; - float windRandom = Math.abs((float) (0.5f * Math.sin(0.22f * currTime) + Math.sin(0.44f * currTime) * Math.sin(0.47f * currTime))); - double windDir = playerAngle + Math.PI / 4f * Math.sin(0.2f * currTime); - - float windDX = (float) Math.cos(windDir + Math.PI / 2f); - float windDZ = (float) Math.sin(windDir + Math.PI / 2f); - for(int y = 0; y < VERT_NODES; y++) { - for(int x = 0; x < HORZ_NODES; x++) { - nodes[x + y * HORZ_NODES].applyForce(-windDX * windRandom * 0.01f, 0, -windDZ * windRandom * 0.01f); - } - } - - if(player.isSneaking()) { - crouchTicks++; - float mult = 0.5f; - if(crouchTicks < 5) { - mult = 2f; - } - for(int y = 0; y < 8; y++) { - for(int x = 0; x < HORZ_NODES; x++) { - nodes[x + y * HORZ_NODES].applyForce(-dX * mult, 0, -dZ * mult); - } - } - } else { - crouchTicks = 0; - } - - Vector3f avgPosition = avgFixedPosition(); - for(int y = 0; y < VERT_NODES; y++) { - for(int x = 0; x < HORZ_NODES; x++) { - CapeNode node = nodes[x + y * HORZ_NODES]; - - Vector3f delta = Vector3f.sub(node.position, avgPosition, null); - - if(delta.lengthSquared() > 5 * 5) { - Vector3f norm = delta.normalise(null); - node.position = Vector3f.add(avgPosition, norm, null); - } - } - } - - oldPlayerAngle = playerAngle; - - for(int y = 0; y < VERT_NODES; y++) { - for(int x = 0; x < HORZ_NODES; x++) { - nodes[x + y * HORZ_NODES].update(); - } - } - int updates = player == Minecraft.getMinecraft().thePlayer ? 50 : 50; - for(int i = 0; i < updates; i++) { - for(int y = 0; y < VERT_NODES; y++) { - for(int x = 0; x < HORZ_NODES; x++) { - nodes[x + y * HORZ_NODES].resolveAll(2 + 1f * y / VERT_NODES, false); - } - } - } - } - - private int ssbo = -1; - - private void generateSSBO() { - ssbo = GL15.glGenBuffers(); - loadSBBO(); - } - - private void loadSBBO() { - FloatBuffer buff = BufferUtils.createFloatBuffer(CapeNode.FLOAT_NUM * HORZ_NODES * VERT_NODES); - for(int y = 0; y < VERT_NODES; y++) { - for(int x = 0; x < HORZ_NODES; x++) { - nodes[x + y * HORZ_NODES].loadIntoBuffer(buff); - } - } - buff.flip(); - - GL15.glBindBuffer(GL43.GL_SHADER_STORAGE_BUFFER, ssbo); - GL15.glBufferData(GL43.GL_SHADER_STORAGE_BUFFER, buff, GL15.GL_DYNAMIC_DRAW); - GL15.glBindBuffer(GL43.GL_SHADER_STORAGE_BUFFER, 0); - } - - private void resolveAllCompute() { - if(ssbo == -1) { - generateSSBO(); - } - loadSBBO(); - - int program = ShaderManager.getInstance().getShader("node"); - - int block_index = GL43.glGetProgramResourceIndex(program, GL43.GL_SHADER_STORAGE_BLOCK, "nodes_buffer"); - int ssbo_binding_point_index = 0; - GL43.glShaderStorageBlockBinding(program, block_index, ssbo_binding_point_index); - int binding_point_index = 0; - GL30.glBindBufferBase(GL43.GL_SHADER_STORAGE_BUFFER, binding_point_index, ssbo); - - GL20.glUseProgram(program); - - for(int i = 0; i < 30; i++) { - GL43.glDispatchCompute(VERT_NODES, 1, 1); - GL42.glMemoryBarrier(GL43.GL_SHADER_STORAGE_BARRIER_BIT); - } - - GL20.glUseProgram(0); - - FloatBuffer buff = BufferUtils.createFloatBuffer(CapeNode.FLOAT_NUM * HORZ_NODES * VERT_NODES); - - GL15.glBindBuffer(GL43.GL_SHADER_STORAGE_BUFFER, ssbo); - GL15.glGetBufferSubData(GL43.GL_SHADER_STORAGE_BUFFER, 0, buff); - GL15.glBindBuffer(GL43.GL_SHADER_STORAGE_BUFFER, 0); - - for(int y = 0; y < VERT_NODES; y++) { - for(int x = 0; x < HORZ_NODES; x++) { - nodes[x + y * HORZ_NODES].readFromBuffer(buff); - } - } - } - - private Vector3f avgRenderPosition() { - Vector3f accum = new Vector3f(); - int num = 0; - for(int y = 0; y < VERT_NODES; y++) { - for(int x = 0; x < HORZ_NODES; x++) { - CapeNode node = nodes[x + y * HORZ_NODES]; - Vector3f.add(accum, node.renderPosition, accum); - num++; - } - } - if(num != 0) { - accum.scale(1f / num); - } - return accum; - } - - private Vector3f avgNormal() { - Vector3f accum = new Vector3f(); - int num = 0; - for(int y = 0; y < VERT_NODES; y++) { - for(int x = 0; x < HORZ_NODES; x++) { - CapeNode node = nodes[x + y * HORZ_NODES]; - Vector3f.add(accum, node.normal(), accum); - num++; - } - } - if(num != 0) { - accum.scale(1f / num); - } - return accum; - } - - private Vector3f avgFixedRenderPosition() { - Vector3f accum = new Vector3f(); - int numFixed = 0; - for(int y = 0; y < VERT_NODES; y++) { - for(int x = 0; x < HORZ_NODES; x++) { - CapeNode node = nodes[x + y * HORZ_NODES]; - if(node.fixed) { - Vector3f.add(accum, node.renderPosition, accum); - numFixed++; - } - } - } - if(numFixed != 0) { - accum.scale(1f / numFixed); - } - return accum; - } - - private Vector3f avgFixedPosition() { - Vector3f accum = new Vector3f(); - int numFixed = 0; - for(int y = 0; y < VERT_NODES; y++) { - for(int x = 0; x < HORZ_NODES; x++) { - CapeNode node = nodes[x + y * HORZ_NODES]; - if(node.fixed) { - Vector3f.add(accum, node.position, accum); - numFixed++; - } - } - } - if(numFixed != 0) { - accum.scale(1f / numFixed); - } - return accum; - } - - private void renderBackAndDoFrontStencil() { - for(int y = 0; y < VERT_NODES; y++) { - for(int x = 0; x < HORZ_NODES; x++) { - nodes[x + y * HORZ_NODES].renderNode(CapeNode.DRAW_MASK_BACK | CapeNode.DRAW_MASK_SIDES); - } - } - - if(!Minecraft.getMinecraft().getFramebuffer().isStencilEnabled()) - Minecraft.getMinecraft().getFramebuffer().enableStencil(); - - GL11.glEnable(GL11.GL_STENCIL_TEST); - GL11.glStencilFunc(GL11.GL_ALWAYS, 1, 0xFF); - GL11.glStencilOp(GL11.GL_ZERO, GL11.GL_ZERO, GL11.GL_REPLACE); - GL11.glStencilMask(0xFF); - GL11.glClear(GL11.GL_STENCIL_BUFFER_BIT); - GlStateManager.enableDepth(); - - GL11.glColorMask(false, false, false, false); - for(int y = 0; y < VERT_NODES; y++) { - for(int x = 0; x < HORZ_NODES; x++) { - nodes[x + y * HORZ_NODES].renderNode(CapeNode.DRAW_MASK_FRONT); - } - } - GL11.glColorMask(true, true, true, true); - - // Only pass stencil test if equal to 1 - GL11.glStencilMask(0x00); - GL11.glStencilFunc(GL11.GL_EQUAL, 1, 0xFF); - } - - private Vector3f getPoint(Vector3f point, Vector3f... vectors) { - Vector3f res = new Vector3f(point); - for(Vector3f vec : vectors) Vector3f.add(res, vec, res); - return res; - } - - private static void renderVBO(WorldRenderer worldRenderer) { - if(worldRenderer != null && worldRenderer.getVertexCount() > 0) { - VertexFormat vertexformat = worldRenderer.getVertexFormat(); - int stride = vertexformat.getNextOffset(); - ByteBuffer bytebuffer = worldRenderer.getByteBuffer(); - List list = vertexformat.getElements(); - - for(int index = 0; index < list.size(); index++) { - VertexFormatElement vertexformatelement = list.get(index); - vertexformatelement.getUsage().preDraw(vertexformat, index, stride, bytebuffer); - } - - GL11.glDrawArrays(worldRenderer.getDrawMode(), 0, worldRenderer.getVertexCount()); - - for(int index = 0; index < list.size(); index++) { - VertexFormatElement vertexformatelement = list.get(index); - vertexformatelement.getUsage().postDraw(vertexformat, index, stride, bytebuffer); - } - } - } - - private static WorldRenderer sphereVBO = null; - - private void renderNodes() { - if(capeName.equalsIgnoreCase("planets")) { - renderBackAndDoFrontStencil(); - - Vector3f pointNorm = avgNormal(); - Vector3f capeAvgPos = avgRenderPosition(); - - pointNorm.scale(0.5f / pointNorm.length()); - pointNorm.scale(1 - pointNorm.y / 1.3f); - Vector3f point = Vector3f.sub(capeAvgPos, pointNorm, null); - - if(sphereVBO == null || Keyboard.isKeyDown(Keyboard.KEY_K)) { - if(sphereVBO != null) sphereVBO.reset(); - - int arcSegments = 24; - int rotationSegments = 24; - double arcAngleDelta = Math.PI / (arcSegments - 1); - - float xScale = 0.95f; - - double diameterUnitArcLen = 0; - - double arcAngle = 0; - for(int i = 0; i < arcSegments; i++) { - diameterUnitArcLen += Math.sin(arcAngle); - arcAngle += arcAngleDelta; - } - double arcLength = 2f / diameterUnitArcLen; - - List> arcs = new ArrayList<>(); - for(int angleI = 0; angleI < rotationSegments; angleI++) { - double angle = Math.PI * 2 * angleI / rotationSegments; - - List arc = new ArrayList<>(); - - Vector3f arcPos = new Vector3f(0, 0, -1); - - arc.add(arcPos); - - arcAngle = 0; - for(int segmentI = 0; segmentI < arcSegments; segmentI++) { - - double deltaZ = Math.sin(arcAngle) * arcLength; - double deltaY = Math.cos(arcAngle) * Math.cos(angle) * arcLength; - double deltaX = Math.cos(arcAngle) * Math.sin(angle) * arcLength * xScale; - - arcPos = new Vector3f(arcPos); - arcPos.z += deltaZ; - arcPos.y += deltaY; - arcPos.x += deltaX; - arcPos.normalise(); - arc.add(arcPos); - - arcAngle += arcAngleDelta; - } - - arcs.add(arc); - } - - sphereVBO = new WorldRenderer(8 * 4 * rotationSegments * arcSegments); - sphereVBO.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_NORMAL); - - double maxXYRad = 0; - for(int angleI = 0; angleI < rotationSegments; angleI++) { - for(int segmentI = 0; segmentI <= arcSegments; segmentI++) { - List thisArc = arcs.get(angleI); - Vector3f point1 = thisArc.get(segmentI); - double rad = Math.sqrt(point1.x * point1.x + point1.y * point1.y); - maxXYRad = Math.max(maxXYRad, rad); - } - } - - for(int angleI = 0; angleI < rotationSegments; angleI++) { - - int nextAngleI = angleI + 1; - if(angleI == rotationSegments - 1) { - nextAngleI = 0; - } - - float v = 0.5f * (angleI) / (rotationSegments); - float v2 = 0.5f * (angleI + 1) / (rotationSegments); - //if(v2 == 0) v2 = 0.5f; - - List thisArc = arcs.get(angleI); - List nextArc = arcs.get(nextAngleI); - - for(int segmentI = 1; segmentI <= arcSegments; segmentI++) { - Vector3f point1 = thisArc.get(segmentI); - Vector3f point2 = thisArc.get(segmentI - 1); - Vector3f point3 = nextArc.get(segmentI - 1); - Vector3f point4 = nextArc.get(segmentI); - - double u1 = 0.5f * segmentI / arcSegments; - double u2 = 0.5f * (segmentI - 1) / arcSegments; - - sphereVBO.pos(point4.x, point4.y, point4.z) - .tex(u1, v2).normal(-point4.x, -point4.y, -point4.z).endVertex(); - sphereVBO.pos(point3.x, point3.y, point3.z) - .tex(u2, v2).normal(-point3.x, -point3.y, -point3.z).endVertex(); - sphereVBO.pos(point2.x, point2.y, point2.z) - .tex(u2, v).normal(-point2.x, -point2.y, -point2.z).endVertex(); - sphereVBO.pos(point1.x, point1.y, point1.z) - .tex(u1, v).normal(-point1.x, -point1.y, -point1.z).endVertex(); - } - } - } - - String shaderId = "capes/" + shaderName + "/" + shaderName; - double mercuryAngle = Math.PI * 2 * ((System.currentTimeMillis() - startTime) / 10000f % 1); - double mercuryX = Math.sin(mercuryAngle) * 0.3; - double mercuryZ = Math.cos(mercuryAngle) * 0.3; - - double earthAngle = Math.PI * 2 * ((System.currentTimeMillis() - startTime) / 30000f % 1); - double earthSlant = Math.PI * 0.1; - double earthX = Math.sin(earthAngle) * Math.cos(earthSlant) * 0.6; - double earthY = Math.sin(earthAngle) * Math.sin(earthSlant) * 0.6; - double earthZ = Math.cos(earthAngle) * Math.cos(earthSlant) * 0.6; - - float sunDist = Vector3f.sub(point, capeAvgPos, null).lengthSquared(); - float mercuryDist = Vector3f.sub(new Vector3f(point.x + (float) mercuryX, point.y, point.z + (float) mercuryZ), - capeAvgPos, null).lengthSquared(); - float earthDist = Vector3f.sub(new Vector3f(point.x + (float) earthX, point.y + (float) earthY, point.z + (float) earthZ), - capeAvgPos, null).lengthSquared(); - - double jupiterAngle = Math.PI * 2 * ((System.currentTimeMillis() - startTime) / 200000f % 1); - double jupiterSlant = Math.PI * -0.08; - double jupiterX = Math.sin(jupiterAngle) * Math.cos(jupiterSlant) * 1.5; - double jupiterY = Math.sin(jupiterAngle) * Math.sin(jupiterSlant) * 1.5; - double jupiterZ = Math.cos(jupiterAngle) * Math.cos(jupiterSlant) * 1.5; - float jupiterDist = Vector3f.sub(new Vector3f(point.x + (float) jupiterX, point.y + (float) jupiterY, point.z + (float) jupiterZ), - capeAvgPos, null).lengthSquared(); - - double neptuneX = -Math.sin(earthAngle) * Math.cos(earthSlant); - double neptuneY = -Math.sin(earthAngle) * Math.sin(earthSlant); - double neptuneZ = -Math.cos(earthAngle) * Math.cos(earthSlant); - - float neptuneDist = Vector3f.sub(new Vector3f(point.x + (float) neptuneX, point.y + (float) neptuneY, point.z + (float) neptuneZ), - capeAvgPos, null).lengthSquared(); - - TreeMap orbitals = new TreeMap<>(); - orbitals.put(sunDist, 0); - orbitals.put(earthDist, 1); - orbitals.put(mercuryDist, 2); - - double delta = Minecraft.getMinecraft().getRenderViewEntity().getRotationYawHead() % 360; - while(delta < 0) delta += 360; - - double jupDelta = (delta + Math.toDegrees(jupiterAngle)) % 360; - while(jupDelta < 0) jupDelta += 360; - if(jupDelta > 250 || jupDelta < 110) orbitals.put(jupiterDist, 3); - - double nepDelta = (delta + Math.toDegrees(-earthAngle)) % 360; - while(nepDelta < 0) nepDelta += 360; - if(nepDelta > 250 || nepDelta < 110) orbitals.put(neptuneDist, 4); - - GlStateManager.disableDepth(); - GlStateManager.enableCull(); - - for(int planetId : orbitals.descendingMap().values()) { - GlStateManager.pushMatrix(); - switch(planetId) { - case 0: { - GlStateManager.translate(point.x, point.y, point.z); - GlStateManager.scale(0.2f, 0.2f, 0.2f); - break; - } - case 1: { - Vector3f sunVec = new Vector3f((float) earthX, (float) earthY, (float) earthZ); - ShaderManager.getInstance().loadData(shaderId, "sunVec", sunVec); - GlStateManager.translate(point.x + earthX, point.y + earthY, point.z + earthZ); - GlStateManager.scale(0.1f, 0.1f, 0.1f); - break; - } - case 2: { - Vector3f sunVec = new Vector3f((float) mercuryX, 0, (float) mercuryZ); - ShaderManager.getInstance().loadData(shaderId, "sunVec", sunVec); - GlStateManager.translate(point.x + mercuryX, point.y, point.z + mercuryZ); - GlStateManager.scale(0.05f, 0.05f, 0.05f); - break; - } - case 3: { - Vector3f sunVec = new Vector3f((float) jupiterX, (float) jupiterY, (float) jupiterZ); - ShaderManager.getInstance().loadData(shaderId, "sunVec", sunVec); - GlStateManager.translate(point.x + jupiterX, point.y + jupiterY, point.z + jupiterZ); - GlStateManager.scale(0.3f, 0.3f, 0.3f); - break; - } - case 4: { - Vector3f sunVec = new Vector3f((float) neptuneX, (float) neptuneY, (float) neptuneZ); - ShaderManager.getInstance().loadData(shaderId, "sunVec", sunVec); - GlStateManager.translate(point.x + neptuneX, point.y + neptuneY, point.z + neptuneZ); - GlStateManager.scale(0.15f, 0.15f, 0.15f); - break; - } - } - ShaderManager.getInstance().loadData(shaderId, "planetType", planetId); - renderVBO(sphereVBO); - GlStateManager.popMatrix(); - } - - - GlStateManager.disableCull(); - GlStateManager.enableDepth(); - - GL11.glDisable(GL11.GL_STENCIL_TEST); - } else if(capeName.equalsIgnoreCase("parallax")) { - renderBackAndDoFrontStencil(); - - Vector3f pointNorm = avgNormal(); - pointNorm.scale(-0.2f / pointNorm.length()); - Vector3f negPointNorm = new Vector3f(pointNorm); - negPointNorm.scale(-1); - //pointNorm.scale(1 - pointNorm.y/1.3f); - Vector3f point = Vector3f.add(avgRenderPosition(), pointNorm, null); - Vector3f fixedPoint = Vector3f.add(avgFixedRenderPosition(), pointNorm, null); - - Vector3f up = Vector3f.sub(fixedPoint, point, null); - float halfUp = up.length(); - - Vector3f down = new Vector3f(up); - down.scale(-1); - - Vector3f left = Vector3f.cross(up, pointNorm, null); - left.scale(halfUp * 522f / 341f / left.length()); - Vector3f right = new Vector3f(left); - right.scale(-1); - - Vector3f point1 = getPoint(point, left); - Vector3f point2 = getPoint(point, left, down, down); - Vector3f point3 = getPoint(point, right, down, down); - Vector3f point4 = getPoint(point, right); - - Vector3f point2Edge = getPoint(point2, negPointNorm, negPointNorm); - Vector3f point3Edge = getPoint(point3, negPointNorm, negPointNorm); - - GlStateManager.disableDepth(); - GlStateManager.disableCull(); - - GlStateManager.color(1, 1, 1, 1); - - Tessellator tessellator = Tessellator.getInstance(); - WorldRenderer worldrenderer = tessellator.getWorldRenderer(); - worldrenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); - - worldrenderer.pos(point1.x, point1.y, point1.z) - .tex(0, 943 / 1024f).endVertex(); - worldrenderer.pos(point2.x, point2.y, point2.z) - .tex(280 / 1024f, 943 / 1024f).endVertex(); - worldrenderer.pos(point3.x, point3.y, point3.z) - .tex(280 / 1024f, 421 / 1024f).endVertex(); - worldrenderer.pos(point4.x, point4.y, point4.z) - .tex(0, 421 / 1024f).endVertex(); - - tessellator.draw(); - - worldrenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); - - worldrenderer.pos(point2.x, point2.y, point2.z) - .tex(280 / 1024f, 943 / 1024f).endVertex(); - worldrenderer.pos(point2Edge.x, point2Edge.y, point2Edge.z) - .tex(341 / 1024f, 943 / 1024f).endVertex(); - worldrenderer.pos(point3Edge.x, point3Edge.y, point3Edge.z) - .tex(341 / 1024f, 421 / 1024f).endVertex(); - worldrenderer.pos(point3.x, point3.y, point3.z) - .tex(280 / 1024f, 421 / 1024f).endVertex(); - - tessellator.draw(); - - - GlStateManager.disableCull(); - GlStateManager.enableDepth(); - - GL11.glDisable(GL11.GL_STENCIL_TEST); - } else if(capeName.equalsIgnoreCase("tunnel")) { - renderBackAndDoFrontStencil(); - - Vector3f pointNorm = avgNormal(); - - pointNorm.scale(0.7f / pointNorm.length()); - pointNorm.scale(1 - pointNorm.y / 1.3f); - Vector3f point = Vector3f.sub(avgRenderPosition(), pointNorm, null); - - List edgeNodes = new ArrayList<>(); - List edgeCoords = new ArrayList<>(); - - //Left edge - for(int y = 0; y < VERT_NODES; y++) { - edgeNodes.add(nodes[y * HORZ_NODES]); - edgeCoords.add(new Vector2f(0, (float) y / (VERT_NODES - 1))); - } - edgeNodes.add(null); - edgeCoords.add(null); - //Bottom edge - int bottomIndex = VERT_NODES - 1; - int botSize = HORZ_NODES; - for(int x = 0; x < botSize; x++) { - edgeNodes.add(getNode(x, bottomIndex)); - edgeCoords.add(new Vector2f((float) x / (botSize - 1), 1)); - } - edgeNodes.add(null); - edgeCoords.add(null); - //Right edge - for(int y = VERT_NODES - 1; y >= 0; y--) { - edgeNodes.add(getNode(HORZ_NODES - 1, y)); - edgeCoords.add(new Vector2f(1, (float) y / VERT_NODES)); - } - edgeNodes.add(null); - edgeCoords.add(null); - //Top edge - int topSize = HORZ_NODES; - for(int x = topSize - 1; x >= 0; x--) { - edgeNodes.add(getNode(x, 0)); - edgeCoords.add(new Vector2f((float) x / (topSize - 1), 0)); - } - - GlStateManager.disableDepth(); - GlStateManager.enableCull(); - CapeNode last = null; - for(int i = 0; i < edgeNodes.size(); i++) { - CapeNode node = edgeNodes.get(i); - if(last != null && node != null) { - Vector2f lastCoord = edgeCoords.get(i - 1); - Vector2f coord = edgeCoords.get(i); - - Tessellator tessellator = Tessellator.getInstance(); - WorldRenderer worldrenderer = tessellator.getWorldRenderer(); - worldrenderer.begin(GL11.GL_TRIANGLES, DefaultVertexFormats.POSITION_TEX_NORMAL); - - Vector3f lastNodeNorm = last.normal(); - worldrenderer.pos(last.renderPosition.x + lastNodeNorm.x * 0.05f, last.renderPosition.y + lastNodeNorm.y * 0.05f, last.renderPosition.z + lastNodeNorm.z * 0.05f) - .tex(lastCoord.x * 300f / 1024f, lastCoord.y * 420f / 1024f) - .normal(-lastNodeNorm.x, -lastNodeNorm.y, -lastNodeNorm.z).endVertex(); - - Vector3f nodeNorm = node.normal(); - worldrenderer.pos(node.renderPosition.x + nodeNorm.x * 0.05f, node.renderPosition.y + nodeNorm.y * 0.05f, node.renderPosition.z + nodeNorm.z * 0.05f) - .tex(coord.x * 300f / 1024f, coord.y * 420f / 1024f) - .normal(-nodeNorm.x, -nodeNorm.y, -nodeNorm.z).endVertex(); - - worldrenderer.pos(point.x, point.y, point.z) - .tex(150f / 1024f, 210f / 1024f) - .normal(-pointNorm.x, -pointNorm.y, -pointNorm.z).endVertex(); - - tessellator.draw(); - } - last = node; - } - GlStateManager.disableCull(); - GlStateManager.enableDepth(); - - GL11.glDisable(GL11.GL_STENCIL_TEST); - } else { - for(int y = 0; y < VERT_NODES; y++) { - for(int x = 0; x < HORZ_NODES; x++) { - nodes[x + y * HORZ_NODES].renderNode(); - } - } - } - } - - private void renderCape(EntityPlayer player, float partialRenderTick) { - ensureCapeNodesCreated(player); - - Vector3f avgPositionFixedBefore = avgFixedRenderPosition(); - updateFixedCapeNodesPartial(player, partialRenderTick); - Vector3f avgPositionFixed = avgFixedRenderPosition(); - Vector3f delta = Vector3f.sub(avgPositionFixed, avgPositionFixedBefore, null); - - if(delta.lengthSquared() > 9) { - updateFixedCapeNodes(player); - - for(int y = 0; y < VERT_NODES; y++) { - for(int x = 0; x < HORZ_NODES; x++) { - CapeNode node = nodes[x + y * HORZ_NODES]; - if(!node.fixed) { - Vector3f.add(node.renderPosition, delta, node.renderPosition); - node.position.set(node.renderPosition); - node.lastPosition.set(node.renderPosition); - } else { - node.lastPosition.set(node.position); - } - } - } - - renderNodes(); - return; - } - - for(int y = 0; y < VERT_NODES; y++) { - for(int x = 0; x < HORZ_NODES; x++) { - CapeNode node = nodes[x + y * HORZ_NODES]; - - node.resetNormal(); - - if(node.fixed) continue; - - Vector3f newPosition = new Vector3f(); - newPosition.x = node.lastPosition.x + (node.position.x - node.lastPosition.x) * partialRenderTick; - newPosition.y = node.lastPosition.y + (node.position.y - node.lastPosition.y) * partialRenderTick; - newPosition.z = node.lastPosition.z + (node.position.z - node.lastPosition.z) * partialRenderTick; - - int length = node.oldRenderPosition.length; - - int fps = Minecraft.getDebugFPS(); - if(fps < 50) { - length = 2; - } else if(fps < 100) { - length = 2 + (int) ((fps - 50) / 50f * 3); - } - - if(node.oldRenderPosition[length - 1] == null) { - Arrays.fill(node.oldRenderPosition, Vector3f.sub(newPosition, avgPositionFixed, null)); - node.renderPosition = newPosition; - } else { - Vector3f accum = new Vector3f(); - for(int i = 0; i < length; i++) { - Vector3f.add(accum, node.oldRenderPosition[i], accum); - Vector3f.add(accum, avgPositionFixed, accum); - } - accum.scale(1 / (float) (length)); - - float blendFactor = 0.5f + 0.3f * y / (float) (VERT_NODES - 1); //0.5/0.5 -> 0.8/0.2 //0-1 - accum.scale(blendFactor); - newPosition.scale(1 - blendFactor); - Vector3f.add(accum, newPosition, accum); - node.renderPosition = accum; - } - - if(!Minecraft.getMinecraft().isGamePaused()) { - for(int i = node.oldRenderPosition.length - 1; i >= 0; i--) { - if(i > 0) { - node.oldRenderPosition[i] = node.oldRenderPosition[i - 1]; - } else { - node.oldRenderPosition[i] = Vector3f.sub(node.renderPosition, avgPositionFixed, null); - } - } - } - } - } - renderNodes(); - } - + private int currentFrame = 0; + private int displayFrame = 0; + private String capeName; + public ResourceLocation[] capeTextures = null; + + private long lastFrameUpdate = 0; + + private static final int ANIM_MODE_LOOP = 0; + private static final int ANIM_MODE_PINGPONG = 1; + private final int animMode = ANIM_MODE_LOOP; + + private CapeNode[] nodes = null; + + private final Random random = new Random(); + + private long eventMillis; + private float eventLength; + private float eventRandom; + + private static final double vertOffset = 1.4; + private static final double shoulderLength = 0.24; + private static final double shoulderWidth = 0.13; + + public static final int HORZ_NODES = 6; + public static final int VERT_NODES = 22; + + public static float targetDist = 1 / 20f; + + private EntityPlayer currentPlayer; + private boolean keepCurrentPlayer = false; + + private String shaderName = "cape"; + + public NEUCape(String capeName) { + setCapeTexture(capeName); + } + + public void setCapeTexture(String capeName) { + if (this.capeName != null && this.capeName.equalsIgnoreCase(capeName)) return; + + startTime = System.currentTimeMillis(); + boolean defaultBehaviour = true; + + if (NotEnoughUpdates.INSTANCE.config.hidden.disableBrokenCapes) { + if (capeName.equals("negative")) { + defaultBehaviour = false; + this.capeName = "fade"; + this.shaderName = "fade_cape"; + } + + } + if (defaultBehaviour) { + this.capeName = capeName; + + if (capeName.equalsIgnoreCase("fade")) { + shaderName = "fade_cape"; + } else if (capeName.equalsIgnoreCase("space")) { + shaderName = "space_cape"; + } else if (capeName.equalsIgnoreCase("mcworld")) { + shaderName = "mcworld_cape"; + } else if (capeName.equalsIgnoreCase("lava") || capeName.equalsIgnoreCase("skyclient")) { + shaderName = "lava_cape"; + } else if (capeName.equalsIgnoreCase("lightning")) { + shaderName = "lightning_cape"; + } else if (capeName.equalsIgnoreCase("thebakery")) { + shaderName = "biscuit_cape"; + } else if (capeName.equalsIgnoreCase("negative")) { + shaderName = "negative"; + } else if (capeName.equalsIgnoreCase("void")) { + shaderName = "void"; + } else if (capeName.equalsIgnoreCase("tunnel")) { + shaderName = "tunnel"; + } else if (capeName.equalsIgnoreCase("planets")) { + shaderName = "planets"; + } else { + shaderName = "shiny_cape"; + } + } + + ResourceLocation staticCapeTex = new ResourceLocation("notenoughupdates:capes/" + capeName + ".png"); + capeTextures = new ResourceLocation[1]; + capeTextures[0] = staticCapeTex; + } + + private void bindTexture() { + if (capeName.equalsIgnoreCase("negative")) { + CapeManager.getInstance().updateWorldFramebuffer = true; + if (CapeManager.getInstance().backgroundFramebuffer != null) { + CapeManager.getInstance().backgroundFramebuffer.bindFramebufferTexture(); + } + } else if (capeTextures != null && capeTextures.length > 0) { + long currentTime = System.currentTimeMillis(); + if (currentTime - lastFrameUpdate > 100) { + lastFrameUpdate = currentTime / 100 * 100; + currentFrame++; + + if (animMode == ANIM_MODE_PINGPONG) { + if (capeTextures.length == 1) { + currentFrame = displayFrame = 0; + } else { + int frameCount = 2 * capeTextures.length - 2; + currentFrame %= frameCount; + displayFrame = currentFrame; + if (currentFrame >= capeTextures.length) { + displayFrame = frameCount - displayFrame; + } + } + } else if (animMode == ANIM_MODE_LOOP) { + currentFrame %= capeTextures.length; + displayFrame = currentFrame; + } + } + Minecraft.getMinecraft().getTextureManager().bindTexture(capeTextures[displayFrame]); + } + } + + private CapeNode getNode(int x, int y) { + return nodes[x + y * HORZ_NODES]; + } + + public void createCapeNodes(EntityPlayer player) { + nodes = new CapeNode[HORZ_NODES * VERT_NODES]; + + float pX = (float) player.posX % 7789; + float pY = (float) player.posY; + float pZ = (float) player.posZ % 7789; + + float uMinTop = 48 / 1024f; + float uMaxTop = 246 / 1024f; + float uMinBottom = 0 / 1024f; + float uMaxBottom = 293 / 1024f; + + float vMaxSide = 404 / 1024f; + float vMaxCenter = 419 / 1024f; + + for (int i = 0; i < VERT_NODES; i++) { + float uMin = uMinTop + (uMinBottom - uMinTop) * i / (float) (VERT_NODES - 1); + float uMax = uMaxTop + (uMaxBottom - uMaxTop) * i / (float) (VERT_NODES - 1); + + for (int j = 0; j < HORZ_NODES; j++) { + float vMin = 0f; + float centerMult = 1 - Math.abs(j - (HORZ_NODES - 1) / 2f) / + ((HORZ_NODES - 1) / 2f);//0-(horzCapeNodes) -> 0-1-0 + float vMax = vMaxSide + (vMaxCenter - vMaxSide) * centerMult; + + CapeNode node = new CapeNode(pX, pY, pZ);//pX-1, pY+2-i*targetDist, pZ+(j-(horzCapeNodes-1)/2f)*targetDist*2 + node.texU = uMin + (uMax - uMin) * j / (float) (HORZ_NODES - 1); + node.texV = vMin + (vMax - vMin) * i / (float) (VERT_NODES - 1); + + node.horzDistMult = 2f + 1f * i / (float) (VERT_NODES - 1); + + if (j == 0 || j == HORZ_NODES - 1) { + node.horzSideTexU = 406 / 1024f * i / (float) (VERT_NODES - 1); + if (j == 0) { + node.horzSideTexVTop = 1 - 20 / 1024f; + } else { + node.horzSideTexVTop = 1 - 40 / 1024f; + } + } + if (i == 0) { + node.vertSideTexU = 198 / 1024f * j / (float) (HORZ_NODES - 1); + node.vertSideTexVTop = 1 - 60 / 1024f; + } else if (i == VERT_NODES - 1) { + node.vertSideTexU = 300 / 1024f * j / (float) (HORZ_NODES - 1); + node.vertSideTexVTop = 1 - 80 / 1024f; + } + nodes[j + i * HORZ_NODES] = node; + } + } + for (int y = 0; y < VERT_NODES; y++) { + for (int x = 0; x < HORZ_NODES; x++) { + CapeNode node = nodes[x + y * HORZ_NODES]; + + for (Direction dir : Direction.values()) { + for (int i = 1; i <= 2; i++) { + Offset offset = new Offset(dir, i); + + int xNeighbor = x + offset.getXOffset(); + int yNeighbor = y + offset.getYOffset(); + + if (xNeighbor >= 0 && xNeighbor < HORZ_NODES + && yNeighbor >= 0 && yNeighbor < VERT_NODES) { + CapeNode neighbor = nodes[xNeighbor + yNeighbor * HORZ_NODES]; + node.setNeighbor(offset, neighbor); + } + } + } + } + } + } + + public void ensureCapeNodesCreated(EntityPlayer player) { + if (nodes == null) createCapeNodes(player); + } + + public enum Direction { + LEFT(-1, 0), + UP(0, 1), + RIGHT(1, 0), + DOWN(0, -1), + UPLEFT(-1, 1), + UPRIGHT(1, 1), + DOWNLEFT(-1, -1), + DOWNRIGHT(1, -1); + + int xOff; + int yOff; + + Direction(int xOff, int yOff) { + this.xOff = xOff; + this.yOff = yOff; + } + + public Direction rotateRight90() { + int wantXOff = -yOff; + int wantYOff = xOff; + for (Direction dir : values()) { + if (dir.xOff == wantXOff && dir.yOff == wantYOff) { + return dir; + } + } + return this; + } + + public Direction rotateLeft90() { + int wantXOff = yOff; + int wantYOff = -xOff; + for (Direction dir : values()) { + if (dir.xOff == wantXOff && dir.yOff == wantYOff) { + return dir; + } + } + return this; + } + } + + public static class Offset { + Direction direction; + int steps; + + public Offset(Direction direction, int steps) { + this.direction = direction; + this.steps = steps; + } + + public int getXOffset() { + return direction.xOff * steps; + } + + public int getYOffset() { + return direction.yOff * steps; + } + + public boolean equals(Object obj) { + if (obj instanceof Offset) { + Offset other = (Offset) obj; + return other.direction == direction && other.steps == steps; + } + return false; + } + + @Override + public int hashCode() { + return 13 * direction.ordinal() + 7 * steps; + } + } + + private void loadShaderUniforms(ShaderManager shaderManager) { + String shaderId = "capes/" + shaderName + "/" + shaderName; + if (shaderName.equalsIgnoreCase("fade_cape") || shaderName.equalsIgnoreCase("planets")) { + shaderManager.loadData(shaderId, "millis", (int) (System.currentTimeMillis() - startTime)); + } else if (shaderName.equalsIgnoreCase("space_cape")) { + shaderManager.loadData(shaderId, "millis", (int) (System.currentTimeMillis() - startTime)); + shaderManager.loadData(shaderId, "eventMillis", (int) (System.currentTimeMillis() - eventMillis)); + shaderManager.loadData(shaderId, "eventRand", eventRandom); + } else if (shaderName.equalsIgnoreCase("mcworld_cape")) { + shaderManager.loadData(shaderId, "millis", (int) (System.currentTimeMillis() - startTime)); + } else if (shaderName.equalsIgnoreCase("lava_cape")) { + shaderManager.loadData(shaderId, "millis", (int) (System.currentTimeMillis() - startTime)); + } else if (shaderName.equalsIgnoreCase("tunnel")) { + shaderManager.loadData(shaderId, "millis", (int) (System.currentTimeMillis() - startTime)); + } else if (shaderName.equalsIgnoreCase("biscuit_cape") || shaderName.equalsIgnoreCase("shiny_cape")) { + shaderManager.loadData(shaderId, "millis", (int) (System.currentTimeMillis() - startTime)); + shaderManager.loadData(shaderId, "eventMillis", (int) (System.currentTimeMillis() - eventMillis)); + } else if (shaderName.equalsIgnoreCase("negative")) { + shaderManager.loadData(shaderId, "screensize", new Vector2f( + Minecraft.getMinecraft().displayWidth, + Minecraft.getMinecraft().displayHeight + )); + } else if (shaderName.equalsIgnoreCase("void")) { + shaderManager.loadData(shaderId, "millis", (int) (System.currentTimeMillis() - startTime)); + shaderManager.loadData(shaderId, "screensize", new Vector2f( + Minecraft.getMinecraft().displayWidth, + Minecraft.getMinecraft().displayHeight + )); + } + } + + long lastRender = 0; + + public void onRenderPlayer(RenderPlayerEvent.Post e) { + EntityPlayer player = e.entityPlayer; + + if (currentPlayer != null && keepCurrentPlayer && currentPlayer != player) return; + + if (player.getActivePotionEffect(Potion.invisibility) != null) return; + if (player.isSpectator() || player.isInvisible()) return; + + ensureCapeNodesCreated(player); + + Entity viewer = Minecraft.getMinecraft().getRenderViewEntity(); + double viewerX = (viewer.lastTickPosX + (viewer.posX - viewer.lastTickPosX) * e.partialRenderTick) % 7789; + double viewerY = viewer.lastTickPosY + (viewer.posY - viewer.lastTickPosY) * e.partialRenderTick; + double viewerZ = (viewer.lastTickPosZ + (viewer.posZ - viewer.lastTickPosZ) * e.partialRenderTick) % 7789; + + GlStateManager.pushMatrix(); + GlStateManager.enableBlend(); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, + GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO + ); + bindTexture(); + GlStateManager.enableTexture2D(); + GlStateManager.enableDepth(); + GlStateManager.disableCull(); + GlStateManager.disableLighting(); + GlStateManager.color(1, 1, 1, 1); + + if (shaderName.equals("mcworld_cape")) { + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR); + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR); + } else { + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST); + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST); + } + + GL11.glTranslatef(-(float) viewerX, -(float) viewerY, -(float) viewerZ); + + ShaderManager shaderManager = ShaderManager.getInstance(); + shaderManager.loadShader("capes/" + shaderName + "/" + shaderName); + loadShaderUniforms(shaderManager); + + renderCape(player, e.partialRenderTick); + + GL11.glTranslatef((float) viewerX, (float) viewerY, (float) viewerZ); + + GL20.glUseProgram(0); + + GlStateManager.enableCull(); + GlStateManager.enableTexture2D(); + GlStateManager.disableBlend(); + GlStateManager.enableDepth(); + GlStateManager.enableLighting(); + GlStateManager.popMatrix(); + + lastRender = System.currentTimeMillis(); + } + + public void onTick(TickEvent.ClientTickEvent event, EntityPlayer player) { + if (player == null) return; + if (Minecraft.getMinecraft().isGamePaused()) return; + + if (System.currentTimeMillis() - lastRender < 500) { + if (currentPlayer == null || !keepCurrentPlayer) { + keepCurrentPlayer = true; + currentPlayer = player; + } else if (currentPlayer != player) { + return; + } + + ensureCapeNodesCreated(player); + + for (int y = 0; y < VERT_NODES; y++) { + for (int x = 0; x < HORZ_NODES; x++) { + CapeNode node = nodes[x + y * HORZ_NODES]; + node.lastPosition.x = node.position.x; + node.lastPosition.y = node.position.y; + node.lastPosition.z = node.position.z; + } + } + updateCape(player); + } else { + keepCurrentPlayer = false; + } + } + + private static double interpolateRotation(float a, float b, float amount) { + double f; + + for (f = b - a; f < -180.0F; f += 360.0F) { + } + + while (f >= 180.0F) { + f -= 360.0F; + } + + return a + amount * f; + } + + private double getPlayerRenderAngle(EntityPlayer player, float partialRenderTick) { + double angle = interpolateRotation(player.prevRenderYawOffset, player.renderYawOffset, partialRenderTick); + + if (player.isRiding() && player.ridingEntity instanceof EntityLivingBase && player.ridingEntity.shouldRiderSit()) { + + EntityLivingBase entitylivingbase = (EntityLivingBase) player.ridingEntity; + double head = interpolateRotation(player.prevRotationYawHead, player.rotationYawHead, partialRenderTick); + angle = interpolateRotation( + entitylivingbase.prevRenderYawOffset, + entitylivingbase.renderYawOffset, + partialRenderTick + ); + double wrapped = MathHelper.wrapAngleTo180_double(head - angle); + + if (wrapped < -85.0F) { + wrapped = -85.0F; + } + + if (wrapped >= 85.0F) { + wrapped = 85.0F; + } + + angle = head - wrapped; + + if (wrapped * wrapped > 2500.0F) { + angle += wrapped * 0.2F; + } + } + + return Math.toRadians(angle); + } + + private Vector3f updateFixedCapeNodes(EntityPlayer player) { + double pX = player.posX % 7789;//player.lastTickPosX + (player.posX - player.lastTickPosX) * partialRenderTick; + double pY = player.posY;//player.lastTickPosY + (player.posY - player.lastTickPosY) * partialRenderTick; + double pZ = player.posZ % 7789;//player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * partialRenderTick; + double angle = getPlayerRenderAngle(player, 0); + + double vertOffset2 = + vertOffset + (player.isSneaking() ? -0.22f : 0) + (player.getCurrentArmor(2) != null ? 0.06f : 0); + double shoulderWidth2 = shoulderWidth + (player.getCurrentArmor(2) != null ? 0.08f : 0); + + float xOff = (float) (Math.cos(angle) * shoulderLength); + float zOff = (float) (Math.sin(angle) * shoulderLength); + + float totalDX = 0; + float totalDY = 0; + float totalDZ = 0; + int totalMovements = 0; + + for (int i = 0; i < HORZ_NODES; i++) { + float mult = 1 - 2f * i / (HORZ_NODES - 1); //1 -> -1 + float widthMult = 1.25f - (1.414f * i / (HORZ_NODES - 1) - 0.707f) * (1.414f * i / (HORZ_NODES - 1) - 0.707f); + CapeNode node = nodes[i]; + float x = (float) pX + (float) (xOff * mult - widthMult * Math.cos(angle + Math.PI / 2) * shoulderWidth2); + float y = (float) pY + (float) (vertOffset2); + float z = (float) pZ + (float) (zOff * mult - widthMult * Math.sin(angle + Math.PI / 2) * shoulderWidth2); + totalDX += x - node.position.x; + totalDY += y - node.position.y; + totalDZ += z - node.position.z; + totalMovements++; + node.position.x = x; + node.position.y = y; + node.position.z = z; + node.fixed = true; + } + + float avgDX = totalDX / totalMovements; + float avgDY = totalDY / totalMovements; + float avgDZ = totalDZ / totalMovements; + + return new Vector3f(avgDX, avgDY, avgDZ); + } + + private void updateFixedCapeNodesPartial(EntityPlayer player, float partialRenderTick) { + double pX = (player.lastTickPosX + (player.posX - player.lastTickPosX) * partialRenderTick) % 7789; + double pY = player.lastTickPosY + (player.posY - player.lastTickPosY) * partialRenderTick; + double pZ = (player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * partialRenderTick) % 7789; + double angle = getPlayerRenderAngle(player, partialRenderTick); + + double vertOffset2 = + vertOffset + (player.isSneaking() ? -0.22f : 0) + (player.getCurrentArmor(2) != null ? 0.06f : 0); + double shoulderWidth2 = shoulderWidth + (player.getCurrentArmor(2) != null ? 0.08f : 0); + + float xOff = (float) (Math.cos(angle) * shoulderLength); + float zOff = (float) (Math.sin(angle) * shoulderLength); + + for (int i = 0; i < HORZ_NODES; i++) { + float mult = 1 - 2f * i / (HORZ_NODES - 1); //1 -> -1 + float widthMult = 1.25f - (1.414f * i / (HORZ_NODES - 1) - 0.707f) * (1.414f * i / (HORZ_NODES - 1) - 0.707f); + CapeNode node = nodes[i]; + node.renderPosition.x = (float) pX + (float) (xOff * mult - widthMult * Math.cos(angle + Math.PI / 2) * + shoulderWidth2); + node.renderPosition.y = (float) pY + (float) (vertOffset2); + node.renderPosition.z = (float) pZ + (float) (zOff * mult - widthMult * Math.sin(angle + Math.PI / 2) * + shoulderWidth2); + node.fixed = true; + } + } + + private double deltaAngleAccum; + private double oldPlayerAngle; + private int crouchTicks = 0; + long startTime = 0; + + private void updateCape(EntityPlayer player) { + Vector3f capeTranslation = updateFixedCapeNodes(player); + + if (shaderName.equals("space_cape")) { + long currentTime = System.currentTimeMillis(); + if (currentTime - startTime > eventMillis - startTime + eventLength) { + eventMillis = currentTime; + eventLength = random.nextFloat() * 2000 + 4000; + eventRandom = random.nextFloat(); + } + } else if (shaderName.equals("biscuit_cape") || shaderName.equals("shiny_cape")) { + long currentTime = System.currentTimeMillis(); + if (currentTime - startTime > eventMillis - startTime + eventLength) { + eventMillis = currentTime; + eventLength = random.nextFloat() * 3000 + 3000; + } + } + + double playerAngle = getPlayerRenderAngle(player, 0); + double deltaAngle = playerAngle - oldPlayerAngle; + if (deltaAngle > Math.PI) { + deltaAngle = 2 * Math.PI - deltaAngle; + } + if (deltaAngle < -Math.PI) { + deltaAngle = 2 * Math.PI + deltaAngle; + } + deltaAngleAccum *= 0.5f; + deltaAngleAccum += deltaAngle; + + float dX = (float) Math.cos(playerAngle + Math.PI / 2f); + float dZ = (float) Math.sin(playerAngle + Math.PI / 2f); + + float factor = (float) (deltaAngleAccum * deltaAngleAccum); + + float capeTransLength = capeTranslation.length(); + + float capeTranslationFactor = 0f; + if (capeTransLength > 0.5f) { + capeTranslationFactor = (capeTransLength - 0.5f) / capeTransLength; + } + Vector3f lookDir = new Vector3f(dX, 0, dZ); + Vector3f lookDirNorm = lookDir.normalise(null); + float dot = Vector3f.dot(capeTranslation, lookDirNorm); + if (dot < 0) { //Moving backwards + for (int y = 0; y < VERT_NODES; y++) { + for (int x = 0; x < HORZ_NODES; x++) { + CapeNode node = nodes[x + y * HORZ_NODES]; + if (!node.fixed) { + node.position.x += lookDirNorm.x * dot; + node.position.y += lookDirNorm.y * dot; + node.position.z += lookDirNorm.z * dot; + } + } + } + //Apply small backwards force + factor = 0.05f; + } + + if (factor > 0) { + for (int y = 0; y < VERT_NODES; y++) { + for (int x = 0; x < HORZ_NODES; x++) { + nodes[x + y * HORZ_NODES].applyForce(-dX * factor, 0, -dZ * factor); + } + } + } + + if (capeTranslationFactor > 0f) { + float capeDX = capeTranslation.x * capeTranslationFactor; + float capeDY = capeTranslation.y * capeTranslationFactor; + float capeDZ = capeTranslation.z * capeTranslationFactor; + + for (int y = 0; y < VERT_NODES; y++) { + for (int x = 0; x < HORZ_NODES; x++) { + CapeNode node = nodes[x + y * HORZ_NODES]; + if (!node.fixed) { + node.position.x += capeDX; + node.position.y += capeDY; + node.position.z += capeDZ; + } + } + } + } + + //Wind + float currTime = (System.currentTimeMillis() - startTime) / 1000f; + float windRandom = Math.abs((float) (0.5f * Math.sin(0.22f * currTime) + Math.sin(0.44f * currTime) * Math.sin( + 0.47f * currTime))); + double windDir = playerAngle + Math.PI / 4f * Math.sin(0.2f * currTime); + + float windDX = (float) Math.cos(windDir + Math.PI / 2f); + float windDZ = (float) Math.sin(windDir + Math.PI / 2f); + for (int y = 0; y < VERT_NODES; y++) { + for (int x = 0; x < HORZ_NODES; x++) { + nodes[x + y * HORZ_NODES].applyForce(-windDX * windRandom * 0.01f, 0, -windDZ * windRandom * 0.01f); + } + } + + if (player.isSneaking()) { + crouchTicks++; + float mult = 0.5f; + if (crouchTicks < 5) { + mult = 2f; + } + for (int y = 0; y < 8; y++) { + for (int x = 0; x < HORZ_NODES; x++) { + nodes[x + y * HORZ_NODES].applyForce(-dX * mult, 0, -dZ * mult); + } + } + } else { + crouchTicks = 0; + } + + Vector3f avgPosition = avgFixedPosition(); + for (int y = 0; y < VERT_NODES; y++) { + for (int x = 0; x < HORZ_NODES; x++) { + CapeNode node = nodes[x + y * HORZ_NODES]; + + Vector3f delta = Vector3f.sub(node.position, avgPosition, null); + + if (delta.lengthSquared() > 5 * 5) { + Vector3f norm = delta.normalise(null); + node.position = Vector3f.add(avgPosition, norm, null); + } + } + } + + oldPlayerAngle = playerAngle; + + for (int y = 0; y < VERT_NODES; y++) { + for (int x = 0; x < HORZ_NODES; x++) { + nodes[x + y * HORZ_NODES].update(); + } + } + int updates = 50; + for (int i = 0; i < updates; i++) { + for (int y = 0; y < VERT_NODES; y++) { + for (int x = 0; x < HORZ_NODES; x++) { + nodes[x + y * HORZ_NODES].resolveAll(2 + 1f * y / VERT_NODES, false); + } + } + } + } + + private int ssbo = -1; + + private void generateSSBO() { + ssbo = GL15.glGenBuffers(); + loadSBBO(); + } + + private void loadSBBO() { + FloatBuffer buff = BufferUtils.createFloatBuffer(CapeNode.FLOAT_NUM * HORZ_NODES * VERT_NODES); + for (int y = 0; y < VERT_NODES; y++) { + for (int x = 0; x < HORZ_NODES; x++) { + nodes[x + y * HORZ_NODES].loadIntoBuffer(buff); + } + } + buff.flip(); + + GL15.glBindBuffer(GL43.GL_SHADER_STORAGE_BUFFER, ssbo); + GL15.glBufferData(GL43.GL_SHADER_STORAGE_BUFFER, buff, GL15.GL_DYNAMIC_DRAW); + GL15.glBindBuffer(GL43.GL_SHADER_STORAGE_BUFFER, 0); + } + + private void resolveAllCompute() { + if (ssbo == -1) { + generateSSBO(); + } + loadSBBO(); + + int program = ShaderManager.getInstance().getShader("node"); + + int block_index = GL43.glGetProgramResourceIndex(program, GL43.GL_SHADER_STORAGE_BLOCK, "nodes_buffer"); + int ssbo_binding_point_index = 0; + GL43.glShaderStorageBlockBinding(program, block_index, ssbo_binding_point_index); + int binding_point_index = 0; + GL30.glBindBufferBase(GL43.GL_SHADER_STORAGE_BUFFER, binding_point_index, ssbo); + + GL20.glUseProgram(program); + + for (int i = 0; i < 30; i++) { + GL43.glDispatchCompute(VERT_NODES, 1, 1); + GL42.glMemoryBarrier(GL43.GL_SHADER_STORAGE_BARRIER_BIT); + } + + GL20.glUseProgram(0); + + FloatBuffer buff = BufferUtils.createFloatBuffer(CapeNode.FLOAT_NUM * HORZ_NODES * VERT_NODES); + + GL15.glBindBuffer(GL43.GL_SHADER_STORAGE_BUFFER, ssbo); + GL15.glGetBufferSubData(GL43.GL_SHADER_STORAGE_BUFFER, 0, buff); + GL15.glBindBuffer(GL43.GL_SHADER_STORAGE_BUFFER, 0); + + for (int y = 0; y < VERT_NODES; y++) { + for (int x = 0; x < HORZ_NODES; x++) { + nodes[x + y * HORZ_NODES].readFromBuffer(buff); + } + } + } + + private Vector3f avgRenderPosition() { + Vector3f accum = new Vector3f(); + int num = 0; + for (int y = 0; y < VERT_NODES; y++) { + for (int x = 0; x < HORZ_NODES; x++) { + CapeNode node = nodes[x + y * HORZ_NODES]; + Vector3f.add(accum, node.renderPosition, accum); + num++; + } + } + if (num != 0) { + accum.scale(1f / num); + } + return accum; + } + + private Vector3f avgNormal() { + Vector3f accum = new Vector3f(); + int num = 0; + for (int y = 0; y < VERT_NODES; y++) { + for (int x = 0; x < HORZ_NODES; x++) { + CapeNode node = nodes[x + y * HORZ_NODES]; + Vector3f.add(accum, node.normal(), accum); + num++; + } + } + if (num != 0) { + accum.scale(1f / num); + } + return accum; + } + + private Vector3f avgFixedRenderPosition() { + Vector3f accum = new Vector3f(); + int numFixed = 0; + for (int y = 0; y < VERT_NODES; y++) { + for (int x = 0; x < HORZ_NODES; x++) { + CapeNode node = nodes[x + y * HORZ_NODES]; + if (node.fixed) { + Vector3f.add(accum, node.renderPosition, accum); + numFixed++; + } + } + } + if (numFixed != 0) { + accum.scale(1f / numFixed); + } + return accum; + } + + private Vector3f avgFixedPosition() { + Vector3f accum = new Vector3f(); + int numFixed = 0; + for (int y = 0; y < VERT_NODES; y++) { + for (int x = 0; x < HORZ_NODES; x++) { + CapeNode node = nodes[x + y * HORZ_NODES]; + if (node.fixed) { + Vector3f.add(accum, node.position, accum); + numFixed++; + } + } + } + if (numFixed != 0) { + accum.scale(1f / numFixed); + } + return accum; + } + + private void renderBackAndDoFrontStencil() { + for (int y = 0; y < VERT_NODES; y++) { + for (int x = 0; x < HORZ_NODES; x++) { + nodes[x + y * HORZ_NODES].renderNode(CapeNode.DRAW_MASK_BACK | CapeNode.DRAW_MASK_SIDES); + } + } + + if (!Minecraft.getMinecraft().getFramebuffer().isStencilEnabled()) + Minecraft.getMinecraft().getFramebuffer().enableStencil(); + + GL11.glEnable(GL11.GL_STENCIL_TEST); + GL11.glStencilFunc(GL11.GL_ALWAYS, 1, 0xFF); + GL11.glStencilOp(GL11.GL_ZERO, GL11.GL_ZERO, GL11.GL_REPLACE); + GL11.glStencilMask(0xFF); + GL11.glClear(GL11.GL_STENCIL_BUFFER_BIT); + GlStateManager.enableDepth(); + + GL11.glColorMask(false, false, false, false); + for (int y = 0; y < VERT_NODES; y++) { + for (int x = 0; x < HORZ_NODES; x++) { + nodes[x + y * HORZ_NODES].renderNode(CapeNode.DRAW_MASK_FRONT); + } + } + GL11.glColorMask(true, true, true, true); + + // Only pass stencil test if equal to 1 + GL11.glStencilMask(0x00); + GL11.glStencilFunc(GL11.GL_EQUAL, 1, 0xFF); + } + + private Vector3f getPoint(Vector3f point, Vector3f... vectors) { + Vector3f res = new Vector3f(point); + for (Vector3f vec : vectors) Vector3f.add(res, vec, res); + return res; + } + + private static void renderVBO(WorldRenderer worldRenderer) { + if (worldRenderer != null && worldRenderer.getVertexCount() > 0) { + VertexFormat vertexformat = worldRenderer.getVertexFormat(); + int stride = vertexformat.getNextOffset(); + ByteBuffer bytebuffer = worldRenderer.getByteBuffer(); + List list = vertexformat.getElements(); + + for (int index = 0; index < list.size(); index++) { + VertexFormatElement vertexformatelement = list.get(index); + vertexformatelement.getUsage().preDraw(vertexformat, index, stride, bytebuffer); + } + + GL11.glDrawArrays(worldRenderer.getDrawMode(), 0, worldRenderer.getVertexCount()); + + for (int index = 0; index < list.size(); index++) { + VertexFormatElement vertexformatelement = list.get(index); + vertexformatelement.getUsage().postDraw(vertexformat, index, stride, bytebuffer); + } + } + } + + private static WorldRenderer sphereVBO = null; + + private void renderNodes() { + if (capeName.equalsIgnoreCase("planets")) { + renderBackAndDoFrontStencil(); + + Vector3f pointNorm = avgNormal(); + Vector3f capeAvgPos = avgRenderPosition(); + + pointNorm.scale(0.5f / pointNorm.length()); + pointNorm.scale(1 - pointNorm.y / 1.3f); + Vector3f point = Vector3f.sub(capeAvgPos, pointNorm, null); + + if (sphereVBO == null || Keyboard.isKeyDown(Keyboard.KEY_K)) { + if (sphereVBO != null) sphereVBO.reset(); + + int arcSegments = 24; + int rotationSegments = 24; + double arcAngleDelta = Math.PI / (arcSegments - 1); + + float xScale = 0.95f; + + double diameterUnitArcLen = 0; + + double arcAngle = 0; + for (int i = 0; i < arcSegments; i++) { + diameterUnitArcLen += Math.sin(arcAngle); + arcAngle += arcAngleDelta; + } + double arcLength = 2f / diameterUnitArcLen; + + List> arcs = new ArrayList<>(); + for (int angleI = 0; angleI < rotationSegments; angleI++) { + double angle = Math.PI * 2 * angleI / rotationSegments; + + List arc = new ArrayList<>(); + + Vector3f arcPos = new Vector3f(0, 0, -1); + + arc.add(arcPos); + + arcAngle = 0; + for (int segmentI = 0; segmentI < arcSegments; segmentI++) { + + double deltaZ = Math.sin(arcAngle) * arcLength; + double deltaY = Math.cos(arcAngle) * Math.cos(angle) * arcLength; + double deltaX = Math.cos(arcAngle) * Math.sin(angle) * arcLength * xScale; + + arcPos = new Vector3f(arcPos); + arcPos.z += deltaZ; + arcPos.y += deltaY; + arcPos.x += deltaX; + arcPos.normalise(); + arc.add(arcPos); + + arcAngle += arcAngleDelta; + } + + arcs.add(arc); + } + + sphereVBO = new WorldRenderer(8 * 4 * rotationSegments * arcSegments); + sphereVBO.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_NORMAL); + + double maxXYRad = 0; + for (int angleI = 0; angleI < rotationSegments; angleI++) { + for (int segmentI = 0; segmentI <= arcSegments; segmentI++) { + List thisArc = arcs.get(angleI); + Vector3f point1 = thisArc.get(segmentI); + double rad = Math.sqrt(point1.x * point1.x + point1.y * point1.y); + maxXYRad = Math.max(maxXYRad, rad); + } + } + + for (int angleI = 0; angleI < rotationSegments; angleI++) { + + int nextAngleI = angleI + 1; + if (angleI == rotationSegments - 1) { + nextAngleI = 0; + } + + float v = 0.5f * (angleI) / (rotationSegments); + float v2 = 0.5f * (angleI + 1) / (rotationSegments); + //if(v2 == 0) v2 = 0.5f; + + List thisArc = arcs.get(angleI); + List nextArc = arcs.get(nextAngleI); + + for (int segmentI = 1; segmentI <= arcSegments; segmentI++) { + Vector3f point1 = thisArc.get(segmentI); + Vector3f point2 = thisArc.get(segmentI - 1); + Vector3f point3 = nextArc.get(segmentI - 1); + Vector3f point4 = nextArc.get(segmentI); + + double u1 = 0.5f * segmentI / arcSegments; + double u2 = 0.5f * (segmentI - 1) / arcSegments; + + sphereVBO.pos(point4.x, point4.y, point4.z) + .tex(u1, v2).normal(-point4.x, -point4.y, -point4.z).endVertex(); + sphereVBO.pos(point3.x, point3.y, point3.z) + .tex(u2, v2).normal(-point3.x, -point3.y, -point3.z).endVertex(); + sphereVBO.pos(point2.x, point2.y, point2.z) + .tex(u2, v).normal(-point2.x, -point2.y, -point2.z).endVertex(); + sphereVBO.pos(point1.x, point1.y, point1.z) + .tex(u1, v).normal(-point1.x, -point1.y, -point1.z).endVertex(); + } + } + } + + String shaderId = "capes/" + shaderName + "/" + shaderName; + double mercuryAngle = Math.PI * 2 * ((System.currentTimeMillis() - startTime) / 10000f % 1); + double mercuryX = Math.sin(mercuryAngle) * 0.3; + double mercuryZ = Math.cos(mercuryAngle) * 0.3; + + double earthAngle = Math.PI * 2 * ((System.currentTimeMillis() - startTime) / 30000f % 1); + double earthSlant = Math.PI * 0.1; + double earthX = Math.sin(earthAngle) * Math.cos(earthSlant) * 0.6; + double earthY = Math.sin(earthAngle) * Math.sin(earthSlant) * 0.6; + double earthZ = Math.cos(earthAngle) * Math.cos(earthSlant) * 0.6; + + float sunDist = Vector3f.sub(point, capeAvgPos, null).lengthSquared(); + float mercuryDist = Vector3f.sub(new Vector3f(point.x + (float) mercuryX, point.y, point.z + (float) mercuryZ), + capeAvgPos, null + ).lengthSquared(); + float earthDist = Vector3f.sub(new Vector3f( + point.x + (float) earthX, + point.y + (float) earthY, + point.z + (float) earthZ + ), + capeAvgPos, null + ).lengthSquared(); + + double jupiterAngle = Math.PI * 2 * ((System.currentTimeMillis() - startTime) / 200000f % 1); + double jupiterSlant = Math.PI * -0.08; + double jupiterX = Math.sin(jupiterAngle) * Math.cos(jupiterSlant) * 1.5; + double jupiterY = Math.sin(jupiterAngle) * Math.sin(jupiterSlant) * 1.5; + double jupiterZ = Math.cos(jupiterAngle) * Math.cos(jupiterSlant) * 1.5; + float jupiterDist = Vector3f.sub(new Vector3f( + point.x + (float) jupiterX, + point.y + (float) jupiterY, + point.z + (float) jupiterZ + ), + capeAvgPos, null + ).lengthSquared(); + + double neptuneX = -Math.sin(earthAngle) * Math.cos(earthSlant); + double neptuneY = -Math.sin(earthAngle) * Math.sin(earthSlant); + double neptuneZ = -Math.cos(earthAngle) * Math.cos(earthSlant); + + float neptuneDist = Vector3f.sub(new Vector3f( + point.x + (float) neptuneX, + point.y + (float) neptuneY, + point.z + (float) neptuneZ + ), + capeAvgPos, null + ).lengthSquared(); + + TreeMap orbitals = new TreeMap<>(); + orbitals.put(sunDist, 0); + orbitals.put(earthDist, 1); + orbitals.put(mercuryDist, 2); + + double delta = Minecraft.getMinecraft().getRenderViewEntity().getRotationYawHead() % 360; + while (delta < 0) delta += 360; + + double jupDelta = (delta + Math.toDegrees(jupiterAngle)) % 360; + while (jupDelta < 0) jupDelta += 360; + if (jupDelta > 250 || jupDelta < 110) orbitals.put(jupiterDist, 3); + + double nepDelta = (delta + Math.toDegrees(-earthAngle)) % 360; + while (nepDelta < 0) nepDelta += 360; + if (nepDelta > 250 || nepDelta < 110) orbitals.put(neptuneDist, 4); + + GlStateManager.disableDepth(); + GlStateManager.enableCull(); + + for (int planetId : orbitals.descendingMap().values()) { + GlStateManager.pushMatrix(); + switch (planetId) { + case 0: { + GlStateManager.translate(point.x, point.y, point.z); + GlStateManager.scale(0.2f, 0.2f, 0.2f); + break; + } + case 1: { + Vector3f sunVec = new Vector3f((float) earthX, (float) earthY, (float) earthZ); + ShaderManager.getInstance().loadData(shaderId, "sunVec", sunVec); + GlStateManager.translate(point.x + earthX, point.y + earthY, point.z + earthZ); + GlStateManager.scale(0.1f, 0.1f, 0.1f); + break; + } + case 2: { + Vector3f sunVec = new Vector3f((float) mercuryX, 0, (float) mercuryZ); + ShaderManager.getInstance().loadData(shaderId, "sunVec", sunVec); + GlStateManager.translate(point.x + mercuryX, point.y, point.z + mercuryZ); + GlStateManager.scale(0.05f, 0.05f, 0.05f); + break; + } + case 3: { + Vector3f sunVec = new Vector3f((float) jupiterX, (float) jupiterY, (float) jupiterZ); + ShaderManager.getInstance().loadData(shaderId, "sunVec", sunVec); + GlStateManager.translate(point.x + jupiterX, point.y + jupiterY, point.z + jupiterZ); + GlStateManager.scale(0.3f, 0.3f, 0.3f); + break; + } + case 4: { + Vector3f sunVec = new Vector3f((float) neptuneX, (float) neptuneY, (float) neptuneZ); + ShaderManager.getInstance().loadData(shaderId, "sunVec", sunVec); + GlStateManager.translate(point.x + neptuneX, point.y + neptuneY, point.z + neptuneZ); + GlStateManager.scale(0.15f, 0.15f, 0.15f); + break; + } + } + ShaderManager.getInstance().loadData(shaderId, "planetType", planetId); + renderVBO(sphereVBO); + GlStateManager.popMatrix(); + } + + GlStateManager.disableCull(); + GlStateManager.enableDepth(); + + GL11.glDisable(GL11.GL_STENCIL_TEST); + } else if (capeName.equalsIgnoreCase("parallax")) { + renderBackAndDoFrontStencil(); + + Vector3f pointNorm = avgNormal(); + pointNorm.scale(-0.2f / pointNorm.length()); + Vector3f negPointNorm = new Vector3f(pointNorm); + negPointNorm.scale(-1); + //pointNorm.scale(1 - pointNorm.y/1.3f); + Vector3f point = Vector3f.add(avgRenderPosition(), pointNorm, null); + Vector3f fixedPoint = Vector3f.add(avgFixedRenderPosition(), pointNorm, null); + + Vector3f up = Vector3f.sub(fixedPoint, point, null); + float halfUp = up.length(); + + Vector3f down = new Vector3f(up); + down.scale(-1); + + Vector3f left = Vector3f.cross(up, pointNorm, null); + left.scale(halfUp * 522f / 341f / left.length()); + Vector3f right = new Vector3f(left); + right.scale(-1); + + Vector3f point1 = getPoint(point, left); + Vector3f point2 = getPoint(point, left, down, down); + Vector3f point3 = getPoint(point, right, down, down); + Vector3f point4 = getPoint(point, right); + + Vector3f point2Edge = getPoint(point2, negPointNorm, negPointNorm); + Vector3f point3Edge = getPoint(point3, negPointNorm, negPointNorm); + + GlStateManager.disableDepth(); + GlStateManager.disableCull(); + + GlStateManager.color(1, 1, 1, 1); + + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer worldrenderer = tessellator.getWorldRenderer(); + worldrenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); + + worldrenderer.pos(point1.x, point1.y, point1.z) + .tex(0, 943 / 1024f).endVertex(); + worldrenderer.pos(point2.x, point2.y, point2.z) + .tex(280 / 1024f, 943 / 1024f).endVertex(); + worldrenderer.pos(point3.x, point3.y, point3.z) + .tex(280 / 1024f, 421 / 1024f).endVertex(); + worldrenderer.pos(point4.x, point4.y, point4.z) + .tex(0, 421 / 1024f).endVertex(); + + tessellator.draw(); + + worldrenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); + + worldrenderer.pos(point2.x, point2.y, point2.z) + .tex(280 / 1024f, 943 / 1024f).endVertex(); + worldrenderer.pos(point2Edge.x, point2Edge.y, point2Edge.z) + .tex(341 / 1024f, 943 / 1024f).endVertex(); + worldrenderer.pos(point3Edge.x, point3Edge.y, point3Edge.z) + .tex(341 / 1024f, 421 / 1024f).endVertex(); + worldrenderer.pos(point3.x, point3.y, point3.z) + .tex(280 / 1024f, 421 / 1024f).endVertex(); + + tessellator.draw(); + + GlStateManager.disableCull(); + GlStateManager.enableDepth(); + + GL11.glDisable(GL11.GL_STENCIL_TEST); + } else if (capeName.equalsIgnoreCase("tunnel")) { + renderBackAndDoFrontStencil(); + + Vector3f pointNorm = avgNormal(); + + pointNorm.scale(0.7f / pointNorm.length()); + pointNorm.scale(1 - pointNorm.y / 1.3f); + Vector3f point = Vector3f.sub(avgRenderPosition(), pointNorm, null); + + List edgeNodes = new ArrayList<>(); + List edgeCoords = new ArrayList<>(); + + //Left edge + for (int y = 0; y < VERT_NODES; y++) { + edgeNodes.add(nodes[y * HORZ_NODES]); + edgeCoords.add(new Vector2f(0, (float) y / (VERT_NODES - 1))); + } + edgeNodes.add(null); + edgeCoords.add(null); + //Bottom edge + int bottomIndex = VERT_NODES - 1; + int botSize = HORZ_NODES; + for (int x = 0; x < botSize; x++) { + edgeNodes.add(getNode(x, bottomIndex)); + edgeCoords.add(new Vector2f((float) x / (botSize - 1), 1)); + } + edgeNodes.add(null); + edgeCoords.add(null); + //Right edge + for (int y = VERT_NODES - 1; y >= 0; y--) { + edgeNodes.add(getNode(HORZ_NODES - 1, y)); + edgeCoords.add(new Vector2f(1, (float) y / VERT_NODES)); + } + edgeNodes.add(null); + edgeCoords.add(null); + //Top edge + int topSize = HORZ_NODES; + for (int x = topSize - 1; x >= 0; x--) { + edgeNodes.add(getNode(x, 0)); + edgeCoords.add(new Vector2f((float) x / (topSize - 1), 0)); + } + + GlStateManager.disableDepth(); + GlStateManager.enableCull(); + CapeNode last = null; + for (int i = 0; i < edgeNodes.size(); i++) { + CapeNode node = edgeNodes.get(i); + if (last != null && node != null) { + Vector2f lastCoord = edgeCoords.get(i - 1); + Vector2f coord = edgeCoords.get(i); + + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer worldrenderer = tessellator.getWorldRenderer(); + worldrenderer.begin(GL11.GL_TRIANGLES, DefaultVertexFormats.POSITION_TEX_NORMAL); + + Vector3f lastNodeNorm = last.normal(); + worldrenderer.pos( + last.renderPosition.x + lastNodeNorm.x * 0.05f, + last.renderPosition.y + lastNodeNorm.y * 0.05f, + last.renderPosition.z + lastNodeNorm.z * 0.05f + ) + .tex(lastCoord.x * 300f / 1024f, lastCoord.y * 420f / 1024f) + .normal(-lastNodeNorm.x, -lastNodeNorm.y, -lastNodeNorm.z).endVertex(); + + Vector3f nodeNorm = node.normal(); + worldrenderer.pos( + node.renderPosition.x + nodeNorm.x * 0.05f, + node.renderPosition.y + nodeNorm.y * 0.05f, + node.renderPosition.z + nodeNorm.z * 0.05f + ) + .tex(coord.x * 300f / 1024f, coord.y * 420f / 1024f) + .normal(-nodeNorm.x, -nodeNorm.y, -nodeNorm.z).endVertex(); + + worldrenderer.pos(point.x, point.y, point.z) + .tex(150f / 1024f, 210f / 1024f) + .normal(-pointNorm.x, -pointNorm.y, -pointNorm.z).endVertex(); + + tessellator.draw(); + } + last = node; + } + GlStateManager.disableCull(); + GlStateManager.enableDepth(); + + GL11.glDisable(GL11.GL_STENCIL_TEST); + } else { + for (int y = 0; y < VERT_NODES; y++) { + for (int x = 0; x < HORZ_NODES; x++) { + nodes[x + y * HORZ_NODES].renderNode(); + } + } + } + } + + private void renderCape(EntityPlayer player, float partialRenderTick) { + ensureCapeNodesCreated(player); + + Vector3f avgPositionFixedBefore = avgFixedRenderPosition(); + updateFixedCapeNodesPartial(player, partialRenderTick); + Vector3f avgPositionFixed = avgFixedRenderPosition(); + Vector3f delta = Vector3f.sub(avgPositionFixed, avgPositionFixedBefore, null); + + if (delta.lengthSquared() > 9) { + updateFixedCapeNodes(player); + + for (int y = 0; y < VERT_NODES; y++) { + for (int x = 0; x < HORZ_NODES; x++) { + CapeNode node = nodes[x + y * HORZ_NODES]; + if (!node.fixed) { + Vector3f.add(node.renderPosition, delta, node.renderPosition); + node.position.set(node.renderPosition); + node.lastPosition.set(node.renderPosition); + } else { + node.lastPosition.set(node.position); + } + } + } + + renderNodes(); + return; + } + + for (int y = 0; y < VERT_NODES; y++) { + for (int x = 0; x < HORZ_NODES; x++) { + CapeNode node = nodes[x + y * HORZ_NODES]; + + node.resetNormal(); + + if (node.fixed) continue; + + Vector3f newPosition = new Vector3f(); + newPosition.x = node.lastPosition.x + (node.position.x - node.lastPosition.x) * partialRenderTick; + newPosition.y = node.lastPosition.y + (node.position.y - node.lastPosition.y) * partialRenderTick; + newPosition.z = node.lastPosition.z + (node.position.z - node.lastPosition.z) * partialRenderTick; + + int length = node.oldRenderPosition.length; + + int fps = Minecraft.getDebugFPS(); + if (fps < 50) { + length = 2; + } else if (fps < 100) { + length = 2 + (int) ((fps - 50) / 50f * 3); + } + + if (node.oldRenderPosition[length - 1] == null) { + Arrays.fill(node.oldRenderPosition, Vector3f.sub(newPosition, avgPositionFixed, null)); + node.renderPosition = newPosition; + } else { + Vector3f accum = new Vector3f(); + for (int i = 0; i < length; i++) { + Vector3f.add(accum, node.oldRenderPosition[i], accum); + Vector3f.add(accum, avgPositionFixed, accum); + } + accum.scale(1 / (float) (length)); + + float blendFactor = 0.5f + 0.3f * y / (float) (VERT_NODES - 1); //0.5/0.5 -> 0.8/0.2 //0-1 + accum.scale(blendFactor); + newPosition.scale(1 - blendFactor); + Vector3f.add(accum, newPosition, accum); + node.renderPosition = accum; + } + + if (!Minecraft.getMinecraft().isGamePaused()) { + for (int i = node.oldRenderPosition.length - 1; i >= 0; i--) { + if (i > 0) { + node.oldRenderPosition[i] = node.oldRenderPosition[i - 1]; + } else { + node.oldRenderPosition[i] = Vector3f.sub(node.renderPosition, avgPositionFixed, null); + } + } + } + } + } + renderNodes(); + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/ShaderManager.java b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/ShaderManager.java index a750f59777..4e934e10b6 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/ShaderManager.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/ShaderManager.java @@ -15,143 +15,144 @@ import java.util.HashMap; public class ShaderManager { - - private ResourceLocation shaderLocation = new ResourceLocation("notenoughupdates:shaders"); - private HashMap shaderMap = new HashMap<>(); - - private static final ShaderManager INSTANCE = new ShaderManager(); - - public static ShaderManager getInstance() { - return INSTANCE; - } - - public class Shader { - public final int program; - - public Shader(int program) { - this.program = program; - } - } - - public int getShader(String name) { - if(!shaderMap.containsKey(name)) { - reloadShader(name); - } - return shaderMap.get(name).program; - } - - public int loadShader(String name) { - if(!shaderMap.containsKey(name)) { - reloadShader(name); - } - GL20.glUseProgram(shaderMap.get(name).program); - return shaderMap.get(name).program; - } - - public void loadData(String name, String var, Object value) { - int location = GL20.glGetUniformLocation(shaderMap.get(name).program, var); - - if(value instanceof Integer) { - GL20.glUniform1i(location, (Integer) value); - } else if(value instanceof Float) { - GL20.glUniform1f(location, (Float) value); - } else if(value instanceof Vector2f) { - Vector2f vec = (Vector2f) value; - GL20.glUniform2f(location, vec.x, vec.y); - } else if(value instanceof Vector3f) { - Vector3f vec = (Vector3f) value; - GL20.glUniform3f(location, vec.x, vec.y, vec.z); - } else if(value instanceof Vector4f) { - Vector4f vec = (Vector4f) value; - GL20.glUniform4f(location, vec.x, vec.y, vec.z, vec.w); - } else { - throw new UnsupportedOperationException("Failed to load data into shader: Unsupported data type."); - } - } - - private void reloadShader(String name) { - int vertex = -1; - String sourceVert = getShaderSource(name, GL20.GL_VERTEX_SHADER); - if(!sourceVert.isEmpty()) { - vertex = GL20.glCreateShader(GL20.GL_VERTEX_SHADER); - GL20.glShaderSource(vertex, sourceVert); - GL20.glCompileShader(vertex); - - if (GL20.glGetShaderi(vertex, 35713) == 0) { - System.err.println(GL20.glGetShaderInfoLog(vertex, 100)); - } - } - - int fragment = -1; - String sourceFrag = getShaderSource(name, GL20.GL_FRAGMENT_SHADER); - if(!sourceFrag.isEmpty()) { - fragment = GL20.glCreateShader(GL20.GL_FRAGMENT_SHADER); - GL20.glShaderSource(fragment, sourceFrag); - GL20.glCompileShader(fragment); - - if (GL20.glGetShaderi(fragment, 35713) == 0) { - System.err.println(GL20.glGetShaderInfoLog(fragment, 100)); - } - } - - int compute = -1; - String sourceCompute = getShaderSource(name, GL43.GL_COMPUTE_SHADER); - if(!sourceCompute.isEmpty()) { - compute = GL20.glCreateShader(GL43.GL_COMPUTE_SHADER); - GL20.glShaderSource(compute, sourceCompute); - GL20.glCompileShader(compute); - - if (GL20.glGetShaderi(compute, 35713) == 0) { - System.err.println(GL20.glGetShaderInfoLog(compute, 100)); - } - } - - int program = GL20.glCreateProgram(); - if(vertex != -1) GL20.glAttachShader(program, vertex); - if(fragment != -1) GL20.glAttachShader(program, fragment); - if(compute != -1) GL20.glAttachShader(program, compute); - - GL20.glLinkProgram(program); - - if(vertex != -1) GL20.glDeleteShader(vertex); - if(fragment != -1) GL20.glDeleteShader(fragment); - if(compute != -1) GL20.glDeleteShader(compute); - - if (GL20.glGetProgrami(program, 35714) == 0) { - System.err.println(GL20.glGetProgramInfoLog(program, 100)); - } - GL20.glValidateProgram(program); - if (GL20.glGetProgrami(program, 35715) == 0) { - System.err.println(GL20.glGetProgramInfoLog(program, 100)); - } - - shaderMap.put(name, new Shader(program)); - } - - public String getShaderSource(String name, int type) { - String ext = ""; - if(type == GL20.GL_VERTEX_SHADER) { - ext = ".vert"; - } else if(type == GL20.GL_FRAGMENT_SHADER) { - ext = ".frag"; - } else if(type == GL43.GL_COMPUTE_SHADER) { - ext = ".compute"; - } else { - return ""; - } - ResourceLocation location = new ResourceLocation(shaderLocation.getResourceDomain(), - shaderLocation.getResourcePath()+"/"+name+ext); - try(InputStream is = Minecraft.getMinecraft().getResourceManager().getResource(location).getInputStream()) { - StringBuilder source = new StringBuilder(); - BufferedReader br = new BufferedReader(new InputStreamReader(is)); - - String line; - while((line = br.readLine()) != null) { - source.append(line).append("\n"); - } - return source.toString(); - } catch(IOException e) { - } - return ""; - } + private final ResourceLocation shaderLocation = new ResourceLocation("notenoughupdates:shaders"); + private final HashMap shaderMap = new HashMap<>(); + + private static final ShaderManager INSTANCE = new ShaderManager(); + + public static ShaderManager getInstance() { + return INSTANCE; + } + + public static class Shader { + public final int program; + + public Shader(int program) { + this.program = program; + } + } + + public int getShader(String name) { + if (!shaderMap.containsKey(name)) { + reloadShader(name); + } + return shaderMap.get(name).program; + } + + public int loadShader(String name) { + if (!shaderMap.containsKey(name)) { + reloadShader(name); + } + GL20.glUseProgram(shaderMap.get(name).program); + return shaderMap.get(name).program; + } + + public void loadData(String name, String var, Object value) { + int location = GL20.glGetUniformLocation(shaderMap.get(name).program, var); + + if (value instanceof Integer) { + GL20.glUniform1i(location, (Integer) value); + } else if (value instanceof Float) { + GL20.glUniform1f(location, (Float) value); + } else if (value instanceof Vector2f) { + Vector2f vec = (Vector2f) value; + GL20.glUniform2f(location, vec.x, vec.y); + } else if (value instanceof Vector3f) { + Vector3f vec = (Vector3f) value; + GL20.glUniform3f(location, vec.x, vec.y, vec.z); + } else if (value instanceof Vector4f) { + Vector4f vec = (Vector4f) value; + GL20.glUniform4f(location, vec.x, vec.y, vec.z, vec.w); + } else { + throw new UnsupportedOperationException("Failed to load data into shader: Unsupported data type."); + } + } + + private void reloadShader(String name) { + int vertex = -1; + String sourceVert = getShaderSource(name, GL20.GL_VERTEX_SHADER); + if (!sourceVert.isEmpty()) { + vertex = GL20.glCreateShader(GL20.GL_VERTEX_SHADER); + GL20.glShaderSource(vertex, sourceVert); + GL20.glCompileShader(vertex); + + if (GL20.glGetShaderi(vertex, 35713) == 0) { + System.err.println(GL20.glGetShaderInfoLog(vertex, 100)); + } + } + + int fragment = -1; + String sourceFrag = getShaderSource(name, GL20.GL_FRAGMENT_SHADER); + if (!sourceFrag.isEmpty()) { + fragment = GL20.glCreateShader(GL20.GL_FRAGMENT_SHADER); + GL20.glShaderSource(fragment, sourceFrag); + GL20.glCompileShader(fragment); + + if (GL20.glGetShaderi(fragment, 35713) == 0) { + System.err.println(GL20.glGetShaderInfoLog(fragment, 100)); + } + } + + int compute = -1; + String sourceCompute = getShaderSource(name, GL43.GL_COMPUTE_SHADER); + if (!sourceCompute.isEmpty()) { + compute = GL20.glCreateShader(GL43.GL_COMPUTE_SHADER); + GL20.glShaderSource(compute, sourceCompute); + GL20.glCompileShader(compute); + + if (GL20.glGetShaderi(compute, 35713) == 0) { + System.err.println(GL20.glGetShaderInfoLog(compute, 100)); + } + } + + int program = GL20.glCreateProgram(); + if (vertex != -1) GL20.glAttachShader(program, vertex); + if (fragment != -1) GL20.glAttachShader(program, fragment); + if (compute != -1) GL20.glAttachShader(program, compute); + + GL20.glLinkProgram(program); + + if (vertex != -1) GL20.glDeleteShader(vertex); + if (fragment != -1) GL20.glDeleteShader(fragment); + if (compute != -1) GL20.glDeleteShader(compute); + + if (GL20.glGetProgrami(program, 35714) == 0) { + System.err.println(GL20.glGetProgramInfoLog(program, 100)); + } + GL20.glValidateProgram(program); + if (GL20.glGetProgrami(program, 35715) == 0) { + System.err.println(GL20.glGetProgramInfoLog(program, 100)); + } + + shaderMap.put(name, new Shader(program)); + } + + public String getShaderSource(String name, int type) { + String ext = ""; + if (type == GL20.GL_VERTEX_SHADER) { + ext = ".vert"; + } else if (type == GL20.GL_FRAGMENT_SHADER) { + ext = ".frag"; + } else if (type == GL43.GL_COMPUTE_SHADER) { + ext = ".compute"; + } else { + return ""; + } + ResourceLocation location = new ResourceLocation( + shaderLocation.getResourceDomain(), + shaderLocation.getResourcePath() + "/" + name + ext + ); + try (InputStream is = Minecraft.getMinecraft().getResourceManager().getResource(location).getInputStream()) { + StringBuilder source = new StringBuilder(); + BufferedReader br = new BufferedReader(new InputStreamReader(is)); + + String line; + while ((line = br.readLine()) != null) { + source.append(line).append("\n"); + } + return source.toString(); + } catch (IOException ignored) { + } + return ""; + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonBlocks.java b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonBlocks.java index 890155e854..0e7c59c724 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonBlocks.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonBlocks.java @@ -7,12 +7,17 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.ScaledResolution; -import net.minecraft.client.renderer.*; -import net.minecraft.client.renderer.texture.*; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.renderer.texture.TextureMap; import net.minecraft.client.shader.Framebuffer; import net.minecraft.util.ResourceLocation; import org.lwjgl.BufferUtils; -import org.lwjgl.opengl.*; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL12; +import org.lwjgl.opengl.GL14; +import org.lwjgl.opengl.GL30; import java.nio.FloatBuffer; import java.util.HashMap; @@ -20,237 +25,273 @@ import java.util.Map; public class DungeonBlocks { - - private static Framebuffer framebufferBlocksTo = null; - private static Framebuffer framebufferBlocksFrom = null; - - private static HashMap framebuffersDynamicTo = new HashMap<>(); - public static HashMap framebuffersDynamicFrom = new HashMap<>(); - private static HashSet dynamicUpdated = new HashSet<>(); - - private static FloatBuffer projectionMatrixOld = BufferUtils.createFloatBuffer(16); - private static FloatBuffer modelviewMatrixOld = BufferUtils.createFloatBuffer(16); - - public static boolean textureExists() { - return framebufferBlocksFrom != null && isOverriding(); - } - - public static void bindTextureIfExists() { - if(textureExists()) { - framebufferBlocksFrom.bindFramebufferTexture(); - } - } - - public static boolean isOverriding() { - return OpenGlHelper.isFramebufferEnabled() && NotEnoughUpdates.INSTANCE.config.dungeons.enableDungBlockOverlay && - (NotEnoughUpdates.INSTANCE.config.dungeons.dungeonBlocksEverywhere || - (SBInfo.getInstance().getLocation() != null && SBInfo.getInstance().getLocation().equals("dungeon"))); - } - - public static boolean bindModifiedTexture(ResourceLocation location, int colour) { - if(!isOverriding()) { - return false; - } - - if(Utils.disableCustomDungColours) { - return false; - } - - if(((colour >> 24) & 0xFF) < 10) { - return false; - } - - String id = location.getResourceDomain()+":"+location.getResourcePath(); - if(dynamicUpdated.contains(id) && framebuffersDynamicFrom.containsKey(id)) { - framebuffersDynamicFrom.get(id).bindFramebufferTexture(); - return true; - } - - Minecraft.getMinecraft().getTextureManager().bindTexture(location); - int w = GL11.glGetTexLevelParameteri(GL11.GL_TEXTURE_2D, 0, GL11.GL_TEXTURE_WIDTH); - int h = GL11.glGetTexLevelParameteri(GL11.GL_TEXTURE_2D, 0, GL11.GL_TEXTURE_HEIGHT); - - Framebuffer to = checkFramebufferSizes(framebuffersDynamicTo.get(id), w, h); - dynamicUpdated.add(id); - - try { - GL11.glGetFloat(GL11.GL_PROJECTION_MATRIX, projectionMatrixOld); - GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, modelviewMatrixOld); - - GL11.glPushMatrix(); - - GlStateManager.matrixMode(GL11.GL_PROJECTION); - GlStateManager.loadIdentity(); - GlStateManager.ortho(0.0D, w, h, 0.0D, 1000.0D, 3000.0D); - GlStateManager.matrixMode(GL11.GL_MODELVIEW); - GlStateManager.loadIdentity(); - GlStateManager.translate(0.0F, 0.0F, -2000.0F); - - to.bindFramebuffer(true); - GlStateManager.clearColor(0, 1, 0, 1); - GlStateManager.clear(GL11.GL_COLOR_BUFFER_BIT); - - GlStateManager.disableBlend(); - GlStateManager.disableLighting(); - GlStateManager.disableFog(); - - Minecraft.getMinecraft().getTextureManager().bindTexture(location); - GlStateManager.color(1, 1, 1, 1); - Utils.drawTexturedRectNoBlend(0, 0, w, h, 0, 1, 1, 0, GL11.GL_LINEAR); - - GlStateManager.enableBlend(); - GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); - Utils.drawRectNoBlend(0, 0, w, h, colour); - - GL11.glPopMatrix(); - - to.bindFramebufferTexture(); - if (Minecraft.getMinecraft().gameSettings.mipmapLevels >= 0) { - GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL12.GL_TEXTURE_MAX_LEVEL, Minecraft.getMinecraft().gameSettings.mipmapLevels); - GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL12.GL_TEXTURE_MIN_LOD, 0.0F); - GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL12.GL_TEXTURE_MAX_LOD, (float)Minecraft.getMinecraft().gameSettings.mipmapLevels); - GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL14.GL_TEXTURE_LOD_BIAS, 0.0F); - GL30.glGenerateMipmap(GL11.GL_TEXTURE_2D); - } - - GlStateManager.matrixMode(GL11.GL_PROJECTION); - GL11.glLoadMatrix(projectionMatrixOld); - GlStateManager.matrixMode(GL11.GL_MODELVIEW); - GL11.glLoadMatrix(modelviewMatrixOld); - - Framebuffer from = checkFramebufferSizes(framebuffersDynamicFrom.get(id), w, h); - framebuffersDynamicFrom.put(id, to); - framebuffersDynamicTo.put(id, from); - - to.bindFramebufferTexture(); - - Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true); - GlStateManager.disableBlend(); - GlStateManager.enableLighting(); - return true; - } catch(Exception e) { - e.printStackTrace(); - } - Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true); - GlStateManager.disableBlend(); - GlStateManager.enableLighting(); - return false; - } - - private static HashMap dynamicPreloadMap = new HashMap<>(); - - static { - dynamicPreloadMap.put(new ResourceLocation("textures/entity/bat.png"), - NotEnoughUpdates.INSTANCE.config.dungeons.dungBatColour); - dynamicPreloadMap.put(new ResourceLocation("textures/entity/chest/normal.png"), - NotEnoughUpdates.INSTANCE.config.dungeons.dungChestColour); - dynamicPreloadMap.put(new ResourceLocation("textures/entity/chest/normal_double.png"), - NotEnoughUpdates.INSTANCE.config.dungeons.dungChestColour); - dynamicPreloadMap.put(new ResourceLocation("textures/entity/chest/trapped.png"), - NotEnoughUpdates.INSTANCE.config.dungeons.dungTrappedChestColour); - dynamicPreloadMap.put(new ResourceLocation("textures/entity/chest/trapped_double.png"), - NotEnoughUpdates.INSTANCE.config.dungeons.dungTrappedChestColour); - } - - public static void tick() { - if(!isOverriding() || Minecraft.getMinecraft().theWorld == null) { - return; - } - - dynamicUpdated.clear(); - - for(Map.Entry entry : dynamicPreloadMap.entrySet()) { - bindModifiedTexture(entry.getKey(), SpecialColour.specialToChromaRGB(entry.getValue())); - } - - Minecraft.getMinecraft().getTextureManager().bindTexture(TextureMap.locationBlocksTexture); - int w = GL11.glGetTexLevelParameteri(GL11.GL_TEXTURE_2D, 0, GL11.GL_TEXTURE_WIDTH); - int h = GL11.glGetTexLevelParameteri(GL11.GL_TEXTURE_2D, 0, GL11.GL_TEXTURE_HEIGHT); - - Framebuffer to = checkFramebufferSizes(framebufferBlocksTo, w, h); - - try { - GL11.glPushMatrix(); - - GlStateManager.matrixMode(5889); - GlStateManager.loadIdentity(); - GlStateManager.ortho(0.0D, w, h, 0.0D, 1000.0D, 3000.0D); - GlStateManager.matrixMode(5888); - GlStateManager.loadIdentity(); - GlStateManager.translate(0.0F, 0.0F, -2000.0F); - - to.bindFramebuffer(true); - GlStateManager.clear(GL11.GL_COLOR_BUFFER_BIT); - - GlStateManager.disableBlend(); - GlStateManager.disableLighting(); - GlStateManager.disableFog(); - - Minecraft.getMinecraft().getTextureManager().bindTexture(TextureMap.locationBlocksTexture); - GlStateManager.color(1, 1, 1, 1); - Utils.drawTexturedRectNoBlend(0, 0, w, h, 0, 1, 1, 0, GL11.GL_LINEAR); - - HashMap spriteMap = new HashMap<>(); - spriteMap.put(Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite("minecraft:blocks/stonebrick_cracked"), - SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.dungeons.dungCrackedColour)); - spriteMap.put(Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite("minecraft:blocks/dispenser_front_horizontal"), - SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.dungeons.dungDispenserColour)); - spriteMap.put(Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite("minecraft:blocks/lever"), - SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.dungeons.dungLeverColour)); - spriteMap.put(Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite("minecraft:blocks/trip_wire"), - SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.dungeons.dungTripWireColour)); - - for(Map.Entry entry : spriteMap.entrySet()) { - if(((entry.getValue() >> 24) & 0xFF) < 10) continue; - - TextureAtlasSprite tas = entry.getKey(); - Gui.drawRect((int)(w*tas.getMinU()), h-(int)(h*tas.getMaxV())-1, - (int)(w*tas.getMaxU())+1, h-(int)(h*tas.getMinV()), entry.getValue()); - } - - ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); - GlStateManager.matrixMode(5889); - GlStateManager.loadIdentity(); - GlStateManager.ortho(0.0D, scaledResolution.getScaledWidth_double(), scaledResolution.getScaledHeight_double(), - 0.0D, 1000.0D, 3000.0D); - GlStateManager.matrixMode(5888); - GlStateManager.loadIdentity(); - GlStateManager.translate(0.0F, 0.0F, -2000.0F); - - GL11.glPopMatrix(); - - to.bindFramebufferTexture(); - if (Minecraft.getMinecraft().gameSettings.mipmapLevels >= 0) { - GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL12.GL_TEXTURE_MAX_LEVEL, Minecraft.getMinecraft().gameSettings.mipmapLevels); - GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL12.GL_TEXTURE_MIN_LOD, 0.0F); - GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL12.GL_TEXTURE_MAX_LOD, (float)Minecraft.getMinecraft().gameSettings.mipmapLevels); - GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL14.GL_TEXTURE_LOD_BIAS, 0.0F); - GL30.glGenerateMipmap(GL11.GL_TEXTURE_2D); - } - - Framebuffer from = checkFramebufferSizes(framebufferBlocksFrom, w, h); - framebufferBlocksFrom = to; - framebufferBlocksTo = from; - } catch(Exception e) { - e.printStackTrace(); - } - Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true); - GlStateManager.enableBlend(); - } - - private static Framebuffer checkFramebufferSizes(Framebuffer framebuffer, int width, int height) { - if(framebuffer == null || framebuffer.framebufferWidth != width || framebuffer.framebufferHeight != height) { - if(framebuffer == null) { - framebuffer = new Framebuffer(width, height, false); - framebuffer.framebufferColor[0] = 1f; - framebuffer.framebufferColor[1] = 0f; - framebuffer.framebufferColor[2] = 0f; - framebuffer.framebufferColor[3] = 0; - } else { - framebuffer.createBindFramebuffer(width, height); - } - framebuffer.setFramebufferFilter(GL11.GL_NEAREST); - } - return framebuffer; - } + private static Framebuffer framebufferBlocksTo = null; + private static Framebuffer framebufferBlocksFrom = null; + + private static final HashMap framebuffersDynamicTo = new HashMap<>(); + public static HashMap framebuffersDynamicFrom = new HashMap<>(); + private static final HashSet dynamicUpdated = new HashSet<>(); + + private static final FloatBuffer projectionMatrixOld = BufferUtils.createFloatBuffer(16); + private static final FloatBuffer modelviewMatrixOld = BufferUtils.createFloatBuffer(16); + + public static boolean textureExists() { + return framebufferBlocksFrom != null && isOverriding(); + } + + public static void bindTextureIfExists() { + if (textureExists()) { + framebufferBlocksFrom.bindFramebufferTexture(); + } + } + + public static boolean isOverriding() { + return OpenGlHelper.isFramebufferEnabled() && NotEnoughUpdates.INSTANCE.config.dungeons.enableDungBlockOverlay && + (NotEnoughUpdates.INSTANCE.config.dungeons.dungeonBlocksEverywhere || + (SBInfo.getInstance().getLocation() != null && SBInfo.getInstance().getLocation().equals("dungeon"))); + } + + public static boolean bindModifiedTexture(ResourceLocation location, int colour) { + if (!isOverriding()) { + return false; + } + + if (Utils.disableCustomDungColours) { + return false; + } + + if (((colour >> 24) & 0xFF) < 10) { + return false; + } + + String id = location.getResourceDomain() + ":" + location.getResourcePath(); + if (dynamicUpdated.contains(id) && framebuffersDynamicFrom.containsKey(id)) { + framebuffersDynamicFrom.get(id).bindFramebufferTexture(); + return true; + } + + Minecraft.getMinecraft().getTextureManager().bindTexture(location); + int w = GL11.glGetTexLevelParameteri(GL11.GL_TEXTURE_2D, 0, GL11.GL_TEXTURE_WIDTH); + int h = GL11.glGetTexLevelParameteri(GL11.GL_TEXTURE_2D, 0, GL11.GL_TEXTURE_HEIGHT); + + Framebuffer to = checkFramebufferSizes(framebuffersDynamicTo.get(id), w, h); + dynamicUpdated.add(id); + + try { + GL11.glGetFloat(GL11.GL_PROJECTION_MATRIX, projectionMatrixOld); + GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, modelviewMatrixOld); + + GL11.glPushMatrix(); + + GlStateManager.matrixMode(GL11.GL_PROJECTION); + GlStateManager.loadIdentity(); + GlStateManager.ortho(0.0D, w, h, 0.0D, 1000.0D, 3000.0D); + GlStateManager.matrixMode(GL11.GL_MODELVIEW); + GlStateManager.loadIdentity(); + GlStateManager.translate(0.0F, 0.0F, -2000.0F); + + to.bindFramebuffer(true); + GlStateManager.clearColor(0, 1, 0, 1); + GlStateManager.clear(GL11.GL_COLOR_BUFFER_BIT); + + GlStateManager.disableBlend(); + GlStateManager.disableLighting(); + GlStateManager.disableFog(); + + Minecraft.getMinecraft().getTextureManager().bindTexture(location); + GlStateManager.color(1, 1, 1, 1); + Utils.drawTexturedRectNoBlend(0, 0, w, h, 0, 1, 1, 0, GL11.GL_LINEAR); + + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate( + GL11.GL_SRC_ALPHA, + GL11.GL_ONE_MINUS_SRC_ALPHA, + GL11.GL_ONE, + GL11.GL_ONE_MINUS_SRC_ALPHA + ); + Utils.drawRectNoBlend(0, 0, w, h, colour); + + GL11.glPopMatrix(); + + to.bindFramebufferTexture(); + if (Minecraft.getMinecraft().gameSettings.mipmapLevels >= 0) { + GL11.glTexParameteri( + GL11.GL_TEXTURE_2D, + GL12.GL_TEXTURE_MAX_LEVEL, + Minecraft.getMinecraft().gameSettings.mipmapLevels + ); + GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL12.GL_TEXTURE_MIN_LOD, 0.0F); + GL11.glTexParameterf( + GL11.GL_TEXTURE_2D, + GL12.GL_TEXTURE_MAX_LOD, + (float) Minecraft.getMinecraft().gameSettings.mipmapLevels + ); + GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL14.GL_TEXTURE_LOD_BIAS, 0.0F); + GL30.glGenerateMipmap(GL11.GL_TEXTURE_2D); + } + + GlStateManager.matrixMode(GL11.GL_PROJECTION); + GL11.glLoadMatrix(projectionMatrixOld); + GlStateManager.matrixMode(GL11.GL_MODELVIEW); + GL11.glLoadMatrix(modelviewMatrixOld); + + Framebuffer from = checkFramebufferSizes(framebuffersDynamicFrom.get(id), w, h); + framebuffersDynamicFrom.put(id, to); + framebuffersDynamicTo.put(id, from); + + to.bindFramebufferTexture(); + + Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true); + GlStateManager.disableBlend(); + GlStateManager.enableLighting(); + return true; + } catch (Exception e) { + e.printStackTrace(); + } + Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true); + GlStateManager.disableBlend(); + GlStateManager.enableLighting(); + return false; + } + + private static final HashMap dynamicPreloadMap = new HashMap() {{ + put(new ResourceLocation("textures/entity/bat.png"), NotEnoughUpdates.INSTANCE.config.dungeons.dungBatColour); + put( + new ResourceLocation("textures/entity/chest/normal.png"), + NotEnoughUpdates.INSTANCE.config.dungeons.dungChestColour + ); + put( + new ResourceLocation("textures/entity/chest/normal_double.png"), + NotEnoughUpdates.INSTANCE.config.dungeons.dungChestColour + ); + put( + new ResourceLocation("textures/entity/chest/trapped.png"), + NotEnoughUpdates.INSTANCE.config.dungeons.dungTrappedChestColour + ); + put( + new ResourceLocation("textures/entity/chest/trapped_double.png"), + NotEnoughUpdates.INSTANCE.config.dungeons.dungTrappedChestColour + ); + }}; + + public static void tick() { + if (!isOverriding() || Minecraft.getMinecraft().theWorld == null) { + return; + } + + dynamicUpdated.clear(); + + for (Map.Entry entry : dynamicPreloadMap.entrySet()) { + bindModifiedTexture(entry.getKey(), SpecialColour.specialToChromaRGB(entry.getValue())); + } + + Minecraft.getMinecraft().getTextureManager().bindTexture(TextureMap.locationBlocksTexture); + int w = GL11.glGetTexLevelParameteri(GL11.GL_TEXTURE_2D, 0, GL11.GL_TEXTURE_WIDTH); + int h = GL11.glGetTexLevelParameteri(GL11.GL_TEXTURE_2D, 0, GL11.GL_TEXTURE_HEIGHT); + + Framebuffer to = checkFramebufferSizes(framebufferBlocksTo, w, h); + + try { + GL11.glPushMatrix(); + + GlStateManager.matrixMode(5889); + GlStateManager.loadIdentity(); + GlStateManager.ortho(0.0D, w, h, 0.0D, 1000.0D, 3000.0D); + GlStateManager.matrixMode(5888); + GlStateManager.loadIdentity(); + GlStateManager.translate(0.0F, 0.0F, -2000.0F); + + to.bindFramebuffer(true); + GlStateManager.clear(GL11.GL_COLOR_BUFFER_BIT); + + GlStateManager.disableBlend(); + GlStateManager.disableLighting(); + GlStateManager.disableFog(); + + Minecraft.getMinecraft().getTextureManager().bindTexture(TextureMap.locationBlocksTexture); + GlStateManager.color(1, 1, 1, 1); + Utils.drawTexturedRectNoBlend(0, 0, w, h, 0, 1, 1, 0, GL11.GL_LINEAR); + + HashMap spriteMap = new HashMap() {{ + put( + Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite("minecraft:blocks/stonebrick_cracked"), + SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.dungeons.dungCrackedColour) + ); + put( + Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite("minecraft:blocks/dispenser_front_horizontal"), + SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.dungeons.dungDispenserColour) + ); + put( + Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite("minecraft:blocks/lever"), + SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.dungeons.dungLeverColour) + ); + put( + Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite("minecraft:blocks/trip_wire"), + SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.dungeons.dungTripWireColour) + ); + }}; + + for (Map.Entry entry : spriteMap.entrySet()) { + if (((entry.getValue() >> 24) & 0xFF) < 10) continue; + + TextureAtlasSprite tas = entry.getKey(); + Gui.drawRect((int) (w * tas.getMinU()), h - (int) (h * tas.getMaxV()) - 1, + (int) (w * tas.getMaxU()) + 1, h - (int) (h * tas.getMinV()), entry.getValue() + ); + } + + ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + GlStateManager.matrixMode(5889); + GlStateManager.loadIdentity(); + GlStateManager.ortho(0.0D, scaledResolution.getScaledWidth_double(), scaledResolution.getScaledHeight_double(), + 0.0D, 1000.0D, 3000.0D + ); + GlStateManager.matrixMode(5888); + GlStateManager.loadIdentity(); + GlStateManager.translate(0.0F, 0.0F, -2000.0F); + + GL11.glPopMatrix(); + + to.bindFramebufferTexture(); + if (Minecraft.getMinecraft().gameSettings.mipmapLevels >= 0) { + GL11.glTexParameteri( + GL11.GL_TEXTURE_2D, + GL12.GL_TEXTURE_MAX_LEVEL, + Minecraft.getMinecraft().gameSettings.mipmapLevels + ); + GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL12.GL_TEXTURE_MIN_LOD, 0.0F); + GL11.glTexParameterf( + GL11.GL_TEXTURE_2D, + GL12.GL_TEXTURE_MAX_LOD, + (float) Minecraft.getMinecraft().gameSettings.mipmapLevels + ); + GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL14.GL_TEXTURE_LOD_BIAS, 0.0F); + GL30.glGenerateMipmap(GL11.GL_TEXTURE_2D); + } + + Framebuffer from = checkFramebufferSizes(framebufferBlocksFrom, w, h); + framebufferBlocksFrom = to; + framebufferBlocksTo = from; + } catch (Exception e) { + e.printStackTrace(); + } + Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true); + GlStateManager.enableBlend(); + } + + private static Framebuffer checkFramebufferSizes(Framebuffer framebuffer, int width, int height) { + if (framebuffer == null || framebuffer.framebufferWidth != width || framebuffer.framebufferHeight != height) { + if (framebuffer == null) { + framebuffer = new Framebuffer(width, height, false); + framebuffer.framebufferColor[0] = 1f; + framebuffer.framebufferColor[1] = 0f; + framebuffer.framebufferColor[2] = 0f; + framebuffer.framebufferColor[3] = 0; + } else { + framebuffer.createBindFramebuffer(width, height); + } + framebuffer.setFramebufferFilter(GL11.GL_NEAREST); + } + return framebuffer; + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonMap.java b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonMap.java index 658f72df97..592f5b19ab 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonMap.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonMap.java @@ -2,10 +2,10 @@ import com.google.common.collect.Iterables; import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.core.BackgroundBlur; import io.github.moulberry.notenoughupdates.core.config.Position; import io.github.moulberry.notenoughupdates.util.NEUResourceManager; -import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.util.SpecialColour; import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.block.material.MapColor; @@ -13,7 +13,10 @@ import net.minecraft.client.entity.AbstractClientPlayer; import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.ScaledResolution; -import net.minecraft.client.renderer.*; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.client.renderer.texture.TextureUtil; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.client.resources.DefaultPlayerSkin; @@ -29,11 +32,12 @@ import net.minecraft.scoreboard.ScoreObjective; import net.minecraft.scoreboard.ScorePlayerTeam; import net.minecraft.scoreboard.Scoreboard; -import net.minecraft.util.*; +import net.minecraft.util.Matrix4f; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.Vec4b; import net.minecraft.world.storage.MapData; import net.minecraftforge.client.event.RenderGameOverlayEvent; import net.minecraftforge.event.world.WorldEvent; -import net.minecraftforge.fml.common.eventhandler.EventPriority; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL14; @@ -42,357 +46,393 @@ import java.io.BufferedReader; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; -import java.util.*; import java.util.List; +import java.util.*; public class DungeonMap { - - private static final ResourceLocation GREEN_CHECK = new ResourceLocation("notenoughupdates:dungeon_map/green_check.png"); - private static final ResourceLocation WHITE_CHECK = new ResourceLocation("notenoughupdates:dungeon_map/white_check.png"); - private static final ResourceLocation QUESTION = new ResourceLocation("notenoughupdates:dungeon_map/question.png"); - private static final ResourceLocation CROSS = new ResourceLocation("notenoughupdates:dungeon_map/cross.png"); - - private static final ResourceLocation ROOM_RED = new ResourceLocation("notenoughupdates:dungeon_map/rooms_default/red_room.png"); - private static final ResourceLocation ROOM_BROWN = new ResourceLocation("notenoughupdates:dungeon_map/rooms_default/brown_room.png"); - private static final ResourceLocation ROOM_GRAY = new ResourceLocation("notenoughupdates:dungeon_map/rooms_default/gray_room.png"); - private static final ResourceLocation ROOM_GREEN = new ResourceLocation("notenoughupdates:dungeon_map/rooms_default/green_room.png"); - private static final ResourceLocation ROOM_PINK = new ResourceLocation("notenoughupdates:dungeon_map/rooms_default/pink_room.png"); - private static final ResourceLocation ROOM_PURPLE = new ResourceLocation("notenoughupdates:dungeon_map/rooms_default/purple_room.png"); - private static final ResourceLocation ROOM_YELLOW = new ResourceLocation("notenoughupdates:dungeon_map/rooms_default/yellow_room.png"); - private static final ResourceLocation ROOM_ORANGE = new ResourceLocation("notenoughupdates:dungeon_map/rooms_default/orange_room.png"); - - private static final ResourceLocation CORRIDOR_RED = new ResourceLocation("notenoughupdates:dungeon_map/corridors_default/red_corridor.png"); - private static final ResourceLocation CORRIDOR_BROWN = new ResourceLocation("notenoughupdates:dungeon_map/corridors_default/brown_corridor.png"); - private static final ResourceLocation CORRIDOR_GRAY = new ResourceLocation("notenoughupdates:dungeon_map/corridors_default/gray_corridor.png"); - private static final ResourceLocation CORRIDOR_GREEN = new ResourceLocation("notenoughupdates:dungeon_map/corridors_default/green_corridor.png"); - private static final ResourceLocation CORRIDOR_PINK = new ResourceLocation("notenoughupdates:dungeon_map/corridors_default/pink_corridor.png"); - private static final ResourceLocation CORRIDOR_PURPLE = new ResourceLocation("notenoughupdates:dungeon_map/corridors_default/purple_corridor.png"); - private static final ResourceLocation CORRIDOR_YELLOW = new ResourceLocation("notenoughupdates:dungeon_map/corridors_default/yellow_corridor.png"); - private static final ResourceLocation CORRIDOR_ORANGE = new ResourceLocation("notenoughupdates:dungeon_map/corridors_default/orange_corridor.png"); - - private static final ResourceLocation DIVIDER_BROWN = new ResourceLocation("notenoughupdates:dungeon_map/dividers_default/brown_divider.png"); - - private static final ResourceLocation CORNER_BROWN = new ResourceLocation("notenoughupdates:dungeon_map/corners_default/brown_corner.png"); - - private final HashMap roomMap = new HashMap<>(); - private Color[][] colourMap = new Color[128][128]; - private int startRoomX = -1; - private int startRoomY = -1; - private int connectorSize = 5; - private int roomSize = 0; - - //private final List decorations = new ArrayList<>(); - //private final List lastDecorations = new ArrayList<>(); - private long lastDecorationsMillis = -1; - private long lastLastDecorationsMillis = -1; - - private Map playerEntityMapPositions = new HashMap<>(); - private Map playerMarkerMapPositions = new HashMap<>(); - private Set rawPlayerMarkerMapPositions = new HashSet<>(); - private Map playerMarkerMapPositionsLast = new HashMap<>(); - private HashMap playerIdMap = new HashMap<>(); - - private Map playerSkinMap = new HashMap<>(); - - private class RoomOffset { - int x; - int y; - - public RoomOffset(int x, int y) { - this.x = x; - this.y = y; - } - - public RoomOffset left() { - return new RoomOffset(x-1, y); - } - - public RoomOffset right() { - return new RoomOffset(x+1, y); - } - - public RoomOffset up() { - return new RoomOffset(x, y-1); - } - - public RoomOffset down() { - return new RoomOffset(x, y+1); - } - - public RoomOffset[] getNeighbors() { - return new RoomOffset[]{left(), right(), up(), down()}; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - RoomOffset that = (RoomOffset) o; - return x == that.x && y == that.y; - } - - @Override - public int hashCode() { - return Objects.hash(x, y); - } - } - - private enum RoomConnectionType { - NONE, WALL, CORRIDOR, ROOM_DIVIDER - } - - private class RoomConnection { - RoomConnectionType type; - Color colour; - - public RoomConnection(RoomConnectionType type, Color colour) { - this.type = type; - this.colour = colour; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - RoomConnection that = (RoomConnection) o; - return type == that.type && - Objects.equals(colour, that.colour); - } - - @Override - public int hashCode() { - return Objects.hash(type, colour); - } - } - - private class Room { - Color colour = new Color(0, 0, 0, 0); - int tickColour = 0; - boolean fillCorner = false; - - RoomConnection left = new RoomConnection(RoomConnectionType.NONE, new Color(0, true)); - RoomConnection up = new RoomConnection(RoomConnectionType.NONE, new Color(0, true)); - RoomConnection right = new RoomConnection(RoomConnectionType.NONE, new Color(0, true)); - RoomConnection down = new RoomConnection(RoomConnectionType.NONE, new Color(0, true)); - - public void renderNoRotate(int roomSize, int connectorSize, int rotation) { - if(tickColour != 0) { - Color tick = new Color(tickColour, true); - ResourceLocation indicatorTex = null; - if(tick.getRed() == 255 && tick.getGreen() == 255 && tick.getBlue() == 255) { - indicatorTex = WHITE_CHECK; - } else if(tick.getRed() == 0 && tick.getGreen() == 124 && tick.getBlue() == 0) { - indicatorTex = GREEN_CHECK; - } else if(tick.getRed() == 13 && tick.getGreen() == 13 && tick.getBlue() == 13) { - indicatorTex = QUESTION; - } else if(tick.getRed() == 255 && tick.getGreen() == 0 && tick.getBlue() == 0) { - indicatorTex = CROSS; - } - if(indicatorTex != null) { - Minecraft.getMinecraft().getTextureManager().bindTexture(indicatorTex); - float x = 0; - float y = 0; - - if(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmCenterCheck) { - if(fillCorner) { - x += -(roomSize+connectorSize)/2f*Math.cos(Math.toRadians(rotation-45))*1.414f; - y += (roomSize+connectorSize)/2f*Math.sin(Math.toRadians(rotation-45))*1.414; - } - if(down.type == RoomConnectionType.ROOM_DIVIDER && right.type != RoomConnectionType.ROOM_DIVIDER) { - x += -(roomSize+connectorSize)/2f*Math.sin(Math.toRadians(rotation)); - y += -(roomSize+connectorSize)/2f*Math.cos(Math.toRadians(rotation)); - } else if(down.type != RoomConnectionType.ROOM_DIVIDER && right.type == RoomConnectionType.ROOM_DIVIDER) { - x += -(roomSize+connectorSize)/2f*Math.cos(Math.toRadians(rotation)); - y += (roomSize+connectorSize)/2f*Math.sin(Math.toRadians(rotation)); - } - } - GlStateManager.translate(x, y, 0); - if(!NotEnoughUpdates.INSTANCE.config.dungeonMap.dmOrientCheck) { - GlStateManager.rotate(-rotation+180, 0, 0, 1); - } - - GlStateManager.pushMatrix(); - GlStateManager.scale(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmIconScale, - NotEnoughUpdates.INSTANCE.config.dungeonMap.dmIconScale, 1); - Utils.drawTexturedRect(-5, -5, 10, 10, GL11.GL_NEAREST); - GlStateManager.popMatrix(); - - if(!NotEnoughUpdates.INSTANCE.config.dungeonMap.dmOrientCheck) { - GlStateManager.rotate(rotation-180, 0, 0, 1); - } - GlStateManager.translate(-x, -y, 0); - } - } - } - - public void render(int roomSize, int connectorSize) { - ResourceLocation roomTex = null; - if(colour.getRed() == 114 && colour.getGreen() == 67 && colour.getBlue() == 27) { - roomTex = ROOM_BROWN; - } else if(colour.getRed() == 65 && colour.getGreen() == 65 && colour.getBlue() == 65) { - roomTex = ROOM_GRAY; - } else if(colour.getRed() == 0 && colour.getGreen() == 124 && colour.getBlue() == 0) { - roomTex = ROOM_GREEN; - } else if(colour.getRed() == 242 && colour.getGreen() == 127 && colour.getBlue() == 165) { - roomTex = ROOM_PINK; - } else if(colour.getRed() == 178 && colour.getGreen() == 76 && colour.getBlue() == 216) { - roomTex = ROOM_PURPLE; - } else if(colour.getRed() == 255 && colour.getGreen() == 0 && colour.getBlue() == 0) { - roomTex = ROOM_RED; - } else if(colour.getRed() == 229 && colour.getGreen() == 229 && colour.getBlue() == 51) { - roomTex = ROOM_YELLOW; - } else if(colour.getRed() == 216 && colour.getGreen() == 127 && colour.getBlue() == 51) { - roomTex = ROOM_ORANGE; - } - - if(roomTex != null) { - Minecraft.getMinecraft().getTextureManager().bindTexture(roomTex); - GlStateManager.color(1, 1, 1, 1); - Utils.drawTexturedRect(0, 0, roomSize, roomSize, GL11.GL_LINEAR); - } else { - Gui.drawRect(0, 0, roomSize, roomSize, colour.getRGB()); - } - - if(fillCorner) { - GlStateManager.color(1, 1, 1, 1); - Minecraft.getMinecraft().getTextureManager().bindTexture(CORNER_BROWN); - Utils.drawTexturedRect(roomSize, roomSize, connectorSize, connectorSize, GL11.GL_NEAREST); - } - - for(int k=0; k<2; k++) { - RoomConnection connection = down; - if(k == 1) connection = right; - - if(connection.type == RoomConnectionType.NONE || connection.type == RoomConnectionType.WALL) continue; - - ResourceLocation corridorTex = null; - if(connection.colour.getRed() == 114 && connection.colour.getGreen() == 67 && connection.colour.getBlue() == 27) { - corridorTex = connection.type == RoomConnectionType.CORRIDOR ? CORRIDOR_BROWN : DIVIDER_BROWN; - } else if(connection.colour.getRed() == 65 && connection.colour.getGreen() == 65 && connection.colour.getBlue() == 65) { - corridorTex = CORRIDOR_GRAY; - } else if(connection.colour.getRed() == 0 && connection.colour.getGreen() == 124 && connection.colour.getBlue() == 0) { - corridorTex = CORRIDOR_GREEN; - } else if(connection.colour.getRed() == 242 && connection.colour.getGreen() == 127 && connection.colour.getBlue() == 165) { - corridorTex = CORRIDOR_PINK; - } else if(connection.colour.getRed() == 178 && connection.colour.getGreen() == 76 && connection.colour.getBlue() == 216) { - corridorTex = CORRIDOR_PURPLE; - } else if(connection.colour.getRed() == 255 && connection.colour.getGreen() == 0 && connection.colour.getBlue() == 0) { - corridorTex = CORRIDOR_RED; - } else if(connection.colour.getRed() == 229 && connection.colour.getGreen() == 229 && connection.colour.getBlue() == 51) { - corridorTex = CORRIDOR_YELLOW; - } else if(connection.colour.getRed() == 216 && connection.colour.getGreen() == 127 && connection.colour.getBlue() == 51) { - corridorTex = CORRIDOR_ORANGE; - } - - if(corridorTex == null) { - int xOffset = 0; - int yOffset = 0; - int width = 0; - int height = 0; - - if(connection == right) { - xOffset = roomSize; - width = connectorSize; - height = roomSize; - - if(connection.type == RoomConnectionType.CORRIDOR) { - height = 8; - yOffset += 4; - } - } else if(connection == down) { - yOffset = roomSize; - width = roomSize; - height = connectorSize; - - if(connection.type == RoomConnectionType.CORRIDOR) { - width = 8; - xOffset += 4; - } - } - - Gui.drawRect(xOffset, yOffset, xOffset+width, yOffset+height, connection.colour.getRGB()); - } else { - GlStateManager.color(1, 1, 1, 1); - Minecraft.getMinecraft().getTextureManager().bindTexture(corridorTex); - GlStateManager.pushMatrix(); - if(connection==right) { - GlStateManager.translate(roomSize/2f, roomSize/2f, 0); - GlStateManager.rotate(-90, 0, 0, 1); - GlStateManager.translate(-roomSize/2f, -roomSize/2f, 0); - } - Utils.drawTexturedRect(0, roomSize, roomSize, connectorSize, GL11.GL_NEAREST); - GlStateManager.popMatrix(); - } - } - } - } - - private static final ResourceLocation mapIcons = new ResourceLocation("textures/map/map_icons.png"); - - public static Framebuffer mapFramebuffer1 = null; - public static Framebuffer mapFramebuffer2 = null; - public static Matrix4f projectionMatrix = null; - public static Shader mapShader = null; - - private static Framebuffer checkFramebufferSizes(Framebuffer framebuffer, int width, int height) { - if(framebuffer == null || framebuffer.framebufferWidth != width || framebuffer.framebufferHeight != height) { - if(framebuffer == null) { - framebuffer = new Framebuffer(width, height, true); - } else { - framebuffer.createBindFramebuffer(width, height); - } - framebuffer.setFramebufferFilter(GL11.GL_NEAREST); - } - return framebuffer; - } - - private static void upload(Shader shader, int width, int height, int scale, float radiusSq) { - if(shader == null) return; - shader.getShaderManager().getShaderUniformOrDefault("ProjMat").set(projectionMatrix); - shader.getShaderManager().getShaderUniformOrDefault("InSize").set(width*scale, height*scale); - shader.getShaderManager().getShaderUniformOrDefault("OutSize").set(width, height); - shader.getShaderManager().getShaderUniformOrDefault("ScreenSize").set((float)width, (float)height); - shader.getShaderManager().getShaderUniformOrDefault("radiusSq").set(radiusSq); - } - - public int getRenderRoomSize() { - double roomSizeOption = NotEnoughUpdates.INSTANCE.config.dungeonMap.dmRoomSize; - if(roomSizeOption <= 0) return 12; - return 12 + (int)Math.round(roomSizeOption*4); - } - - public int getRenderConnSize() { - int roomSizeOption = (int)Math.round(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmRoomSize); - if(roomSizeOption <= 0) return 3; - return 3 + roomSizeOption; - } - - private HashMap borderRadiusCache = new HashMap<>(); - public float getBorderRadius() { - int borderSizeOption = Math.round(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderSize); - String sizeId = borderSizeOption == 0 ? "small" : borderSizeOption == 2 ? "large" : "medium"; - - int style = NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderStyle; - if(borderRadiusCache.containsKey(style)) { - return borderRadiusCache.get(style); - } - - try(BufferedReader reader = new BufferedReader(new InputStreamReader(Minecraft.getMinecraft().getResourceManager().getResource( - new ResourceLocation("notenoughupdates:dungeon_map/borders/"+sizeId+"/"+style+".json")).getInputStream(), StandardCharsets.UTF_8))) { - JsonObject json = NotEnoughUpdates.INSTANCE.manager.gson.fromJson(reader, JsonObject.class); - float radiusSq = json.get("radiusSq").getAsFloat(); - - borderRadiusCache.put(style, radiusSq); - return radiusSq; - } catch(Exception ignored) { } - - borderRadiusCache.put(style, 1f); - return 1f; - } - - public void render(int centerX, int centerY) { - boolean useFb = NotEnoughUpdates.INSTANCE.config.dungeonMap.dmCompat <= 1 && OpenGlHelper.isFramebufferEnabled(); - boolean useShd = NotEnoughUpdates.INSTANCE.config.dungeonMap.dmCompat <= 0 && OpenGlHelper.areShadersSupported(); + private static final ResourceLocation GREEN_CHECK = new ResourceLocation( + "notenoughupdates:dungeon_map/green_check.png"); + private static final ResourceLocation WHITE_CHECK = new ResourceLocation( + "notenoughupdates:dungeon_map/white_check.png"); + private static final ResourceLocation QUESTION = new ResourceLocation("notenoughupdates:dungeon_map/question.png"); + private static final ResourceLocation CROSS = new ResourceLocation("notenoughupdates:dungeon_map/cross.png"); + + private static final ResourceLocation ROOM_RED = new ResourceLocation( + "notenoughupdates:dungeon_map/rooms_default/red_room.png"); + private static final ResourceLocation ROOM_BROWN = new ResourceLocation( + "notenoughupdates:dungeon_map/rooms_default/brown_room.png"); + private static final ResourceLocation ROOM_GRAY = new ResourceLocation( + "notenoughupdates:dungeon_map/rooms_default/gray_room.png"); + private static final ResourceLocation ROOM_GREEN = new ResourceLocation( + "notenoughupdates:dungeon_map/rooms_default/green_room.png"); + private static final ResourceLocation ROOM_PINK = new ResourceLocation( + "notenoughupdates:dungeon_map/rooms_default/pink_room.png"); + private static final ResourceLocation ROOM_PURPLE = new ResourceLocation( + "notenoughupdates:dungeon_map/rooms_default/purple_room.png"); + private static final ResourceLocation ROOM_YELLOW = new ResourceLocation( + "notenoughupdates:dungeon_map/rooms_default/yellow_room.png"); + private static final ResourceLocation ROOM_ORANGE = new ResourceLocation( + "notenoughupdates:dungeon_map/rooms_default/orange_room.png"); + + private static final ResourceLocation CORRIDOR_RED = new ResourceLocation( + "notenoughupdates:dungeon_map/corridors_default/red_corridor.png"); + private static final ResourceLocation CORRIDOR_BROWN = new ResourceLocation( + "notenoughupdates:dungeon_map/corridors_default/brown_corridor.png"); + private static final ResourceLocation CORRIDOR_GRAY = new ResourceLocation( + "notenoughupdates:dungeon_map/corridors_default/gray_corridor.png"); + private static final ResourceLocation CORRIDOR_GREEN = new ResourceLocation( + "notenoughupdates:dungeon_map/corridors_default/green_corridor.png"); + private static final ResourceLocation CORRIDOR_PINK = new ResourceLocation( + "notenoughupdates:dungeon_map/corridors_default/pink_corridor.png"); + private static final ResourceLocation CORRIDOR_PURPLE = new ResourceLocation( + "notenoughupdates:dungeon_map/corridors_default/purple_corridor.png"); + private static final ResourceLocation CORRIDOR_YELLOW = new ResourceLocation( + "notenoughupdates:dungeon_map/corridors_default/yellow_corridor.png"); + private static final ResourceLocation CORRIDOR_ORANGE = new ResourceLocation( + "notenoughupdates:dungeon_map/corridors_default/orange_corridor.png"); + + private static final ResourceLocation DIVIDER_BROWN = new ResourceLocation( + "notenoughupdates:dungeon_map/dividers_default/brown_divider.png"); + + private static final ResourceLocation CORNER_BROWN = new ResourceLocation( + "notenoughupdates:dungeon_map/corners_default/brown_corner.png"); + + private final HashMap roomMap = new HashMap<>(); + private Color[][] colourMap = new Color[128][128]; + private int startRoomX = -1; + private int startRoomY = -1; + private int connectorSize = 5; + private int roomSize = 0; + + //private final List decorations = new ArrayList<>(); + //private final List lastDecorations = new ArrayList<>(); + private long lastDecorationsMillis = -1; + private long lastLastDecorationsMillis = -1; + + private final Map playerEntityMapPositions = new HashMap<>(); + private final Map playerMarkerMapPositions = new HashMap<>(); + private final Set rawPlayerMarkerMapPositions = new HashSet<>(); + private final Map playerMarkerMapPositionsLast = new HashMap<>(); + private final HashMap playerIdMap = new HashMap<>(); + + private final Map playerSkinMap = new HashMap<>(); + + private static class RoomOffset { + int x; + int y; + + public RoomOffset(int x, int y) { + this.x = x; + this.y = y; + } + + public RoomOffset left() { + return new RoomOffset(x - 1, y); + } + + public RoomOffset right() { + return new RoomOffset(x + 1, y); + } + + public RoomOffset up() { + return new RoomOffset(x, y - 1); + } + + public RoomOffset down() { + return new RoomOffset(x, y + 1); + } + + public RoomOffset[] getNeighbors() { + return new RoomOffset[]{left(), right(), up(), down()}; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + RoomOffset that = (RoomOffset) o; + return x == that.x && y == that.y; + } + + @Override + public int hashCode() { + return Objects.hash(x, y); + } + } + + private enum RoomConnectionType { + NONE, WALL, CORRIDOR, ROOM_DIVIDER + } + + private static class RoomConnection { + RoomConnectionType type; + Color colour; + + public RoomConnection(RoomConnectionType type, Color colour) { + this.type = type; + this.colour = colour; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + RoomConnection that = (RoomConnection) o; + return type == that.type && + Objects.equals(colour, that.colour); + } + + @Override + public int hashCode() { + return Objects.hash(type, colour); + } + } + + private class Room { + Color colour = new Color(0, 0, 0, 0); + int tickColour = 0; + boolean fillCorner = false; + + RoomConnection left = new RoomConnection(RoomConnectionType.NONE, new Color(0, true)); + RoomConnection up = new RoomConnection(RoomConnectionType.NONE, new Color(0, true)); + RoomConnection right = new RoomConnection(RoomConnectionType.NONE, new Color(0, true)); + RoomConnection down = new RoomConnection(RoomConnectionType.NONE, new Color(0, true)); + + public void renderNoRotate(int roomSize, int connectorSize, int rotation) { + if (tickColour != 0) { + Color tick = new Color(tickColour, true); + ResourceLocation indicatorTex = null; + if (tick.getRed() == 255 && tick.getGreen() == 255 && tick.getBlue() == 255) { + indicatorTex = WHITE_CHECK; + } else if (tick.getRed() == 0 && tick.getGreen() == 124 && tick.getBlue() == 0) { + indicatorTex = GREEN_CHECK; + } else if (tick.getRed() == 13 && tick.getGreen() == 13 && tick.getBlue() == 13) { + indicatorTex = QUESTION; + } else if (tick.getRed() == 255 && tick.getGreen() == 0 && tick.getBlue() == 0) { + indicatorTex = CROSS; + } + if (indicatorTex != null) { + Minecraft.getMinecraft().getTextureManager().bindTexture(indicatorTex); + float x = 0; + float y = 0; + + if (NotEnoughUpdates.INSTANCE.config.dungeonMap.dmCenterCheck) { + if (fillCorner) { + x += -(roomSize + connectorSize) / 2f * Math.cos(Math.toRadians(rotation - 45)) * 1.414f; + y += (roomSize + connectorSize) / 2f * Math.sin(Math.toRadians(rotation - 45)) * 1.414; + } + if (down.type == RoomConnectionType.ROOM_DIVIDER && right.type != RoomConnectionType.ROOM_DIVIDER) { + x += -(roomSize + connectorSize) / 2f * Math.sin(Math.toRadians(rotation)); + y += -(roomSize + connectorSize) / 2f * Math.cos(Math.toRadians(rotation)); + } else if (down.type != RoomConnectionType.ROOM_DIVIDER && right.type == RoomConnectionType.ROOM_DIVIDER) { + x += -(roomSize + connectorSize) / 2f * Math.cos(Math.toRadians(rotation)); + y += (roomSize + connectorSize) / 2f * Math.sin(Math.toRadians(rotation)); + } + } + GlStateManager.translate(x, y, 0); + if (!NotEnoughUpdates.INSTANCE.config.dungeonMap.dmOrientCheck) { + GlStateManager.rotate(-rotation + 180, 0, 0, 1); + } + + GlStateManager.pushMatrix(); + GlStateManager.scale(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmIconScale, + NotEnoughUpdates.INSTANCE.config.dungeonMap.dmIconScale, 1 + ); + Utils.drawTexturedRect(-5, -5, 10, 10, GL11.GL_NEAREST); + GlStateManager.popMatrix(); + + if (!NotEnoughUpdates.INSTANCE.config.dungeonMap.dmOrientCheck) { + GlStateManager.rotate(rotation - 180, 0, 0, 1); + } + GlStateManager.translate(-x, -y, 0); + } + } + } + + public void render(int roomSize, int connectorSize) { + ResourceLocation roomTex = null; + if (colour.getRed() == 114 && colour.getGreen() == 67 && colour.getBlue() == 27) { + roomTex = ROOM_BROWN; + } else if (colour.getRed() == 65 && colour.getGreen() == 65 && colour.getBlue() == 65) { + roomTex = ROOM_GRAY; + } else if (colour.getRed() == 0 && colour.getGreen() == 124 && colour.getBlue() == 0) { + roomTex = ROOM_GREEN; + } else if (colour.getRed() == 242 && colour.getGreen() == 127 && colour.getBlue() == 165) { + roomTex = ROOM_PINK; + } else if (colour.getRed() == 178 && colour.getGreen() == 76 && colour.getBlue() == 216) { + roomTex = ROOM_PURPLE; + } else if (colour.getRed() == 255 && colour.getGreen() == 0 && colour.getBlue() == 0) { + roomTex = ROOM_RED; + } else if (colour.getRed() == 229 && colour.getGreen() == 229 && colour.getBlue() == 51) { + roomTex = ROOM_YELLOW; + } else if (colour.getRed() == 216 && colour.getGreen() == 127 && colour.getBlue() == 51) { + roomTex = ROOM_ORANGE; + } + + if (roomTex != null) { + Minecraft.getMinecraft().getTextureManager().bindTexture(roomTex); + GlStateManager.color(1, 1, 1, 1); + Utils.drawTexturedRect(0, 0, roomSize, roomSize, GL11.GL_LINEAR); + } else { + Gui.drawRect(0, 0, roomSize, roomSize, colour.getRGB()); + } + + if (fillCorner) { + GlStateManager.color(1, 1, 1, 1); + Minecraft.getMinecraft().getTextureManager().bindTexture(CORNER_BROWN); + Utils.drawTexturedRect(roomSize, roomSize, connectorSize, connectorSize, GL11.GL_NEAREST); + } + + for (int k = 0; k < 2; k++) { + RoomConnection connection = down; + if (k == 1) connection = right; + + if (connection.type == RoomConnectionType.NONE || connection.type == RoomConnectionType.WALL) continue; + + ResourceLocation corridorTex = null; + if (connection.colour.getRed() == 114 && connection.colour.getGreen() == 67 && + connection.colour.getBlue() == 27) { + corridorTex = connection.type == RoomConnectionType.CORRIDOR ? CORRIDOR_BROWN : DIVIDER_BROWN; + } else if (connection.colour.getRed() == 65 && connection.colour.getGreen() == 65 && + connection.colour.getBlue() == 65) { + corridorTex = CORRIDOR_GRAY; + } else if (connection.colour.getRed() == 0 && connection.colour.getGreen() == 124 && + connection.colour.getBlue() == 0) { + corridorTex = CORRIDOR_GREEN; + } else if (connection.colour.getRed() == 242 && connection.colour.getGreen() == 127 && + connection.colour.getBlue() == 165) { + corridorTex = CORRIDOR_PINK; + } else if (connection.colour.getRed() == 178 && connection.colour.getGreen() == 76 && + connection.colour.getBlue() == 216) { + corridorTex = CORRIDOR_PURPLE; + } else if (connection.colour.getRed() == 255 && connection.colour.getGreen() == 0 && + connection.colour.getBlue() == 0) { + corridorTex = CORRIDOR_RED; + } else if (connection.colour.getRed() == 229 && connection.colour.getGreen() == 229 && + connection.colour.getBlue() == 51) { + corridorTex = CORRIDOR_YELLOW; + } else if (connection.colour.getRed() == 216 && connection.colour.getGreen() == 127 && + connection.colour.getBlue() == 51) { + corridorTex = CORRIDOR_ORANGE; + } + + if (corridorTex == null) { + int xOffset = 0; + int yOffset = 0; + int width = 0; + int height = 0; + + if (connection == right) { + xOffset = roomSize; + width = connectorSize; + height = roomSize; + + if (connection.type == RoomConnectionType.CORRIDOR) { + height = 8; + yOffset += 4; + } + } else if (connection == down) { + yOffset = roomSize; + width = roomSize; + height = connectorSize; + + if (connection.type == RoomConnectionType.CORRIDOR) { + width = 8; + xOffset += 4; + } + } + + Gui.drawRect(xOffset, yOffset, xOffset + width, yOffset + height, connection.colour.getRGB()); + } else { + GlStateManager.color(1, 1, 1, 1); + Minecraft.getMinecraft().getTextureManager().bindTexture(corridorTex); + GlStateManager.pushMatrix(); + if (connection == right) { + GlStateManager.translate(roomSize / 2f, roomSize / 2f, 0); + GlStateManager.rotate(-90, 0, 0, 1); + GlStateManager.translate(-roomSize / 2f, -roomSize / 2f, 0); + } + Utils.drawTexturedRect(0, roomSize, roomSize, connectorSize, GL11.GL_NEAREST); + GlStateManager.popMatrix(); + } + } + } + } + + private static final ResourceLocation mapIcons = new ResourceLocation("textures/map/map_icons.png"); + + public static Framebuffer mapFramebuffer1 = null; + public static Framebuffer mapFramebuffer2 = null; + public static Matrix4f projectionMatrix = null; + public static Shader mapShader = null; + + private static Framebuffer checkFramebufferSizes(Framebuffer framebuffer, int width, int height) { + if (framebuffer == null || framebuffer.framebufferWidth != width || framebuffer.framebufferHeight != height) { + if (framebuffer == null) { + framebuffer = new Framebuffer(width, height, true); + } else { + framebuffer.createBindFramebuffer(width, height); + } + framebuffer.setFramebufferFilter(GL11.GL_NEAREST); + } + return framebuffer; + } + + private static void upload(Shader shader, int width, int height, int scale, float radiusSq) { + if (shader == null) return; + shader.getShaderManager().getShaderUniformOrDefault("ProjMat").set(projectionMatrix); + shader.getShaderManager().getShaderUniformOrDefault("InSize").set(width * scale, height * scale); + shader.getShaderManager().getShaderUniformOrDefault("OutSize").set(width, height); + shader.getShaderManager().getShaderUniformOrDefault("ScreenSize").set((float) width, (float) height); + shader.getShaderManager().getShaderUniformOrDefault("radiusSq").set(radiusSq); + } + + public int getRenderRoomSize() { + double roomSizeOption = NotEnoughUpdates.INSTANCE.config.dungeonMap.dmRoomSize; + if (roomSizeOption <= 0) return 12; + return 12 + (int) Math.round(roomSizeOption * 4); + } + + public int getRenderConnSize() { + int roomSizeOption = Math.round(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmRoomSize); + if (roomSizeOption <= 0) return 3; + return 3 + roomSizeOption; + } + + private final HashMap borderRadiusCache = new HashMap<>(); + + public float getBorderRadius() { + int borderSizeOption = Math.round(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderSize); + String sizeId = borderSizeOption == 0 ? "small" : borderSizeOption == 2 ? "large" : "medium"; + + int style = NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderStyle; + if (borderRadiusCache.containsKey(style)) { + return borderRadiusCache.get(style); + } + + try ( + BufferedReader reader = new BufferedReader(new InputStreamReader(Minecraft + .getMinecraft() + .getResourceManager() + .getResource( + new ResourceLocation("notenoughupdates:dungeon_map/borders/" + sizeId + "/" + style + ".json")) + .getInputStream(), StandardCharsets.UTF_8)) + ) { + JsonObject json = NotEnoughUpdates.INSTANCE.manager.gson.fromJson(reader, JsonObject.class); + float radiusSq = json.get("radiusSq").getAsFloat(); + + borderRadiusCache.put(style, radiusSq); + return radiusSq; + } catch (Exception ignored) { + } + + borderRadiusCache.put(style, 1f); + return 1f; + } + + public void render(int centerX, int centerY) { + boolean useFb = NotEnoughUpdates.INSTANCE.config.dungeonMap.dmCompat <= 1 && OpenGlHelper.isFramebufferEnabled(); + boolean useShd = NotEnoughUpdates.INSTANCE.config.dungeonMap.dmCompat <= 0 && OpenGlHelper.areShadersSupported(); /*if((useFb && !OpenGlHelper.isFramebufferEnabled()) || (useShd && !OpenGlHelper.areShadersSupported())) { Utils.drawStringCentered(EnumChatFormatting.RED+"NEU Dungeon Map requires framebuffers & shaders", @@ -404,203 +444,221 @@ public void render(int centerX, int centerY) { return; }*/ - ScaledResolution scaledResolution = Utils.pushGuiScale(2); - - int minRoomX = 999; - int minRoomY = 999; - int maxRoomX = -999; - int maxRoomY = -999; - for(RoomOffset offset : roomMap.keySet()) { - minRoomX = Math.min(offset.x, minRoomX); - minRoomY = Math.min(offset.y, minRoomY); - maxRoomX = Math.max(offset.x, maxRoomX); - maxRoomY = Math.max(offset.y, maxRoomY); - } - - int borderSizeOption = Math.round(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderSize); - - int renderRoomSize = getRenderRoomSize(); - int renderConnSize = getRenderConnSize(); - - MapPosition playerPos = null; - if(playerEntityMapPositions.containsKey(Minecraft.getMinecraft().thePlayer.getName())) { - playerPos = playerEntityMapPositions.get(Minecraft.getMinecraft().thePlayer.getName()); - } else if(playerMarkerMapPositions.containsKey(Minecraft.getMinecraft().thePlayer.getName())) { - playerPos = playerMarkerMapPositions.get(Minecraft.getMinecraft().thePlayer.getName()); - } - - int rotation = 180; - if(playerPos != null && NotEnoughUpdates.INSTANCE.config.dungeonMap.dmRotatePlayer) { - rotation = (int)playerPos.rotation; - } - - int mapSizeX; - int mapSizeY; - if(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderStyle <= 1) { - mapSizeX = 80 + Math.round(40*NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderSize); - } else { - mapSizeX = borderSizeOption == 0 ? 90 : borderSizeOption == 1 ? 120 : borderSizeOption == 2 ? 160 : 240; - } - mapSizeY = mapSizeX; - int roomsSizeX = (maxRoomX-minRoomX)*(renderRoomSize+renderConnSize)+renderRoomSize; - int roomsSizeY = (maxRoomY-minRoomY)*(renderRoomSize+renderConnSize)+renderRoomSize; - int mapCenterX = mapSizeX/2; - int mapCenterY = mapSizeY/2; - int scaleFactor = 8; - - projectionMatrix = Utils.createProjectionMatrix(mapSizeX*scaleFactor, mapSizeY*scaleFactor); - mapFramebuffer1 = checkFramebufferSizes(mapFramebuffer1, mapSizeX*scaleFactor, mapSizeY*scaleFactor); - mapFramebuffer2 = checkFramebufferSizes(mapFramebuffer2, mapSizeX*scaleFactor, mapSizeY*scaleFactor); - mapFramebuffer1.framebufferColor[1] = 0; - mapFramebuffer1.framebufferColor[2] = 0; - - try { - if(mapShader == null) { - mapShader = new Shader(new NEUResourceManager(Minecraft.getMinecraft().getResourceManager()), - "dungeonmap", mapFramebuffer1, mapFramebuffer2); - } - } catch(Exception e) { - e.printStackTrace(); - Utils.pushGuiScale(-1); - return; - } - - int backgroundColour = SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBackgroundColour); - - mapFramebuffer1.framebufferColor[0] = ((backgroundColour >> 16) & 0xFF)/255f; - mapFramebuffer1.framebufferColor[1] = ((backgroundColour >> 8) & 0xFF)/255f; - mapFramebuffer1.framebufferColor[2] = (backgroundColour & 0xFF)/255f; - mapFramebuffer2.framebufferColor[0] = ((backgroundColour >> 16) & 0xFF)/255f; - mapFramebuffer2.framebufferColor[1] = ((backgroundColour >> 8) & 0xFF)/255f; - mapFramebuffer2.framebufferColor[2] = (backgroundColour & 0xFF)/255f; - - try { - if(useFb) { - mapFramebuffer1.framebufferClear(); - mapFramebuffer2.framebufferClear(); - } - - GlStateManager.pushMatrix(); { - if(useFb) { - GlStateManager.matrixMode(5889); - GlStateManager.loadIdentity(); - GlStateManager.ortho(0.0D, mapSizeX*scaleFactor, mapSizeY*scaleFactor, 0.0D, 1000.0D, 3000.0D); - GlStateManager.matrixMode(5888); - GlStateManager.loadIdentity(); - GlStateManager.translate(0.0F, 0.0F, -2000.0F); - - GlStateManager.scale(scaleFactor, scaleFactor, 1); - mapFramebuffer1.bindFramebuffer(true); - - GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); - GlStateManager.disableBlend(); - } else { - GL11.glEnable(GL11.GL_SCISSOR_TEST); - GL11.glScissor((centerX-mapSizeX/2)*2, Minecraft.getMinecraft().displayHeight-(centerY+mapSizeY/2)*2, mapSizeX*2, mapSizeY*2); - - GlStateManager.translate(centerX-mapSizeX/2, centerY-mapSizeY/2, 100); - } - - if(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBackgroundBlur > 0.1) { - GlStateManager.translate(-centerX+mapSizeX/2, -centerY+mapSizeY/2, 0); - BackgroundBlur.renderBlurredBackground(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBackgroundBlur, - scaledResolution.getScaledWidth(), scaledResolution.getScaledHeight(), - centerX-mapSizeX/2, centerY-mapSizeY/2, mapSizeX, mapSizeY); - BackgroundBlur.markDirty(); - GlStateManager.translate(centerX-mapSizeX/2, centerY-mapSizeY/2, 0); - } - - GlStateManager.translate(mapCenterX, mapCenterY, 10); - - if(!useFb || NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBackgroundBlur > 0.1) { - GlStateManager.enableBlend(); - GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); - } - Utils.drawRectNoBlend(-mapCenterX, -mapCenterY, mapCenterX, mapCenterY, backgroundColour); - - GlStateManager.rotate(-rotation+180, 0, 0, 1); - - if(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmCenterPlayer && playerPos != null) { - float x = playerPos.getRenderX(); - float y = playerPos.getRenderY(); - x -= minRoomX*(renderRoomSize+renderConnSize); - y -= minRoomY*(renderRoomSize+renderConnSize); - - GlStateManager.translate(-x, -y, 0); - } else { - GlStateManager.translate(-roomsSizeX/2, -roomsSizeY/2, 0); - } - - for(Map.Entry entry : roomMap.entrySet()) { - RoomOffset roomOffset = entry.getKey(); - Room room = entry.getValue(); - - int x = (roomOffset.x-minRoomX)*(renderRoomSize+renderConnSize); - int y = (roomOffset.y-minRoomY)*(renderRoomSize+renderConnSize); - - GlStateManager.pushMatrix(); - GlStateManager.translate(x, y, 0); - - room.render(renderRoomSize, renderConnSize); - - GlStateManager.translate(-x, -y, 0); - GlStateManager.popMatrix(); - } - - GlStateManager.translate(-mapCenterX+roomsSizeX/2f, -mapCenterY+roomsSizeY/2f, 0); - - GlStateManager.translate(mapCenterX, mapCenterY, 0); - GlStateManager.rotate(rotation-180, 0, 0, 1); - GlStateManager.translate(-mapCenterX, -mapCenterY, 0); - - GlStateManager.translate(mapCenterX, mapCenterY, 0); - - for(Map.Entry entry : roomMap.entrySet()) { - RoomOffset roomOffset = entry.getKey(); - Room room = entry.getValue(); - - float x = (roomOffset.x-minRoomX)*(renderRoomSize+renderConnSize)-roomsSizeX/2f+renderRoomSize/2f; - float y = (roomOffset.y-minRoomY)*(renderRoomSize+renderConnSize)-roomsSizeY/2f+renderRoomSize/2f; - float x2 = (float)(-x*Math.cos(Math.toRadians(-rotation)) + y*Math.sin(Math.toRadians(-rotation))); - float y2 = (float)(-x*Math.sin(Math.toRadians(-rotation)) - y*Math.cos(Math.toRadians(-rotation))); - - GlStateManager.pushMatrix(); - GlStateManager.translate(x2, y2, 0); - - GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); - room.renderNoRotate(renderRoomSize, renderConnSize, rotation); - - GlStateManager.translate(-x2, -y2, 0); - GlStateManager.popMatrix(); - } - - - GlStateManager.translate(-mapCenterX, -mapCenterY, 0); - - GlStateManager.translate(mapCenterX, mapCenterY, 0); - GlStateManager.rotate(-rotation+180, 0, 0, 1); - GlStateManager.translate(-mapCenterX, -mapCenterY, 0); - - GlStateManager.translate(mapCenterX-roomsSizeX/2f, mapCenterY-roomsSizeY/2f, 0); - - Tessellator tessellator = Tessellator.getInstance(); - WorldRenderer worldrenderer = tessellator.getWorldRenderer(); - int k = 0; - - for(Map.Entry entry : playerMarkerMapPositions.entrySet()) { - String name = entry.getKey(); - MapPosition pos = entry.getValue(); - float x = pos.getRenderX(); - float y = pos.getRenderY(); - float angle = pos.rotation; - - boolean doInterp = NotEnoughUpdates.INSTANCE.config.dungeonMap.dmPlayerInterp; - if(!isFloorOne && playerEntityMapPositions.containsKey(name)) { - MapPosition entityPos = playerEntityMapPositions.get(name); - angle = entityPos.rotation; + ScaledResolution scaledResolution = Utils.pushGuiScale(2); + + int minRoomX = 999; + int minRoomY = 999; + int maxRoomX = -999; + int maxRoomY = -999; + for (RoomOffset offset : roomMap.keySet()) { + minRoomX = Math.min(offset.x, minRoomX); + minRoomY = Math.min(offset.y, minRoomY); + maxRoomX = Math.max(offset.x, maxRoomX); + maxRoomY = Math.max(offset.y, maxRoomY); + } + + int borderSizeOption = Math.round(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderSize); + + int renderRoomSize = getRenderRoomSize(); + int renderConnSize = getRenderConnSize(); + + MapPosition playerPos = null; + if (playerEntityMapPositions.containsKey(Minecraft.getMinecraft().thePlayer.getName())) { + playerPos = playerEntityMapPositions.get(Minecraft.getMinecraft().thePlayer.getName()); + } else if (playerMarkerMapPositions.containsKey(Minecraft.getMinecraft().thePlayer.getName())) { + playerPos = playerMarkerMapPositions.get(Minecraft.getMinecraft().thePlayer.getName()); + } + + int rotation = 180; + if (playerPos != null && NotEnoughUpdates.INSTANCE.config.dungeonMap.dmRotatePlayer) { + rotation = (int) playerPos.rotation; + } + + int mapSizeX; + int mapSizeY; + if (NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderStyle <= 1) { + mapSizeX = 80 + Math.round(40 * NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderSize); + } else { + mapSizeX = borderSizeOption == 0 ? 90 : borderSizeOption == 1 ? 120 : borderSizeOption == 2 ? 160 : 240; + } + mapSizeY = mapSizeX; + int roomsSizeX = (maxRoomX - minRoomX) * (renderRoomSize + renderConnSize) + renderRoomSize; + int roomsSizeY = (maxRoomY - minRoomY) * (renderRoomSize + renderConnSize) + renderRoomSize; + int mapCenterX = mapSizeX / 2; + int mapCenterY = mapSizeY / 2; + int scaleFactor = 8; + + projectionMatrix = Utils.createProjectionMatrix(mapSizeX * scaleFactor, mapSizeY * scaleFactor); + mapFramebuffer1 = checkFramebufferSizes(mapFramebuffer1, mapSizeX * scaleFactor, mapSizeY * scaleFactor); + mapFramebuffer2 = checkFramebufferSizes(mapFramebuffer2, mapSizeX * scaleFactor, mapSizeY * scaleFactor); + mapFramebuffer1.framebufferColor[1] = 0; + mapFramebuffer1.framebufferColor[2] = 0; + + try { + if (mapShader == null) { + mapShader = new Shader(new NEUResourceManager(Minecraft.getMinecraft().getResourceManager()), + "dungeonmap", mapFramebuffer1, mapFramebuffer2 + ); + } + } catch (Exception e) { + e.printStackTrace(); + Utils.pushGuiScale(-1); + return; + } + + int backgroundColour = + SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBackgroundColour); + + mapFramebuffer1.framebufferColor[0] = ((backgroundColour >> 16) & 0xFF) / 255f; + mapFramebuffer1.framebufferColor[1] = ((backgroundColour >> 8) & 0xFF) / 255f; + mapFramebuffer1.framebufferColor[2] = (backgroundColour & 0xFF) / 255f; + mapFramebuffer2.framebufferColor[0] = ((backgroundColour >> 16) & 0xFF) / 255f; + mapFramebuffer2.framebufferColor[1] = ((backgroundColour >> 8) & 0xFF) / 255f; + mapFramebuffer2.framebufferColor[2] = (backgroundColour & 0xFF) / 255f; + + try { + if (useFb) { + mapFramebuffer1.framebufferClear(); + mapFramebuffer2.framebufferClear(); + } + + GlStateManager.pushMatrix(); + { + if (useFb) { + GlStateManager.matrixMode(5889); + GlStateManager.loadIdentity(); + GlStateManager.ortho(0.0D, mapSizeX * scaleFactor, mapSizeY * scaleFactor, 0.0D, 1000.0D, 3000.0D); + GlStateManager.matrixMode(5888); + GlStateManager.loadIdentity(); + GlStateManager.translate(0.0F, 0.0F, -2000.0F); + + GlStateManager.scale(scaleFactor, scaleFactor, 1); + mapFramebuffer1.bindFramebuffer(true); + + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + GlStateManager.disableBlend(); + } else { + GL11.glEnable(GL11.GL_SCISSOR_TEST); + GL11.glScissor( + (centerX - mapSizeX / 2) * 2, + Minecraft.getMinecraft().displayHeight - (centerY + mapSizeY / 2) * 2, + mapSizeX * 2, + mapSizeY * 2 + ); + + GlStateManager.translate(centerX - mapSizeX / 2, centerY - mapSizeY / 2, 100); + } + + if (NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBackgroundBlur > 0.1 && + NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBackgroundBlur < 100 && + NotEnoughUpdates.INSTANCE.config.dungeonMap.dmEnable) { + GlStateManager.translate(-centerX + mapSizeX / 2, -centerY + mapSizeY / 2, 0); + BackgroundBlur.renderBlurredBackground(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBackgroundBlur, + scaledResolution.getScaledWidth(), scaledResolution.getScaledHeight(), + centerX - mapSizeX / 2, centerY - mapSizeY / 2, mapSizeX, mapSizeY + ); + BackgroundBlur.markDirty(); + GlStateManager.translate(centerX - mapSizeX / 2, centerY - mapSizeY / 2, 0); + } + + GlStateManager.translate(mapCenterX, mapCenterY, 10); + + if (!useFb || NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBackgroundBlur > 0.1 && + NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBackgroundBlur < 100) { + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate( + GL11.GL_SRC_ALPHA, + GL11.GL_ONE_MINUS_SRC_ALPHA, + GL11.GL_ONE, + GL11.GL_ONE_MINUS_SRC_ALPHA + ); + } + Utils.drawRectNoBlend(-mapCenterX, -mapCenterY, mapCenterX, mapCenterY, backgroundColour); + + GlStateManager.rotate(-rotation + 180, 0, 0, 1); + + if (NotEnoughUpdates.INSTANCE.config.dungeonMap.dmCenterPlayer && playerPos != null) { + float x = playerPos.getRenderX(); + float y = playerPos.getRenderY(); + x -= minRoomX * (renderRoomSize + renderConnSize); + y -= minRoomY * (renderRoomSize + renderConnSize); + + GlStateManager.translate(-x, -y, 0); + } else { + GlStateManager.translate(-roomsSizeX / 2, -roomsSizeY / 2, 0); + } + + for (Map.Entry entry : roomMap.entrySet()) { + RoomOffset roomOffset = entry.getKey(); + Room room = entry.getValue(); + + int x = (roomOffset.x - minRoomX) * (renderRoomSize + renderConnSize); + int y = (roomOffset.y - minRoomY) * (renderRoomSize + renderConnSize); + + GlStateManager.pushMatrix(); + GlStateManager.translate(x, y, 0); + + room.render(renderRoomSize, renderConnSize); + + GlStateManager.translate(-x, -y, 0); + GlStateManager.popMatrix(); + } + + GlStateManager.translate(-mapCenterX + roomsSizeX / 2f, -mapCenterY + roomsSizeY / 2f, 0); + + GlStateManager.translate(mapCenterX, mapCenterY, 0); + GlStateManager.rotate(rotation - 180, 0, 0, 1); + GlStateManager.translate(-mapCenterX, -mapCenterY, 0); + + GlStateManager.translate(mapCenterX, mapCenterY, 0); + + for (Map.Entry entry : roomMap.entrySet()) { + RoomOffset roomOffset = entry.getKey(); + Room room = entry.getValue(); + + float x = + (roomOffset.x - minRoomX) * (renderRoomSize + renderConnSize) - roomsSizeX / 2f + renderRoomSize / 2f; + float y = + (roomOffset.y - minRoomY) * (renderRoomSize + renderConnSize) - roomsSizeY / 2f + renderRoomSize / 2f; + float x2 = (float) (-x * Math.cos(Math.toRadians(-rotation)) + y * Math.sin(Math.toRadians(-rotation))); + float y2 = (float) (-x * Math.sin(Math.toRadians(-rotation)) - y * Math.cos(Math.toRadians(-rotation))); + + GlStateManager.pushMatrix(); + GlStateManager.translate(x2, y2, 0); + + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + room.renderNoRotate(renderRoomSize, renderConnSize, rotation); + + GlStateManager.translate(-x2, -y2, 0); + GlStateManager.popMatrix(); + } + + GlStateManager.translate(-mapCenterX, -mapCenterY, 0); + + GlStateManager.translate(mapCenterX, mapCenterY, 0); + GlStateManager.rotate(-rotation + 180, 0, 0, 1); + GlStateManager.translate(-mapCenterX, -mapCenterY, 0); + + GlStateManager.translate(mapCenterX - roomsSizeX / 2f, mapCenterY - roomsSizeY / 2f, 0); + + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer worldrenderer = tessellator.getWorldRenderer(); + int k = 0; + + for (Map.Entry entry : playerMarkerMapPositions.entrySet()) { + String name = entry.getKey(); + MapPosition pos = entry.getValue(); + float x = pos.getRenderX(); + float y = pos.getRenderY(); + float angle = pos.rotation; + + boolean doInterp = NotEnoughUpdates.INSTANCE.config.dungeonMap.dmPlayerInterp; + if (!isFloorOne && playerEntityMapPositions.containsKey(name)) { + MapPosition entityPos = playerEntityMapPositions.get(name); + angle = entityPos.rotation; - float deltaX = entityPos.getRenderX() - pos.getRenderX(); - float deltaY = entityPos.getRenderY() - pos.getRenderY(); + float deltaX = entityPos.getRenderX() - pos.getRenderX(); + float deltaY = entityPos.getRenderY() - pos.getRenderY(); /*if(deltaX > (renderRoomSize + renderConnSize)/2) { deltaX -= (renderRoomSize + renderConnSize); @@ -613,843 +671,901 @@ public void render(int centerX, int centerY) { deltaY += (renderRoomSize + renderConnSize); }*/ - x += deltaX; - y += deltaY; - - doInterp = false; - } - - float minU = 3/4f; - float minV = 0; - - if(name.equals(Minecraft.getMinecraft().thePlayer.getName())) { - minU = 1/4f; - } - - float maxU = minU + 1/4f; - float maxV = minV + 1/4f; - - if(doInterp && playerMarkerMapPositionsLast.containsKey(name)) { - MapPosition last = playerMarkerMapPositionsLast.get(name); - float xLast = last.getRenderX(); - float yLast = last.getRenderY(); - - float distSq = (x-xLast) * (x-xLast) + (y-yLast) * (y-yLast); - if (distSq < renderRoomSize*renderRoomSize/4f) { - float angleLast = last.rotation; - if (angle > 180 && angleLast < 180) angleLast += 360; - if (angleLast > 180 && angle < 180) angle += 360; - - float interpFactor = Math.round((System.currentTimeMillis() - lastDecorationsMillis) * 100f) / 100f / (lastDecorationsMillis - lastLastDecorationsMillis); - interpFactor = Math.max(0, Math.min(1, interpFactor)); - - x = xLast + (x - xLast) * interpFactor; - y = yLast + (y - yLast) * interpFactor; - angle = angleLast + (angle - angleLast) * interpFactor; - angle %= 360; - } - } - - boolean blackBorder = false; - boolean headLayer = false; - int pixelWidth = 8; - int pixelHeight = 8; - if(renderRoomSize >= 24) { - pixelWidth = pixelHeight = 12; - } - GlStateManager.color(1, 1, 1, 1); - if((!NotEnoughUpdates.INSTANCE.config.dungeons.showOwnHeadAsMarker || - playerMarkerMapPositions.size() <= 1 || minU != 1/4f) && - NotEnoughUpdates.INSTANCE.config.dungeonMap.dmPlayerHeads >= 1 && - playerSkinMap.containsKey(entry.getKey())) { - Minecraft.getMinecraft().getTextureManager().bindTexture(playerSkinMap.get(entry.getKey())); - - minU = 8/64f; - minV = 8/64f; - maxU = 16/64f; - maxV = 16/64f; - - headLayer = true; - if(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmPlayerHeads >= 2) { - blackBorder = true; - } - } else { - Minecraft.getMinecraft().getTextureManager().bindTexture(mapIcons); - } - - x -= minRoomX*(renderRoomSize+renderConnSize); - y -= minRoomY*(renderRoomSize+renderConnSize); - - GlStateManager.pushMatrix(); - - GlStateManager.disableDepth(); - GlStateManager.enableBlend(); - GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); - - GlStateManager.translate(x, y, -0.02F); - GlStateManager.scale(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmIconScale, - NotEnoughUpdates.INSTANCE.config.dungeonMap.dmIconScale, 1); - GlStateManager.rotate(angle, 0.0F, 0.0F, 1.0F); - GlStateManager.translate(-0.5F, 0.5F, 0.0F); - - if(blackBorder) { - Gui.drawRect(-pixelWidth/2-1,-pixelHeight/2-1, pixelWidth/2+1, pixelHeight/2+1, 0xff111111); - GlStateManager.color(1, 1, 1, 1); - } - - worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX); - worldrenderer.pos(-pixelWidth/2f, pixelHeight/2f, 30+((float)k * -0.005F)).tex(minU, minV).endVertex(); - worldrenderer.pos(pixelWidth/2f, pixelHeight/2f, 30+((float)k * -0.005F)).tex(maxU, minV).endVertex(); - worldrenderer.pos(pixelWidth/2f, -pixelHeight/2f, 30+((float)k * -0.005F)).tex(maxU, maxV).endVertex(); - worldrenderer.pos(-pixelWidth/2f, -pixelHeight/2f, 30+((float)k * -0.005F)).tex(minU, maxV).endVertex(); - tessellator.draw(); - - if(headLayer) { - worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX); - worldrenderer.pos(-pixelWidth/2f, pixelHeight/2f, 30+((float)k * -0.005F)+0.001f).tex(minU+0.5f, minV).endVertex(); - worldrenderer.pos(pixelWidth/2f, pixelHeight/2f, 30+((float)k * -0.005F)+0.001f).tex(maxU+0.5f, minV).endVertex(); - worldrenderer.pos(pixelWidth/2f, -pixelHeight/2f, 30+((float)k * -0.005F)+0.001f).tex(maxU+0.5f, maxV).endVertex(); - worldrenderer.pos(-pixelWidth/2f, -pixelHeight/2f, 30+((float)k * -0.005F)+0.001f).tex(minU+0.5f, maxV).endVertex(); - tessellator.draw(); - } - GlStateManager.popMatrix(); - k--; - } - - if(useFb) { - GlStateManager.enableBlend(); - GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); - } else { - GL11.glDisable(GL11.GL_SCISSOR_TEST); - } - } GlStateManager.popMatrix(); - - if(useFb) { - Framebuffer renderFromBuffer = mapFramebuffer1; - if(useShd) { - GlStateManager.pushMatrix(); { - try { - upload(mapShader, mapSizeX, mapSizeY, scaleFactor, getBorderRadius()); - mapShader.setProjectionMatrix(projectionMatrix); - mapShader.loadShader(0); - renderFromBuffer = mapFramebuffer2; - } catch(Exception e) { - } - } GlStateManager.popMatrix(); - } - - Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true); - - Utils.pushGuiScale(2); - - GlStateManager.translate(centerX, centerY, 100); - - renderFromBuffer.bindFramebufferTexture(); - Utils.drawTexturedRect(-mapSizeX/2, -mapSizeY/2, mapSizeX, mapSizeY, - 0, 1, 1, 0, GL11.GL_NEAREST); - GlStateManager.bindTexture(0); - - GlStateManager.translate(-centerX, -centerY, -100); - - Utils.pushGuiScale(-1); - } - - GlStateManager.translate(centerX, centerY, 100); - - if(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmChromaBorder) { - int colour = SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderColour); - - Gui.drawRect(-mapCenterX-2, -mapCenterY-2, -mapCenterX, -mapCenterY, - colour); //topleft - Gui.drawRect(-mapCenterX-2, mapCenterY+2, -mapCenterX, mapCenterY, - SpecialColour.rotateHue(colour, -180)); //bottomleft - Gui.drawRect(mapCenterX, -mapCenterY-2, mapCenterX+2, mapCenterY, - SpecialColour.rotateHue(colour, -180)); //topright - Gui.drawRect(mapCenterX, mapCenterY, mapCenterX+2, mapCenterY+2, - colour); //bottomright - - for(int i=0; i<20; i++) { - int start1 = SpecialColour.rotateHue(colour, -9*i); - int start2 = SpecialColour.rotateHue(colour, -9*i-9); - int end1 = SpecialColour.rotateHue(colour, -180-9*i); - int end2 = SpecialColour.rotateHue(colour, -180-9*i-9); - - Utils.drawGradientRect(-mapCenterX-2, -mapCenterY+(int)(mapSizeY*(i/20f)), -mapCenterX, - -mapCenterY+(int)(mapSizeY*((i+1)/20f)), start1, start2); //left - Utils.drawGradientRect(mapCenterX, -mapCenterY+(int)(mapSizeX*(i/20f)), mapCenterX+2, - -mapCenterY+(int)(mapSizeX*((i+1)/20f)), - end1, end2); //right - Utils.drawGradientRectHorz(-mapCenterX+(int)(mapSizeX*(i/20f)), -mapCenterY-2, - -mapCenterX+(int)(mapSizeX*((i+1)/20f)), -mapCenterY, start1, start2); //top - Utils.drawGradientRectHorz(-mapCenterX+(int)(mapSizeX*(i/20f)), - mapCenterY, -mapCenterX+(int)(mapSizeX*((i+1)/20f)), mapCenterY+2, - end1, end2); //bottom - } - - } else { - Gui.drawRect(-mapCenterX-2, -mapCenterY, -mapCenterX, mapCenterY, - SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderColour)); //left - Gui.drawRect(mapCenterX, -mapCenterY, mapCenterX+2, mapCenterY, - SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderColour)); //right - Gui.drawRect(-mapCenterX-2, -mapCenterY-2, mapCenterX+2, -mapCenterY, - SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderColour)); //top - Gui.drawRect(-mapCenterX-2, mapCenterY, mapCenterX+2, mapCenterY+2, - SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderColour)); //bottom - } - - String sizeId = borderSizeOption == 0 ? "small" : borderSizeOption == 2 ? "large" : "medium"; - - ResourceLocation rl = new ResourceLocation("notenoughupdates:dungeon_map/borders/"+sizeId+"/"+ - NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderStyle+".png"); - if(Minecraft.getMinecraft().getTextureManager().getTexture(rl) != TextureUtil.missingTexture) { - Minecraft.getMinecraft().getTextureManager().bindTexture(rl); - GlStateManager.color(1, 1, 1, 1); - - int size = borderSizeOption == 0 ? 165 : borderSizeOption == 1 ? 220 : borderSizeOption == 2 ? 300 : 440; - Utils.drawTexturedRect(-size/2, -size/2, size, size, GL11.GL_NEAREST); - } - - GlStateManager.translate(-centerX, -centerY, -100); - } catch(Exception e) { - e.printStackTrace(); - Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true); - Minecraft.getMinecraft().entityRenderer.setupOverlayRendering(); - } - - Utils.pushGuiScale(-1); - - GlStateManager.enableBlend(); - GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); - GlStateManager.enableDepth(); - GlStateManager.disableLighting(); - } - - - public void updateRoomConnections(RoomOffset roomOffset) { - if(roomMap.containsKey(roomOffset)) { - Room room = roomMap.get(roomOffset); - - int otherPixelFilled = 0; - int otherPixelColour = 0; - for(int xOff=0; xOff 0 && y > 0 && x < colourMap.length && y < colourMap[x].length) { - Color c = colourMap[x][y]; - if(!c.equals(room.colour)) { - if(otherPixelColour == c.getRGB()) { - otherPixelFilled++; - } else { - otherPixelFilled--; - if(otherPixelFilled <= 0) { - otherPixelFilled = 1; - otherPixelColour = c.getRGB(); - } - } - } - } - } - } - - room.tickColour = 0; - if((float)otherPixelFilled/roomSize/connectorSize > 0.05) { - room.tickColour = otherPixelColour; - } - - for(int k=0; k<4; k++) { - Color colour = null; - int totalFilled = 0; - - for(int i=0; i 0 && y > 0 && x < colourMap.length && y < colourMap[x].length) { - Color pixel = colourMap[x][y]; - if(pixel.getAlpha() > 40) { - if(colour == null) { - colour = pixel; - totalFilled = 1; - } else { - if(colour.equals(pixel)) { - totalFilled++; - } else { - totalFilled--; - if(totalFilled <= 0) { - colour = pixel; - totalFilled = 1; - } - } - } - } - } - } - } - float proportionFilled = (float)totalFilled/roomSize/connectorSize; - - RoomConnectionType type = RoomConnectionType.WALL; - if(proportionFilled > 0.8) { - type = RoomConnectionType.ROOM_DIVIDER; - } else if(proportionFilled > 0.1) { - type = RoomConnectionType.CORRIDOR; - } - if(k == 0) { - room.up = new RoomConnection(type, colour); - } else if(k == 1) { - room.right = new RoomConnection(type, colour); - } else if(k == 2) { - room.down = new RoomConnection(type, colour); - } else { - room.left = new RoomConnection(type, colour); - } - } - - int x = startRoomX + roomOffset.x*(roomSize+connectorSize) + roomSize + connectorSize/2; - int y = startRoomY + roomOffset.y*(roomSize+connectorSize) + roomSize + connectorSize/2; - - room.fillCorner = false; - if(x > 0 && y > 0 && x < colourMap.length && y < colourMap[x].length) { - Color pixel = colourMap[x][y]; - if(pixel.equals(room.colour)) { - room.fillCorner = true; - } - } - } - } - - public void loadNeighbors(RoomOffset room) { - if(!roomMap.containsKey(room)) { - roomMap.put(room, new Room()); - } - for(RoomOffset neighbor : room.getNeighbors()) { - if(!roomMap.containsKey(neighbor)) { - int x = startRoomX + neighbor.x*(roomSize+connectorSize); - int y = startRoomY + neighbor.y*(roomSize+connectorSize); - - if(x >= 0 && y >= 0 && x+roomSize < colourMap.length && y+roomSize < colourMap[x].length) { - if(colourMap[x][y].getAlpha() > 100) { - roomMap.put(neighbor, new Room()); - loadNeighbors(neighbor); - } - } - } - } - } - - public void updateRoomColours() { - for(Map.Entry entry : roomMap.entrySet()) { - int x = startRoomX + entry.getKey().x*(roomSize+connectorSize); - int y = startRoomY + entry.getKey().y*(roomSize+connectorSize); - - try { - entry.getValue().colour = colourMap[x][y]; - } catch(Exception e) {} - } - } - - private class MapPosition { - public float roomOffsetX; - public float connOffsetX; - - public float roomOffsetY; - public float connOffsetY; - - public float rotation; - - public MapPosition(float roomOffsetX, float connOffsetX, float roomOffsetY, float connOffsetY) { - this.roomOffsetX = roomOffsetX; - this.connOffsetX = connOffsetX; - this.roomOffsetY = roomOffsetY; - this.connOffsetY = connOffsetY; - } - - public float getRenderX() { - return roomOffsetX*getRenderRoomSize() + connOffsetX*getRenderConnSize(); - } - - public float getRenderY() { - return roomOffsetY*getRenderRoomSize() + connOffsetY*getRenderConnSize(); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - MapPosition that = (MapPosition) o; - return Float.compare(that.roomOffsetX, roomOffsetX) == 0 && - Float.compare(that.connOffsetX, connOffsetX) == 0 && - Float.compare(that.roomOffsetY, roomOffsetY) == 0 && - Float.compare(that.connOffsetY, connOffsetY) == 0 && - Float.compare(that.rotation, rotation) == 0; - } - - @Override - public int hashCode() { - return Objects.hash(roomOffsetX, connOffsetX, roomOffsetY, connOffsetY, rotation); - } - } - - private boolean isFloorOne = false; - private boolean failMap = false; - private long lastClearCache = 0; - public void renderMap(int centerX, int centerY, Color[][] colourMap, Map mapDecorations, - int roomSizeBlocks, Set actualPlayers, boolean usePlayerPositions, float partialTicks) { - if(!NotEnoughUpdates.INSTANCE.config.dungeonMap.dmEnable) return; - if(colourMap == null) return; - if(colourMap.length != 128) return; - if(colourMap[0].length != 128) return; - this.colourMap = colourMap; - - boolean searchForPlayers = false; - if(System.currentTimeMillis() - lastClearCache > 1000) { - roomMap.clear(); - searchForPlayers = true; - startRoomX = -1; - startRoomY = -1; - connectorSize = -1; - roomSize = -1; - borderRadiusCache.clear(); - failMap = false; - - lastClearCache = System.currentTimeMillis(); - - isFloorOne = false; - Scoreboard scoreboard = Minecraft.getMinecraft().thePlayer.getWorldScoreboard(); - - ScoreObjective sidebarObjective = scoreboard.getObjectiveInDisplaySlot(1); - - List scores = new ArrayList<>(scoreboard.getSortedScores(sidebarObjective)); - - for(int i=scores.size()-1; i>=0; i--) { - Score score = scores.get(i); - ScorePlayerTeam scoreplayerteam1 = scoreboard.getPlayersTeam(score.getPlayerName()); - String line = ScorePlayerTeam.formatPlayerName(scoreplayerteam1, score.getPlayerName()); - line = Utils.cleanColour(line); - - if(line.contains("(F1)") || line.contains("(E)") || line.contains("(M1)")) { - isFloorOne = true; - break; - } - } - } - - if(failMap) { - return; - } - - int alphaPixels = 0; - for(int x=0; x<128; x++) { - for(int y=0; y<128; y++) { - Color c = colourMap[x][y]; - if(c == null) { - return; - } else if(c.getAlpha() < 50) { - alphaPixels++; - } - } - } - if(alphaPixels < 128*128/10) { - failMap = true; - return; - } - - if(startRoomX < 0 || startRoomY < 0 || roomSize <= 0) { - for(int x=0; x 80) { - if(startRoomX < 0 && startRoomY < 0 && c.getRed() == 0 && c.getGreen() == 124 && c.getBlue() == 0) { - roomSize = 0; - out: - for(int xd=0; xd<=20; xd++) { - for(int yd=0; yd<=20; yd++) { - if(x+xd >= colourMap.length || y+yd >= colourMap[x+xd].length) continue; - Color c2 = colourMap[x+xd][y+yd]; - - if(c2.getGreen() != 124 || c2.getAlpha() <= 80) { - if(xd < 10 && yd < 10) { - break out; - } - } else { - roomSize = Math.max(roomSize, Math.min(xd+1, yd+1)); - } - if(xd == 20 && yd == 20) { - if(roomSize == 0) roomSize = 20; - startRoomX = x; - startRoomY = y; - } - } - } - } - } - } - } - } - - if(startRoomX < 0 || startRoomY < 0) { - failMap = true; - return; - } - - if(connectorSize <= 0) { - for(int i=0; i 0 && y > 0 && x < colourMap.length && y < colourMap[x].length) { - if(colourMap[x][y].getAlpha() > 80) { - if(j == 1) { - break; - } - connectorSize = Math.min(connectorSize, j-1); - } - } - } - } - } - - if(connectorSize <= 0) { - connectorSize = 4; - } - } - - actualPlayers.add(Minecraft.getMinecraft().thePlayer.getName()); - if(searchForPlayers) { - for(EntityPlayer player : Minecraft.getMinecraft().theWorld.playerEntities) { - if(player instanceof AbstractClientPlayer && actualPlayers.contains(player.getName())) { - AbstractClientPlayer aplayer = (AbstractClientPlayer) player; - ResourceLocation skin = aplayer.getLocationSkin(); - if(skin != DefaultPlayerSkin.getDefaultSkin(aplayer.getUniqueID())) { - playerSkinMap.put(player.getName(), skin); - playerIdMap.put(player.getName(), player.getEntityId()); - } - } - } - } - - playerEntityMapPositions.clear(); - if(usePlayerPositions) { - for(String playerName : actualPlayers) { - if(playerIdMap.containsKey(playerName)) { - Entity entity = Minecraft.getMinecraft().theWorld.getEntityByID(playerIdMap.get(playerName)); - if(entity instanceof EntityPlayer) { - EntityPlayer player = (EntityPlayer) entity; - - float roomX = (float)player.posX / (roomSizeBlocks+1); - float roomY = (float)player.posZ / (roomSizeBlocks+1); - - float playerRoomOffsetX = (float) Math.floor(roomX); - float playerConnOffsetX = (float) Math.floor(roomX); - float playerRoomOffsetY = (float) Math.floor(roomY); - float playerConnOffsetY = (float) Math.floor(roomY); - - float roomXInBlocks = (float)player.posX % (roomSizeBlocks+1); - if(roomXInBlocks < 2) { //0,1 - playerConnOffsetX -= 2/5f-roomXInBlocks/5f; - } else if(roomXInBlocks > roomSizeBlocks-2) { //31,30,29 - playerRoomOffsetX++; - playerConnOffsetX += (roomXInBlocks - (roomSizeBlocks-2))/5f; - } else { - playerRoomOffsetX += (roomXInBlocks-2) / (roomSizeBlocks-4); - } - - float roomYInBlocks = (float)player.posZ % (roomSizeBlocks+1); - if(roomYInBlocks < 2) { //0,1 - playerConnOffsetY -= 2/5f-roomYInBlocks/5f; - } else if(roomYInBlocks > roomSizeBlocks-2) { //31,30,29 - playerRoomOffsetY++; - playerConnOffsetY += (roomYInBlocks - (roomSizeBlocks-2))/5f; - } else { - playerRoomOffsetY += (roomYInBlocks-2) / (roomSizeBlocks-4); - } - - playerRoomOffsetX -= startRoomX/(roomSize+connectorSize); - playerRoomOffsetY -= startRoomY/(roomSize+connectorSize); - playerConnOffsetX -= startRoomX/(roomSize+connectorSize); - playerConnOffsetY -= startRoomY/(roomSize+connectorSize); - - MapPosition pos = new MapPosition(playerRoomOffsetX, playerConnOffsetX, playerRoomOffsetY, playerConnOffsetY); - pos.rotation = (player.prevRotationYawHead + (player.rotationYawHead-player.prevRotationYawHead)*partialTicks) % 360; - if(pos.rotation < 0) pos.rotation += 360; - playerEntityMapPositions.put(player.getName(), pos); - } - } - } - } - - loadNeighbors(new RoomOffset(0, 0)); - updateRoomColours(); - for(RoomOffset offset : roomMap.keySet()) { - updateRoomConnections(offset); - } - - if(roomMap.isEmpty()) { - failMap = true; - return; - } - - if(mapDecorations != null && mapDecorations.size() > 0) { - List positions = new ArrayList<>(); - int decorations = 0; - for (Vec4b vec4b : mapDecorations.values()) { - byte id = vec4b.func_176110_a(); - if(id != 1 && id != 3) continue; - - float x = (float) vec4b.func_176112_b() / 2.0F + 64.0F; - float y = (float) vec4b.func_176113_c() / 2.0F + 64.0F; - - if(x < 0 || y < 0 || x > 128 || y > 128) { - continue; - } - - float deltaX = x - startRoomX; - float deltaY = y - startRoomY; - - float roomsOffsetX = (int) Math.floor(deltaX / (roomSize + connectorSize)); - float connOffsetX = (int) Math.floor(deltaX / (roomSize + connectorSize)); - float xRemainder = deltaX % (roomSize + connectorSize); - if (Math.abs(xRemainder) > roomSize) { - roomsOffsetX += Math.copySign(1, xRemainder); - connOffsetX += Math.copySign(1, xRemainder) * (Math.abs(xRemainder) - roomSize) / connectorSize; - } else { - roomsOffsetX += xRemainder / roomSize; - } - if (deltaX < 0 && xRemainder != 0) { - roomsOffsetX++; - connOffsetX++; - } - float roomsOffsetY = (int) Math.floor(deltaY / (roomSize + connectorSize)); - float connOffsetY = (int) Math.floor(deltaY / (roomSize + connectorSize)); - float yRemainder = deltaY % (roomSize + connectorSize); - if (Math.abs(yRemainder) > roomSize) { - roomsOffsetY += Math.copySign(1, yRemainder); - connOffsetY += Math.copySign(1, yRemainder) * (Math.abs(yRemainder) - roomSize) / connectorSize; - } else { - roomsOffsetY += yRemainder / roomSize; - } - if (deltaY < 0 && yRemainder != 0) { - roomsOffsetY++; - connOffsetY++; - } - - float angle = (float) (vec4b.func_176111_d() * 360) / 16.0F; - - MapPosition pos = new MapPosition(roomsOffsetX, connOffsetX, roomsOffsetY, connOffsetY); - pos.rotation = angle % 360; - if(pos.rotation < 0) pos.rotation += 360; - - if(decorations++ <= 6) { - positions.add(pos); - } - rawPlayerMarkerMapPositions.add(pos); - } - - boolean different = playerMarkerMapPositions.size() != positions.size(); - - if (!different) { - for (MapPosition pos : playerMarkerMapPositions.values()) { - if (!positions.contains(pos)) { - different = true; - break; - } - } - } - - if(different && positions.size() > 0) { - lastLastDecorationsMillis = lastDecorationsMillis; - lastDecorationsMillis = System.currentTimeMillis(); - - playerMarkerMapPositionsLast.clear(); - for (Map.Entry entry : playerMarkerMapPositions.entrySet()) { - playerMarkerMapPositionsLast.put(entry.getKey(), entry.getValue()); - } - playerMarkerMapPositions.clear(); - - Set foundPlayers = new HashSet<>(); - for (Map.Entry entry : playerEntityMapPositions.entrySet()) { - playerMarkerMapPositions.put(entry.getKey(), entry.getValue()); - playerMarkerMapPositionsLast.put(entry.getKey(), entry.getValue()); - foundPlayers.add(entry.getKey()); - } - - HashMap> distanceMap = new HashMap<>(); - for (Map.Entry entry : playerMarkerMapPositionsLast.entrySet()) { - HashMap deltaDists = new HashMap<>(); - for (int i = 0; i < positions.size(); i++) { - float dx = entry.getValue().getRenderX() - positions.get(i).getRenderX(); - float dy = entry.getValue().getRenderY() - positions.get(i).getRenderY(); - deltaDists.put(i, dx * dx + dy * dy); - } - distanceMap.put(entry.getKey(), deltaDists); - } - - List playerList = new ArrayList<>(playerMarkerMapPositionsLast.keySet()); - List> playerPermutations = permutations(playerList); - - List finalUsedIndexes = new ArrayList<>(); - if (playerPermutations.size() > 0) { - HashMap smallestPermutation = null; - float smallestTotalDistance = 0; - - for (List permutation : playerPermutations) { - HashMap usedIndexes = new HashMap<>(); - - float totalDistance = 0; - for (String player : permutation) { - int smallestIndex = -1; - float smallestDist = 0; - for (Map.Entry entry : distanceMap.get(player).entrySet()) { - if (!usedIndexes.containsValue(entry.getKey())) { - if (smallestIndex == -1 || entry.getValue() < smallestDist) { - smallestIndex = entry.getKey(); - smallestDist = entry.getValue(); - } - } - } - if (smallestIndex != -1) { - usedIndexes.put(player, smallestIndex); - totalDistance += smallestDist; - } - } - - if (smallestPermutation == null || totalDistance < smallestTotalDistance) { - smallestPermutation = usedIndexes; - smallestTotalDistance = totalDistance; - } - } - - //System.out.println("--- PERM START ---"); - for (Map.Entry entry : smallestPermutation.entrySet()) { - //System.out.println(entry.getKey() + ":" + entry.getValue() + " : Total dist: " + smallestTotalDistance); - finalUsedIndexes.add(entry.getValue()); - playerMarkerMapPositions.put(entry.getKey(), positions.get(entry.getValue())); - } - } - - List nonUsedIndexes = new ArrayList<>(); - for(int i=0; i entry : playerEntityMapPositions.entrySet()) { - playerMarkerMapPositions.put(entry.getKey(), entry.getValue()); - } - } - - if(!roomMap.isEmpty() && startRoomX >= 0 && startRoomY >= 0) { - render(centerX, centerY); - } - - this.colourMap = colourMap; - } - - @SubscribeEvent - public void onWorldChange(WorldEvent.Load event) { - colourMap = null; - } - - @SubscribeEvent - public void onRenderOverlay(RenderGameOverlayEvent.Post event) { - if(!NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) return; - if(event.type == RenderGameOverlayEvent.ElementType.ALL) { - if(!NotEnoughUpdates.INSTANCE.config.dungeonMap.dmEnable) return; - - if(Minecraft.getMinecraft().gameSettings.showDebugInfo || - (Minecraft.getMinecraft().gameSettings.keyBindPlayerList.isKeyDown() && - (!Minecraft.getMinecraft().isIntegratedServerRunning() || - Minecraft.getMinecraft().thePlayer.sendQueue.getPlayerInfoMap().size() > 1))) { - return; - } - - ItemStack stack = Minecraft.getMinecraft().thePlayer.inventory.mainInventory[8]; - boolean holdingBow = stack != null && stack.getItem() == Items.arrow && colourMap != null; - if(holdingBow || (stack != null && stack.getItem() instanceof ItemMap)) { - Map decorations = null; - - Color[][] colourMap = new Color[128][128]; - if(holdingBow) { - for(int x=0; x<128; x++) { - for(int y=0; y<128; y++) { - if(this.colourMap[x][y] != null) { - colourMap[x][y] = this.colourMap[x][y]; - } else { - colourMap[x][y] = new Color(0, true); - } - } - } - } else { - ItemMap map = (ItemMap) stack.getItem(); - MapData mapData = map.getMapData(stack, Minecraft.getMinecraft().theWorld); - - if(mapData == null) return; - - decorations = mapData.mapDecorations; - - for (int i = 0; i < 16384; ++i) { - int x = i % 128; - int y = i / 128; - - int j = mapData.colors[i] & 255; - - Color c; - if (j / 4 == 0) { - c = new Color((i + i / 128 & 1) * 8 + 16 << 24, true); - } else { - c = new Color(MapColor.mapColorArray[j / 4].getMapColor(j & 3), true); - } - - colourMap[x][y] = c; - } - } - - int roomSizeBlocks = 31; + x += deltaX; + y += deltaY; + + doInterp = false; + } + + float minU = 3 / 4f; + float minV = 0; + + if (name.equals(Minecraft.getMinecraft().thePlayer.getName())) { + minU = 1 / 4f; + } + + float maxU = minU + 1 / 4f; + float maxV = minV + 1 / 4f; + + if (doInterp && playerMarkerMapPositionsLast.containsKey(name)) { + MapPosition last = playerMarkerMapPositionsLast.get(name); + float xLast = last.getRenderX(); + float yLast = last.getRenderY(); + + float distSq = (x - xLast) * (x - xLast) + (y - yLast) * (y - yLast); + if (distSq < renderRoomSize * renderRoomSize / 4f) { + float angleLast = last.rotation; + if (angle > 180 && angleLast < 180) angleLast += 360; + if (angleLast > 180 && angle < 180) angle += 360; + + float interpFactor = Math.round((System.currentTimeMillis() - lastDecorationsMillis) * 100f) / 100f / + (lastDecorationsMillis - lastLastDecorationsMillis); + interpFactor = Math.max(0, Math.min(1, interpFactor)); + + x = xLast + (x - xLast) * interpFactor; + y = yLast + (y - yLast) * interpFactor; + angle = angleLast + (angle - angleLast) * interpFactor; + angle %= 360; + } + } + + boolean blackBorder = false; + boolean headLayer = false; + int pixelWidth = 8; + int pixelHeight = 8; + if (renderRoomSize >= 24) { + pixelWidth = pixelHeight = 12; + } + GlStateManager.color(1, 1, 1, 1); + if ((!NotEnoughUpdates.INSTANCE.config.dungeons.showOwnHeadAsMarker || + playerMarkerMapPositions.size() <= 1 || minU != 1 / 4f) && + NotEnoughUpdates.INSTANCE.config.dungeonMap.dmPlayerHeads >= 1 && + playerSkinMap.containsKey(entry.getKey())) { + Minecraft.getMinecraft().getTextureManager().bindTexture(playerSkinMap.get(entry.getKey())); + + minU = 8 / 64f; + minV = 8 / 64f; + maxU = 16 / 64f; + maxV = 16 / 64f; + + headLayer = true; + if (NotEnoughUpdates.INSTANCE.config.dungeonMap.dmPlayerHeads >= 2) { + blackBorder = true; + } + } else { + Minecraft.getMinecraft().getTextureManager().bindTexture(mapIcons); + } + + x -= minRoomX * (renderRoomSize + renderConnSize); + y -= minRoomY * (renderRoomSize + renderConnSize); + + GlStateManager.pushMatrix(); + + GlStateManager.disableDepth(); + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate( + GL11.GL_SRC_ALPHA, + GL11.GL_ONE_MINUS_SRC_ALPHA, + GL11.GL_ONE, + GL11.GL_ONE_MINUS_SRC_ALPHA + ); + + GlStateManager.translate(x, y, -0.02F); + GlStateManager.scale(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmIconScale, + NotEnoughUpdates.INSTANCE.config.dungeonMap.dmIconScale, 1 + ); + GlStateManager.rotate(angle, 0.0F, 0.0F, 1.0F); + GlStateManager.translate(-0.5F, 0.5F, 0.0F); + + if (blackBorder) { + Gui.drawRect( + -pixelWidth / 2 - 1, + -pixelHeight / 2 - 1, + pixelWidth / 2 + 1, + pixelHeight / 2 + 1, + 0xff111111 + ); + GlStateManager.color(1, 1, 1, 1); + } + + worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX); + worldrenderer.pos(-pixelWidth / 2f, pixelHeight / 2f, 30 + ((float) k * -0.005F)).tex(minU, minV).endVertex(); + worldrenderer.pos(pixelWidth / 2f, pixelHeight / 2f, 30 + ((float) k * -0.005F)).tex(maxU, minV).endVertex(); + worldrenderer.pos(pixelWidth / 2f, -pixelHeight / 2f, 30 + ((float) k * -0.005F)).tex(maxU, maxV).endVertex(); + worldrenderer + .pos(-pixelWidth / 2f, -pixelHeight / 2f, 30 + ((float) k * -0.005F)) + .tex(minU, maxV) + .endVertex(); + tessellator.draw(); + + if (headLayer) { + worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX); + worldrenderer.pos(-pixelWidth / 2f, pixelHeight / 2f, 30 + ((float) k * -0.005F) + 0.001f).tex( + minU + 0.5f, + minV + ).endVertex(); + worldrenderer.pos(pixelWidth / 2f, pixelHeight / 2f, 30 + ((float) k * -0.005F) + 0.001f).tex( + maxU + 0.5f, + minV + ).endVertex(); + worldrenderer.pos(pixelWidth / 2f, -pixelHeight / 2f, 30 + ((float) k * -0.005F) + 0.001f).tex( + maxU + 0.5f, + maxV + ).endVertex(); + worldrenderer.pos(-pixelWidth / 2f, -pixelHeight / 2f, 30 + ((float) k * -0.005F) + 0.001f).tex( + minU + 0.5f, + maxV + ).endVertex(); + tessellator.draw(); + } + GlStateManager.popMatrix(); + k--; + } + + if (useFb) { + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate( + GL11.GL_SRC_ALPHA, + GL11.GL_ONE_MINUS_SRC_ALPHA, + GL11.GL_ONE, + GL11.GL_ONE_MINUS_SRC_ALPHA + ); + } else { + GL11.glDisable(GL11.GL_SCISSOR_TEST); + } + } + GlStateManager.popMatrix(); + + if (useFb) { + Framebuffer renderFromBuffer = mapFramebuffer1; + if (useShd) { + GlStateManager.pushMatrix(); + { + try { + upload(mapShader, mapSizeX, mapSizeY, scaleFactor, getBorderRadius()); + mapShader.setProjectionMatrix(projectionMatrix); + mapShader.loadShader(0); + renderFromBuffer = mapFramebuffer2; + } catch (Exception ignored) { + } + } + GlStateManager.popMatrix(); + } + + Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true); + + Utils.pushGuiScale(2); + + GlStateManager.translate(centerX, centerY, 100); + + renderFromBuffer.bindFramebufferTexture(); + Utils.drawTexturedRect(-mapSizeX / 2, -mapSizeY / 2, mapSizeX, mapSizeY, + 0, 1, 1, 0, GL11.GL_NEAREST + ); + GlStateManager.bindTexture(0); + + GlStateManager.translate(-centerX, -centerY, -100); + + Utils.pushGuiScale(-1); + } + + GlStateManager.translate(centerX, centerY, 100); + + if (NotEnoughUpdates.INSTANCE.config.dungeonMap.dmChromaBorder) { + int colour = SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderColour); + + Gui.drawRect(-mapCenterX - 2, -mapCenterY - 2, -mapCenterX, -mapCenterY, + colour + ); //topleft + Gui.drawRect(-mapCenterX - 2, mapCenterY + 2, -mapCenterX, mapCenterY, + SpecialColour.rotateHue(colour, -180) + ); //bottomleft + Gui.drawRect(mapCenterX, -mapCenterY - 2, mapCenterX + 2, mapCenterY, + SpecialColour.rotateHue(colour, -180) + ); //topright + Gui.drawRect(mapCenterX, mapCenterY, mapCenterX + 2, mapCenterY + 2, + colour + ); //bottomright + + for (int i = 0; i < 20; i++) { + int start1 = SpecialColour.rotateHue(colour, -9 * i); + int start2 = SpecialColour.rotateHue(colour, -9 * i - 9); + int end1 = SpecialColour.rotateHue(colour, -180 - 9 * i); + int end2 = SpecialColour.rotateHue(colour, -180 - 9 * i - 9); + + Utils.drawGradientRect(-mapCenterX - 2, -mapCenterY + (int) (mapSizeY * (i / 20f)), -mapCenterX, + -mapCenterY + (int) (mapSizeY * ((i + 1) / 20f)), start1, start2 + ); //left + Utils.drawGradientRect(mapCenterX, -mapCenterY + (int) (mapSizeX * (i / 20f)), mapCenterX + 2, + -mapCenterY + (int) (mapSizeX * ((i + 1) / 20f)), + end1, end2 + ); //right + Utils.drawGradientRectHorz(-mapCenterX + (int) (mapSizeX * (i / 20f)), -mapCenterY - 2, + -mapCenterX + (int) (mapSizeX * ((i + 1) / 20f)), -mapCenterY, start1, start2 + ); //top + Utils.drawGradientRectHorz(-mapCenterX + (int) (mapSizeX * (i / 20f)), + mapCenterY, -mapCenterX + (int) (mapSizeX * ((i + 1) / 20f)), mapCenterY + 2, + end1, end2 + ); //bottom + } + + } else { + Gui.drawRect(-mapCenterX - 2, -mapCenterY, -mapCenterX, mapCenterY, + SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderColour) + ); //left + Gui.drawRect(mapCenterX, -mapCenterY, mapCenterX + 2, mapCenterY, + SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderColour) + ); //right + Gui.drawRect(-mapCenterX - 2, -mapCenterY - 2, mapCenterX + 2, -mapCenterY, + SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderColour) + ); //top + Gui.drawRect(-mapCenterX - 2, mapCenterY, mapCenterX + 2, mapCenterY + 2, + SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderColour) + ); //bottom + } + + String sizeId = borderSizeOption == 0 ? "small" : borderSizeOption == 2 ? "large" : "medium"; + + ResourceLocation rl = new ResourceLocation("notenoughupdates:dungeon_map/borders/" + sizeId + "/" + + NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderStyle + ".png"); + if (Minecraft.getMinecraft().getTextureManager().getTexture(rl) != TextureUtil.missingTexture) { + Minecraft.getMinecraft().getTextureManager().bindTexture(rl); + GlStateManager.color(1, 1, 1, 1); + + int size = borderSizeOption == 0 ? 165 : borderSizeOption == 1 ? 220 : borderSizeOption == 2 ? 300 : 440; + Utils.drawTexturedRect(-size / 2, -size / 2, size, size, GL11.GL_NEAREST); + } + + GlStateManager.translate(-centerX, -centerY, -100); + } catch (Exception e) { + e.printStackTrace(); + Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true); + Minecraft.getMinecraft().entityRenderer.setupOverlayRendering(); + } + + Utils.pushGuiScale(-1); + + GlStateManager.enableBlend(); + GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); + GlStateManager.enableDepth(); + GlStateManager.disableLighting(); + } + + public void updateRoomConnections(RoomOffset roomOffset) { + if (roomMap.containsKey(roomOffset)) { + Room room = roomMap.get(roomOffset); + + int otherPixelFilled = 0; + int otherPixelColour = 0; + for (int xOff = 0; xOff < roomSize; xOff++) { + for (int yOff = 0; yOff < roomSize; yOff++) { + int x = startRoomX + roomOffset.x * (roomSize + connectorSize) + xOff; + int y = startRoomY + roomOffset.y * (roomSize + connectorSize) + yOff; + + if (x > 0 && y > 0 && x < colourMap.length && y < colourMap[x].length) { + Color c = colourMap[x][y]; + if (!c.equals(room.colour)) { + if (otherPixelColour == c.getRGB()) { + otherPixelFilled++; + } else { + otherPixelFilled--; + if (otherPixelFilled <= 0) { + otherPixelFilled = 1; + otherPixelColour = c.getRGB(); + } + } + } + } + } + } + + room.tickColour = 0; + if ((float) otherPixelFilled / roomSize / connectorSize > 0.05) { + room.tickColour = otherPixelColour; + } + + for (int k = 0; k < 4; k++) { + Color colour = null; + int totalFilled = 0; + + for (int i = 0; i < roomSize; i++) { + for (int j = 1; j <= connectorSize; j++) { + int x = startRoomX + roomOffset.x * (roomSize + connectorSize); + int y = startRoomY + roomOffset.y * (roomSize + connectorSize); + + if (k == 0) { + x += i; + y -= j; + } else if (k == 1) { + x += roomSize + j - 1; + y += i; + } else if (k == 2) { + x += i; + y += roomSize + j - 1; + } else { + x -= j; + y += i; + } + + if (x > 0 && y > 0 && x < colourMap.length && y < colourMap[x].length) { + Color pixel = colourMap[x][y]; + if (pixel.getAlpha() > 40) { + if (colour == null) { + colour = pixel; + totalFilled = 1; + } else { + if (colour.equals(pixel)) { + totalFilled++; + } else { + totalFilled--; + if (totalFilled <= 0) { + colour = pixel; + totalFilled = 1; + } + } + } + } + } + } + } + float proportionFilled = (float) totalFilled / roomSize / connectorSize; + + RoomConnectionType type = RoomConnectionType.WALL; + if (proportionFilled > 0.8) { + type = RoomConnectionType.ROOM_DIVIDER; + } else if (proportionFilled > 0.1) { + type = RoomConnectionType.CORRIDOR; + } + if (k == 0) { + room.up = new RoomConnection(type, colour); + } else if (k == 1) { + room.right = new RoomConnection(type, colour); + } else if (k == 2) { + room.down = new RoomConnection(type, colour); + } else { + room.left = new RoomConnection(type, colour); + } + } + + int x = startRoomX + roomOffset.x * (roomSize + connectorSize) + roomSize + connectorSize / 2; + int y = startRoomY + roomOffset.y * (roomSize + connectorSize) + roomSize + connectorSize / 2; + + room.fillCorner = false; + if (x > 0 && y > 0 && x < colourMap.length && y < colourMap[x].length) { + Color pixel = colourMap[x][y]; + if (pixel.equals(room.colour)) { + room.fillCorner = true; + } + } + } + } + + public void loadNeighbors(RoomOffset room) { + if (!roomMap.containsKey(room)) { + roomMap.put(room, new Room()); + } + for (RoomOffset neighbor : room.getNeighbors()) { + if (!roomMap.containsKey(neighbor)) { + int x = startRoomX + neighbor.x * (roomSize + connectorSize); + int y = startRoomY + neighbor.y * (roomSize + connectorSize); + + if (x >= 0 && y >= 0 && x + roomSize < colourMap.length && y + roomSize < colourMap[x].length) { + if (colourMap[x][y].getAlpha() > 100) { + roomMap.put(neighbor, new Room()); + loadNeighbors(neighbor); + } + } + } + } + } + + public void updateRoomColours() { + for (Map.Entry entry : roomMap.entrySet()) { + int x = startRoomX + entry.getKey().x * (roomSize + connectorSize); + int y = startRoomY + entry.getKey().y * (roomSize + connectorSize); + + try { + entry.getValue().colour = colourMap[x][y]; + } catch (Exception ignored) { + } + } + } + + private class MapPosition { + public float roomOffsetX; + public float connOffsetX; + + public float roomOffsetY; + public float connOffsetY; + + public float rotation; + + public MapPosition(float roomOffsetX, float connOffsetX, float roomOffsetY, float connOffsetY) { + this.roomOffsetX = roomOffsetX; + this.connOffsetX = connOffsetX; + this.roomOffsetY = roomOffsetY; + this.connOffsetY = connOffsetY; + } + + public float getRenderX() { + return roomOffsetX * getRenderRoomSize() + connOffsetX * getRenderConnSize(); + } + + public float getRenderY() { + return roomOffsetY * getRenderRoomSize() + connOffsetY * getRenderConnSize(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + MapPosition that = (MapPosition) o; + return Float.compare(that.roomOffsetX, roomOffsetX) == 0 && + Float.compare(that.connOffsetX, connOffsetX) == 0 && + Float.compare(that.roomOffsetY, roomOffsetY) == 0 && + Float.compare(that.connOffsetY, connOffsetY) == 0 && + Float.compare(that.rotation, rotation) == 0; + } + + @Override + public int hashCode() { + return Objects.hash(roomOffsetX, connOffsetX, roomOffsetY, connOffsetY, rotation); + } + } + + private boolean isFloorOne = false; + private boolean failMap = false; + private long lastClearCache = 0; + + public void renderMap( + int centerX, int centerY, Color[][] colourMap, Map mapDecorations, + int roomSizeBlocks, Set actualPlayers, boolean usePlayerPositions, float partialTicks + ) { + if (!NotEnoughUpdates.INSTANCE.config.dungeonMap.dmEnable) return; + if (colourMap == null) return; + if (colourMap.length != 128) return; + if (colourMap[0].length != 128) return; + this.colourMap = colourMap; + + boolean searchForPlayers = false; + if (System.currentTimeMillis() - lastClearCache > 1000) { + roomMap.clear(); + searchForPlayers = true; + startRoomX = -1; + startRoomY = -1; + connectorSize = -1; + roomSize = -1; + borderRadiusCache.clear(); + failMap = false; + + lastClearCache = System.currentTimeMillis(); + + isFloorOne = false; + Scoreboard scoreboard = Minecraft.getMinecraft().thePlayer.getWorldScoreboard(); + + ScoreObjective sidebarObjective = scoreboard.getObjectiveInDisplaySlot(1); + + List scores = new ArrayList<>(scoreboard.getSortedScores(sidebarObjective)); + + for (int i = scores.size() - 1; i >= 0; i--) { + Score score = scores.get(i); + ScorePlayerTeam scoreplayerteam1 = scoreboard.getPlayersTeam(score.getPlayerName()); + String line = ScorePlayerTeam.formatPlayerName(scoreplayerteam1, score.getPlayerName()); + line = Utils.cleanColour(line); + + if (line.contains("(F1)") || line.contains("(E0)") || line.contains("(M1)")) { + isFloorOne = true; + break; + } + } + } + + if (failMap) { + return; + } + + int alphaPixels = 0; + for (int x = 0; x < 128; x++) { + for (int y = 0; y < 128; y++) { + Color c = colourMap[x][y]; + if (c == null) { + return; + } else if (c.getAlpha() < 50) { + alphaPixels++; + } + } + } + if (alphaPixels < 128 * 128 / 10) { + failMap = true; + return; + } + + if (startRoomX < 0 || startRoomY < 0 || roomSize <= 0) { + for (int x = 0; x < colourMap.length; x++) { + for (int y = 0; y < colourMap[x].length; y++) { + Color c = colourMap[x][y]; + if (c.getAlpha() > 80) { + if (startRoomX < 0 && startRoomY < 0 && c.getRed() == 0 && c.getGreen() == 124 && c.getBlue() == 0) { + roomSize = 0; + out: + for (int xd = 0; xd <= 20; xd++) { + for (int yd = 0; yd <= 20; yd++) { + if (x + xd >= colourMap.length || y + yd >= colourMap[x + xd].length) continue; + Color c2 = colourMap[x + xd][y + yd]; + + if (c2.getGreen() != 124 || c2.getAlpha() <= 80) { + if (xd < 10 && yd < 10) { + break out; + } + } else { + roomSize = Math.max(roomSize, Math.min(xd + 1, yd + 1)); + } + if (xd == 20 && yd == 20) { + if (roomSize == 0) roomSize = 20; + startRoomX = x; + startRoomY = y; + } + } + } + } + } + } + } + } + + if (startRoomX < 0 || startRoomY < 0) { + failMap = true; + return; + } + + if (connectorSize <= 0) { + for (int i = 0; i < roomSize; i++) { + for (int k = 0; k < 4; k++) { + for (int j = 1; j < 8; j++) { + int x; + int y; + + if (k == 0) { + x = startRoomX + i; + y = startRoomY - j; + } else if (k == 1) { + x = startRoomX + roomSize + j - 1; + y = startRoomY + i; + } else if (k == 2) { + x = startRoomX + i; + y = startRoomY + roomSize + j - 1; + } else { + x = startRoomX - j; + y = startRoomY + i; + } + + if (x > 0 && y > 0 && x < colourMap.length && y < colourMap[x].length) { + if (colourMap[x][y].getAlpha() > 80) { + if (j == 1) { + break; + } + connectorSize = Math.min(connectorSize, j - 1); + } + } + } + } + } + + if (connectorSize <= 0) { + connectorSize = 4; + } + } + + actualPlayers.add(Minecraft.getMinecraft().thePlayer.getName()); + if (searchForPlayers) { + for (EntityPlayer player : Minecraft.getMinecraft().theWorld.playerEntities) { + if (player instanceof AbstractClientPlayer && actualPlayers.contains(player.getName())) { + AbstractClientPlayer aplayer = (AbstractClientPlayer) player; + ResourceLocation skin = aplayer.getLocationSkin(); + if (skin != DefaultPlayerSkin.getDefaultSkin(aplayer.getUniqueID())) { + playerSkinMap.put(player.getName(), skin); + playerIdMap.put(player.getName(), player.getEntityId()); + } + } + } + } + + playerEntityMapPositions.clear(); + if (usePlayerPositions) { + for (String playerName : actualPlayers) { + if (playerIdMap.containsKey(playerName)) { + Entity entity = Minecraft.getMinecraft().theWorld.getEntityByID(playerIdMap.get(playerName)); + if (entity instanceof EntityPlayer) { + EntityPlayer player = (EntityPlayer) entity; + + float roomX = (float) player.posX / (roomSizeBlocks + 1); + float roomY = (float) player.posZ / (roomSizeBlocks + 1); + + float playerRoomOffsetX = (float) Math.floor(roomX); + float playerConnOffsetX = (float) Math.floor(roomX); + float playerRoomOffsetY = (float) Math.floor(roomY); + float playerConnOffsetY = (float) Math.floor(roomY); + + float roomXInBlocks = (float) player.posX % (roomSizeBlocks + 1); + if (roomXInBlocks < 2) { //0,1 + playerConnOffsetX -= 2 / 5f - roomXInBlocks / 5f; + } else if (roomXInBlocks > roomSizeBlocks - 2) { //31,30,29 + playerRoomOffsetX++; + playerConnOffsetX += (roomXInBlocks - (roomSizeBlocks - 2)) / 5f; + } else { + playerRoomOffsetX += (roomXInBlocks - 2) / (roomSizeBlocks - 4); + } + + float roomYInBlocks = (float) player.posZ % (roomSizeBlocks + 1); + if (roomYInBlocks < 2) { //0,1 + playerConnOffsetY -= 2 / 5f - roomYInBlocks / 5f; + } else if (roomYInBlocks > roomSizeBlocks - 2) { //31,30,29 + playerRoomOffsetY++; + playerConnOffsetY += (roomYInBlocks - (roomSizeBlocks - 2)) / 5f; + } else { + playerRoomOffsetY += (roomYInBlocks - 2) / (roomSizeBlocks - 4); + } + + playerRoomOffsetX -= startRoomX / (roomSize + connectorSize); + playerRoomOffsetY -= startRoomY / (roomSize + connectorSize); + playerConnOffsetX -= startRoomX / (roomSize + connectorSize); + playerConnOffsetY -= startRoomY / (roomSize + connectorSize); + + MapPosition pos = new MapPosition( + playerRoomOffsetX, + playerConnOffsetX, + playerRoomOffsetY, + playerConnOffsetY + ); + pos.rotation = + (player.prevRotationYawHead + (player.rotationYawHead - player.prevRotationYawHead) * partialTicks) % 360; + if (pos.rotation < 0) pos.rotation += 360; + playerEntityMapPositions.put(player.getName(), pos); + } + } + } + } + + loadNeighbors(new RoomOffset(0, 0)); + updateRoomColours(); + for (RoomOffset offset : roomMap.keySet()) { + updateRoomConnections(offset); + } + + if (roomMap.isEmpty()) { + failMap = true; + return; + } + + if (mapDecorations != null && mapDecorations.size() > 0) { + List positions = new ArrayList<>(); + int decorations = 0; + for (Vec4b vec4b : mapDecorations.values()) { + byte id = vec4b.func_176110_a(); + if (id != 1 && id != 3) continue; + + float x = (float) vec4b.func_176112_b() / 2.0F + 64.0F; + float y = (float) vec4b.func_176113_c() / 2.0F + 64.0F; + + if (x < 0 || y < 0 || x > 128 || y > 128) { + continue; + } + + float deltaX = x - startRoomX; + float deltaY = y - startRoomY; + + float roomsOffsetX = (int) Math.floor(deltaX / (roomSize + connectorSize)); + float connOffsetX = (int) Math.floor(deltaX / (roomSize + connectorSize)); + float xRemainder = deltaX % (roomSize + connectorSize); + if (Math.abs(xRemainder) > roomSize) { + roomsOffsetX += Math.copySign(1, xRemainder); + connOffsetX += Math.copySign(1, xRemainder) * (Math.abs(xRemainder) - roomSize) / connectorSize; + } else { + roomsOffsetX += xRemainder / roomSize; + } + if (deltaX < 0 && xRemainder != 0) { + roomsOffsetX++; + connOffsetX++; + } + float roomsOffsetY = (int) Math.floor(deltaY / (roomSize + connectorSize)); + float connOffsetY = (int) Math.floor(deltaY / (roomSize + connectorSize)); + float yRemainder = deltaY % (roomSize + connectorSize); + if (Math.abs(yRemainder) > roomSize) { + roomsOffsetY += Math.copySign(1, yRemainder); + connOffsetY += Math.copySign(1, yRemainder) * (Math.abs(yRemainder) - roomSize) / connectorSize; + } else { + roomsOffsetY += yRemainder / roomSize; + } + if (deltaY < 0 && yRemainder != 0) { + roomsOffsetY++; + connOffsetY++; + } + + float angle = (float) (vec4b.func_176111_d() * 360) / 16.0F; + + MapPosition pos = new MapPosition(roomsOffsetX, connOffsetX, roomsOffsetY, connOffsetY); + pos.rotation = angle % 360; + if (pos.rotation < 0) pos.rotation += 360; + + if (decorations++ <= 6) { + positions.add(pos); + } + rawPlayerMarkerMapPositions.add(pos); + } + + boolean different = playerMarkerMapPositions.size() != positions.size(); + + if (!different) { + for (MapPosition pos : playerMarkerMapPositions.values()) { + if (!positions.contains(pos)) { + different = true; + break; + } + } + } + + if (different && positions.size() > 0) { + lastLastDecorationsMillis = lastDecorationsMillis; + lastDecorationsMillis = System.currentTimeMillis(); + + playerMarkerMapPositionsLast.clear(); + for (Map.Entry entry : playerMarkerMapPositions.entrySet()) { + playerMarkerMapPositionsLast.put(entry.getKey(), entry.getValue()); + } + playerMarkerMapPositions.clear(); + + Set foundPlayers = new HashSet<>(); + for (Map.Entry entry : playerEntityMapPositions.entrySet()) { + playerMarkerMapPositions.put(entry.getKey(), entry.getValue()); + playerMarkerMapPositionsLast.put(entry.getKey(), entry.getValue()); + foundPlayers.add(entry.getKey()); + } + + HashMap> distanceMap = new HashMap<>(); + for (Map.Entry entry : playerMarkerMapPositionsLast.entrySet()) { + HashMap deltaDists = new HashMap<>(); + for (int i = 0; i < positions.size(); i++) { + float dx = entry.getValue().getRenderX() - positions.get(i).getRenderX(); + float dy = entry.getValue().getRenderY() - positions.get(i).getRenderY(); + deltaDists.put(i, dx * dx + dy * dy); + } + distanceMap.put(entry.getKey(), deltaDists); + } + + List playerList = new ArrayList<>(playerMarkerMapPositionsLast.keySet()); + List> playerPermutations = permutations(playerList); + + List finalUsedIndexes = new ArrayList<>(); + if (playerPermutations.size() > 0) { + HashMap smallestPermutation = null; + float smallestTotalDistance = 0; + + for (List permutation : playerPermutations) { + HashMap usedIndexes = new HashMap<>(); + + float totalDistance = 0; + for (String player : permutation) { + int smallestIndex = -1; + float smallestDist = 0; + for (Map.Entry entry : distanceMap.get(player).entrySet()) { + if (!usedIndexes.containsValue(entry.getKey())) { + if (smallestIndex == -1 || entry.getValue() < smallestDist) { + smallestIndex = entry.getKey(); + smallestDist = entry.getValue(); + } + } + } + if (smallestIndex != -1) { + usedIndexes.put(player, smallestIndex); + totalDistance += smallestDist; + } + } + + if (smallestPermutation == null || totalDistance < smallestTotalDistance) { + smallestPermutation = usedIndexes; + smallestTotalDistance = totalDistance; + } + } + + //System.out.println("--- PERM START ---"); + for (Map.Entry entry : smallestPermutation.entrySet()) { + //System.out.println(entry.getKey() + ":" + entry.getValue() + " : Total dist: " + smallestTotalDistance); + finalUsedIndexes.add(entry.getValue()); + playerMarkerMapPositions.put(entry.getKey(), positions.get(entry.getValue())); + } + } + + List nonUsedIndexes = new ArrayList<>(); + for (int i = 0; i < positions.size(); i++) { + if (!finalUsedIndexes.contains(i)) { + nonUsedIndexes.add(i); + } + } + + for (String missingPlayer : actualPlayers) { + if (!playerList.contains(missingPlayer)) { + if (nonUsedIndexes.isEmpty()) break; + playerMarkerMapPositions.put(missingPlayer, positions.get(nonUsedIndexes.get(0))); + nonUsedIndexes.remove(0); + } + } + } + } else if (mapDecorations == null) { + playerMarkerMapPositions.clear(); + playerMarkerMapPositionsLast.clear(); + + for (Map.Entry entry : playerEntityMapPositions.entrySet()) { + playerMarkerMapPositions.put(entry.getKey(), entry.getValue()); + } + } + + if (!roomMap.isEmpty() && startRoomX >= 0 && startRoomY >= 0) { + render(centerX, centerY); + } + + this.colourMap = colourMap; + } + + @SubscribeEvent + public void onWorldChange(WorldEvent.Load event) { + colourMap = null; + } + + @SubscribeEvent + public void onRenderOverlay(RenderGameOverlayEvent.Post event) { + if (!NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) return; + if (event.type == RenderGameOverlayEvent.ElementType.ALL) { + if (!NotEnoughUpdates.INSTANCE.config.dungeonMap.dmEnable) return; + + if (Minecraft.getMinecraft().gameSettings.showDebugInfo || + (Minecraft.getMinecraft().gameSettings.keyBindPlayerList.isKeyDown() && + (!Minecraft.getMinecraft().isIntegratedServerRunning() || + Minecraft.getMinecraft().thePlayer.sendQueue.getPlayerInfoMap().size() > 1))) { + return; + } + + ItemStack stack = Minecraft.getMinecraft().thePlayer.inventory.mainInventory[8]; + boolean holdingBow = stack != null && stack.getItem() == Items.arrow && colourMap != null; + if (holdingBow || (stack != null && stack.getItem() instanceof ItemMap)) { + Map decorations = null; + + Color[][] colourMap = new Color[128][128]; + if (holdingBow) { + for (int x = 0; x < 128; x++) { + for (int y = 0; y < 128; y++) { + if (this.colourMap[x][y] != null) { + colourMap[x][y] = this.colourMap[x][y]; + } else { + colourMap[x][y] = new Color(0, true); + } + } + } + } else { + ItemMap map = (ItemMap) stack.getItem(); + MapData mapData = map.getMapData(stack, Minecraft.getMinecraft().theWorld); + + if (mapData == null) return; + + decorations = mapData.mapDecorations; + + for (int i = 0; i < 16384; ++i) { + int x = i % 128; + int y = i / 128; + + int j = mapData.colors[i] & 255; + + Color c; + if (j / 4 == 0) { + c = new Color((i + i / 128 & 1) * 8 + 16 << 24, true); + } else { + c = new Color(MapColor.mapColorArray[j / 4].getMapColor(j & 3), true); + } + + colourMap[x][y] = c; + } + } + + int roomSizeBlocks = 31; /*List dists = new ArrayList<>(); int currentBlockCount = 0; for(int i=0; i<300; i++) { @@ -1485,7 +1601,7 @@ public void onRenderOverlay(RenderGameOverlayEvent.Post event) { } if(mostCommonDist > 31) roomSizeBlocks = mostCommonDist;*/ - Set actualPlayers = new HashSet<>(); + Set actualPlayers = new HashSet<>(); /*for(EntityPlayer player : Minecraft.getMinecraft().theWorld.playerEntities) { if(player.getUniqueID().toString().charAt(14) == '4') { actualPlayers.add(player.getName()); @@ -1493,88 +1609,96 @@ public void onRenderOverlay(RenderGameOverlayEvent.Post event) { } }*/ - int players = 0; - for(ScorePlayerTeam team : Minecraft.getMinecraft().thePlayer.getWorldScoreboard().getTeams()) { - if(team.getTeamName().startsWith("a") && team.getMembershipCollection().size() == 1) { - String playerName = Iterables.get(team.getMembershipCollection(), 0); - boolean foundPlayer = false; - for(EntityPlayer player : Minecraft.getMinecraft().theWorld.playerEntities) { - if(player.getName().equals(playerName) && (player == Minecraft.getMinecraft().thePlayer || !player.isPlayerSleeping())) { - actualPlayers.add(playerName); - foundPlayer = true; - break; - } - } - if(!foundPlayer) actualPlayers.add(playerName); - if(++players >= 6) break; - } - } - - Position pos = NotEnoughUpdates.INSTANCE.config.dungeonMap.dmPosition; - - int size = 80 + Math.round(40*NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderSize); - ScaledResolution scaledResolution = Utils.pushGuiScale(2); - renderMap(pos.getAbsX(scaledResolution, size/2)+size/2, pos.getAbsY(scaledResolution, size/2)+size/2, - colourMap, decorations, roomSizeBlocks, actualPlayers, true, event.partialTicks); - Utils.pushGuiScale(-1); - } else if(stack != null && Item.getIdFromItem(stack.getItem()) == 399){ - //This should clear the map if you're in the dungeon boss room - //so when you're holding a bow it doesnt show the map anymore - this.colourMap = null; - } - } - } - - public List> permutations(List values) { - List> permutations = new ArrayList<>(); - - if(values.size() == 1) { - permutations.add(values); - return permutations; - } - - for(String first : values) { - List newList = new ArrayList<>(); - for(String val : values) { - if(!val.equals(first)) { - newList.add(val); - } - } - - for(List list2 : permutations(newList)) { - List perm = new ArrayList<>(); - perm.add(first); - perm.addAll(list2); - permutations.add(perm); - } - } - - return permutations; - } - - Shader blurShaderHorz = null; - Framebuffer blurOutputHorz = null; - Shader blurShaderVert = null; - Framebuffer blurOutputVert = null; - - /** - * Creates a projection matrix that projects from our coordinate space [0->width; 0->height] to OpenGL coordinate - * space [-1 -> 1; 1 -> -1] (Note: flipped y-axis). - * - * This is so that we can render to and from the framebuffer in a way that is familiar to us, instead of needing to - * apply scales and translations manually. - */ - private Matrix4f createProjectionMatrix(int width, int height) { - Matrix4f projMatrix = new Matrix4f(); - projMatrix.setIdentity(); - projMatrix.m00 = 2.0F / (float)width; - projMatrix.m11 = 2.0F / (float)(-height); - projMatrix.m22 = -0.0020001999F; - projMatrix.m33 = 1.0F; - projMatrix.m03 = -1.0F; - projMatrix.m13 = 1.0F; - projMatrix.m23 = -1.0001999F; - return projMatrix; - } - + int players = 0; + for (ScorePlayerTeam team : Minecraft.getMinecraft().thePlayer.getWorldScoreboard().getTeams()) { + if (team.getTeamName().startsWith("a") && team.getMembershipCollection().size() == 1) { + String playerName = Iterables.get(team.getMembershipCollection(), 0); + boolean foundPlayer = false; + for (EntityPlayer player : Minecraft.getMinecraft().theWorld.playerEntities) { + if (player.getName().equals(playerName) && + (player == Minecraft.getMinecraft().thePlayer || !player.isPlayerSleeping())) { + actualPlayers.add(playerName); + foundPlayer = true; + break; + } + } + if (!foundPlayer) actualPlayers.add(playerName); + if (++players >= 6) break; + } + } + + Position pos = NotEnoughUpdates.INSTANCE.config.dungeonMap.dmPosition; + + int size = 80 + Math.round(40 * NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderSize); + ScaledResolution scaledResolution = Utils.pushGuiScale(2); + renderMap( + pos.getAbsX(scaledResolution, size / 2) + size / 2, + pos.getAbsY(scaledResolution, size / 2) + size / 2, + colourMap, + decorations, + roomSizeBlocks, + actualPlayers, + true, + event.partialTicks + ); + Utils.pushGuiScale(-1); + } else if (stack != null && Item.getIdFromItem(stack.getItem()) == 399) { + //This should clear the map if you're in the dungeon boss room + //so when you're holding a bow it doesnt show the map anymore + this.colourMap = null; + } + } + } + + public List> permutations(List values) { + List> permutations = new ArrayList<>(); + + if (values.size() == 1) { + permutations.add(values); + return permutations; + } + + for (String first : values) { + List newList = new ArrayList<>(); + for (String val : values) { + if (!val.equals(first)) { + newList.add(val); + } + } + + for (List list2 : permutations(newList)) { + List perm = new ArrayList<>(); + perm.add(first); + perm.addAll(list2); + permutations.add(perm); + } + } + + return permutations; + } + + Shader blurShaderHorz = null; + Framebuffer blurOutputHorz = null; + Shader blurShaderVert = null; + Framebuffer blurOutputVert = null; + + /** + * Creates a projection matrix that projects from our coordinate space [0->width; 0->height] to OpenGL coordinate + * space [-1 -> 1; 1 -> -1] (Note: flipped y-axis). + *

+ * This is so that we can render to and from the framebuffer in a way that is familiar to us, instead of needing to + * apply scales and translations manually. + */ + private Matrix4f createProjectionMatrix(int width, int height) { + Matrix4f projMatrix = new Matrix4f(); + projMatrix.setIdentity(); + projMatrix.m00 = 2.0F / (float) width; + projMatrix.m11 = 2.0F / (float) (-height); + projMatrix.m22 = -0.0020001999F; + projMatrix.m33 = 1.0F; + projMatrix.m03 = -1.0F; + projMatrix.m13 = 1.0F; + projMatrix.m23 = -1.0001999F; + return projMatrix; + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonWin.java b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonWin.java index 95ca32c945..976dfcf87c 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonWin.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonWin.java @@ -14,9 +14,7 @@ import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL14; -import java.awt.*; import java.util.*; -import java.util.List; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -24,390 +22,443 @@ import java.util.regex.Pattern; public class DungeonWin { - - private static class Confetti { - private float x; - private float y; - private float xLast; - private float yLast; - private int life = 0; - private float xVel; - private float yVel; - private int id; - - public Confetti(float x, float y, float xVel, float yVel) { - this.x = x; - this.xLast = x; - this.y = y; - this.yLast = y; - this.xVel = xVel; - this.yVel = yVel; - this.id = rand.nextInt(16); - this.life = 20+rand.nextInt(10); - } - } - public static ResourceLocation CONFETTI = new ResourceLocation("notenoughupdates:dungeon_win/confetti.png"); - public static ResourceLocation SPLUS = new ResourceLocation("notenoughupdates:dungeon_win/splus.png"); - public static ResourceLocation S = new ResourceLocation("notenoughupdates:dungeon_win/s.png"); - public static ResourceLocation A = new ResourceLocation("notenoughupdates:dungeon_win/a.png"); - public static ResourceLocation B = new ResourceLocation("notenoughupdates:dungeon_win/b.png"); - public static ResourceLocation C = new ResourceLocation("notenoughupdates:dungeon_win/c.png"); - public static ResourceLocation D = new ResourceLocation("notenoughupdates:dungeon_win/d.png"); - public static ResourceLocation TEAM_SCORE = SPLUS; - - private static final int SCALE_FACTOR = 3; - private static final int WIDTH = 32*SCALE_FACTOR; - private static final int HEIGHT = 16*SCALE_FACTOR; - - private static boolean hideChat = false; - private static long lastDungeonFinish = 0; - private static final Pattern TEAM_SCORE_REGEX = Pattern.compile("Team Score: [0-9]+ \\((S\\+|S|A|B|C|D)\\)"); - - private static final ScheduledExecutorService SES = Executors.newScheduledThreadPool(1); - - public static Random rand = new Random(); - public static List confetti = new ArrayList<>(); - public static List text = new ArrayList<>(); - public static long startTime = 0; - - static { - for(int i=0; i<10; i++) { - text.add("{PLACEHOLDER DUNGEON STAT #"+i+"}"); - } - } - - public static void displayWin() { - if(NotEnoughUpdates.INSTANCE.config.dungeons.dungeonWinMillis < 100 || !NotEnoughUpdates.INSTANCE.config.dungeons.enableDungeonWin) return; - startTime = System.currentTimeMillis(); - confetti.clear(); - } - - public static void tick() { - if(NotEnoughUpdates.INSTANCE.config.dungeons.dungeonWinMillis < 100 || !NotEnoughUpdates.INSTANCE.config.dungeons.enableDungeonWin) return; - if(System.currentTimeMillis() - startTime > 5000) return; - int deltaTime = (int)(System.currentTimeMillis() - startTime); - - if(deltaTime < 1000) { - ScaledResolution sr = Utils.pushGuiScale(2); - int cap = 0; - switch(TEAM_SCORE.getResourcePath()) { - case "dungeon_win/splus.png": - cap = 200; break; - case "dungeon_win/s.png": - cap = 100; break; - case "dungeon_win/a.png": - cap = 50; break; - } - int maxConfetti = Math.min(cap, deltaTime/5); - while(confetti.size() < maxConfetti) { - int y; - if(deltaTime < 500) { - y = sr.getScaledHeight()/2-(int)(Math.sin(deltaTime/1000f*Math.PI)*sr.getScaledHeight()/9); - } else { - y = sr.getScaledHeight()/6+(int)(Math.sin(deltaTime/1000f*Math.PI)*sr.getScaledHeight()*4/18); - } - int xOffset = -WIDTH/2+rand.nextInt(WIDTH); - int x = sr.getScaledWidth()/2+xOffset; - - int xVel = xOffset/2; - int yVel = -25-rand.nextInt(10)+Math.abs(xVel)/2; - - confetti.add(new Confetti(x, y, xVel, yVel)); - } - } else { - Set toRemove = new HashSet<>(); - for(Confetti c : confetti) { - if(c.life <= 0) { - toRemove.add(c); - } - } - try { - confetti.removeAll(toRemove); - } catch(ConcurrentModificationException ignored) {} - } - - Utils.pushGuiScale(-1); - for(Confetti c : confetti) { - c.yVel += 1; - c.xVel /= 1.1f; - c.yVel /= 1.1f; - c.xLast = c.x; - c.yLast = c.y; - c.x += c.xVel; - c.y += c.yVel; - c.life--; - } - } - - - public static void onChatMessage(ClientChatReceivedEvent e) { - if(e.type == 2) return; - - if(NotEnoughUpdates.INSTANCE.config.dungeons.dungeonWinMillis < 100 || !NotEnoughUpdates.INSTANCE.config.dungeons.enableDungeonWin) return; - - long currentTime = System.currentTimeMillis(); - String unformatted = Utils.cleanColour(e.message.getUnformattedText()); - - //Added two more Resets, cant do Reset+Reset+Reset cause idk? - //hypixel please dont randomly add more - - if(e.message.getFormattedText().startsWith(EnumChatFormatting.RESET+""+EnumChatFormatting.RESET+""+EnumChatFormatting.RESET+" ")){ - if(currentTime - lastDungeonFinish > 30000) { - Matcher matcher = TEAM_SCORE_REGEX.matcher(unformatted); - if(matcher.find()) { - lastDungeonFinish = currentTime; - String score = matcher.group(1); - switch (score.toUpperCase()) { - case "S+": - TEAM_SCORE = SPLUS; break; - case "S": - TEAM_SCORE = S; break; - case "A": - TEAM_SCORE = A; break; - case "B": - TEAM_SCORE = B; break; - case "C": - TEAM_SCORE = C; break; - default: - TEAM_SCORE = D; break; - } - - SES.schedule(()-> { - NotEnoughUpdates.INSTANCE.sendChatMessage("/showextrastats"); - }, 100L, TimeUnit.MILLISECONDS); - } - } - } - if(currentTime - lastDungeonFinish > 100 && currentTime - lastDungeonFinish < 10000) { - if(hideChat) { - if(text.size() > 50) text.clear(); - - e.setCanceled(true); - if(unformatted.contains("\u25AC")) { - hideChat = false; - displayWin(); - } else { - if(unformatted.trim().length() > 0) { - text.add(e.message.getFormattedText().substring(6).trim()); - } - } - } else { - if(unformatted.contains("\u25AC")) { - hideChat = true; - text.clear(); - e.setCanceled(true); - } - } - - } - } - - public static void render(float partialTicks) { - if(NotEnoughUpdates.INSTANCE.config.dungeons.dungeonWinMillis < 100 || !NotEnoughUpdates.INSTANCE.config.dungeons.enableDungeonWin) return; - int maxTime = Math.min(30000, NotEnoughUpdates.INSTANCE.config.dungeons.dungeonWinMillis); - if(System.currentTimeMillis() - startTime > maxTime) return; - int deltaTime = (int)(System.currentTimeMillis() - startTime); - - float alpha = Math.max(0, Math.min(1, 1-(deltaTime-maxTime+150)/150f)); - - ScaledResolution sr = Utils.pushGuiScale(2); - - if(deltaTime > 600) { - float bottom; - if(deltaTime < 1000) { - bottom = sr.getScaledHeight()/6f+(float)Math.sin(deltaTime/1000f*Math.PI)*sr.getScaledHeight()*4/18+HEIGHT/2; - } else { - bottom = sr.getScaledHeight()/6f+HEIGHT/2; - } - for(int i=0; i bottom) { - int textAlpha = (int)(alpha * (deltaTime > 1000 ? 255 : Math.min(255, (textCenterY-bottom)/30f*255))); - GlStateManager.enableBlend(); - - if(textAlpha > 150) { - for(int xOff=-2; xOff<=2; xOff++) { - for(int yOff=-2; yOff<=2; yOff++) { - if(Math.abs(xOff) != Math.abs(yOff)) { - Utils.drawStringCentered(Utils.cleanColourNotModifiers(line), Minecraft.getMinecraft().fontRendererObj, - sr.getScaledWidth()/2+xOff/2f, textCenterY+yOff/2f, false, - ((textAlpha/Math.max(Math.abs(xOff), Math.abs(yOff))) << 24)); - } - } - } - } - - Utils.drawStringCentered(line, Minecraft.getMinecraft().fontRendererObj, - sr.getScaledWidth()/2, textCenterY, false, (textAlpha << 24) | 0x00FFFFFF); - } - } - } - - for(Confetti c : confetti) { - Minecraft.getMinecraft().getTextureManager().bindTexture(CONFETTI); - GlStateManager.color(1, 1, 1, 1); - if(c.life >= 15) { - GlStateManager.color(1, 1, 1, Math.min(1, c.life/4f)); - Utils.drawTexturedRect(c.xLast+(c.x-c.xLast)*partialTicks-4, c.yLast+(c.y-c.yLast)*partialTicks-4, - 8, 8, (c.id%4)/4f, (c.id%4+1)/4f, (c.id/4)/4f, (c.id/4+1)/4f, GL11.GL_NEAREST); - } - } - - Minecraft.getMinecraft().getTextureManager().bindTexture(TEAM_SCORE); - GlStateManager.color(1, 1, 1, alpha); - - GlStateManager.pushMatrix(); - if(deltaTime < 1600) { - GlStateManager.translate(sr.getScaledWidth()/2, 0, 0); - if(deltaTime < 500) { - GlStateManager.translate(0, sr.getScaledHeight()/2f-Math.sin(deltaTime/1000f*Math.PI)*sr.getScaledHeight()/9, 0); - } else if(deltaTime < 1000) { - GlStateManager.translate(0, sr.getScaledHeight()/6f+Math.sin(deltaTime/1000f*Math.PI)*sr.getScaledHeight()*4/18, 0); - } else { - GlStateManager.translate(0, sr.getScaledHeight()/6f, 0); - } - if(deltaTime < 200) { - float scale = deltaTime/200f; - GlStateManager.scale(scale, scale, 1); - } else if(deltaTime < 1000) { - float scale = 1+(float)Math.sin((deltaTime-200)/800f*Math.PI)*0.8f; - GlStateManager.scale(scale, scale, 1); - } else if(deltaTime < 1100) { - float scale = 1+(float)Math.sin((deltaTime-1000)/100f*Math.PI)*0.15f; - GlStateManager.scale(scale, scale, 1); - } - - if(deltaTime < 600) { - GlStateManager.rotate(180+deltaTime/600f*180, 0, 1, 0); - GlStateManager.rotate(180-deltaTime/600f*180, 1, 0, 0); - GlStateManager.rotate(-180-deltaTime/600f*165, 0, 0, 1); - } else if(deltaTime < 1000) { - GlStateManager.rotate(15-(deltaTime-600)/400f*11, 0, 0, 1); - } else { - float logFac = 1-(float)Math.log((deltaTime-1000)/600f*1.7f+1); - logFac = logFac*logFac; - - GlStateManager.rotate(4f*logFac, 0, 0, 1); - float x = (deltaTime-1000)/300f; - GlStateManager.rotate((float)(40*(1-Math.log(x*0.85f+1))*Math.sin(10*x*x)), 0, 1, 0); - } - } else { - GlStateManager.translate(sr.getScaledWidth()/2, sr.getScaledHeight()/6f, 0); - } - - GlStateManager.disableCull(); - - Utils.drawTexturedRect(-WIDTH/2, -HEIGHT/2, WIDTH, HEIGHT, GL11.GL_NEAREST); - GlStateManager.translate(0, 0, -SCALE_FACTOR*2); - Utils.drawTexturedRect(-WIDTH/2, -HEIGHT/2, WIDTH, HEIGHT, GL11.GL_NEAREST); - GlStateManager.translate(0, 0, SCALE_FACTOR*2); - - if(deltaTime < 1600) { - float epsilon = 0.01f; - for(int xIndex=0; xIndex<32; xIndex++) { - for(int yIndex=0; yIndex<16; yIndex++) { - float uMin = xIndex/32f; - float uMax = (xIndex+1)/32f; - float vMin = yIndex/16f; - float vMax = (yIndex+1)/16f; - - int x = -WIDTH/2+xIndex*SCALE_FACTOR; - int y = -HEIGHT/2+yIndex*SCALE_FACTOR; - - GlStateManager.enableTexture2D(); - GlStateManager.enableBlend(); - GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); - - GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST); - GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST); - - Tessellator tessellator = Tessellator.getInstance(); - WorldRenderer worldrenderer = tessellator.getWorldRenderer(); - //Left - worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX); - worldrenderer - .pos(x+epsilon, y+SCALE_FACTOR, 0.0D+epsilon) - .tex(uMin, vMax).endVertex(); - worldrenderer - .pos(x+epsilon, y, 0.0D+epsilon) - .tex(uMax, vMax).endVertex(); - worldrenderer - .pos(x+epsilon, y, -SCALE_FACTOR*2-epsilon) - .tex(uMax, vMin).endVertex(); - worldrenderer - .pos(x+epsilon, y+SCALE_FACTOR, -SCALE_FACTOR*2-epsilon) - .tex(uMin, vMin).endVertex(); - tessellator.draw(); - //Right - worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX); - worldrenderer - .pos(x+SCALE_FACTOR-epsilon, y+SCALE_FACTOR, 0.0D+epsilon) - .tex(uMin, vMax).endVertex(); - worldrenderer - .pos(x+SCALE_FACTOR-epsilon, y, 0.0D+epsilon) - .tex(uMax, vMax).endVertex(); - worldrenderer - .pos(x+SCALE_FACTOR-epsilon, y, -SCALE_FACTOR*2-epsilon) - .tex(uMax, vMin).endVertex(); - worldrenderer - .pos(x+SCALE_FACTOR-epsilon, y+SCALE_FACTOR, -SCALE_FACTOR*2-epsilon) - .tex(uMin, vMin).endVertex(); - tessellator.draw(); - //Top - worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX); - worldrenderer - .pos(x+SCALE_FACTOR, y+epsilon, 0.0D+epsilon) - .tex(uMin, vMax).endVertex(); - worldrenderer - .pos(x, y+epsilon, 0.0D+epsilon) - .tex(uMax, vMax).endVertex(); - worldrenderer - .pos(x, y+epsilon, -SCALE_FACTOR*2-epsilon) - .tex(uMax, vMin).endVertex(); - worldrenderer - .pos(x+SCALE_FACTOR, y+epsilon, -SCALE_FACTOR*2-epsilon) - .tex(uMin, vMin).endVertex(); - tessellator.draw(); - //Top - worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX); - worldrenderer - .pos(x+SCALE_FACTOR, y+SCALE_FACTOR-epsilon, 0.0D+epsilon) - .tex(uMin, vMax).endVertex(); - worldrenderer - .pos(x, y+SCALE_FACTOR-epsilon, 0.0D+epsilon) - .tex(uMax, vMax).endVertex(); - worldrenderer - .pos(x, y+SCALE_FACTOR-epsilon, -SCALE_FACTOR*2-epsilon) - .tex(uMax, vMin).endVertex(); - worldrenderer - .pos(x+SCALE_FACTOR, y+SCALE_FACTOR-epsilon, -SCALE_FACTOR*2-epsilon) - .tex(uMin, vMin).endVertex(); - tessellator.draw(); - - GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST); - GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST); - - GlStateManager.disableBlend(); - } - } - } - - GlStateManager.popMatrix(); - - for(Confetti c : confetti) { - Minecraft.getMinecraft().getTextureManager().bindTexture(CONFETTI); - GlStateManager.color(1, 1, 1, 1); - if(c.life > 0 && c.life < 15) { - GlStateManager.color(1, 1, 1, Math.min(1, c.life/4f)); - Utils.drawTexturedRect(c.xLast+(c.x-c.xLast)*partialTicks-4, c.yLast+(c.y-c.yLast)*partialTicks-4, - 8, 8, (c.id%4)/4f, (c.id%4+1)/4f, (c.id/4)/4f, (c.id/4+1)/4f, GL11.GL_NEAREST); - } - } - - Utils.pushGuiScale(-1); - - GlStateManager.enableBlend(); - } - + private static class Confetti { + private float x; + private float y; + private float xLast; + private float yLast; + private int life = 0; + private float xVel; + private float yVel; + private final int id; + + public Confetti(float x, float y, float xVel, float yVel) { + this.x = x; + this.xLast = x; + this.y = y; + this.yLast = y; + this.xVel = xVel; + this.yVel = yVel; + this.id = rand.nextInt(16); + this.life = 20 + rand.nextInt(10); + } + } + + public static ResourceLocation CONFETTI = new ResourceLocation("notenoughupdates:dungeon_win/confetti.png"); + public static ResourceLocation SPLUS = new ResourceLocation("notenoughupdates:dungeon_win/splus.png"); + public static ResourceLocation S = new ResourceLocation("notenoughupdates:dungeon_win/s.png"); + public static ResourceLocation A = new ResourceLocation("notenoughupdates:dungeon_win/a.png"); + public static ResourceLocation B = new ResourceLocation("notenoughupdates:dungeon_win/b.png"); + public static ResourceLocation C = new ResourceLocation("notenoughupdates:dungeon_win/c.png"); + public static ResourceLocation D = new ResourceLocation("notenoughupdates:dungeon_win/d.png"); + public static ResourceLocation TEAM_SCORE = SPLUS; + + private static final int SCALE_FACTOR = 3; + private static final int WIDTH = 32 * SCALE_FACTOR; + private static final int HEIGHT = 16 * SCALE_FACTOR; + + private static boolean hideChat = false; + private static long lastDungeonFinish = 0; + private static final Pattern TEAM_SCORE_REGEX = Pattern.compile("Team Score: [0-9]+ \\((S\\+|S|A|B|C|D)\\)"); + + private static final ScheduledExecutorService SES = Executors.newScheduledThreadPool(1); + + public static Random rand = new Random(); + public static List confetti = new ArrayList<>(); + public static List text = new ArrayList<>(); + public static long startTime = 0; + + static { + for (int i = 0; i < 10; i++) { + text.add("{PLACEHOLDER DUNGEON STAT #" + i + "}"); + } + } + + public static void displayWin() { + if (NotEnoughUpdates.INSTANCE.config.dungeons.dungeonWinMillis < 100 || + !NotEnoughUpdates.INSTANCE.config.dungeons.enableDungeonWin) + return; + startTime = System.currentTimeMillis(); + confetti.clear(); + } + + public static void tick() { + if (NotEnoughUpdates.INSTANCE.config.dungeons.dungeonWinMillis < 100 || + !NotEnoughUpdates.INSTANCE.config.dungeons.enableDungeonWin) + return; + if (System.currentTimeMillis() - startTime > 5000) return; + int deltaTime = (int) (System.currentTimeMillis() - startTime); + + if (deltaTime < 1000) { + ScaledResolution sr = Utils.pushGuiScale(2); + int cap = 0; + switch (TEAM_SCORE.getResourcePath()) { + case "dungeon_win/splus.png": + cap = 200; + break; + case "dungeon_win/s.png": + cap = 100; + break; + case "dungeon_win/a.png": + cap = 50; + break; + } + int maxConfetti = Math.min(cap, deltaTime / 5); + while (confetti.size() < maxConfetti) { + int y; + if (deltaTime < 500) { + y = sr.getScaledHeight() / 2 - (int) (Math.sin(deltaTime / 1000f * Math.PI) * sr.getScaledHeight() / 9); + } else { + y = sr.getScaledHeight() / 6 + (int) (Math.sin(deltaTime / 1000f * Math.PI) * sr.getScaledHeight() * 4 / 18); + } + int xOffset = -WIDTH / 2 + rand.nextInt(WIDTH); + int x = sr.getScaledWidth() / 2 + xOffset; + + int xVel = xOffset / 2; + int yVel = -25 - rand.nextInt(10) + Math.abs(xVel) / 2; + + confetti.add(new Confetti(x, y, xVel, yVel)); + } + } else { + Set toRemove = new HashSet<>(); + for (Confetti c : confetti) { + if (c.life <= 0) { + toRemove.add(c); + } + } + try { + confetti.removeAll(toRemove); + } catch (ConcurrentModificationException ignored) { + } + } + + Utils.pushGuiScale(-1); + for (Confetti c : confetti) { + c.yVel += 1; + c.xVel /= 1.1f; + c.yVel /= 1.1f; + c.xLast = c.x; + c.yLast = c.y; + c.x += c.xVel; + c.y += c.yVel; + c.life--; + } + } + + public static void onChatMessage(ClientChatReceivedEvent e) { + if (e.type == 2) return; + + if (NotEnoughUpdates.INSTANCE.config.dungeons.dungeonWinMillis < 100 || + !NotEnoughUpdates.INSTANCE.config.dungeons.enableDungeonWin) + return; + + long currentTime = System.currentTimeMillis(); + String unformatted = Utils.cleanColour(e.message.getUnformattedText()); + + //Added two more Resets, can't do Reset+Reset+Reset cause idk? + //hypixel please don't randomly add more + + if (e.message.getFormattedText().startsWith( + EnumChatFormatting.RESET + "" + EnumChatFormatting.RESET + "" + EnumChatFormatting.RESET + " ")) { + if (currentTime - lastDungeonFinish > 30000) { + Matcher matcher = TEAM_SCORE_REGEX.matcher(unformatted); + if (matcher.find()) { + lastDungeonFinish = currentTime; + String score = matcher.group(1); + switch (score.toUpperCase()) { + case "S+": + TEAM_SCORE = SPLUS; + break; + case "S": + TEAM_SCORE = S; + break; + case "A": + TEAM_SCORE = A; + break; + case "B": + TEAM_SCORE = B; + break; + case "C": + TEAM_SCORE = C; + break; + default: + TEAM_SCORE = D; + break; + } + + SES.schedule(() -> NotEnoughUpdates.INSTANCE.sendChatMessage("/showextrastats"), 100L, TimeUnit.MILLISECONDS); + } + } + } + if (currentTime - lastDungeonFinish > 100 && currentTime - lastDungeonFinish < 10000) { + if (hideChat) { + if (text.size() > 50) text.clear(); + + e.setCanceled(true); + if (unformatted.contains("\u25AC")) { + hideChat = false; + displayWin(); + } else { + if (unformatted.trim().length() > 0) { + text.add(e.message.getFormattedText().substring(6).trim()); + } + } + } else { + if (unformatted.contains("\u25AC")) { + hideChat = true; + text.clear(); + e.setCanceled(true); + } + } + + } + } + + public static void render(float partialTicks) { + if (NotEnoughUpdates.INSTANCE.config.dungeons.dungeonWinMillis < 100 || + !NotEnoughUpdates.INSTANCE.config.dungeons.enableDungeonWin) + return; + int maxTime = Math.min(30000, NotEnoughUpdates.INSTANCE.config.dungeons.dungeonWinMillis); + if (System.currentTimeMillis() - startTime > maxTime) return; + int deltaTime = (int) (System.currentTimeMillis() - startTime); + + float alpha = Math.max(0, Math.min(1, 1 - (deltaTime - maxTime + 150) / 150f)); + + ScaledResolution sr = Utils.pushGuiScale(2); + + if (deltaTime > 600) { + float bottom; + if (deltaTime < 1000) { + bottom = sr.getScaledHeight() / 6f + (float) Math.sin(deltaTime / 1000f * Math.PI) * sr.getScaledHeight() * 4 / + 18 + HEIGHT / 2; + } else { + bottom = sr.getScaledHeight() / 6f + HEIGHT / 2; + } + for (int i = 0; i < text.size(); i++) { + String line = text.get(i); + float textCenterY = sr.getScaledHeight() / 6f + HEIGHT / 2 + 7 + i * 10; + if (textCenterY > bottom) { + int textAlpha = (int) (alpha * (deltaTime > 1000 ? 255 : Math.min(255, (textCenterY - bottom) / 30f * 255))); + GlStateManager.enableBlend(); + + if (textAlpha > 150) { + for (int xOff = -2; xOff <= 2; xOff++) { + for (int yOff = -2; yOff <= 2; yOff++) { + if (Math.abs(xOff) != Math.abs(yOff)) { + Utils.drawStringCentered( + Utils.cleanColourNotModifiers(line), + Minecraft.getMinecraft().fontRendererObj, + sr.getScaledWidth() / 2 + xOff / 2f, + textCenterY + yOff / 2f, + false, + ((textAlpha / Math.max(Math.abs(xOff), Math.abs(yOff))) << 24) + ); + } + } + } + } + + Utils.drawStringCentered(line, Minecraft.getMinecraft().fontRendererObj, + sr.getScaledWidth() / 2, textCenterY, false, (textAlpha << 24) | 0x00FFFFFF + ); + } + } + } + + for (Confetti c : confetti) { + Minecraft.getMinecraft().getTextureManager().bindTexture(CONFETTI); + GlStateManager.color(1, 1, 1, 1); + if (c.life >= 15) { + GlStateManager.color(1, 1, 1, Math.min(1, c.life / 4f)); + Utils.drawTexturedRect( + c.xLast + (c.x - c.xLast) * partialTicks - 4, + c.yLast + (c.y - c.yLast) * partialTicks - 4, + 8, + 8, + (c.id % 4) / 4f, + (c.id % 4 + 1) / 4f, + (c.id / 4) / 4f, + (c.id / 4 + 1) / 4f, + GL11.GL_NEAREST + ); + } + } + + Minecraft.getMinecraft().getTextureManager().bindTexture(TEAM_SCORE); + GlStateManager.color(1, 1, 1, alpha); + + GlStateManager.pushMatrix(); + if (deltaTime < 1600) { + GlStateManager.translate(sr.getScaledWidth() / 2, 0, 0); + if (deltaTime < 500) { + GlStateManager.translate( + 0, + sr.getScaledHeight() / 2f - Math.sin(deltaTime / 1000f * Math.PI) * sr.getScaledHeight() / 9, + 0 + ); + } else if (deltaTime < 1000) { + GlStateManager.translate( + 0, + sr.getScaledHeight() / 6f + Math.sin(deltaTime / 1000f * Math.PI) * sr.getScaledHeight() * 4 / 18, + 0 + ); + } else { + GlStateManager.translate(0, sr.getScaledHeight() / 6f, 0); + } + if (deltaTime < 200) { + float scale = deltaTime / 200f; + GlStateManager.scale(scale, scale, 1); + } else if (deltaTime < 1000) { + float scale = 1 + (float) Math.sin((deltaTime - 200) / 800f * Math.PI) * 0.8f; + GlStateManager.scale(scale, scale, 1); + } else if (deltaTime < 1100) { + float scale = 1 + (float) Math.sin((deltaTime - 1000) / 100f * Math.PI) * 0.15f; + GlStateManager.scale(scale, scale, 1); + } + + if (deltaTime < 600) { + GlStateManager.rotate(180 + deltaTime / 600f * 180, 0, 1, 0); + GlStateManager.rotate(180 - deltaTime / 600f * 180, 1, 0, 0); + GlStateManager.rotate(-180 - deltaTime / 600f * 165, 0, 0, 1); + } else if (deltaTime < 1000) { + GlStateManager.rotate(15 - (deltaTime - 600) / 400f * 11, 0, 0, 1); + } else { + float logFac = 1 - (float) Math.log((deltaTime - 1000) / 600f * 1.7f + 1); + logFac = logFac * logFac; + + GlStateManager.rotate(4f * logFac, 0, 0, 1); + float x = (deltaTime - 1000) / 300f; + GlStateManager.rotate((float) (40 * (1 - Math.log(x * 0.85f + 1)) * Math.sin(10 * x * x)), 0, 1, 0); + } + } else { + GlStateManager.translate(sr.getScaledWidth() / 2, sr.getScaledHeight() / 6f, 0); + } + + GlStateManager.disableCull(); + + Utils.drawTexturedRect(-WIDTH / 2, -HEIGHT / 2, WIDTH, HEIGHT, GL11.GL_NEAREST); + GlStateManager.translate(0, 0, -SCALE_FACTOR * 2); + Utils.drawTexturedRect(-WIDTH / 2, -HEIGHT / 2, WIDTH, HEIGHT, GL11.GL_NEAREST); + GlStateManager.translate(0, 0, SCALE_FACTOR * 2); + + if (deltaTime < 1600) { + float epsilon = 0.01f; + for (int xIndex = 0; xIndex < 32; xIndex++) { + for (int yIndex = 0; yIndex < 16; yIndex++) { + float uMin = xIndex / 32f; + float uMax = (xIndex + 1) / 32f; + float vMin = yIndex / 16f; + float vMax = (yIndex + 1) / 16f; + + int x = -WIDTH / 2 + xIndex * SCALE_FACTOR; + int y = -HEIGHT / 2 + yIndex * SCALE_FACTOR; + + GlStateManager.enableTexture2D(); + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate( + GL11.GL_SRC_ALPHA, + GL11.GL_ONE_MINUS_SRC_ALPHA, + GL11.GL_ONE, + GL11.GL_ONE_MINUS_SRC_ALPHA + ); + + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST); + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST); + + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer worldrenderer = tessellator.getWorldRenderer(); + //Left + worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX); + worldrenderer + .pos(x + epsilon, y + SCALE_FACTOR, 0.0D + epsilon) + .tex(uMin, vMax).endVertex(); + worldrenderer + .pos(x + epsilon, y, 0.0D + epsilon) + .tex(uMax, vMax).endVertex(); + worldrenderer + .pos(x + epsilon, y, -SCALE_FACTOR * 2 - epsilon) + .tex(uMax, vMin).endVertex(); + worldrenderer + .pos(x + epsilon, y + SCALE_FACTOR, -SCALE_FACTOR * 2 - epsilon) + .tex(uMin, vMin).endVertex(); + tessellator.draw(); + //Right + worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX); + worldrenderer + .pos(x + SCALE_FACTOR - epsilon, y + SCALE_FACTOR, 0.0D + epsilon) + .tex(uMin, vMax).endVertex(); + worldrenderer + .pos(x + SCALE_FACTOR - epsilon, y, 0.0D + epsilon) + .tex(uMax, vMax).endVertex(); + worldrenderer + .pos(x + SCALE_FACTOR - epsilon, y, -SCALE_FACTOR * 2 - epsilon) + .tex(uMax, vMin).endVertex(); + worldrenderer + .pos(x + SCALE_FACTOR - epsilon, y + SCALE_FACTOR, -SCALE_FACTOR * 2 - epsilon) + .tex(uMin, vMin).endVertex(); + tessellator.draw(); + //Top + worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX); + worldrenderer + .pos(x + SCALE_FACTOR, y + epsilon, 0.0D + epsilon) + .tex(uMin, vMax).endVertex(); + worldrenderer + .pos(x, y + epsilon, 0.0D + epsilon) + .tex(uMax, vMax).endVertex(); + worldrenderer + .pos(x, y + epsilon, -SCALE_FACTOR * 2 - epsilon) + .tex(uMax, vMin).endVertex(); + worldrenderer + .pos(x + SCALE_FACTOR, y + epsilon, -SCALE_FACTOR * 2 - epsilon) + .tex(uMin, vMin).endVertex(); + tessellator.draw(); + //Top + worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX); + worldrenderer + .pos(x + SCALE_FACTOR, y + SCALE_FACTOR - epsilon, 0.0D + epsilon) + .tex(uMin, vMax).endVertex(); + worldrenderer + .pos(x, y + SCALE_FACTOR - epsilon, 0.0D + epsilon) + .tex(uMax, vMax).endVertex(); + worldrenderer + .pos(x, y + SCALE_FACTOR - epsilon, -SCALE_FACTOR * 2 - epsilon) + .tex(uMax, vMin).endVertex(); + worldrenderer + .pos(x + SCALE_FACTOR, y + SCALE_FACTOR - epsilon, -SCALE_FACTOR * 2 - epsilon) + .tex(uMin, vMin).endVertex(); + tessellator.draw(); + + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST); + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST); + + GlStateManager.disableBlend(); + } + } + } + + GlStateManager.popMatrix(); + + for (Confetti c : confetti) { + Minecraft.getMinecraft().getTextureManager().bindTexture(CONFETTI); + GlStateManager.color(1, 1, 1, 1); + if (c.life > 0 && c.life < 15) { + GlStateManager.color(1, 1, 1, Math.min(1, c.life / 4f)); + Utils.drawTexturedRect( + c.xLast + (c.x - c.xLast) * partialTicks - 4, + c.yLast + (c.y - c.yLast) * partialTicks - 4, + 8, + 8, + (c.id % 4) / 4f, + (c.id % 4 + 1) / 4f, + (c.id / 4) / 4f, + (c.id / 4 + 1) / 4f, + GL11.GL_NEAREST + ); + } + } + + Utils.pushGuiScale(-1); + + GlStateManager.enableBlend(); + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/GuiDungeonMapEditor.java b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/GuiDungeonMapEditor.java index 1a420c6724..41fa366311 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/GuiDungeonMapEditor.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/GuiDungeonMapEditor.java @@ -1,13 +1,12 @@ package io.github.moulberry.notenoughupdates.dungeons; -import io.github.moulberry.notenoughupdates.core.config.gui.GuiPositionEditor; -import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils; -import io.github.moulberry.notenoughupdates.core.util.render.TextRenderUtils; -import io.github.moulberry.notenoughupdates.options.NEUConfig; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.core.GuiElementColour; import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorSlider; import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption; +import io.github.moulberry.notenoughupdates.core.config.gui.GuiPositionEditor; +import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils; +import io.github.moulberry.notenoughupdates.core.util.render.TextRenderUtils; import io.github.moulberry.notenoughupdates.itemeditor.GuiElementTextField; import io.github.moulberry.notenoughupdates.options.seperateSections.DungeonMapConfig; import io.github.moulberry.notenoughupdates.util.SpecialColour; @@ -30,686 +29,819 @@ import java.awt.*; import java.io.IOException; import java.lang.reflect.Field; -import java.util.*; import java.util.List; +import java.util.*; + import static io.github.moulberry.notenoughupdates.util.GuiTextures.*; public class GuiDungeonMapEditor extends GuiScreen { - - public static final ResourceLocation BACKGROUND = new ResourceLocation("notenoughupdates:dungeon_map/editor/background.png"); - public static final ResourceLocation BUTTON = new ResourceLocation("notenoughupdates:dungeon_map/editor/button.png"); - private static final DungeonMap demoMap = new DungeonMap(); - - private int sizeX; - private int sizeY; - private int guiLeft; - private int guiTop; - - private List