├── .github
└── workflows
│ └── build.yml
├── .gitignore
├── README.md
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── src
└── main
├── java
└── com
│ └── luna
│ └── synthesis
│ ├── Synthesis.java
│ ├── commands
│ ├── CopyToClipboardCommand.java
│ └── SynthesisCommand.java
│ ├── core
│ ├── Config.java
│ └── CustomSortingBehavior.java
│ ├── events
│ ├── MessageSentEvent.java
│ └── packet
│ │ ├── CustomChannelDuplexHandler.java
│ │ ├── PacketEvent.java
│ │ ├── PacketReceivedEvent.java
│ │ └── PacketSentEvent.java
│ ├── features
│ ├── cleanup
│ │ ├── CoopCleanup.java
│ │ ├── DungeonCleanup.java
│ │ └── LoreCleanup.java
│ ├── future
│ │ └── ChunkBorders.java
│ └── utilities
│ │ ├── AncestralSpade.java
│ │ ├── BestiaryDropRate.java
│ │ ├── BetterWitherImpactPerspective.java
│ │ ├── ChatBridge.java
│ │ ├── ContainerChat.java
│ │ ├── SearchMode.java
│ │ ├── Share.java
│ │ ├── VisibleLinks.java
│ │ └── WishingCompass.java
│ ├── managers
│ ├── BackpackManager.java
│ └── MathManager.java
│ ├── mixins
│ ├── BlockStainedGlassPaneMixin.java
│ ├── ContainerMixin.java
│ ├── EntityPlayerMixin.java
│ ├── EntityPlayerSPMixin.java
│ ├── GuiContainerMixin.java
│ ├── GuiNewChatMixin.java
│ ├── GuiPlayerTabOverlayMixin.java
│ ├── GuiScreenMixin.java
│ ├── RenderItemMixin.java
│ ├── accessors
│ │ ├── GuiChatAccessor.java
│ │ ├── GuiContainerAccessor.java
│ │ ├── GuiNewChatAccessor.java
│ │ ├── GuiRepairAccessor.java
│ │ ├── ItemModelMesherAccessor.java
│ │ └── S2FPacketSetSlotAccessor.java
│ ├── neu
│ │ └── NEUEventListenerMixin.java
│ ├── optifine
│ │ ├── CapeUtilsMixin.java
│ │ └── PlayerItemsLayerMixin.java
│ ├── patcher
│ │ ├── ChatHandlerMixin.java
│ │ └── ImagePreviewerMixin.java
│ └── skytils
│ │ └── ChatTabsMixin.java
│ └── utils
│ ├── ChatLib.java
│ ├── MixinUtils.java
│ ├── ReflectionUtils.java
│ └── Utils.java
└── resources
├── mcmod.info
└── synthesis.mixins.json
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: build
2 | on: [ pull_request, push ]
3 |
4 | jobs:
5 | build:
6 | strategy:
7 | matrix:
8 | java: [ 8 ]
9 | os: [ ubuntu-20.04 ]
10 | runs-on: ${{ matrix.os }}
11 | steps:
12 | - name: checkout repository
13 | uses: actions/checkout@v2
14 | - name: validate gradle wrapper
15 | uses: gradle/wrapper-validation-action@v1
16 | - name: setup jdk ${{ matrix.java }}
17 | uses: actions/setup-java@v1
18 | with:
19 | java-version: ${{ matrix.java }}
20 | - name: make gradle wrapper executable
21 | run: chmod +x ./gradlew
22 | - name: build
23 | run: ./gradlew build
24 | - name: capture build artifacts
25 | uses: actions/upload-artifact@v2
26 | with:
27 | name: Artifacts
28 | path: build/libs/
29 | - name: send jar to webhook
30 | env:
31 | commits: ${{ toJSON(github.event.commits)}}
32 | run: |
33 | curl -H "secret:${{ secrets.BUILD_SECRET }}" \
34 | -F commits="$commits" \
35 | -F filename=Synthesis.jar \
36 | -F upload=@build/libs/Synthesis.jar \
37 | ${{ secrets.BUILD_URL }}
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # eclipse
2 | bin
3 | *.launch
4 | .settings
5 | .metadata
6 | .classpath
7 | .project
8 |
9 | # idea
10 | out
11 | *.ipr
12 | *.iws
13 | *.iml
14 | .idea
15 |
16 | # gradle
17 | build
18 | .gradle
19 |
20 | # other
21 | eclipse
22 | run
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Synthesis
2 | Hypixel SkyBlock QoL Mod. A collection of random mod features that I couldn't find anywhere else.
3 |
4 | Releases and announcements at the official [discord](https://discord.gg/vAUuKSwbp6).
5 | Feedback such as suggestions, new features, bugs, etc. will also be collected there.
6 |
7 | ***
8 |
9 | ## Features
10 |
11 | Cleanup
12 |
13 | ### Cleanup
14 | Features that help the game feel more clean.
15 | - Coop cleanup, fully customizable
16 | - Auction creation messages
17 | - Auction cancellation messages
18 | - Auction collection messages
19 | - Collection tooltips
20 | - Beacon stat change messages
21 | - Co-op member traveled to island messages
22 | - Dungeon cleanup, fully customizable
23 | - Potion effects message
24 | - Solo dungeon class message
25 | - Ultimate ability message
26 | - Blessing stats messages
27 | - Silverfish messages
28 | - Wither/Blood key usage messages
29 | - Watcher messages
30 | - Doesn't remove the final message
31 | - Lore cleanup, still customizable (0.2.0+)
32 | - Gear score line
33 | - HPB stat bonuses
34 | - Reforge stat bonuses
35 | - Gemstone stat bonuses
36 | - Gemstone icons
37 | - Enchantment descriptions
38 | - And an option to remove enchantment names
39 | - Item abilities
40 | - Full armor set bonuses
41 | - Soulbound text
42 | - Obfuscated text from recombobulator
43 | - Option to not cleanup lore when in the auction house
44 | - Tablist cleanup (0.2.0+)
45 | - Option to remove tablist header
46 | - Option to remove the last 2 lines from the tablist footer
47 | - Chat cleanup (0.3.0+)
48 | - Option to remove old reforge messages when a new one is received
49 | -
50 |
51 |
52 |
53 |
54 | Future features
55 |
56 | ### Future features
57 | Features from future versions of the game. Yes, I don't know to name this one.
58 | - Chunk borders (F3 + G)
59 | - Chat clear (F3 + D) not clearing sent messages, so up and down arrows still work.
60 |
61 |
62 |
63 | Utilities
64 |
65 | ### Utilities
66 | The actual collection of QoL features that doesn't fit any other category.
67 | - Container Chat
68 | - Allows you to type and chat while inside gui inventories
69 | - Search Mode
70 | - Allows you to toggle search mode by pressing Ctrl + F with chat open,
71 | which will only display chat messages that contain what you type.
72 | - Mode to scroll back to a message when you right click on it while on search mode.
73 | - Backpack Retexturing
74 | - HOTM Perk Level Display
75 | - Displays perk level as stack size in the HOTM menu.
76 | - Drop chance to drop rate
77 | - Converts item drop chance to drop rate in the bestiary menu.
78 | - Bestiary glance
79 | - Displays bestiary level and progress in the bestiary menu.
80 | - Armadillo fix
81 | - Prevents your screen being blocked when you are inside a block while riding an armadillo pet.
82 | - Wishing compass triangulation
83 | - Locates where a wishing compass points to. Use one, wait for the particle trail to disappear, move away and use it again.
84 | - Option to add a waypoint at the location while using [Skytils](https://github.com/Skytils/SkytilsMod/).
85 | - Ancestral Spade triangulation
86 | - Quite literally the same thing as wishing compass, but with a few changes.
87 | - Wishing compass uses left display
88 | - Displays a wishing compass' left uses as stack size.
89 | - Visible links
90 | - Makes clickable links in chat blue and underlined.
91 | - Colorless panes
92 | - Turns glass panes gray so glass blocks are more visible. Just used for some gemstone mining, really.
93 | - Chat in portal
94 | - Allows you to type and use chat while inside a nether portal, like the one in dungeon blood room.
95 | - **Note**: It's possible to make portals not close containers such as player inventory, ender chest and others,
96 | but won't for now since I don't know if Hypixel would like that.
97 | - Better wither impact perspective (im good with names, 0.2.0+)
98 | - Toggling perspective while holding a wither impact weapon will skip the front camera.
99 | - Option to make it global instead of wither impact only (0.3.0+)
100 | - Superpairs IDs (0.2.0+)
101 | - Gives skyblock item IDs to items inside superpairs, so NEU and SBE can read them for price displays.
102 | - Additionally, resource packs can also modify those items.
103 | - This was made 1 minute before realizing [Skytils](https://github.com/Skytils/SkytilsMod/) has a working price display inside superpairs, so no need to use this if you use Skytils.
104 | - Shares
105 | - Shares are a way to showcase your items to other users using the mod.
106 | - To show an item, hold it and type "[item]" (configurable) in chat.
107 | - Option to be able to scroll through the share tooltip while using [ScrollableTooltips](https://github.com/Sk1erLLC/ScrollableTooltips)
108 | - Option to click a share to copy an embed for discord. Simply copy it and paste it in a channel on discord.
109 | - Bridge messages
110 | - Formats guild messages sent by a bridge bot.
111 | - Detects username and message based on message format.
112 | - Currently, only works with the formats "ign > msg" and "ign: msg".
113 | - If your bridge bot has another format, let me know.
114 | - If you don't have a bridge bot, [get one](https://neppy.antonio32a.com/).
115 | - Customizable bot name.
116 | - Customizable message format.
117 | - Working links sent from discord while using the format.
118 | - Compatible with [Skytils](https://github.com/Skytils/SkytilsMod/)' guild chat tab regardless of format.
119 | - Optifine
120 | - Allows you to have any optifine user's cape. Only you see this cape!
121 | - Options to bring back from early SkyBlock:
122 | - Yeti with trans cape.
123 | - Terracotta with trans cape.
124 | - Bonzo with non binary cape.
125 | - Grinch with candy cane cape.
126 | - Option to disable all of them, but come on, why would you.
127 | - Option to disable optifine's santa/witch hat.
128 | - [Patcher](https://github.com/Sk1erLLC/Patcher)
129 | - Option to fix an issue that would make compact chat not work under very specific circumstance.
130 | Also when using search mode/container chat in some instances.
131 | - Option to add custom trusted domains to Patcher's Image Preview.
132 | - Some image hosts, like [boob.li](https://boob.li/), won't work with [Patcher](https://github.com/Sk1erLLC/Patcher) 's Image Preview, but will when trusted with this feature.
133 |
134 |
135 | Commands
136 |
137 | ### Commands
138 |
139 | The mod only really has one command, /synth, which hosts all other subcommands.
140 | - /synth
141 | - Aliases: /synthesis, /syn
142 | - When used without an argument, it opens the config menu.
143 | - Subcommands:
144 | - bp
145 | - Arguments: backpack number, texture name, texture meta.
146 | - Re textures the backpack in the *backpack number* slot, with the texture *texture name* and *texture meta*
147 | - For example, if you wanted the first backpack to be a fish, you would just use /synth bp fish. If you wanted a pufferfish instead, you would do /synth bp fish 3.
148 | - To remove a backpack's texture, don't add any texture name or meta to the command.
149 | - domains
150 | - Arguments: "add/remove/list", domain
151 | - Adds or removes a domain to or from the trusted domain list for [Patcher](https://github.com/Sk1erLLC/Patcher)'s Image Preview.
152 | - Can also list all the current trusted domains.
153 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | mavenCentral()
4 | maven {
5 | name = "forge"
6 | url = "https://maven.minecraftforge.net/"
7 | }
8 | maven {
9 | name = "sponge"
10 | url = "https://repo.spongepowered.org/repository/maven-public"
11 | }
12 | maven {
13 | name = "jitpack"
14 | url = "https://jitpack.io/"
15 | }
16 | }
17 | dependencies {
18 | classpath "com.github.asbyth:ForgeGradle:6f53277"
19 | classpath "com.github.jengelman.gradle.plugins:shadow:6.1.0"
20 | classpath "com.github.xcfrg:MixinGradle:0.6-SNAPSHOT"
21 | }
22 | }
23 |
24 | apply plugin: "java"
25 | apply plugin: "net.minecraftforge.gradle.forge"
26 | apply plugin: "com.github.johnrengelman.shadow"
27 | apply plugin: "org.spongepowered.mixin"
28 |
29 | version = "0.3.1"
30 | group = "com.luna"
31 | archivesBaseName = "Synthesis"
32 |
33 | sourceCompatibility = JavaVersion.VERSION_1_8
34 | targetCompatibility = JavaVersion.VERSION_1_8
35 | compileJava.options.encoding = "UTF-8"
36 |
37 | sourceSets {
38 | main {
39 | output.resourcesDir = java.outputDir
40 | }
41 | }
42 |
43 | minecraft {
44 | version = "1.8.9-11.15.1.2318-1.8.9"
45 | runDir = "run"
46 | mappings = "stable_22"
47 | makeObfSourceJar = false
48 |
49 | clientJvmArgs += "-Delementa.dev=true"
50 | clientRunArgs += "--tweakClass gg.essential.loader.stage0.EssentialSetupTweaker"
51 | clientRunArgs += "--mixin synthesis.mixins.json"
52 | }
53 |
54 | mixin {
55 | add sourceSets.main, "synthesis.mixins.refmap.json"
56 | defaultObfuscationEnv searge
57 | }
58 |
59 | configurations {
60 | embed
61 | implementation.extendsFrom(embed)
62 | }
63 |
64 | repositories {
65 | mavenCentral()
66 | maven { url = "https://repo.sk1er.club/repository/maven-public/" }
67 | maven { url = "https://jitpack.io/" }
68 | maven { url = "https://repo.spongepowered.org/repository/maven-public/" }
69 | }
70 |
71 | dependencies {
72 | embed "gg.essential:loader-launchwrapper:1.1.3"
73 | compileOnly "gg.essential:essential-1.8.9-forge:1759"
74 |
75 | annotationProcessor "org.spongepowered:mixin:0.8.4"
76 | compileOnly "org.spongepowered:mixin:0.8.4"
77 |
78 | annotationProcessor "com.google.code.gson:gson:2.2.4"
79 | annotationProcessor "com.google.guava:guava:21.0"
80 | annotationProcessor "org.ow2.asm:asm-tree:6.2"
81 | annotationProcessor "org.ow2.asm:asm-util:6.2"
82 | annotationProcessor "org.apache.logging.log4j:log4j-core:2.0-beta9"
83 |
84 | compileOnly "org.projectlombok:lombok:1.18.12"
85 | annotationProcessor "org.projectlombok:lombok:1.18.12"
86 | }
87 |
88 | shadowJar {
89 | archiveName = "Synthesis.jar"
90 | classifier = ""
91 | duplicatesStrategy = DuplicatesStrategy.EXCLUDE
92 |
93 | manifest.attributes(
94 | "ForceLoadAsMod": true,
95 | "ModSide": "CLIENT",
96 | "TweakClass": "gg.essential.loader.stage0.EssentialSetupTweaker",
97 | "MixinConfigs": "synthesis.mixins.json"
98 | )
99 |
100 | exclude("dummyThing")
101 | exclude("META-INF/maven/")
102 | exclude("META-INF/nar/")
103 | exclude("module-info.class")
104 | exclude("META-INF/versions/")
105 | exclude("LICENSE.txt")
106 |
107 | configurations = [project.configurations.embed]
108 | }
109 |
110 | reobfJar.dependsOn tasks.shadowJar
111 |
112 | reobf {
113 | shadowJar {
114 | mappingType = "SEARGE"
115 | }
116 | }
117 |
118 | processResources {
119 | inputs.property "version", project.version
120 | inputs.property "mcversion", project.minecraft.version
121 |
122 | from(sourceSets.main.resources.srcDirs) {
123 | include "mcmod.info"
124 |
125 | expand "version": project.version, "mcversion": project.minecraft.version
126 | }
127 |
128 | from(sourceSets.main.resources.srcDirs) {
129 | exclude "mcmod.info"
130 | }
131 |
132 | from(file("LICENSE"))
133 | }
134 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx4G
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SynthesisMod/Synthesis/574824a82a0833ce2a3b41ee345e33e68cb27cc2/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/Synthesis.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis;
2 |
3 | import com.luna.synthesis.commands.CopyToClipboardCommand;
4 | import com.luna.synthesis.commands.SynthesisCommand;
5 | import com.luna.synthesis.core.Config;
6 | import com.luna.synthesis.events.packet.PacketEvent;
7 | import com.luna.synthesis.features.cleanup.CoopCleanup;
8 | import com.luna.synthesis.features.cleanup.DungeonCleanup;
9 | import com.luna.synthesis.features.cleanup.LoreCleanup;
10 | import com.luna.synthesis.features.future.ChunkBorders;
11 | import com.luna.synthesis.features.utilities.*;
12 | import com.luna.synthesis.managers.BackpackManager;
13 | import com.luna.synthesis.utils.ReflectionUtils;
14 | import lombok.Getter;
15 | import net.minecraftforge.common.MinecraftForge;
16 | import net.minecraftforge.fml.common.Mod;
17 | import net.minecraftforge.fml.common.Mod.EventHandler;
18 | import net.minecraftforge.fml.common.event.FMLInitializationEvent;
19 |
20 | import java.io.File;
21 |
22 | @Mod(
23 | modid = Synthesis.MODID,
24 | version = Synthesis.VERSION,
25 | name = Synthesis.NAME,
26 | clientSideOnly = true
27 | )
28 | public class Synthesis {
29 | public static final String NAME = "Synthesis";
30 | public static final String MODID = "synthesis";
31 | public static final String VERSION = "0.3.1";
32 | public static final String configLocation = "./config/synthesis.toml";
33 |
34 | @Getter private static Synthesis instance;
35 | @Getter private final Config config;
36 | @Getter private final BackpackManager backpackManager;
37 |
38 | public Synthesis() {
39 | instance = this;
40 | config = new Config();
41 | backpackManager = new BackpackManager(new File("./config/synthesisbackpacks.json"));
42 | }
43 |
44 | @EventHandler
45 | public void init(FMLInitializationEvent event) {
46 | MinecraftForge.EVENT_BUS.register(new PacketEvent());
47 | MinecraftForge.EVENT_BUS.register(this);
48 | MinecraftForge.EVENT_BUS.register(new CoopCleanup());
49 | MinecraftForge.EVENT_BUS.register(new ChunkBorders());
50 | MinecraftForge.EVENT_BUS.register(new SearchMode());
51 | MinecraftForge.EVENT_BUS.register(new BestiaryDropRate());
52 | MinecraftForge.EVENT_BUS.register(new ContainerChat());
53 | MinecraftForge.EVENT_BUS.register(new WishingCompass());
54 | MinecraftForge.EVENT_BUS.register(new ChatBridge());
55 | MinecraftForge.EVENT_BUS.register(new VisibleLinks());
56 | MinecraftForge.EVENT_BUS.register(new Share());
57 | MinecraftForge.EVENT_BUS.register(new DungeonCleanup());
58 | MinecraftForge.EVENT_BUS.register(new BetterWitherImpactPerspective());
59 | MinecraftForge.EVENT_BUS.register(new LoreCleanup());
60 | MinecraftForge.EVENT_BUS.register(new AncestralSpade());
61 | config.preload();
62 | new SynthesisCommand().register();
63 | new CopyToClipboardCommand().register();
64 | ReflectionUtils.onInit();
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/commands/CopyToClipboardCommand.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.commands;
2 |
3 | import com.luna.synthesis.Synthesis;
4 | import com.luna.synthesis.core.Config;
5 | import com.luna.synthesis.utils.ChatLib;
6 | import gg.essential.api.commands.Command;
7 | import gg.essential.api.commands.DefaultHandler;
8 |
9 | import java.awt.*;
10 | import java.awt.datatransfer.StringSelection;
11 |
12 | public class CopyToClipboardCommand extends Command {
13 |
14 | public CopyToClipboardCommand() {
15 | super("ctcc");
16 | }
17 |
18 | private final Config config = Synthesis.getInstance().getConfig();
19 |
20 | // I will let you know that I despise having to create commands to run code on chat click.
21 | // I'll end up rewriting clicks eventually. JUST YOU WAIT.
22 | @DefaultHandler
23 | public void handle(String toCopy) {
24 | if (!config.utilitiesShareCopyEmbed) return;
25 | ChatLib.chat("Copied &a" + toCopy + "&r to clipboard.");
26 | Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(toCopy), null);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/commands/SynthesisCommand.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.commands;
2 |
3 | import com.luna.synthesis.Synthesis;
4 | import com.luna.synthesis.core.Config;
5 | import com.luna.synthesis.managers.BackpackManager;
6 | import com.luna.synthesis.utils.ChatLib;
7 | import gg.essential.api.EssentialAPI;
8 | import gg.essential.api.commands.*;
9 | import net.minecraft.item.Item;
10 | import net.minecraft.item.ItemStack;
11 | import net.minecraftforge.fml.common.Loader;
12 |
13 | import java.util.*;
14 |
15 | public class SynthesisCommand extends Command {
16 | public SynthesisCommand() {
17 | super("synthesis");
18 | }
19 |
20 | private final Config config = Synthesis.getInstance().getConfig();
21 |
22 | @Override
23 | public Set getCommandAliases() {
24 | return new HashSet<>(Arrays.asList(new Alias("syn"), new Alias("synth")));
25 | }
26 |
27 | @DefaultHandler
28 | public void handle() {
29 | EssentialAPI.getGuiUtil().openScreen(Synthesis.getInstance().getConfig().gui());
30 | }
31 |
32 | @SubCommand("bp")
33 | public void bp(@DisplayName("backpack number") int number, @DisplayName("texture name") Optional name, @DisplayName("texture meta") Optional meta) {
34 | BackpackManager bpm = Synthesis.getInstance().getBackpackManager();
35 | if (number < 1 || number > 18) {
36 | ChatLib.chat("That's not a valid backpack number.");
37 | return;
38 | }
39 | if (!name.isPresent()) {
40 | bpm.modifyData(String.valueOf(number), "", 0);
41 | ChatLib.chat("Removed custom texture from backpack " + number);
42 | } else {
43 | String itemName = name.get().toLowerCase();
44 | if (!itemName.startsWith("minecraft:")) {
45 | itemName = "minecraft:" + itemName;
46 | }
47 | Item item = Item.getByNameOrId(itemName);
48 | if (item == null) {
49 | ChatLib.chat("Item \"" + itemName + "\" does not exist.");
50 | return;
51 | }
52 | if (meta.isPresent()) {
53 | List items = new ArrayList<>();
54 | item.getSubItems(item, item.getCreativeTab(), items);
55 | if (items.size() - 1 < meta.get()) {
56 | ChatLib.chat("Meta can't be that high for this item.");
57 | return;
58 | }
59 | bpm.modifyData(String.valueOf(number), itemName, meta.get());
60 | ChatLib.chat("Added " + itemName + " texture to backpack " + number + " with meta " + meta.get());
61 | } else {
62 | bpm.modifyData(String.valueOf(number), itemName, 0);
63 | ChatLib.chat("Added " + itemName + " texture to backpack " + number);
64 | }
65 | }
66 | }
67 |
68 | @SubCommand("domains")
69 | public void domains(@Options({"add", "remove", "list"}) String options, @DisplayName("domain") Optional domain) {
70 | if (!Loader.isModLoaded("patcher")) {
71 | ChatLib.chat("You can only use this feature if you use patcher.");
72 | return;
73 | }
74 | switch (options) {
75 | case "add":
76 | if (!domain.isPresent()) {
77 | ChatLib.chat("You need to specify a domain. Example: bigraccoon.monster");
78 | return;
79 | }
80 | if (config.patcherCustomDomains.contains(domain.get().toLowerCase())) {
81 | ChatLib.chat("That's already a trusted domain.");
82 | return;
83 | }
84 | config.patcherCustomDomains += domain.get().toLowerCase() + ",";
85 | ChatLib.chat("Added &a" + domain.get() + "&r to the trusted domain list.");
86 | config.markDirty();
87 | config.writeData();
88 | break;
89 | case "remove":
90 | if (!domain.isPresent()) {
91 | ChatLib.chat("You need to specify a domain. Example: bigraccoon.monster");
92 | return;
93 | }
94 | if (!config.patcherCustomDomains.contains(domain.get().toLowerCase())) {
95 | ChatLib.chat("That was not a trusted domain.");
96 | return;
97 | }
98 | config.patcherCustomDomains = config.patcherCustomDomains.replace(domain.get().toLowerCase() + ",", "");
99 | ChatLib.chat("Removed &c" + domain.get() + "&r from the trusted domain list.");
100 | config.markDirty();
101 | config.writeData();
102 | break;
103 | case "list":
104 | if (config.patcherCustomDomains.equals("")) {
105 | ChatLib.chat("There aren't any trusted domains.");
106 | return;
107 | }
108 | ChatLib.chat("&aList of domains: ");
109 | for (String s : config.patcherCustomDomains.split(",")) {
110 | ChatLib.chat(" &7- &a" + s);
111 | }
112 | if (domain.isPresent()) {
113 | ChatLib.chat("&dYou don't need to specify another argument, btw.");
114 | }
115 | break;
116 | }
117 | }
118 | }
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/core/Config.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.core;
2 |
3 | import com.luna.synthesis.Synthesis;
4 | import gg.essential.vigilance.Vigilant;
5 | import gg.essential.vigilance.data.JVMAnnotationPropertyCollector;
6 | import gg.essential.vigilance.data.Property;
7 | import gg.essential.vigilance.data.PropertyType;
8 | import net.minecraft.client.Minecraft;
9 | import net.minecraft.util.ChatComponentText;
10 | import net.minecraft.util.EnumChatFormatting;
11 | import net.minecraftforge.fml.common.Loader;
12 |
13 | import java.awt.*;
14 | import java.io.File;
15 |
16 | public class Config extends Vigilant {
17 |
18 | // Me englando is no bueno.
19 | // If you find something that could be rewritten to be more concise and clear, let me know
20 |
21 | @Property(
22 | type = PropertyType.SELECTOR,
23 | name = "Collection tooltips",
24 | description = "Cleans some lines on the co-op collection display.",
25 | category = "Cleanup",
26 | subcategory = "Co-op",
27 | options = {
28 | "Unchanged",
29 | "Empty contributions",
30 | "Other people's contributions",
31 | "All contributions"
32 | }
33 | )
34 | public int cleanupCoopCollections = 0;
35 |
36 | @Property(
37 | type = PropertyType.SELECTOR,
38 | name = "Auction creation",
39 | description = "Removes co-op auction creation messages.",
40 | category = "Cleanup",
41 | subcategory = "Co-op",
42 | options = {
43 | "None",
44 | "Own auctions",
45 | "Own auctions and show price",
46 | "Other people's auctions",
47 | "All auctions",
48 | "All auctions and show price for own"
49 | }
50 | )
51 | public int cleanupCoopAuctionCreation = 0;
52 |
53 | @Property(
54 | type = PropertyType.SELECTOR,
55 | name = "Auction cancellations",
56 | description = "Removes co-op auction cancellation messages.",
57 | category = "Cleanup",
58 | subcategory = "Co-op",
59 | options = {
60 | "None",
61 | "Own auctions",
62 | "Other people's auctions",
63 | "All auctions"
64 | }
65 | )
66 | public int cleanupCoopAuctionCancellation = 0;
67 |
68 | @Property(
69 | type = PropertyType.SELECTOR,
70 | name = "Auction collections",
71 | description = "Removes co-op auction collection messages.",
72 | category = "Cleanup",
73 | subcategory = "Co-op",
74 | options = {
75 | "None",
76 | "Own auctions",
77 | "Other people's auctions",
78 | "All auctions"
79 | }
80 | )
81 | public int cleanupCoopAuctionCollection = 0;
82 |
83 | @Property(
84 | type = PropertyType.SELECTOR,
85 | name = "Beacon stat changes",
86 | description = "Removes co-op beacon stat changes messages.",
87 | category = "Cleanup",
88 | subcategory = "Co-op",
89 | options = {
90 | "None",
91 | "Own changes",
92 | "Other people's changes",
93 | "All changes"
94 | }
95 | )
96 | public int cleanupCoopBeaconStatChanges = 0;
97 |
98 | @Property(
99 | type = PropertyType.SWITCH,
100 | name = "Co-op travel messages",
101 | description = "Removes the chat message when your coop members travel to another island.",
102 | category = "Cleanup",
103 | subcategory = "Co-op"
104 | )
105 | public boolean cleanupCoopTravel = false;
106 |
107 | @Property(
108 | type = PropertyType.SWITCH,
109 | name = "Remove dungeon potion effects message",
110 | description = "Removes the chat message when you join a dungeon with active potion effects outside.",
111 | category = "Cleanup",
112 | subcategory = "Dungeon"
113 | )
114 | public boolean cleanupDungeonPotionEffects = false;
115 |
116 | @Property(
117 | type = PropertyType.SWITCH,
118 | name = "Remove dungeon class message",
119 | description = "Removes the chat message when you're the only player using a class.",
120 | category = "Cleanup",
121 | subcategory = "Dungeon"
122 | )
123 | public boolean cleanupDungeonSoloClassMessage = false;
124 |
125 | @Property(
126 | type = PropertyType.SWITCH,
127 | name = "Remove dungeon ultimate message",
128 | description = "Removes the dungeon reminder that your ultimate is ready to use.",
129 | category = "Cleanup",
130 | subcategory = "Dungeon"
131 | )
132 | public boolean cleanupDungeonUltimateMessage = false;
133 |
134 | @Property(
135 | type = PropertyType.SWITCH,
136 | name = "Remove dungeon blessing stats messages",
137 | description = "Removes the chat message that shows the stats of the collected blessing.",
138 | category = "Cleanup",
139 | subcategory = "Dungeon"
140 | )
141 | public boolean cleanupDungeonBlessingStatMessages = false;
142 |
143 | @Property(
144 | type = PropertyType.SWITCH,
145 | name = "Remove dungeon blessing messages",
146 | description = "Also removes the message that a blessing has been obtained, not only stats.",
147 | category = "Cleanup",
148 | subcategory = "Dungeon"
149 | )
150 | public boolean cleanupDungeonBlessingMessages = false;
151 |
152 | @Property(
153 | type = PropertyType.SWITCH,
154 | name = "Remove dungeon silverfish messages",
155 | description = "Removes the chat message when you hit the silverfish while it's moving.",
156 | category = "Cleanup",
157 | subcategory = "Dungeon"
158 | )
159 | public boolean cleanupDungeonSilverfishMessages = false;
160 |
161 | @Property(
162 | type = PropertyType.SWITCH,
163 | name = "Remove dungeon key usage messages",
164 | description = "Removes the chat message that explains how to use blood and wither keys.",
165 | category = "Cleanup",
166 | subcategory = "Dungeon"
167 | )
168 | public boolean cleanupDungeonKeyUsageMessages = false;
169 |
170 | @Property(
171 | type = PropertyType.SWITCH,
172 | name = "Remove dungeon watcher messages",
173 | description = "Removes all watcher messages except for the last one.",
174 | category = "Cleanup",
175 | subcategory = "Dungeon"
176 | )
177 | public boolean cleanupDungeonWatcherMessages = false;
178 |
179 | @Property(
180 | type = PropertyType.SWITCH,
181 | name = "Remove gear score",
182 | description = "Removes the gear score line.",
183 | category = "Cleanup",
184 | subcategory = "Lore"
185 | )
186 | public boolean cleanupLoreGearScore = false;
187 |
188 | @Property(
189 | type = PropertyType.SWITCH,
190 | name = "Remove HPB stat bonuses",
191 | description = "Removes the text of bonus stats from hot/fuming potato books.",
192 | category = "Cleanup",
193 | subcategory = "Lore"
194 | )
195 | public boolean cleanupLoreHPB = false;
196 |
197 | @Property(
198 | type = PropertyType.SWITCH,
199 | name = "Remove reforge stat bonuses",
200 | description = "Removes the text of bonus stats from reforge.",
201 | category = "Cleanup",
202 | subcategory = "Lore"
203 | )
204 | public boolean cleanupLoreReforge = false;
205 |
206 | @Property(
207 | type = PropertyType.SWITCH,
208 | name = "Remove gemstone stat bonuses",
209 | description = "Removes the text of bonus stats from gemstones.",
210 | category = "Cleanup",
211 | subcategory = "Lore"
212 | )
213 | public boolean cleanupLoreGemstones = false;
214 |
215 | @Property(
216 | type = PropertyType.SWITCH,
217 | name = "Remove dungeon stat bonuses",
218 | description = "Removes the text of the weapon's dungeon stats.",
219 | category = "Cleanup",
220 | subcategory = "Lore"
221 | )
222 | public boolean cleanupLoreDungeon = false;
223 |
224 | @Property(
225 | type = PropertyType.SWITCH,
226 | name = "Remove gemstone icons",
227 | description = "Removes the line that indicates applied gemstones.",
228 | category = "Cleanup",
229 | subcategory = "Lore"
230 | )
231 | public boolean cleanupLoreGemstoneSlots = false;
232 |
233 | @Property(
234 | type = PropertyType.SWITCH,
235 | name = "Remove enchantment descriptions",
236 | description = "Removes the explanation of what each enchantment does when the item has a low amount of enchantments.",
237 | category = "Cleanup",
238 | subcategory = "Lore"
239 | )
240 | public boolean cleanupLoreEnchantmentDescriptions = false;
241 |
242 | @Property(
243 | type = PropertyType.SWITCH,
244 | name = "Remove enchantments and reforge abilities",
245 | description = "Removes both the paragraph of enchantments and any mention of reforge abilities.",
246 | category = "Cleanup",
247 | subcategory = "Lore"
248 | )
249 | public boolean cleanupLoreEnchantments = false;
250 |
251 | @Property(
252 | type = PropertyType.SWITCH,
253 | name = "Remove reforge abilities",
254 | description = "Removes only the reforge ability text and leaves the paragraph of enchantments alone.",
255 | category = "Cleanup",
256 | subcategory = "Lore"
257 | )
258 | public boolean cleanupLoreReforgeAbility = false;
259 |
260 | @Property(
261 | type = PropertyType.SWITCH,
262 | name = "Remove item abilities",
263 | description = "Removes the item ability text.",
264 | category = "Cleanup",
265 | subcategory = "Lore"
266 | )
267 | public boolean cleanupLoreAbilities = false;
268 |
269 | @Property(
270 | type = PropertyType.SWITCH,
271 | name = "Remove armor piece bonuses",
272 | description = "Removes the armor piece bonus text.",
273 | category = "Cleanup",
274 | subcategory = "Lore"
275 | )
276 | public boolean cleanupLorePieceBonus = false;
277 |
278 | @Property(
279 | type = PropertyType.SWITCH,
280 | name = "Remove armor full set bonuses",
281 | description = "Removes the armor full set bonus text.",
282 | category = "Cleanup",
283 | subcategory = "Lore"
284 | )
285 | public boolean cleanupLoreFullSetBonus = false;
286 |
287 | @Property(
288 | type = PropertyType.SWITCH,
289 | name = "Remove co-op soulbound text",
290 | description = "Removes the \"§8* Co-op Soulbound *§r\" text.",
291 | category = "Cleanup",
292 | subcategory = "Lore"
293 | )
294 | public boolean cleanupLoreCoopSoulbound = false;
295 |
296 | @Property(
297 | type = PropertyType.SWITCH,
298 | name = "Remove solo soulbound text",
299 | description = "Removes the \"§8* Soulbound *§r\" text.",
300 | category = "Cleanup",
301 | subcategory = "Lore"
302 | )
303 | public boolean cleanupLoreSoloSoulbound = false;
304 |
305 | @Property(
306 | type = PropertyType.SWITCH,
307 | name = "Remove recombobulated obfuscated text",
308 | description = "Removes the obfuscated text (§ka§r) on the rarity of a recombobulated item.",
309 | category = "Cleanup",
310 | subcategory = "Lore"
311 | )
312 | public boolean cleanupLoreRecombobulatedObfuscated = false;
313 |
314 | @Property(
315 | type = PropertyType.SWITCH,
316 | name = "Remove \"§7Lvl§r\" from pet names in the pet menu",
317 | description = "Shows only the pet's level number in the pet menu.\n\n" +
318 | "§c§lWARNING§r§c: This WILL conflict with Skytils' item rarity feature at this time\n§cdue to their pet name regex detection, and consequently almost any other mod features that depends on the pet's display name.\n" +
319 | "§e§lCAUTION§r§e: This will also affect the output of the pet's display name\n§eif you use Developer Mode to copy item NBT data using the §7/sba nbt§e command from SkyblockAddons.",
320 | category = "Cleanup",
321 | subcategory = "Lore"
322 | )
323 | public boolean cleanupPetDisplayName = false;
324 |
325 | @Property(
326 | type = PropertyType.SELECTOR,
327 | name = "Remove pet type text in the pet menu",
328 | description = "Removes the pet's type (type and/or skill, your choice) from its lore in the pet menu.\n" +
329 | "Example (show skill only): §8Mining Pet§r -> §8Mining\n" +
330 | "Example (show type only): §8Combat Morph§r -> §8Morph\n",
331 | category = "Cleanup",
332 | subcategory = "Lore",
333 | options = {
334 | "Off",
335 | "Show skill only and remove pet type",
336 | "Show type only and remove pet's skill",
337 | "Remove both skill and type"
338 | }
339 | )
340 | public int cleanupLorePetType = 0;
341 |
342 | @Property(
343 | type = PropertyType.SWITCH,
344 | name = "Remove pet perk names in the pet menu",
345 | description = "Examples: §6Hive§r, §6Ridable§r, §6Run§r, §6Odyssey§r, §6Mining Exp Boost§r.",
346 | category = "Cleanup",
347 | subcategory = "Lore"
348 | )
349 | public boolean cleanupLorePetPerkName = false;
350 |
351 | @Property(
352 | type = PropertyType.SWITCH,
353 | name = "Remove pet \"§6Held Item: §r\" prefix in the pet menu",
354 | description = "Example: §6Held Item: §aGold Claws\nThis will §lNOT§r remove the ability text\n§rof the held pet item in question.",
355 | category = "Cleanup",
356 | subcategory = "Lore"
357 | )
358 | public boolean cleanupLorePetHeldItemPrefix = false;
359 |
360 | @Property(
361 | type = PropertyType.SWITCH,
362 | name = "Remove pet lore's empty lines in the pet menu",
363 | description = "This is a rather self-explanatory feature, but Essential's config menu renderer throws a hissy fit if you leave the description line empty, so now you're forced to read this.",
364 | category = "Cleanup",
365 | subcategory = "Lore"
366 | )
367 | public boolean cleanupLorePetEmptyLines = false;
368 |
369 | @Property(
370 | type = PropertyType.SWITCH,
371 | name = "Remove pet lore's \"§b§lMAX LEVEL§r\" line in the pet menu",
372 | description = "This is a rather self-explanatory feature, but Essential's config menu renderer throws a hissy fit if you leave the description line empty, so now you're forced to read this.",
373 | category = "Cleanup",
374 | subcategory = "Lore"
375 | )
376 | public boolean cleanupLorePetMaxLevel = false;
377 |
378 | @Property(
379 | type = PropertyType.SWITCH,
380 | name = "Remove pet lore's \"§eClick to summon!§r\" line in the pet menu",
381 | description = "This is a rather self-explanatory feature, but Essential's config menu renderer throws a hissy fit if you leave the description line empty, so now you're forced to read this.",
382 | category = "Cleanup",
383 | subcategory = "Lore"
384 | )
385 | public boolean cleanupLorePetClickToSummon = false;
386 |
387 | @Property(
388 | type = PropertyType.SWITCH,
389 | name = "Remove pet lore's \"§cClick to despawn!§r\" line in the pet menu",
390 | description = "This is a rather self-explanatory feature, but Essential's config menu renderer throws a hissy fit if you leave the description line empty, so now you're forced to read this.",
391 | category = "Cleanup",
392 | subcategory = "Lore"
393 | )
394 | public boolean cleanupLorePetClickToDespawn = false;
395 |
396 | @Property(
397 | type = PropertyType.SWITCH,
398 | name = "Compact pet lore's \"§a(X/10) Pet Candy Used§r\" line in the pet menu",
399 | description = "Example: §a(X/10) Pet Candy Used§r -> §aX Cand[y/ies]",
400 | category = "Cleanup",
401 | subcategory = "Lore"
402 | )
403 | public boolean cleanupLorePetCandiesUsed = false;
404 |
405 | @Property(
406 | type = PropertyType.SWITCH,
407 | name = "Auction house exception",
408 | description = "Stops the lore being cleaned up when the auction house menu is opened.",
409 | category = "Cleanup",
410 | subcategory = "Lore"
411 | )
412 | public boolean cleanupLoreAuctionException = false;
413 |
414 | @Property(
415 | type = PropertyType.SWITCH,
416 | name = "Remove old reforge messages",
417 | description = "Removes past reforge messages from chat when a new one is received.",
418 | category = "Cleanup",
419 | subcategory = "Chat"
420 | )
421 | public boolean cleanupChatOldReforgeMessages = false;
422 |
423 | @Property(
424 | type = PropertyType.SWITCH,
425 | name = "Remove tablist header",
426 | description = "Removes the message at the top of the tablist.",
427 | category = "Cleanup",
428 | subcategory = "Tablist"
429 | )
430 | public boolean cleanupTablistHeader = false;
431 |
432 | @Property(
433 | type = PropertyType.SWITCH,
434 | name = "Remove tablist footer",
435 | description = "Removes the last 2 lines at the bottom of the tablist.",
436 | category = "Cleanup",
437 | subcategory = "Tablist"
438 | )
439 | public boolean cleanupTablistFooter = false;
440 |
441 | //FUTURE
442 |
443 | @Property(
444 | type = PropertyType.SWITCH,
445 | name = "Keep sent messages",
446 | description = "Clearing the chat with F3 + D won't clear sent messages from the up and down arrows.",
447 | category = "Future features"
448 | )
449 | public boolean futureKeepSentMessages = false;
450 |
451 | @Property(
452 | type = PropertyType.SWITCH,
453 | name = "Chunk borders",
454 | description = "Pressing F3 + G toggles chunk borders.",
455 | category = "Future features"
456 | )
457 | public boolean futureChunkBorders = false;
458 |
459 | @Property(
460 | type = PropertyType.SWITCH,
461 | name = "Container chat",
462 | description = "Opens the chat when having a container open.",
463 | category = "Utilities"
464 | )
465 | public boolean utilitiesContainerChat = false;
466 |
467 | @Property(
468 | type = PropertyType.SWITCH,
469 | name = "Container control",
470 | description = "Requires to have the control key held down to be able to open chat inside a container.\nIf not toggled, holding control key down will not open container chat.",
471 | category = "Utilities"
472 | )
473 | public boolean utilitiesContainerControl = false;
474 |
475 | @Property(
476 | type = PropertyType.SWITCH,
477 | name = "Resize chat",
478 | description = "Resizes chat when inside a container for it to fit on the screen.",
479 | category = "Utilities"
480 | )
481 | public boolean utilitiesResizeContainerChat = false;
482 |
483 | @Property(
484 | type = PropertyType.SWITCH,
485 | name = "Reopen chat",
486 | description = "When a container is closed while typing, reopen chat with what you were typing.",
487 | category = "Utilities"
488 | )
489 | public boolean utilitiesReopenContainerChat = false;
490 |
491 | @Property(
492 | type = PropertyType.SWITCH,
493 | name = "Transfer chat",
494 | description = "When a container is opened while typing from chat or another container, carry over what you were typing.",
495 | category = "Utilities"
496 | )
497 | public boolean utilitiesTransferContainerChat = false;
498 |
499 | @Property(
500 | type = PropertyType.SWITCH,
501 | name = "Chat search mode",
502 | description = "Pressing Ctrl + F when chat is open will toggle search mode.",
503 | category = "Utilities"
504 | )
505 | public boolean utilitiesChatSearchMode = false;
506 |
507 | @Property(
508 | type = PropertyType.SWITCH,
509 | name = "Chat search instant refresh",
510 | description = "Chat will look for chat messages every key typed instead of only after pressing enter.",
511 | category = "Utilities"
512 | )
513 | public boolean utilitiesChatSearchKeyRefresh = false;
514 |
515 | @Property(
516 | type = PropertyType.SWITCH,
517 | name = "Search scroll",
518 | description = "Scrolls to a message when right clicked on while on search mode.",
519 | category = "Utilities"
520 | )
521 | public boolean utilitiesChatScrollClick = false;
522 |
523 | @Property(
524 | type = PropertyType.SWITCH,
525 | name = "Backpack retexturing",
526 | description = "Allows you to retexture storage backpacks.",
527 | category = "Utilities"
528 | )
529 | public boolean utilitiesBackpackRetexturing = false;
530 |
531 | @Property(
532 | type = PropertyType.SWITCH,
533 | name = "HOTM Perk Level Display",
534 | description = "Shows perk level as stack size.",
535 | category = "Utilities"
536 | )
537 | public boolean utilitiesPerkLevelDisplay = false;
538 |
539 | @Property(
540 | type = PropertyType.SWITCH,
541 | name = "HOTM Max Perk Display",
542 | description = "Shows perk level as stack size also on maxed perks.",
543 | category = "Utilities"
544 | )
545 | public boolean utilitiesMaxPerkLevelDisplay = false;
546 |
547 | @Property(
548 | type = PropertyType.SELECTOR,
549 | name = "Drop chance to drop rate",
550 | description = "Displays drop chances as drop rates in bestiary.",
551 | category = "Utilities",
552 | options = {
553 | "None",
554 | "Hold shift",
555 | "Permanent"
556 | }
557 | )
558 | public int utilitiesDropChanceToDropRate = 0;
559 |
560 | @Property(
561 | type = PropertyType.SWITCH,
562 | name = "Bestiary glance",
563 | description = "Displays bestiary level and progress in the bestiary menu.",
564 | category = "Utilities"
565 | )
566 | public boolean utilitiesBestiaryGlance = false;
567 |
568 | @Property(
569 | type = PropertyType.SWITCH,
570 | name = "Armadillo fix",
571 | description = "Stops armadillo blocking the screen when trying to mine blocks.",
572 | category = "Utilities"
573 | )
574 | public boolean utilitiesArmadilloFix = false;
575 |
576 | @Property(
577 | type = PropertyType.SWITCH,
578 | name = "WishingCompass helper",
579 | description = "Triangulates the location wishing compass points to. Use the item once, wait until the particle trail has disappeared, move away a bit and use it again. Make sure /pq is NOT \"off\".",
580 | category = "Utilities"
581 | )
582 | public boolean utilitiesWishingCompass = false;
583 |
584 | @Property(
585 | type = PropertyType.SWITCH,
586 | name = "Block triangulation item",
587 | description = "Blocks using wishing compass if the last trail hasn't disappeared.",
588 | category = "Utilities"
589 | )
590 | public boolean utilitiesBlockWishingCompass = false;
591 |
592 | @Property(
593 | type = PropertyType.SWITCH,
594 | name = "WishingCompass waypoints",
595 | description = "Sets a waypoint at the location calculated by triangulation. Uses Skytils' waypoints.",
596 | category = "Utilities"
597 | )
598 | public boolean utilitiesWishingCompassWaypoint = false;
599 |
600 | @Property(
601 | type = PropertyType.SWITCH,
602 | name = "AncestralSpade helper",
603 | description = "Triangulates the location ancestral spade points to. §cLook straight up or down§r, se the item once, wait until the particle trail has disappeared, move away a bit and use it again. Make sure /pq is NOT \"off\".",
604 | category = "Utilities"
605 | )
606 | public boolean utilitiesAncestralSpade = false;
607 |
608 | @Property(
609 | type = PropertyType.SWITCH,
610 | name = "Burrow waypoints",
611 | description = "Sets a waypoint at the location calculated by ancestral spade triangulation.",
612 | category = "Utilities"
613 | )
614 | public boolean utilitiesAncestralSpadeWaypoint = false;
615 |
616 | @Property(
617 | type = PropertyType.COLOR,
618 | name = "Burrow waypoint color",
619 | description = "The color of the waypoint beacon.",
620 | category = "Utilities",
621 | allowAlpha = false
622 | )
623 | public Color utilitiesAncestralSpadeWaypointColor = Color.RED;
624 |
625 | @Property(
626 | type = PropertyType.SWITCH,
627 | name = "Parse burrow arrow",
628 | description = "Saves the direction arrow from a burrow, making it only require an extra use of Ancestral Spade. If waypoints are in the opposite direction, lower /pq values are recommended.",
629 | category = "Utilities"
630 | )
631 | public boolean utilitiesAncestralSpadeArrow = false;
632 |
633 | @Property(
634 | type = PropertyType.SWITCH,
635 | name = "Display wishing compass uses left",
636 | description = "Displays the uses left on wishing compasses.",
637 | category = "Utilities"
638 | )
639 | public boolean utilitiesWishingCompassUsesLeft = false;
640 |
641 | @Property(
642 | type = PropertyType.SWITCH,
643 | name = "Always display wishing compass uses left",
644 | description = "Also displays uses left on wishing compasses when they have 3 uses left.",
645 | category = "Utilities"
646 | )
647 | public boolean utilitiesWishingCompassAlwaysUsesLeft = false;
648 |
649 | @Property(
650 | type = PropertyType.SWITCH,
651 | name = "Visible links",
652 | description = "Makes clickable links blue and underlined.",
653 | category = "Utilities"
654 | )
655 | public boolean utilitiesVisibleLinks = false;
656 |
657 | @Property(
658 | type = PropertyType.SWITCH,
659 | name = "Colorless panes",
660 | description = "Removes the color from glass panes so glass blocks are more visible.",
661 | category = "Utilities"
662 | )
663 | public boolean utilitiesColorlessPanes = false;
664 |
665 | @Property(
666 | type = PropertyType.SWITCH,
667 | name = "Chat in portal",
668 | description = "Lets you open and use chat inside a nether portal.",
669 | category = "Utilities"
670 | )
671 | public boolean utilitiesPortalChat = false;
672 |
673 | @Property(
674 | type = PropertyType.SWITCH,
675 | name = "Better wither impact perspective",
676 | description = "Toggling third person view will skip the front camera if holding a wither impact weapon.",
677 | category = "Utilities"
678 | )
679 | public boolean utilitiesWitherImpactPerspective = false;
680 |
681 | @Property(
682 | type = PropertyType.SWITCH,
683 | name = "Better perspective",
684 | description = "Makes Better wither impact perspective skip the wither impact test and will always skip the front camera.",
685 | category = "Utilities"
686 | )
687 | public boolean utilitiesWitherImpactPerspectiveGlobal = false;
688 |
689 | @Property(
690 | type = PropertyType.SWITCH,
691 | name = "Superpairs IDs",
692 | description = "Gives superpairs item rewards SkyBlock IDs so mods like NEU and SBE can display price and resource packs can display custom textures.",
693 | category = "Utilities"
694 | )
695 | public boolean utilitiesSuperpairsIDs = false;
696 |
697 | @Property(
698 | type = PropertyType.TEXT,
699 | name = "Share text",
700 | description = "Hold an item and type the text to show the item to other Synthesis users.",
701 | category = "Utilities",
702 | subcategory = "Share"
703 | )
704 | public String utilitiesShareText = "[item]";
705 |
706 | @Property(
707 | type = PropertyType.SWITCH,
708 | name = "Share scroll",
709 | description = "Scrolling while hovering a share and holding control will not scroll the chat.",
710 | category = "Utilities",
711 | subcategory = "Share"
712 | )
713 | public boolean utilitiesShareScroll = false;
714 |
715 | @Property(
716 | type = PropertyType.SWITCH,
717 | name = "Share copy embed",
718 | description = "Clicking on shares copies a link to clipboard, that embeds an item preview on discord.",
719 | category = "Utilities",
720 | subcategory = "Share"
721 | )
722 | public boolean utilitiesShareCopyEmbed = false;
723 |
724 | @Property(
725 | type = PropertyType.SWITCH,
726 | name = "Better bridge message",
727 | description = "Reformats guild bridge messages.",
728 | category = "Utilities",
729 | subcategory = "Bridge"
730 | )
731 | public boolean utilitiesBridge = false;
732 |
733 | @Property(
734 | type = PropertyType.TEXT,
735 | name = "Bridge bot name",
736 | description = "The IGN of the minecraft account acting as a bridge. Case sensitive.",
737 | category = "Utilities",
738 | subcategory = "Bridge",
739 | min = 1,
740 | max = 16
741 | )
742 | public String utilitiesBridgeBotName = "mmmmBeepBeepBeep";
743 |
744 | @Property(
745 | type = PropertyType.TEXT,
746 | name = "Bridge message format",
747 | description = "The message that will be sent when a message is sent from discord. Use and for message sender and message. Use & for color codes.",
748 | category = "Utilities",
749 | subcategory = "Bridge"
750 | )
751 | public String utilitiesBridgeMessageFormat = "&9[Discord] &6&r: ";
752 |
753 | @Property(
754 | type = PropertyType.BUTTON,
755 | name = "Test bridge message",
756 | description = "Send in chat a message formatted like the above format. Useful for testing that format.",
757 | category = "Utilities",
758 | subcategory = "Bridge",
759 | placeholder = "Test"
760 | )
761 | public void utilitiesBridgeTestFormat() {
762 | Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(utilitiesBridgeMessageFormat.replaceAll("&", "§").replace("", "Luna").replace("", "This is an example message. Thank you for using Synthesis!")));
763 | }
764 |
765 | @Property(
766 | type = PropertyType.BUTTON,
767 | name = "Color code guide",
768 | description = "Sends a chat message with all formatting codes.",
769 | category = "Utilities",
770 | subcategory = "Bridge",
771 | placeholder = "Show"
772 | )
773 | public void utilitiesBridgeColorCodeGuide() {
774 | for (EnumChatFormatting value : EnumChatFormatting.values()) {
775 | if (value.getFriendlyName().equals("obfuscated")) {
776 | Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( "&" + value.toString().replace("§", "") + " - " + value + value.getFriendlyName()));
777 | } else {
778 | Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(value + "&" + value.toString().replace("§", "") + " - " + value.getFriendlyName()));
779 | }
780 | }
781 | }
782 |
783 | @Property(
784 | type = PropertyType.SWITCH,
785 | name = "Bridge guild chat tab",
786 | description = "If using skytils' chattabs, moves formatted bridge messages to the guild tab.",
787 | category = "Utilities",
788 | subcategory = "Bridge"
789 | )
790 | public boolean utilitiesBridgeGuildChatTab = true;
791 |
792 | @Property(
793 | type = PropertyType.TEXT,
794 | name = "Custom cape",
795 | description = "Use someone else's optifine cape. Only you will see this! Leave empty to not use someone else's cape.",
796 | category = "Utilities",
797 | subcategory = "Optifine",
798 | min = 1,
799 | max = 16
800 | )
801 | public String utilitiesOptifineCustomCape = "";
802 |
803 | @Property(
804 | type = PropertyType.SWITCH,
805 | name = "Trans yeti",
806 | description = "Gives the yeti a trans cape.",
807 | category = "Utilities",
808 | subcategory = "Optifine"
809 | )
810 | public boolean utilitiesOptifineTransYeti = true;
811 |
812 | @Property(
813 | type = PropertyType.SWITCH,
814 | name = "Trans terracotta",
815 | description = "Gives the terracotta a trans cape.",
816 | category = "Utilities",
817 | subcategory = "Optifine"
818 | )
819 | public boolean utilitiesOptifineTransTerracotta = true;
820 |
821 | @Property(
822 | type = PropertyType.SWITCH,
823 | name = "Non binary bonzo",
824 | description = "Gives bonzo a non binary cape.",
825 | category = "Utilities",
826 | subcategory = "Optifine"
827 | )
828 | public boolean utilitiesOptifineNonBinaryBonzo = true;
829 |
830 | @Property(
831 | type = PropertyType.SWITCH,
832 | name = "Candy cane grinch",
833 | description = "Gives the grinch a candy cane cape.",
834 | category = "Utilities",
835 | subcategory = "Optifine"
836 | )
837 | public boolean utilitiesOptifineCandyCaneGrinch = true;
838 |
839 | @Property(
840 | type = PropertyType.SWITCH,
841 | name = "Hide santa/witch hat",
842 | description = "Hides the witch/santa hat given to players with capes on halloween/christmas.",
843 | category = "Utilities",
844 | subcategory = "Optifine"
845 | )
846 | public boolean utilitiesOptifineHideHats = false;
847 |
848 | //PATCHER
849 |
850 | @Property(
851 | type = PropertyType.SWITCH,
852 | name = "Compact chat fix",
853 | description = "Fixes chat messages not being removed with compact chat when the chat is refreshed.",
854 | category = "Patcher"
855 | )
856 | public boolean patcherCompactChatFix = true;
857 |
858 | @Property(
859 | type = PropertyType.SWITCH,
860 | name = "Custom image preview domains",
861 | description = "Lets you set and use custom domains for Patcher's ImagePreview. Do not add sites you do not trust. Use at own risk.",
862 | category = "Patcher"
863 | )
864 | public boolean patcherCustomImagePreviewer = false;
865 |
866 | @Property(
867 | type = PropertyType.TEXT,
868 | name = "Custom domains",
869 | description = "Look, I'm way too lazy to store this in a json as an array or whatever. It's literally just text why would I care.",
870 | category = "Patcher",
871 | hidden = true
872 | )
873 | public String patcherCustomDomains = "";
874 |
875 | public Config() {
876 | super(new File(Synthesis.configLocation), "§dSynthesis", new JVMAnnotationPropertyCollector(), new CustomSortingBehavior());
877 | initialize();
878 | setSubcategoryDescription("Utilities", "Share", "A simple way to show your items to other people using the mod. Hold the item, type whatever \"Share text\" is and a preview for your item will be sent.");
879 | hidePropertyIf("patcherCompactChatFix", () -> !Loader.isModLoaded("patcher"));
880 | hidePropertyIf("patcherCustomImagePreviewer", () -> !Loader.isModLoaded("patcher"));
881 | hidePropertyIf("utilitiesShareScroll", () -> !Loader.isModLoaded("text_overflow_scroll"));
882 | hidePropertyIf("utilitiesWishingCompassWaypoint", () -> !Loader.isModLoaded("skytils"));
883 | addDependency("utilitiesWishingCompassWaypoint", "utilitiesWishingCompass");
884 | addDependency("utilitiesBlockWishingCompass", "utilitiesWishingCompass");
885 | addDependency("utilitiesContainerControl", "utilitiesContainerChat");
886 | addDependency("cleanupDungeonBlessingMessages", "cleanupDungeonBlessingStatMessages");
887 | addDependency("utilitiesWitherImpactPerspectiveGlobal", "utilitiesWitherImpactPerspective");
888 | registerListener("utilitiesColorlessPanes", (z) -> Minecraft.getMinecraft().renderGlobal.loadRenderers());
889 | }
890 | }
891 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/core/CustomSortingBehavior.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.core;
2 |
3 | import gg.essential.vigilance.data.Category;
4 | import gg.essential.vigilance.data.PropertyData;
5 | import gg.essential.vigilance.data.SortingBehavior;
6 | import org.jetbrains.annotations.NotNull;
7 |
8 | import java.util.Comparator;
9 | import java.util.List;
10 | import java.util.Map;
11 |
12 | public class CustomSortingBehavior extends SortingBehavior {
13 |
14 | @NotNull
15 | @Override
16 | public Comparator super Category> getCategoryComparator() {
17 | return (o1, o2) -> 0;
18 | }
19 |
20 | @NotNull
21 | @Override
22 | public Comparator super PropertyData> getPropertyComparator() {
23 | return (o1, o2) -> 0;
24 | }
25 |
26 | @NotNull
27 | @Override
28 | public Comparator super Map.Entry>> getSubcategoryComparator() {
29 | return (o1, o2) -> 0;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/events/MessageSentEvent.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.events;
2 |
3 | import net.minecraftforge.fml.common.eventhandler.Cancelable;
4 | import net.minecraftforge.fml.common.eventhandler.Event;
5 |
6 | @Cancelable
7 | public class MessageSentEvent extends Event {
8 | public String message;
9 |
10 | public MessageSentEvent(String message) {
11 | this.message = message;
12 | }
13 | }
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/events/packet/CustomChannelDuplexHandler.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.events.packet;
2 |
3 | import io.netty.channel.ChannelDuplexHandler;
4 | import io.netty.channel.ChannelHandlerContext;
5 | import io.netty.channel.ChannelPromise;
6 | import net.minecraft.network.Packet;
7 | import net.minecraftforge.common.MinecraftForge;
8 |
9 | // https://github.com/ChatTriggers/ChatTriggers/pull/232
10 | public class CustomChannelDuplexHandler extends ChannelDuplexHandler {
11 | @Override
12 | public void channelRead(ChannelHandlerContext ctx, Object msg) {
13 | if (msg instanceof Packet>) {
14 | PacketReceivedEvent event = new PacketReceivedEvent((Packet>) msg);
15 | MinecraftForge.EVENT_BUS.post(event);
16 |
17 | if (!event.isCanceled())
18 | ctx.fireChannelRead(event.getPacket());
19 | }
20 | }
21 |
22 | @Override
23 | public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
24 | if (msg instanceof Packet>) {
25 | PacketSentEvent event = new PacketSentEvent((Packet>) msg);
26 | MinecraftForge.EVENT_BUS.post(event);
27 |
28 | if (!event.isCanceled())
29 | ctx.write(event.getPacket(), promise);
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/events/packet/PacketEvent.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.events.packet;
2 |
3 | import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
4 | import net.minecraftforge.fml.common.network.FMLNetworkEvent;
5 |
6 | public class PacketEvent {
7 | @SubscribeEvent
8 | public void onNetworkEvent(FMLNetworkEvent.ClientConnectedToServerEvent event) {
9 | event.manager.channel().pipeline().addAfter(
10 | "fml:packet_handler",
11 | "synthesis_packet_handler",
12 | new CustomChannelDuplexHandler()
13 | );
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/events/packet/PacketReceivedEvent.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.events.packet;
2 |
3 | import lombok.Getter;
4 | import net.minecraft.network.Packet;
5 | import net.minecraftforge.fml.common.eventhandler.Event;
6 |
7 | public class PacketReceivedEvent extends Event {
8 | @Getter private final Packet> packet;
9 | private Boolean cancelled = false;
10 |
11 | public PacketReceivedEvent(Packet> packet) {
12 | this.packet = packet;
13 | }
14 |
15 | @Override
16 | public boolean isCancelable() {
17 | return true;
18 | }
19 |
20 | @Override
21 | public boolean isCanceled() {
22 | return cancelled;
23 | }
24 |
25 | @Override
26 | public void setCanceled(boolean cancel) {
27 | cancelled = cancel;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/events/packet/PacketSentEvent.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.events.packet;
2 |
3 | import lombok.Getter;
4 | import net.minecraft.network.Packet;
5 | import net.minecraftforge.fml.common.eventhandler.Event;
6 |
7 | public class PacketSentEvent extends Event {
8 | @Getter private final Packet> packet;
9 | private Boolean cancelled = false;
10 |
11 | public PacketSentEvent(Packet> packet) {
12 | this.packet = packet;
13 | }
14 |
15 | @Override
16 | public boolean isCancelable() {
17 | return true;
18 | }
19 |
20 | @Override
21 | public boolean isCanceled() {
22 | return cancelled;
23 | }
24 |
25 | @Override
26 | public void setCanceled(boolean cancel) {
27 | cancelled = cancel;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/features/cleanup/CoopCleanup.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.features.cleanup;
2 |
3 | import com.luna.synthesis.Synthesis;
4 | import com.luna.synthesis.core.Config;
5 | import com.luna.synthesis.events.packet.PacketReceivedEvent;
6 | import com.luna.synthesis.utils.ChatLib;
7 | import com.luna.synthesis.utils.Utils;
8 | import net.minecraft.client.Minecraft;
9 | import net.minecraft.event.HoverEvent;
10 | import net.minecraft.network.play.server.S02PacketChat;
11 | import net.minecraft.util.ChatComponentText;
12 | import net.minecraft.util.EnumChatFormatting;
13 | import net.minecraft.util.IChatComponent;
14 | import net.minecraftforge.client.event.ClientChatReceivedEvent;
15 | import net.minecraftforge.event.entity.player.ItemTooltipEvent;
16 | import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
17 |
18 | import java.util.ArrayList;
19 | import java.util.Iterator;
20 | import java.util.List;
21 | import java.util.concurrent.atomic.AtomicReference;
22 | import java.util.stream.Collectors;
23 |
24 | public class CoopCleanup {
25 |
26 | private final Config config = Synthesis.getInstance().getConfig();
27 | private boolean onContributions = false;
28 | private boolean shouldRemove = false;
29 |
30 | private List messageQueue = new ArrayList<>();
31 | private boolean isDividerBlock = false;
32 | private IChatComponent theMessage = null;
33 | private final AtomicReference price = new AtomicReference<>("");
34 |
35 | // I'm deeply terrified of regexes being called way too many times, as long as the message cannot be faked or give false positives, this will have to work.
36 | @SubscribeEvent
37 | public void onTooltip(ItemTooltipEvent event) {
38 | if (config.cleanupCoopCollections == 0) return;
39 | if (config.cleanupCoopCollections == 1) {
40 | event.toolTip.removeIf(s -> EnumChatFormatting.getTextWithoutFormattingCodes(s).endsWith(": 0"));
41 | } else if (config.cleanupCoopCollections == 2) {
42 | Iterator iterator = event.toolTip.iterator();
43 | while (iterator.hasNext()) {
44 | String actualLine = EnumChatFormatting.getTextWithoutFormattingCodes(iterator.next());
45 | if (actualLine.equals("")) {
46 | onContributions = false;
47 | }
48 | if (onContributions) {
49 | String player = Minecraft.getMinecraft().getSession().getUsername();
50 | if (!actualLine.contains(player)) {
51 | iterator.remove();
52 | }
53 | }
54 | if (actualLine.startsWith("Co-op Contributions:")) {
55 | onContributions = true;
56 | }
57 | }
58 | onContributions = false;
59 | } else if (config.cleanupCoopCollections == 3) {
60 | Iterator iterator = event.toolTip.iterator();
61 | while (iterator.hasNext()) {
62 | String actualLine = EnumChatFormatting.getTextWithoutFormattingCodes(iterator.next());
63 | if (actualLine.startsWith("Co-op Contributions:")) {
64 | shouldRemove = true;
65 | }
66 | if (shouldRemove) {
67 | iterator.remove();
68 | }
69 | if (actualLine.startsWith("Total Collected: ")) {
70 | shouldRemove = true;
71 | }
72 | if (actualLine.equals("")) {
73 | shouldRemove = false;
74 | }
75 | }
76 | shouldRemove = false;
77 | }
78 | }
79 |
80 | // It is not necessary to check hover action because the " » " changes color depending on party/coop member, but I realised that when this was already done so whatever
81 | @SubscribeEvent
82 | public void onChatMessage(ClientChatReceivedEvent event) {
83 | if (!config.cleanupCoopTravel) return;
84 | if (event.type != 0) return;
85 | String message = EnumChatFormatting.getTextWithoutFormattingCodes(event.message.getUnformattedText());
86 | if (message.startsWith(" » ") && message.contains(" is traveling to ") && message.endsWith(" FOLLOW")) {
87 | if (event.message.getChatStyle() != null) {
88 | HoverEvent hover = event.message.getChatStyle().getChatHoverEvent();
89 | if (hover == null) return;
90 | if (hover.getAction() == HoverEvent.Action.SHOW_TEXT) {
91 | String text = EnumChatFormatting.getTextWithoutFormattingCodes(hover.getValue().getUnformattedText());
92 | if (!text.startsWith("SkyBlock Travel")) return;
93 | if (text.split("\n").length >= 2) {
94 | text = text.split("\n")[1];
95 | }
96 | if (!text.equals("Party member")) {
97 | event.setCanceled(true);
98 | }
99 | }
100 | }
101 | }
102 | if (!messageQueue.isEmpty() && !isDividerBlock) {
103 | if (event.message.getUnformattedText().equals(messageQueue.get(0))) {
104 | messageQueue.remove(0);
105 | event.setCanceled(true);
106 | }
107 | }
108 | if (event.message.getUnformattedText().startsWith("BIN Auction started for ")) {
109 | if (!price.get().equals("")) {
110 | event.message = new ChatComponentText(event.message.getFormattedText().replace("!", "") + EnumChatFormatting.YELLOW + " at " + EnumChatFormatting.GOLD + price.get() + " coins" + EnumChatFormatting.YELLOW + "!");
111 | price.set("");
112 | } else {
113 | theMessage = event.message;
114 | event.setCanceled(true);
115 | }
116 | }
117 | }
118 |
119 | // Used as a way to detect bulk messages (the ones between dividers) and filter out potential messages that got caught between them.
120 | @SubscribeEvent
121 | public void onPacketReceived(PacketReceivedEvent event) {
122 | if (event.getPacket() instanceof S02PacketChat) {
123 | S02PacketChat packet = (S02PacketChat) event.getPacket();
124 | if (packet.getType() != 2) {
125 | if (isDividerBlock) {
126 | messageQueue.add(packet.getChatComponent().getUnformattedText());
127 | }
128 | if (Utils.isDivider(packet.getChatComponent().getUnformattedText())) {
129 | if (isDividerBlock) {
130 | isDividerBlock = false;
131 | String player = Minecraft.getMinecraft().getSession().getUsername();
132 | messageQueue = messageQueue.stream().filter(s -> {
133 | if (Utils.isDivider(s)) return true;
134 | if (s.contains(" created a BIN auction for ") || s.contains(" created an auction for ")) {
135 | switch (config.cleanupCoopAuctionCreation) {
136 | case 0:
137 | return false;
138 | case 1:
139 | return s.contains(player);
140 | case 2:
141 | if (s.contains(player) && s.endsWith(" coins!")) {
142 | price.set(s.split(" at ")[1].replace(" coins!", ""));
143 | return true;
144 | }
145 | return false;
146 | case 3:
147 | return !s.contains(player);
148 | case 4:
149 | return true;
150 | case 5:
151 | if (s.contains(player) && s.endsWith(" coins!")) {
152 | price.set(s.split(" at ")[1].replace(" coins!", ""));
153 | }
154 | return true;
155 | }
156 | } else if (s.contains(" cancelled an auction ")) {
157 | switch (config.cleanupCoopAuctionCancellation) {
158 | case 0:
159 | return false;
160 | case 1:
161 | return s.contains(player);
162 | case 2:
163 | return !s.contains(player);
164 | case 3:
165 | return true;
166 | }
167 | } else if (s.contains(" collected an auction for ")) {
168 | switch (config.cleanupCoopAuctionCollection) {
169 | case 0:
170 | return false;
171 | case 1:
172 | return s.contains(player);
173 | case 2:
174 | return !s.contains(player);
175 | case 3:
176 | return true;
177 | }
178 | } else if (s.contains(" has set the beacon profile stat to ")) {
179 | switch (config.cleanupCoopBeaconStatChanges) {
180 | case 0:
181 | return false;
182 | case 1:
183 | return s.contains(player);
184 | case 2:
185 | return !s.contains(player);
186 | case 3:
187 | return true;
188 | }
189 | }
190 | return false;
191 | }).collect(Collectors.toList());
192 | if (messageQueue.size() <= 2) messageQueue.clear();
193 | if (theMessage != null && !price.get().equals("")) {
194 | Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(theMessage.getFormattedText().replace("!", "") + EnumChatFormatting.YELLOW + " at " + EnumChatFormatting.GOLD + price.get() + " coins" + EnumChatFormatting.YELLOW + "!"));
195 | theMessage = null;
196 | price.set("");
197 | }
198 | } else {
199 | isDividerBlock = true;
200 | messageQueue.add(packet.getChatComponent().getUnformattedText());
201 | }
202 | }
203 | }
204 | }
205 | }
206 | }
207 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/features/cleanup/DungeonCleanup.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.features.cleanup;
2 |
3 | import com.luna.synthesis.Synthesis;
4 | import com.luna.synthesis.core.Config;
5 | import net.minecraft.util.StringUtils;
6 | import net.minecraftforge.client.event.ClientChatReceivedEvent;
7 | import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
8 |
9 | public class DungeonCleanup {
10 |
11 | private final Config config = Synthesis.getInstance().getConfig();
12 |
13 | @SubscribeEvent
14 | public void onChatMessage(ClientChatReceivedEvent event) {
15 | if (event.type != 0) return;
16 | String msg = StringUtils.stripControlCodes(event.message.getUnformattedText());
17 | if (!msg.contains(":")) {
18 | if (config.cleanupDungeonPotionEffects && msg.equals("Your active Potion Effects have been paused and stored. They will be restored when you leave Dungeons! You are not allowed to use existing Potion Effects while in Dungeons.")) {
19 | event.setCanceled(true);
20 | }
21 | if (config.cleanupDungeonSoloClassMessage) {
22 | if (msg.startsWith("Your ") && msg.endsWith(" stats are doubled because you are the only player using this class!")) {
23 | event.setCanceled(true);
24 | } else if (msg.startsWith("[Healer] ") || msg.startsWith("[Berserk] ") || msg.startsWith("[Mage] ") || msg.startsWith("[Archer] ") || msg.startsWith("[Tank] ")) {
25 | event.setCanceled(true);
26 | }
27 | }
28 | if (config.cleanupDungeonUltimateMessage && msg.endsWith(" is ready to use! Press DROP to activate it!")) {
29 | event.setCanceled(true);
30 | }
31 | if (config.cleanupDungeonBlessingStatMessages) {
32 | if ((config.cleanupDungeonBlessingMessages && (msg.startsWith("A Blessing of ") || (msg.contains(" has obtained Blessing of ") && msg.endsWith("!")))) || msg.startsWith("DUNGEON BUFF! A Blessing of ") || msg.startsWith("DUNGEON BUFF! You found a Blessing of ") || msg.startsWith(" Grants you ") || msg.startsWith(" Granted you ")) {
33 | event.setCanceled(true);
34 | }
35 | }
36 | if (config.cleanupDungeonSilverfishMessages && msg.equals("You cannot hit the silverfish while it's moving!")) {
37 | event.setCanceled(true);
38 | }
39 | if (config.cleanupDungeonKeyUsageMessages && (msg.equals("RIGHT CLICK on the BLOOD DOOR to open it. This key can only be used to open 1 door!") || msg.equals("RIGHT CLICK on a WITHER door to open it. This key can only be used to open 1 door!"))) {
40 | event.setCanceled(true);
41 | }
42 | }
43 | if (config.cleanupDungeonWatcherMessages && msg.startsWith("[BOSS] The Watcher: ") && !msg.equals("[BOSS] The Watcher: You have proven yourself. You may pass.")) {
44 | event.setCanceled(true);
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/features/cleanup/LoreCleanup.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.features.cleanup;
2 |
3 | import com.luna.synthesis.Synthesis;
4 | import com.luna.synthesis.core.Config;
5 | import net.minecraft.client.Minecraft;
6 | import net.minecraft.inventory.ContainerChest;
7 | import net.minecraft.item.ItemStack;
8 | import net.minecraft.util.StringUtils;
9 | import net.minecraftforge.event.entity.player.ItemTooltipEvent;
10 | import net.minecraftforge.fml.common.eventhandler.EventPriority;
11 | import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
12 |
13 | import net.minecraft.item.ItemSkull;
14 |
15 | import java.util.Iterator;
16 |
17 | public class LoreCleanup {
18 |
19 | private final Config config = Synthesis.getInstance().getConfig();
20 | // Some fucking tasty spaghetti
21 |
22 | @SubscribeEvent(priority = EventPriority.LOW)
23 | public void onItemTooltip(ItemTooltipEvent event) {
24 | if (Minecraft.getMinecraft().thePlayer.openContainer instanceof ContainerChest) {
25 | ContainerChest containerChest = (ContainerChest)Minecraft.getMinecraft().thePlayer.openContainer;
26 | String title = StringUtils.stripControlCodes(containerChest.getLowerChestInventory().getDisplayName().getUnformattedText());
27 | if (config.cleanupLoreAuctionException && (title.startsWith("Auctions") || title.endsWith("Auction View") || title.endsWith("'s Auctions"))) return;
28 | }
29 | ItemStack item = event.itemStack;
30 | if (!item.hasTagCompound() || !item.getTagCompound().hasKey("ExtraAttributes") || !item.getTagCompound().getCompoundTag("ExtraAttributes").hasKey("id")) return;
31 | Iterator iterator = event.toolTip.iterator();
32 | int index = 0;
33 | boolean inEnchantments = false;
34 | boolean inAbility = false;
35 | boolean petHoldingItem = false;
36 | boolean inPetsMenuAndIsAPet = ((item.getItem() instanceof ItemSkull && Minecraft.getMinecraft().thePlayer.openContainer instanceof ContainerChest && StringUtils.stripControlCodes(((ContainerChest)(Minecraft.getMinecraft().thePlayer.openContainer)).getLowerChestInventory().getDisplayName().getUnformattedText()).endsWith("Pets")) && (item.getDisplayName().matches(".+\\[Lvl \\d+\\] (?§[0-9a-fk-or]).+") || item.getDisplayName().matches(".+\\[\\d+\\] (?§[0-9a-fk-or]).+")));
37 | String previousLine = "";
38 | while (iterator.hasNext()) {
39 | // Thank you vanilla, very cool
40 | String line = iterator.next().replace("§5§o", "");
41 | // GEAR SCORE, GEMSTONE SLOTS, SOULBOUND, PET STUFF
42 | if (config.cleanupPetDisplayName && inPetsMenuAndIsAPet && StringUtils.stripControlCodes(item.getDisplayName()).startsWith("[Lvl ") && StringUtils.stripControlCodes(item.getDisplayName()).contains("] ")){
43 | item.setStackDisplayName(item.getDisplayName().replace("Lvl ", ""));
44 | }
45 | /* CONDITIONAL TO SKIP BASE CASE LINES, EDIT WITH CAUTION! -ERY */
46 | else if (inPetsMenuAndIsAPet && (previousLine.startsWith("§6") && previousLine.contains("Held Item"))) {
47 | //(inPetsMenuAndIsAPet && (previousLine.startsWith("§6") && previousLine.contains("Held Item")) || line.matches(".*§7[a-z].*") || line.matches(".*§[abcde569].*")) //PLAN: THERE IS NONE. HYPIXEL IS SO INCONSISTENT WITH THEIR LINE SPACING I'M SURPRISED ANY OF THE UNCOMMENTED CODE I WROTE EVEN WORKS. -ERY
48 | previousLine = line;
49 | } else if (config.cleanupLorePetType > 0 && config.cleanupLorePetType < 4 && inPetsMenuAndIsAPet && line.startsWith("§8") && (line.endsWith(" Pet") || line.endsWith(" Mount") || line.endsWith(" Morph") || line.endsWith(" gain XP") || line.contains("All Skills"))) {
50 | previousLine = line;
51 | if (config.cleanupLorePetType == 3 || line.contains("All Skills"))
52 | iterator.remove();
53 | else if (config.cleanupLorePetType == 2 && !line.contains("All Skills"))
54 | event.toolTip.set(index, line.replace("Mining ", "").replace("Combat ", "").replace("Fishing ", "").replace("Farming ", "").replace("Foraging ", "").replace("Enchanting ", "").replace("Alchemy ", "").replace("Gabagool ", ""));
55 | else if (config.cleanupLorePetType == 1)
56 | event.toolTip.set(index, line.replace(" Pet", "").replace(" Mount", "").replace(" Morph", "").replace(", feed to gain XP", ""));
57 | } else if (config.cleanupLorePetPerkName && inPetsMenuAndIsAPet && line.startsWith("§6") && !line.contains("Held Item")) {
58 | previousLine = line;
59 | iterator.remove();
60 | }
61 | /* PLAN: SOMEHOW DETECT THE BEGINNING OF A NEW PERK DESCRIPTION AND ADD A HYPHEN TO THE BEGINNING OF IT.
62 | I ALREADY TRIED THE "inXYZ" CONDITIONAL STRATEGY AND IT WENT TERRIBLY WRONG BECAUSE, AGAIN, HYPIXEL
63 | PET MENU LORE HAS NO STANDARD CONVENTION WHATSOEVER. -ERY
64 |
65 | else if (config.cleanupLorePetPerkHyphens && inPetsMenuAndIsAPet && line.contains("§7§7") && !line.contains(":") && line.matches(".*§7§7[A-Z].*") && !previousLine.contains("Held Item")) {
66 | event.toolTip.set(index, ("§e§r§7- " + line));
67 | previousLine = line;
68 | continue;
69 | */
70 | else if (config.cleanupLorePetHeldItemPrefix && inPetsMenuAndIsAPet && line.contains("Held Item")) {
71 | previousLine = line;
72 | event.toolTip.set(index, line.replace("Held Item: ", ""));
73 | petHoldingItem = true;
74 | } else if (config.cleanupLorePetMaxLevel && inPetsMenuAndIsAPet && line.contains("MAX LEVEL")) {
75 | previousLine = line;
76 | iterator.remove();
77 | } else if (config.cleanupLorePetClickToSummon && inPetsMenuAndIsAPet && line.contains("Click to summon!")) {
78 | previousLine = line;
79 | iterator.remove();
80 | } else if (config.cleanupLorePetClickToDespawn && inPetsMenuAndIsAPet && line.contains("Click to despawn!")) {
81 | previousLine = line;
82 | iterator.remove();
83 | } else if (config.cleanupLorePetCandiesUsed && inPetsMenuAndIsAPet && line.contains("Pet Candy Used")) {
84 | previousLine = line;
85 | // begin the very hacky solution i wrote but it works on the pets that i own so im rolling with this unless anyone has better ideas -ery
86 | int ifPetHeldItemEnabledOffset = 2;
87 | if (!config.cleanupLorePetHeldItemPrefix)
88 | if (!petHoldingItem)
89 | ifPetHeldItemEnabledOffset = 0;
90 | else
91 | ifPetHeldItemEnabledOffset = 1;
92 | else if (!petHoldingItem)
93 | ifPetHeldItemEnabledOffset = 0;
94 | // end hacky solution -ery
95 | String pluralOrSingular = "Candies";
96 | if (line.contains("1/") && !line.contains("10/"))
97 | pluralOrSingular = "Candy";
98 | event.toolTip.set(index + ifPetHeldItemEnabledOffset, line.replace("/10", "").replace("Pet Candy Used", pluralOrSingular).replace("(", "").replace(")", ""));
99 | } else if (config.cleanupLorePetEmptyLines && inPetsMenuAndIsAPet && line.equals("")) {
100 | previousLine = line;
101 | iterator.remove();
102 | }
103 | /* PLAN: SOMEHOW REMOVE PROGRESS BAR WITHOUT EDGE CASES OF PROGRESS COUNT DUPLICATING ITSELF.
104 | ATTEMPTED AND FAILED BECAUSE AAAAAAAAAAAAAAAAAA -ERY
105 |
106 | else if (config.cleanupLorePetLevelProgressBar && inPetsMenuAndIsAPet && line.contains("--") && (line.contains("f-") || line.contains("2-"))) {
107 | event.toolTip.set(index, line.replaceAll("-", ""));
108 | previousLine = line;
109 | // iterator.remove();
110 | continue;
111 | }
112 | */
113 | /* PLAN: SOMEHOW REMOVE TEXT PRECEDING PERCENTAGE PROGRESS.
114 | ATTEMPTED AND FAILED BECAUSE AAAAAAAAAAAAAAAAAA -ERY
115 |
116 | else if (config.cleanupLorePetLevelPercent && inPetsMenuAndIsAPet && line.contains("Progress to Level")) {
117 | event.toolTip.set(index, line.replaceAll(".*Progress to Level [0-9]{1,3}.*", "% of next Lvl"));
118 | // previousLine = line;
119 | continue;
120 | }
121 | */
122 | else if (StringUtils.stripControlCodes(line).startsWith("Gear Score: ") && config.cleanupLoreGearScore) {
123 | iterator.remove();
124 | } else if (StringUtils.stripControlCodes(line).startsWith(" [") && config.cleanupLoreGemstoneSlots) {
125 | iterator.remove();
126 | } else if ((line.contains("§8§l") && line.contains("*") && line.contains("8Co-op Soulbound")) && config.cleanupLoreCoopSoulbound) {
127 | iterator.remove();
128 | } else if ((line.contains("§8§l") && line.contains("*") && line.contains("8Soulbound")) && config.cleanupLoreSoloSoulbound) {
129 | iterator.remove();
130 | } else {
131 | // STAT BONUSES, RECOMBOBULATED TEXT
132 | if (line.contains(" ")) {
133 | for (String s : line.split(" ")) {
134 | String replacement = line.replace(s + " ", "").replace(s, "");
135 | if (s.startsWith("§8(+") && config.cleanupLoreDungeon) {
136 | event.toolTip.set(index, replacement);
137 | line = replacement;
138 | } else if (s.startsWith("§d(+") && config.cleanupLoreGemstones) {
139 | event.toolTip.set(index, replacement);
140 | line = replacement;
141 | } else if (s.startsWith("§9(+") && config.cleanupLoreReforge) {
142 | event.toolTip.set(index, replacement);
143 | line = replacement;
144 | } else if (s.startsWith("§e(+") && config.cleanupLoreHPB) {
145 | event.toolTip.set(index, replacement);
146 | line = replacement;
147 | } else if (s.contains("§l§ka") && config.cleanupLoreRecombobulatedObfuscated) {
148 | event.toolTip.set(index, replacement);
149 | line = replacement;
150 | }
151 | }
152 | }
153 |
154 | // ENCHANTMENTS
155 | if (!StringUtils.stripControlCodes(item.getDisplayName()).equals("Enchanted Book")) {
156 | if (((line.startsWith("§9") || line.startsWith("§d§l")) && config.cleanupLoreEnchantmentDescriptions && !(inPetsMenuAndIsAPet && item.getItem() instanceof ItemSkull))) inEnchantments = true;
157 | if (inEnchantments) {
158 | if (!config.cleanupLoreEnchantments && (line.startsWith("§9") || line.startsWith("§d§l"))) {
159 | index++;
160 | continue;
161 | }
162 | if (StringUtils.stripControlCodes(line).equals("")) {
163 | iterator.remove();
164 | continue;
165 | }
166 | inEnchantments = false;
167 | if (config.cleanupLoreEnchantments) {
168 | iterator.remove();
169 | continue;
170 | }
171 | }
172 | }
173 |
174 | // ABILITIES
175 | if (!line.endsWith("RIGHT CLICK") && !line.endsWith("LEFT CLICK") && !line.equals("§aScroll Abilities:")) {
176 | if (config.cleanupLoreReforgeAbility && line.startsWith("§9") && line.endsWith(" Bonus")) inAbility = true;
177 | else if (config.cleanupLoreFullSetBonus && line.startsWith("§6Full Set Bonus: ")) inAbility = true;
178 | else if (config.cleanupLorePieceBonus && line.startsWith("§6Piece Bonus: ")) inAbility = true;
179 | } else if (config.cleanupLoreAbilities) {
180 | inAbility = true;
181 | }
182 | if (inAbility) {
183 | iterator.remove();
184 | if (line.equals("")) inAbility = false;
185 | } else {
186 | index++;
187 | }
188 | }
189 | }
190 |
191 | }
192 | }
193 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/features/future/ChunkBorders.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.features.future;
2 |
3 | import com.luna.synthesis.Synthesis;
4 | import com.luna.synthesis.core.Config;
5 | import net.minecraft.client.Minecraft;
6 | import net.minecraft.client.renderer.GlStateManager;
7 | import net.minecraft.client.renderer.Tessellator;
8 | import net.minecraft.client.renderer.WorldRenderer;
9 | import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
10 | import net.minecraft.entity.player.EntityPlayer;
11 | import net.minecraftforge.client.event.RenderWorldLastEvent;
12 | import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
13 | import net.minecraftforge.fml.common.gameevent.InputEvent;
14 | import org.lwjgl.input.Keyboard;
15 | import org.lwjgl.opengl.GL11;
16 |
17 | public class ChunkBorders {
18 |
19 | private final Config config = Synthesis.getInstance().getConfig();
20 | private boolean isToggled = false;
21 |
22 | // Directly taken from 1.12.2, translated and adapted a bit.
23 | @SubscribeEvent
24 | public void onRenderWorld(RenderWorldLastEvent event) {
25 | if (!config.futureChunkBorders) return;
26 | if (!isToggled) return;
27 | if (Minecraft.getMinecraft().thePlayer == null) return;
28 |
29 | EntityPlayer entityplayer = Minecraft.getMinecraft().thePlayer;
30 | Tessellator tessellator = Tessellator.getInstance();
31 | WorldRenderer worldRenderer = tessellator.getWorldRenderer();
32 | double d0 = entityplayer.lastTickPosX + (entityplayer.posX - entityplayer.lastTickPosX) * event.partialTicks;
33 | double d1 = entityplayer.lastTickPosY + (entityplayer.posY - entityplayer.lastTickPosY) * event.partialTicks;
34 | double d2 = entityplayer.lastTickPosZ + (entityplayer.posZ - entityplayer.lastTickPosZ) * event.partialTicks;
35 | double d3 = 0.0D - d1;
36 | double d4 = 256.0D - d1;
37 | GlStateManager.disableTexture2D();
38 | GlStateManager.disableBlend();
39 | double d5 = (entityplayer.chunkCoordX << 4) - d0;
40 | double d6 = (entityplayer.chunkCoordZ << 4) - d2;
41 | GL11.glLineWidth(1.0F);
42 | worldRenderer.begin(3, DefaultVertexFormats.POSITION_COLOR);
43 |
44 | for (int i = -16; i <= 32; i += 16) {
45 | for (int j = -16; j <= 32; j += 16) {
46 | worldRenderer.pos(d5 + i, d3, d6 + j).color(1.0F, 0.0F, 0.0F, 0.0F).endVertex();
47 | worldRenderer.pos(d5 + i, d3, d6 + j).color(1.0F, 0.0F, 0.0F, 0.5F).endVertex();
48 | worldRenderer.pos(d5 + i, d4, d6 + j).color(1.0F, 0.0F, 0.0F, 0.5F).endVertex();
49 | worldRenderer.pos(d5 + i, d4, d6 + j).color(1.0F, 0.0F, 0.0F, 0.0F).endVertex();
50 | }
51 | }
52 |
53 | for (int k = 2; k < 16; k += 2) {
54 | worldRenderer.pos(d5 + k, d3, d6).color(1.0F, 1.0F, 0.0F, 0.0F).endVertex();
55 | worldRenderer.pos(d5 + k, d3, d6).color(1.0F, 1.0F, 0.0F, 1.0F).endVertex();
56 | worldRenderer.pos(d5 + k, d4, d6).color(1.0F, 1.0F, 0.0F, 1.0F).endVertex();
57 | worldRenderer.pos(d5 + k, d4, d6).color(1.0F, 1.0F, 0.0F, 0.0F).endVertex();
58 | worldRenderer.pos(d5 + k, d3, d6 + 16.0D).color(1.0F, 1.0F, 0.0F, 0.0F).endVertex();
59 | worldRenderer.pos(d5 + k, d3, d6 + 16.0D).color(1.0F, 1.0F, 0.0F, 1.0F).endVertex();
60 | worldRenderer.pos(d5 + k, d4, d6 + 16.0D).color(1.0F, 1.0F, 0.0F, 1.0F).endVertex();
61 | worldRenderer.pos(d5 + k, d4, d6 + 16.0D).color(1.0F, 1.0F, 0.0F, 0.0F).endVertex();
62 | }
63 |
64 | for (int l = 2; l < 16; l += 2) {
65 | worldRenderer.pos(d5, d3, d6 + l).color(1.0F, 1.0F, 0.0F, 0.0F).endVertex();
66 | worldRenderer.pos(d5, d3, d6 + l).color(1.0F, 1.0F, 0.0F, 1.0F).endVertex();
67 | worldRenderer.pos(d5, d4, d6 + l).color(1.0F, 1.0F, 0.0F, 1.0F).endVertex();
68 | worldRenderer.pos(d5, d4, d6 + l).color(1.0F, 1.0F, 0.0F, 0.0F).endVertex();
69 | worldRenderer.pos(d5 + 16.0D, d3, d6 + l).color(1.0F, 1.0F, 0.0F, 0.0F).endVertex();
70 | worldRenderer.pos(d5 + 16.0D, d3, d6 + l).color(1.0F, 1.0F, 0.0F, 1.0F).endVertex();
71 | worldRenderer.pos(d5 + 16.0D, d4, d6 + l).color(1.0F, 1.0F, 0.0F, 1.0F).endVertex();
72 | worldRenderer.pos(d5 + 16.0D, d4, d6 + l).color(1.0F, 1.0F, 0.0F, 0.0F).endVertex();
73 | }
74 |
75 | for (int i1 = 0; i1 <= 256; i1 += 2) {
76 | double d7 = i1 - d1;
77 | worldRenderer.pos(d5, d7, d6).color(1.0F, 1.0F, 0.0F, 0.0F).endVertex();
78 | worldRenderer.pos(d5, d7, d6).color(1.0F, 1.0F, 0.0F, 1.0F).endVertex();
79 | worldRenderer.pos(d5, d7, d6 + 16.0D).color(1.0F, 1.0F, 0.0F, 1.0F).endVertex();
80 | worldRenderer.pos(d5 + 16.0D, d7, d6 + 16.0D).color(1.0F, 1.0F, 0.0F, 1.0F).endVertex();
81 | worldRenderer.pos(d5 + 16.0D, d7, d6).color(1.0F, 1.0F, 0.0F, 1.0F).endVertex();
82 | worldRenderer.pos(d5, d7, d6).color(1.0F, 1.0F, 0.0F, 1.0F).endVertex();
83 | worldRenderer.pos(d5, d7, d6).color(1.0F, 1.0F, 0.0F, 0.0F).endVertex();
84 | }
85 |
86 | tessellator.draw();
87 | GL11.glLineWidth(2.0F);
88 | worldRenderer.begin(3, DefaultVertexFormats.POSITION_COLOR);
89 |
90 | for (int j1 = 0; j1 <= 16; j1 += 16) {
91 | for (int l1 = 0; l1 <= 16; l1 += 16) {
92 | worldRenderer.pos(d5 + j1, d3, d6 + l1).color(0.25F, 0.25F, 1.0F, 0.0F).endVertex();
93 | worldRenderer.pos(d5 + j1, d3, d6 + l1).color(0.25F, 0.25F, 1.0F, 1.0F).endVertex();
94 | worldRenderer.pos(d5 + j1, d4, d6 + l1).color(0.25F, 0.25F, 1.0F, 1.0F).endVertex();
95 | worldRenderer.pos(d5 + j1, d4, d6 + l1).color(0.25F, 0.25F, 1.0F, 0.0F).endVertex();
96 | }
97 | }
98 |
99 | for (int k1 = 0; k1 <= 256; k1 += 16) {
100 | double d8 = k1 - d1;
101 | worldRenderer.pos(d5, d8, d6).color(0.25F, 0.25F, 1.0F, 0.0F).endVertex();
102 | worldRenderer.pos(d5, d8, d6).color(0.25F, 0.25F, 1.0F, 1.0F).endVertex();
103 | worldRenderer.pos(d5, d8, d6 + 16.0D).color(0.25F, 0.25F, 1.0F, 1.0F).endVertex();
104 | worldRenderer.pos(d5 + 16.0D, d8, d6 + 16.0D).color(0.25F, 0.25F, 1.0F, 1.0F).endVertex();
105 | worldRenderer.pos(d5 + 16.0D, d8, d6).color(0.25F, 0.25F, 1.0F, 1.0F).endVertex();
106 | worldRenderer.pos(d5, d8, d6).color(0.25F, 0.25F, 1.0F, 1.0F).endVertex();
107 | worldRenderer.pos(d5, d8, d6).color(0.25F, 0.25F, 1.0F, 0.0F).endVertex();
108 | }
109 |
110 | tessellator.draw();
111 | GL11.glLineWidth(1.0F);
112 | GlStateManager.enableBlend();
113 | GlStateManager.enableTexture2D();
114 | }
115 |
116 | // F3 + G, like in future versions of the game. Should this be configurable? Eh..
117 | @SubscribeEvent
118 | public void onKeyPress(InputEvent.KeyInputEvent event) {
119 | if (!Keyboard.getEventKeyState()) return;
120 | if (!config.futureChunkBorders) return;
121 | if (Keyboard.isKeyDown(61) && Keyboard.getEventKey() == 34) {
122 | isToggled = !isToggled;
123 | }
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/features/utilities/AncestralSpade.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.features.utilities;
2 |
3 | import com.luna.synthesis.Synthesis;
4 | import com.luna.synthesis.core.Config;
5 | import com.luna.synthesis.events.packet.PacketReceivedEvent;
6 | import com.luna.synthesis.utils.ChatLib;
7 | import com.luna.synthesis.utils.Utils;
8 | import net.minecraft.client.Minecraft;
9 | import net.minecraft.client.renderer.GlStateManager;
10 | import net.minecraft.item.ItemStack;
11 | import net.minecraft.network.play.server.S2APacketParticles;
12 | import net.minecraft.util.*;
13 | import net.minecraftforge.client.event.ClientChatReceivedEvent;
14 | import net.minecraftforge.client.event.RenderWorldLastEvent;
15 | import net.minecraftforge.event.entity.player.PlayerInteractEvent;
16 | import net.minecraftforge.event.world.WorldEvent;
17 | import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
18 | import net.minecraftforge.fml.common.gameevent.TickEvent;
19 |
20 | import java.awt.*;
21 |
22 | public class AncestralSpade {
23 |
24 | private final Config config = Synthesis.getInstance().getConfig();
25 | private final ResourceLocation beaconBeam = new ResourceLocation("textures/entity/beacon_beam.png");
26 | private boolean awaiting = false;
27 | private boolean awaitingForArrow = false;
28 | private long lastSpoon = -1L;
29 | private Vec3 pos1 = null;
30 | private Vec3 pos2 = null;
31 | private Vec3 vec1 = null;
32 | private Vec3 vec2 = null;
33 | private BlockPos solution = null;
34 |
35 | @SubscribeEvent
36 | public void onPacketReceived(PacketReceivedEvent event) {
37 | if (!config.utilitiesAncestralSpade) return;
38 | if (event.getPacket() instanceof S2APacketParticles) {
39 | S2APacketParticles packet = (S2APacketParticles) event.getPacket();
40 | if (packet.getParticleType() == EnumParticleTypes.FIREWORKS_SPARK && packet.getXOffset() == 0 && packet.getYOffset() == 0 && packet.getZOffset() == 0) {
41 | if (packet.getParticleSpeed() == 0 && packet.getParticleCount() == 1) {
42 | if (awaiting) {
43 | if (pos1 == null) {
44 | pos1 = new Vec3(packet.getXCoordinate(), packet.getYCoordinate(), packet.getZCoordinate());
45 | awaiting = false;
46 | } else if (pos2 == null) {
47 | pos2 = new Vec3(packet.getXCoordinate(), packet.getYCoordinate(), packet.getZCoordinate());
48 | awaiting = false;
49 | }
50 | } else {
51 | if (vec1 == null && pos1 != null) {
52 | vec1 = new Vec3(packet.getXCoordinate() - pos1.xCoord, packet.getYCoordinate() - pos1.yCoord, packet.getZCoordinate() - pos1.zCoord).normalize();
53 | } else if (vec2 == null && pos2 != null) {
54 | vec2 = new Vec3(packet.getXCoordinate() - pos2.xCoord, packet.getYCoordinate() - pos2.yCoord, packet.getZCoordinate() - pos2.zCoord).normalize();
55 | calculateIntercept();
56 | }
57 | }
58 | }
59 | } else if (packet.getParticleType() == EnumParticleTypes.REDSTONE && packet.getParticleSpeed() == 1 && packet.getParticleCount() == 0) {
60 | if (awaitingForArrow) {
61 | if (pos1 == null) {
62 | pos1 = new Vec3(packet.getXCoordinate(), packet.getYCoordinate(), packet.getZCoordinate());
63 | } else if (vec1 == null) {
64 | if (packet.getXCoordinate() - pos1.xCoord == 0 && packet.getZCoordinate() - pos1.zCoord == 0) return;
65 | vec1 = new Vec3(packet.getXCoordinate() - pos1.xCoord, packet.getYCoordinate() - pos1.yCoord, packet.getZCoordinate() - pos1.zCoord).normalize();
66 | awaitingForArrow = false;
67 | }
68 | }
69 | }
70 | }
71 | }
72 |
73 | @SubscribeEvent
74 | public void onRightClick(PlayerInteractEvent event) {
75 | if (!config.utilitiesAncestralSpade) return;
76 | if (event.action == PlayerInteractEvent.Action.RIGHT_CLICK_AIR || event.action == PlayerInteractEvent.Action.RIGHT_CLICK_BLOCK) {
77 | ItemStack item = Minecraft.getMinecraft().thePlayer.getHeldItem();
78 | if (item == null) return;
79 | if (StringUtils.stripControlCodes(item.getDisplayName()).contains("Ancestral Spade")) {
80 | if (System.currentTimeMillis() >= lastSpoon + 3000) {
81 | if (Minecraft.getMinecraft().thePlayer.rotationPitch == 90 || Minecraft.getMinecraft().thePlayer.rotationPitch == -90) {
82 | awaiting = true;
83 | lastSpoon = System.currentTimeMillis();
84 | }
85 | }
86 | }
87 | }
88 | }
89 |
90 | @SubscribeEvent
91 | public void onClientTick(TickEvent.ClientTickEvent event) {
92 | if (solution != null && Minecraft.getMinecraft().thePlayer != null) {
93 | if (Math.pow(Minecraft.getMinecraft().thePlayer.posX - solution.getX(), 2) + Math.pow(Minecraft.getMinecraft().thePlayer.posZ - solution.getZ(), 2) <= 9) {
94 | solution = null;
95 | }
96 | }
97 | }
98 |
99 | @SubscribeEvent
100 | public void onChatMessage(ClientChatReceivedEvent event) {
101 | if (event.type == 2) return;
102 | if (!config.utilitiesAncestralSpade || !config.utilitiesAncestralSpadeArrow) return;
103 | String msg = StringUtils.stripControlCodes(event.message.getUnformattedText());
104 | if (msg.startsWith("You dug out a Griffin Burrow!")) {
105 | awaitingForArrow = true;
106 | }
107 | }
108 |
109 | @SubscribeEvent
110 | public void onRenderWorld(RenderWorldLastEvent event) {
111 | if (config.utilitiesAncestralSpadeWaypoint && solution != null) {
112 | double renderPosX = Minecraft.getMinecraft().getRenderManager().viewerPosX;
113 | double renderPosY = Minecraft.getMinecraft().getRenderManager().viewerPosY;
114 | double renderPosZ = Minecraft.getMinecraft().getRenderManager().viewerPosZ;
115 | GlStateManager.pushMatrix();
116 | GlStateManager.translate(-renderPosX, -renderPosY, -renderPosZ);
117 | Minecraft.getMinecraft().getTextureManager().bindTexture(beaconBeam);
118 | Utils.renderBeamSegment(solution.getX(), 0, solution.getZ(), event.partialTicks, 1.0, Minecraft.getMinecraft().theWorld.getTotalWorldTime(), 0, 256, config.utilitiesAncestralSpadeWaypointColor.getColorComponents(null));
119 | GlStateManager.translate(renderPosX, renderPosY, renderPosZ);
120 | GlStateManager.popMatrix();
121 | }
122 | }
123 |
124 | @SubscribeEvent
125 | public void onWorldLoad(WorldEvent.Load event) {
126 | pos1 = null;
127 | pos2 = null;
128 | vec1 = null;
129 | vec2 = null;
130 | awaiting = false;
131 | solution = null;
132 | }
133 |
134 | // All math in the mod is thanks to Lucy, this included, thank you, Lucy!
135 | // If you don't understand something don't blame me, I just copied her notes.
136 | // And no, you cannot expect me to do very simple math, I will simply ask the math genius when possible.
137 | private void calculateIntercept() {
138 | double p1x = pos1.xCoord;
139 | double p1z = pos1.zCoord;
140 | double v1x = vec1.xCoord;
141 | double v1z = vec1.zCoord;
142 | //
143 | double p2x = pos2.xCoord;
144 | double p2z = pos2.zCoord;
145 | double v2x = vec2.xCoord;
146 | double v2z = vec2.zCoord;
147 | double a = v1z / v1x * p1x - p1z;
148 | double b = v2z / v2x * p2x - p2z;
149 | double x = (a - b) / (v1z / v1x - v2z / v2x);
150 | double z = v1z / v1x * x - a;
151 |
152 | BlockPos solution = new BlockPos(x, 0, z);
153 | ChatLib.chat("Solution: (" + solution.getX() + ", " + solution.getZ() + ")");
154 | this.solution = solution;
155 | pos1 = pos2 = vec1 = vec2 = null;
156 | }
157 | }
158 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/features/utilities/BestiaryDropRate.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.features.utilities;
2 |
3 | import com.luna.synthesis.Synthesis;
4 | import com.luna.synthesis.core.Config;
5 | import net.minecraft.client.Minecraft;
6 | import net.minecraft.client.gui.GuiScreen;
7 | import net.minecraft.client.gui.inventory.GuiChest;
8 | import net.minecraft.inventory.ContainerChest;
9 | import net.minecraft.util.EnumChatFormatting;
10 | import net.minecraft.util.StringUtils;
11 | import net.minecraftforge.event.entity.player.ItemTooltipEvent;
12 | import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
13 |
14 | import java.util.Iterator;
15 | import java.util.concurrent.atomic.AtomicInteger;
16 |
17 | public class BestiaryDropRate {
18 |
19 | private final Config config = Synthesis.getInstance().getConfig();
20 |
21 | @SubscribeEvent
22 | public void onItemTooltip(ItemTooltipEvent event) {
23 | if (config.utilitiesDropChanceToDropRate == 0) return;
24 | if (config.utilitiesDropChanceToDropRate == 1 && !GuiScreen.isShiftKeyDown()) return;
25 | if (Minecraft.getMinecraft().currentScreen instanceof GuiChest) {
26 | ContainerChest chest = (ContainerChest) ((GuiChest) Minecraft.getMinecraft().currentScreen).inventorySlots;
27 | if (chest.getLowerChestInventory().getDisplayName().getUnformattedText().contains(" ➜ ")) {
28 | Iterator it = event.toolTip.iterator();
29 | AtomicInteger i = new AtomicInteger(0);
30 | it.forEachRemaining(s -> {
31 | String line = StringUtils.stripControlCodes(s);
32 | if (line.endsWith("%)")) {
33 | try {
34 | double number = Double.parseDouble(line.split("\\(")[1].replace("%)", ""));
35 | if (number < 100) {
36 | event.toolTip.set(i.get(), s.replaceAll("\\(§a[\\d.]+%§8\\)",
37 | EnumChatFormatting.DARK_GRAY + "(" + EnumChatFormatting.GREEN + "1/" + Math.floor(10000 / number + 0.5) / 100 + EnumChatFormatting.DARK_GRAY + ")"));
38 | }
39 | } catch (NumberFormatException ignored) {}
40 | }
41 | i.getAndIncrement();
42 | });
43 | }
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/features/utilities/BetterWitherImpactPerspective.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.features.utilities;
2 |
3 | import com.luna.synthesis.Synthesis;
4 | import com.luna.synthesis.core.Config;
5 | import net.minecraft.client.Minecraft;
6 | import net.minecraft.item.ItemStack;
7 | import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
8 | import net.minecraftforge.fml.common.gameevent.InputEvent;
9 | import org.lwjgl.input.Keyboard;
10 |
11 | public class BetterWitherImpactPerspective {
12 |
13 | private final Config config = Synthesis.getInstance().getConfig();
14 |
15 | // InputEvent has to be the absolute worst event in forge
16 | @SubscribeEvent
17 | public void onKey(InputEvent.KeyInputEvent event) {
18 | if (!config.utilitiesWitherImpactPerspective) return;
19 | if (!Keyboard.getEventKeyState()) return;
20 | if (Keyboard.getEventKey() == Minecraft.getMinecraft().gameSettings.keyBindTogglePerspective.getKeyCode()) {
21 | if (Minecraft.getMinecraft().gameSettings.thirdPersonView == 2) {
22 | if (config.utilitiesWitherImpactPerspectiveGlobal) {
23 | Minecraft.getMinecraft().gameSettings.thirdPersonView = 0;
24 | } else {
25 | ItemStack item = Minecraft.getMinecraft().thePlayer.getHeldItem();
26 | if (item == null) return;
27 | if (item.hasTagCompound()) {
28 | if (item.getTagCompound().hasKey("ExtraAttributes")) {
29 | if (item.getTagCompound().getCompoundTag("ExtraAttributes").hasKey("ability_scroll")) {
30 | if (item.getTagCompound().getCompoundTag("ExtraAttributes").getTagList("ability_scroll", 8).tagCount() == 3) {
31 | Minecraft.getMinecraft().gameSettings.thirdPersonView = 0;
32 | }
33 | }
34 | }
35 | }
36 | }
37 | }
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/features/utilities/ChatBridge.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.features.utilities;
2 |
3 | import com.luna.synthesis.Synthesis;
4 | import com.luna.synthesis.core.Config;
5 | import com.luna.synthesis.utils.Utils;
6 | import net.minecraft.event.ClickEvent;
7 | import net.minecraft.util.ChatComponentText;
8 | import net.minecraft.util.IChatComponent;
9 | import net.minecraft.util.StringUtils;
10 | import net.minecraftforge.client.event.ClientChatReceivedEvent;
11 | import net.minecraftforge.fml.common.eventhandler.EventPriority;
12 | import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
13 |
14 | import java.net.URI;
15 | import java.net.URISyntaxException;
16 | import java.util.regex.Matcher;
17 | import java.util.regex.Pattern;
18 |
19 | public class ChatBridge {
20 |
21 | private final Config config = Synthesis.getInstance().getConfig();
22 | private final Pattern msgPattern = Pattern.compile("^Guild > (?\\[[A-Z+]+] )?(?[a-zA-Z0-9_]{3,16})(? \\[.+])?: (?.*)(?( >|:))(? .*)");
23 |
24 | @SubscribeEvent(priority = EventPriority.HIGHEST)
25 | public void onClientChatMessage(ClientChatReceivedEvent event) {
26 | if (!config.utilitiesBridge) return;
27 | String message = StringUtils.stripControlCodes(event.message.getUnformattedText());
28 | if (!message.startsWith("Guild > ") || !message.contains(config.utilitiesBridgeBotName)) return;
29 | Matcher matcher = msgPattern.matcher(message);
30 | if (matcher.matches() && matcher.groupCount() == 7) {
31 | String msgSender = matcher.group(2);
32 | if (msgSender.equals(config.utilitiesBridgeBotName)) {
33 | String ign = matcher.group(4);
34 | String msg = matcher.group(7);
35 | event.message = Utils.newChatWithLinks(config.utilitiesBridgeMessageFormat.replaceAll("&", "§").replace("", ign).replace("", msg));
36 | }
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/features/utilities/ContainerChat.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.features.utilities;
2 |
3 | import com.luna.synthesis.Synthesis;
4 | import com.luna.synthesis.core.Config;
5 | import com.luna.synthesis.mixins.accessors.GuiRepairAccessor;
6 | import com.luna.synthesis.utils.MixinUtils;
7 | import net.minecraft.client.Minecraft;
8 | import net.minecraft.client.gui.GuiChat;
9 | import net.minecraft.client.gui.GuiRepair;
10 | import net.minecraft.client.gui.GuiScreen;
11 | import net.minecraft.client.gui.inventory.GuiContainer;
12 | import net.minecraft.client.gui.inventory.GuiContainerCreative;
13 | import net.minecraft.util.MathHelper;
14 | import net.minecraftforge.client.event.GuiOpenEvent;
15 | import net.minecraftforge.client.event.GuiScreenEvent;
16 | import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
17 | import org.lwjgl.input.Keyboard;
18 | import org.lwjgl.input.Mouse;
19 |
20 | public class ContainerChat {
21 |
22 | private final Config config = Synthesis.getInstance().getConfig();
23 |
24 | private String historyBuffer = "";
25 | private int sentHistoryCursor = -1;
26 |
27 | // For chat transfer magic
28 | @SubscribeEvent
29 | public void onGuiOpen(GuiOpenEvent event) {
30 | if (!config.utilitiesContainerChat) return;
31 | sentHistoryCursor = Minecraft.getMinecraft().ingameGUI.getChatGUI().getSentMessages().size();
32 | if (config.utilitiesReopenContainerChat && MixinUtils.inputField != null) {
33 | if (event.gui == null) {
34 | if (Minecraft.getMinecraft().currentScreen instanceof GuiContainer) {
35 | if (MixinUtils.inputField.isFocused()) {
36 | event.gui = new GuiChat(MixinUtils.inputField.getText());
37 | }
38 | } else {
39 | MixinUtils.inputField = null;
40 | }
41 | }
42 | }
43 | }
44 |
45 | // Originally in mixin, had to rewrite because SBE and Cowlection would have bad compatibility issues.
46 | // I also need to fix this working when SBE's search bar is focused, but I don't think I'll be able to do that.
47 | @SubscribeEvent
48 | public void onKeyTyped(GuiScreenEvent.KeyboardInputEvent event) {
49 | if (!(event.gui instanceof GuiContainer)) return;
50 | if (event.gui instanceof GuiContainerCreative) return;
51 | if (!config.utilitiesContainerChat) return;
52 | if (!Keyboard.getEventKeyState()) return;
53 | int keyCode = Keyboard.getEventKey();
54 | if (MixinUtils.inputField == null) return;
55 | if (event.gui instanceof GuiRepair && ((GuiRepairAccessor) event.gui).getNameField().isFocused()) return;
56 | if (event instanceof GuiScreenEvent.KeyboardInputEvent.Pre) {
57 | if (MixinUtils.inputField.isFocused()) {
58 | if (keyCode == 1) {
59 | MixinUtils.inputField.setFocused(false);
60 | MixinUtils.inputField.setText("");
61 | Keyboard.enableRepeatEvents(false);
62 | Minecraft.getMinecraft().ingameGUI.getChatGUI().resetScroll();
63 | }
64 | if (keyCode != Minecraft.getMinecraft().gameSettings.keyBindScreenshot.getKeyCode()) {
65 | event.setCanceled(true);
66 | }
67 | } else {
68 | if (keyCode == Minecraft.getMinecraft().gameSettings.keyBindChat.getKeyCode()) {
69 | if (config.utilitiesContainerControl && !GuiScreen.isCtrlKeyDown()) return;
70 | if (!config.utilitiesContainerControl && GuiScreen.isCtrlKeyDown()) return;
71 | MixinUtils.inputField.setFocused(true);
72 | Keyboard.enableRepeatEvents(true);
73 | return;
74 | } else if (keyCode == Minecraft.getMinecraft().gameSettings.keyBindCommand.getKeyCode()) {
75 | MixinUtils.inputField.setText("/");
76 | MixinUtils.inputField.setFocused(true);
77 | Keyboard.enableRepeatEvents(true);
78 | return;
79 | }
80 | }
81 |
82 | if (keyCode != 28 && keyCode != 156) {
83 | if (keyCode == 200) {
84 | getSentHistory(-1);
85 | } else if (keyCode == 208) {
86 | getSentHistory(1);
87 | } else {
88 | MixinUtils.inputField.textboxKeyTyped(Keyboard.getEventCharacter(), keyCode);
89 | }
90 | } else {
91 | if (!MixinUtils.inputField.isFocused()) return;
92 | String text = MixinUtils.inputField.getText().trim();
93 |
94 | if (!text.isEmpty()) {
95 | event.gui.sendChatMessage(text);
96 | }
97 | sentHistoryCursor = Minecraft.getMinecraft().ingameGUI.getChatGUI().getSentMessages().size();
98 | MixinUtils.inputField.setText("");
99 | MixinUtils.inputField.setFocused(false);
100 | Minecraft.getMinecraft().ingameGUI.getChatGUI().resetScroll();
101 | }
102 | }
103 | }
104 |
105 | @SubscribeEvent
106 | public void onScroll(GuiScreenEvent.MouseInputEvent.Pre event) {
107 | if (!config.utilitiesContainerChat) return;
108 | if (!(event.gui instanceof GuiContainer)) return;
109 | if (MixinUtils.inputField == null) return;
110 | if (!MixinUtils.inputField.isFocused()) return;
111 | int i = Mouse.getEventDWheel();
112 | if (i != 0) {
113 | if (i > 1) {
114 | i = 1;
115 | }
116 |
117 | if (i < -1) {
118 | i = -1;
119 | }
120 |
121 | if (!GuiScreen.isShiftKeyDown()) {
122 | i *= 7;
123 | }
124 |
125 | Minecraft.getMinecraft().ingameGUI.getChatGUI().scroll(i);
126 | }
127 | }
128 |
129 | private void getSentHistory(int msgPos) {
130 | int i = this.sentHistoryCursor + msgPos;
131 | int j = Minecraft.getMinecraft().ingameGUI.getChatGUI().getSentMessages().size();
132 | i = MathHelper.clamp_int(i, 0, j);
133 |
134 | if (i != this.sentHistoryCursor) {
135 | if (i == j) {
136 | this.sentHistoryCursor = j;
137 | MixinUtils.inputField.setText(this.historyBuffer);
138 | } else {
139 | if (this.sentHistoryCursor == j) {
140 | this.historyBuffer = MixinUtils.inputField.getText();
141 | }
142 | MixinUtils.inputField.setText(Minecraft.getMinecraft().ingameGUI.getChatGUI().getSentMessages().get(i));
143 | this.sentHistoryCursor = i;
144 | }
145 | }
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/features/utilities/SearchMode.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.features.utilities;
2 |
3 | import com.luna.synthesis.Synthesis;
4 | import com.luna.synthesis.core.Config;
5 | import com.luna.synthesis.mixins.accessors.GuiNewChatAccessor;
6 | import com.luna.synthesis.utils.MixinUtils;
7 | import com.luna.synthesis.utils.Utils;
8 | import net.minecraft.client.Minecraft;
9 | import net.minecraft.client.gui.ChatLine;
10 | import net.minecraft.client.gui.GuiChat;
11 | import net.minecraft.client.gui.ScaledResolution;
12 | import net.minecraft.client.gui.inventory.GuiContainer;
13 | import net.minecraft.util.ChatComponentText;
14 | import net.minecraft.util.EnumChatFormatting;
15 | import net.minecraft.util.MathHelper;
16 | import net.minecraftforge.client.event.GuiScreenEvent;
17 | import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
18 | import org.lwjgl.input.Keyboard;
19 | import org.lwjgl.input.Mouse;
20 |
21 | import java.util.Iterator;
22 | import java.util.List;
23 | import java.util.stream.Collectors;
24 |
25 | public class SearchMode {
26 |
27 | public static boolean isSearchMode = false;
28 | private final Config config = Synthesis.getInstance().getConfig();
29 |
30 | @SubscribeEvent
31 | public void onKeyTyped(GuiScreenEvent.KeyboardInputEvent.Pre event) {
32 | if (!(event.gui instanceof GuiChat || (event.gui instanceof GuiContainer && config.utilitiesContainerChat && MixinUtils.inputField != null && MixinUtils.inputField.isFocused()))) return;
33 | if (!config.utilitiesChatSearchMode) return;
34 | if (!Keyboard.getEventKeyState()) return;
35 | if (Keyboard.isRepeatEvent()) return;
36 | if (Keyboard.getEventKey() == 33 && Keyboard.isKeyDown(29)) {
37 | isSearchMode = !isSearchMode;
38 | if (isSearchMode) {
39 | ((GuiNewChatAccessor) Minecraft.getMinecraft().ingameGUI.getChatGUI()).invokeSetChatLine(new ChatComponentText(EnumChatFormatting.YELLOW + "" + EnumChatFormatting.BOLD + "SEARCH MODE ON"), "synthesissearchmode".hashCode(), Minecraft.getMinecraft().ingameGUI.getUpdateCounter(), true);
40 | } else {
41 | Minecraft.getMinecraft().ingameGUI.getChatGUI().deleteChatLine("synthesissearchmode".hashCode());
42 | }
43 | event.setCanceled(true);
44 | if (!isSearchMode) {
45 | Minecraft.getMinecraft().ingameGUI.getChatGUI().refreshChat();
46 | }
47 | } else if (Keyboard.getEventKey() == 1) {
48 | if (isSearchMode) {
49 | isSearchMode = false;
50 | Minecraft.getMinecraft().ingameGUI.getChatGUI().deleteChatLine("synthesissearchmode".hashCode());
51 | Minecraft.getMinecraft().ingameGUI.getChatGUI().refreshChat();
52 | }
53 | } else if (Keyboard.getEventKey() == 28 && isSearchMode) {
54 | if (!config.utilitiesChatSearchKeyRefresh) {
55 | Minecraft.getMinecraft().ingameGUI.getChatGUI().refreshChat();
56 | if (((GuiNewChatAccessor) Minecraft.getMinecraft().ingameGUI.getChatGUI()).getDrawnChatLines().size() == 0) {
57 | ((GuiNewChatAccessor) Minecraft.getMinecraft().ingameGUI.getChatGUI()).invokeSetChatLine(new ChatComponentText(EnumChatFormatting.YELLOW + "" + EnumChatFormatting.BOLD + "SEARCH MODE ON"), "synthesissearchmode".hashCode(), Minecraft.getMinecraft().ingameGUI.getUpdateCounter(), true);
58 | }
59 | }
60 | event.setCanceled(true);
61 | }
62 | }
63 |
64 | @SubscribeEvent
65 | public void onKeyTypedPost(GuiScreenEvent.KeyboardInputEvent.Post event) {
66 | if (!(event.gui instanceof GuiChat || (event.gui instanceof GuiContainer && config.utilitiesContainerChat && MixinUtils.inputField != null && MixinUtils.inputField.isFocused()))) return;
67 | if (!Keyboard.getEventKeyState() && event.gui instanceof GuiChat) return;
68 | if (config.utilitiesChatSearchKeyRefresh && isSearchMode) {
69 | Minecraft.getMinecraft().ingameGUI.getChatGUI().refreshChat();
70 | if (((GuiNewChatAccessor) Minecraft.getMinecraft().ingameGUI.getChatGUI()).getDrawnChatLines().size() == 0) {
71 | ((GuiNewChatAccessor) Minecraft.getMinecraft().ingameGUI.getChatGUI()).invokeSetChatLine(new ChatComponentText(EnumChatFormatting.YELLOW + "" + EnumChatFormatting.BOLD + "SEARCH MODE ON"), "synthesissearchmode".hashCode(), Minecraft.getMinecraft().ingameGUI.getUpdateCounter(), true);
72 | }
73 | }
74 | }
75 |
76 | @SubscribeEvent
77 | public void onMouseClicked(GuiScreenEvent.MouseInputEvent.Pre event) {
78 | if (!isSearchMode) return;
79 | if (!config.utilitiesChatScrollClick) return;
80 | if (Mouse.getEventButton() != 1) return;
81 | if (!Mouse.getEventButtonState()) return;
82 | int index = getChatLineIndex(Mouse.getX(), Mouse.getY());
83 | if (index == -1) return;
84 | List chatLines = ((GuiNewChatAccessor) Minecraft.getMinecraft().ingameGUI.getChatGUI()).getDrawnChatLines();
85 | ChatLine cl = ((GuiNewChatAccessor) Minecraft.getMinecraft().ingameGUI.getChatGUI()).getDrawnChatLines().get(index);
86 | int newIndex = 0;
87 | if (chatLines.stream().map(chatLine -> chatLine.getChatComponent().equals(cl.getChatComponent())).count() > 1) {
88 | for (int i = 0; i < index; i++) {
89 | if (chatLines.get(i).getChatComponent().equals(cl.getChatComponent())) {
90 | newIndex++;
91 | }
92 | }
93 | }
94 | isSearchMode = false;
95 | Minecraft.getMinecraft().ingameGUI.getChatGUI().deleteChatLine("synthesissearchmode".hashCode());
96 | Minecraft.getMinecraft().ingameGUI.getChatGUI().refreshChat();
97 | Minecraft.getMinecraft().ingameGUI.getChatGUI().resetScroll();
98 | chatLines = ((GuiNewChatAccessor) Minecraft.getMinecraft().ingameGUI.getChatGUI()).getDrawnChatLines();
99 | int scrollAmount = -1;
100 | if (newIndex == 0) {
101 | scrollAmount = chatLines.stream().map(ChatLine::getChatComponent).collect(Collectors.toList()).indexOf(cl.getChatComponent());
102 | }
103 | if (chatLines.stream().filter(chatLine -> chatLine.getChatComponent().equals(cl.getChatComponent())).count() > 1) {
104 | for (int i = 0; i < chatLines.size(); i++) {
105 | if (chatLines.get(i).getChatComponent().equals(cl.getChatComponent())) {
106 | if (newIndex == 0) {
107 | scrollAmount = i;
108 | break;
109 | } else {
110 | newIndex--;
111 | }
112 | }
113 | }
114 | }
115 | Minecraft.getMinecraft().ingameGUI.getChatGUI().scroll(scrollAmount);
116 | }
117 |
118 | private int getChatLineIndex(int mouseX, int mouseY) {
119 | if (!Minecraft.getMinecraft().ingameGUI.getChatGUI().getChatOpen()) {
120 | return -1;
121 | } else {
122 | ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft());
123 | int i = scaledresolution.getScaleFactor();
124 | float f = Minecraft.getMinecraft().ingameGUI.getChatGUI().getChatScale();
125 | int j = mouseX / i - 3;
126 | int k = mouseY / i - 27;
127 | j = MathHelper.floor_float(j / f);
128 | k = MathHelper.floor_float(k / f);
129 |
130 | if (j >= 0 && k >= 0) {
131 | //int l = Minecraft.getMinecraft().ingameGUI.getChatGUI().getLineCount();
132 | int l = Math.min(Minecraft.getMinecraft().ingameGUI.getChatGUI().getLineCount(), ((GuiNewChatAccessor) Minecraft.getMinecraft().ingameGUI.getChatGUI()).getDrawnChatLines().size());
133 |
134 | if (j <= MathHelper.floor_float(Minecraft.getMinecraft().ingameGUI.getChatGUI().getChatWidth() / Minecraft.getMinecraft().ingameGUI.getChatGUI().getChatScale()) && k < Minecraft.getMinecraft().fontRendererObj.FONT_HEIGHT * l + l) {
135 | int i1 = k / Minecraft.getMinecraft().fontRendererObj.FONT_HEIGHT + ((GuiNewChatAccessor) Minecraft.getMinecraft().ingameGUI.getChatGUI()).getScrollPos();
136 |
137 | if (i1 >= 0 && i1 < ((GuiNewChatAccessor) Minecraft.getMinecraft().ingameGUI.getChatGUI()).getDrawnChatLines().size()) {
138 | return i1;
139 | //return ((GuiNewChatAccessor) Minecraft.getMinecraft().ingameGUI.getChatGUI()).getDrawnChatLines().get(i1);
140 | }
141 |
142 | return -1;
143 | } else {
144 | return -1;
145 | }
146 | } else {
147 | return -1;
148 | }
149 | }
150 | }
151 | }
152 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/features/utilities/Share.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.features.utilities;
2 |
3 | import com.google.gson.*;
4 | import com.luna.synthesis.Synthesis;
5 | import com.luna.synthesis.core.Config;
6 | import com.luna.synthesis.events.MessageSentEvent;
7 | import com.luna.synthesis.utils.ChatLib;
8 | import com.luna.synthesis.utils.MixinUtils;
9 | import net.minecraft.client.Minecraft;
10 | import net.minecraft.client.gui.GuiChat;
11 | import net.minecraft.client.gui.GuiScreen;
12 | import net.minecraft.client.gui.inventory.GuiContainer;
13 | import net.minecraft.event.ClickEvent;
14 | import net.minecraft.event.HoverEvent;
15 | import net.minecraft.item.ItemStack;
16 | import net.minecraft.nbt.NBTTagCompound;
17 | import net.minecraft.nbt.NBTTagList;
18 | import net.minecraft.util.ChatComponentText;
19 | import net.minecraft.util.EnumChatFormatting;
20 | import net.minecraft.util.IChatComponent;
21 | import net.minecraft.util.StringUtils;
22 | import net.minecraftforge.client.event.ClientChatReceivedEvent;
23 | import net.minecraftforge.client.event.GuiScreenEvent;
24 | import net.minecraftforge.fml.common.Loader;
25 | import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
26 | import org.apache.commons.io.IOUtils;
27 | import org.apache.http.HttpEntity;
28 | import org.apache.http.HttpResponse;
29 | import org.apache.http.client.HttpClient;
30 | import org.apache.http.client.methods.HttpGet;
31 | import org.apache.http.client.methods.HttpPost;
32 | import org.apache.http.entity.ContentType;
33 | import org.apache.http.entity.StringEntity;
34 | import org.apache.http.impl.client.HttpClients;
35 | import org.lwjgl.input.Mouse;
36 |
37 | import java.io.IOException;
38 | import java.io.InputStream;
39 | import java.io.OutputStream;
40 | import java.net.HttpURLConnection;
41 | import java.net.URL;
42 | import java.nio.charset.StandardCharsets;
43 | import java.util.*;
44 | import java.util.concurrent.atomic.AtomicReference;
45 | import java.util.regex.Matcher;
46 | import java.util.regex.Pattern;
47 |
48 | public class Share {
49 |
50 | private final Pattern shareRegexPattern = Pattern.compile("\\{SynthesisShare:([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})}", Pattern.CASE_INSENSITIVE);
51 | private final Config config = Synthesis.getInstance().getConfig();
52 |
53 | @SubscribeEvent
54 | public void onMessageSent(MessageSentEvent event) {
55 | String message = event.message;
56 | if (message.contains(config.utilitiesShareText)) {
57 | ItemStack item = Minecraft.getMinecraft().thePlayer.getHeldItem();
58 | if (item == null) return;
59 | event.setCanceled(true);
60 |
61 | NBTTagCompound extraAttributes = item.getSubCompound("ExtraAttributes", false);
62 | JsonArray loreArray = new JsonArray();
63 | NBTTagList lore = item.getSubCompound("display", false).getTagList("Lore", 8);
64 | for (int i = 0; i < lore.tagCount(); i++) {
65 | loreArray.add(new JsonPrimitive(lore.getStringTagAt(i)));
66 | }
67 |
68 | JsonObject itemJson = new JsonObject();
69 | itemJson.add("name", new JsonPrimitive(item.getSubCompound("display", false).getString("Name")));
70 | itemJson.add("lore", loreArray);
71 | JsonObject extraObject = new JsonObject();
72 | if (item.hasTagCompound()) {
73 | if (item.getTagCompound().hasKey("display")) {
74 | if (item.getTagCompound().getCompoundTag("display").hasKey("color")) {
75 | extraObject.add("color", new JsonPrimitive(item.getTagCompound().getCompoundTag("display").getInteger("color")));
76 | }
77 | }
78 | }
79 | if (extraAttributes != null && extraAttributes.hasKey("uuid")) {
80 | itemJson.add("uuid", new JsonPrimitive(extraAttributes.getString("uuid")));
81 | }
82 |
83 | itemJson.add("extra", extraObject);
84 |
85 | JsonObject body = new JsonObject();
86 | body.add("owner", new JsonPrimitive(Minecraft.getMinecraft().getSession().getPlayerID()));
87 | body.add("item", itemJson);
88 |
89 | (new Thread(() -> {
90 | try {
91 | URL url = new URL("https://synthesis-share.antonio32a.com/share");
92 | HttpURLConnection http = (HttpURLConnection) url.openConnection();
93 | http.setDoOutput(true);
94 | http.setDoInput(true);
95 | http.setRequestProperty("Content-Type", "application/json");
96 | http.setRequestProperty("User-Agent", "SynthesisMod");
97 | http.setRequestProperty("Accept", "application/json");
98 | http.setRequestProperty("Method", "POST");
99 | http.connect();
100 | try (OutputStream os = http.getOutputStream()) {
101 | os.write(body.toString().getBytes(StandardCharsets.UTF_8));
102 | os.close();
103 | if (http.getResponseCode() != 200) {
104 | ChatLib.chat("Something went wrong trying to upload share. Check logs maybe?");
105 | return;
106 | }
107 | JsonParser parser = new JsonParser();
108 | JsonObject shareJson = parser.parse(IOUtils.toString(http.getInputStream())).getAsJsonObject();
109 | if (!shareJson.get("success").getAsBoolean()) {
110 | ChatLib.chat("Share was not successful. Reason: " + shareJson.get("error").getAsString());
111 | return;
112 | }
113 |
114 | String shareId = shareJson.get("share").getAsJsonObject().get("id").getAsString();
115 | String share = "{SynthesisShare:" + shareId + "}";
116 | //Can't write event.message because this is a thread
117 | Minecraft.getMinecraft().thePlayer.sendChatMessage(message.replace("[item]", share).replace("[share]", share));
118 | }
119 | } catch (IOException e) {
120 | ChatLib.chat("Something went wrong trying to upload share. Check logs maybe?");
121 | e.printStackTrace();
122 | }
123 | })).start();
124 | }
125 | }
126 |
127 | @SubscribeEvent
128 | public void onChatReceived(ClientChatReceivedEvent event) {
129 | if (event.type == 0 || event.type == 1) {
130 | String msg = StringUtils.stripControlCodes(event.message.getUnformattedText());
131 | if (!msg.contains("{SynthesisShare:") || !msg.contains("}")) return;
132 |
133 | Matcher matcher = shareRegexPattern.matcher(msg);
134 | event.setCanceled(true);
135 |
136 | (new Thread(() -> {
137 | ArrayList shares = new ArrayList<>();
138 | while (matcher.find()) {
139 | String shareId = matcher.group(1);
140 |
141 | try {
142 | URL url = new URL("https://synthesis-share.antonio32a.com/share/" + shareId);
143 | HttpURLConnection http = (HttpURLConnection) url.openConnection();
144 | http.setDoOutput(true);
145 | http.setDoInput(true);
146 | http.setRequestProperty("User-Agent", "SynthesisMod");
147 | http.setRequestProperty("Accept", "application/json");
148 | http.setRequestProperty("Method", "GET");
149 | http.connect();
150 | try (InputStream instream = http.getInputStream()) {
151 | if (http.getResponseCode() != 200) {
152 | Minecraft.getMinecraft().thePlayer.addChatMessage(event.message);
153 | return;
154 | }
155 | JsonParser parser = new JsonParser();
156 | JsonObject shareJson = parser.parse(new String(IOUtils.toByteArray(instream), StandardCharsets.UTF_8)).getAsJsonObject();
157 | if (!shareJson.get("success").getAsBoolean()) {
158 | Minecraft.getMinecraft().thePlayer.addChatMessage(event.message);
159 | return;
160 | }
161 |
162 | JsonObject shareItem = shareJson.get("share").getAsJsonObject().get("item").getAsJsonObject();
163 | String itemName = shareItem.get("name").getAsString();
164 | JsonArray itemLore = shareItem.get("lore").getAsJsonArray();
165 | boolean isItemVerified = shareJson.get("share").getAsJsonObject().get("verified").getAsBoolean();
166 |
167 | IChatComponent verifiedComponent = new ChatComponentText((isItemVerified ? EnumChatFormatting.GREEN + "✔ " : EnumChatFormatting.RED + "✖ "));
168 | verifiedComponent.getChatStyle().setChatHoverEvent(new HoverEvent(
169 | HoverEvent.Action.SHOW_TEXT,
170 | new ChatComponentText((isItemVerified ? EnumChatFormatting.GREEN + "This item is verified!\nIt exists in the API." : EnumChatFormatting.RED + "This item is not verified!\nAPI is off or the item may not exist."))
171 | ));
172 |
173 | AtomicReference s = new AtomicReference<>("");
174 | if (shareItem.has("extra")) {
175 | if (shareItem.get("extra").getAsJsonObject().has("color")) {
176 | s.set(EnumChatFormatting.GRAY + "Color: #" + Integer.toHexString(shareItem.get("extra").getAsJsonObject().get("color").getAsInt()).toUpperCase() + "\n");
177 | }
178 | }
179 | itemLore.iterator().forEachRemaining(jsonElement -> s.set(s.get() + jsonElement.getAsString() + "\n"));
180 | String shareLore = itemName + "\n" + s.get();
181 |
182 | IChatComponent shareComponent = new ChatComponentText(EnumChatFormatting.LIGHT_PURPLE
183 | + "[Synthesis " + itemName + EnumChatFormatting.LIGHT_PURPLE + "]");
184 | shareComponent.getChatStyle().setChatHoverEvent(new HoverEvent(
185 | HoverEvent.Action.SHOW_TEXT,
186 | new ChatComponentText(shareLore.substring(0, shareLore.length() - 1))
187 | )).setChatClickEvent(new ClickEvent(
188 | ClickEvent.Action.RUN_COMMAND,
189 | "/ctcc https://synthesis-share.antonio32a.com/share/" + shareId + "?embed"
190 | ));
191 | verifiedComponent.appendSibling(shareComponent);
192 | shares.add(verifiedComponent);
193 | }
194 | } catch (IOException | JsonParseException e) {
195 | Minecraft.getMinecraft().thePlayer.addChatMessage(event.message);
196 | e.printStackTrace();
197 | }
198 | }
199 |
200 | IChatComponent toSend = new ChatComponentText("");
201 | ListIterator it = Arrays.asList(event.message.getFormattedText().split(shareRegexPattern.pattern())).listIterator();
202 | while (it.hasNext()) {
203 | String s = it.next();
204 | toSend.appendSibling(new ChatComponentText(s));
205 | if (it.hasNext()) {
206 | toSend.appendSibling(shares.get(it.nextIndex() - 1));
207 | }
208 | }
209 |
210 | Minecraft.getMinecraft().thePlayer.addChatMessage(toSend);
211 | })).start();
212 |
213 | }
214 | }
215 |
216 | @SubscribeEvent
217 | public void onScroll(GuiScreenEvent.MouseInputEvent.Pre event) {
218 | if (!config.utilitiesShareScroll) return;
219 | if (!GuiScreen.isCtrlKeyDown()) return;
220 | if (!(event.gui instanceof GuiChat)) return;
221 | int i = Mouse.getEventDWheel();
222 | if (i != 0) {
223 | IChatComponent comp = Minecraft.getMinecraft().ingameGUI.getChatGUI().getChatComponent(Mouse.getX(), Mouse.getY());
224 | if (comp != null && comp.getChatStyle().getChatHoverEvent() != null && comp.getChatStyle().getChatHoverEvent().getAction() == HoverEvent.Action.SHOW_TEXT) {
225 | event.setCanceled(true);
226 | }
227 | }
228 | }
229 | }
230 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/features/utilities/VisibleLinks.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.features.utilities;
2 |
3 | import com.luna.synthesis.Synthesis;
4 | import com.luna.synthesis.core.Config;
5 | import net.minecraft.event.ClickEvent;
6 | import net.minecraft.util.EnumChatFormatting;
7 | import net.minecraft.util.IChatComponent;
8 | import net.minecraftforge.client.event.ClientChatReceivedEvent;
9 | import net.minecraftforge.fml.common.eventhandler.EventPriority;
10 | import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
11 |
12 | public class VisibleLinks {
13 |
14 | private final Config config = Synthesis.getInstance().getConfig();
15 |
16 | // Low priority so it's compatible with bridge
17 | @SubscribeEvent(priority = EventPriority.LOW)
18 | public void onChatMessage(ClientChatReceivedEvent event) {
19 | if (!config.utilitiesVisibleLinks) return;
20 | if (event.type == 0 || event.type == 1) {
21 | for (IChatComponent iChatComponent : event.message.getSiblings()) {
22 | if (iChatComponent.getChatStyle().getChatClickEvent() != null) {
23 | if (iChatComponent.getChatStyle().getChatClickEvent().getAction().equals(ClickEvent.Action.OPEN_URL)) {
24 | iChatComponent.getChatStyle().setColor(EnumChatFormatting.AQUA).setUnderlined(true);
25 | }
26 | }
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/features/utilities/WishingCompass.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.features.utilities;
2 |
3 | import com.luna.synthesis.Synthesis;
4 | import com.luna.synthesis.core.Config;
5 | import com.luna.synthesis.events.packet.PacketReceivedEvent;
6 | import com.luna.synthesis.utils.ChatLib;
7 | import net.minecraft.client.Minecraft;
8 | import net.minecraft.item.ItemStack;
9 | import net.minecraft.network.play.server.S2APacketParticles;
10 | import net.minecraft.util.BlockPos;
11 | import net.minecraft.util.EnumParticleTypes;
12 | import net.minecraft.util.StringUtils;
13 | import net.minecraft.util.Vec3;
14 | import net.minecraftforge.client.ClientCommandHandler;
15 | import net.minecraftforge.event.entity.player.PlayerInteractEvent;
16 | import net.minecraftforge.event.world.WorldEvent;
17 | import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
18 |
19 | public class WishingCompass {
20 |
21 | private final Config config = Synthesis.getInstance().getConfig();
22 | private boolean awaiting = false;
23 | private long lastItem = -1L;
24 | private Vec3 pos1 = null;
25 | private Vec3 pos2 = null;
26 | private Vec3 vec1 = null;
27 | private Vec3 vec2 = null;
28 |
29 | @SubscribeEvent
30 | public void onPacketReceived(PacketReceivedEvent event) {
31 | if (!config.utilitiesWishingCompass) return;
32 | if (event.getPacket() instanceof S2APacketParticles) {
33 | S2APacketParticles packet = (S2APacketParticles) event.getPacket();
34 | if (packet.getParticleType() == EnumParticleTypes.VILLAGER_HAPPY && packet.getParticleSpeed() == 0.0 && packet.getParticleCount() == 1.0) {
35 | if (awaiting) {
36 | if (pos1 == null) {
37 | pos1 = new Vec3(packet.getXCoordinate(), packet.getYCoordinate(), packet.getZCoordinate());
38 | awaiting = false;
39 | } else if (pos2 == null) {
40 | pos2 = new Vec3(packet.getXCoordinate(), packet.getYCoordinate(), packet.getZCoordinate());
41 | awaiting = false;
42 | }
43 | } else {
44 | if (vec1 == null && pos1 != null) {
45 | vec1 = new Vec3(packet.getXCoordinate() - pos1.xCoord, packet.getYCoordinate() - pos1.yCoord, packet.getZCoordinate() - pos1.zCoord).normalize();
46 | } else if (vec2 == null && pos2 != null) {
47 | vec2 = new Vec3(packet.getXCoordinate() - pos2.xCoord, packet.getYCoordinate() - pos2.yCoord, packet.getZCoordinate() - pos2.zCoord).normalize();
48 | calculateIntercept();
49 | }
50 | }
51 | }
52 | }
53 | }
54 |
55 | @SubscribeEvent
56 | public void onRightClick(PlayerInteractEvent event) {
57 | if (!config.utilitiesWishingCompass) return;
58 | if (event.action == PlayerInteractEvent.Action.RIGHT_CLICK_AIR || event.action == PlayerInteractEvent.Action.RIGHT_CLICK_BLOCK) {
59 | ItemStack item = Minecraft.getMinecraft().thePlayer.getHeldItem();
60 | if (item == null) return;
61 | if (StringUtils.stripControlCodes(item.getDisplayName()).contains("Wishing Compass")) {
62 | if (config.utilitiesBlockWishingCompass && System.currentTimeMillis() - lastItem < 4000) {
63 | ChatLib.chat("Last trail hasn't disappeared yet, chill.");
64 | event.setCanceled(true);
65 | return;
66 | }
67 | awaiting = true;
68 | lastItem = System.currentTimeMillis();
69 | }
70 | }
71 | }
72 |
73 | @SubscribeEvent
74 | public void onWorldLoad(WorldEvent.Load event) {
75 | pos1 = null;
76 | pos2 = null;
77 | vec1 = null;
78 | vec2 = null;
79 | awaiting = false;
80 | }
81 |
82 | // All math in the mod is thanks to Lucy, this included, thank you, Lucy!
83 | // If you don't understand something don't blame me, I just copied her notes.
84 | // And no, you cannot expect me to do very simple math, I will simply ask the math genius when possible.
85 | private void calculateIntercept() {
86 | double a = pos1.xCoord;
87 | double b = pos1.yCoord;
88 | double c = pos1.zCoord;
89 | double i = vec1.xCoord;
90 | double j = vec1.yCoord;
91 | double k = vec1.zCoord;
92 | //
93 | double h = pos2.xCoord;
94 | double v = pos2.yCoord;
95 | double w = pos2.zCoord;
96 | double l = vec2.xCoord;
97 | double m = vec2.yCoord;
98 | double n = vec2.zCoord;
99 |
100 | double t = ((b - v) / m - (a - h) / l) / ((i / l) - (j / m));
101 | double s = (j * (c - w) + k * (v - b)) / (j * n - k * m);
102 |
103 | if (t < 0 || s < 0) {
104 | ChatLib.chat("Something went wrong. Did you wait until the first particle trail disappeared? Did you move from one quadrant to another?");
105 | } else {
106 | BlockPos solution = new BlockPos((a + t * i + h + s * l) / 2, (b + t * j + v + s * m) / 2, (c + t * k + w + s * n) / 2);
107 | if (Math.abs(solution.getX() - 513) < 65 && Math.abs(solution.getZ() - 513) < 65) {
108 | ChatLib.chat("This compass points to the nucleus! You need to place crystals so the compass points somewhere else. It's also possible that the structure hasn't spawned.");
109 | } else {
110 | ChatLib.chat("Solution: (" + solution.getX() + ", " + solution.getY() + ", " + solution.getZ() + ")");
111 | if (config.utilitiesWishingCompassWaypoint) {
112 | ClientCommandHandler.instance.executeCommand(Minecraft.getMinecraft().thePlayer, "/sthw set " + solution.getX() + " " + solution.getY() + " " + solution.getZ() + " WishingCompass");
113 | }
114 | }
115 | }
116 |
117 | pos1 = pos2 = vec1 = vec2 = null;
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/managers/BackpackManager.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.managers;
2 |
3 | import com.google.gson.Gson;
4 | import com.google.gson.JsonArray;
5 | import com.google.gson.JsonObject;
6 | import com.google.gson.JsonPrimitive;
7 |
8 | import java.io.*;
9 |
10 | public class BackpackManager {
11 |
12 | private JsonObject jsonObject;
13 | private File file;
14 |
15 | // Damn this is old and garbage lmao
16 | public BackpackManager(File file) {
17 | if (!file.exists()) {
18 | try {
19 | file.createNewFile();
20 | this.file = file;
21 | createData();
22 | } catch (IOException e) {
23 | e.printStackTrace();
24 | }
25 | } else {
26 | try {
27 | FileReader reader = new FileReader(file);
28 | this.jsonObject = new Gson().fromJson(reader, JsonObject.class);
29 | this.file = file;
30 | reader.close();
31 | } catch (IOException e) {
32 | e.printStackTrace();
33 | }
34 | }
35 | }
36 |
37 |
38 | private void createData() throws IOException {
39 | JsonObject emptyData = new JsonObject();
40 | for (int i = 1; i <= 18; i++) {
41 | JsonArray array = new JsonArray();
42 | array.add(new JsonPrimitive(""));
43 | array.add(new JsonPrimitive(0));
44 | emptyData.add(String.valueOf(i), array);
45 | }
46 | this.jsonObject = emptyData;
47 | saveData();
48 | }
49 |
50 | private void saveData() {
51 | try {
52 | FileWriter writer = new FileWriter(this.file);
53 | new Gson().toJson(this.jsonObject, writer);
54 | writer.close();
55 | } catch (IOException e) {
56 | e.printStackTrace();
57 | }
58 | }
59 |
60 | public void modifyData(String key, String name, int meta) {
61 | JsonArray array = new JsonArray();
62 | array.add(new JsonPrimitive(name));
63 | array.add(new JsonPrimitive(meta));
64 | this.jsonObject.add(key, array);
65 | saveData();
66 | }
67 |
68 | public String getName(String key) {
69 | if (this.jsonObject.has(key)) {
70 | return this.jsonObject.get(key).getAsJsonArray().get(0).getAsString();
71 | } else {
72 | return "";
73 | }
74 | }
75 |
76 | public int getMeta(String key) {
77 | if (this.jsonObject.has(key)) {
78 | return this.jsonObject.get(key).getAsJsonArray().get(1).getAsInt();
79 | } else {
80 | return 0;
81 | }
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/managers/MathManager.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.managers;
2 |
3 | public class MathManager {
4 | }
5 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/mixins/BlockStainedGlassPaneMixin.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.mixins;
2 |
3 | import com.luna.synthesis.Synthesis;
4 | import net.minecraft.block.BlockPane;
5 | import net.minecraft.block.BlockStainedGlassPane;
6 | import net.minecraft.block.material.Material;
7 | import net.minecraft.block.properties.PropertyEnum;
8 | import net.minecraft.block.state.IBlockState;
9 | import net.minecraft.item.EnumDyeColor;
10 | import net.minecraft.util.BlockPos;
11 | import net.minecraft.util.EnumFacing;
12 | import net.minecraft.world.IBlockAccess;
13 | import org.spongepowered.asm.mixin.Mixin;
14 | import org.spongepowered.asm.mixin.Shadow;
15 |
16 | @Mixin(BlockStainedGlassPane.class)
17 | public class BlockStainedGlassPaneMixin extends BlockPane {
18 |
19 | protected BlockStainedGlassPaneMixin(Material materialIn, boolean canDrop) {
20 | super(materialIn, canDrop);
21 | }
22 |
23 | @Shadow
24 | public static final PropertyEnum COLOR = PropertyEnum.create("color", EnumDyeColor.class);
25 |
26 | @Override
27 | public IBlockState getActualState(IBlockState state, IBlockAccess worldIn, BlockPos pos) {
28 | if (Synthesis.getInstance() != null && Synthesis.getInstance().getConfig() != null) {
29 | if (Synthesis.getInstance().getConfig().utilitiesColorlessPanes) {
30 | return state.withProperty(NORTH, canPaneConnectTo(worldIn, pos, EnumFacing.NORTH))
31 | .withProperty(SOUTH, canPaneConnectTo(worldIn, pos, EnumFacing.SOUTH))
32 | .withProperty(WEST, canPaneConnectTo(worldIn, pos, EnumFacing.WEST))
33 | .withProperty(EAST, canPaneConnectTo(worldIn, pos, EnumFacing.EAST))
34 | .withProperty(COLOR, EnumDyeColor.SILVER);
35 | }
36 | }
37 | return super.getActualState(state, worldIn, pos);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/mixins/ContainerMixin.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.mixins;
2 |
3 | import com.luna.synthesis.Synthesis;
4 | import com.luna.synthesis.core.Config;
5 | import net.minecraft.client.Minecraft;
6 | import net.minecraft.inventory.Container;
7 | import net.minecraft.inventory.ContainerChest;
8 | import net.minecraft.item.ItemStack;
9 | import net.minecraft.nbt.NBTTagCompound;
10 | import net.minecraft.nbt.NBTTagInt;
11 | import net.minecraft.nbt.NBTTagString;
12 | import net.minecraft.util.StringUtils;
13 | import org.spongepowered.asm.mixin.Mixin;
14 | import org.spongepowered.asm.mixin.injection.At;
15 | import org.spongepowered.asm.mixin.injection.ModifyArg;
16 |
17 | @Mixin(Container.class)
18 | public class ContainerMixin {
19 |
20 | private final Config config = Synthesis.getInstance().getConfig();
21 |
22 | @ModifyArg(method = {"putStackInSlot", "putStacksInSlots"}, at = @At(value = "INVOKE", target = "Lnet/minecraft/inventory/Slot;putStack(Lnet/minecraft/item/ItemStack;)V"))
23 | public ItemStack overridePutStack(ItemStack in) {
24 | if (!config.utilitiesSuperpairsIDs) return in;
25 | if (Minecraft.getMinecraft().thePlayer.openContainer instanceof ContainerChest) {
26 | ContainerChest containerChest = (ContainerChest) Minecraft.getMinecraft().thePlayer.openContainer;
27 | String title = StringUtils.stripControlCodes(containerChest.getLowerChestInventory().getDisplayName().getUnformattedText());
28 | if (!title.startsWith("Superpairs (")) return in;
29 | if (in == null) return in;
30 | String itemName = StringUtils.stripControlCodes(in.getDisplayName());
31 | if (itemName.equals("Experiment the Fish")) return in;
32 |
33 | if (!in.getTagCompound().hasKey("ExtraAttributes")) {
34 | in.getTagCompound().setTag("ExtraAttributes", new NBTTagCompound());
35 | }
36 | NBTTagCompound ea = in.getTagCompound().getCompoundTag("ExtraAttributes");
37 |
38 | if (itemName.startsWith("+")) {
39 | if (itemName.endsWith(" Enchanting Exp")) {
40 | ea.setTag("id", new NBTTagString("ENCHANTING_EXPERIENCE"));
41 | } else if (itemName.endsWith(" XP")) {
42 | ea.setTag("id", new NBTTagString("POWER_UP_EXPERIENCE"));
43 | }
44 | }
45 |
46 | switch (itemName) {
47 | case "Gained +3 Clicks":
48 | ea.setTag("id", new NBTTagString("POWER_UP_EXTRA_CLICKS"));
49 | break;
50 | case "Instant Find":
51 | ea.setTag("id", new NBTTagString("POWER_UP_INSTANT_FIND"));
52 | break;
53 | case "Titanic Experience Bottle":
54 | ea.setTag("id", new NBTTagString("TITANIC_EXP_BOTTLE"));
55 | break;
56 | case "Grand Experience Bottle":
57 | ea.setTag("id", new NBTTagString("GRAND_EXP_BOTTLE"));
58 | break;
59 | case "Experience Bottle":
60 | ea.setTag("id", new NBTTagString("EXP_BOTTLE"));
61 | break;
62 | case "Enchanted Book":
63 | ea.setTag("id", new NBTTagString("ENCHANTED_BOOK"));
64 | ea.setTag("enchantments", new NBTTagCompound());
65 | String enchant = StringUtils.stripControlCodes(in.getSubCompound("display", false).getTagList("Lore", 8).getStringTagAt(2));
66 | String enchantName = "";
67 | for (int i = 0; i < enchant.split(" ").length - 1; i++) {
68 | enchantName += enchant.split(" ")[i];
69 | if (i != enchant.split(" ").length - 2) {
70 | enchantName += "_";
71 | }
72 | }
73 | enchantName = enchantName.toLowerCase();
74 | ea.getCompoundTag("enchantments").setTag(enchantName, new NBTTagInt(in.stackSize));
75 | break;
76 | }
77 | }
78 | return in;
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/mixins/EntityPlayerMixin.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.mixins;
2 |
3 | import com.luna.synthesis.Synthesis;
4 | import com.luna.synthesis.core.Config;
5 | import net.minecraft.entity.EntityLivingBase;
6 | import net.minecraft.entity.monster.EntityZombie;
7 | import net.minecraft.entity.player.EntityPlayer;
8 | import net.minecraft.world.World;
9 | import org.spongepowered.asm.mixin.Mixin;
10 | import org.spongepowered.asm.mixin.injection.At;
11 | import org.spongepowered.asm.mixin.injection.Inject;
12 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
13 |
14 | @Mixin(EntityPlayer.class)
15 | public abstract class EntityPlayerMixin extends EntityLivingBase {
16 |
17 | private final Config config = Synthesis.getInstance().getConfig();
18 |
19 | public EntityPlayerMixin(World worldIn) {
20 | super(worldIn);
21 | }
22 |
23 | @Inject(method = "isEntityInsideOpaqueBlock", at = @At("HEAD"), cancellable = true)
24 | public void isEntityInsideOpaqueBlock(CallbackInfoReturnable cir) {
25 | if (config.utilitiesArmadilloFix && this.isRiding() && this.ridingEntity instanceof EntityZombie) {
26 | cir.setReturnValue(false);
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/mixins/EntityPlayerSPMixin.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.mixins;
2 |
3 | import com.luna.synthesis.Synthesis;
4 | import com.luna.synthesis.core.Config;
5 | import net.minecraft.client.entity.EntityPlayerSP;
6 | import net.minecraft.client.gui.GuiChat;
7 | import net.minecraft.client.gui.GuiScreen;
8 | import net.minecraft.client.gui.inventory.GuiContainer;
9 | import org.spongepowered.asm.mixin.Mixin;
10 | import org.spongepowered.asm.mixin.injection.At;
11 | import org.spongepowered.asm.mixin.injection.Redirect;
12 |
13 | @Mixin(EntityPlayerSP.class)
14 | public class EntityPlayerSPMixin {
15 |
16 | private final Config config = Synthesis.getInstance().getConfig();
17 |
18 | // It's possible (and very easy) to make portals never close any gui (since it closes it only clientside, server would not care)
19 | // BUT I'm not sure if Hypixel would like that/there's any potential false bans SO only chat for now.
20 | @Redirect(method = "onLivingUpdate", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiScreen;doesGuiPauseGame()Z"))
21 | public boolean overrideDoesGuiPauseGame(GuiScreen gui) {
22 | if (config.utilitiesPortalChat) {
23 | return gui.doesGuiPauseGame() || gui instanceof GuiChat; //|| gui instanceof GuiContainer;
24 | }
25 | return gui.doesGuiPauseGame();
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/mixins/GuiContainerMixin.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.mixins;
2 |
3 | import com.luna.synthesis.Synthesis;
4 | import com.luna.synthesis.core.Config;
5 | import com.luna.synthesis.utils.MixinUtils;
6 | import com.luna.synthesis.utils.ReflectionUtils;
7 | import net.minecraft.client.gui.*;
8 | import net.minecraft.client.gui.inventory.GuiContainer;
9 | import org.spongepowered.asm.mixin.Mixin;
10 | import org.spongepowered.asm.mixin.injection.At;
11 | import org.spongepowered.asm.mixin.injection.Inject;
12 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
13 |
14 | import java.util.ArrayList;
15 | import java.util.List;
16 |
17 | @Mixin(GuiContainer.class)
18 | public class GuiContainerMixin extends GuiScreen {
19 |
20 | private final Config config = Synthesis.getInstance().getConfig();
21 | private final boolean patcherClearField = ReflectionUtils.getPatcherChatField();
22 |
23 | private GuiTextField inputField;
24 |
25 | @Inject(method = "initGui", at = @At("RETURN"))
26 | public void initGui(CallbackInfo ci) {
27 | if (config.utilitiesContainerChat) {
28 | this.inputField = new GuiTextField(0, this.fontRendererObj, 4, this.height - 12, this.width - 4, 12);
29 | this.inputField.setMaxStringLength(256);
30 | this.inputField.setEnableBackgroundDrawing(false);
31 | this.inputField.setText(config.utilitiesTransferContainerChat && MixinUtils.inputField != null && MixinUtils.inputField.isFocused() && !MixinUtils.inputField.getText().equals("") ? MixinUtils.inputField.getText() : "");
32 | this.inputField.setFocused(MixinUtils.inputField != null && MixinUtils.inputField.isFocused());
33 | this.inputField.setCanLoseFocus(false);
34 | MixinUtils.inputField = this.inputField;
35 | if (config.utilitiesResizeContainerChat) {
36 | mc.ingameGUI.getChatGUI().refreshChat();
37 | }
38 | }
39 | }
40 |
41 | @Inject(method = "updateScreen", at = @At("RETURN"))
42 | public void updateScreen(CallbackInfo ci) {
43 | if (config.utilitiesContainerChat) {
44 | this.inputField.updateCursorCounter();
45 | }
46 | }
47 |
48 | @Inject(method = "drawScreen", at = @At(value = "INVOKE", target = "net/minecraft/client/gui/GuiScreen.drawScreen(IIF)V"))
49 | public void drawScreen(int mouseX, int mouseY, float partialTicks, CallbackInfo ci) {
50 | if (config.utilitiesContainerChat && this.inputField.isFocused()) {
51 | if (!patcherClearField) {
52 | Gui.drawRect(2, this.height - 14, this.width - 2, this.height - 2, Integer.MIN_VALUE);
53 | }
54 | this.inputField.drawTextBox();
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/mixins/GuiNewChatMixin.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.mixins;
2 |
3 | import com.google.common.collect.Lists;
4 | import com.luna.synthesis.Synthesis;
5 | import com.luna.synthesis.core.Config;
6 | import com.luna.synthesis.features.utilities.SearchMode;
7 | import com.luna.synthesis.mixins.accessors.GuiChatAccessor;
8 | import com.luna.synthesis.mixins.accessors.GuiContainerAccessor;
9 | import com.luna.synthesis.utils.MixinUtils;
10 | import com.luna.synthesis.utils.Utils;
11 | import net.minecraft.client.Minecraft;
12 | import net.minecraft.client.gui.*;
13 | import net.minecraft.client.gui.inventory.GuiContainer;
14 | import net.minecraft.util.ChatComponentText;
15 | import net.minecraft.util.EnumChatFormatting;
16 | import net.minecraft.util.IChatComponent;
17 | import net.minecraft.util.StringUtils;
18 | import org.spongepowered.asm.mixin.Final;
19 | import org.spongepowered.asm.mixin.Mixin;
20 | import org.spongepowered.asm.mixin.Shadow;
21 | import org.spongepowered.asm.mixin.injection.*;
22 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
23 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
24 | import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
25 |
26 | import java.util.List;
27 |
28 | @Mixin(GuiNewChat.class)
29 | public abstract class GuiNewChatMixin {
30 |
31 | private boolean needsRefresh = false;
32 | @Final @Shadow private final List chatLines = Lists.newArrayList();
33 | @Final @Shadow private final List drawnChatLines = Lists.newArrayList();
34 | @Shadow public abstract void deleteChatLine(int id);
35 | @Shadow protected abstract void setChatLine(IChatComponent chatComponent, int chatLineId, int updateCounter, boolean displayOnly);
36 | private final Config config = Synthesis.getInstance().getConfig();
37 |
38 | @Inject(method = "clearChatMessages", at = @At(value = "INVOKE", target = "Ljava/util/List;clear()V", ordinal = 2), cancellable = true)
39 | public void clearChatMessages(CallbackInfo ci) {
40 | if (Synthesis.getInstance() != null && Synthesis.getInstance().getConfig() != null && Synthesis.getInstance().getConfig().futureKeepSentMessages) {
41 | ci.cancel();
42 | }
43 | }
44 |
45 | @Inject(method = "getChatWidth", at = @At("HEAD"), cancellable = true)
46 | public void getChatWidth(CallbackInfoReturnable cir) {
47 | if (Synthesis.getInstance() != null && Synthesis.getInstance().getConfig() != null && Synthesis.getInstance().getConfig().utilitiesContainerChat && Minecraft.getMinecraft().currentScreen instanceof GuiContainer && Synthesis.getInstance().getConfig().utilitiesResizeContainerChat) {
48 | cir.setReturnValue(((GuiContainerAccessor) Minecraft.getMinecraft().currentScreen).getGuiLeft());
49 | needsRefresh = true;
50 | } else {
51 | if (needsRefresh) {
52 | needsRefresh = false;
53 | Minecraft.getMinecraft().ingameGUI.getChatGUI().refreshChat();
54 | }
55 | }
56 | }
57 |
58 | @Inject(method = "getChatOpen", at = @At("HEAD"), cancellable = true)
59 | public void getChatOpen(CallbackInfoReturnable cir) {
60 | if (Synthesis.getInstance() != null && Synthesis.getInstance().getConfig() != null && Synthesis.getInstance().getConfig().utilitiesContainerChat && Minecraft.getMinecraft().currentScreen instanceof GuiContainer) {
61 | if (MixinUtils.inputField != null && MixinUtils.inputField.isFocused()) {
62 | cir.setReturnValue(true);
63 | }
64 | }
65 | }
66 |
67 | // A way to "continue" in loops from inside a mixin. Kinda proud of this one ngl, fixes lag when searching for a lot of lines, mostly with Patcher's void chat.
68 | @ModifyVariable(method = "refreshChat", at = @At(value = "INVOKE", target = "Ljava/util/List;get(I)Ljava/lang/Object;", shift = At.Shift.BEFORE), index = 1)
69 | public int i(int in) {
70 | GuiScreen gui = Minecraft.getMinecraft().currentScreen;
71 | if (SearchMode.isSearchMode && ((gui instanceof GuiChat) || (gui instanceof GuiContainer && config.utilitiesContainerChat && MixinUtils.inputField != null && MixinUtils.inputField.isFocused()))) {
72 | GuiTextField input = gui instanceof GuiChat ? ((GuiChatAccessor) gui).getInputField() : MixinUtils.inputField;
73 | if (!input.getText().equals("")) {
74 | String line = StringUtils.stripControlCodes(this.chatLines.get(in).getChatComponent().getUnformattedText()).toLowerCase();
75 | if (!line.contains(input.getText().toLowerCase()) || !line.equals("search mode on")) {
76 | for (int i = in; i >= 0; i--) {
77 | String line2 = StringUtils.stripControlCodes(this.chatLines.get(i).getChatComponent().getUnformattedText()).toLowerCase();
78 | if (line2.contains(input.getText().toLowerCase()) || line2.equals("search mode on")) {
79 | return i;
80 | }
81 | }
82 | return -1;
83 | }
84 | return in;
85 | }
86 | }
87 | return in;
88 | }
89 |
90 | // This just here so it's possible to "continue" in the last iteration of the loop
91 | @Inject(method = "refreshChat", at = @At(value = "INVOKE", target = "Ljava/util/List;get(I)Ljava/lang/Object;"), cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD)
92 | public void refreshChat(CallbackInfo ci, int i) {
93 | if (i == -1) {
94 | ci.cancel();
95 | }
96 | }
97 |
98 | @Inject(method = "setChatLine", at = @At("HEAD"), cancellable = true)
99 | public void setChatLine(IChatComponent chatComponent, int chatLineId, int updateCounter, boolean displayOnly, CallbackInfo ci) {
100 | if (SearchMode.isSearchMode && Minecraft.getMinecraft().currentScreen instanceof GuiChat) {
101 | GuiTextField input = ((GuiChatAccessor) Minecraft.getMinecraft().currentScreen).getInputField();
102 | String text = chatComponent.getUnformattedText().toLowerCase();
103 | if (!input.getText().equals("") && !text.contains(input.getText().toLowerCase()) && !displayOnly) {
104 | this.chatLines.add(0, new ChatLine(updateCounter, chatComponent, chatLineId));
105 | ci.cancel();
106 | }
107 | }
108 | }
109 |
110 | // The section below is used so the SEARCH MODE ON message always stays at the bottom of the chat
111 |
112 | // Fix for refreshChat deleting messages with same id? For no reason either??
113 | // If you're not using the mod, go to a hub and tab player's names so the message of potential players shows up
114 | // Then, go to chat options and modify any setting, like opacity, doesn't matter if end value is the same, it just has to be changed
115 | // THE MESSAGE WILL DISAPPEAR, FOR NO REASON EITHER, WHAT THE FWICK
116 | @Redirect(method = "setChatLine", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiNewChat;deleteChatLine(I)V"))
117 | public void deleteChatLine(GuiNewChat chat, int id, IChatComponent chatComponent, int chatLineId, int updateCounter, boolean displayOnly) {
118 | if (!displayOnly) {
119 | this.deleteChatLine(id);
120 | }
121 | }
122 |
123 | @ModifyArg(method = "setChatLine", at = @At(value = "INVOKE", target = "Ljava/util/List;add(ILjava/lang/Object;)V", ordinal = 0))
124 | public int modifyIndex(int in, Object line) {
125 | ChatLine cl = (ChatLine) line;
126 | if (SearchMode.isSearchMode && !cl.getChatComponent().getFormattedText().contains(EnumChatFormatting.YELLOW + "" + EnumChatFormatting.BOLD + "SEARCH MODE ON")) {
127 | if (this.drawnChatLines.size() == 0) {
128 | this.deleteChatLine("synthesissearchmode".hashCode());
129 | this.setChatLine(new ChatComponentText(EnumChatFormatting.YELLOW + "" + EnumChatFormatting.BOLD + "SEARCH MODE ON"), "synthesissearchmode".hashCode(), Minecraft.getMinecraft().ingameGUI.getUpdateCounter(), true);
130 | }
131 | return 1;
132 | }
133 | return in;
134 | }
135 |
136 | // For reforge message cleanup - There's probably a better way to do this, but I'm blind
137 | // Also regexes wack, you know how it goes with me and regexes
138 | @ModifyArg(method = "printChatMessage", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiNewChat;printChatMessageWithOptionalDeletion(Lnet/minecraft/util/IChatComponent;I)V"), index = 1)
139 | public int overrideChatId(IChatComponent chatComponent, int in) {
140 | if (config.cleanupChatOldReforgeMessages) {
141 | String msg = StringUtils.stripControlCodes(chatComponent.getUnformattedText());
142 | // Why must I be punished like this.
143 | // What have I done to deserve this.
144 | // Luna from the future (10 minutes after starting to code this): I should have done this with like 5 regexes holy shit this is annoying
145 | // I have no clue what I did here, but I indeed regret it now, months after the fact, now that I have to change this.
146 | if ((msg.startsWith("You reforged your ") && msg.contains(" into a ") && msg.endsWith("!")) ||
147 | (msg.startsWith("You applied the ") && msg.contains(" reforge to your ") && msg.endsWith("!")) ||
148 | (msg.startsWith("You selected the ") && msg.endsWith(" power for your Accessory Bag!"))) {
149 | return "synthesisreforgemessagecleanup".hashCode();
150 | }
151 | }
152 | return in;
153 | }
154 | }
155 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/mixins/GuiPlayerTabOverlayMixin.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.mixins;
2 |
3 | import com.luna.synthesis.Synthesis;
4 | import com.luna.synthesis.core.Config;
5 | import net.minecraft.client.gui.GuiPlayerTabOverlay;
6 | import net.minecraft.util.ChatComponentText;
7 | import net.minecraft.util.IChatComponent;
8 | import org.spongepowered.asm.mixin.Mixin;
9 | import org.spongepowered.asm.mixin.injection.At;
10 | import org.spongepowered.asm.mixin.injection.ModifyVariable;
11 |
12 | @Mixin(GuiPlayerTabOverlay.class)
13 | public class GuiPlayerTabOverlayMixin {
14 |
15 | private final Config config = Synthesis.getInstance().getConfig();
16 |
17 | // mhm tasty spaghetti
18 |
19 | @ModifyVariable(method = "setFooter", at = @At("HEAD"), argsOnly = true)
20 | public IChatComponent overrideFooter(IChatComponent in) {
21 | if (config.cleanupTablistFooter) {
22 | String s = in.getFormattedText()
23 | .replace("\n§r§r§r§r§s§r\n§r§r§aRanks, Boosters & MORE! §r§c§lSTORE.HYPIXEL.NET§r", "")
24 | .replace("§r§aRanks, Boosters & MORE! §r§c§lSTORE.HYPIXEL.NET§r", "");
25 | return s.length() == 0 ? null : new ChatComponentText(s);
26 | }
27 | return in;
28 | }
29 |
30 | @ModifyVariable(method = "setHeader", at = @At("HEAD"), argsOnly = true)
31 | public IChatComponent overrideHeader(IChatComponent in) {
32 | if (config.cleanupTablistHeader) {
33 | return null;
34 | }
35 | return in;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/mixins/GuiScreenMixin.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.mixins;
2 |
3 | import com.luna.synthesis.events.MessageSentEvent;
4 | import net.minecraft.client.gui.GuiScreen;
5 | import net.minecraftforge.common.MinecraftForge;
6 | import org.spongepowered.asm.mixin.Mixin;
7 | import org.spongepowered.asm.mixin.injection.At;
8 | import org.spongepowered.asm.mixin.injection.Inject;
9 | import org.spongepowered.asm.mixin.injection.ModifyVariable;
10 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
11 |
12 | @Mixin(GuiScreen.class)
13 | public class GuiScreenMixin {
14 |
15 | private String newMessage = "";
16 |
17 | @Inject(method = "sendChatMessage(Ljava/lang/String;)V", at = @At("HEAD"), cancellable = true)
18 | public void onMessageSent(String message, CallbackInfo ci) {
19 | MessageSentEvent event = new MessageSentEvent(message);
20 | MinecraftForge.EVENT_BUS.post(event);
21 |
22 | if (event.isCanceled()) {
23 | ci.cancel();
24 | } else if (!event.message.equals(message)) {
25 | newMessage = event.message;
26 | }
27 | }
28 |
29 | @ModifyVariable(method = "sendChatMessage(Ljava/lang/String;)V", at = @At("HEAD"))
30 | public String overrideMessageSent(String msg) {
31 | if (!newMessage.equals("")) {
32 | msg = newMessage;
33 | newMessage = "";
34 | }
35 | return msg;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/mixins/RenderItemMixin.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.mixins;
2 |
3 | import com.luna.synthesis.Synthesis;
4 | import com.luna.synthesis.core.Config;
5 | import com.luna.synthesis.managers.BackpackManager;
6 | import com.luna.synthesis.utils.MixinUtils;
7 | import net.minecraft.client.Minecraft;
8 | import net.minecraft.client.gui.FontRenderer;
9 | import net.minecraft.client.renderer.GlStateManager;
10 | import net.minecraft.client.renderer.ItemModelMesher;
11 | import net.minecraft.client.renderer.entity.RenderItem;
12 | import net.minecraft.client.resources.model.IBakedModel;
13 | import net.minecraft.init.Items;
14 | import net.minecraft.inventory.ContainerChest;
15 | import net.minecraft.item.Item;
16 | import net.minecraft.item.ItemStack;
17 | import net.minecraft.nbt.NBTTagCompound;
18 | import net.minecraft.util.StringUtils;
19 | import org.spongepowered.asm.mixin.Mixin;
20 | import org.spongepowered.asm.mixin.injection.*;
21 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
22 |
23 | import java.util.Iterator;
24 | import java.util.concurrent.atomic.AtomicReference;
25 |
26 | @Mixin(RenderItem.class)
27 | public class RenderItemMixin {
28 |
29 | private final Config config = Synthesis.getInstance().getConfig();
30 |
31 | // Might make these two onto a forge event because they're very cool
32 | @Redirect(method = "renderItemIntoGUI", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/ItemModelMesher;getItemModel(Lnet/minecraft/item/ItemStack;)Lnet/minecraft/client/resources/model/IBakedModel;"))
33 | public IBakedModel iBakedModel(ItemModelMesher imm, ItemStack stack) {
34 | String name = StringUtils.stripControlCodes(stack.getDisplayName());
35 | if (config.utilitiesBackpackRetexturing && name.startsWith("Backpack Slot ")) {
36 | String number = name.replaceAll("Backpack Slot ", "");
37 | BackpackManager bpm = Synthesis.getInstance().getBackpackManager();
38 | if (!bpm.getName(number).equals("")) {
39 | return MixinUtils.getItemModel(imm, Item.getByNameOrId(bpm.getName(number)), bpm.getMeta(number));
40 | }
41 | }
42 | return imm.getItemModel(stack);
43 | }
44 |
45 | @Inject(method = "renderItemOverlayIntoGUI", at = @At(value = "JUMP", ordinal = 1, shift = At.Shift.BEFORE), cancellable = true)
46 | public void renderItemOverlayIntoGUI(FontRenderer fr, ItemStack stack, int xPosition, int yPosition, String text, CallbackInfo ci) {
47 | if (Minecraft.getMinecraft().thePlayer.openContainer instanceof ContainerChest) {
48 | ContainerChest containerChest = (ContainerChest) Minecraft.getMinecraft().thePlayer.openContainer;
49 | String title = StringUtils.stripControlCodes(containerChest.getLowerChestInventory().getDisplayName().getUnformattedText());
50 | if (config.utilitiesPerkLevelDisplay && title.equals("Heart of the Mountain")) {
51 | if (stack.getItem() == Items.emerald || (config.utilitiesMaxPerkLevelDisplay && stack.getItem() == Items.diamond)) {
52 | String level = StringUtils.stripControlCodes(stack.getTooltip(Minecraft.getMinecraft().thePlayer, true).get(1));
53 | if (level.startsWith("Level ")) {
54 | level = level.replaceAll("Level ", "");
55 | } else {
56 | return;
57 | }
58 | if (level.contains("/")) {
59 | level = level.split("/")[0];
60 | }
61 | if (level.equals("1")) return;
62 | drawStringAsStackSize(level, xPosition, yPosition);
63 | ci.cancel();
64 | }
65 | } else if (config.utilitiesBestiaryGlance && (title.equals("Bestiary") || title.contains(" ➜ "))) {
66 | if (StringUtils.stripControlCodes(stack.getDisplayName()).startsWith("Bestiary Milestone ")) {
67 | String level = StringUtils.stripControlCodes(stack.getDisplayName()).replace("Bestiary Milestone ", "");
68 | drawStringAsStackSize(level, xPosition, yPosition);
69 | ci.cancel();
70 | } else if (stack == containerChest.getInventory().get(52)) {
71 | ItemStack bestiary = containerChest.getInventory().get(51);
72 | if (bestiary == null || !bestiary.getDisplayName().contains("Bestiary Milestone ")) return;
73 | AtomicReference progress = new AtomicReference<>("");
74 | Iterator it = bestiary.getTooltip(Minecraft.getMinecraft().thePlayer, false).iterator();
75 | it.forEachRemaining(s -> {
76 | String line = StringUtils.stripControlCodes(s);
77 | if (line.endsWith("/10")) {
78 | progress.set(line.split(" ")[line.split(" ").length - 1].replace("/10", ""));
79 | }
80 | });
81 | if (progress.get().equals("")) return;
82 | drawStringAsStackSize(progress.get(), xPosition, yPosition);
83 | ci.cancel();
84 | }
85 | }
86 | }
87 | if (config.utilitiesWishingCompassUsesLeft) {
88 | if (stack != null && stack.getDisplayName().contains("Wishing Compass")) {
89 | NBTTagCompound tag = stack.getTagCompound();
90 | if (tag.hasKey("ExtraAttributes")) {
91 | if (tag.getCompoundTag("ExtraAttributes").hasKey("wishing_compass_uses")) {
92 | drawStringAsStackSize(String.valueOf(3 - tag.getCompoundTag("ExtraAttributes").getInteger("wishing_compass_uses")), xPosition, yPosition);
93 | } else {
94 | if (config.utilitiesWishingCompassAlwaysUsesLeft) {
95 | drawStringAsStackSize("3", xPosition, yPosition);
96 | }
97 | }
98 | }
99 | }
100 | }
101 | }
102 |
103 | private void drawStringAsStackSize(String text, int xPosition, int yPosition) {
104 | GlStateManager.disableLighting();
105 | GlStateManager.disableDepth();
106 | GlStateManager.disableBlend();
107 | Minecraft.getMinecraft().fontRendererObj.drawStringWithShadow(text, (float)(xPosition + 19 - 2 - Minecraft.getMinecraft().fontRendererObj.getStringWidth(text)), (float)(yPosition + 6 + 3), 16777215);
108 | GlStateManager.enableLighting();
109 | GlStateManager.enableDepth();
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/mixins/accessors/GuiChatAccessor.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.mixins.accessors;
2 |
3 | import net.minecraft.client.gui.GuiChat;
4 | import net.minecraft.client.gui.GuiTextField;
5 | import org.spongepowered.asm.mixin.Mixin;
6 | import org.spongepowered.asm.mixin.gen.Accessor;
7 |
8 | @Mixin(GuiChat.class)
9 | public interface GuiChatAccessor {
10 |
11 | @Accessor GuiTextField getInputField();
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/mixins/accessors/GuiContainerAccessor.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.mixins.accessors;
2 |
3 | import net.minecraft.client.gui.inventory.GuiContainer;
4 | import org.spongepowered.asm.mixin.Mixin;
5 | import org.spongepowered.asm.mixin.gen.Accessor;
6 |
7 | @Mixin(GuiContainer.class)
8 | public interface GuiContainerAccessor {
9 |
10 | @Accessor int getGuiLeft();
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/mixins/accessors/GuiNewChatAccessor.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.mixins.accessors;
2 |
3 | import net.minecraft.client.gui.ChatLine;
4 | import net.minecraft.client.gui.GuiNewChat;
5 | import net.minecraft.util.IChatComponent;
6 | import org.spongepowered.asm.mixin.Mixin;
7 | import org.spongepowered.asm.mixin.Shadow;
8 | import org.spongepowered.asm.mixin.gen.Accessor;
9 | import org.spongepowered.asm.mixin.gen.Invoker;
10 |
11 | import java.util.List;
12 |
13 | @Mixin(GuiNewChat.class)
14 | public interface GuiNewChatAccessor {
15 |
16 | @Accessor List getChatLines();
17 | @Accessor List getDrawnChatLines();
18 | @Accessor int getScrollPos();
19 | @Invoker void invokeSetChatLine(IChatComponent chatComponent, int chatLineId, int updateCounter, boolean displayOnly);
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/mixins/accessors/GuiRepairAccessor.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.mixins.accessors;
2 |
3 | import net.minecraft.client.gui.GuiRepair;
4 | import net.minecraft.client.gui.GuiTextField;
5 | import org.spongepowered.asm.mixin.Mixin;
6 | import org.spongepowered.asm.mixin.gen.Accessor;
7 |
8 | @Mixin(GuiRepair.class)
9 | public interface GuiRepairAccessor {
10 |
11 | @Accessor GuiTextField getNameField();
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/mixins/accessors/ItemModelMesherAccessor.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.mixins.accessors;
2 |
3 | import net.minecraft.client.renderer.ItemModelMesher;
4 | import net.minecraft.client.resources.model.IBakedModel;
5 | import net.minecraft.item.Item;
6 | import org.spongepowered.asm.mixin.Mixin;
7 | import org.spongepowered.asm.mixin.gen.Invoker;
8 |
9 | @Mixin(ItemModelMesher.class)
10 | public interface ItemModelMesherAccessor {
11 |
12 | @Invoker IBakedModel invokeGetItemModel(Item item, int meta);
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/mixins/accessors/S2FPacketSetSlotAccessor.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.mixins.accessors;
2 |
3 | import net.minecraft.item.ItemStack;
4 | import net.minecraft.network.play.server.S2FPacketSetSlot;
5 | import org.spongepowered.asm.mixin.Mixin;
6 | import org.spongepowered.asm.mixin.gen.Accessor;
7 |
8 | @Mixin(S2FPacketSetSlot.class)
9 | public interface S2FPacketSetSlotAccessor {
10 |
11 | @Accessor int getWindowId();
12 | @Accessor int getSlot();
13 | @Accessor(value = "item") ItemStack getItemStack();
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/mixins/neu/NEUEventListenerMixin.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.mixins.neu;
2 |
3 | import com.luna.synthesis.utils.MixinUtils;
4 | import org.spongepowered.asm.mixin.Dynamic;
5 | import org.spongepowered.asm.mixin.Mixin;
6 | import org.spongepowered.asm.mixin.Pseudo;
7 | import org.spongepowered.asm.mixin.injection.At;
8 | import org.spongepowered.asm.mixin.injection.ModifyArg;
9 |
10 | @Pseudo
11 | @Mixin(targets = "io.github.moulberry.notenoughupdates.NEUEventListener", remap = false)
12 | public class NEUEventListenerMixin {
13 |
14 | @Dynamic
15 | @ModifyArg(method = "onTick", at = @At(value = "INVOKE", target = "Lorg/lwjgl/input/Keyboard;enableRepeatEvents(Z)V"))
16 | public boolean overrideKeyEvents(boolean in) {
17 | if (MixinUtils.inputField != null && MixinUtils.inputField.isFocused()) {
18 | return true;
19 | }
20 | return in;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/mixins/optifine/CapeUtilsMixin.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.mixins.optifine;
2 |
3 | import com.luna.synthesis.Synthesis;
4 | import com.luna.synthesis.core.Config;
5 | import com.luna.synthesis.utils.ChatLib;
6 | import net.minecraft.client.Minecraft;
7 | import org.spongepowered.asm.mixin.Dynamic;
8 | import org.spongepowered.asm.mixin.Mixin;
9 | import org.spongepowered.asm.mixin.Pseudo;
10 | import org.spongepowered.asm.mixin.injection.At;
11 | import org.spongepowered.asm.mixin.injection.ModifyVariable;
12 |
13 | @Pseudo
14 | @Mixin(targets = "net.optifine.player.CapeUtils")
15 | public class CapeUtilsMixin {
16 |
17 | private static final Config config = Synthesis.getInstance().getConfig();
18 |
19 | // I want to give people the ability to toggle anything in the mod they don't want.
20 | // I don't know what would cause people to toggle them off.
21 | // I wouldn't be mad, just disappointed.
22 | @Dynamic
23 | @ModifyVariable(method = "downloadCape(Lnet/minecraft/client/entity/AbstractClientPlayer;)V", at = @At("STORE"), name = "username")
24 | private static String downloadCape(String in) {
25 | if (!config.utilitiesOptifineCustomCape.equals("") && in.equals(Minecraft.getMinecraft().getSession().getUsername())) {
26 | return config.utilitiesOptifineCustomCape;
27 | }
28 | if (config.utilitiesOptifineTransYeti && in.equals("Yeti ")) {
29 | return "Yeti";
30 | }
31 | if (config.utilitiesOptifineTransTerracotta && in.equals("Terracotta ")) {
32 | return "Terracotta";
33 | }
34 | if (config.utilitiesOptifineNonBinaryBonzo && in.equals("Bonzo ")) {
35 | return "Bonzo";
36 | }
37 | if (config.utilitiesOptifineCandyCaneGrinch && in.equals("Grinch ")) {
38 | return "Grinch";
39 | }
40 | return in;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/mixins/optifine/PlayerItemsLayerMixin.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.mixins.optifine;
2 |
3 | import com.luna.synthesis.Synthesis;
4 | import com.luna.synthesis.core.Config;
5 | import net.minecraft.entity.EntityLivingBase;
6 | import org.spongepowered.asm.mixin.Mixin;
7 | import org.spongepowered.asm.mixin.Pseudo;
8 | import org.spongepowered.asm.mixin.injection.At;
9 | import org.spongepowered.asm.mixin.injection.Inject;
10 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
11 |
12 | @Pseudo
13 | @Mixin(targets = "net.optifine.player.PlayerItemsLayer")
14 | public class PlayerItemsLayerMixin {
15 |
16 | private final Config config = Synthesis.getInstance().getConfig();
17 |
18 | // It's so great that I just made this almost after the santa hat is gone, but hey, here's to 2022 halloween if humanity hasn't collapsed by then.
19 | @Inject(method = "renderEquippedItems(Lnet/minecraft/entity/EntityLivingBase;FF)V", at = @At("HEAD"), cancellable = true)
20 | public void renderEquippedItems(EntityLivingBase entityLiving, float scale, float partialTicks, CallbackInfo ci) {
21 | if (config.utilitiesOptifineHideHats) {
22 | ci.cancel();
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/mixins/patcher/ChatHandlerMixin.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.mixins.patcher;
2 |
3 | import com.luna.synthesis.Synthesis;
4 | import com.luna.synthesis.core.Config;
5 | import net.minecraft.client.gui.ChatLine;
6 | import org.spongepowered.asm.mixin.Dynamic;
7 | import org.spongepowered.asm.mixin.Mixin;
8 | import org.spongepowered.asm.mixin.Pseudo;
9 | import org.spongepowered.asm.mixin.injection.At;
10 | import org.spongepowered.asm.mixin.injection.Redirect;
11 |
12 | import java.util.Set;
13 |
14 | @Pseudo
15 | @Mixin(targets = "club.sk1er.patcher.util.chat.ChatHandler", remap = false)
16 | public class ChatHandlerMixin {
17 |
18 | private static final Config config = Synthesis.getInstance().getConfig();
19 |
20 | // GuiNewChat::setChatLine breaks equals since ChatLine's is not overridden + the method creates a new chat line, this fixes that
21 | @Dynamic
22 | @Redirect(method = "deleteMessageByHash(I)Z", at = @At(value = "INVOKE", target = "Ljava/util/Set;contains(Ljava/lang/Object;)Z"), remap = false)
23 | private static boolean contains(Set toRemove, Object obj) {
24 | if (!config.patcherCompactChatFix) return toRemove.contains(obj);
25 | ChatLine cl2 = (ChatLine) obj;
26 | for (ChatLine cl : toRemove) {
27 | if (cl.getChatLineID() == cl2.getChatLineID() && cl.getUpdatedCounter() == cl2.getUpdatedCounter() && cl.getChatComponent().equals(cl2.getChatComponent())) {
28 | return true;
29 | }
30 | }
31 | return false;
32 | }
33 | }
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/mixins/patcher/ImagePreviewerMixin.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.mixins.patcher;
2 |
3 | import com.luna.synthesis.Synthesis;
4 | import com.luna.synthesis.core.Config;
5 | import gg.essential.api.utils.TrustedHostsUtil;
6 | import org.spongepowered.asm.mixin.Dynamic;
7 | import org.spongepowered.asm.mixin.Mixin;
8 | import org.spongepowered.asm.mixin.Pseudo;
9 | import org.spongepowered.asm.mixin.injection.At;
10 | import org.spongepowered.asm.mixin.injection.Redirect;
11 |
12 | import java.util.Collections;
13 | import java.util.HashSet;
14 | import java.util.Set;
15 |
16 | @Pseudo
17 | @Mixin(targets = "club.sk1er.patcher.screen.render.overlay.ImagePreview", remap = false)
18 | public class ImagePreviewerMixin {
19 |
20 | private final Config config = Synthesis.getInstance().getConfig();
21 |
22 | // Probably not the way to do this since TrustedHostUtil::addTrustedHost exists BUT don't care.
23 | @Dynamic
24 | @Redirect(method = "handle(Ljava/lang/String;)V", at = @At(value = "INVOKE", target = "Lgg/essential/api/utils/TrustedHostsUtil;getTrustedHosts()Ljava/util/Set;"))
25 | public Set equalsIgnoreCase(TrustedHostsUtil util) {
26 | if (config.patcherCustomImagePreviewer && !config.patcherCustomDomains.equals("")) {
27 | Set newHosts = new HashSet<>(util.getTrustedHosts());
28 | for (String s : config.patcherCustomDomains.split(",")) {
29 | newHosts.add(new TrustedHostsUtil.TrustedHost(s, s, Collections.singleton(s)));
30 | }
31 | return newHosts;
32 | } else {
33 | return util.getTrustedHosts();
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/mixins/skytils/ChatTabsMixin.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.mixins.skytils;
2 |
3 | import com.luna.synthesis.Synthesis;
4 | import com.luna.synthesis.core.Config;
5 | import com.luna.synthesis.utils.Utils;
6 | import net.minecraft.network.play.server.S02PacketChat;
7 | import net.minecraft.util.ChatComponentText;
8 | import net.minecraft.util.IChatComponent;
9 | import net.minecraft.util.StringUtils;
10 | import org.spongepowered.asm.mixin.Dynamic;
11 | import org.spongepowered.asm.mixin.Mixin;
12 | import org.spongepowered.asm.mixin.Pseudo;
13 | import org.spongepowered.asm.mixin.injection.At;
14 | import org.spongepowered.asm.mixin.injection.ModifyVariable;
15 | import org.spongepowered.asm.mixin.injection.Redirect;
16 |
17 | import java.util.regex.Matcher;
18 | import java.util.regex.Pattern;
19 |
20 | @Pseudo
21 | @Mixin(targets = "skytils.skytilsmod.features.impl.handlers.ChatTabs", remap = false)
22 | public class ChatTabsMixin {
23 |
24 | private final Config config = Synthesis.getInstance().getConfig();
25 |
26 | // Hacky way to add bridge messages to guild, shrug
27 | @Dynamic
28 | @ModifyVariable(method = "shouldAllow", at = @At("HEAD"))
29 | public IChatComponent overrideShouldAllow(IChatComponent in) {
30 | if (config.utilitiesBridgeGuildChatTab) {
31 | if (in.getFormattedText().startsWith(config.utilitiesBridgeMessageFormat.replaceAll("&", "§").split("<")[0])) {
32 | return new ChatComponentText("§r§2Guild > " + in.getFormattedText());
33 | }
34 | }
35 | return in;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/utils/ChatLib.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.utils;
2 |
3 | import net.minecraft.client.Minecraft;
4 | import net.minecraft.util.ChatComponentText;
5 |
6 | public class ChatLib {
7 |
8 | public static void chat(Object message) {
9 | if (message instanceof String) {
10 | for (String s : ((String) message).split("\n")) {
11 | s = "&d[Synthesis]&r " + s;
12 | Minecraft.getMinecraft().thePlayer.addChatMessage(
13 | new ChatComponentText(s.replaceAll("&", "§"))
14 | );
15 | }
16 | } else {
17 | message = ("&d[Synthesis]&r " + message).replaceAll("&", "§");
18 | Minecraft.getMinecraft().thePlayer.addChatMessage(
19 | new ChatComponentText(message.toString()));
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/utils/MixinUtils.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.utils;
2 |
3 | import com.luna.synthesis.mixins.accessors.ItemModelMesherAccessor;
4 | import net.minecraft.client.gui.GuiTextField;
5 | import net.minecraft.client.renderer.ItemModelMesher;
6 | import net.minecraft.client.resources.model.IBakedModel;
7 | import net.minecraft.item.Item;
8 |
9 | // This is the absolute wrong way to do this BUT until I figure out something better, shrug
10 | public class MixinUtils {
11 |
12 | public static GuiTextField inputField;
13 |
14 | public static IBakedModel getItemModel(ItemModelMesher imm, Item item, int meta) {
15 | ItemModelMesherAccessor imma = (ItemModelMesherAccessor) imm;
16 | return imma.invokeGetItemModel(item, meta);
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/utils/ReflectionUtils.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.utils;
2 |
3 | import net.minecraftforge.fml.common.Loader;
4 |
5 | import java.lang.reflect.Field;
6 |
7 | public class ReflectionUtils {
8 |
9 | private static final String PATCHER_CONFIG_NAME = "club.sk1er.patcher.config.PatcherConfig";
10 | private static Field patcherChatField = null;
11 |
12 | public static void onInit() {
13 | if (Loader.isModLoaded("patcher")) {
14 | handlePatcherReflection();
15 | }
16 | }
17 |
18 | private static void handlePatcherReflection() {
19 | try {
20 | Class> cls = Class.forName(PATCHER_CONFIG_NAME);
21 | Field f = cls.getField("transparentChatInputField");
22 | if (f.getType() == boolean.class) {
23 | patcherChatField = f;
24 | }
25 | } catch (ReflectiveOperationException e) {
26 | // Why is there not a logger
27 | System.out.println("Unable to execute Patcher Reflection");
28 | }
29 | }
30 |
31 | public static boolean getPatcherChatField(){
32 | if (patcherChatField == null) return false;
33 | try {
34 | return patcherChatField.getBoolean(null);
35 | } catch (ReflectiveOperationException ignored) {}
36 | return false;
37 | }
38 |
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/com/luna/synthesis/utils/Utils.java:
--------------------------------------------------------------------------------
1 | package com.luna.synthesis.utils;
2 |
3 | import net.minecraft.client.renderer.GlStateManager;
4 | import net.minecraft.client.renderer.Tessellator;
5 | import net.minecraft.client.renderer.WorldRenderer;
6 | import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
7 | import net.minecraft.event.ClickEvent;
8 | import net.minecraft.util.ChatComponentText;
9 | import net.minecraft.util.IChatComponent;
10 | import net.minecraft.util.MathHelper;
11 | import org.lwjgl.opengl.GL11;
12 |
13 | import java.net.URI;
14 | import java.net.URISyntaxException;
15 | import java.util.regex.Matcher;
16 | import java.util.regex.Pattern;
17 |
18 | import static org.lwjgl.opengl.GL11.*;
19 |
20 | public class Utils {
21 |
22 | private static final Pattern linkPattern = Pattern.compile("((?:[a-z0-9]{2,}:\\/\\/)?(?:(?:[0-9]{1,3}\\.){3}[0-9]{1,3}|(?:[-\\w_\\.]{1,}\\.[a-z]{2,}?))(?::[0-9]{1,5})?.*?(?=[!\"\u00A7 \n]|$))", Pattern.CASE_INSENSITIVE);
23 |
24 | // Copied and adapted from Patcher
25 | public static boolean isDivider(String message) {
26 | if (message == null) return false;
27 | if (message.length() < 5) {
28 | return false;
29 | } else {
30 | // Dear god, forgive me, for I am tired.
31 | if (message.equals("-------------- Guild: Message Of The Day --------------") || message.equals("---------- Guild: Message Of The Day (Preview) ----------")) {
32 | return true;
33 | } else {
34 | for (int i = 0; i < message.length(); i++) {
35 | char c = message.charAt(i);
36 | if (c != '-' && c != '=' && c != '\u25AC') {
37 | return false;
38 | }
39 | }
40 | }
41 | }
42 | return true;
43 | }
44 |
45 | // Adapted from ForgeHooks::newChatWithLinks, may change linkPattern in the future
46 | public static IChatComponent newChatWithLinks(String string) {
47 | IChatComponent ichat = null;
48 | Matcher matcher = linkPattern.matcher(string);
49 | int lastEnd = 0;
50 |
51 | while (matcher.find()) {
52 | int start = matcher.start();
53 | int end = matcher.end();
54 |
55 | String part = string.substring(lastEnd, start);
56 | if (part.length() > 0) {
57 | if (ichat == null) {
58 | ichat = new ChatComponentText(part);
59 | } else {
60 | ichat.appendText(part);
61 | }
62 | }
63 | lastEnd = end;
64 | String url = string.substring(start, end);
65 | IChatComponent link = new ChatComponentText(url);
66 |
67 | try {
68 | if ((new URI(url)).getScheme() == null) {
69 | url = "http://" + url;
70 | }
71 | } catch (URISyntaxException e) {
72 | if (ichat == null) ichat = new ChatComponentText(url);
73 | else ichat.appendText(url);
74 | continue;
75 | }
76 |
77 | ClickEvent click = new ClickEvent(ClickEvent.Action.OPEN_URL, url);
78 | link.getChatStyle().setChatClickEvent(click);
79 | if (ichat == null) {
80 | ichat = link;
81 | } else {
82 | ichat.appendSibling(link);
83 | }
84 | }
85 |
86 | String end = string.substring(lastEnd);
87 | if (ichat == null) {
88 | ichat = new ChatComponentText(end);
89 | } else if (end.length() > 0) {
90 | ichat.appendText(string.substring(lastEnd));
91 | }
92 | return ichat;
93 | }
94 |
95 | public static void renderBeamSegment(double x, double y, double z, double partialTicks, double textureScale, double totalWorldTime, int yOffset, int height, float[] colors) {
96 | double beamRadius = 0.2D;
97 | double glowRadius = 0.25D;
98 | int i = yOffset + height;
99 | GL11.glTexParameteri(3553, 10242, 10497);
100 | GL11.glTexParameteri(3553, 10243, 10497);
101 | GlStateManager.disableLighting();
102 | GlStateManager.disableCull();
103 | GlStateManager.disableBlend();
104 | GlStateManager.depthMask(true);
105 | GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ONE, GL_ZERO);
106 | Tessellator tessellator = Tessellator.getInstance();
107 | WorldRenderer worldRenderer = tessellator.getWorldRenderer();
108 | double d0 = totalWorldTime + partialTicks;
109 | double d1 = height < 0 ? d0 : -d0;
110 | double d2 = MathHelper.func_181162_h(d1 * 0.2D - (double)MathHelper.floor_double(d1 * 0.1D));
111 | float f = colors[0];
112 | float f1 = colors[1];
113 | float f2 = colors[2];
114 | double d3 = d0 * 0.025D * -1.5D;
115 | double d4 = 0.5D + Math.cos(d3 + 2.356194490192345D) * beamRadius;
116 | double d5 = 0.5D + Math.sin(d3 + 2.356194490192345D) * beamRadius;
117 | double d6 = 0.5D + Math.cos(d3 + (Math.PI / 4D)) * beamRadius;
118 | double d7 = 0.5D + Math.sin(d3 + (Math.PI / 4D)) * beamRadius;
119 | double d8 = 0.5D + Math.cos(d3 + 3.9269908169872414D) * beamRadius;
120 | double d9 = 0.5D + Math.sin(d3 + 3.9269908169872414D) * beamRadius;
121 | double d10 = 0.5D + Math.cos(d3 + 5.497787143782138D) * beamRadius;
122 | double d11 = 0.5D + Math.sin(d3 + 5.497787143782138D) * beamRadius;
123 | double d14 = -1.0D + d2;
124 | double d15 = (double)height * textureScale * (0.5D / beamRadius) + d14;
125 | worldRenderer.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR);
126 | worldRenderer.pos(x + d4, y + (double)i, z + d5).tex(1.0D, d15).color(f, f1, f2, 1.0F).endVertex();
127 | worldRenderer.pos(x + d4, y + (double)yOffset, z + d5).tex(1.0D, d14).color(f, f1, f2, 1.0F).endVertex();
128 | worldRenderer.pos(x + d6, y + (double)yOffset, z + d7).tex(0.0D, d14).color(f, f1, f2, 1.0F).endVertex();
129 | worldRenderer.pos(x + d6, y + (double)i, z + d7).tex(0.0D, d15).color(f, f1, f2, 1.0F).endVertex();
130 | worldRenderer.pos(x + d10, y + (double)i, z + d11).tex(1.0D, d15).color(f, f1, f2, 1.0F).endVertex();
131 | worldRenderer.pos(x + d10, y + (double)yOffset, z + d11).tex(1.0D, d14).color(f, f1, f2, 1.0F).endVertex();
132 | worldRenderer.pos(x + d8, y + (double)yOffset, z + d9).tex(0.0D, d14).color(f, f1, f2, 1.0F).endVertex();
133 | worldRenderer.pos(x + d8, y + (double)i, z + d9).tex(0.0D, d15).color(f, f1, f2, 1.0F).endVertex();
134 | worldRenderer.pos(x + d6, y + (double)i, z + d7).tex(1.0D, d15).color(f, f1, f2, 1.0F).endVertex();
135 | worldRenderer.pos(x + d6, y + (double)yOffset, z + d7).tex(1.0D, d14).color(f, f1, f2, 1.0F).endVertex();
136 | worldRenderer.pos(x + d10, y + (double)yOffset, z + d11).tex(0.0D, d14).color(f, f1, f2, 1.0F).endVertex();
137 | worldRenderer.pos(x + d10, y + (double)i, z + d11).tex(0.0D, d15).color(f, f1, f2, 1.0F).endVertex();
138 | worldRenderer.pos(x + d8, y + (double)i, z + d9).tex(1.0D, d15).color(f, f1, f2, 1.0F).endVertex();
139 | worldRenderer.pos(x + d8, y + (double)yOffset, z + d9).tex(1.0D, d14).color(f, f1, f2, 1.0F).endVertex();
140 | worldRenderer.pos(x + d4, y + (double)yOffset, z + d5).tex(0.0D, d14).color(f, f1, f2, 1.0F).endVertex();
141 | worldRenderer.pos(x + d4, y + (double)i, z + d5).tex(0.0D, d15).color(f, f1, f2, 1.0F).endVertex();
142 | tessellator.draw();
143 | GlStateManager.enableBlend();
144 | GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
145 | GlStateManager.depthMask(false);
146 | d3 = 0.5D - glowRadius;
147 | d4 = 0.5D - glowRadius;
148 | d5 = 0.5D + glowRadius;
149 | d6 = 0.5D - glowRadius;
150 | d7 = 0.5D - glowRadius;
151 | d8 = 0.5D + glowRadius;
152 | d9 = 0.5D + glowRadius;
153 | d10 = 0.5D + glowRadius;
154 | double d13 = -1.0D + d2;
155 | d14 = (double)height * textureScale + d13;
156 | worldRenderer.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR);
157 | worldRenderer.pos(x + d3, y + (double)i, z + d4).tex(1.0D, d14).color(f, f1, f2, 0.125F).endVertex();
158 | worldRenderer.pos(x + d3, y + (double)yOffset, z + d4).tex(1.0D, d13).color(f, f1, f2, 0.125F).endVertex();
159 | worldRenderer.pos(x + d5, y + (double)yOffset, z + d6).tex(0.0D, d13).color(f, f1, f2, 0.125F).endVertex();
160 | worldRenderer.pos(x + d5, y + (double)i, z + d6).tex(0.0D, d14).color(f, f1, f2, 0.125F).endVertex();
161 | worldRenderer.pos(x + d9, y + (double)i, z + d10).tex(1.0D, d14).color(f, f1, f2, 0.125F).endVertex();
162 | worldRenderer.pos(x + d9, y + (double)yOffset, z + d10).tex(1.0D, d13).color(f, f1, f2, 0.125F).endVertex();
163 | worldRenderer.pos(x + d7, y + (double)yOffset, z + d8).tex(0.0D, d13).color(f, f1, f2, 0.125F).endVertex();
164 | worldRenderer.pos(x + d7, y + (double)i, z + d8).tex(0.0D, d14).color(f, f1, f2, 0.125F).endVertex();
165 | worldRenderer.pos(x + d5, y + (double)i, z + d6).tex(1.0D, d14).color(f, f1, f2, 0.125F).endVertex();
166 | worldRenderer.pos(x + d5, y + (double)yOffset, z + d6).tex(1.0D, d13).color(f, f1, f2, 0.125F).endVertex();
167 | worldRenderer.pos(x + d9, y + (double)yOffset, z + d10).tex(0.0D, d13).color(f, f1, f2, 0.125F).endVertex();
168 | worldRenderer.pos(x + d9, y + (double)i, z + d10).tex(0.0D, d14).color(f, f1, f2, 0.125F).endVertex();
169 | worldRenderer.pos(x + d7, y + (double)i, z + d8).tex(1.0D, d14).color(f, f1, f2, 0.125F).endVertex();
170 | worldRenderer.pos(x + d7, y + (double)yOffset, z + d8).tex(1.0D, d13).color(f, f1, f2, 0.125F).endVertex();
171 | worldRenderer.pos(x + d3, y + (double)yOffset, z + d4).tex(0.0D, d13).color(f, f1, f2, 0.125F).endVertex();
172 | worldRenderer.pos(x + d3, y + (double)i, z + d4).tex(0.0D, d14).color(f, f1, f2, 0.125F).endVertex();
173 | tessellator.draw();
174 | GlStateManager.enableLighting();
175 | GlStateManager.enableTexture2D();
176 | GlStateManager.depthMask(true);
177 | }
178 | }
179 |
--------------------------------------------------------------------------------
/src/main/resources/mcmod.info:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "modid": "synthesis",
4 | "name": "Synthesis",
5 | "description": "Hypixel SkyBlock/general QoL mod.",
6 | "version": "${version}",
7 | "mcversion": "1.8.9",
8 | "url": "",
9 | "updateUrl": "",
10 | "authorList": ["Luna, Desco"],
11 | "credits": "Heart DC, The CouncilTM, E and microwave guild for a lot of this mod's suggestions. Also Antonio32A for hosting the share service and making the entire backend.",
12 | "logoFile": "",
13 | "screenshots": [],
14 | "dependencies": []
15 | }
16 | ]
17 |
--------------------------------------------------------------------------------
/src/main/resources/synthesis.mixins.json:
--------------------------------------------------------------------------------
1 | {
2 | "compatibilityLevel": "JAVA_8",
3 | "package": "com.luna.synthesis.mixins",
4 | "refmap": "synthesis.mixins.refmap.json",
5 | "mixins": [
6 | "accessors.GuiChatAccessor",
7 | "accessors.GuiContainerAccessor",
8 | "accessors.GuiNewChatAccessor",
9 | "accessors.GuiRepairAccessor",
10 | "accessors.ItemModelMesherAccessor",
11 | "accessors.S2FPacketSetSlotAccessor",
12 | "neu.NEUEventListenerMixin",
13 | "optifine.CapeUtilsMixin",
14 | "optifine.PlayerItemsLayerMixin",
15 | "patcher.ChatHandlerMixin",
16 | "patcher.ImagePreviewerMixin",
17 | "skytils.ChatTabsMixin",
18 | "BlockStainedGlassPaneMixin",
19 | "ContainerMixin",
20 | "EntityPlayerMixin",
21 | "EntityPlayerSPMixin",
22 | "GuiContainerMixin",
23 | "GuiNewChatMixin",
24 | "GuiPlayerTabOverlayMixin",
25 | "GuiScreenMixin",
26 | "RenderItemMixin"
27 | ],
28 | "client": [],
29 | "server": []
30 | }
--------------------------------------------------------------------------------