diff --git a/README.md b/README.md index 0bce57191..902fe61c5 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # PolyPatcher - ![Dev Workflow Status](https://img.shields.io/github/v/release/Polyfrost/PolyPatcher.svg?style=for-the-badge&color=1452cc&label=release) +oneconfig logo ![Dev Workflow Status](https://img.shields.io/github/v/release/Polyfrost/PolyPatcher.svg?style=for-the-badge&color=1452cc&label=release) PolyPatcher is a Forge mod for 1.8.9 & 1.12.2 created to improve your all-around Minecraft experience, bringing tons of Quality of Life additions, performance improvements, and tons of Vanilla bug fixes. @@ -17,6 +17,7 @@ This work, "PolyPatcher", is adapted from ["Patcher"](https://sk1er.club/mods/pa - **Layers In Tab** - Resolve players sometimes not having a hat layer in Tab. *default - **Player Void Rendering** - Resolve the black box around the player while in the void. *default - **Alex Arm Position** - Resolve Alex-model arms being shifted down further than Steve-model arms. *default +- **Add Background to Book GUI** *(not in original)* - Adds the dark background to the book GUI like all other containers/menus. - **Resource Exploit Fix** - Resolve an exploit in 1.8 allowing servers to look through directories. *default - **Forge Chest Behavior** - Resolve forge changing vanilla chest behavior. *default @@ -24,6 +25,7 @@ This work, "PolyPatcher", is adapted from ["Patcher"](https://sk1er.club/mods/pa Experimental # Experimental +- **Improved Skin Rendering** *(not in original)* - Remove transparent pixels on skins instead of turning them black. - **HUD Caching** - Reuse frames from the HUD instead of constantly recreating them every frame, as most HUD elements will stay the same for a long amount of time. (This may cause stuff with animations to feel "choppy".) - **Cache FPS** *(not in original)* - The amount of frames to cache for the HUD. @@ -34,6 +36,7 @@ This work, "PolyPatcher", is adapted from ["Patcher"](https://sk1er.club/mods/pa # Miscellaneous - **Remove Ground Foliage** - Stop plants/flower from rendering. - **1.12 Farm Selection Boxes** - Replace the selection box for crops with the 1.12 variant. (Only works on Hypixel & Singleplayer) *default +- **Exclude Cacti from 1.12 Boxes** *(not in original)* - Exclude cacti from the 1.12 selection box changes, as it would actually shrink rather than increase in size. *default - **Remove Water FOV** *(not in original)* - Remove FOV change when underwater. *default - **FOV Modifier** - Allow for modifying FOV change states. - **Sprinting FOV** - Modify your FOV when sprinting. @@ -45,7 +48,7 @@ This work, "PolyPatcher", is adapted from ["Patcher"](https://sk1er.club/mods/pa - **Disable Hotbar Scrolling** - Remove the ability to scroll through your hotbar. - **Invert Hotbar Scrolling** *(not in original)* - Change the direction of scrolling in your hotbar. - **Prevent Overflow Hotbar Scrolling** *(not in original)* - Prevent from directly scrolling between the first and last hotbar slot. -- ~~**Crosshair Perspective** - Remove the crosshair when in third person.~~ (replaced by [PolyCrosshair](https://modrinth.com/mod/polycrosshair)) +- ~~**Crosshair Perspective** - Remove the crosshair when in third person.~~ (replaced by [PolyCrosshair](https://modrinth.com/mod/crosshair)) - **Unfocused Sounds** - Change the volume of sounds when you're not tabbed into the window. - **Unfocused FPS** - Toggle changing your FPS to whatever Unfocused FPS is set to when not tabbed into the window.** - **Unfocused FPS Amount** - Change the maximum FPS when you're not tabbed into the window, saving resources. @@ -77,7 +80,7 @@ This work, "PolyPatcher", is adapted from ["Patcher"](https://sk1er.club/mods/pa - **Hide Fire Overlay with Fire Resistance** - Hide the fire overlay when you have fire resistance active. The overlay will blink 5 seconds before your fire resistance is about to run out. - **Pumpkin Overlay Opacity** *(not in original)* - Change the opacity of the pumpkin overlay. - **Remove Water Overlay** - Remove the water texture overlay when underwater. -- ~~**Remove Inverted Colors from Crosshair** - Remove the inverted color effect on the crosshair.~~ (replaced by [PolyCrosshair](https://modrinth.com/mod/polycrosshair)) +- ~~**Remove Inverted Colors from Crosshair** - Remove the inverted color effect on the crosshair.~~ (replaced by [PolyCrosshair](https://modrinth.com/mod/crosshair)) - **Fullbright** - Remove lighting updates, increasing visibility. (Can positively impact performance. May conflict with minimaps) *default - **Smart Fullbright** - Automatically Disable the Fullbright Effect when using OptiFine Shaders. (Requires Fullbright) *default - **Disable Night Vision** *(not in original)* - Completely disables the effects of night vision. @@ -85,6 +88,7 @@ This work, "PolyPatcher", is adapted from ["Patcher"](https://sk1er.club/mods/pa - ~~**Show Own Nametag** - See your nametag in third person.~~ (replaced by [PolyNametag](https://modrinth.com/mod/polynametag)) - **Clean Projectiles** - Show projectiles 2 ticks after they're shot up to stop them from obstructing your view. (Includes eggs, snowballs, and fishing hooks) - **Ridden Horse Opacity** - Change the opacity of the horse you're currently riding for visibility. +- **Water Fog Density** *(not in original)* - Changes the fog density in water to improve visibility. - **Hide Aura on Invisible Withers** - Don't render the aura around a wither when it is invisible. - **Numerical Enchantments** - Use readable numbers instead of Roman numerals on enchants. - **Translate Unknown Roman Numerals** - Generate Roman Numeral from enchantment/potion level instead of using language file. *default @@ -105,8 +109,7 @@ This work, "PolyPatcher", is adapted from ["Patcher"](https://sk1er.club/mods/pa - ~~**Title Opacity** - Change the opacity of titles.~~ (replaced by [VanillaHUD](https://modrinth.com/mod/vanillahud)) - **Windowed Fullscreen** - Implement Windowed Fullscreen in Minecraft, allowing you to drag your mouse outside the window. - **Instant Fullscreen** - Instant switching between fullscreen and non-fullscreen modes. -- **Natural Capes** - Changes some physics in capes to fix rotation bugs and look more natural. -- **Fix Action Bar Overlap** - Prevents action bar text from overlapping with armor or health bars. +- ~~**Fix Action Bar Overlap** - Prevents action bar text from overlapping with armor or health bars.~~ (replaced by [VanillaHUD](https://modrinth.com/mod/vanillahud))
@@ -162,16 +165,16 @@ This work, "PolyPatcher", is adapted from ["Patcher"](https://sk1er.club/mods/pa # Screens - **1.11 Chat Length** - Extend the number of characters you can type from 100 to 256 on supported servers. (Supported servers are servers that support 1.11 or above. Some servers may kick you for this despite supporting 1.11 or above) *default - **Remove Chat Message Limit** *(not in original)* - Remove the limit on how many messages can show up in chat. *default -- **Transparent Chat** - Remove the background from chat. (Can positively impact performance). -- **Transparent Chat Input Field** - Remove the background from chat's input field. (Can positively impact performance). -- **Extend Chat Background** - Extend the chat background all the way to the left of the screen. *default +- ~~**Transparent Chat** - Remove the background from chat. (Can positively impact performance).~~ (replaced by [Chatting](https://modrinth.com/mod/chatting)) +- ~~**Transparent Chat Input Field** - Remove the background from chat's input field. (Can positively impact performance).~~ (replaced by [Chatting](https://modrinth.com/mod/chatting)) +- ~~**Extend Chat Background** - Extend the chat background all the way to the left of the screen. *default~~ (replaced by [Chatting](https://modrinth.com/mod/chatting)) - **Compact Chat** - Clean up the chat by stacking duplicate messages (Does not work with Labymod) *default - **Consecutive Compact Chat** - Only compact messages if they're consecutive. - **Compact Chat Time** - Change the amount of time old messages take to stop being compacted. (Measured in seconds) - **Remove Blank Messages** - Stop messages with no content from showing up in chat. - **Shift Chat** - Keep chat open while sending a message if Shift is held while pressing Enter. - **Chat Delay** - Delay chat messages if they're sent within the selected timeframe after the previous message. (Measured in seconds) -- **Chat Position** - Move the chat up 12 pixels to stop it from overlapping the health bar, as done in 1.12+. *default +- ~~**Chat Position** - Move the chat up 12 pixels to stop it from overlapping the health bar, as done in 1.12+. *default~~ (replaced by [Chatting](https://modrinth.com/mod/chatting)) - **Chat Timestamps** - Add timestamps before a message. - **Chat Timestamps Style** - Choose how Chat Timestamps should appear. - **Chat Timestamps Format** - Change the time format of Chat Timestamps. @@ -184,7 +187,7 @@ This work, "PolyPatcher", is adapted from ["Patcher"](https://sk1er.club/mods/pa - **Projectile Protection Percentage** - View how much total projectile protection you have inside your inventory. - **Container Background Opacity** *(not in original)* - Change the opacity of the dark background inside a container, or remove it completely. - **Container Opacity** - Change the opacity of supported containers. Includes Chests & Survival inventory. -- ~~**GUI Crosshair** - Stop rendering the crosshair when in a GUI.~~ (replaced by [PolyCrosshair](https://modrinth.com/mod/polycrosshair)) +- ~~**GUI Crosshair** - Stop rendering the crosshair when in a GUI.~~ (replaced by [PolyCrosshair](https://modrinth.com/mod/crosshair)) - **Startup Notification** - Notify how long the game took to start. *default - **Clean Main Menu** - Remove the Realms button on the main menu as it's useless on 1.8.9. *default - **Open to LAN Replacement** - Modify the Open to LAN button to either redirect to the server list or be removed. @@ -222,27 +225,38 @@ This work, "PolyPatcher", is adapted from ["Patcher"](https://sk1er.club/mods/pa Changes from original mod # Changes from original mod +- Replace Essential with OneConfig - Boost performance by batch-drawing tile entities - Boost performance by reducing quad counts in item models +- Boost performance by decreasing size of sine and cosine lookup tables +- Boost performance by only rendering special tile entities once instead of twice per frame +- Improve speed when changing language, mipmap level, and anisotropic filtering level - Fix Forge held item lighting to match vanilla - Fix vanilla bug where entering an entity in spectator mode while in third person applies shaders - Fix vanilla bug where enchantment glint takes up the whole slot - Fix vanilla bug where items glitch out when using negative scale +- Fix vanilla bug where pumpkin overlay shows in spectator mode - Fix vanilla sky lighting calculation +- Fix texture manager memory leak +- Fix compatability with LoliASM/CensoredASM - Add ability to change HUD Caching FPS - Add "Natural Capes" feature - Add "Pumpkin Overlay Opacity" - Add "Cleaner Night Vision" and "Disable Night Vision" -- Add Invert Hotbar Scrolling -- Add Prevent Overflow Hotbar Scrolling +- Add "Invert Hotbar Scrolling" +- Add "Prevent Overflow Hotbar Scrolling" - Add "Disable Falling Blocks" +- Add "Exclude Cacti from 1.12 Boxes" +- Add "Improved Skin Rendering" +- Add "Add Background to Book GUI" - Replace "Remove Container Background" with "Container Background Opacity" - Replace "Nausea Effect" toggle to "Distortion Effects" slider - Split "Disable Grounded Arrows" into two settings ("Disable Unpickable Grounded Arrows" and "Disable All Grounded Arrows") - Add ability to change tile entity render distance - Add ability not to cull ender dragons and withers from Entity Culling - Fix very rare crash on Minecraft's main menu -- Re-add "Remove Water FOV" +- Re-add "Tooltip Cache" feature +- Re-add "Remove Water FOV" feature - Re-add "Remove Chat Message Limit" feature - Remove features replaced by various Polyfrost mods - Please install VanillaHUD for any title-related, actionbar-related, or tablist-related features @@ -285,3 +299,11 @@ This list may not always be up-to-date. To view an updated list, click [here](ht - **NoScroll**
+
+ License disclaimers + +This work, "PolyPatcher", uses code from CaffeineMC's "lithium-fabric", licensed under the LGPL-3.0 license. The original license is included in the repository. +https://github.com/CaffeineMC/lithium-fabric/tree/develop +https://github.com/CaffeineMC/lithium-fabric/blob/develop/LICENSE.txt + +
diff --git a/build.gradle.kts b/build.gradle.kts index 2faf83145..30244a63f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -93,6 +93,7 @@ val modShade: Configuration by configurations.creating { sourceSets { val dummy by creating main { + dummy.compileClasspath += compileClasspath compileClasspath += dummy.output output.setResourcesDir(java.classesDirectory) } @@ -121,7 +122,7 @@ dependencies { // If we are building for legacy forge, includes the launch wrapper with `shade` as we configured earlier. if (platform.isLegacyForge) { compileOnly("org.spongepowered:mixin:0.7.11-SNAPSHOT") - shade("cc.polyfrost:oneconfig-wrapper-launchwrapper:1.0.0-beta+") + shade("cc.polyfrost:oneconfig-wrapper-launchwrapper:1.0.0-beta17") } } diff --git a/gradle.properties b/gradle.properties index f83ed150c..5c1ad5b40 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ mod_id=patcher # betas will be "1.x.x+beta-y" / "1.x.x+branch_beta-y" # rcs will be 1.x.x+rc-y # extra branches will be 1.x.x+branch-y -mod_version=1.9.0 +mod_version=1.9.3-alpha.6 # Sets the name of the jar file that you put in your 'mods' folder. mod_archives_name=PolyPatcher diff --git a/settings.gradle.kts b/settings.gradle.kts index 9e4f59935..0a96c8ce6 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -7,7 +7,7 @@ pluginManagement { maven("https://repo.polyfrost.org/releases") // Adds the Polyfrost maven repository to get Polyfrost Gradle Toolkit } plugins { - val pgtVersion = "0.6.2" // Sets the default versions for Polyfrost Gradle Toolkit + val pgtVersion = "0.6.3" // Sets the default versions for Polyfrost Gradle Toolkit id("org.polyfrost.multi-version.root") version pgtVersion } } diff --git a/src/dummy/java/com/unascribed/ears/Ears.java b/src/dummy/java/com/unascribed/ears/Ears.java new file mode 100644 index 000000000..44cb09662 --- /dev/null +++ b/src/dummy/java/com/unascribed/ears/Ears.java @@ -0,0 +1,10 @@ +package com.unascribed.ears; + +import net.minecraft.client.renderer.ImageBufferDownload; + +import java.awt.image.BufferedImage; + +public class Ears { + public static void preprocessSkin(ImageBufferDownload subject, BufferedImage rawImg, BufferedImage img) { + } +} diff --git a/src/main/java/club/sk1er/patcher/Patcher.java b/src/main/java/club/sk1er/patcher/Patcher.java index b6747e0b0..8b5299479 100644 --- a/src/main/java/club/sk1er/patcher/Patcher.java +++ b/src/main/java/club/sk1er/patcher/Patcher.java @@ -25,7 +25,9 @@ import club.sk1er.patcher.util.chat.ChatHandler; import club.sk1er.patcher.util.enhancement.EnhancementManager; import club.sk1er.patcher.util.enhancement.ReloadListener; +import club.sk1er.patcher.util.forge.EntrypointCaching; import club.sk1er.patcher.util.fov.FovHandler; +import club.sk1er.patcher.util.item.TooltipHandler; import club.sk1er.patcher.util.keybind.FunctionKeyChanger; import club.sk1er.patcher.util.keybind.KeybindDropModifier; import club.sk1er.patcher.util.keybind.MousePerspectiveKeybindHandler; @@ -102,6 +104,8 @@ public class Patcher { @Mod.EventHandler public void onInit(FMLInitializationEvent event) { + EntrypointCaching.INSTANCE.onInit(); + registerKeybinds( dropModifier = new KeybindDropModifier(), hideScreen = new FunctionKeyChanger.KeybindHideScreen(), @@ -132,7 +136,7 @@ public void onInit(FMLInitializationEvent event) { new TitleFix(), new LinuxKeybindFix(), new MetricsRenderer(), new HUDCaching(), new EntityRendererHook(), MinecraftHook.INSTANCE, ScreenshotPreview.INSTANCE, - new MousePerspectiveKeybindHandler() + new MousePerspectiveKeybindHandler(), TooltipHandler.INSTANCE ); checkLogs(); @@ -347,11 +351,6 @@ private void detectIncompatibilities(List activeModList, Notificat notifications.send("Patcher", baseMessage + "Compact Chat is now disabled."); PatcherConfig.compactChat = false; } - - if (PatcherConfig.chatPosition) { - notifications.send("Patcher", baseMessage + "Chat Position is now disabled."); - PatcherConfig.chatPosition = false; - } } if (PatcherConfig.optimizedFontRenderer && modId.equals("smoothfont")) { diff --git a/src/main/java/club/sk1er/patcher/asm/external/forge/loader/JarDiscovererTransformer.java b/src/main/java/club/sk1er/patcher/asm/external/forge/loader/JarDiscovererTransformer.java index dc91ed146..1bb7bcdc6 100644 --- a/src/main/java/club/sk1er/patcher/asm/external/forge/loader/JarDiscovererTransformer.java +++ b/src/main/java/club/sk1er/patcher/asm/external/forge/loader/JarDiscovererTransformer.java @@ -26,17 +26,54 @@ public String[] getClassName() { @Override public void transform(ClassNode classNode, String name) { for (MethodNode method : classNode.methods) { - if (method.name.equals("discover")) { + boolean isDiscover = method.name.equals("discover"); + boolean isFindClassesASM = + //#if MC>10809 + //$$ method.name.equals("findClassesASM"); + //#else + false; + //#endif + + //noinspection ConstantValue + if (isDiscover || isFindClassesASM) { final ListIterator iterator = method.instructions.iterator(); + while (iterator.hasNext()) { final AbstractInsnNode next = iterator.next(); if (next instanceof MethodInsnNode) { final MethodInsnNode insn = ((MethodInsnNode) next); - if (insn.name.equals("entries")) { - method.instructions.insertBefore(next, discoverCachedJar()); - } else if (insn.name.equals("bindMetadata")) { - method.instructions.insert(insn, putCachedJar()); + switch (insn.name) { + case + //#if MC<=10809 + "entries": + //#else + //$$ "findClassesASM": + //#endif + + //#if MC>10809 + //$$ if (isFindClassesASM) break; + //#endif + method.instructions.insertBefore(next, discoverCachedJar()); + break; + case "addClassEntry": + //#if MC>10809 + //$$ if (!isFindClassesASM) break; + //#endif + method.instructions.insert(next, putCachedClass(false)); + break; + case + //#if MC<=10809 + "bindMetadata": + //#else + //$$ "setClassVersion": + //#endif + + //#if MC>10809 + //$$ if (!isFindClassesASM) break; + //#endif + method.instructions.insert(next, putCachedClass(true)); + break; } } } @@ -60,7 +97,13 @@ private InsnList discoverCachedJar() { list.add(new VarInsnNode(Opcodes.ALOAD, 1)); list.add(new VarInsnNode(Opcodes.ALOAD, 2)); list.add(new VarInsnNode(Opcodes.ALOAD, 4)); - list.add(new VarInsnNode(Opcodes.ALOAD, 6)); + list.add(new VarInsnNode(Opcodes.ALOAD, + //#if MC<=10809 + 6 + //#else + //$$ 7 + //#endif + )); list.add(new MethodInsnNode( Opcodes.INVOKEVIRTUAL, "club/sk1er/patcher/util/forge/EntrypointCaching", @@ -78,16 +121,22 @@ private InsnList discoverCachedJar() { return list; } - private InsnList putCachedJar() { + private InsnList putCachedClass(boolean entry) { InsnList list = new InsnList(); getInstance(list); list.add(new VarInsnNode(Opcodes.ALOAD, 1)); - list.add(new VarInsnNode(Opcodes.ALOAD, 8)); + list.add(new VarInsnNode(Opcodes.ALOAD, + //#if MC<=10809 + 8 + //#else + //$$ 7 + //#endif + )); list.add(new MethodInsnNode( Opcodes.INVOKEVIRTUAL, "club/sk1er/patcher/util/forge/EntrypointCaching", - "putCachedEntrypoints", + entry ? "putCachedEntrypoints" : "putCachedClassEntries", "(Lnet/minecraftforge/fml/common/discovery/ModCandidate;Ljava/util/zip/ZipEntry;)V", false )); diff --git a/src/main/java/club/sk1er/patcher/config/OldPatcherConfig.java b/src/main/java/club/sk1er/patcher/config/OldPatcherConfig.java index 0eb084e3f..61fe93488 100644 --- a/src/main/java/club/sk1er/patcher/config/OldPatcherConfig.java +++ b/src/main/java/club/sk1er/patcher/config/OldPatcherConfig.java @@ -29,4 +29,9 @@ public class OldPatcherConfig { public static boolean tabHeightAllow = true; // VanillaHUD public static int tabHeight = 10; // VanillaHUD public static boolean fixActionbarOverlap; // VanillaHUD + public static boolean transparentChat; // Chatting + public static boolean transparentChatOnlyWhenClosed; // Chatting + public static boolean transparentChatInputField; // Chatting + public static boolean extendChatBackground = true; // Chatting + public static boolean chatPosition = true; // Chatting } diff --git a/src/main/java/club/sk1er/patcher/config/PatcherConfig.java b/src/main/java/club/sk1er/patcher/config/PatcherConfig.java index a5dd36138..2ddc55242 100644 --- a/src/main/java/club/sk1er/patcher/config/PatcherConfig.java +++ b/src/main/java/club/sk1er/patcher/config/PatcherConfig.java @@ -11,6 +11,7 @@ import cc.polyfrost.oneconfig.config.migration.VigilanceName; import club.sk1er.patcher.Patcher; import club.sk1er.patcher.tweaker.ClassTransformer; +import club.sk1er.patcher.util.forge.EntrypointCaching; import net.minecraft.client.Minecraft; import net.minecraftforge.common.ForgeVersion; import org.apache.commons.io.FileUtils; @@ -34,17 +35,10 @@ public class PatcherConfig extends Config { ) public static boolean keepShadersOnPerspectiveChange = true; - @Info( - text = "Parallax Fix currently makes the F3 crosshair disappear.", - category = "Bug Fixes", subcategory = "General", - type = InfoType.ERROR - ) - private static String parallaxFixInfo = ""; - @Switch( name = "Parallax Fix", description = "Resolve the camera being too far back, seemingly making your eyes be in the back of your head.", - category = "Bug Fixes", subcategory = "General" + category = "Bug Fixes", subcategory = "General", size = 2 ) public static boolean parallaxFix; @@ -98,6 +92,13 @@ public class PatcherConfig extends Config { ) public static boolean fixedAlexArms = true; + @Switch( + name = "Add Background to Book GUI", + description = "Adds the dark background to the book GUI like all other containers/menus.", + category = "Bug Fixes", subcategory = "Rendering" + ) + public static boolean bookBackground = false; + @Dropdown( name = "Keyboard Layout", description = "The layout of your keyboard, used to fix input bugs accordingly.", @@ -106,6 +107,13 @@ public class PatcherConfig extends Config { ) public static int keyboardLayout = 0; + @Switch( + name = "Vanilla Held Item Lighting", + description = "Amends a Forge bug causing item sides to have incorrect lighting compared to Vanilla 1.8.", + category = "Bug Fixes", subcategory = "Forge" + ) + public static boolean heldItemLighting = true; + @Switch( name = "Vanilla Glass Panes", description = "Reverts a Forge change causing Glass Panes and Iron Bars to connect where they shouldn't.", @@ -356,6 +364,7 @@ public class PatcherConfig extends Config { @Slider( name = "Water Fog Density (%)", + description = "Changes the fog density in water to improve visibility.", category = "Miscellaneous", subcategory = "Fog", min = 0, max = 100 ) @@ -526,6 +535,13 @@ public class PatcherConfig extends Config { ) public static boolean futureHitBoxes = true; + @Switch( + name = "Exclude Cacti from 1.12 Boxes", + description = "Exclude cacti from the 1.12 selection box changes, as it would actually shrink rather than increase in size.", + category = "Miscellaneous", subcategory = "Blocks" + ) + public static boolean cactusHitboxExclusion = true; + @Switch( name = "Alternate Text Shadow", description = "Change the text-shadow to only move down rather than move to the side.", @@ -853,6 +869,21 @@ private void modifyEverySound() { ) public static boolean disableEnchantmentGlint; + @Info( + text = "May cause tooltips to appear on another item for 200ms.", + category = "Performance", subcategory = "Items", + type = InfoType.WARNING, + size = 2 + ) + private static boolean tooltipCacheInfo = true; + + @Switch( + name = "Tooltip Cache", + description = "Cache tooltips to avoid fetching very long lists every frame.", + category = "Performance", subcategory = "Items" + ) + public static boolean tooltipCache; + @Info( text = "When back-face culling is enabled, being inside an entity will cause that body part to be invisible.", category = "Performance", subcategory = "Culling", @@ -962,7 +993,7 @@ public static int getInventoryScale() { @Slider( name = "Container Background Opacity (%)", - description = "Change the opacity of the dark background inside a container, or remove it completely.", + description = "Change the opacity of the dark background inside a container, or remove it completely. By default, this is 81.5%.", category = "Screens", subcategory = "General", min = 0F, max = 100F ) @@ -1006,49 +1037,6 @@ public static int getInventoryScale() { ) public static boolean removeChatMessageLimit = true; - @Info( - text = "Transparent Chat can positively impact performance.", - category = "Screens", subcategory = "Chat", - type = InfoType.INFO - ) - private static boolean transparentChatInfo = true; - - @Switch( - name = "Transparent Chat", - description = "Remove the background from chat.", - category = "Screens", subcategory = "Chat" - ) - public static boolean transparentChat; - - @Switch( - name = "Chat Background When Open", - description = "Add back the background when chat is open.", - category = "Screens", subcategory = "Chat" - ) - public static boolean transparentChatOnlyWhenClosed; - - @Info( - text = "Transparent Chat Input Field can positively impact performance.", - category = "Screens", subcategory = "Chat", - type = InfoType.INFO, - size = 2 - ) - private static boolean transparentChatInputFieldInfo = true; - - @Switch( - name = "Transparent Chat Input Field", - description = "Remove the background from chat's input field.", - category = "Screens", subcategory = "Chat" - ) - public static boolean transparentChatInputField; - - @Switch( - name = "Extend Chat Background", - description = "Extend the chat background all the way to the left of the screen.", - category = "Screens", subcategory = "Chat" - ) - public static boolean extendChatBackground = true; - @Switch( name = "Compact Chat", description = "Clean up the chat by stacking duplicate messages.", @@ -1135,13 +1123,6 @@ public static int getInventoryScale() { ) public static boolean projectileProtectionPercentage; - @Switch( - name = "Chat Position", - description = "Move the chat up 12 pixels to stop it from overlapping the health bar, as done in 1.12+.", - category = "Screens", subcategory = "Chat" - ) - public static boolean chatPosition = true; - @Switch( name = "Chat Timestamps", description = "Add timestamps before a message.", @@ -1337,13 +1318,37 @@ public static int getInventoryScale() { // EXPERIMENTAL - /*Switchty( + @Switch( name = "Cache Entrypoints", description = "Cache Forge mod entry points, improving startup time as Forge no longer needs to walk through " + "every class to find the @Mod annotation.", category = "Experimental", subcategory = "Mod Discovery" ) - public static boolean cacheEntrypoints = true;*/ + public static boolean cacheEntrypoints = true; + + @Button( + name = "Reset Cache", + description = "Reset the cache of Forge mod entry points.", + category = "Experimental", subcategory = "Mod Discovery", + text = "Reset" + ) + public static void resetCache() { + EntrypointCaching.INSTANCE.resetCache(); + } + + @Info( + text = "Improved Skin Rendering can make some skins invisible. It requires a restart once toggled.", + category = "Experimental", subcategory = "Skin Rendering", + type = InfoType.WARNING, size = 2 + ) + private static boolean improvedSkinRenderingInfo; + + @Switch( + name = "Improved Skin Rendering", + description = "Remove transparent pixels on skins instead of turning them black.", + category = "Experimental", subcategory = "Skin Rendering" + ) + public static boolean improvedSkinRendering = false; @Info( text = "This may cause stuff with animations to feel \"choppy\".", @@ -1554,7 +1559,7 @@ public static int getInventoryScale() { category = "Screens", subcategory = "Tab" ) // HIDDEN OPTION!!!!!!! DO NOT REMOVE OR TOUCH - public static boolean tabHeightAllowOld = true; + public static boolean tabHeightAllowOld; @Slider( name = "Set Tab Height", @@ -1573,33 +1578,218 @@ public static int getInventoryScale() { // HIDDEN OPTION!!!!!!! DO NOT REMOVE OR TOUCH public static boolean fixActionbarOverlapOld; + @Switch( + name = "Transparent Chat", + description = "Remove the background from chat.", + category = "Screens", subcategory = "Chat" + ) + // HIDDEN OPTION!!!!!!! DO NOT REMOVE OR TOUCH + public static boolean transparentChatOld; + + @Switch( + name = "Chat Background When Open", + description = "Add back the background when chat is open.", + category = "Screens", subcategory = "Chat" + ) + // HIDDEN OPTION!!!!!!! DO NOT REMOVE OR TOUCH + public static boolean transparentChatOnlyWhenClosedOld; + + @Switch( + name = "Transparent Chat Input Field", + description = "Remove the background from chat's input field.", + category = "Screens", subcategory = "Chat" + ) + // HIDDEN OPTION!!!!!!! DO NOT REMOVE OR TOUCH + public static boolean transparentChatInputFieldOld; + + @Switch( + name = "Extend Chat Background", + description = "Extend the chat background all the way to the left of the screen.", + category = "Screens", subcategory = "Chat" + ) + // HIDDEN OPTION!!!!!!! DO NOT REMOVE OR TOUCH + public static boolean extendChatBackgroundOld; + + @Switch( + name = "Chat Position", + description = "Move the chat up 12 pixels to stop it from overlapping the health bar, as done in 1.12+.", + category = "Screens", subcategory = "Chat" + ) + // HIDDEN OPTION!!!!!!! DO NOT REMOVE OR TOUCH + public static boolean chatPositionOld; + @Exclude public static boolean nauseaEffect = false; @Exclude public static float fireOverlayOpacity = 1F; - @Exclude public static boolean disableTitles = false; - @Exclude public static float titleScale = 1.0F; - @Exclude public static float titleOpacity = 1.0F; - @Exclude public static boolean toggleTab = false; - @Exclude public static boolean crosshairPerspective = false; - @Exclude public static boolean showOwnNametag = false; + @Switch( + name = "Disable Titles", + description = "Stop titles from appearing.", + category = "Deprecated", subcategory = "Titles" + ) + public static boolean disableTitles = false; + @Slider( + name = "Title Scale", + description = "Set the scale for titles.", + category = "Deprecated", subcategory = "Titles", + min = 0F, max = 1F + ) + public static float titleScale = 1.0F; + @Slider( + name = "Title Opacity", + description = "Change the opacity of titles.", + category = "Deprecated", subcategory = "Titles", + min = 0F, max = 1.0F + ) + public static float titleOpacity = 1.0F; + @Switch( + name = "Toggle Tab", + description = "Hold tab open without needing to hold down the tab key.", + category = "Deprecated", subcategory = "Tab" + ) + public static boolean toggleTab = false; + @Switch( + name = "Crosshair Perspective", + description = "Remove the crosshair when in third person.", + category = "Deprecated", subcategory = "Crosshair" + ) + public static boolean crosshairPerspective = false; + @Switch( + name = "Remove Inverted Colors from Crosshair", + description = "Remove the inverted color effect on the crosshair.", + category = "Deprecated", subcategory = "Crosshair" + ) + public static boolean removeInvertFromCrosshair = false; + @Switch( + name = "Show Own Nametag", + description = "See your nametag in third person.", + category = "Deprecated", subcategory = "Nametags" + ) + public static boolean showOwnNametag = false; + @Switch( + name = "Add Text Shadow to Nametags", + description = "Render nametags with shadowed text.", + category = "Deprecated", subcategory = "Nametags" + ) + public static boolean shadowedNametagText = false; @Exclude public static float riddenHorseOpacity = 1F; - @Exclude public static boolean numberPing = false; - @Exclude public static boolean cleanView = false; - @Exclude public static boolean disableBlockBreakParticles = false; - @Exclude public static boolean removeInvertFromCrosshair = false; - @Exclude public static boolean shadowedNametagText = false; - @Exclude public static boolean shadowedActionbarText = false; - @Exclude public static boolean actionbarBackground = false; - @Exclude public static boolean removeVerticalViewBobbing = false; - @Exclude public static boolean staticParticleColor = false; - @Exclude public static int maxParticleLimit = 4000; - @Exclude public static boolean disableNametagBoxes = false; + @Switch( + name = "Clean View", + description = "Stop rendering your potion effect particles.", + category = "Deprecated", subcategory = "Particles" + ) + public static boolean cleanView = false; + @Switch( + name = "Disable Breaking Particles", + description = "Remove block-breaking particles for visibility.", + category = "Deprecated", subcategory = "Particles" + ) + public static boolean disableBlockBreakParticles = false; + @Switch( + name = "Add Text Shadow to Actionbar", + description = "Render actionbar messages with shadowed text.", + category = "Deprecated", subcategory = "Actionbar" + ) + public static boolean shadowedActionbarText = false; + @Switch( + name = "Add Background to Actionbar", + description = "Render a background behind the actionbar.", + category = "Deprecated", subcategory = "Actionbar" + ) + public static boolean actionbarBackground = false; + @Switch( + name = "Remove Vertical Bobbing", + description = "While using View Bobbing, remove the vertical bobbing like in 1.14+.", + category = "Deprecated", subcategory = "Animations" + ) + public static boolean removeVerticalViewBobbing = false; + @Switch( + name = "Static Particle Color", + description = "Disable particle lighting checks each frame.", + category = "Deprecated", subcategory = "Particles" + ) + public static boolean staticParticleColor = false; + @Slider( + name = "Max Particle Limit", + description = "Stop additional particles from appearing when there are too many at once.", + category = "Deprecated", subcategory = "Particles", + min = 1, max = 10000 + ) + public static int maxParticleLimit = 4000; + @Switch( + name = "Disable Nametag Boxes", + description = "Remove the transparent box around the nametag.", + category = "Deprecated", subcategory = "Nametags" + ) + public static boolean disableNametagBoxes = false; @Exclude public static boolean removeContainerBackground = false; - @Exclude public static boolean guiCrosshair = false; - @Exclude public static float tabOpacity = 1.0F; - @Exclude public static int tabPlayerCount = 80; - @Exclude public static boolean tabHeightAllow = false; - @Exclude public static int tabHeight = 0; - @Exclude public static boolean fixActionbarOverlap = false; + @Switch( + name = "GUI Crosshair", + description = "Stop rendering the crosshair when in a GUI.", + category = "Deprecated", subcategory = "Crosshair" + ) + public static boolean guiCrosshair = false; + @Slider( + name = "Tab Opacity", + description = "Change the tab list opacity.", + category = "Deprecated", subcategory = "Tab", + min = 0F, max = 1.0F + ) + public static float tabOpacity = 1.0F; + @Slider( + name = "Tab Player Count", + description = "Change how many players can display on tab.", + category = "Deprecated", subcategory = "Tab", + min = 10, max = 120 + ) + public static int tabPlayerCount = 80; + @Switch( + name = "Tab Height", + description = "Move the tab overlay down the selected amount of pixels when there's an active bossbar.", + category = "Deprecated", subcategory = "Tab" + ) + public static boolean tabHeightAllow = false; + @Slider( + name = "Set Tab Height", + description = "Choose how many pixels tab will move down when there's an active bossbar.", + category = "Deprecated", subcategory = "Tab", + min = 0, max = 24 + ) + public static int tabHeight = 0; + @Switch( + name = "Fix Actionbar Overlap", + description = "Prevents the actionbar text from rendering above the armor/health bar.", + category = "Deprecated", subcategory = "Actionbar" + ) + public static boolean fixActionbarOverlap = false; + @Switch( + name = "Transparent Chat", + description = "Remove the background from chat.", + category = "Deprecated", subcategory = "Chat" + ) + public static boolean transparentChat; + @Switch( + name = "Chat Background When Open", + description = "Add back the background when chat is open.", + category = "Deprecated", subcategory = "Chat" + ) + public static boolean transparentChatOnlyWhenClosed; + @Switch( + name = "Transparent Chat Input Field", + description = "Remove the background from chat's input field.", + category = "Deprecated", subcategory = "Chat" + ) + public static boolean transparentChatInputField; + @Switch( + name = "Extend Chat Background", + description = "Extend the chat background all the way to the left of the screen.", + category = "Deprecated", subcategory = "Chat" + ) + public static boolean extendChatBackground = false; + @Switch( + name = "Chat Position", + description = "Move the chat up 12 pixels to stop it from overlapping the health bar, as done in 1.12+.", + category = "Deprecated", subcategory = "Chat" + ) + public static boolean chatPosition = false; public static boolean labyModMoment = true; @@ -1642,6 +1832,9 @@ public PatcherConfig() { addListener("removeGroundFoliage", reloadWorld); addListener("vanillaGlassPanes", reloadWorld); + Runnable reloadTextures = () -> Minecraft.getMinecraft().refreshResources(); + addListener("heldItemLighting", reloadTextures); + hideIf("nauseaEffectOld", () -> true); hideIf("fireOverlayOpacityOld", () -> true); hideIf("disableTitlesOld", () -> true); @@ -1669,6 +1862,11 @@ public PatcherConfig() { hideIf("tabHeightAllowOld", () -> true); hideIf("tabHeightOld", () -> true); hideIf("fixActionbarOverlapOld", () -> true); + hideIf("transparentChatOld", () -> true); + hideIf("transparentChatOnlyWhenClosedOld", () -> true); + hideIf("transparentChatInputFieldOld", () -> true); + hideIf("extendChatBackgroundOld", () -> true); + hideIf("chatPositionOld", () -> true); OldPatcherConfig.nauseaEffect = nauseaEffectOld; OldPatcherConfig.fireOverlayOpacity = fireOverlayOpacityOld; @@ -1697,8 +1895,43 @@ public PatcherConfig() { OldPatcherConfig.tabHeightAllow = tabHeightAllowOld; OldPatcherConfig.tabHeight = tabHeightOld; OldPatcherConfig.fixActionbarOverlap = fixActionbarOverlapOld; + OldPatcherConfig.transparentChat = transparentChatOld; + OldPatcherConfig.transparentChatOnlyWhenClosed = transparentChatOnlyWhenClosedOld; + OldPatcherConfig.transparentChatInputField = transparentChatInputFieldOld; + OldPatcherConfig.extendChatBackground = extendChatBackgroundOld; + OldPatcherConfig.chatPosition = chatPositionOld; + + addDependency("disableTitles", "Replaced by VanillaHUD. Please install VanillaHUD to use this feature.", () -> false); + addDependency("titleScale", "Replaced by VanillaHUD. Please install VanillaHUD to use this feature.", () -> false); + addDependency("titleOpacity", "Replaced by VanillaHUD. Please install VanillaHUD to use this feature.", () -> false); + addDependency("toggleTab", "Replaced by VanillaHUD. Please install VanillaHUD to use this feature.", () -> false); + addDependency("crosshairPerspective", "Replaced by PolyCrosshair. Please install PolyCrosshair to use this feature.", () -> false); + addDependency("showOwnNametag", "Replaced by PolyNametag. Please install PolyNametag to use this feature.", () -> false); + addDependency("numberPing", "Replaced by VanillaHUD. Please install VanillaHUD to use this feature.", () -> false); + addDependency("cleanView", "Replaced by OverflowParticles. Please install OverflowParticles to use this feature.", () -> false); + addDependency("disableBlockBreakParticles", "Replaced by OverflowParticles. Please install OverflowParticles to use this feature.", () -> false); + addDependency("removeInvertFromCrosshair", "Replaced by PolyCrosshair. Please install PolyCrosshair to use this feature.", () -> false); + addDependency("shadowedNametagText", "Replaced by PolyNametag. Please install PolyNametag to use this feature.", () -> false); + addDependency("shadowedActionbarText", "Replaced by VanillaHUD. Please install VanillaHUD to use this feature.", () -> false); + addDependency("actionbarBackground", "Replaced by VanillaHUD. Please install VanillaHUD to use this feature.", () -> false); + addDependency("removeVerticalViewBobbing", "Replaced by OverflowAnimations. Please install OverflowAnimations to use this feature.", () -> false); + addDependency("staticParticleColor", "Replaced by OverflowParticles. Please install OverflowParticles to use this feature.", () -> false); + addDependency("maxParticleLimit", "Replaced by OverflowParticles. Please install OverflowParticles to use this feature.", () -> false); + addDependency("disableNametagBoxes", "Replaced by PolyNametag. Please install PolyNametag to use this feature.", () -> false); + addDependency("guiCrosshair", "Replaced by PolyCrosshair. Please install PolyCrosshair to use this feature.", () -> false); + addDependency("tabOpacity", "Replaced by VanillaHUD. Please install VanillaHUD to use this feature.", () -> false); + addDependency("tabPlayerCount", "Replaced by VanillaHUD. Please install VanillaHUD to use this feature.", () -> false); + addDependency("tabHeightAllow", "Replaced by VanillaHUD. Please install VanillaHUD to use this feature.", () -> false); + addDependency("tabHeight", "Replaced by VanillaHUD. Please install VanillaHUD to use this feature.", () -> false); + addDependency("fixActionbarOverlap", "Replaced by VanillaHUD. Please install VanillaHUD to use this feature.", () -> false); + addDependency("transparentChat", "Replaced by Chatting. Please install Chatting to use this feature.", () -> false); + addDependency("transparentChatOnlyWhenClosed", "Replaced by Chatting. Please install Chatting to use this feature.", () -> false); + addDependency("transparentChatInputField", "Replaced by Chatting. Please install Chatting to use this feature.", () -> false); + addDependency("extendChatBackground", "Replaced by Chatting. Please install Chatting to use this feature.", () -> false); + addDependency("chatPosition", "Replaced by Chatting. Please install Chatting to use this feature.", () -> false); try { + addDependency("cactusHitboxExclusion", "futureHitBoxes"); addDependency("smartFullbright", "fullbright"); addDependency("cleanerNightVision", "disableNightVision", () -> !disableNightVision); addDependency("unfocusedFPSAmount", "unfocusedFPS"); @@ -1709,7 +1942,6 @@ public PatcherConfig() { addDependency("timestampsStyle", "timestamps"); addDependency("secondsOnTimestamps", "timestamps"); addDependency("imagePreviewWidth", "imagePreview"); - addDependency("transparentChatOnlyWhenClosed", "transparentChat"); Arrays.asList( "slownessFovModifierFloat", "speedFovModifierFloat", @@ -1760,9 +1992,9 @@ public PatcherConfig() { //noinspection ConstantConditions Supplier minecraft112 = () -> ForgeVersion.mcVersion.equals("1.12.2"); Arrays.asList( - "resourceExploitFix", "newKeybindHandling", "separateResourceLoading", "futureHitBoxes", "farmSelectionBoxesInfo", + "resourceExploitFix", "newKeybindHandling", "separateResourceLoading", "futureHitBoxes", "cactusHitboxExclusion", "farmSelectionBoxesInfo", "leftHandInFirstPerson", "extendedChatLength", "chatPosition", - "parallaxFix", "extendChatBackground", "vanillaGlassPanes" + "parallaxFix", "extendChatBackground", "vanillaGlassPanes", "heldItemLighting" ).forEach(property -> hideIf(property, minecraft112)); hideIf("keyboardLayout", () -> !SystemUtils.IS_OS_LINUX); diff --git a/src/main/java/club/sk1er/patcher/config/PatcherSoundConfig.java b/src/main/java/club/sk1er/patcher/config/PatcherSoundConfig.java index d50cddf5b..342c6db96 100644 --- a/src/main/java/club/sk1er/patcher/config/PatcherSoundConfig.java +++ b/src/main/java/club/sk1er/patcher/config/PatcherSoundConfig.java @@ -47,8 +47,7 @@ public void initialize(Map data, Map entry : soundRegistry.entrySet()) { diff --git a/src/main/java/club/sk1er/patcher/hooks/DebugCrosshairHook.java b/src/main/java/club/sk1er/patcher/hooks/DebugCrosshairHook.java new file mode 100644 index 000000000..9360c19e5 --- /dev/null +++ b/src/main/java/club/sk1er/patcher/hooks/DebugCrosshairHook.java @@ -0,0 +1,49 @@ +package club.sk1er.patcher.hooks; + +import cc.polyfrost.oneconfig.libs.universal.UResolution; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.entity.Entity; +import org.lwjgl.opengl.GL11; + +import java.awt.*; + +public class DebugCrosshairHook { + + public static void renderDirections(float partialTicks, Minecraft mc) { + GlStateManager.pushMatrix(); + GlStateManager.translate((float)(UResolution.getScaledWidth() / 2), (float)(UResolution.getScaledHeight() / 2), 0); + Entity entity = mc.getRenderViewEntity(); + GlStateManager.rotate(entity.prevRotationPitch + (entity.rotationPitch - entity.prevRotationPitch) * partialTicks, -1.0F, 0.0F, 0.0F); + GlStateManager.rotate(entity.prevRotationYaw + (entity.rotationYaw - entity.prevRotationYaw) * partialTicks, 0.0F, 1.0F, 0.0F); + GlStateManager.scale(-1.0F, -1.0F, -1.0F); + double mcScale = UResolution.getScaleFactor(); + GlStateManager.scale(1 / mcScale, 1 / mcScale, 1 / mcScale); + GlStateManager.disableTexture2D(); + GlStateManager.depthMask(false); + + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer worldRenderer = tessellator.getWorldRenderer(); + + GL11.glLineWidth(2.0F); + worldRenderer.begin(1, DefaultVertexFormats.POSITION_COLOR); + drawLine(worldRenderer, 38, new Color(255, 0, 0), 1, 0, 0); + drawLine(worldRenderer, 38, new Color(0, 0, 255), 0, 0, 1); + drawLine(worldRenderer, 27, new Color(0, 255, 0), 0, 1, 0); + tessellator.draw(); + + GL11.glLineWidth(1.0F); + GlStateManager.depthMask(true); + GlStateManager.enableTexture2D(); + GlStateManager.popMatrix(); + } + + private static void drawLine(WorldRenderer worldRenderer, double length, Color color, int... pos) { + worldRenderer.pos(0.0, 0.0, 0.0).color(color.getRed(), color.getGreen(), color.getBlue(), 255).endVertex(); + worldRenderer.pos(length * pos[0], length * pos[1], length * pos[2]).color(color.getRed(), color.getGreen(), color.getBlue(), 255).endVertex(); + } + +} diff --git a/src/main/java/club/sk1er/patcher/hooks/EarsModHook.java b/src/main/java/club/sk1er/patcher/hooks/EarsModHook.java new file mode 100644 index 000000000..9c9bf8d5c --- /dev/null +++ b/src/main/java/club/sk1er/patcher/hooks/EarsModHook.java @@ -0,0 +1,28 @@ +package club.sk1er.patcher.hooks; + +import com.unascribed.ears.Ears; +import net.minecraft.client.renderer.ImageBufferDownload; + +import java.awt.image.BufferedImage; + +public class EarsModHook { + private static boolean isEarsModPresent; + private static boolean isEarsModPresentChecked; + public static void preprocessSkin(ImageBufferDownload imageBufferDownload, BufferedImage image, BufferedImage bufferedImage) { + if (!isEarsModPresentChecked) { + isEarsModPresentChecked = true; + try { + Class clazz = Class.forName("com.unascribed.ears.Ears"); + clazz.getMethod("preprocessSkin", ImageBufferDownload.class, BufferedImage.class, BufferedImage.class); + isEarsModPresent = true; + } catch (ClassNotFoundException e) { + isEarsModPresent = false; + } catch (NoSuchMethodException e) { + e.printStackTrace(); + isEarsModPresent = false; + } + } + if (!isEarsModPresent) return; + Ears.preprocessSkin(imageBufferDownload, image, bufferedImage); + } +} diff --git a/src/main/java/club/sk1er/patcher/hooks/GuiNewChatHook.java b/src/main/java/club/sk1er/patcher/hooks/GuiNewChatHook.java index eaf2efd40..655c28441 100644 --- a/src/main/java/club/sk1er/patcher/hooks/GuiNewChatHook.java +++ b/src/main/java/club/sk1er/patcher/hooks/GuiNewChatHook.java @@ -53,7 +53,7 @@ public static void drawMessageQueue() { if (!messageQueue.isEmpty()) { GlStateManager.pushMatrix(); GlStateManager.translate(0, 0, 50); - if (!PatcherConfig.transparentChat) Gui.drawRect(0, 0, chatWidth + 4, 9, 2130706432); + Gui.drawRect(0, 0, chatWidth + 4, 9, 2130706432); GlStateManager.enableBlend(); GlStateManager.translate(0, 0, 50); mc.fontRendererObj.drawStringWithShadow(ChatColor.GRAY + "[+" + messageQueue.size() + " pending lines]", 0, 1, -1); diff --git a/src/main/java/club/sk1er/patcher/hooks/ResourceReloadHooks.java b/src/main/java/club/sk1er/patcher/hooks/ResourceReloadHooks.java new file mode 100644 index 000000000..f2dfa9065 --- /dev/null +++ b/src/main/java/club/sk1er/patcher/hooks/ResourceReloadHooks.java @@ -0,0 +1,71 @@ +package club.sk1er.patcher.hooks; + +import club.sk1er.patcher.Patcher; +import com.google.common.collect.Lists; +import net.minecraft.client.resources.IResourceManagerReloadListener; + +import java.lang.reflect.Method; +import java.util.List; + +public class ResourceReloadHooks { + private static boolean loadLanguage = false; + private static boolean loadMipmaps = false; + private static List languageManager = null; + private static List modelManager = null; + private static Method langMethod; + + public static boolean shouldLoadLanguage() { + return loadLanguage; + } + + public static boolean shouldLoadMipmaps() { + return loadMipmaps; + } + + public static List getLanguageManager() { + return languageManager; + } + + public static List getModelManager() { + return modelManager; + } + + public static void setLanguageManager(IResourceManagerReloadListener languageManager) { + ResourceReloadHooks.languageManager = Lists.newArrayList(languageManager); + } + + public static void setModelManager(IResourceManagerReloadListener modelManager) { + ResourceReloadHooks.modelManager = Lists.newArrayList(modelManager); + } + + public static void setLoadLanguage(boolean loadLanguage) { + ResourceReloadHooks.loadLanguage = loadLanguage; + } + + public static void setLoadMipmaps(boolean loadMipmaps) { + ResourceReloadHooks.loadMipmaps = loadMipmaps; + } + + public static void reloadOptiFineLanguage() { + if (langMethod == null) { + try { + Class clazz = Class.forName("net.optifine.Lang"); + langMethod = clazz.getDeclaredMethod("resourcesReloaded"); + } catch (ClassNotFoundException ignored) { + return; + } catch (Exception e) { + if (Patcher.instance != null) { + Patcher.instance.getLogger().error("Failed to reload OptiFine language. If this is causing issues, please report this to https://polyfrost.org/discord", e); + } + return; + } + } + try { + langMethod.invoke(null); + } catch (Exception e) { + if (Patcher.instance != null) { + Patcher.instance.getLogger().error("Failed to reload OptiFine language. If this is causing issues, please report this to https://polyfrost.org/discord", e); + } + } + } +} diff --git a/src/main/java/club/sk1er/patcher/mixins/accessors/RegistrySimpleAccessor.java b/src/main/java/club/sk1er/patcher/mixins/accessors/RegistrySimpleAccessor.java new file mode 100644 index 000000000..b96d85083 --- /dev/null +++ b/src/main/java/club/sk1er/patcher/mixins/accessors/RegistrySimpleAccessor.java @@ -0,0 +1,13 @@ +package club.sk1er.patcher.mixins.accessors; + +import net.minecraft.util.RegistrySimple; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.Map; + +@Mixin(RegistrySimple.class) +public interface RegistrySimpleAccessor { + @Accessor("registryObjects") + Map getRegistryObjects(); +} diff --git a/src/main/java/club/sk1er/patcher/mixins/bugfixes/GameSettingsMixin_MipmapSlider.java b/src/main/java/club/sk1er/patcher/mixins/bugfixes/GameSettingsMixin_MipmapSlider.java index 075a7a108..315c11cfc 100644 --- a/src/main/java/club/sk1er/patcher/mixins/bugfixes/GameSettingsMixin_MipmapSlider.java +++ b/src/main/java/club/sk1er/patcher/mixins/bugfixes/GameSettingsMixin_MipmapSlider.java @@ -1,6 +1,7 @@ package club.sk1er.patcher.mixins.bugfixes; import club.sk1er.patcher.ducks.GameSettingsExt; +import club.sk1er.patcher.hooks.ResourceReloadHooks; import com.google.common.util.concurrent.ListenableFuture; import net.minecraft.client.Minecraft; import net.minecraft.client.settings.GameSettings; @@ -18,7 +19,9 @@ public class GameSettingsMixin_MipmapSlider implements GameSettingsExt { @Override public void patcher$onSettingsGuiClosed() { if (patcher$needsResourceRefresh) { + ResourceReloadHooks.setLoadMipmaps(true); mc.scheduleResourcesRefresh(); + ResourceReloadHooks.setLoadMipmaps(false); patcher$needsResourceRefresh = false; } } diff --git a/src/main/java/club/sk1er/patcher/mixins/bugfixes/GuiIngameMixin_RemoveSpectatorPumpkinOverlay.java b/src/main/java/club/sk1er/patcher/mixins/bugfixes/GuiIngameMixin_RemoveSpectatorPumpkinOverlay.java new file mode 100644 index 000000000..1d7217c58 --- /dev/null +++ b/src/main/java/club/sk1er/patcher/mixins/bugfixes/GuiIngameMixin_RemoveSpectatorPumpkinOverlay.java @@ -0,0 +1,17 @@ +package club.sk1er.patcher.mixins.bugfixes; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiIngame; +import net.minecraft.client.gui.ScaledResolution; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(GuiIngame.class) +public class GuiIngameMixin_RemoveSpectatorPumpkinOverlay { + @Inject(method = "renderPumpkinOverlay", at = @At("HEAD"), cancellable = true) + private void patcher$removeSpectatorPumpkinOverlay(ScaledResolution scaledRes, CallbackInfo ci) { + if (Minecraft.getMinecraft().thePlayer.isSpectator()) ci.cancel(); + } +} diff --git a/src/main/java/club/sk1er/patcher/mixins/bugfixes/GuiScreenBookMixin_AddBackground.java b/src/main/java/club/sk1er/patcher/mixins/bugfixes/GuiScreenBookMixin_AddBackground.java new file mode 100644 index 000000000..0105066d3 --- /dev/null +++ b/src/main/java/club/sk1er/patcher/mixins/bugfixes/GuiScreenBookMixin_AddBackground.java @@ -0,0 +1,17 @@ +package club.sk1er.patcher.mixins.bugfixes; + +import club.sk1er.patcher.config.PatcherConfig; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.gui.GuiScreenBook; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(GuiScreenBook.class) +public class GuiScreenBookMixin_AddBackground extends GuiScreen { + @Inject(method = "drawScreen", at = @At("HEAD")) + private void patcher$addBackground(int mouseX, int mouseY, float partialTicks, CallbackInfo ci) { + if (PatcherConfig.bookBackground) this.drawWorldBackground(1); + } +} diff --git a/src/main/java/club/sk1er/patcher/mixins/bugfixes/render/item/RenderItemMixin_CullFace.java b/src/main/java/club/sk1er/patcher/mixins/bugfixes/render/item/RenderItemMixin_CullFace.java index 1d43ac07a..53598c26a 100644 --- a/src/main/java/club/sk1er/patcher/mixins/bugfixes/render/item/RenderItemMixin_CullFace.java +++ b/src/main/java/club/sk1er/patcher/mixins/bugfixes/render/item/RenderItemMixin_CullFace.java @@ -1,11 +1,6 @@ package club.sk1er.patcher.mixins.bugfixes.render.item; import net.minecraft.client.renderer.GlStateManager; - -//#if MC==11202 -//$$ import net.minecraft.client.renderer.GlStateManager.CullFace; -//#endif - import net.minecraft.client.renderer.block.model.ItemCameraTransforms; import net.minecraft.client.renderer.block.model.ItemTransformVec3f; import net.minecraft.client.renderer.entity.RenderItem; @@ -21,6 +16,8 @@ @Mixin(RenderItem.class) public abstract class RenderItemMixin_CullFace { + //#if MC==10809 + @Shadow protected abstract boolean isThereOneNegativeScale(ItemTransformVec3f itemTranformVec); @@ -33,13 +30,9 @@ public abstract class RenderItemMixin_CullFace { , at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/entity/RenderItem;renderItem(Lnet/minecraft/item/ItemStack;Lnet/minecraft/client/resources/model/IBakedModel;)V")) private void patcher$cullFace(ItemStack stack, IBakedModel model, ItemCameraTransforms.TransformType cameraTransformType, CallbackInfo ci) { if (isThereOneNegativeScale(model.getItemCameraTransforms().getTransform(cameraTransformType))) { - GlStateManager. - //#if MC==10809 - cullFace(1028); - //#else - //$$ cullFace(CullFace.FRONT); - //#endif + GlStateManager.cullFace(1028); } } + //#endif } diff --git a/src/main/java/club/sk1er/patcher/mixins/bugfixes/render/item/RenderItemMixin_FixGlint.java b/src/main/java/club/sk1er/patcher/mixins/bugfixes/render/item/RenderItemMixin_FixGlint.java index e2570fffa..6effd022b 100644 --- a/src/main/java/club/sk1er/patcher/mixins/bugfixes/render/item/RenderItemMixin_FixGlint.java +++ b/src/main/java/club/sk1er/patcher/mixins/bugfixes/render/item/RenderItemMixin_FixGlint.java @@ -4,6 +4,7 @@ import net.minecraft.client.renderer.entity.RenderItem; import net.minecraft.item.ItemStack; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -11,8 +12,26 @@ @Mixin(RenderItem.class) public abstract class RenderItemMixin_FixGlint { - @Inject(method = "renderItemAndEffectIntoGUI", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/entity/RenderItem;renderItemIntoGUI(Lnet/minecraft/item/ItemStack;II)V")) - private void patcher$correctGlint(ItemStack stack, int xPosition, int yPosition, CallbackInfo ci) { + @Unique private static final String patcher$RENDER_ITEM_AND_EFFECT_INTO_GUI = + //#if MC<=10809 + "renderItemAndEffectIntoGUI"; + //#else + //$$ "renderItemAndEffectIntoGUI(Lnet/minecraft/entity/EntityLivingBase;Lnet/minecraft/item/ItemStack;II)V"; + //#endif + + @Unique private static final String patcher$RENDER_ITEM_MODEL_INTO_GUI = + //#if MC<=10809 + "Lnet/minecraft/client/renderer/entity/RenderItem;renderItemIntoGUI(Lnet/minecraft/item/ItemStack;II)V"; + //#else + //$$ "Lnet/minecraft/client/renderer/RenderItem;renderItemModelIntoGUI(Lnet/minecraft/item/ItemStack;IILnet/minecraft/client/renderer/block/model/IBakedModel;)V"; + //#endif + + @Inject(method = patcher$RENDER_ITEM_AND_EFFECT_INTO_GUI, at = @At(value = "INVOKE", target = patcher$RENDER_ITEM_MODEL_INTO_GUI)) + private void patcher$correctGlint( + //#if MC>10809 + //$$ net.minecraft.entity.EntityLivingBase p_184391_1_, + //#endif + ItemStack stack, int xPosition, int yPosition, CallbackInfo ci) { GlStateManager.enableDepth(); } diff --git a/src/main/java/club/sk1er/patcher/mixins/features/EntityRendererMixin_ParallaxFix.java b/src/main/java/club/sk1er/patcher/mixins/features/EntityRendererMixin_ParallaxFix.java index abf3f24d4..53444bdb3 100644 --- a/src/main/java/club/sk1er/patcher/mixins/features/EntityRendererMixin_ParallaxFix.java +++ b/src/main/java/club/sk1er/patcher/mixins/features/EntityRendererMixin_ParallaxFix.java @@ -1,17 +1,53 @@ package club.sk1er.patcher.mixins.features; import club.sk1er.patcher.config.PatcherConfig; +import club.sk1er.patcher.hooks.DebugCrosshairHook; +import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.EntityRenderer; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Constant; +import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyConstant; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(value = EntityRenderer.class, priority = 1001) +public abstract class EntityRendererMixin_ParallaxFix { + @Shadow + public abstract void setupOverlayRendering(); + + @Shadow + private Minecraft mc; + + @Unique + private boolean canDraw = false; -@Mixin(EntityRenderer.class) -public class EntityRendererMixin_ParallaxFix { //#if MC==10809 @ModifyConstant(method = "orientCamera", constant = @Constant(floatValue = -0.1F)) private float patcher$modifyParallax(float original) { return PatcherConfig.parallaxFix ? 0.05F : original; } + + @Inject(method = "renderWorldDirections", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;getRenderViewEntity()Lnet/minecraft/entity/Entity;"), cancellable = true) + private void cancel(float partialTicks, CallbackInfo ci) { + if (!PatcherConfig.parallaxFix) return; + canDraw = true; + ci.cancel(); + } + + @Inject(method = "updateCameraAndRender", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiIngame;renderGameOverlay(F)V")) + private void drawDebugCrosshair(float partialTicks, long nanoTime, CallbackInfo ci) { + if (canDraw) { + setupOverlayRendering(); + DebugCrosshairHook.renderDirections(partialTicks, mc); + } + } + + @Inject(method = "updateCameraAndRender", at = @At("TAIL")) + private void resetState(float partialTicks, long nanoTime, CallbackInfo ci) { + canDraw = false; + } //#endif } diff --git a/src/main/java/club/sk1er/patcher/mixins/features/GuiNewChatMixin_ExtendChatBackground.java b/src/main/java/club/sk1er/patcher/mixins/features/GuiNewChatMixin_ExtendChatBackground.java deleted file mode 100644 index 9805154d2..000000000 --- a/src/main/java/club/sk1er/patcher/mixins/features/GuiNewChatMixin_ExtendChatBackground.java +++ /dev/null @@ -1,21 +0,0 @@ -package club.sk1er.patcher.mixins.features; - -import club.sk1er.patcher.config.PatcherConfig; -import net.minecraft.client.gui.GuiNewChat; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.ModifyArg; - -@Mixin(GuiNewChat.class) -public class GuiNewChatMixin_ExtendChatBackground { - //#if MC==10809 - @ModifyArg( - method = "drawChat", at = @At(value = "INVOKE", - target = "Lnet/minecraft/client/gui/GuiNewChat;drawRect(IIIII)V", ordinal = 0), - index = 0 - ) - private int patcher$extendChatBackgroundLeft(int left) { - return PatcherConfig.extendChatBackground ? -2 : left; - } - //#endif -} diff --git a/src/main/java/club/sk1er/patcher/mixins/features/GuiNewChatMixin_TransparentChat.java b/src/main/java/club/sk1er/patcher/mixins/features/GuiNewChatMixin_TransparentChat.java deleted file mode 100644 index 45d96c3b0..000000000 --- a/src/main/java/club/sk1er/patcher/mixins/features/GuiNewChatMixin_TransparentChat.java +++ /dev/null @@ -1,22 +0,0 @@ -package club.sk1er.patcher.mixins.features; - -import club.sk1er.patcher.config.PatcherConfig; -import net.minecraft.client.gui.Gui; -import net.minecraft.client.gui.GuiNewChat; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -@Mixin(GuiNewChat.class) -public abstract class GuiNewChatMixin_TransparentChat extends Gui { - - @Shadow - public abstract boolean getChatOpen(); - - @Redirect(method = "drawChat", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiNewChat;drawRect(IIIII)V", ordinal = 0)) - private void patcher$transparentChat(int left, int top, int right, int bottom, int color) { - if (PatcherConfig.transparentChat && (!PatcherConfig.transparentChatOnlyWhenClosed || !getChatOpen())) return; - drawRect(left, top, right, bottom, color); - } -} diff --git a/src/main/java/club/sk1er/patcher/mixins/features/GuiScreenServerListMixin_FakeServerListDirectConnect.java b/src/main/java/club/sk1er/patcher/mixins/features/GuiScreenServerListMixin_FakeServerListDirectConnect.java index d9499949e..9a8a9aefb 100644 --- a/src/main/java/club/sk1er/patcher/mixins/features/GuiScreenServerListMixin_FakeServerListDirectConnect.java +++ b/src/main/java/club/sk1er/patcher/mixins/features/GuiScreenServerListMixin_FakeServerListDirectConnect.java @@ -16,7 +16,7 @@ public class GuiScreenServerListMixin_FakeServerListDirectConnect { @Shadow @Final private GuiScreen field_146303_a; @Inject(method = "actionPerformed", at = @At("HEAD")) - private void disconnectIfNecessary(GuiButton button, CallbackInfo ci) { + private void patcher$disconnectIfNecessary(GuiButton button, CallbackInfo ci) { if (button.enabled && button.id == 0 && this.field_146303_a instanceof FakeMultiplayerMenu) { FakeMultiplayerMenu parentScreen = (FakeMultiplayerMenu) this.field_146303_a; parentScreen.performDisconnection(); diff --git a/src/main/java/club/sk1er/patcher/mixins/features/ImageBufferDownloadMixin_ImprovedHeadRendering.java b/src/main/java/club/sk1er/patcher/mixins/features/ImageBufferDownloadMixin_ImprovedHeadRendering.java new file mode 100644 index 000000000..8e333dbd4 --- /dev/null +++ b/src/main/java/club/sk1er/patcher/mixins/features/ImageBufferDownloadMixin_ImprovedHeadRendering.java @@ -0,0 +1,88 @@ +package club.sk1er.patcher.mixins.features; + +import club.sk1er.patcher.config.PatcherConfig; +import club.sk1er.patcher.hooks.EarsModHook; +import net.minecraft.client.renderer.ImageBufferDownload; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +import java.awt.*; +import java.awt.image.BufferedImage; +import java.awt.image.DataBufferInt; + +/** + * This mixin is based off of SkyBlockcatia's, which is licensed under the MIT license + * sbc's license + */ +@Mixin(value = ImageBufferDownload.class) +public abstract class ImageBufferDownloadMixin_ImprovedHeadRendering { + @Shadow + private int[] imageData; + @Shadow + private int imageWidth; + @Shadow + private int imageHeight; + @Shadow + protected abstract void setAreaOpaque(int x, int y, int width, int height); + @Shadow + protected abstract void setAreaTransparent(int x, int y, int width, int height); + + @Inject(method = "parseUserSkin", at = @At("HEAD"), cancellable = true) + private void patcher$removeTransparentPixels(BufferedImage image, CallbackInfoReturnable cir) { + if (image != null && PatcherConfig.improvedSkinRendering) { + this.imageWidth = 64; + this.imageHeight = 64; + BufferedImage bufferedImage = new BufferedImage(this.imageWidth, this.imageHeight, 2); + Graphics graphics = bufferedImage.getGraphics(); + graphics.drawImage(image, 0, 0, null); + + if (image.getHeight() == 32) { + graphics.drawImage(bufferedImage, 24, 48, 20, 52, 4, 16, 8, 20, null); + graphics.drawImage(bufferedImage, 28, 48, 24, 52, 8, 16, 12, 20, null); + graphics.drawImage(bufferedImage, 20, 52, 16, 64, 8, 20, 12, 32, null); + graphics.drawImage(bufferedImage, 24, 52, 20, 64, 4, 20, 8, 32, null); + graphics.drawImage(bufferedImage, 28, 52, 24, 64, 0, 20, 4, 32, null); + graphics.drawImage(bufferedImage, 32, 52, 28, 64, 12, 20, 16, 32, null); + graphics.drawImage(bufferedImage, 40, 48, 36, 52, 44, 16, 48, 20, null); + graphics.drawImage(bufferedImage, 44, 48, 40, 52, 48, 16, 52, 20, null); + graphics.drawImage(bufferedImage, 36, 52, 32, 64, 48, 20, 52, 32, null); + graphics.drawImage(bufferedImage, 40, 52, 36, 64, 44, 20, 48, 32, null); + graphics.drawImage(bufferedImage, 44, 52, 40, 64, 40, 20, 44, 32, null); + graphics.drawImage(bufferedImage, 48, 52, 44, 64, 52, 20, 56, 32, null); + graphics.dispose(); + this.imageData = ((DataBufferInt) bufferedImage.getRaster().getDataBuffer()).getData(); + this.setAreaOpaque(0, 0, 32, 16); + this.setAreaTransparent(32, 0, 64, 32); + this.setAreaOpaque(0, 16, 64, 32); + this.setAreaTransparent(0, 32, 16, 48); + this.setAreaTransparent(16, 32, 40, 48); + this.setAreaTransparent(40, 32, 56, 48); + this.setAreaTransparent(0, 48, 16, 64); + this.setAreaOpaque(16, 48, 48, 64); + this.setAreaTransparent(48, 48, 64, 64); + cir.setReturnValue(bufferedImage); + } else { + graphics.dispose(); + this.imageData = ((DataBufferInt) bufferedImage.getRaster().getDataBuffer()).getData(); + cir.setReturnValue(image); + } + EarsModHook.preprocessSkin((ImageBufferDownload) (Object) this, image, bufferedImage); + } + } + + @Inject(method = "parseUserSkin", at = @At("TAIL"), locals = LocalCapture.CAPTURE_FAILSOFT) + private void patcher$callPreprocess(BufferedImage image, CallbackInfoReturnable cir, BufferedImage bufferedImage + //#if MC<=10809 + , Graphics var3 + //#endif + ) { + if (!PatcherConfig.improvedSkinRendering) { + EarsModHook.preprocessSkin((ImageBufferDownload) (Object) this, image, bufferedImage); + } + } + +} diff --git a/src/main/java/club/sk1er/patcher/mixins/features/ImageBufferDownload_EarsMod.java b/src/main/java/club/sk1er/patcher/mixins/features/ImageBufferDownload_EarsMod.java new file mode 100644 index 000000000..b601316df --- /dev/null +++ b/src/main/java/club/sk1er/patcher/mixins/features/ImageBufferDownload_EarsMod.java @@ -0,0 +1,19 @@ +package club.sk1er.patcher.mixins.features; + +import net.minecraft.client.renderer.ImageBufferDownload; +import org.spongepowered.asm.mixin.Dynamic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import java.awt.image.BufferedImage; + +@Mixin(ImageBufferDownload.class) +public class ImageBufferDownload_EarsMod { + + @Dynamic("Ears Mod") + @Redirect(method = "parseUserSkin", at = @At(value = "INVOKE", target = "Lcom/unascribed/ears/Ears;preprocessSkin(Lnet/minecraft/client/renderer/ImageBufferDownload;Ljava/awt/image/BufferedImage;Ljava/awt/image/BufferedImage;)V")) + private void preprocessSkin(ImageBufferDownload subject, BufferedImage rawImg, BufferedImage img) { + // this will never work because the way they find the locals is really really fragile and doesn't work with this mixin + } +} diff --git a/src/main/java/club/sk1er/patcher/mixins/features/InventoryPlayerTransformer_HotbarScrolling.java b/src/main/java/club/sk1er/patcher/mixins/features/InventoryPlayerTransformer_HotbarScrolling.java index 5c42a8c41..4373453e1 100644 --- a/src/main/java/club/sk1er/patcher/mixins/features/InventoryPlayerTransformer_HotbarScrolling.java +++ b/src/main/java/club/sk1er/patcher/mixins/features/InventoryPlayerTransformer_HotbarScrolling.java @@ -3,13 +3,11 @@ import club.sk1er.patcher.config.PatcherConfig; import club.sk1er.patcher.hooks.ZoomHook; import net.minecraft.entity.player.InventoryPlayer; -import org.spongepowered.asm.mixin.Debug; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.*; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -@Debug(export = true) @Mixin(InventoryPlayer.class) public class InventoryPlayerTransformer_HotbarScrolling { @Shadow @@ -35,7 +33,7 @@ public class InventoryPlayerTransformer_HotbarScrolling { } } - @ModifyConstant(method = "changeCurrentItem", constant = {@Constant(intValue = 9, ordinal = 2), @Constant(intValue = 9, ordinal = 0)}) + @ModifyConstant(method = "changeCurrentItem", constant = {@Constant(intValue = 9, ordinal = 0), @Constant(intValue = 9, ordinal = 2)}) private int patcher$preventOverflowScrolling(int constant) { if (PatcherConfig.preventOverflowHotbarScrolling) { return 1; diff --git a/src/main/java/club/sk1er/patcher/mixins/features/cropheight/BlockCactusMixin_CropHitbox.java b/src/main/java/club/sk1er/patcher/mixins/features/cropheight/BlockCactusMixin_CropHitbox.java index 6a51eabbe..25b35cf03 100644 --- a/src/main/java/club/sk1er/patcher/mixins/features/cropheight/BlockCactusMixin_CropHitbox.java +++ b/src/main/java/club/sk1er/patcher/mixins/features/cropheight/BlockCactusMixin_CropHitbox.java @@ -20,14 +20,14 @@ public class BlockCactusMixin_CropHitbox extends BlockMixin_CropHitbox { //#if MC==10809 @Inject(method = "getSelectedBoundingBox", at = @At("HEAD")) public void patcher$getSelectedBoundingBox(World worldIn, BlockPos pos, CallbackInfoReturnable cir) { - if (PatcherConfig.futureHitBoxes && (HypixelUtils.INSTANCE.isHypixel() || UMinecraft.getMinecraft().isIntegratedServerRunning())) { + if (PatcherConfig.futureHitBoxes && !PatcherConfig.cactusHitboxExclusion && (HypixelUtils.INSTANCE.isHypixel() || UMinecraft.getMinecraft().isIntegratedServerRunning())) { CropUtilities.updateCactusBox(worldIn.getBlockState(pos).getBlock()); } } @Override public void collisionRayTrace(World worldIn, BlockPos pos, Vec3 start, Vec3 end, CallbackInfoReturnable cir) { - if (PatcherConfig.futureHitBoxes && (HypixelUtils.INSTANCE.isHypixel() || UMinecraft.getMinecraft().isIntegratedServerRunning())) { + if (PatcherConfig.futureHitBoxes && !PatcherConfig.cactusHitboxExclusion && (HypixelUtils.INSTANCE.isHypixel() || UMinecraft.getMinecraft().isIntegratedServerRunning())) { CropUtilities.updateCactusBox(worldIn.getBlockState(pos).getBlock()); } } diff --git a/src/main/java/club/sk1er/patcher/mixins/performance/EnchantmentHelperMixin_MemoryLeak.java b/src/main/java/club/sk1er/patcher/mixins/performance/EnchantmentHelperMixin_MemoryLeak.java new file mode 100644 index 000000000..682172680 --- /dev/null +++ b/src/main/java/club/sk1er/patcher/mixins/performance/EnchantmentHelperMixin_MemoryLeak.java @@ -0,0 +1,60 @@ +package club.sk1er.patcher.mixins.performance; + +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.EnumCreatureAttribute; +import net.minecraft.item.ItemStack; +import net.minecraft.util.DamageSource; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(EnchantmentHelper.class) +public class EnchantmentHelperMixin_MemoryLeak { + + //#if MC==10809 + @Shadow + @Final + private static EnchantmentHelper.HurtIterator ENCHANTMENT_ITERATOR_HURT; + + @Shadow + @Final + private static EnchantmentHelper.DamageIterator ENCHANTMENT_ITERATOR_DAMAGE; + + @Shadow + @Final + private static EnchantmentHelper.ModifierDamage enchantmentModifierDamage; + + @Shadow + @Final + private static EnchantmentHelper.ModifierLiving enchantmentModifierLiving; + + @Inject(method = "getEnchantmentModifierDamage", at = @At("TAIL")) + private static void fixMemoryLeak(ItemStack[] stack, DamageSource source, CallbackInfoReturnable cir) { + enchantmentModifierDamage.source = null; + } + + @Inject(method = "getModifierForCreature", at = @At("TAIL")) + private static void fixMemoryLeak(ItemStack p_152377_0_, EnumCreatureAttribute p_152377_1_, CallbackInfoReturnable cir) { + enchantmentModifierLiving.entityLiving = null; + } + + @Inject(method = "applyThornEnchantments", at = @At("TAIL")) + private static void fixMemoryLeak(EntityLivingBase p_151384_0_, Entity p_151384_1_, CallbackInfo ci) { + ENCHANTMENT_ITERATOR_HURT.attacker = null; + ENCHANTMENT_ITERATOR_HURT.user = null; + } + + @Inject(method = "applyArthropodEnchantments", at = @At("TAIL")) + private static void fixMemoryLeak2(EntityLivingBase p_151385_0_, Entity p_151385_1_, CallbackInfo ci) { + ENCHANTMENT_ITERATOR_DAMAGE.target = null; + ENCHANTMENT_ITERATOR_DAMAGE.user = null; + } + + //#endif +} diff --git a/src/main/java/club/sk1er/patcher/mixins/performance/GameSettingsMixin_RefreshMipmaps.java b/src/main/java/club/sk1er/patcher/mixins/performance/GameSettingsMixin_RefreshMipmaps.java new file mode 100644 index 000000000..9791c17f8 --- /dev/null +++ b/src/main/java/club/sk1er/patcher/mixins/performance/GameSettingsMixin_RefreshMipmaps.java @@ -0,0 +1,22 @@ +package club.sk1er.patcher.mixins.performance; + +import club.sk1er.patcher.hooks.ResourceReloadHooks; +import net.minecraft.client.settings.GameSettings; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(GameSettings.class) +public class GameSettingsMixin_RefreshMipmaps { + + @Inject(method = "setOptionFloatValue", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;scheduleResourcesRefresh()Lcom/google/common/util/concurrent/ListenableFuture;")) + private void onMipmapChange(GameSettings.Options settingsOption, float value, CallbackInfo ci) { + ResourceReloadHooks.setLoadMipmaps(true); + } + + @Inject(method = "setOptionFloatValue", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;scheduleResourcesRefresh()Lcom/google/common/util/concurrent/ListenableFuture;", shift = At.Shift.AFTER)) + private void onMipmapChangeAfter(GameSettings.Options settingsOption, float value, CallbackInfo ci) { + ResourceReloadHooks.setLoadMipmaps(false); + } +} diff --git a/src/main/java/club/sk1er/patcher/mixins/performance/GuiLanguageMixin_RefreshLanguage.java b/src/main/java/club/sk1er/patcher/mixins/performance/GuiLanguageMixin_RefreshLanguage.java new file mode 100644 index 000000000..59085f772 --- /dev/null +++ b/src/main/java/club/sk1er/patcher/mixins/performance/GuiLanguageMixin_RefreshLanguage.java @@ -0,0 +1,34 @@ +package club.sk1er.patcher.mixins.performance; + +import club.sk1er.patcher.hooks.ResourceReloadHooks; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(targets = "net/minecraft/client/gui/GuiLanguage$List") +public class GuiLanguageMixin_RefreshLanguage { + + @Inject( + method = "elementClicked", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/client/Minecraft;refreshResources()V" + ) + ) + private void onResourceLoad(int par1, boolean par2, int par3, int par4, CallbackInfo ci) { + ResourceReloadHooks.setLoadLanguage(true); + } + + @Inject( + method = "elementClicked", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/client/Minecraft;refreshResources()V", + shift = At.Shift.AFTER + ) + ) + private void onGameOptionWrite(int par1, boolean par2, int par3, int par4, CallbackInfo ci) { + ResourceReloadHooks.setLoadLanguage(false); + } +} diff --git a/src/main/java/club/sk1er/patcher/mixins/performance/ItemStackMixin_TooltipCache.java b/src/main/java/club/sk1er/patcher/mixins/performance/ItemStackMixin_TooltipCache.java new file mode 100644 index 000000000..66c3aad12 --- /dev/null +++ b/src/main/java/club/sk1er/patcher/mixins/performance/ItemStackMixin_TooltipCache.java @@ -0,0 +1,46 @@ +package club.sk1er.patcher.mixins.performance; + +import club.sk1er.patcher.config.PatcherConfig; +import club.sk1er.patcher.util.item.TooltipHandler; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.List; + +@Mixin(ItemStack.class) +public abstract class ItemStackMixin_TooltipCache { + @Inject( + method = "getTooltip", + at = @At( + value = "HEAD" + ), + cancellable = true) + public void patcher$useCachedTooltip(EntityPlayer playerIn, boolean advanced, CallbackInfoReturnable> cir) { + if (!PatcherConfig.tooltipCache) { + return; + } + if (TooltipHandler.INSTANCE.tooltipCache != null) { + TooltipHandler.INSTANCE.shouldToolTipRender = false; + cir.setReturnValue(TooltipHandler.INSTANCE.tooltipCache); + } + TooltipHandler.INSTANCE.shouldToolTipRender = true; + } + + @Inject( + method = "getTooltip", + at = @At( + value = "RETURN" + ) + ) + public void patcher$cacheTooltip(EntityPlayer playerIn, boolean advanced, CallbackInfoReturnable> cir) { + if (!PatcherConfig.tooltipCache) { + return; + } + TooltipHandler.INSTANCE.tooltipCache = cir.getReturnValue(); + TooltipHandler.INSTANCE.shouldToolTipRender = false; + } +} diff --git a/src/main/java/club/sk1er/patcher/mixins/performance/MathHelperMixin_CompactLUT.java b/src/main/java/club/sk1er/patcher/mixins/performance/MathHelperMixin_CompactLUT.java new file mode 100644 index 000000000..c7ca61bf0 --- /dev/null +++ b/src/main/java/club/sk1er/patcher/mixins/performance/MathHelperMixin_CompactLUT.java @@ -0,0 +1,28 @@ +package club.sk1er.patcher.mixins.performance; + +import me.jellysquid.mods.lithium.common.util.math.CompactSineLUT; +import net.minecraft.util.MathHelper; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; + +@Mixin(MathHelper.class) +public class MathHelperMixin_CompactLUT { + + /** + * @author Wyvest + * @reason Use a compact LUT for sine calculations + */ + @Overwrite + public static float sin(float f) { + return CompactSineLUT.sin(f); + } + + /** + * @author Wyvest + * @reason Use a compact LUT for cosine calculations + */ + @Overwrite + public static float cos(float f) { + return CompactSineLUT.cos(f); + } +} diff --git a/src/main/java/club/sk1er/patcher/mixins/performance/RenderChunkMixin_OptimizeSpecialTileEntities.java b/src/main/java/club/sk1er/patcher/mixins/performance/RenderChunkMixin_OptimizeSpecialTileEntities.java new file mode 100644 index 000000000..7589ba8bd --- /dev/null +++ b/src/main/java/club/sk1er/patcher/mixins/performance/RenderChunkMixin_OptimizeSpecialTileEntities.java @@ -0,0 +1,29 @@ +package club.sk1er.patcher.mixins.performance; + +import net.minecraft.client.renderer.chunk.CompiledChunk; +import net.minecraft.client.renderer.chunk.RenderChunk; +import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; +import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; +import net.minecraft.tileentity.TileEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(RenderChunk.class) +public class RenderChunkMixin_OptimizeSpecialTileEntities { +//#if MC==10809 + /** + * Minecraft typically renders special tile entities twice per frame. This is noticeable by comparing the opacity + * of a beacon beam when the beacon is in view versus when it's out of view (fly 50 blocks above, for instance). + *

+ * This fix is based off a Forge PR that was added to 1.11.x: + * forge PR + */ + @Redirect(method = "rebuildChunk", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/chunk/CompiledChunk;addTileEntity(Lnet/minecraft/tileentity/TileEntity;)V")) + private void patcher$renderSpecialTileEntitiesOnce(CompiledChunk instance, TileEntity tileEntityIn) { + TileEntitySpecialRenderer tileentityspecialrenderer = TileEntityRendererDispatcher.instance.getSpecialRenderer(tileEntityIn); + if (!tileentityspecialrenderer.forceTileEntityRender()) instance.addTileEntity(tileEntityIn); + } +//#endif +} + diff --git a/src/main/java/club/sk1er/patcher/mixins/performance/SimpleReloadableResourceManager_OnlyRefreshNecessaryListeners.java b/src/main/java/club/sk1er/patcher/mixins/performance/SimpleReloadableResourceManager_OnlyRefreshNecessaryListeners.java new file mode 100644 index 000000000..7b8f32374 --- /dev/null +++ b/src/main/java/club/sk1er/patcher/mixins/performance/SimpleReloadableResourceManager_OnlyRefreshNecessaryListeners.java @@ -0,0 +1,51 @@ +package club.sk1er.patcher.mixins.performance; + +import club.sk1er.patcher.hooks.ResourceReloadHooks; +import net.minecraft.client.resources.IResourceManagerReloadListener; +import net.minecraft.client.resources.LanguageManager; +import net.minecraft.client.resources.SimpleReloadableResourceManager; +import net.minecraft.client.resources.model.ModelManager; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.List; + +@Mixin(SimpleReloadableResourceManager.class) +public class SimpleReloadableResourceManager_OnlyRefreshNecessaryListeners { + + @Shadow + @Final + private List reloadListeners; + + @Inject(method = "registerReloadListener", at = @At("HEAD")) + private void onReloadListenerRegister(IResourceManagerReloadListener reloadListener, CallbackInfo ci) { + if (reloadListener instanceof LanguageManager) { + ResourceReloadHooks.setLanguageManager(reloadListener); + } else if (reloadListener instanceof ModelManager) { + ResourceReloadHooks.setModelManager(reloadListener); + } + } + + @Redirect(method = "notifyReloadListeners", at = @At(value = "FIELD", target = "Lnet/minecraft/client/resources/SimpleReloadableResourceManager;reloadListeners:Ljava/util/List;")) + private List redirectNotifyReloadListeners(SimpleReloadableResourceManager simpleReloadableResourceManager) { + if (ResourceReloadHooks.shouldLoadLanguage()) { + return ResourceReloadHooks.getLanguageManager(); + } else if (ResourceReloadHooks.shouldLoadMipmaps()) { + return ResourceReloadHooks.getModelManager(); + } else { + return reloadListeners; + } + } + + @Inject(method = "notifyReloadListeners", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/fml/common/ProgressManager;pop(Lnet/minecraftforge/fml/common/ProgressManager$ProgressBar;)V")) + private void callOptiFineLanguage(CallbackInfo ci) { + if (ResourceReloadHooks.shouldLoadLanguage()) { + ResourceReloadHooks.reloadOptiFineLanguage(); + } + } +} diff --git a/src/main/java/club/sk1er/patcher/mixins/performance/TextureManagerMixin_MemoryLeak.java b/src/main/java/club/sk1er/patcher/mixins/performance/TextureManagerMixin_MemoryLeak.java new file mode 100644 index 000000000..80cc32880 --- /dev/null +++ b/src/main/java/club/sk1er/patcher/mixins/performance/TextureManagerMixin_MemoryLeak.java @@ -0,0 +1,27 @@ +package club.sk1er.patcher.mixins.performance; + +import net.minecraft.client.renderer.texture.ITextureObject; +import net.minecraft.client.renderer.texture.TextureManager; +import net.minecraft.util.ResourceLocation; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.Map; + +@Mixin(TextureManager.class) +public class TextureManagerMixin_MemoryLeak { + //#if MC==10809 + @Shadow + @Final + private Map mapTextureObjects; + + @Inject(method = "deleteTexture", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/texture/TextureUtil;deleteTexture(I)V", shift = At.Shift.BEFORE)) + private void patcher$removeEntry(ResourceLocation textureLocation, CallbackInfo ci) { + this.mapTextureObjects.remove(textureLocation); + } + //#endif +} diff --git a/src/main/java/club/sk1er/patcher/mixins/performance/forge/ASMDataTableMixin_ComputeParallel.java b/src/main/java/club/sk1er/patcher/mixins/performance/forge/ASMDataTableMixin_ComputeParallel.java new file mode 100644 index 000000000..bd90d4cc6 --- /dev/null +++ b/src/main/java/club/sk1er/patcher/mixins/performance/forge/ASMDataTableMixin_ComputeParallel.java @@ -0,0 +1,43 @@ +package club.sk1er.patcher.mixins.performance.forge; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSetMultimap; +import com.google.common.collect.Multimaps; +import com.google.common.collect.SetMultimap; +import net.minecraftforge.fml.common.ModContainer; +import net.minecraftforge.fml.common.discovery.ASMDataTable; +import org.apache.commons.lang3.tuple.Pair; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Mixin(value = ASMDataTable.class, remap = false) +public class ASMDataTableMixin_ComputeParallel { + //#if MC==10809 + @Shadow + private Map> containerAnnotationData; + + @Shadow + private List containers; + + @Shadow + private SetMultimap globalAnnotationData; + + @Inject(method = "getAnnotationsFor", at = @At("HEAD")) + private void computeParallel(ModContainer container, CallbackInfoReturnable> cir) { + if (containerAnnotationData == null) { + //concurrently filter the values to speed this up + containerAnnotationData = containers.parallelStream() + .map(cont -> Pair.of(cont, ImmutableSetMultimap.copyOf(Multimaps.filterValues(globalAnnotationData, data -> cont.getSource().equals(data.getCandidate().getModContainer()))))) + .collect(Collectors.toMap(Pair::getKey, Pair::getValue)); + containerAnnotationData = ImmutableMap.copyOf(containerAnnotationData); + } + } + //#endif +} diff --git a/src/main/java/club/sk1er/patcher/mixins/performance/forge/FMLControlledNamespacedRegistryMixin_TrimAvailabilityMap.java b/src/main/java/club/sk1er/patcher/mixins/performance/forge/FMLControlledNamespacedRegistryMixin_TrimAvailabilityMap.java new file mode 100644 index 000000000..cfa6b2cd9 --- /dev/null +++ b/src/main/java/club/sk1er/patcher/mixins/performance/forge/FMLControlledNamespacedRegistryMixin_TrimAvailabilityMap.java @@ -0,0 +1,44 @@ +package club.sk1er.patcher.mixins.performance.forge; + +//#if MC==10809 +import net.minecraftforge.fml.common.registry.FMLControlledNamespacedRegistry; +//#endif + +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.relauncher.ReflectionHelper; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyArg; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.BitSet; + +@Mixin( + //#if MC==10809 + value = FMLControlledNamespacedRegistry.class, remap = false + //#else + //$$ net.minecraft.client.Minecraft.class + //#endif +) +public class FMLControlledNamespacedRegistryMixin_TrimAvailabilityMap { + //#if MC==10809 + @Shadow @Final private BitSet availabilityMap; + + @ModifyArg(method = "(Lnet/minecraft/util/ResourceLocation;IILjava/lang/Class;ZLnet/minecraftforge/fml/common/registry/FMLControlledNamespacedRegistry$AddCallback;)V", at = @At(value = "NEW", target = "Ljava/util/BitSet;(I)V"), index = 0) + public int noPreAllocate(int nbits) { + return Math.min(nbits, 0xFFFF); + } + + @Inject(method = "validateContent", at = @At("HEAD")) + public void trimToSize(ResourceLocation registryName, CallbackInfo ci) { + try { + ReflectionHelper.findMethod(BitSet.class, this.availabilityMap, new String[]{"trimToSize"}).invoke(this.availabilityMap); + } catch (Exception ignored) { + + } + } + //#endif +} diff --git a/src/main/java/club/sk1er/patcher/mixins/performance/forge/ItemLayerModelMixin_ReduceQuadCount.java b/src/main/java/club/sk1er/patcher/mixins/performance/forge/ItemLayerModelMixin_ReduceQuadCount.java index 048d80a88..64597ed7e 100644 --- a/src/main/java/club/sk1er/patcher/mixins/performance/forge/ItemLayerModelMixin_ReduceQuadCount.java +++ b/src/main/java/club/sk1er/patcher/mixins/performance/forge/ItemLayerModelMixin_ReduceQuadCount.java @@ -1,5 +1,6 @@ package club.sk1er.patcher.mixins.performance.forge; +import club.sk1er.patcher.config.PatcherConfig; import club.sk1er.patcher.hooks.FaceDataHook; import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; @@ -26,7 +27,7 @@ public abstract class ItemLayerModelMixin_ReduceQuadCount { //#if MC==10809 @Unique - private static final EnumFacing[] patcher$HORIZONTALS = new EnumFacing[] { EnumFacing.UP, EnumFacing.DOWN };; + private static final EnumFacing[] patcher$HORIZONTALS = new EnumFacing[] { EnumFacing.UP, EnumFacing.DOWN }; @Unique private static final EnumFacing[] patcher$VERTICALS = new EnumFacing[] { EnumFacing.WEST, EnumFacing.EAST }; @@ -200,12 +201,12 @@ else if (!building && face) { float u3 = 16.0f * (x2 - dx); float v2 = 16.0f * (1.0f - y0 - dy); float v3 = 16.0f * (1.0f - y2 - dy); - cir.setReturnValue(buildQuad(format, transform, patcher$remap(side), tint, x0, y0, z0, sprite.getInterpolatedU((double)u2), sprite.getInterpolatedV((double)v2), x2, y2, z0, sprite.getInterpolatedU((double)u3), sprite.getInterpolatedV((double)v3), x2, y2, z2, sprite.getInterpolatedU((double)u3), sprite.getInterpolatedV((double)v3), x0, y0, z2, sprite.getInterpolatedU((double)u2), sprite.getInterpolatedV((double)v2))); + cir.setReturnValue(buildQuad(format, transform, patcher$remap(side), tint, x0, y0, z0, sprite.getInterpolatedU(u2), sprite.getInterpolatedV(v2), x2, y2, z0, sprite.getInterpolatedU(u3), sprite.getInterpolatedV(v3), x2, y2, z2, sprite.getInterpolatedU(u3), sprite.getInterpolatedV(v3), x0, y0, z2, sprite.getInterpolatedU(u2), sprite.getInterpolatedV(v2))); } @Unique private static EnumFacing patcher$remap(EnumFacing side) { - return (side.getAxis() == EnumFacing.Axis.Y) ? side.getOpposite() : side; + return !PatcherConfig.heldItemLighting || (side.getAxis() == EnumFacing.Axis.Y) ? side.getOpposite() : side; } //#endif diff --git a/src/main/java/club/sk1er/patcher/mixins/performance/forge/JarDiscovererMixin_ReplaceRegex.java b/src/main/java/club/sk1er/patcher/mixins/performance/forge/JarDiscovererMixin_ReplaceRegex.java new file mode 100644 index 000000000..573e85bee --- /dev/null +++ b/src/main/java/club/sk1er/patcher/mixins/performance/forge/JarDiscovererMixin_ReplaceRegex.java @@ -0,0 +1,40 @@ +package club.sk1er.patcher.mixins.performance.forge; + +import net.minecraftforge.fml.common.discovery.ITypeDiscoverer; +import net.minecraftforge.fml.common.discovery.JarDiscoverer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +@Mixin(value = JarDiscoverer.class, remap = false) +public class JarDiscovererMixin_ReplaceRegex { // todo i cba to put this in directorydiscoverer as well + + @Unique private static final Matcher patcher$dummyMatcher = ITypeDiscoverer.classFile.matcher("null"); + + @Unique + private static final String patcher$replaceRegexMethod = + //#if MC==10809 + "discover"; + //#else + //$$ "findClassesASM"; + //#endif + + @Unique private String patcher$fileName; + + @Redirect(method = patcher$replaceRegexMethod, at = @At(value = "INVOKE", target = "Ljava/util/regex/Pattern;matcher(Ljava/lang/CharSequence;)Ljava/util/regex/Matcher;")) + private Matcher patcher$replaceRegex(Pattern instance, CharSequence input) { + if (input != null) { + patcher$fileName = input.toString(); + } + return patcher$dummyMatcher; + } + + @Redirect(method = patcher$replaceRegexMethod, at = @At(value = "INVOKE", target = "Ljava/util/regex/Matcher;matches()Z")) + private boolean patcher$replaceRegex(Matcher instance) { + return patcher$fileName != null && patcher$fileName.endsWith(".class") && !patcher$fileName.startsWith("$") && !patcher$fileName.endsWith("$"); + } +} diff --git a/src/main/java/club/sk1er/patcher/mixins/performance/forge/ModDiscovererMixin_Logging.java b/src/main/java/club/sk1er/patcher/mixins/performance/forge/ModDiscovererMixin_Logging.java new file mode 100644 index 000000000..99b01d97b --- /dev/null +++ b/src/main/java/club/sk1er/patcher/mixins/performance/forge/ModDiscovererMixin_Logging.java @@ -0,0 +1,28 @@ +package club.sk1er.patcher.mixins.performance.forge; + +import club.sk1er.patcher.util.forge.EntrypointCaching; +import net.minecraftforge.fml.common.ModContainer; +import net.minecraftforge.fml.common.discovery.ModDiscoverer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.List; + +@Mixin(value = ModDiscoverer.class, remap = false) +public class ModDiscovererMixin_Logging { + @Unique + private long patcher$time; + + @Inject(method = "identifyMods", at = @At("HEAD")) + private void patcher$logStart(CallbackInfoReturnable> cir) { + patcher$time = System.currentTimeMillis(); + } + + @Inject(method = "identifyMods", at = @At("TAIL")) + private void patcher$logEnd(CallbackInfoReturnable> cir) { + EntrypointCaching.INSTANCE.logger.info("ModDiscoverer.identifyMods took " + (System.currentTimeMillis() - patcher$time) + "ms"); + } +} diff --git a/src/main/java/club/sk1er/patcher/mixins/performance/forge/ModDiscovererMixin_ReplaceRegex.java b/src/main/java/club/sk1er/patcher/mixins/performance/forge/ModDiscovererMixin_ReplaceRegex.java new file mode 100644 index 000000000..a03f37fdb --- /dev/null +++ b/src/main/java/club/sk1er/patcher/mixins/performance/forge/ModDiscovererMixin_ReplaceRegex.java @@ -0,0 +1,42 @@ +package club.sk1er.patcher.mixins.performance.forge; + +import net.minecraftforge.fml.common.discovery.ModDiscoverer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +@Mixin(value = ModDiscoverer.class, remap = false) +public class ModDiscovererMixin_ReplaceRegex { + + //#if MC<=10809 + @Shadow + private static Pattern zipJar; + @Unique + private static final Matcher patcher$dummyMatcher = zipJar.matcher("null"); + @Unique private String patcher$fileName; + + @Redirect(method = "findModDirMods(Ljava/io/File;[Ljava/io/File;)V", at = @At(value = "INVOKE", target = "Ljava/util/regex/Pattern;matcher(Ljava/lang/CharSequence;)Ljava/util/regex/Matcher;")) + private Matcher patcher$replaceRegex(Pattern instance, CharSequence input) { + if (input != null) { + patcher$fileName = input.toString(); + } + return patcher$dummyMatcher; + } + + @Redirect(method = "findModDirMods(Ljava/io/File;[Ljava/io/File;)V", at = @At(value = "INVOKE", target = "Ljava/util/regex/Matcher;matches()Z")) + private boolean patcher$replaceRegex(Matcher instance) { + return patcher$fileName != null && (patcher$fileName.endsWith(".jar") || patcher$fileName.endsWith(".zip")); + } + + @Redirect(method = "findModDirMods(Ljava/io/File;[Ljava/io/File;)V", at = @At(value = "INVOKE", target = "Ljava/util/regex/Matcher;group(I)Ljava/lang/String;")) + private String patcher$replaceRegex(Matcher instance, int group) { + return patcher$fileName; // we could cut out the file extension but it's not necessary cause this is just for logging + } + + //#endif +} diff --git a/src/main/java/club/sk1er/patcher/mixins/performance/optifine/GameSettingsMixin_RefreshOFMipmaps.java b/src/main/java/club/sk1er/patcher/mixins/performance/optifine/GameSettingsMixin_RefreshOFMipmaps.java new file mode 100644 index 000000000..cff425f13 --- /dev/null +++ b/src/main/java/club/sk1er/patcher/mixins/performance/optifine/GameSettingsMixin_RefreshOFMipmaps.java @@ -0,0 +1,25 @@ +package club.sk1er.patcher.mixins.performance.optifine; + +import club.sk1er.patcher.hooks.ResourceReloadHooks; +import net.minecraft.client.settings.GameSettings; +import org.spongepowered.asm.mixin.Dynamic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(GameSettings.class) +public class GameSettingsMixin_RefreshOFMipmaps { + + @Dynamic("OptiFine") + @Inject(method = "setOptionFloatValueOF", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;refreshResources()V")) + private void onMipmapTypeChange(GameSettings.Options settingsOption, float value, CallbackInfo ci) { + ResourceReloadHooks.setLoadMipmaps(true); + } + + @Dynamic("OptiFine") + @Inject(method = "setOptionFloatValueOF", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;refreshResources()V", shift = At.Shift.AFTER)) + private void onMipmapTypeChangeAfter(GameSettings.Options settingsOption, float value, CallbackInfo ci) { + ResourceReloadHooks.setLoadMipmaps(false); + } +} diff --git a/src/main/java/club/sk1er/patcher/mixins/performance/optifine/MathHelperMixin_OFFastMath.java b/src/main/java/club/sk1er/patcher/mixins/performance/optifine/MathHelperMixin_OFFastMath.java new file mode 100644 index 000000000..e1f398b20 --- /dev/null +++ b/src/main/java/club/sk1er/patcher/mixins/performance/optifine/MathHelperMixin_OFFastMath.java @@ -0,0 +1,39 @@ +package club.sk1er.patcher.mixins.performance.optifine; + +import me.jellysquid.mods.lithium.common.util.math.CompactSineLUT; +import net.minecraft.util.MathHelper; +import org.spongepowered.asm.mixin.*; + +@Mixin(MathHelper.class) +public class MathHelperMixin_OFFastMath { + + @Dynamic("OptiFine") + @Shadow + private static float[] SIN_TABLE_FAST; + + @Dynamic("OptiFine") + @Shadow + private static float radToIndex; + + @Dynamic("OptiFine") + @Shadow + public static boolean fastMath; + + /** + * @author Wyvest + * @reason Use a compact LUT for sine calculations + */ + @Overwrite + public static float sin(float f) { + return fastMath ? SIN_TABLE_FAST[(int)(f * radToIndex) & 4095] : CompactSineLUT.sin(f); + } + + /** + * @author Wyvest + * @reason Use a compact LUT for cosine calculations + */ + @Overwrite + public static float cos(float f) { + return fastMath ? SIN_TABLE_FAST[(int)(f * radToIndex + 1024.0F) & 4095] : CompactSineLUT.cos(f); + } +} diff --git a/src/main/java/club/sk1er/patcher/mixins/plugin/PatcherMixinPlugin.java b/src/main/java/club/sk1er/patcher/mixins/plugin/PatcherMixinPlugin.java index 70372b3d8..e1900408a 100644 --- a/src/main/java/club/sk1er/patcher/mixins/plugin/PatcherMixinPlugin.java +++ b/src/main/java/club/sk1er/patcher/mixins/plugin/PatcherMixinPlugin.java @@ -3,6 +3,7 @@ import club.sk1er.patcher.tweaker.ClassTransformer; import com.google.common.collect.ArrayListMultimap; import kotlin.text.StringsKt; +import org.spongepowered.asm.mixin.MixinEnvironment; import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; import org.spongepowered.asm.mixin.extensibility.IMixinInfo; @@ -12,16 +13,26 @@ public class PatcherMixinPlugin implements IMixinConfigPlugin { private static final String LABYMOD_CLASS = "net/labymod/main/LabyMod.class"; private static final String SMOOTHFONT_CLASS = "bre/smoothfont/mod_SmoothFont.class"; + private static final String OF_CONFIG_CLASS = "Config.class"; private static final ArrayListMultimap CONFLICTING_CLASSES = ArrayListMultimap.create(); + private static boolean isEarsMod = false; static { + MixinEnvironment.getDefaultEnvironment().addTransformerExclusion("com.unascribed.ears.asm.PlatformTransformerAdapter"); CONFLICTING_CLASSES.put("GuiContainerMixin_MouseBindFixThatLabyBreaks", LABYMOD_CLASS); CONFLICTING_CLASSES.put("FontRendererMixin_Optimization", SMOOTHFONT_CLASS); + CONFLICTING_CLASSES.put("MathHelperMixin_CompactLUT", OF_CONFIG_CLASS); } @Override public void onLoad(String mixinPackage) { + try { + Class.forName("com.unascribed.ears.Ears", false, getClass().getClassLoader()); + isEarsMod = true; + } catch (ClassNotFoundException ignored) { + isEarsMod = false; + } } @Override @@ -31,6 +42,9 @@ public String getRefMapperConfig() { @Override public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { + if (mixinClassName.endsWith("_EarsMod")) { + return isEarsMod; + } String mixinPackage = StringsKt.substringBeforeLast(mixinClassName, '.', mixinClassName); if (mixinPackage.endsWith("optifine") && "NONE".equals(ClassTransformer.optifineVersion)) { // OptiFine isn't present, let's not apply this diff --git a/src/main/java/club/sk1er/patcher/screen/PatcherMenuEditor.java b/src/main/java/club/sk1er/patcher/screen/PatcherMenuEditor.java index f39c572bd..6dc2bca2d 100644 --- a/src/main/java/club/sk1er/patcher/screen/PatcherMenuEditor.java +++ b/src/main/java/club/sk1er/patcher/screen/PatcherMenuEditor.java @@ -203,7 +203,6 @@ public void keyboardInput(GuiScreenEvent.KeyboardInputEvent.Post event) { if (next > 9) { next = 0; tripped = !tripped; - Patcher.instance.getLogger().info("yep"); } } } diff --git a/src/main/java/club/sk1er/patcher/tweaker/ClassTransformer.java b/src/main/java/club/sk1er/patcher/tweaker/ClassTransformer.java index 8a00f1f93..3e57c3c4f 100644 --- a/src/main/java/club/sk1er/patcher/tweaker/ClassTransformer.java +++ b/src/main/java/club/sk1er/patcher/tweaker/ClassTransformer.java @@ -4,10 +4,7 @@ import club.sk1er.patcher.asm.external.forge.ForgeChunkManagerTransformer; //#endif import club.sk1er.patcher.asm.external.forge.ModelLoaderTransformer; -import club.sk1er.patcher.asm.external.forge.loader.ASMModParserTransformer; -import club.sk1er.patcher.asm.external.forge.loader.MinecraftForgeTransformer; -import club.sk1er.patcher.asm.external.forge.loader.ModClassLoaderTransformer; -import club.sk1er.patcher.asm.external.forge.loader.ModContainerFactoryTransformer; +import club.sk1er.patcher.asm.external.forge.loader.*; import club.sk1er.patcher.asm.external.forge.render.ForgeHooksClientTransformer; import club.sk1er.patcher.asm.external.forge.render.block.BlockInfoTransformer; import club.sk1er.patcher.asm.external.forge.render.block.ForgeBlockModelRendererTransformer; @@ -154,7 +151,7 @@ public ClassTransformer() { registerTransformer(new ModContainerFactoryTransformer()); //#endif registerTransformer(new GuiIngameForgeTransformer()); - //registerTransformer(new JarDiscovererTransformer()); + registerTransformer(new JarDiscovererTransformer()); // lwjgl registerTransformer(new WindowsDisplayTransformer()); diff --git a/src/main/java/club/sk1er/patcher/util/chat/ChatHandler.java b/src/main/java/club/sk1er/patcher/util/chat/ChatHandler.java index f6594008e..4180ea4cb 100644 --- a/src/main/java/club/sk1er/patcher/util/chat/ChatHandler.java +++ b/src/main/java/club/sk1er/patcher/util/chat/ChatHandler.java @@ -10,7 +10,6 @@ import net.minecraft.util.ChatStyle; import net.minecraft.util.IChatComponent; import net.minecraftforge.client.event.ClientChatReceivedEvent; -import net.minecraftforge.client.event.RenderGameOverlayEvent; import net.minecraftforge.event.world.WorldEvent; import net.minecraftforge.fml.common.Loader; import net.minecraftforge.fml.common.eventhandler.EventPriority; @@ -46,15 +45,6 @@ public class ChatHandler { public static int currentMessageHash = -1; private int ticks; - //#if MC==10809 - @SubscribeEvent - public void renderChat(RenderGameOverlayEvent.Chat event) { - if (event.type == RenderGameOverlayEvent.ElementType.CHAT && PatcherConfig.chatPosition) { - event.posY -= 12; - } - } - //#endif - @SubscribeEvent(priority = EventPriority.LOWEST) public void onChatMessage(ClientChatReceivedEvent event) { //#if MC==10809 diff --git a/src/main/java/club/sk1er/patcher/util/forge/EntrypointCaching.java b/src/main/java/club/sk1er/patcher/util/forge/EntrypointCaching.java index bdc54ac09..47f6d7ae8 100644 --- a/src/main/java/club/sk1er/patcher/util/forge/EntrypointCaching.java +++ b/src/main/java/club/sk1er/patcher/util/forge/EntrypointCaching.java @@ -1,6 +1,8 @@ package club.sk1er.patcher.util.forge; +import cc.polyfrost.oneconfig.utils.Notifications; import club.sk1er.patcher.config.PatcherConfig; +import com.google.common.collect.ImmutableList; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; @@ -27,17 +29,17 @@ import java.util.jar.JarFile; import java.util.zip.ZipEntry; -/*public class EntrypointCaching { +public class EntrypointCaching { public static EntrypointCaching INSTANCE = new EntrypointCaching(); - private final Logger logger = LogManager.getLogger("Patcher Entrypoint Cache"); - private final Type mapType = new TypeToken>>() {}.getType(); + public final Logger logger = LogManager.getLogger("Patcher Entrypoint Cache"); + private final Type mapType = new TypeToken>>>() {}.getType(); private final Gson gson = new GsonBuilder().setPrettyPrinting().create(); private final File cacheFile = new File("patcher/entrypoint_cache.json"); - private Map> readMap; - private Map> usedMap = new HashMap<>(); + private List>> readMap; + private List>> usedMap = ImmutableList.of(new HashMap<>(), new HashMap<>()); private Map hashCache = new HashMap<>(); private EntrypointCaching() { @@ -51,7 +53,7 @@ private EntrypointCaching() { } catch (Exception e) { logger.error("Failed to read entrypoint cache", e); } - readMap = new HashMap<>(); + readMap = ImmutableList.of(new HashMap<>(), new HashMap<>()); } @SuppressWarnings("unused") @@ -62,28 +64,24 @@ public List discoverCachedEntrypoints(ModCandidate candidate, ASMD String hash = getHash(modFile); if (hash == null) return null; - List modClasses = readMap.get(hash); - if (modClasses == null) return null; + List entryClasses = readMap.get(0).get(hash); + List modClasses = readMap.get(1).get(hash); + if (entryClasses == null && modClasses == null) return null; List foundMods = new ArrayList<>(); - List validMods = new ArrayList<>(); - - for (String modClass : modClasses) { - ASMModParser modParser; - try (InputStream is = file.getInputStream(new JarEntry(modClass))) { - modParser = new ASMModParser(is); - } catch (Exception e) { - logger.error("Error parsing mod class " + modClass + " from jar " + modFile, e); - continue; + List validEntries = null; + if (entryClasses != null && !entryClasses.isEmpty()) { + validEntries = new ArrayList<>(entryClasses.size()); + for (String modClass : entryClasses) { + iterateThroughClass(true, candidate, table, file, mc, modFile, foundMods, validEntries, modClass); } - modParser.validate(); - modParser.sendToTable(table, candidate); - ModContainer container = ModContainerFactory.instance().build(modParser, modFile, candidate); - if (container != null) { - table.addContainer(container); - foundMods.add(container); - validMods.add(modClass); - container.bindMetadata(mc); + } + + List validClasses = null; + if (modClasses != null && !modClasses.isEmpty()) { + validClasses = new ArrayList<>(modClasses.size()); + for (String modClass : modClasses) { + iterateThroughClass(false, candidate, table, file, mc, modFile, foundMods, validClasses, modClass); } } @@ -95,11 +93,38 @@ public List discoverCachedEntrypoints(ModCandidate candidate, ASMD logger.error("Error closing mod jar " + modFile, e); } - usedMap.put(hash, validMods); + usedMap.get(0).put(hash, (validEntries)); + usedMap.get(1).put(hash, (validClasses)); return foundMods; } + private void iterateThroughClass(boolean entry, ModCandidate candidate, ASMDataTable table, JarFile file, MetadataCollection mc, File modFile, List foundMods, List validMods, String modClass) { + candidate.addClassEntry(modClass); + + if (entry) { + try (InputStream is = file.getInputStream(new JarEntry(modClass))) { + ASMModParser modParser = new ASMModParser(is); + modParser.validate(); + modParser.sendToTable(table, candidate); + ModContainer container = ModContainerFactory.instance().build(modParser, modFile, candidate); + if (container != null) { + table.addContainer(container); + foundMods.add(container); + validMods.add(modClass); + container.bindMetadata(mc); + //#if MC>10809 + //$$ container.setClassVersion(modParser.getClassVersion()); + //#endif + } + } catch (Exception e) { + logger.error("Error parsing mod class " + modClass + " from jar " + modFile, e); + } + } else { + validMods.add(modClass); + } + } + @SuppressWarnings("unused") public void putCachedEntrypoints(ModCandidate candidate, ZipEntry ze) { if (!PatcherConfig.cacheEntrypoints) return; @@ -107,7 +132,7 @@ public void putCachedEntrypoints(ModCandidate candidate, ZipEntry ze) { String modClass = ze.getName(); String hash = hashCache.computeIfAbsent(modFile, this::getHash); - List modClasses = usedMap.computeIfAbsent(hash, h -> new ArrayList<>()); + List modClasses = usedMap.get(0).computeIfAbsent(hash, h -> new ArrayList<>()); if (!modClasses.contains(modClass)) { modClasses.add(modClass); } @@ -115,6 +140,20 @@ public void putCachedEntrypoints(ModCandidate candidate, ZipEntry ze) { logger.info("Added entrypoint {} for mod jar {}", modClass, modFile); } + @SuppressWarnings("unused") + public void putCachedClassEntries(ModCandidate candidate, ZipEntry ze) { + if (!PatcherConfig.cacheEntrypoints) return; + + File modFile = candidate.getModContainer(); + String modClass = ze.getName(); + + String hash = hashCache.computeIfAbsent(modFile, this::getHash); + List modClasses = usedMap.get(1).computeIfAbsent(hash, h -> new ArrayList<>()); + if (!modClasses.contains(modClass)) { + modClasses.add(modClass); + } + } + public void onInit() { if (!PatcherConfig.cacheEntrypoints) return; readMap = null; @@ -166,4 +205,15 @@ private String getHash(File modFile) { return null; } -}*/ + public void resetCache() { + if (cacheFile.exists()) { + if (cacheFile.delete()) { + Notifications.INSTANCE.send("PolyPatcher", "Deleted entrypoint cache", 5000); + logger.info("Deleted entrypoint cache"); + } else { + Notifications.INSTANCE.send("PolyPatcher", "Failed to delete entrypoint cache!", 5000); + logger.error("Failed to delete entrypoint cache"); + } + } + } +} diff --git a/src/main/java/club/sk1er/patcher/util/item/TooltipHandler.java b/src/main/java/club/sk1er/patcher/util/item/TooltipHandler.java new file mode 100644 index 000000000..41a584dbf --- /dev/null +++ b/src/main/java/club/sk1er/patcher/util/item/TooltipHandler.java @@ -0,0 +1,34 @@ +package club.sk1er.patcher.util.item; + +import club.sk1er.patcher.config.PatcherConfig; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; + +import java.util.List; + +public class TooltipHandler { + + public static TooltipHandler INSTANCE = new TooltipHandler(); + + public boolean shouldToolTipRender = false; + private long cacheTime = 0L; + public List tooltipCache = null; + + @SubscribeEvent + public void onTick(TickEvent.ClientTickEvent event) { + if (event.phase == TickEvent.Phase.START) { + if (!PatcherConfig.tooltipCache) { + return; + } + if (!shouldToolTipRender || tooltipCache == null) { + return; + } + if ((System.currentTimeMillis() - cacheTime) < 200) { + return; + } + tooltipCache = null; + cacheTime = System.currentTimeMillis(); + } + } + +} diff --git a/src/main/java/club/sk1er/patcher/util/world/sound/SoundHandler.java b/src/main/java/club/sk1er/patcher/util/world/sound/SoundHandler.java index 7982aa703..f718e0cbd 100644 --- a/src/main/java/club/sk1er/patcher/util/world/sound/SoundHandler.java +++ b/src/main/java/club/sk1er/patcher/util/world/sound/SoundHandler.java @@ -4,13 +4,11 @@ import club.sk1er.patcher.config.PatcherConfig; import club.sk1er.patcher.config.PatcherSoundConfig; import club.sk1er.patcher.mixins.accessors.PositionedSoundAccessor; +import club.sk1er.patcher.mixins.accessors.RegistrySimpleAccessor; import club.sk1er.patcher.mixins.accessors.SoundHandlerAccessor; import club.sk1er.patcher.mixins.accessors.SoundRegistryAccessor; import net.minecraft.client.Minecraft; -import net.minecraft.client.audio.ISound; -import net.minecraft.client.audio.SoundCategory; -import net.minecraft.client.audio.SoundEventAccessorComposite; -import net.minecraft.client.audio.SoundManager; +import net.minecraft.client.audio.*; import net.minecraft.client.resources.IResourceManager; import net.minecraft.client.resources.IResourceManagerReloadListener; import net.minecraft.util.ResourceLocation; @@ -22,11 +20,24 @@ import java.util.HashMap; import java.util.Map; +//#if MC>10809 +//$$ import net.minecraft.util.SoundCategory; +//#endif + public class SoundHandler implements IResourceManagerReloadListener { + private final boolean isLoliASM; // why, why, why + public SoundHandler() { this.previousActive = Display.isActive(); handleFocusChange(); + boolean isLoliASM = false; + try { + Class.forName("zone.rong.loliasm.api.mixins.RegistrySimpleExtender", false, getClass().getClassLoader()); + isLoliASM = true; + } catch (ClassNotFoundException ignored) { + } + this.isLoliASM = isLoliASM; } private final Map data = new HashMap<>(); @@ -86,7 +97,8 @@ private float getVolumeMultiplier(ResourceLocation sound) { @Override public void onResourceManagerReload(IResourceManager resourceManager) { - Map soundRegistry = ((SoundRegistryAccessor) ((SoundHandlerAccessor) Minecraft.getMinecraft().getSoundHandler()).getSndRegistry()).getSoundRegistry(); - new PatcherSoundConfig(data, soundRegistry); + SoundRegistry soundRegistry = ((SoundHandlerAccessor) Minecraft.getMinecraft().getSoundHandler()).getSndRegistry(); + Map sounds = isLoliASM ? ((RegistrySimpleAccessor) soundRegistry).getRegistryObjects() : ((SoundRegistryAccessor) soundRegistry).getSoundRegistry(); + new PatcherSoundConfig(data, sounds); } } diff --git a/src/main/java/club/sk1er/patcher/util/world/sound/audioswitcher/ALCHelper.java b/src/main/java/club/sk1er/patcher/util/world/sound/audioswitcher/ALCHelper.java index 4d8d9ae1e..0dc8671d6 100644 --- a/src/main/java/club/sk1er/patcher/util/world/sound/audioswitcher/ALCHelper.java +++ b/src/main/java/club/sk1er/patcher/util/world/sound/audioswitcher/ALCHelper.java @@ -32,7 +32,11 @@ private String[] getAvailableDevicesString() { try { return ALC10.alcGetString(null, ALC11.ALC_ALL_DEVICES_SPECIFIER).split("\0"); } catch (Exception ignored) { - return ALC10.alcGetString(null, ALC10.ALC_DEVICE_SPECIFIER).split("\0"); + try { + return ALC10.alcGetString(null, ALC10.ALC_DEVICE_SPECIFIER).split("\0"); + } catch (Exception ignored2) { + return null; + } } } } diff --git a/src/main/java/me/jellysquid/mods/lithium/common/util/math/CompactSineLUT.java b/src/main/java/me/jellysquid/mods/lithium/common/util/math/CompactSineLUT.java new file mode 100644 index 000000000..6d1e49468 --- /dev/null +++ b/src/main/java/me/jellysquid/mods/lithium/common/util/math/CompactSineLUT.java @@ -0,0 +1,118 @@ +/** + * THE FOLLOWING CODE IS LICENSED UNDER THE GNU Lesser General Public License v3.0 + * This work, "PolyPatcher", uses code from CaffeineMC's "lithium-fabric", licensed under the LGPL-3.0 license. The original license is included in the repository. + * https://github.com/CaffeineMC/lithium-fabric/tree/develop + * https://github.com/CaffeineMC/lithium-fabric/blob/develop/LICENSE.txt + */ +package me.jellysquid.mods.lithium.common.util.math; + +import net.minecraft.util.MathHelper; + +import java.lang.reflect.Field; + +/** + * A replacement for the sine angle lookup table used in {@link MathHelper}, both reducing the size of LUT and improving + * the access patterns for common paired sin/cos operations. + * + * sin(-x) = -sin(x) + * ... to eliminate negative angles from the LUT. + * + * sin(x) = sin(pi/2 - x) + * ... to eliminate supplementary angles from the LUT. + * + * Using these identities allows us to reduce the LUT from 64K entries (256 KB) to just 16K entries (64 KB), enabling + * it to better fit into the CPU's caches at the expense of some cycles on the fast path. The implementation has been + * tightly optimized to avoid branching where possible and to use very quick integer operations. + * + * Generally speaking, reducing the size of a lookup table is always a good optimization, but since we need to spend + * extra CPU cycles trying to maintain parity with vanilla, there is the potential risk that this implementation ends + * up being slower than vanilla when the lookup table is able to be kept in cache memory. + * + * Unlike other "fast math" implementations, the values returned by this class are *bit-for-bit identical* with those + * from {@link MathHelper}. Validation is performed during runtime to ensure that the table is correct. + * + * @author coderbot16 Author of the original (and very clever) implementation in Rust: + * https://gitlab.com/coderbot16/i73/-/tree/master/i73-trig/src + * @author jellysquid3 Additional optimizations, port to Java + * @author Wyvest Port to Minecraft 1.8.9 / 1.12.2 mappings + */ +public class CompactSineLUT { + private static final int[] SINE_TABLE_INT = new int[16384 + 1]; + private static final float SINE_TABLE_MIDPOINT; + + static { + float[] SINE_TABLE; + try { + Field field; + try { + field = MathHelper.class.getDeclaredField("SIN_TABLE"); + } catch (NoSuchFieldException e) { + // 1.17 mappings + field = MathHelper.class.getDeclaredField("field_76144_a"); + } + field.setAccessible(true); + SINE_TABLE = (float[]) field.get(null); + } catch (NoSuchFieldException | IllegalAccessException e) { + e.printStackTrace(); + // taking this into our own hands + SINE_TABLE = new float[65536]; + int i; + for (i = 0; i < 65536; ++i) { + SINE_TABLE[i] = (float)Math.sin((double)i * Math.PI * 2.0 / 65536.0); + } + } + // Copy the sine table, covering to raw int bits + for (int i = 0; i < SINE_TABLE_INT.length; i++) { + SINE_TABLE_INT[i] = Float.floatToRawIntBits(SINE_TABLE[i]); + } + + SINE_TABLE_MIDPOINT = SINE_TABLE[SINE_TABLE.length / 2]; + + // Test that the lookup table is correct during runtime + for (int i = 0; i < SINE_TABLE.length; i++) { + float expected = SINE_TABLE[i]; + float value = lookup(i); + + if (expected != value) { + throw new IllegalArgumentException(String.format("LUT error at index %d (expected: %s, found: %s)", i, expected, value)); + } + } + } + + // [VanillaCopy] MathHelper#sin(float) + public static float sin(float f) { + return lookup((int) (f * 10430.378f) & 0xFFFF); + } + + // [VanillaCopy] MathHelper#cos(float) + public static float cos(float f) { + return lookup((int) (f * 10430.378f + 16384.0f) & 0xFFFF); + } + + private static float lookup(int index) { + // A special case... Is there some way to eliminate this? + if (index == 32768) { + return SINE_TABLE_MIDPOINT; + } + + // Trigonometric identity: sin(-x) = -sin(x) + // Given a domain of 0 <= x <= 2*pi, just negate the value if x > pi. + // This allows the sin table size to be halved. + int neg = (index & 0x8000) << 16; + + // All bits set if (pi/2 <= x), none set otherwise + // Extracts the 15th bit from 'half' + int mask = (index << 17) >> 31; + + // Trigonometric identity: sin(x) = sin(pi/2 - x) + int pos = (0x8001 & mask) + (index ^ mask); + + // Wrap the position in the table. Moving this down to immediately before the array access + // seems to help the Hotspot compiler optimize the bit math better. + pos &= 0x7fff; + + // Fetch the corresponding value from the LUT and invert the sign bit as needed + // This directly manipulate the sign bit on the float bits to simplify logic + return Float.intBitsToFloat(SINE_TABLE_INT[pos] ^ neg); + } +} diff --git a/src/main/resources/LITHIUM-FABRIC-LICENSE.txt b/src/main/resources/LITHIUM-FABRIC-LICENSE.txt new file mode 100644 index 000000000..153d416dc --- /dev/null +++ b/src/main/resources/LITHIUM-FABRIC-LICENSE.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. \ No newline at end of file diff --git a/src/main/resources/mixins.patcher.json b/src/main/resources/mixins.patcher.json index abafa33c6..e91b39c6e 100644 --- a/src/main/resources/mixins.patcher.json +++ b/src/main/resources/mixins.patcher.json @@ -2,6 +2,7 @@ "package": "club.sk1er.patcher.mixins", "refmap": "mixins.patcher.refmap.json", "compatibilityLevel": "JAVA_8", + "minVersion": "0.7", "plugin": "club.sk1er.patcher.mixins.plugin.PatcherMixinPlugin", "overwrites": { "conformVisibility": true @@ -25,6 +26,7 @@ "accessors.MinecraftAccessor", "accessors.MinecraftForgeClientAccessor", "accessors.PositionedSoundAccessor", + "accessors.RegistrySimpleAccessor", "accessors.RenderManagerAccessor", "accessors.ResourcePackRepositoryAccessor", "accessors.SoundHandlerAccessor", @@ -50,12 +52,14 @@ "bugfixes.GuiGameOverMixin_ResolveButtonClick", "bugfixes.GuiIngameForgeMixin_FixProfilerSection", "bugfixes.GuiIngameForgeMixin_HotbarAlpha", + "bugfixes.GuiIngameMixin_RemoveSpectatorPumpkinOverlay", "bugfixes.GuiIngameMixin_ScoreboardTextTransparency", "bugfixes.GuiLanguageMixin_ResetUnicodeFont", "bugfixes.GuiNewChat_RemoveChatLimit", "bugfixes.GuiNewChatMixin_ChatComponentBoundary", "bugfixes.GuiNewChatMixin_NullChatLineFix", "bugfixes.GuiOptionsMixin_SaveSettings", + "bugfixes.GuiScreenBookMixin_AddBackground", "bugfixes.GuiScreenBookMixin_ResolveRenderLayer", "bugfixes.GuiScreenMixin_FixWindowsIME", "bugfixes.GuiScreenOptionsSoundsMixin_PacketSpam", @@ -147,10 +151,10 @@ "features.GuiMultiplayerMixin_FastServerJoin", "features.GuiNewChatMixin_ChatDelay", "features.GuiNewChatMixin_CompactChat", - "features.GuiNewChatMixin_ExtendChatBackground", - "features.GuiNewChatMixin_TransparentChat", "features.GuiScreenMixin_BackgroundRendering", "features.GuiScreenServerListMixin_FakeServerListDirectConnect", + "features.ImageBufferDownload_EarsMod", + "features.ImageBufferDownloadMixin_ImprovedHeadRendering", "features.InventoryPlayerTransformer_HotbarScrolling", "features.LayerArrowMixin_CancelRender", "features.LayerCapeMixin_NaturalCapes", @@ -211,6 +215,7 @@ "performance.BlockRedstoneTorchMixin_MemoryLeak", "performance.ChunkMixin_Optimization", "performance.EffectRendererMixin_ParticleCulling", + "performance.EnchantmentHelperMixin_MemoryLeak", "performance.EntityMixin_Capability", "performance.EntityMixin_DisplayNames", "performance.EntityOtherPlayerMPMixin_UselessAnimations", @@ -220,7 +225,11 @@ "performance.EntityRendererMixin_SkipTwitchRendering", "performance.FontRendererMixin_Optimization", "performance.GameRulesValueMixin_Optimization", + "performance.GameSettingsMixin_RefreshMipmaps", + "performance.GuiLanguageMixin_RefreshLanguage", + "performance.ItemStackMixin_TooltipCache", "performance.LoadingScreenRendererMixin_SkipProgress", + "performance.MathHelperMixin_CompactLUT", "performance.MinecraftMixin_MemoryIssues", "performance.MinecraftMixin_OptimizedWorldSwapping", "performance.MinecraftMixin_SkipTwitchStuff", @@ -230,18 +239,26 @@ "performance.NBTTagStringMixin_DataCache", "performance.NetHandlerPlayClientMixin_InstantDimensionSwapping", "performance.NodeProcessorMixin_MemoryLeak", + "performance.RenderChunkMixin_OptimizeSpecialTileEntities", "performance.RenderEntityItemMixin_EntityCulling", "performance.RenderGlobalMixin_LimitVisGraphScan", "performance.ResourcePackRepositoryMixin_FasterSearching", + "performance.SimpleReloadableResourceManager_OnlyRefreshNecessaryListeners", "performance.TexturedQuadMixin_BatchDraw", + "performance.TextureManagerMixin_MemoryLeak", "performance.TileEntityMobSpawnerRendererMixin_EntityCulling", "performance.TileEntityRendererDispatcherMixin_BatchDraw", "performance.VisGraphMixin_LimitScan", "performance.WorldClientMixin_AnimationTick", "performance.WorldMixin_Optimization", + "performance.forge.ASMDataTableMixin_ComputeParallel", "performance.forge.FluidRegistryMixin_Optimization", "performance.forge.FMLClientHandlerMixin_Optimization", + "performance.forge.FMLControlledNamespacedRegistryMixin_TrimAvailabilityMap", "performance.forge.ItemLayerModelMixin_ReduceQuadCount", + "performance.forge.JarDiscovererMixin_ReplaceRegex", + "performance.forge.ModDiscovererMixin_Logging", + "performance.forge.ModDiscovererMixin_ReplaceRegex", "performance.hudcaching.EntityRendererMixin_HUDCaching", "performance.hudcaching.FramebufferMixin_HUDCaching", "performance.hudcaching.GlStateManagerMixin_HUDCaching", @@ -249,6 +266,8 @@ "performance.hudcaching.GuiIngameMixin_HUDCaching", "performance.network.packet.C17PacketCustomPayloadMixin_MemoryLeak", "performance.network.packet.S3FPacketCustomPayloadMixin_MemoryLeak", + "performance.optifine.GameSettingsMixin_RefreshOFMipmaps", + "performance.optifine.MathHelperMixin_OFFastMath", "performance.render.item.ItemStackMixin_CacheDisplayName" ] } \ No newline at end of file diff --git a/src/main/resources/patcher18_at.cfg b/src/main/resources/patcher18_at.cfg index 6cf76b7b5..a902cfe22 100644 --- a/src/main/resources/patcher18_at.cfg +++ b/src/main/resources/patcher18_at.cfg @@ -10,4 +10,10 @@ public net.minecraft.client.renderer.tileentity.TileEntityBannerRenderer$TimedBa public net.minecraft.client.renderer.tileentity.TileEntityBannerRenderer$TimedBannerTexture ()V # constructor # BlockRedstoneTorch -public net.minecraft.block.BlockRedstoneTorch$Toggle \ No newline at end of file +public net.minecraft.block.BlockRedstoneTorch$Toggle + +# EnchantmentHelper +public net.minecraft.enchantment.EnchantmentHelper$DamageIterator +public net.minecraft.enchantment.EnchantmentHelper$HurtIterator +public net.minecraft.enchantment.EnchantmentHelper$ModifierDamage +public net.minecraft.enchantment.EnchantmentHelper$ModifierLiving \ No newline at end of file diff --git a/versions/1.12.2-1.8.9.txt b/versions/1.12.2-1.8.9.txt index f5fd2adf9..e43924de9 100644 --- a/versions/1.12.2-1.8.9.txt +++ b/versions/1.12.2-1.8.9.txt @@ -59,4 +59,5 @@ net.minecraft.client.particle.Particle net.minecraft.client.particle.EntityFX net.minecraft.client.gui.advancements.GuiAdvancement net.minecraft.client.gui.achievement.GuiAchievement net.minecraft.client.gui.GuiWorldSelection net.minecraft.client.gui.GuiSelectWorld net.minecraft.pathfinding.NodeProcessor net.minecraft.world.pathfinder.NodeProcessor -net.minecraft.util.SoundCategory net.minecraft.client.audio.SoundCategory \ No newline at end of file +net.minecraft.util.SoundCategory net.minecraft.client.audio.SoundCategory +net.minecraft.util.registry.RegistrySimple net.minecraft.util.RegistrySimple \ No newline at end of file